diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index d4d44f8..db15d75 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -1,140 +1,168 @@ -# Feature 0008 Remediation Review +# Feature 0009 Remediation Review -Status: resolved +Status: open Reviewed implementation commits: -- `bc6df2a Add the D&D Audita configuration defaults` -- `7ca812c Add the Narratio D&D processing configuration` -- `c1fa8ba Test the D&D processing configuration` -- `e99983b Document D&D processing profiles and artifacts` +- `66ebea9 Make Audita configuration ownership configurable` +- `e9ae2dc Make Notarius configuration ownership configurable` +- `8b4c86e Make Scriptorium configuration ownership configurable` +- `eeb1105 Make Narratio configuration ownership configurable` -The implementation substantially matches Feature 0008. The pipeline role -selects the complete D&D Audita policy, deploys a small explicit ConfigKit -layout, keeps each ordinary artifact and the character family in its own -fragment, and provides a testing overlay that changes only Scriptorium profile -selection. Production convergence adds only one directory loop and one -template loop. Native validation, artifact inspection, both campaigns, profile -selection, and repeated convergence all succeed. +## Review Summary -Two narrow findings remain. +The four completed standalone-role stages are concise, idiomatic, and aligned +with Feature 0009. Each role exposes owner, group, configuration-directory +mode, and configuration-file mode variables; applies them directly through the +ordinary `file` and `template` tasks; preserves its standalone defaults; and +documents the interface. No redundant inspection, corrective convergence, +private state, or unrelated application behavior was introduced. All four +repository-local integration suites passed independently during review. -## Finding 1: Pin the Narratio Configuration Boundary Used by the Pipeline +Feature 0009 as a whole is not implemented. The active implementation plan and +workspace status correctly record a publication blocker after Stage 4. The +pipeline repository remains at pre-feature commit `3e253d7`; Stages 5 through +8 have not been executed. The following findings therefore describe missing +target architecture rather than defects in the completed standalone commits. + +## Finding 1: The Pipeline Does Not Select the Shared Configuration Policy + +Severity: high + +`ansible-role-dnd-pipeline/defaults/main.yml` and +`meta/argument_specs.yml` do not define the four suite-level runtime identity +and configuration-mode variables. `meta/main.yml:19-98` still runs Narratio +last and does not pass the new configuration ownership interfaces to Audita, +Notarius, Scriptorium, or Narratio. `requirements.yml:7-22` still pins the four +pre-feature role commits. + +Consequently, applying the current pipeline role retains standalone ownership: +Audita, Notarius, and Scriptorium configuration remains `root:root`, while +Narratio configuration remains `root:narratio` with its standalone restrictive +modes. The target `narratio:narratio`, `0755` directory, and `0644` file suite +policy is not selected. Narratio also does not establish the service identity +before the other configuration-bearing dependencies run. + +### Required Remediation + +- Publish the four reviewed standalone-role commits so immutable dependency + installation can resolve them; do not replace commit pins with branches. +- Execute Stage 5 of `docs/roadmap/implementation.md` in full. +- Add the four suite defaults and argument-spec entries, run Narratio first, + pass the selected identity and modes through every generic role interface, + update the four dependency pins, and apply the same values directly to the + pipeline-owned Narratio fragments. +- Retain direct module convergence without any post-dependency permission + repair. + +## Finding 2: Shared Writable-Root ACL Convergence Is Absent + +Severity: high + +`ansible-role-dnd-pipeline/collections/requirements.yml:1-4` contains only +`community.general`. `tasks/main.yml:1-65` neither installs Ubuntu's `acl` +package nor uses `ansible.posix.acl`. The three Narratio writable roots still +receive mode `2775` from the standalone role, but the suite does not establish +the access and default ACLs required to preserve group write and world +read/traverse behavior across invocation identities with different umasks. + +### Required Remediation + +- Execute Stage 6 of the implementation plan in full. +- Pin `ansible.posix` 2.2.0 alongside the existing collection dependency. +- Install `acl` with one ordinary privileged `ansible.builtin.apt` task. +- Apply the selected access and default ACL entries to exactly + `/var/lib/narratio`, `/var/spool/narratio`, and `/var/cache/narratio` with + direct, non-recursive `ansible.posix.acl` convergence. +- Do not add filesystem probes, `getfacl` production commands, recursive + migration, handler flow, or supplemental permission repair. + +## Finding 3: The Shared Execution Contract Has No Behavioral Coverage Severity: medium -`ansible-role-dnd-pipeline/tasks/main.yml:29-65` writes suite-owned fragments -under the fixed `/usr/local/etc/narratio` root and assigns them to the fixed -`narratio` group. `meta/main.yml:75-96` gives the standalone Narratio role -relative imports, but does not set `narratio_config_path` or `narratio_group`. +`ansible-role-dnd-pipeline/tests/integration:64-133` exercises the established +pipeline only as root and the `narratio` service account. It does not use a +representative existing member of the shared group, exchange writable-state +content between invocation identities, exercise inheritance under a +restrictive ordinary umask, or observe the deliberate world-readable boundary. -The assembled role therefore relies on two standalone-role defaults for state -that the pipeline itself consumes. If inventory supplies either unmapped -standalone variable—or if the standalone defaults later change—the Narratio -role can write its root document somewhere other than -`/usr/local/etc/narratio/pipeline.yml` or create a differently named group, -while the pipeline role continues using its fixed path and group. The result is -either unresolved relative imports or a failed file task on a fresh host. - -These are cross-role coordination values, not application-local defaults. The -roadmap explicitly fixes the root document, imported layout, and -`root:narratio` ownership boundary, so the suite role must establish the same -values on both sides. +The missing tests are important because the group-sharing outcome is suite +behavior authored by this feature, not a request to re-test an individual +Ansible module. The tests should exercise actual access rather than assert +mode values or parse ACL metadata. ### Required Remediation -- In the `rakestraw.narratio` dependency variables, explicitly set - `narratio_config_path: /usr/local/etc/narratio/pipeline.yml` and - `narratio_group: narratio`. -- Keep the fixed task paths and ownership unchanged. Do not add state probes, - path-discovery facts, or new public variables merely to restate this fixed - topology. -- Retain the exact relative import list and confirm native base/testing - validation and clean repeated convergence. +- Execute Stage 7 of the implementation plan after Findings 1 and 2 are + resolved. +- Use one uniquely named, test-owned operator account as an integration + fixture and clean up only that account and its explicitly named content. +- Validate one representative Narratio operation as that group member and one + bidirectional content exchange with the service account. +- Observe one representative world-readable configuration or artifact as an + account outside the group. +- Preserve immediate clean repeated convergence and avoid an exhaustive + identity, path, mode, or ACL matrix. -## Finding 2: Derive the Production Prompt Profile in the Integration Test +## Finding 4: Pipeline Consumer Documentation Is Stale -Severity: low +Severity: medium -`ansible-role-dnd-pipeline/tests/integration:87-90` separately asks -Scriptorium to inspect the hard-coded `claude-fable-latest` profile and then -inspects `dnd.session_recap` version `2.0.0`. The useful behavior is that the -explicitly inspected prompt's declared production profile resolves. The -literal profile name instead freezes a prompt-owned current value in the test. - -If the prompt deliberately selects a new default profile, this check can either -fail because the old profile is removed or continue passing without verifying -the new production profile. That is the change-detector pattern prohibited by -the testing policy. +`ansible-role-dnd-pipeline/README.md:185` still lists operator access among +deferred concerns. It does not document the new suite variables, +Narratio-first dependency order, service-owned and world-readable +configuration, shared setgid roots, inherited ACL behavior, +existing-group-member invocation, or the restricted future `secrets/` +boundary. ### Required Remediation -- Capture the existing native JSON result for the explicitly selected - `dnd.session_recap` prompt once. -- Read its `default_profile_id` and pass that value to Scriptorium's native - `inspect profile` command. -- Preserve the explicit `endpoint-profile` override as the representative - caller-selected testing case. -- Do not assert that `claude-fable-latest`, `gemini-flash-latest`, or any other - prompt/profile value remains a current default, and do not snapshot the - complete prompt document. +- Execute Stage 8 of the implementation plan after the production behavior and + tests are complete. +- Clearly distinguish generic standalone defaults from the pipeline's + opinionated overrides. +- Document setgid terminology, the three shared roots, supported invocation + identities, the fact that production does not manage human membership, and + the deliberate non-secret boundary. +- Do not promise the deferred secrets implementation, recursive migration, or + Feature 0010 Notarius behavior. -## Resolution +## Required Validation -Resolved in pipeline-role commit `3e253d7`. The Narratio dependency now pins -the fixed configuration path and group consumed by the pipeline role. The -integration driver now obtains the selected recap prompt's -`default_profile_id` from Scriptorium's native JSON inspection and validates -that profile without naming a prompt-owned default in the test. No public -variables, convergence tasks, or supplemental state were added. - -## Validation - -From `ansible-role-dnd-pipeline`, run: +After remediation, run the complete integration entry point in each changed +role: ```text -bash -n tests/integration -tests/integration -git diff --check -git status --short --branch +cd ansible-role-audita && tests/integration +cd ../ansible-role-notarius && tests/integration +cd ../ansible-role-scriptorium && tests/integration +cd ../ansible-role-narratio && tests/integration +cd ../ansible-role-dnd-pipeline && tests/integration ``` -Expected result: syntax checking and production-profile lint pass; Audita and -Narratio validate natively; base/testing comparison, representative inferred -dependency, family expansion, derived production-profile resolution, and the -explicit testing-profile override all succeed without provider calls; every -immediate repeat reports `changed=0` and `failed=0`; and only intended -remediation changes remain before commit. - -From the workspace root, run: +Then run from the workspace root: ```text +git diff --check ./scripts/status ``` -Expected result: implementation and reference repositories remain clean except -for intended remediation work before it is committed. +The expected result is that all five role suites pass syntax and lint checks, +native application checks succeed, the shared cross-identity contract is +observed, every immediate repeat reports `changed=0` and `failed=0`, all eight +implementation-stage commits are identified, and every repository is clean. ## Review Validation Evidence -During review, `ansible-role-dnd-pipeline/tests/integration` completed -successfully. It installed fresh pinned dependencies, passed Ansible syntax -checking and production-profile lint, validated the managed Audita policy, -validated base and testing Narratio configuration, observed the enabled recap, -inferred recap-to-rumor dependency, and disabled party-expanded character -family, resolved production and explicitly selected testing Scriptorium -profiles, and reported `changed=0` and `failed=0` on every required immediate -repeat. Cleanup restored the baseline suite. +During this review, the complete `tests/integration` entry points passed in +`ansible-role-audita`, `ansible-role-notarius`, +`ansible-role-scriptorium`, and `ansible-role-narratio`. Each suite installed +its pinned collection dependencies, passed syntax checking and +production-profile lint, exercised its native application behavior, and +reported clean immediate repeats. `git diff --check` passed and all +implementation repositories remained clean after testing. -Direct review also validated the `dilfs` campaign, inspected ConfigKit source -ownership and the complete effective artifact catalog, confirmed that the -default `gemini-flash-latest` testing profile currently resolves, and verified -that all profile differences are confined to `profile_id` leaves. All -repositories were clean before this remediation document was written. - -After remediation, `bash -n tests/integration`, the complete integration -driver, and `git diff --check` passed again. The driver performed fresh -dependency bootstrap, syntax checking, production-profile lint, native Audita -and Narratio validation, artifact and profile inspection, the explicit -testing-profile scenario, the explicit Seriatim-version scenario, and clean -immediate repeats before restoring the baseline suite. +The pipeline suite was not presented as Feature 0009 validation evidence +because the pipeline repository contains no Feature 0009 implementation +commits. Its current test suite exercises the prior Feature 0008 architecture.