diff --git a/docs/roadmap/features/0003-notarius-source-installation-and-configuration.md b/docs/roadmap/features/0003-notarius-source-installation-and-configuration.md index 13877e5..e4b70df 100644 --- a/docs/roadmap/features/0003-notarius-source-installation-and-configuration.md +++ b/docs/roadmap/features/0003-notarius-source-installation-and-configuration.md @@ -1,6 +1,6 @@ # Feature 0003: Notarius Source Installation and Configuration -Status: proposed +Status: in_progress ## Summary @@ -327,11 +327,10 @@ a configured pipeline, input artifacts, PromptKit assets and endpoints, and secret environment variables; those belong to consumers or later suite-level work. -After this roadmap is approved, replace the pending notice at -`docs/roadmap/implementation.md` with a numbered staged Notarius implementation -plan. The pipeline role can supply its D&D definitions through -`notarius_pipelines` and select the other field-specific values after the -standalone interface is implemented and reviewed. +The approved staged plan is maintained at +`docs/roadmap/implementation.md`. The pipeline role can supply its D&D +definitions through `notarius_pipelines` and select the other field-specific +values after the standalone interface is implemented and reviewed. ## Potential Future Hardening diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 69a9394..675519d 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,14 +1,392 @@ -# Implementation Plan +# Implementation Plan 0003: Install and Configure Notarius -Status: pending +Status: in_progress -No implementation plan is currently active. The Feature 0002 configuration -amendment was completed in `ansible-role-audita` commits `e61f02f` and -`847c4c3`. Its durable scope remains in -[the Feature 0002 roadmap](features/0002-audita-source-installation-and-configuration.md), -and its review history remains in [the remediation record](remediation.md). +Target executor: GPT-5.6-Terra -Feature 0003 is the next proposed unit of work. Its durable roadmap has been -revised to follow the workspace configuration-interface conventions and awaits -review and approval before this notice is replaced with a staged -implementation plan. +Feature roadmap: +[Feature 0003: Notarius Source Installation and Configuration](features/0003-notarius-source-installation-and-configuration.md) + +Active plan location: `docs/roadmap/implementation.md` + +## Objective + +Implement the small, independently usable `rakestraw.notarius` role defined +by Feature 0003. Install Notarius from its pinned source release, build its +executable on the managed host, and manage its versioned YAML configuration +through the approved nullable field-specific interface. + +The feature roadmap remains authoritative for scope, rationale, target end +state, and acceptance criteria. + +## Execution Rules + +- Execute Stage 1 and Stage 2 in numeric order. +- Before each stage, confirm its preconditions and the owning repository's + working-tree state. +- Modify only `ansible-role-notarius`. Treat this workspace, `../notarius`, + `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 0003 simplest viable + implementation. Trust the idempotence, change detection, check-mode + behavior, and error handling of APT, Snap, `file`, `git`, and `template`. +- Inspect only binary existence because that result is independently required + to decide whether the arbitrary build command must run. +- Put the two rebuild conditions directly on the build task. Do not add an + intermediate fact, handler, or handler flush. +- Do not execute Notarius from production role tasks. Executable and + configuration validation belong only in repository-local integration tests. +- Do not add configuration assembly facts, preliminary configuration probes, + fingerprints, checksums, sidecar state, manual Git cleanup, staged + replacement, compiler inspection, version interrogation, or out-of-band + drift detection. +- Render configuration with one template task. Use `is not none` for optional + values, omit empty parent sections, and serialize strings and mappings with + filters rather than hand-written quoting. +- Accept the already composed `notarius_pipelines` mapping. Do not load + pipeline files or implement merging, precedence, or a second configuration + interface inside the role. +- Use fully qualified collection names and `argv` for command execution. +- Run every stage's validation before committing it. Do not begin Stage 2 if + Stage 1 fails validation. +- Commit each completed stage with its specified plain-English message. Do not + push. +- Treat `/usr/local/src/notarius`, `/usr/local/bin/notarius`, and + `/usr/local/etc/notarius/config.yml` as disposable role-managed test state. + +## Starting State and Preconditions + +- `ansible-role-notarius` is clean on `main` at initial commit `f8a3e11`, + tracking `origin/main` without divergence. +- This plan and the ready Feature 0003 roadmap are committed before + out-of-band execution begins. +- Feature 0001 established the accepted minimal source-build task flow, and + Feature 0002 established the nullable field-specific configuration and + conditional-template conventions. +- The local controller and managed host are Ubuntu 26.04 `amd64`, with + gathered facts and 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 and Go Snap channel `1.26/stable` are available. +- Upstream tag `v0.6.0` resolves to + `77ae132e5609916da40dcd4fcc749c000a63cbac` and declares Go 1.25.5. +- The release build uses package `./cmd/notarius`, `CGO_ENABLED=0`, + `GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flag + `-X gitea.maximumdirect.net/eric/notarius/internal/buildinfo.Override=`. +- Configuration schema version 4 accepts a document containing only + `version: 4`. `notarius config validate --config ` validates a managed + file without requiring a selected pipeline. +- Tag `v0.5.0`, commit + `61436d7c186af57b06004e090ceac898e83cdb71`, remains available for the + checkout-change test. + +## Repository Scope + +- `ansible-role-notarius` owns all implementation, public interface, template, + README, dependency, metadata, and repository-local test changes. +- `ansible-workspace-dnd` owns the roadmap, plan, and aggregate status but + remains unchanged during out-of-band implementation. +- `../notarius` is the authoritative read-only build, CLI, and configuration + contract. +- `rakestraw-ansible` is a read-only style and deployment-policy reference. +- Every other repository in `workspace.yml` remains unchanged. + +## Fixed Public Interface + +Implement exactly the eight installation variables and fourteen +configuration variables in the Feature 0003 roadmap, with matching argument +specifications. + +Use these argument-specification types: + +- `str`: `notarius_version`, `notarius_repository_url`, + `notarius_go_snap_channel`, `notarius_promptkit_profile_dir`, + `notarius_promptkit_profile_file`, + `notarius_promptkit_local_backend_endpoint`, + `notarius_output_directory`, `notarius_cache_chunk_plans_mode`, + `notarius_cache_chunk_plans_directory`, + `notarius_cache_checkpoints_directory`, and `notarius_debug_directory`; +- `path`: `notarius_source_dir`, `notarius_binary_path`, + `notarius_go_binary`, and `notarius_config_path`; +- `bool`: `notarius_manage_build_dependencies` and + `notarius_cache_checkpoints_enabled`; +- `int`: `notarius_config_version`, + `notarius_promptkit_local_backend_concurrency_limit`, + `notarius_concurrency_total_llm`, and + `notarius_concurrency_stage_workers_extract`; +- `dict`: `notarius_pipelines`. + +The eight installation variables and `notarius_config_version` are required +by the argument specification because they have concrete defaults. The other +thirteen configuration variables are optional and default to YAML null. Do not +add `notarius_config`, a template override, a raw-file variable, or hidden +configuration defaults. + +## Stage 1: Implement the Complete Minimal Role + +### Objective + +Create the role contract, concise production task flow, conditional +configuration template, documentation, and baseline integration harness that +install and configure Notarius idempotently. + +### Preconditions + +- The starting revisions and upstream contracts remain unchanged. +- `ansible-role-notarius` has no uncommitted changes. +- The default managed paths contain no data that must be preserved. + +### Owning Repository + +`ansible-role-notarius` + +### Required Changes + +1. Retain the existing license and add the conventional role structure: + `defaults/main.yml`, `meta/main.yml`, `meta/argument_specs.yml`, + `tasks/main.yml`, `templates/config.yml.j2`, + `collections/requirements.yml`, `ansible.cfg`, and focused files under + `tests/`. +2. Declare role name `notarius`, namespace `rakestraw`, Ubuntu 26.04 support, + Ansible Core 2.18 or newer, an empty role dependency list, and the canonical + issue tracker. Pin `community.general` to version `13.3.0`. +3. Define exactly the twenty-two public variables from the roadmap. Keep all + thirteen optional configuration values explicitly null. Mirror the public + names and the types above in `meta/argument_specs.yml`; do not encode + Notarius's semantic validation rules in Ansible. +4. Implement one readable `tasks/main.yml` with this flow: + 1. assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`; + 2. install Git with `ansible.builtin.apt`, including + `cache_valid_time: 3600`, when dependency management is enabled; + 3. install the classic Go Snap from `notarius_go_snap_channel` with + `community.general.snap` when dependency management is enabled; + 4. create the source, binary, and configuration parent directories as + `root:root` mode `0755` with one `ansible.builtin.file` loop; + 5. check out `notarius_version` with `ansible.builtin.git`, `force: true`, + and register the module result; + 6. inspect only `notarius_binary_path` with `ansible.builtin.stat`; + 7. build directly to `notarius_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; + 9. render `templates/config.yml.j2` to `notarius_config_path` as + `root:root` mode `0644` with one `ansible.builtin.template` task. +5. Invoke `notarius_go_binary` with `ansible.builtin.command` and `argv` from + `notarius_source_dir`. Use the fixed package, environment, trim-path flag, + linker symbol, selected version, and output path from the upstream build + contract. This build is the only production command; rely on the command + module's ordinary changed result when it runs. +6. Put `notarius_checkout.changed or not notarius_binary.stat.exists` + directly on the build task. Register only the Git and binary results needed + by that expression. +7. Use task-level `become: true` for dependency installation and every task + that manages root-owned state. Do not require play-level privilege + escalation. +8. Make the template always emit `version`. Emit these optional structures + only when their variables are non-null: + - `promptkit`, with direct profile-source fields and nested `local_backend`; + - `pipelines`, serialized from the caller-supplied mapping without + structural rewriting; + - `concurrency`, with nested `stage_workers.extract`; + - `output`; + - `cache`, with independently conditional `chunk_plans` and `checkpoints`; + - `debug`. +9. Preserve explicit false, zero, empty string, and empty mapping values by + testing presence with `is not none`. Serialize scalar values and the + pipeline mapping safely; do not build a configuration dictionary in a fact + or reproduce application defaults. +10. Replace the placeholder README with concise documentation covering the + supported platform, fact and privilege requirements, all public variables, + dependency opt-out, build behavior, rebuild triggers, null-as-omission + behavior, secrets boundary, native `pipelines` mapping, caller-side + `combine` example, and test effects. +11. 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: + - source commit `77ae132e5609916da40dcd4fcc749c000a63cbac` and recursive + `root:root` source ownership; + - binary `root:root` ownership, mode `0755`, and output + `notarius v0.6.0`; + - configuration `root:root` ownership, mode `0644`, and parsed content + exactly equal to `{"version": 4}`; + - native configuration validation succeeds; and + - an immediate repeat reports `changed=0` and `failed=0`. +12. Keep repository paths relative and temporary test artifacts outside the + repository. The integration driver's cleanup must restore the default + release and minimal configuration. + +### Validation + +From `ansible-role-notarius`, run: + +```sh +tests/integration +git diff --check +git status --short +``` + +Expected result: syntax and lint pass; source resolves to +`77ae132e5609916da40dcd4fcc749c000a63cbac`; the executable reports +`notarius v0.6.0` and is `root:root` mode `0755`; the configuration parses as +exactly `{"version": 4}`, is `root:root` mode `0644`, and passes Notarius's +native validation; the immediate repeat reports `changed=0` and `failed=0`; +only intended Stage 1 changes remain. + +### Completion Criteria + +- Exactly eight installation defaults and fourteen configuration defaults + exist with matching argument specifications. +- Production tasks follow the nine-operation roadmap flow without unrequested + probes, persisted private state, handlers, or production validation. +- The template implements every public configuration field and the required + omission semantics without a parallel interface. +- README, metadata, dependencies, tasks, template, and baseline tests agree. +- Baseline integration passes and proves default convergence and idempotence. +- No repository outside `ansible-role-notarius` changed. + +### Commit + +Commit message: `Install and configure Notarius` + +## Stage 2: Add Focused Behavioral Coverage + +### Objective + +Prove the selected rebuild triggers, independent configuration convergence, +inventory-side pipeline composition, falsey-value rendering, dependency +opt-out, metadata repair, platform guard, and restored default state without +expanding production behavior. + +### Preconditions + +- Stage 1 is committed and `ansible-role-notarius` is otherwise clean. +- Stage 1 integration passes. +- The default and alternate upstream revisions remain available. + +### Owning Repository + +`ansible-role-notarius` + +### Required Changes + +1. Extend `tests/integration` using strict shell options, + repository-relative paths, a private temporary directory, and cleanup that + restores `v0.6.0` and the minimal configuration. +2. Retain baseline convergence, verification, native configuration validation, + and clean repeat, then test: + - an absent binary causes one build followed by an unchanged run; + - dependency opt-out with a caller-supplied Go executable causes one build + through that executable followed by an unchanged run; + - binary metadata drift is repaired by `ansible.builtin.file` without + running the build, followed by an unchanged run; + - selecting `v0.5.0` causes one checkout rebuild, installs commit + `61436d7c186af57b06004e090ceac898e83cdb71`, and reaches an unchanged run; + - restoring `v0.6.0` causes one checkout rebuild, restores the default + commit, and reaches an unchanged run; + - unsupported distribution, Ubuntu release, and architecture facts fail + before creating application state at isolated temporary paths. +3. Add configuration verification that parses the YAML and compares native + structures rather than relying on whitespace or key order. Cover: + - the exact minimal document; + - a valid representative configuration spanning `promptkit`, `pipelines`, + `concurrency`, `output`, both cache subsections, and `debug`; + - each PromptKit profile-source field in separate valid scenarios because + Notarius makes them mutually exclusive; + - null omission and parent-section omission; + - explicit false, zero, empty string, and empty mapping rendering, without + requiring semantically invalid falsey examples to pass native validation; + - restoration to the exact minimal document. +4. Exercise caller-side pipeline composition directly. Define at least two + inventory mappings, each keyed by a distinct pipeline ID, assign + `notarius_pipelines` with the ordinary `combine` filter, and prove both + native definitions are rendered without role-side rewriting and pass + `notarius config validate`. +5. Prove each configuration-only transition changes the template task, skips + the build task, and reaches an unchanged immediate repeat. Do not add + production tasks to facilitate testing. +6. Inspect captured task output only where necessary to distinguish build, + metadata, and configuration convergence. Fail on hidden task failures or + unexpected changes in idempotence runs. +7. Limit test mutation to the three declared managed paths and the driver's + private temporary directory. Leave the default release and minimal + configuration installed after successful or failed test execution when + restoration is possible. +8. Add no coverage that implies production support for version interrogation, + fingerprints, checksums, compiler drift, source dirt, staged build failure, + malformed adversarial host state, role-side pipeline merging, or production + configuration preflight. +9. Update the README test section to describe the focused suite, pipeline + composition coverage, and managed-host effects. + +### Validation + +From `ansible-role-notarius`, run: + +```sh +tests/integration +git diff --check +git status --short +``` + +Then confirm the restored installation: + +```sh +sudo git -C /usr/local/src/notarius rev-parse HEAD +sudo stat -c '%U:%G %a' /usr/local/bin/notarius +sudo stat -c '%U:%G %a' /usr/local/etc/notarius/config.yml +/usr/local/bin/notarius --version +/usr/local/bin/notarius config validate --config /usr/local/etc/notarius/config.yml +``` + +Expected result: all focused and negative cases pass; every required repeat +reports `changed=0` and `failed=0`; source is restored to +`77ae132e5609916da40dcd4fcc749c000a63cbac`; metadata is `root:root 755` for +the binary and `root:root 644` for configuration; the executable reports +`notarius v0.6.0`; and native validation accepts the restored minimal file. + +### Completion Criteria + +- Every Feature 0003 acceptance criterion has direct static or integration + evidence. +- Configuration coverage proves nullable field rendering, empty-parent + omission, intentional falsey values, and native validity where applicable. +- Inventory-defined pipeline maps compose into the native field without any + role-side merge mechanism. +- Configuration-only convergence demonstrably does not rebuild Notarius. +- Coverage remains limited to the selected operational contract. +- README, interface, tasks, template, and tests agree. +- Default local state is restored and idempotent. +- No repository outside `ansible-role-notarius` changed. + +### Commit + +Commit message: `Add focused Notarius integration coverage` + +## Final Validation and Handoff + +After Stage 2, run: + +```sh +tests/integration +git log --oneline -2 +git status --short --branch +cd .. +./scripts/status +``` + +Report the two commit hashes, final integration and repeat results, restored +source commit, file metadata, executable version, native +configuration-validation result, any deviation or remaining concern, and any +complexity beyond this task flow with the acceptance criterion that required +it. + +Do not edit workspace planning files, mark Feature 0003 `done`, or push during +out-of-band execution. Completion requires subsequent review. + +## Progress Notes + +- Stage 1 completed in `ansible-role-notarius` commit `287fc4a`. +- Stage 2 completed in `ansible-role-notarius` commit `733a194`. +- Post-implementation review passed the complete integration suite and opened + the findings in `docs/roadmap/remediation.md`. diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index 619e0a9..0aa6bb9 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -1,40 +1,84 @@ -# Feature 0002A Remediation Review +# Feature 0003 Remediation Review -Status: resolved +Status: open -The field-specific Audita configuration implementation has the intended -architecture and its complete integration suite passes. +Reviewed implementation commits: -## Finding 2: Synchronize Amendment Progress Tracking +- `287fc4a Install and configure Notarius` +- `733a194 Add focused Notarius integration coverage` + +The role's complete integration suite passes. The production architecture is +substantially complete and follows the selected nine-operation flow, but the +following issues should be corrected before Feature 0003 is marked done. + +## Finding 1: Correct the Galaxy License Metadata + +Severity: medium + +`ansible-role-notarius/meta/main.yml` declares `license: BSD-3-Clause`, while +the repository's retained `LICENSE` file is CC0 1.0 Universal. Package metadata +must not misstate the terms under which the repository is distributed. + +### Required Remediation + +- Change the Galaxy license identifier to `CC0-1.0`, consistent with the + repository license and the other standalone roles that use the same license. +- Run metadata lint as part of the complete integration suite. + +## Finding 2: Remove the Redundant Build Change Override Severity: low -The configuration amendment was completed in `ansible-role-audita` commits -`e61f02f` and `847c4c3`, while the implementation plan and workspace status -still described it as awaiting execution. +The `Build Notarius` task sets `changed_when: true`. The +`ansible.builtin.command` module already reports a successful executed command +as changed, and the task's `when` expression already determines exactly when a +build occurs. The override adds no behavior and conflicts with the convention +to trust module behavior and require a reason for every additional directive. -### Resolution +### Required Remediation -- Recorded the completed amendment commits in the durable Feature 0002 - roadmap. -- Marked Feature 0002 complete in workspace status. -- Replaced the completed fixed-location implementation plan with a pending-plan - notice for Feature 0003. -- Preserved Feature 0003 as the next proposed unit of work and identified its - configuration-interface revision as the next roadmap-review step. +- Remove `changed_when: true` from the production build task. +- Retain the existing rebuild expression unchanged: + `notarius_checkout.changed or not notarius_binary.stat.exists`. +- Run the complete integration suite to confirm that build runs still report + changed and immediate repeats remain clean. -## Review Conclusion +## Finding 3: Make the Dependency-Opt-Out Test Prove the Selected Go Binary -No code remediation was required. A proposed assertion that the configuration -was a regular file was rejected because a successful -`ansible.builtin.template` operation already establishes the specified file -state. Adding another assertion would re-prove the module's documented -postcondition and conflict with the workspace convention to trust Ansible's -abstraction boundary. +Severity: low -The review ran the complete `tests/integration` suite on Ubuntu 26.04 with -Ansible Core 2.21.3 and ansible-lint 26.8.0. It passed default minimal -rendering, representative nested rendering, explicit falsey values, native -configuration validation, configuration-only convergence, both rebuild -triggers, dependency opt-out, metadata repair, restored default state, -repeated convergence, and platform rejection. `git diff --check` also passed. +The integration suite sets `notarius_go_binary` to a symlink whose target is +`/snap/bin/go`. The test succeeds with the current implementation, but it would +also succeed if the build task ignored `notarius_go_binary` and hard-coded +`/snap/bin/go`. It therefore does not establish the acceptance criterion that +a caller-supplied Go executable is actually used. + +### Required Remediation + +- Replace the symlink with a small executable wrapper in the suite's private + temporary directory. +- Have the wrapper record its invocation and then delegate to `/snap/bin/go`. +- Assert that the invocation record was written during the dependency-opt-out + build, while retaining the existing clean-repeat assertion. +- Keep the wrapper and its record in the existing private temporary directory; + do not add production behavior. + +## Review Evidence + +The review ran from `ansible-role-notarius`: + +```sh +tests/integration +git diff --check +``` + +The complete suite passed with Ansible Core 2.21.3 and ansible-lint 26.8.0. It +covered default convergence, the selected source commit, executable version, +native configuration validation, clean repeats, missing-binary and checkout +rebuilds, metadata repair without rebuilding, nullable field rendering, +PromptKit source alternatives, intentional falsey values, caller-side +pipeline-map composition, dependency opt-out, and platform rejection. The +suite restored Notarius `v0.6.0` and the minimal `version: 4` configuration. + +No additional production tasks, configuration probes, runtime validation, +private state, or unrequested hardening were found. diff --git a/docs/status.md b/docs/status.md index 250904d..9235381 100644 --- a/docs/status.md +++ b/docs/status.md @@ -4,7 +4,7 @@ Last updated: 2026-09-08 Current milestone: MVP standalone application roles -Current focus: Review the revised Feature 0003 Notarius roadmap. +Current focus: Remediate the Feature 0003 post-implementation review findings. | ID | Deliverable | Owner | State | Evidence or next step | | --- | --- | --- | --- | --- | @@ -13,13 +13,13 @@ Current focus: Review the revised Feature 0003 Notarius roadmap. | M0-03 | Tracked MVP roadmap | workspace | done | `docs/roadmap/mvp.md` established | | M0-04 | Aggregate repository status | workspace | done | `scripts/status` created | | M0-05 | Suite-level role repository | ansible-role-dnd-pipeline | done | Repository created and added to `workspace.yml` | -| M1-01 | Remaining MVP design decisions | workspace | ready | Approve the revised Notarius configuration interface | -| M1-02 | Standalone application roles | role repositories | in_progress | Review and approve the revised Notarius feature roadmap | +| M1-01 | Remaining MVP design decisions | workspace | done | Feature 0003 roadmap fixes the Notarius configuration interface | +| M1-02 | Standalone application roles | role repositories | in_progress | Resolve the Feature 0003 remediation findings | | M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | proposed | Begin after standalone role interfaces stabilize | | M1-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism | | F0001 | Install Seriatim from pinned source | ansible-role-seriatim | done | Implementation, integration coverage, and final remediation completed through `fb8dc41` | | F0002 | Install and configure Audita | ansible-role-audita | done | Field-specific configuration completed in `e61f02f` and `847c4c3`; full suite passed | -| F0003 | Install and configure Notarius | ansible-role-notarius | proposed | Review and approve the convention-aligned feature roadmap | +| F0003 | Install and configure Notarius | ansible-role-notarius | in_progress | Resolve the findings in `docs/roadmap/remediation.md` | ## Updating This File