Prepare the Audita implementation sprint

This commit is contained in:
2026-09-08 03:34:03 +00:00
parent da799198b2
commit c297f56b7e
4 changed files with 422 additions and 237 deletions

View File

@@ -1,259 +1,239 @@
# Implementation Plan 0001: Simplify Seriatim Source Installation
# Implementation Plan 0002: Install and Configure Audita
Status: done
Status: ready
Target executor: GPT-5.6-Terra
Feature roadmap:
[Feature 0001: Seriatim Source Installation](features/0001-seriatim-source-installation.md)
[Feature 0002: Audita Source Installation and Configuration](features/0002-audita-source-installation-and-configuration.md)
## Objective
Replace the current overengineered `ansible-role-seriatim` implementation with
the concise, module-driven role defined by Feature 0001. Preserve the useful
role metadata and supported installation outcome while removing persistent
build state, duplicated module logic, speculative recovery, and obsolete test
coverage.
Implement the small, independently usable `rakestraw.audita` role defined by
Feature 0002. Install Audita from its pinned source release, build its
executable on the managed host, and manage its complete versioned
configuration mapping using the minimal module-driven Seriatim pattern.
## Execution Rules
- Execute Stage 1 and Stage 2 in numeric order.
- Before each stage, confirm its preconditions and the working-tree state of
the owning repository.
- Modify only `ansible-role-seriatim`. Treat this workspace plan,
`rakestraw-ansible`, and `../seriatim` as read-only during implementation.
- Preserve unrelated and pre-existing changes. Stop if the role repository is
not clean at a stage boundary unless its changes are the expected output of
the immediately preceding stage.
- Follow `docs/conventions.md` and the Feature 0001 task flow. Trust the
idempotence and change detection of `apt`, Snap, `file`, and `git`.
- Keep the two rebuild triggers directly on the build task. Do not create an
intermediate rebuild fact, build handlers, or a handler flush.
- Do not run the installed executable from production role tasks. Verify its
build output in repository-local integration tests.
- Do not reintroduce fingerprints, checksums, sidecar build state, manual Git
cleanup, staged replacement, compiler inspection, or malformed-path
recovery.
- Before each stage, confirm its preconditions and the owning repository's
working-tree state.
- Modify only `ansible-role-audita`. Treat this workspace, `../audita`,
`rakestraw-ansible`, and every other repository as read-only.
- Preserve unrelated changes. Stop if the role repository is unexpectedly
dirty at a stage boundary.
- Follow `docs/conventions.md` and the Feature 0002 task flow. Trust the
idempotence and change detection of APT, Snap, `file`, `git`, and `copy`.
- Put the two rebuild conditions directly on the build task. Do not add an
intermediate fact, handler, or handler flush.
- Do not execute Audita from production role tasks. Executable and
configuration validation belong only in integration tests.
- Do not add fingerprints, checksums, sidecar state, manual Git cleanup,
staged replacement, compiler inspection, configuration preflight, or
out-of-band drift detection.
- Use fully qualified collection names and `argv` for command execution.
- Run each stage's validation before committing it. Do not begin Stage 2 if
Stage 1 fails validation.
- Commit each completed stage with the plain-English message specified below.
Do not push.
- Treat `/usr/local/src/seriatim` and `/usr/local/bin/seriatim` as disposable
role-managed state during local integration. Do not remove the obsolete
`/usr/local/src/seriatim.ansible-build-state` directory from the host; the
revised role simply stops managing it.
- Run each stage's validation before committing. Do not begin Stage 2 if Stage
1 fails.
- Commit each completed stage with its specified plain-English message. Do not
push.
- Treat `/usr/local/src/audita`, `/usr/local/bin/audita`, and
`/usr/local/etc/audita/config.yml` as disposable role-managed test state.
## Starting State and Preconditions
- `ansible-role-seriatim` is clean on `main` at commit `6fb1aa2` and is ten
commits ahead of its current `origin/main`.
- The workspace plan and revised feature roadmap are reviewed and committed
before out-of-band execution begins.
- `ansible-role-audita` is clean on `main` at initial commit `793e6d3`, tracking
`origin/main` without divergence.
- This plan and the approved Feature 0002 roadmap are committed before
out-of-band execution begins.
- The local controller and managed host are Ubuntu 26.04 `amd64`, with
passwordless privilege escalation available for the approved integration
test.
passwordless privilege escalation available.
- Workspace tooling is available in `../.venv/bin` from the role repository:
Ansible Core 2.21.3 and ansible-lint 26.8.0.
- `community.general` 13.3.0 remains pinned in
`collections/requirements.yml`, and the Go Snap channel `1.26/stable` is
available.
- Upstream tag `v1.5.0` resolves to commit
`0fc92f364316c874d366b00cdc884a33e1900b25`.
- The upstream `v1.5.0` contract remains:
- Go module requirement 1.25;
- build package `./cmd/seriatim`;
- `CGO_ENABLED=0`, `GOWORK=off`, `GOTOOLCHAIN=local`, and `-trimpath`;
- linker flags `-s -w -X
gitea.maximumdirect.net/eric/seriatim/internal/buildinfo.Version=<version>`;
- `seriatim --version` output `seriatim version <version>`.
- Upstream tag `v1.4.0` resolves to
`9202ccddb962ab499f0772d3c01efdf2ff703077` and supports the same build and
version contracts for the selected-version integration case.
- `community.general` 13.3.0 and Go Snap channel `1.26/stable` are available.
- Upstream tag `v0.9.1` resolves to
`a84941d68168a1ed9ea7423b6477ae8218be73f9` and uses Go 1.24.0.
- The release build uses package
`gitea.maximumdirect.net/eric/audita/cmd/audita`, `CGO_ENABLED=0`,
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flags `-s -w -X
gitea.maximumdirect.net/eric/audita/internal/buildinfo.Version=<version>`.
- Configuration schema version 1 accepts `{"version": 1}`. The command
`audita config validate --config <path>` emits `config is valid` for it.
- Buildable commit `46b7356a3b54a2771ce9a617e4fa3e8d13728cac` is available for the
checkout-change test. Do not use `v0.9.0` for that test because it resolves
to the same commit as `v0.9.1`.
## Repository Scope
- `ansible-role-seriatim` owns every implementation, interface, README, and
repository-local test change in this plan.
- `ansible-workspace-dnd` owns the roadmap, this plan, and aggregate status but
- `ansible-role-audita` owns all implementation, interface, README,
dependency, and repository-local test changes.
- `ansible-workspace-dnd` owns the roadmap, plan, and aggregate status but
remains unchanged during out-of-band implementation.
- `../seriatim` is the authoritative read-only application contract.
- `rakestraw-ansible` is a read-only style reference.
- `../audita` is the authoritative read-only application contract.
- `rakestraw-ansible` is a read-only style and configuration-policy reference.
- Every other repository in `workspace.yml` remains unchanged.
## Fixed Public Interface
Retain exactly these public defaults:
Implement exactly these defaults and matching argument specifications:
| Variable | Default | Purpose |
| --- | --- | --- |
| `seriatim_version` | `v1.5.0` | Git revision and version injected into the executable |
| `seriatim_repository_url` | `https://gitea.maximumdirect.net/eric/seriatim.git` | Source repository |
| `seriatim_source_dir` | `/usr/local/src/seriatim` | Managed source checkout |
| `seriatim_binary_path` | `/usr/local/bin/seriatim` | Installed executable |
| `seriatim_manage_build_dependencies` | `true` | Whether to install Git and Go |
| `seriatim_go_snap_channel` | `1.26/stable` | Go Snap channel |
| `seriatim_go_binary` | `/snap/bin/go` | Go executable used for the build |
| Variable | Default |
| --- | --- |
| `audita_version` | `v0.9.1` |
| `audita_repository_url` | `https://gitea.maximumdirect.net/eric/audita.git` |
| `audita_source_dir` | `/usr/local/src/audita` |
| `audita_binary_path` | `/usr/local/bin/audita` |
| `audita_manage_build_dependencies` | `true` |
| `audita_go_snap_channel` | `1.26/stable` |
| `audita_go_binary` | `/snap/bin/go` |
| `audita_config_path` | `/usr/local/etc/audita/config.yml` |
| `audita_config` | `{"version": 1}` |
The package, build flags, linker symbol, and build environment are fixed
implementation details. The selected version is both the Git ref and the value
injected into the binary.
The build details, ownership, and modes are fixed implementation details.
`audita_config` is the complete document, not an overlay onto hidden defaults.
## Stage 1: Replace the Role with the Minimal Implementation
**Completion:** Complete (`ansible-role-seriatim` commit `325a5c7`).
## Stage 1: Implement the Complete Minimal Role
### Objective
Replace the existing role contract, task graph, documentation, and baseline
test harness with one coherent minimal implementation that installs and
validates the default Seriatim release idempotently.
Create the role contract, concise production task flow, documentation, and
baseline test harness that install and configure Audita idempotently.
### Preconditions
- The starting-state commits and upstream contracts above are unchanged.
- `ansible-role-seriatim` has no uncommitted changes.
- The starting revisions and upstream contracts remain unchanged.
- `ansible-role-audita` has no uncommitted changes.
- The default managed paths contain no data that must be preserved.
### Owning Repository
`ansible-role-seriatim`
`ansible-role-audita`
### Required Changes
1. Reduce `defaults/main.yml` and `meta/argument_specs.yml` to the seven variables
in the Fixed Public Interface. Retain useful role and Galaxy metadata in
`meta/main.yml`.
2. Replace the imported task structure with one readable `tasks/main.yml` and
remove the obsolete task files. Implement approximately this task flow:
1. Add conventional role structure: defaults, metadata, argument
specifications, one task file, collection requirements, and focused local
tests. Retain the existing license and declare Ubuntu 26.04 support and
Ansible Core 2.18 or newer in Galaxy metadata.
2. Define exactly the nine variables above. Mirror their names and appropriate
scalar, boolean, and dictionary types in the argument specification; do not
duplicate Audita's configuration schema there.
3. Implement one readable `tasks/main.yml` with approximately this flow:
1. assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`;
2. install Git with `ansible.builtin.apt` when dependency management is
enabled;
3. install the classic Go Snap from `seriatim_go_snap_channel` with
2. install Git with `ansible.builtin.apt`, including
`cache_valid_time: 3600`, when dependency management is enabled;
3. install the classic Go Snap from `audita_go_snap_channel` with
`community.general.snap` when dependency management is enabled;
4. create the source and binary parent directories as `root:root` mode
`0755` with one `ansible.builtin.file` loop;
5. check out `seriatim_version` with `ansible.builtin.git`, using
`seriatim_repository_url`, `seriatim_source_dir`, and `force: true`, and
register the module result;
6. inspect `seriatim_binary_path` with `ansible.builtin.stat`;
7. build directly to `seriatim_binary_path` when the Git task changed or the
4. create source, binary, and configuration parent directories as
`root:root` mode `0755` with one `ansible.builtin.file` loop;
5. check out `audita_version` with `ansible.builtin.git`, `force: true`, and
register its result;
6. inspect `audita_binary_path` with `ansible.builtin.stat`;
7. build directly to `audita_binary_path` when the checkout changed or the
binary is absent;
8. converge recursive `root:root` source ownership and binary
`root:root` mode `0755` with one item-driven `ansible.builtin.file` loop;
3. Put the rebuild expression directly on the build command. Register the
Git and binary inspection results needed by its two conditions without
creating an intermediate rebuild fact.
4. Invoke `seriatim_go_binary` with `argv`, the fixed package, flags, linker
value, output path, working directory, and environment from the upstream
contract. Do not turn the remaining fixed values into defaults or facts.
Apply task-level privilege escalation to dependency installation and tasks
that manage root-owned application state.
5. Remove all code for Git executable discovery, Go executable and compiler
validation, manual Git status/reset/clean, resolved-commit facts, temporary
build directories, build inputs, fingerprints, checksums, sidecar state,
special path-object recovery, and transactional installation.
6. Do not add `handlers/main.yml`; the build and permission tasks execute in
normal order.
7. Rewrite the README to document the seven-variable interface, privilege and
fact requirements, dependency opt-out behavior, authoritative Git checkout,
direct build contract, two rebuild triggers, installed metadata, and
validation commands. Remove every claim or example tied to deleted
variables, state files, staging, compiler invalidation, or failure
preservation.
8. Rewrite `tests/verify.yml` to check only the selected commit, recursive
source ownership, binary type and metadata, and exact version output.
9. Replace `tests/integration` with a focused baseline driver that installs the
pinned collection locally, runs syntax checking and ansible-lint, converges
the default role, runs `tests/verify.yml`, and requires `changed=0` and
`failed=0` on an immediate repeat. Keep `tests/converge.yml`,
`tests/inventory`, and the compatible platform-guard playbook concise.
8. converge recursive `root:root` source ownership and binary `root:root`
mode `0755` with one item-driven `ansible.builtin.file` loop;
9. serialize `audita_config` as YAML at `audita_config_path` with
`ansible.builtin.copy`, `root:root` ownership, and mode `0644`.
4. Put the rebuild expression directly on the build command. Register only the
Git and binary results it needs. Invoke `audita_go_binary` with `argv`, the
fixed upstream build contract, output path, and source working directory.
5. Use task-level `become: true` for dependency installation and tasks that
manage root-owned state. Do not require play-level privilege escalation.
6. Pin `community.general` 13.3.0. Do not add handlers or abstractions for the
linear task flow.
7. Write a concise README covering the nine-variable interface, supported
platform, privilege and fact requirements, dependency opt-out, build and
configuration behavior, metadata, rebuild triggers, and test commands.
8. Add a baseline integration driver that installs the pinned collection into
a private temporary location, runs syntax checking and production-profile
ansible-lint, converges without play-level `become`, and verifies the
selected commit, recursive source ownership, binary metadata and execution,
configuration metadata, and exact native validation output
`config is valid`.
9. Require an immediate repeat role application to report `changed=0` and
`failed=0`. Keep paths repository-relative and temporary test artifacts out
of the repository.
### Validation
From `ansible-role-seriatim`, run:
From `ansible-role-audita`, run:
```sh
tests/integration
! rg -n \
'seriatim_(source_ref|build_version|build_state_dir|go_build_flags|go_ldflags|go_package)|fingerprint|checksum' \
defaults meta tasks tests README.md
git diff --check
git status --short
```
Expected result: static validation passes; the default source resolves to
`0fc92f364316c874d366b00cdc884a33e1900b25`; the binary reports
`seriatim version v1.5.0` with `root:root` ownership and mode `0755`; the
immediate repeat reports `changed=0` and `failed=0`; and only intended Stage 1
changes remain before commit.
Expected result: syntax and lint pass; source resolves to
`a84941d68168a1ed9ea7423b6477ae8218be73f9`; the executable runs and is
`root:root` mode `0755`; configuration is schema version 1 and `root:root`
mode `0644`; native validation reports `config is valid`; the immediate repeat
reports `changed=0` and `failed=0`; only intended Stage 1 changes remain.
### Completion Criteria
- The public interface contains exactly seven defaults and matching argument
specifications.
- The role's effective task flow matches the roadmap without intermediate
rebuild state or handlers.
- No role code or active documentation references the obsolete sidecar state
or removed variables.
- The baseline integration driver passes and proves default idempotence.
- No repository outside `ansible-role-seriatim` changed.
- Exactly nine defaults and matching argument specifications exist.
- Production flow matches the roadmap without unrequested probes, persisted
private state, or production validation commands.
- README, metadata, dependencies, tasks, and baseline tests agree.
- Baseline integration passes and proves default idempotence.
- No repository outside `ansible-role-audita` changed.
### Commit
Commit message: `Simplify the Seriatim role`
Commit message: `Install and configure Audita`
## Stage 2: Add Focused Behavioral Coverage
**Completion:** Complete (`ansible-role-seriatim` commit `718030e`).
### Objective
Extend the baseline test harness only far enough to prove the revised feature's
selected rebuild triggers, metadata convergence, platform guard, and final
default state.
Prove the selected rebuild triggers, independent configuration convergence,
dependency opt-out, metadata repair, platform guard, and restored default
state without expanding production behavior.
### Preconditions
- Stage 1 is committed and the role repository is otherwise clean.
- The Stage 1 baseline integration test passes.
- Upstream tags `v1.4.0` and `v1.5.0` remain available.
- Stage 1 integration passes.
- The default release and alternate buildable commit remain available.
### Owning Repository
`ansible-role-seriatim`
`ansible-role-audita`
### Required Changes
1. Extend `tests/integration` using strict shell options, repository-relative
paths, a private temporary directory, and cleanup that restores the default
`v1.5.0` installation when possible.
2. Retain the baseline convergence, verification, and clean-repeat cases, then
add focused cases for:
- an absent binary causing one rebuild followed by an unchanged run;
- dependency opt-out with a caller-supplied Go executable causing one build
paths, a private temporary directory, and cleanup that restores `v0.9.1`.
2. Retain baseline convergence, verification, and clean repeat, then test:
- an absent binary causes one rebuild followed by an unchanged run;
- dependency opt-out with a caller-supplied Go executable causes one build
followed by an unchanged run;
- binary ownership or mode drift being repaired by the ordinary `file` task
without requiring a rebuild, as shown by the captured Ansible task output;
- selecting `v1.4.0`, confirming its commit and version output, and reaching
an unchanged repeat;
- restoring `v1.5.0`, confirming its commit and version output, and reaching
a final unchanged repeat;
- unsupported distribution, Ubuntu release, and architecture inputs failing
- binary metadata drift is repaired by `file` without running the build,
followed by an unchanged run;
- changing `audita_config` updates only configuration state, passes native
validation, and reaches an unchanged repeat;
- selecting `46b7356a3b54a2771ce9a617e4fa3e8d13728cac` causes one checkout
rebuild followed by an unchanged run;
- restoring `v0.9.1` confirms its commit, causes one rebuild, and reaches a
final unchanged repeat;
- unsupported distribution, Ubuntu release, and architecture facts fail
before creating application state at isolated temporary paths.
3. Keep recap checks simple and fail the driver on hidden task failures or
unexpected changes during idempotence runs.
4. Keep test mutation limited to the two declared managed paths and paths below
the driver's private temporary directory.
5. Do not add cases for fingerprints, checksums, compiler changes, source-tree
dirt, staged failure preservation, custom-parent recovery, symbolic links,
malformed state, or the obsolete build-state directory.
6. Update the README test section to describe the actual focused suite and its
managed-host effects without advertising superseded behavior.
3. Inspect captured task output only where needed to distinguish a build from
metadata or configuration convergence. Fail on hidden task failures or
unexpected changes in idempotence runs.
4. Limit test mutation to the three declared managed paths and the driver's
private temporary directory.
5. Add no tests for version interrogation, fingerprints, checksums, compiler
changes, source dirt, staged failures, malformed host state, production
configuration preflight, or other non-goals.
6. Update the README test section to describe the focused suite and its host
effects.
### Validation
From `ansible-role-seriatim`, run:
From `ansible-role-audita`, run:
```sh
tests/integration
@@ -261,32 +241,33 @@ git diff --check
git status --short
```
Then confirm the restored default installation:
Then confirm the restored installation:
```sh
/usr/local/bin/seriatim --version
sudo git -C /usr/local/src/seriatim rev-parse HEAD
sudo stat -c '%U:%G %a' /usr/local/bin/seriatim
sudo git -C /usr/local/src/audita rev-parse HEAD
sudo stat -c '%U:%G %a' /usr/local/bin/audita
sudo stat -c '%U:%G %a' /usr/local/etc/audita/config.yml
/usr/local/bin/audita config validate --config /usr/local/etc/audita/config.yml
```
Expected result: the complete focused suite passes; all expected negative
platform cases are recognized; the final repeat reports `changed=0` and
`failed=0`; the restored executable reports `seriatim version v1.5.0`; the
source is at `0fc92f364316c874d366b00cdc884a33e1900b25`; binary metadata is
`root:root 755`; and only intended Stage 2 changes remain before commit.
Expected result: the focused suite and negative cases pass; the final repeat
reports `changed=0` and `failed=0`; source is restored to
`a84941d68168a1ed9ea7423b6477ae8218be73f9`; metadata is `root:root 755` for
the binary and `root:root 644` for configuration; validation reports
`config is valid`.
### Completion Criteria
- Every Feature 0001 acceptance criterion has direct test or static evidence.
- The suite tests only the revised operational contract and contains no
superseded hardening matrix.
- The README, defaults, argument specifications, task flow, and tests agree.
- The default local installation is restored and idempotent.
- No repository outside `ansible-role-seriatim` changed.
- Every Feature 0002 acceptance criterion has direct static or test evidence.
- Coverage remains limited to the selected operational contract.
- Configuration-only convergence demonstrably does not rebuild Audita.
- README, interface, tasks, and tests agree.
- Default local state is restored and idempotent.
- No repository outside `ansible-role-audita` changed.
### Commit
Commit message: `Focus Seriatim integration coverage`
Commit message: `Add focused Audita integration coverage`
## Final Validation and Handoff
@@ -300,21 +281,14 @@ cd ..
./scripts/status
```
The implementation handoff must report:
Report the two commit hashes, final integration and repeat results, restored
source commit, file metadata, native configuration-validation result, any
deviation or remaining concern, and any complexity beyond this task flow with
the acceptance criterion that required it.
- the Stage 1 and Stage 2 commit hashes in order;
- the final integration result and clean-repeat recap;
- the final source commit, version output, ownership, and mode;
- any deviation from this plan or the feature roadmap;
- any remaining implementation concern or potential future hardening item.
Do not edit workspace roadmap or status files, mark Feature 0001 `done`, or
push during out-of-band execution. Completion requires subsequent review.
Do not edit workspace planning files, mark Feature 0002 `done`, or push during
out-of-band execution. Completion requires subsequent review.
## Progress Notes
- Stage 1 completed in `ansible-role-seriatim` commit `325a5c7`.
- Stage 2 completed in `ansible-role-seriatim` commit `718030e`.
- The final manual-review remediation in `docs/roadmap/remediation.md` was
implemented and validated in `ansible-role-seriatim` commit `fb8dc41` on
2026-09-08. Feature acceptance remains a separate review step.
- Plan approved and ready for out-of-band execution on 2026-09-08.