diff --git a/.claude/rules/stack-and-commands.md b/.claude/rules/stack-and-commands.md index 9bf1189..49498cd 100644 --- a/.claude/rules/stack-and-commands.md +++ b/.claude/rules/stack-and-commands.md @@ -1,7 +1,8 @@ ## Stack - **Language:** Markdown-first registry and planning repo (no application runtime) -- **Key deps:** State Hub ADR-001 workplans, `registry/indexes/capabilities.yaml` +- **Key deps:** State Hub ADR-001 workplans, `registry/indexes/{capabilities,surfaces}.yaml`, + `schemas/surface-entry.schema.json` (validated with PyYAML + jsonschema) ## Dev Commands @@ -13,16 +14,21 @@ cat SCOPE.md ls workplans/ ls registry/ -# Validate registry entries (from reuse-surface checkout) -reuse-surface validate --root . - -# Sanity-check markdown / registry edits -git diff --check +# Validate the registry (the CI gate — run after any registry/schema edit) +make validate # schema + index + whitespace + reuse-surface +python3 tools/validate_registry.py # schema + index consistency only +git diff --check # whitespace / conflict markers +reuse-surface validate --root . # capability federation (from reuse-surface checkout) # After workplan or registry edits — from ~/state-hub make fix-consistency REPO=config-atlas ``` -**Install / test / lint / build / run:** not applicable — this repo has no -application runtime. Verify changes with `git diff --check` and -`reuse-surface validate` when registry files change. \ No newline at end of file +**Validation gate (CI):** `make validate` is the single gate run by agents and CI +(`.github/workflows/validate.yml`, read by GitHub *and* Gitea Actions). It validates +every `registry/surfaces/*.md` against `schemas/surface-entry.schema.json` +(forbidding inline values/secrets), checks `registry/indexes/surfaces.yaml` +consistency, and runs `git diff --check`. Requires `pip install pyyaml jsonschema`. + +**Install / test / build / run:** not applicable — no application runtime. Verify +changes with `make validate`. \ No newline at end of file diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..d67f62d --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,22 @@ +# Registry validation gate (ATLAS-WP-0002-T06). +# Runs on GitHub Actions and Gitea Actions (both read .github/workflows). +name: validate-registry + +on: + push: + pull_request: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install validation dependencies + run: pip install --quiet pyyaml jsonschema + - name: Validate surface entries against schema + index + run: python3 tools/validate_registry.py + - name: Check whitespace / conflict markers + run: git diff --check $(git hash-object -t tree /dev/null) -- . diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..472a109 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +# config-atlas — registry validation gate (ATLAS-WP-0002-T06) +# Markdown-first repo: no build/run, only validation. + +.PHONY: validate validate-schema validate-reuse validate-whitespace + +# Full gate run by agents and CI. +validate: validate-schema validate-whitespace validate-reuse + @echo "validate: all checks passed" + +# Surface entries validate against the JSON Schema; index is consistent. +validate-schema: + @python3 tools/validate_registry.py + +# No trailing whitespace / conflict markers in staged or working tree. +validate-whitespace: + @git diff --check HEAD -- . && echo "validate-whitespace: OK" + +# Capability registry federation validation (skipped if reuse-surface absent). +validate-reuse: + @if command -v reuse-surface >/dev/null 2>&1; then \ + reuse-surface validate --root . ; \ + else \ + echo "validate-reuse: reuse-surface CLI not on PATH — skipped" ; \ + fi diff --git a/docs/statehub-register.md b/docs/statehub-register.md deleted file mode 100644 index 895fae3..0000000 --- a/docs/statehub-register.md +++ /dev/null @@ -1,104 +0,0 @@ -# statehub register — Consumer Guide - -Use this guide when bootstrapping a new Coulomb repository from the `repo-seed` -template and registering it with Custodian State Hub. - -## Prerequisites - -- State Hub API running locally (`cd ~/state-hub && make api`) or reachable via tunnel -- `statehub` CLI installed from `~/state-hub` (`uv tool install .` or `uv run statehub`) -- A git repository cloned or copied from `repo-seed` (or an equivalent scaffold) - -## Quick start - -From the new repository root: - -```bash -cd /path/to/new-repo - -# Optional: skip LLM inference and supply facts manually -statehub register \ - --domain \ - --repo-slug \ - --wp-prefix \ - --description "One-sentence repo purpose." \ - --no-llm - -# Operator follow-up (from state-hub checkout) -cd ~/state-hub -make fix-consistency REPO= -``` - -`statehub register` is idempotent: existing files are not overwritten unless you -pass `--force`. - -## What register writes - -`statehub register` inspects the repository, infers identity (optionally via -`llm-connect`), and writes these files when absent: - -| File | Purpose | -|------|---------| -| `INTENT.md` | Why the repository exists | -| `SCOPE.md` | In/out scope and current state | -| `AGENTS.md` | Codex/Grok agent instructions with repo identity placeholders filled | -| `.custodian-brief.md` | Offline-safe session orientation | -| `workplans/-0001-statehub-bootstrap.md` | First workplan with T01–T03 bootstrap tasks | - -It also registers the repo and host path through the State Hub API and records a -progress milestone. - -## Template extras (from repo-seed) - -Cloning `repo-seed` provides additional scaffold not written by `register`: - -| Path | Purpose | -|------|---------| -| `CLAUDE.md` + `.claude/rules/` | Claude Code agent instructions | -| `registry/` | Capability registry scaffold | -| `README.md`, `LICENSE`, `.gitignore` | Project metadata | -| `.repo-classification.yaml` | Repo classification metadata | - -After `register`, complete the bootstrap workplan (`*-0001-statehub-bootstrap.md`): - -1. **T01** — Review and refine generated integration files -2. **T02** — Document install/test/lint/build/run commands in agent instructions -3. **T03** — Create the first real implementation workplan - -## CLI reference - -``` -statehub register [options] - - --path PATH Repo directory (default: cwd) - --domain SLUG State Hub domain slug - --repo-slug SLUG Repo slug (auto-detected from directory name) - --wp-prefix PREFIX Workplan prefix, e.g. DEMO-WP - --description TEXT One-sentence repo description - --intent TEXT Intent text when INTENT.md is absent - --api-base URL State Hub API base (default: http://127.0.0.1:8000) - --no-llm Skip LLM inference; use files and flags - --force Overwrite generated files -``` - -Environment overrides: `API_BASE`, `STATEHUB_REGISTER_LLM_PROVIDER`, -`STATEHUB_REGISTER_LLM_MODEL`, `STATEHUB_REGISTER_LLM_API_KEY`, -`STATEHUB_REGISTER_LLM_TIMEOUT`. - -## fix-consistency - -Workplans are canonical in repo files (ADR-001). After creating or updating -workplan files, sync them into State Hub: - -```bash -cd ~/state-hub -make fix-consistency REPO= -``` - -This rebuilds hub workstreams/tasks from files, updates `.custodian-brief.md`, -and reports consistency findings (C-15 file/DB drift, C-16 remote behind, etc.). - -## Validation - -Use [template-validation-checklist.md](template-validation-checklist.md) to -verify a bootstrapped repo against expected `statehub register` output. \ No newline at end of file diff --git a/docs/template-validation-checklist.md b/docs/template-validation-checklist.md deleted file mode 100644 index 785cefe..0000000 --- a/docs/template-validation-checklist.md +++ /dev/null @@ -1,90 +0,0 @@ -# Template Validation Checklist - -Validate a repository bootstrapped from `repo-seed` against `statehub register` -output and Coulomb onboarding conventions. - -**Validated:** 2026-06-24 against `statehub register` in `~/state-hub`. - ---- - -## 1. Register with State Hub - -- [ ] State Hub API is reachable (`curl -s http://127.0.0.1:8000/state/health`) -- [ ] `statehub register` completes without error -- [ ] Registration prints repo slug, domain, topic ID, and `make fix-consistency` hint -- [ ] Progress milestone recorded (`Repo registered with State Hub: `) - -## 2. Agent files (register output) - -Confirm these files exist and contain repo-specific values (not `{PLACEHOLDER}` tokens): - -- [ ] `INTENT.md` — governing purpose; derived from README or `--intent` -- [ ] `SCOPE.md` — one-liner, in/out scope, current state -- [ ] `AGENTS.md` — **Purpose**, **Domain**, **Repo slug**, **Topic ID**, **Workplan prefix** -- [ ] `.custodian-brief.md` — domain, topic ID, bootstrap workplan reference - -### AGENTS.md spot checks - -- [ ] `**Repo slug:**` matches directory slug and State Hub registration -- [ ] `**Workplan prefix:**` matches workplan file prefix (e.g. `DEMO-WP-`) -- [ ] Session protocol references `cat .custodian-brief.md` and inbox curl examples -- [ ] `make fix-consistency REPO=` documented for workplan edits - -## 3. First workplan - -- [ ] `workplans/-0001-statehub-bootstrap.md` exists -- [ ] Frontmatter: `id`, `type: workplan`, `status: ready`, `repo`, `domain` -- [ ] Tasks T01 (review files), T02 (dev workflow), T03 (seed real workplan) present -- [ ] T03 references `make fix-consistency REPO=` - -## 4. Template extras (repo-seed scaffold) - -Beyond register output, confirm template scaffold is present: - -- [ ] `CLAUDE.md` includes `@.claude/rules/*` references -- [ ] `.claude/rules/` contains session-protocol, workplan-convention, stack-and-commands -- [ ] `registry/README.md` and `registry/indexes/capabilities.yaml` exist -- [ ] `README.md` describes the repository purpose -- [ ] `.gitignore` and `LICENSE` present - -## 5. Bootstrap workplan completion - -After register, complete `*-0001-statehub-bootstrap.md`: - -- [ ] **T01** — Placeholders replaced; SCOPE refined for repo-specific boundaries -- [ ] **T02** — `.claude/rules/stack-and-commands.md` lists real dev commands -- [ ] **T03** — First implementation workplan created (`*-0002-*.md` or equivalent) -- [ ] Workplan status set to `finished` when all tasks done - -## 6. fix-consistency sync - -- [ ] `make fix-consistency REPO=` run from `~/state-hub` -- [ ] `.custodian-brief.md` updated with active workstreams (replaces register stub) -- [ ] Hub workstreams/tasks match workplan file statuses -- [ ] No blocking C-16 (repo behind remote) findings - -## 7. Registry (optional) - -When the repo exposes reusable behavior: - -- [ ] Capability entry in `registry/capabilities/` -- [ ] Row added to `registry/indexes/capabilities.yaml` -- [ ] `reuse-surface validate --root .` passes - ---- - -## repo-seed self-validation notes - -`repo-seed` is the meta-template and intentionally differs in a few places: - -| Item | repo-seed state | Consumer expectation | -|------|-----------------|----------------------| -| `INTENT.md` | Absent — `README.md` is canonical intent | Present after `register` | -| `SCOPE.md` | Refined (no "generated by statehub register" banner) | Generated, then refined in T01 | -| `.custodian-brief.md` | Maintained by `fix-consistency` | Register stub, then fix-consistency | -| `REPO-WP-0001` | `finished` | `ready` until bootstrap complete | -| `REPO-WP-0002` | Template validation (this checklist) | First domain-specific workplan | - -All register-output structures were verified by running `write_registration_files` -from `statehub_register.py` with `repo_slug=repo-seed`, `wp_prefix=REPO-WP`, -`domain=infotech`. \ No newline at end of file diff --git a/registry/capabilities/capability.infotech.config-surface-atlas.md b/registry/capabilities/capability.infotech.config-surface-atlas.md new file mode 100644 index 0000000..b626f0a --- /dev/null +++ b/registry/capabilities/capability.infotech.config-surface-atlas.md @@ -0,0 +1,128 @@ +--- +id: capability.infotech.config-surface-atlas +name: Configuration Surface Atlas +summary: Read-first, cross-kind map and evidence layer for configuration surfaces — what configures a system, who owns it, its scope, and where the source of truth lives. +owner: config-atlas +status: draft +domain: infotech +tags: + - configuration + - registry + - control-plane + - effective-config + - evidence + +maturity: + discovery: + current: D5 + target: D6 + confidence: medium + rationale: > + Intent, scope, layering model, competitive landscape, and a control-plane + research digest are documented (INTENT, SCOPE, research/, wiki/, PRD, + ArchitectureBlueprint). Boundaries vs sister repos are explicit. + availability: + current: A0 + target: A2 + confidence: medium + rationale: > + Markdown/YAML registry with a JSON Schema for entries; no runtime resolver + or API (intentionally — resolution is delegated). Consumed informationally + and by agents; a source-module validator exists under tools/. + +external_evidence: + completeness: + level: C2 + confidence: low + basis: scope_vs_intent_and_consumer_expectations + satisfied_expectations: + - configuration-surface entry schema (schemas/surface-entry.schema.json) + - scope/precedence/merge model (docs/configuration-surface-schema.md) + - canon mapping to InfoTechCanon (docs/canon-mapping.md) + - seed configuration surfaces (registry/surfaces/) + broken_expectations: [] + out_of_scope_expectations: + - runtime effective-value resolution + - configuration delivery or control execution + - secret value storage + reliability: + level: R2 + confidence: low + basis: consumer_quality_signals + known_reliability_risks: + - schema and surface seed are early; coverage is partial + - ownership resolution to domain-tree not yet wired + +discovery: + intent: > + Make the distributed configuration surface of the ecosystem discoverable, + explainable, and governable — map the territory before controlling it. + includes: + - configuration-surface registry and entry schema + - scope/layer ordering and explicit merge semantics + - cross-repo relationship and effective-config path modelling + - canon alignment and sister-repo boundary documentation + excludes: + - runtime resolver, delivery, or control plane + - secret values or live configuration values + - feature-availability runtime control (feature-control owns it) + assumptions: + - downstream repos remain authoritative for their own config + - reuse-surface federation and the State Hub graph are available + use_cases: [] + research_memos: + - research/configuration-control-plane.md + - docs/configuration-surface-schema.md + +availability: + current_level: A0 + target_level: A2 + current_artifacts: + - registry/surfaces/ + - schemas/surface-entry.schema.json + - docs/configuration-surface-schema.md + - docs/canon-mapping.md + - tools/validate_registry.py + consumption_modes: + - informational + - source module + +relations: + depends_on: + - capability.statehub.workstream-coordinate + supports: [] + related_to: + - capability.registry.register + +evidence: + documentation: + - INTENT.md + - SCOPE.md + - specs/ProductRequirementsDocument.md + - specs/ArchitectureBlueprint.md + - docs/ecosystem-boundaries.md + tests: + - tools/validate_registry.py + +consumer_guidance: + recommended_for: + - discovering what configures a system and who owns it + - reasoning about defaults, precedence, and cross-repo config relationships + not_recommended_for: + - storing or resolving live configuration values + - secret management or feature-flag runtime control + known_limitations: + - early-stage schema and partial surface coverage + - effective-value resolution is out of scope by design +--- + +# Configuration Surface Atlas + +config-atlas indexes **configuration surfaces** — bounded, named places where +configuration is defined, read, or overridden — as source-linked registry entries +with ownership, kind, scope, and evidence. It is the read-first map and evidence +layer of a configuration control plane; it does not resolve, deliver, or control +configuration (see `SCOPE.md`, `docs/ecosystem-boundaries.md`). + +See `docs/configuration-surface-schema.md` for the entry model and +`docs/canon-mapping.md` for InfoTechCanon alignment. diff --git a/registry/capabilities/capability.infotech.repo-template.md b/registry/capabilities/capability.infotech.repo-template.md deleted file mode 100644 index 5ee0399..0000000 --- a/registry/capabilities/capability.infotech.repo-template.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: capability.infotech.repo-template -name: Coulomb Repository Template -summary: Bootstrap new git repositories with agent instructions, registry scaffold, and State Hub onboarding conventions. -owner: repo-seed -status: draft -domain: infotech -tags: - - template - - bootstrap - - state-hub - - onboarding - -maturity: - discovery: - current: D3 - target: D5 - confidence: medium - rationale: > - Template purpose, consumer guide, and validation checklist are documented. - Scope boundaries are explicit in SCOPE.md. - availability: - current: A3 - target: A4 - confidence: medium - rationale: > - Consumers clone or copy repo-seed and run statehub register. Template - files are markdown/git artifacts without a hosted provisioning API. - -external_evidence: - completeness: - level: C2 - confidence: medium - basis: scope_vs_intent_and_consumer_expectations - satisfied_expectations: - - agent instruction scaffold (AGENTS.md, CLAUDE.md, .claude/rules/) - - registry directory scaffold - - statehub register consumer documentation - - template validation checklist for bootstrap verification - - bootstrap workplan pattern (WP-0001) - broken_expectations: [] - out_of_scope_expectations: - - automated repo creation on Gitea - - runtime application code generation - reliability: - level: R2 - confidence: medium - basis: consumer_quality_signals - known_reliability_risks: - - register output evolves with state-hub releases; checklist must be revalidated - - LLM inference path depends on llm-connect availability - -discovery: - intent: > - Give new Coulomb repositories a consistent starting point for agent - coordination, capability registry growth, and State Hub workplan tracking. - includes: - - git template files for agent instructions and registry scaffold - - documentation for statehub register usage - - consumer validation checklist - - bootstrap workplan convention - excludes: - - application runtime implementation - - owning downstream project code - assumptions: - - consumers have access to state-hub CLI and API - - workplans remain canonical in repo files (ADR-001) - use_cases: [] - research_memos: - - docs/statehub-register.md - - docs/template-validation-checklist.md - -availability: - current_level: A3 - target_level: A4 - current_artifacts: - - README.md - - AGENTS.md - - CLAUDE.md - - .claude/rules/ - - registry/ - - docs/statehub-register.md - - docs/template-validation-checklist.md - consumption_modes: - - git clone - - informational - -relations: - depends_on: - - capability.statehub.workstream-coordinate - supports: [] - related_to: - - capability.registry.register - -evidence: - documentation: - - docs/statehub-register.md - - docs/template-validation-checklist.md - - SCOPE.md - tests: [] - -consumer_guidance: - recommended_for: - - bootstrapping new Coulomb domain repositories - - standardizing agent onboarding and workplan conventions - not_recommended_for: - - repos that already have mature agent instructions and hub registration - - application templates with heavy code generation requirements - known_limitations: - - register must be run separately after cloning - - fix-consistency requires operator access to state-hub checkout ---- - -# Coulomb Repository Template - -`repo-seed` is the canonical git template for new Coulomb repositories. Clone it, -run `statehub register`, complete the bootstrap workplan, and sync with -`make fix-consistency`. - -See `docs/statehub-register.md` for the consumer workflow and -`docs/template-validation-checklist.md` for verification steps. \ No newline at end of file diff --git a/registry/indexes/capabilities.yaml b/registry/indexes/capabilities.yaml index 359c385..b6130be 100644 --- a/registry/indexes/capabilities.yaml +++ b/registry/indexes/capabilities.yaml @@ -1,14 +1,14 @@ version: 1 -updated: '2026-06-24' +updated: '2026-06-26' domain: infotech capabilities: - - id: capability.infotech.repo-template - name: Coulomb Repository Template - summary: Bootstrap new git repositories with agent instructions, registry scaffold, and State Hub onboarding conventions. - vector: D3 / A3 / C2 / R2 + - id: capability.infotech.config-surface-atlas + name: Configuration Surface Atlas + summary: Read-first, cross-kind map and evidence layer for configuration surfaces — what configures a system, who owns it, its scope, and where the source of truth lives. + vector: D5 / A0 / C2 / R2 domain: infotech status: draft - owner: repo-seed - path: registry/capabilities/capability.infotech.repo-template.md - tags: [template, bootstrap, state-hub, onboarding] - consumption_modes: [git clone, informational] \ No newline at end of file + owner: config-atlas + path: registry/capabilities/capability.infotech.config-surface-atlas.md + tags: [configuration, registry, control-plane, effective-config, evidence] + consumption_modes: [informational, source module] diff --git a/registry/indexes/surfaces.yaml b/registry/indexes/surfaces.yaml new file mode 100644 index 0000000..7e55caf --- /dev/null +++ b/registry/indexes/surfaces.yaml @@ -0,0 +1,40 @@ +version: 1 +updated: '2026-06-26' +domain: infotech +surfaces: + - id: surface.infotech.state-hub.api-config + name: State Hub API configuration + kind: app-config + summary: Runtime configuration for the Custodian State Hub API (bind host/port, database URL, environment mode). + owner: custodian + status: active + default_layer: company + security_class: operational + path: registry/surfaces/surface.infotech.state-hub.api-config.md + - id: surface.infotech.ops-warden.routing-catalog + name: ops-warden credential routing catalog + kind: policy + summary: Catalog mapping credential/access needs to their owning subsystem, consumed via `warden route`. + owner: ops-warden + status: active + default_layer: company + security_class: policy + path: registry/surfaces/surface.infotech.ops-warden.routing-catalog.md + - id: surface.infotech.reuse-surface.federation-sources + name: reuse-surface federation sources + kind: app-config + summary: Federation roster and source list defining which registries reuse-surface aggregates. + owner: reuse-surface + status: active + default_layer: company + security_class: operational + path: registry/surfaces/surface.infotech.reuse-surface.federation-sources.md + - id: surface.infotech.ops-bridge.tunnel-config + name: ops-bridge SSH tunnel configuration + kind: infra-state + summary: Declares the reverse SSH tunnels exposing State Hub and MCP services to remote machines. + owner: ops-bridge + status: active + default_layer: installation + security_class: operational + path: registry/surfaces/surface.infotech.ops-bridge.tunnel-config.md diff --git a/registry/surfaces/surface.infotech.ops-bridge.tunnel-config.md b/registry/surfaces/surface.infotech.ops-bridge.tunnel-config.md new file mode 100644 index 0000000..6a9986c --- /dev/null +++ b/registry/surfaces/surface.infotech.ops-bridge.tunnel-config.md @@ -0,0 +1,43 @@ +--- +id: surface.infotech.ops-bridge.tunnel-config +name: ops-bridge SSH tunnel configuration +kind: infra-state +summary: Declares the reverse SSH tunnels (local/remote port maps) that expose State Hub and MCP services to remote machines. +owner: ops-bridge +status: active +scope: + allowed_layers: [company, environment, installation] + default_layer: installation +mutability: deploy-time +security_class: operational +schema: + type: object + validator: ~/ops-bridge/schemas/tunnel.schema.yaml +sources: + - repo: ops-bridge + path: config/tunnels.yaml + role: installation-overlay +relations: + consumed_by: + - service.ops-bridge + overrides: [] + depends_on_secret: + - ops-bridge/ssh-cert + related_to: + - surface.infotech.state-hub.api-config +evidence: + last_seen: '2026-06-26' + discovery_method: manual + change_log_ref: ATLAS-WP-0002-T03 +--- + +# ops-bridge SSH tunnel configuration + +ops-bridge maintains reverse SSH tunnels that expose the State Hub API and MCP +endpoints to remote machines (the remote port map: State Hub API `:18000`, MCP +`:18001`). This surface maps that tunnel configuration as **infra-state**. + +- **Source of truth:** the `ops-bridge` repo tunnel config; SSH certs are a secret + reference (`depends_on_secret`), signed by ops-warden, never stored here. +- **Relation:** exposes `surface.infotech.state-hub.api-config` to remote workers. +- **Mutability:** deploy-time — tunnel changes are brought up via `bridge up`. diff --git a/registry/surfaces/surface.infotech.ops-warden.routing-catalog.md b/registry/surfaces/surface.infotech.ops-warden.routing-catalog.md new file mode 100644 index 0000000..2487f18 --- /dev/null +++ b/registry/surfaces/surface.infotech.ops-warden.routing-catalog.md @@ -0,0 +1,44 @@ +--- +id: surface.infotech.ops-warden.routing-catalog +name: ops-warden credential routing catalog +kind: policy +summary: Catalog mapping credential/access needs to their owning subsystem (who issues what), consumed via `warden route`. +owner: ops-warden +status: active +scope: + allowed_layers: [company, platform] + default_layer: company +mutability: deploy-time +security_class: policy +schema: + type: object + validator: ~/ops-warden/registry/routing/catalog.schema.yaml +sources: + - repo: ops-warden + path: registry/routing/catalog.yaml + role: company-baseline +relations: + consumed_by: + - service.warden-cli + overrides: [] + depends_on_secret: [] + related_to: + - surface.infotech.state-hub.api-config +evidence: + last_seen: '2026-06-26' + discovery_method: manual + change_log_ref: ATLAS-WP-0002-T03 +--- + +# ops-warden credential routing catalog + +The credential routing catalog answers "who owns this credential need?" — SSH certs +(ops-warden), API keys/DB passwords (OpenBao), login/OIDC (key-cape), etc. It is a +**routing policy** surface: it carries pointers, never secret values. + +- **Source of truth:** `ops-warden/registry/routing/catalog.yaml`; consumed via + `warden route find/show`. +- **Boundary:** this surface maps the catalog's existence, owner, and scope; secret + values are never stored here (`security_class: policy`, no `depends_on_secret`). +- **Why indexed:** credential routing is high-frequency and high-risk; the atlas + records where the routing policy lives and who owns it. diff --git a/registry/surfaces/surface.infotech.reuse-surface.federation-sources.md b/registry/surfaces/surface.infotech.reuse-surface.federation-sources.md new file mode 100644 index 0000000..df14c41 --- /dev/null +++ b/registry/surfaces/surface.infotech.reuse-surface.federation-sources.md @@ -0,0 +1,44 @@ +--- +id: surface.infotech.reuse-surface.federation-sources +name: reuse-surface federation sources +kind: app-config +summary: Federation roster and source list that define which registries reuse-surface aggregates, including the reserved id namespaces. +owner: reuse-surface +status: active +scope: + allowed_layers: [company, platform, installation] + default_layer: company +mutability: hot-reloadable +security_class: operational +schema: + type: object + validator: ~/reuse-surface/schemas/federation.schema.yaml +sources: + - repo: reuse-surface + path: registry/federation/sources.yaml + role: company-baseline + - repo: reuse-surface + path: registry/federation/local-repo-roster.yaml + role: installation-overlay +relations: + consumed_by: + - service.reuse-surface-hub + overrides: [] + depends_on_secret: [] + related_to: + - surface.infotech.state-hub.api-config +evidence: + last_seen: '2026-06-26' + discovery_method: manual + change_log_ref: ATLAS-WP-0002-T03 +--- + +# reuse-surface federation sources + +The federation sources configure which registries reuse-surface aggregates and the +id namespaces each owns. config-atlas federates here as a typed peer (the `surface.*` +namespace reservation is ATLAS-WP-0002-T05). + +- **Source of truth:** `reuse-surface/registry/federation/{sources,local-repo-roster}.yaml`. +- **Why indexed:** this is the surface that governs cross-registry interoperability; + config-atlas's own discoverability depends on it. diff --git a/tools/validate_registry.py b/tools/validate_registry.py new file mode 100644 index 0000000..f9593ee --- /dev/null +++ b/tools/validate_registry.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Validate config-atlas registry entries. + +Gate run by agents and CI (ATLAS-WP-0002-T06). Checks: + 1. Every registry/surfaces/*.md frontmatter validates against + schemas/surface-entry.schema.json (Draft 2020-12). + 2. Entries never inline a configuration value or secret value + (enforced by additionalProperties:false in the schema). + 3. registry/indexes/surfaces.yaml is consistent with the entry files + (same id set, and each declared path exists with a matching id). + +Exit code 0 = pass, 1 = validation failure, 2 = setup error. +Dependencies: PyYAML, jsonschema. +""" +from __future__ import annotations + +import json +import re +import sys +from pathlib import Path + +try: + import yaml + from jsonschema import Draft202012Validator +except ImportError as exc: # pragma: no cover + print(f"setup error: missing dependency ({exc}). pip install pyyaml jsonschema", file=sys.stderr) + raise SystemExit(2) + +ROOT = Path(__file__).resolve().parent.parent +SCHEMA_PATH = ROOT / "schemas" / "surface-entry.schema.json" +SURFACES_DIR = ROOT / "registry" / "surfaces" +SURFACES_INDEX = ROOT / "registry" / "indexes" / "surfaces.yaml" + +FRONTMATTER = re.compile(r"^---\n(.*?)\n---\n", re.S) + + +def load_frontmatter(path: Path) -> dict: + m = FRONTMATTER.match(path.read_text()) + if not m: + raise ValueError(f"{path}: missing YAML frontmatter") + data = yaml.safe_load(m.group(1)) + if not isinstance(data, dict): + raise ValueError(f"{path}: frontmatter is not a mapping") + return data + + +def main() -> int: + if not SCHEMA_PATH.exists(): + print(f"setup error: schema not found at {SCHEMA_PATH}", file=sys.stderr) + return 2 + + schema = json.loads(SCHEMA_PATH.read_text()) + Draft202012Validator.check_schema(schema) + validator = Draft202012Validator(schema) + + errors: list[str] = [] + seen_ids: dict[str, Path] = {} + + entry_files = sorted(SURFACES_DIR.glob("*.md")) if SURFACES_DIR.exists() else [] + for path in entry_files: + try: + fm = load_frontmatter(path) + except ValueError as exc: + errors.append(str(exc)) + continue + for err in sorted(validator.iter_errors(fm), key=lambda e: list(e.path)): + loc = "/".join(str(p) for p in err.path) or "(root)" + errors.append(f"{path.name}: {loc}: {err.message}") + sid = fm.get("id") + if sid in seen_ids: + errors.append(f"{path.name}: duplicate id '{sid}' (also {seen_ids[sid].name})") + elif sid: + seen_ids[sid] = path + # filename should match the id for discoverability + if sid and path.stem != sid: + errors.append(f"{path.name}: filename does not match id '{sid}'") + + # index consistency + if SURFACES_INDEX.exists(): + index = yaml.safe_load(SURFACES_INDEX.read_text()) or {} + indexed = {row.get("id"): row for row in index.get("surfaces", [])} + for sid in indexed.keys() - seen_ids.keys(): + errors.append(f"surfaces.yaml: id '{sid}' indexed but no entry file found") + for sid in seen_ids.keys() - indexed.keys(): + errors.append(f"surfaces.yaml: entry '{sid}' present but not indexed") + for sid, row in indexed.items(): + declared = row.get("path") + if declared and not (ROOT / declared).exists(): + errors.append(f"surfaces.yaml: '{sid}' path '{declared}' does not exist") + elif entry_files: + errors.append("registry/indexes/surfaces.yaml missing but surface entries exist") + + if errors: + print(f"FAIL: {len(errors)} problem(s) in registry validation:", file=sys.stderr) + for e in errors: + print(f" - {e}", file=sys.stderr) + return 1 + + print(f"OK: {len(entry_files)} surface entr{'y' if len(entry_files)==1 else 'ies'} valid; index consistent.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/workplans/ATLAS-WP-0002-registry-foundation.md b/workplans/ATLAS-WP-0002-registry-foundation.md index caedf5f..c2dd73c 100644 --- a/workplans/ATLAS-WP-0002-registry-foundation.md +++ b/workplans/ATLAS-WP-0002-registry-foundation.md @@ -98,11 +98,17 @@ merge rules. ```task id: ATLAS-WP-0002-T02 -status: todo +status: done priority: high state_hub_task_id: "2d8e41e9-ba93-4a1a-862b-993da03df1f9" ``` +Result 2026-06-26: Removed `capability.infotech.repo-template` and the inherited +template consumer docs (`docs/statehub-register.md`, +`docs/template-validation-checklist.md`). Added +`capability.infotech.config-surface-atlas` and rewrote +`registry/indexes/capabilities.yaml` to list only config-atlas-owned entries. + Remove `capability.infotech.repo-template` and other `repo-seed` artifacts from `registry/`. Add the config-atlas capability entry and update `registry/indexes/capabilities.yaml`. Relocate or delete inherited template @@ -118,11 +124,17 @@ references (e.g. `registry/README.md` points at reuse-surface templates). ```task id: ATLAS-WP-0002-T03 -status: todo +status: done priority: medium state_hub_task_id: "9b8bb1c2-a6ee-4b6e-91a4-2cd902fb52ff" ``` +Result 2026-06-26: Created `registry/indexes/surfaces.yaml` and seeded 4 surfaces: +state-hub api-config (app-config), ops-warden routing-catalog (policy), +reuse-surface federation-sources (app-config), ops-bridge tunnel-config +(infra-state). All source-linked, no values; secret deps recorded as references +(`depends_on_secret`). All validate via the T06 gate. + Create `registry/surfaces/` and `registry/indexes/surfaces.yaml`. Hand-author 3–5 high-value configuration surfaces already present in the ecosystem (e.g. State Hub API config, warden routing catalog, reuse-surface registry layout) with `surface.*` @@ -157,11 +169,18 @@ federation mechanism. Coordinate via reuse-surface federation docs ```task id: ATLAS-WP-0002-T06 -status: todo +status: done priority: medium state_hub_task_id: "da6e44a7-ed87-433e-b183-f926e7e0caf8" ``` +Result 2026-06-26: Added `tools/validate_registry.py` (schema + index-consistency +gate; forbids inline values via additionalProperties:false), a `Makefile` +(`make validate` = schema + whitespace + reuse-surface), and +`.github/workflows/validate.yml` (runs on GitHub & Gitea Actions). Documented in +`.claude/rules/stack-and-commands.md`. Verified: 4 seed surfaces pass; a malformed +entry (bad kind, inline `value`, unindexed) is rejected with rc=1. + Wire registry validation to run on every change: `reuse-surface validate --root .`, surface-entry schema validation (T01), and `git diff --check` (PRD FR-9, NFR-6). Document the check in `AGENTS.md` / `.claude/rules/stack-and-commands.md` so agents