Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions docs/architecture/runtime-authority-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,70 @@ source line from `actools.sh`: it is invoked from `cli/actools` (the copied
operator-CLI surface), which is why the union with the entry-point grep, not the
closure alone, is required.

## File-level wiring within live modules (C4 inventory)

> Recorded at C4. The "Standalone modules" section above proves WHICH module dirs
> are live; this section proves, within the 6 live dirs, WHICH FILES are reached
> on the live path vs which ship unwired. Human-readable mirror of
> `tests/guards/live_module_file_inventory_test.bats`, which fails CI on any
> unclassified or wiring-flipped file. **C4 changed NO module file** — disposition
> of the unwired files is deferred (see the disposition column). Baseline `d482818`.

The 6 live modules ship **35 files: 21 wired, 1 documentation, 13 unwired.** The
13 unwired files reside on the box (in-place install + `chown -R`, `actools.sh:94`/`:405`)
but never execute on the live path.

### Wired (21) — reached on the live path
| file | reached via |
|---|---|
| `modules/audit/audit.sh` | EXECUTED by `cli/actools:313` (the `audit` command) |
| `modules/audit/lib/output.sh` | sourced by `audit.sh:57` (and `cli/actools:317`) |
| `modules/audit/lib/drupal.sh` | sourced by `audit.sh:58` |
| `modules/audit/lib/integration.sh` | sourced by `audit.sh:59` |
| `modules/audit/lib/stack.sh` | sourced by `audit.sh:60` |
| `modules/audit/lib/security.sh` | sourced by `audit.sh:61` |
| `modules/audit/lib/report.sh` | sourced by `audit.sh:62` |
| `modules/backup/cron.sh` | source-closure of `actools.sh` (`:516`) |
| `modules/db/core.sh` | source-closure of `actools.sh` (`:457`) |
| `modules/drupal/provision.sh` | source-closure of `actools.sh` (`:181`) |
| `modules/host/age.sh` | source-closure — host loop (`:193`) |
| `modules/host/docker.sh` | source-closure — host loop |
| `modules/host/firewall.sh` | source-closure — host loop |
| `modules/host/kernel.sh` | source-closure — host loop |
| `modules/host/logrotate.sh` | source-closure — host loop |
| `modules/host/packages.sh` | source-closure — host loop |
| `modules/host/swap.sh` | source-closure — host loop |
| `modules/stack/caddyfile.sh` | source-closure — stack loop (`:204`) |
| `modules/stack/compose.sh` | source-closure — stack loop |
| `modules/stack/images.sh` | source-closure — stack loop |
| `modules/stack/mycnf.sh` | source-closure — stack loop |

### Documentation (1) — ships, executed by no code
| file | note |
|---|---|
| `modules/audit/docs/fix_catalog.md` | audit fix-catalog reference doc; referenced by no code |

### Unwired (13) — ship on the box, OFF the live path; disposition deferred
| file | what it is | disposition (deferred) |
|---|---|---|
| `modules/backup/encrypted_backup.sh` | "Phase 4.5 Item 2" — age-encrypted backups | **E2** (encrypted backups): reconcile/wire/harden |
| `modules/backup/binlog-rotate.sh` | hourly binlog rotation/encryption/upload | **E3** (binlog/PITR) |
| `modules/backup/db-full-backup.sh` | daily full dump (PITR baseline) | **E3** |
| `modules/backup/pitr-restore.sh` | point-in-time restore | **E3** |
| `modules/backup/cli-pitr.sh` | `actools` CLI integration for PITR | **E3** |
| `modules/backup/deploy-pitr.sh` | manual PITR deploy script (entrypoint for the above) | **E3** |
| `modules/backup/mariadb-binlog.cnf` | binlog MariaDB config | **E3** |
| `modules/backup/99-binlog.cnf` | binlog MariaDB config | **E3** |
| `modules/backup/docker-compose.binlog.yml` | binlog volume compose override | **E3** |
| `modules/backup/actools-db-backup.cron` | backup cron entries | **E3** |
| `modules/audit/deploy-audit.sh` | self-declared UNWIRED + STALE; superseded by `lib/*.sh` | **Phase 5**: reconcile-or-delete |
| `modules/drupal/prepare.sh` | "Stage 1" extraction; superseded (`provision.sh` inlines it); unsourced | **Phase 5**: reconcile-or-delete |
| `modules/drupal/secure.sh` | self-declared UNWIRED; "Phase 5 decision" | **Phase 5**: wire-or-delete |

The 10-file `backup/` cluster is a **partial implementation of E2 + E3** — those
phases reconcile/test/harden it rather than build from scratch. C4 records and
guards these files; it wires, deletes, and moves nothing.

## Update rule

Every phase must update this map if it changes authority.
Expand Down
49 changes: 47 additions & 2 deletions docs/runbooks/PHASE0_LEDGER.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,52 @@ Approved / Needs revision / Blocked
### Forbidden next scope
````

## Entry 024 — C4: file-level orphan inventory + file-level wiring guard

Date: <fill on apply>
Phase: C4 (Track C — cleanup; the repurposed slot after vocabulary folded into D1)
Baseline: d482818 (#52)

### Objective

Inventory + pin the FILE-level wiring inside the 6 live modules (the dir-level C1
guard only proved which module DIRS are live). Of the 35 files: 21 wired
(source-closure of actools.sh, or executed/sourced via the cli/actools `audit`
command), 1 documentation (audit/docs/fix_catalog.md), and 13 UNWIRED that ship to
prod (in-place install + chown -R) but never execute — the 10-file backup/ "Phase
4.5 Item 2" PITR/binlog/encrypted-backup cluster (a partial E2/E3 implementation,
manually deployable via deploy-pitr.sh), audit/deploy-audit.sh (self-declared
stale), and drupal/{prepare,secure}.sh (superseded/unwired extractions; provision.sh
is the wired stage). Adds a new guard (live_module_file_inventory_test.bats) that
fails CI if any live-module file is unclassified or if an unwired file flips onto
the live closure; records the inventory in runtime-authority-map.md.

C4 changes NO module file. Disposition is DEFERRED: backup/* -> E2/E3
(reconcile/wire/harden the existing drafts); audit/deploy-audit.sh +
drupal/{prepare,secure}.sh -> Phase 5 (per their own self-declared notes).

### Runtime authority changes

None. No module/code/installer file is touched; the live source-closure is
byte-identical to d482818. C4 adds one doc subsection, one new guard test, and this
ledger entry. **Behavior-free -> no branch e2e required** (as with C1).

### Files

New: tests/guards/live_module_file_inventory_test.bats. Edited:
docs/architecture/runtime-authority-map.md (add the "File-level wiring within live
modules" subsection only; the existing Standalone section + line-45 row are
untouched, left to D1), this ledger.

### Verdict

Pending — the Review Gate ratifies on merge (this coding window does not
self-approve). Verify in order: see SPEC-C4 §6.

### Commit SHA

Sandbox commit on top of d482818; operator stamps the squash/merge SHA on apply.

## Entry 023 — C3: quarantine the 7 4.5-seed modules into experimental/

Date: <fill on apply>
Expand Down Expand Up @@ -132,8 +178,7 @@ Moved (git mv, 7 dirs / 11 files): `modules/{ai,compliance,dr,network,observabil

### Verdict

**Pending** — the Review Gate ratifies on merge (this coding window does not
self-approve). Verify in order: see SPEC-C3 §6.
**APPROVED — ratified (<date>): C3 merged to `main` as `d482818` (#52); branch e2e #87 reached `MariaDB ready.`, confirming the seed quarantine is transparent to the live path. `d482818` is the verified baseline of C4, and this ratification rides with the C4 patch — which adds the file-level inventory + guard on top of the C3 dir-level quarantine and re-runs all guards green.** *(Original pending text, for the record:)* **Pending** — the Review Gate ratifies on merge (this coding window does not self-approve). Verify in order: see SPEC-C3 §6.

### Commit SHA

Expand Down
103 changes: 103 additions & 0 deletions tests/guards/live_module_file_inventory_test.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bats
# =============================================================================
# live_module_file_inventory_test.bats — FILE-LEVEL wiring guard (Phase C4)
#
# The dir-level guard (orphan_inventory_guard_test.bats) proves WHICH module dirs
# are live. This guard proves, WITHIN the 6 live dirs, which files are reached on
# the live path vs which ship unwired — so an unwired file cannot (a) ship
# unflagged (every file must be classified in the manifest below) or (b) silently
# flip wiring (an unwired draft cannot enter the live source-closure without
# failing CI).
#
# C4 changes NO module file; disposition of the unwired files is deferred —
# backup/* -> E2/E3; audit/deploy-audit.sh, drupal/{prepare,secure}.sh -> Phase 5.
#
# Update this manifest when a file is added to / removed from a live module, or
# when a file's wiring changes. Non-vacuity demos are recorded in HANDOFF-C4.
# =============================================================================

load live_closure # build_live_closure + CLOSURE (reused byte-unmodified from C1)

REPO=""
setup() {
REPO="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)"
}

# --- the classified manifest (the 35 files of the 6 live modules) ---
# WIRED: reached on the live path (source-closure of actools.sh, OR executed /
# sourced via the cli/actools `audit` command).
EXPECTED_WIRED_FILES=(
modules/audit/audit.sh
modules/audit/lib/output.sh
modules/audit/lib/drupal.sh
modules/audit/lib/integration.sh
modules/audit/lib/stack.sh
modules/audit/lib/security.sh
modules/audit/lib/report.sh
modules/backup/cron.sh
modules/db/core.sh
modules/drupal/provision.sh
modules/host/age.sh
modules/host/docker.sh
modules/host/firewall.sh
modules/host/kernel.sh
modules/host/logrotate.sh
modules/host/packages.sh
modules/host/swap.sh
modules/stack/caddyfile.sh
modules/stack/compose.sh
modules/stack/images.sh
modules/stack/mycnf.sh
)
# DOC: ships as module documentation, executed by no code.
EXPECTED_DOC_FILES=(
modules/audit/docs/fix_catalog.md
)
# UNWIRED: ship on the box (in-place install) but OFF the live path. Disposition
# deferred — see header. These MUST stay off the live source-closure (test 2).
EXPECTED_UNWIRED_FILES=(
modules/backup/encrypted_backup.sh
modules/backup/binlog-rotate.sh
modules/backup/db-full-backup.sh
modules/backup/pitr-restore.sh
modules/backup/cli-pitr.sh
modules/backup/deploy-pitr.sh
modules/backup/mariadb-binlog.cnf
modules/backup/99-binlog.cnf
modules/backup/docker-compose.binlog.yml
modules/backup/actools-db-backup.cron
modules/audit/deploy-audit.sh
modules/drupal/prepare.sh
modules/drupal/secure.sh
)

@test "every file in the 6 live modules is classified (no surprise file ships)" {
local expected actual
expected="$(printf '%s\n' "${EXPECTED_WIRED_FILES[@]}" "${EXPECTED_DOC_FILES[@]}" "${EXPECTED_UNWIRED_FILES[@]}" | sort -u)"
actual="$(cd "$REPO" && find modules -type f | sort -u)"
if [[ "$expected" != "$actual" ]]; then
echo "Live-module file set drifted from the C4 manifest."
echo "A file was added/removed/renamed in a live module without updating this"
echo "guard. Classify it (wired / doc / unwired) and update the inventory in"
echo "runtime-authority-map.md. diff (expected vs actual):"
diff <(printf '%s\n' "$expected") <(printf '%s\n' "$actual") || true
return 1
fi
}

@test "no unwired live-module file is reached by the live install closure" {
build_live_closure "$REPO"
local breach="" f
for f in "${EXPECTED_UNWIRED_FILES[@]}"; do
if printf '%s\n' "${CLOSURE[@]}" | grep -qxF "$f"; then
breach="$breach $f"
fi
done
if [[ -n "$breach" ]]; then
echo "An UNWIRED live-module file is now on the live source-closure:"
printf ' %s\n' $breach
echo "If it was wired intentionally, move it from EXPECTED_UNWIRED_FILES to"
echo "EXPECTED_WIRED_FILES and update the runtime-authority-map inventory."
return 1
fi
}