diff --git a/docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md b/docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md index ebf751f..9f5b2c0 100644 --- a/docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md +++ b/docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md @@ -1,6 +1,6 @@ # Feature 0009: Shared Pipeline Filesystem and Execution -Status: in_progress +Status: done ## Summary diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index de45ee7..12a37fb 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,876 +1,13 @@ -# Implementation Plan 0009: Shared Pipeline Filesystem and Execution +# Implementation Plan -Status: ready +Status: pending -Target executor: GPT-5.6-Terra +No implementation plan is currently active. Feature 0009 was implemented, +independently reviewed, and completed through pipeline-role remediation commit +`b15fe8d`. Its durable scope, decisions, and acceptance criteria remain in +[Feature 0009](features/0009-shared-pipeline-filesystem-and-execution.md), and +the completed review record remains in [the remediation +document](remediation.md). -Feature roadmap: -`docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` - -Active plan location: `docs/roadmap/implementation.md` - -## Objective - -Give each configuration-bearing standalone role a small, generic ownership -and mode interface, then have the D&D pipeline role select the suite's -`narratio:narratio` and world-readable configuration policy through those -interfaces. Establish setgid and default-ACL behavior on the three existing -Narratio writable roots so the service account and an existing human member of -the shared group can safely use the same state. - -The feature roadmap remains authoritative for scope, rationale, target end -state, and acceptance criteria. Decision 0002 remains authoritative for the -shared-readable filesystem boundary. - -## Execution Rules - -- Execute stages in numeric order. -- Before each stage, confirm its preconditions and the working-tree state of - its owning repository. -- Before each stage, reread every document listed in that stage's Required - Policy Review. Do not rely on policy recalled from an earlier stage. -- Preserve unrelated and pre-existing changes. Stop if an owning repository is - unexpectedly dirty at a stage boundary. -- Keep standalone roles independently useful. They expose generic owner, - group, directory-mode, and file-mode controls; only the pipeline role selects - `narratio:narratio`, `0755`, and `0644` as D&D suite policy. -- Change only the existing directory and template operations that own - configuration. Do not add corrective permission passes, preliminary - `stat` calls, handlers, validation tasks, checksums, manifests, or - role-private state. -- Trust `ansible.builtin.file`, `ansible.builtin.template`, - `ansible.builtin.apt`, and `ansible.posix.acl` to converge their documented - state. Apply `become: true` only to tasks that require it. -- Keep source checkouts, installed binaries, campaign assets, and prompt - assets outside the new configuration ownership interface. -- Do not create a `secrets/` directory, deliver credentials, select human - operators, alter an existing human account's group membership in production, - or recursively rewrite existing runtime descendants. -- Use `ansible.posix` version `2.2.0`, the current stable release selected for - this plan. Do not substitute another collection or version during execution. -- Test the public operating contract through native application use and actual - cross-identity read/write behavior. Do not assert task order, module results, - exact default values, or filesystem metadata merely to restate module - arguments. -- Run every stage's validation before committing it. Commit each completed - stage when it leaves the owning repository valid, using the plain-English - commit intent specified by that stage. -- Do not begin a dependent stage after an earlier stage fails validation. -- Do not push during implementation. Before Stage 5, the commits produced by - Stages 1 through 4 must nevertheless be reachable from their canonical Git - origins so the pipeline's isolated dependency installation can consume exact - immutable revisions. If they are not reachable, stop after Stage 4 and - report the four hashes for publication rather than weakening the dependency - test or using branch references. - -## Starting State and Preconditions - -- The workspace control repository contains the committed Feature 0009 - roadmap, Decision 0002, and settled MVP filesystem policy at `a7d7189` or a - reviewed descendant. -- Features 0001 through 0008 and the standalone-role test-suite simplification - are complete. -- The following implementation repositories are clean on `main` at these - reviewed starting commits: - - | Repository | Starting commit | - | --- | --- | - | `ansible-role-audita` | `d2d0b9d00b3b491ce7613ccfc8f686f3d1fa0896` | - | `ansible-role-notarius` | `cfecf37261f2595d45113235c591ee102d6f181f` | - | `ansible-role-scriptorium` | `8f47aa802a5e0c9dae9c0f43a1c70b3512b2c8b2` | - | `ansible-role-narratio` | `7feff4728a5968b6b1dd87e83add9fa1a9066b18` | - | `ansible-role-dnd-pipeline` | `3e253d714d0e242f2bcb25e1552d3f8511004d85` | - -- The four standalone-role starting commits match `origin/main`. The pipeline - starting commit is local and may be ahead of `origin/main`; this is expected - and must not be reset or replaced. -- The workspace `.venv` provides Ansible Core 2.21.3 and ansible-lint 26.8.0. -- The integration host is an accepted Ubuntu 26.04 proxy, supports task-level - privilege escalation, and provides ordinary POSIX ACL support. -- `ansible.posix` 2.2.0 supports Ansible Core 2.16 or newer and supplies the - `ansible.posix.acl` module used by this feature. -- Notarius remains at the Feature 0008-compatible release during this feature. - Its v0.7.0 upgrade, ConfigKit import interface, D&D pipeline, and cache root - belong to Feature 0010. - -## Repository Scope - -Repositories that change: - -- `ansible-role-audita`: generic Audita configuration ownership and mode - interface, argument specification, tasks, and consumer documentation. -- `ansible-role-notarius`: generic Notarius configuration ownership and mode - interface, argument specification, tasks, and consumer documentation. -- `ansible-role-scriptorium`: generic Scriptorium configuration ownership and - mode interface, argument specification, tasks, and consumer documentation. -- `ansible-role-narratio`: generic Narratio configuration ownership and mode - interface, argument specification, tasks, and consumer documentation. -- `ansible-role-dnd-pipeline`: dependency order and pins, suite identity and - configuration policy, ACL dependency and convergence, focused integration - coverage, and consumer documentation. - -Repositories that may be inspected but must remain unchanged: - -- `ansible-role-seriatim`, which owns no application configuration file. -- `ansible-collection-dnd`, whose assembly remains later work. -- `../{audita,notarius,scriptorium,narratio,seriatim}`, which remain the - read-only application authorities. -- `assets/campaigns`, `assets/narratio-prompts`, and `assets/configs`. -- `rakestraw-ansible` and every other repository in `workspace.yml`. -- The workspace control repository during implementation stages. It is updated - only before or after the sprint for planning and progress management. - -## Stage 1: Expose Audita Configuration Ownership - -### Objective - -Make Audita's managed configuration ownership and modes configurable while -preserving its current standalone installation as the default. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- `ansible-role-audita/defaults/main.yml` -- `ansible-role-audita/meta/argument_specs.yml` -- `ansible-role-audita/tasks/main.yml` -- `ansible-role-audita/tests/integration` -- `ansible-role-audita/README.md` - -### Preconditions - -- `ansible-role-audita` is clean at the stated starting commit. -- Its existing integration suite passes before modification. - -### Owning Repository - -`ansible-role-audita` - -### Required Changes - -1. Add these required, defaulted public variables: - `audita_config_owner: root`, `audita_config_group: root`, - `audita_config_directory_mode: "0755"`, and - `audita_config_file_mode: "0644"`. -2. Add matching string entries to `meta/argument_specs.yml`, with descriptions - that distinguish the configuration directory mode from the managed file - mode. -3. Keep source and binary parent directories `root:root` mode `0755`. Manage - `audita_config_path | dirname` directly with the four configuration inputs, - either by giving it a distinct declarative file task or by using an equally - clear existing loop shape. -4. Replace the template task's hard-coded owner, group, and mode with the new - variables. Do not add a follow-up file task, state inspection, or other task - flow. -5. Document all four variables and their standalone defaults in the README. - Explain that composing roles may override them; do not introduce D&D policy - into this role. -6. Keep the existing focused integration suite and clean-repeat contract. Do - not add metadata assertions or a test whose only purpose is to prove that - `file` or `template` honored its arguments. - -### Validation - -Run from `ansible-role-audita`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: syntax and lint pass, Audita natively validates its managed -configuration, every existing representative behavior remains valid, the -immediate repeat reports `changed=0` and `failed=0`, and only intended Audita -role files are modified. - -### Completion Criteria - -- The four public inputs, argument specification, directory operation, - template operation, and README agree. -- The default standalone result remains `root:root`, `0755` for the directory, - and `0644` for the file. -- No new production task exists solely to inspect or repair module-managed - state. - -### Commit - -Commit intent: `Make Audita configuration ownership configurable` - -## Stage 2: Expose Notarius Configuration Ownership - -### Objective - -Make Notarius's managed configuration ownership and modes configurable while -leaving its application version and configuration schema unchanged for Feature -0010. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- `ansible-role-notarius/defaults/main.yml` -- `ansible-role-notarius/meta/argument_specs.yml` -- `ansible-role-notarius/tasks/main.yml` -- `ansible-role-notarius/tests/integration` -- `ansible-role-notarius/README.md` - -### Preconditions - -- Stage 1 is committed and validated. -- `ansible-role-notarius` is clean at the stated starting commit. -- Its existing integration suite passes before modification. - -### Owning Repository - -`ansible-role-notarius` - -### Required Changes - -1. Add `notarius_config_owner: root`, `notarius_config_group: root`, - `notarius_config_directory_mode: "0755"`, and - `notarius_config_file_mode: "0644"` as required, defaulted public inputs. -2. Add matching string argument-specification entries. -3. Keep source and binary parents under the existing `root:root` mode `0755` - policy. Apply the new inputs directly when managing - `notarius_config_path | dirname`. -4. Use the same inputs directly in the existing configuration template task. - Do not add permission-repair tasks, inspection, handlers, or validation to - production convergence. -5. Document the interface and standalone defaults without mentioning the D&D - cache, ConfigKit imports, Notarius v0.7.0, or any other Feature 0010 work. -6. Retain the existing native and clean-repeat integration behavior without - adding filesystem metadata assertions or tests of trusted modules. - -### Validation - -Run from `ansible-role-notarius`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: syntax and lint pass, the current Notarius configuration and -explicit version-selection cases remain natively valid, all immediate repeats -remain clean, and only intended Notarius role files are modified. - -### Completion Criteria - -- The generic four-variable interface is complete and documented. -- Existing version, schema, cache, and pipeline behavior is unchanged. -- Standalone defaults remain `root:root`, `0755`, and `0644`. -- Production convergence contains no redundant permission machinery. - -### Commit - -Commit intent: `Make Notarius configuration ownership configurable` - -## Stage 3: Expose Scriptorium Configuration Ownership - -### Objective - -Make Scriptorium's managed configuration ownership and modes configurable while -preserving its current generic standalone behavior. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- `ansible-role-scriptorium/defaults/main.yml` -- `ansible-role-scriptorium/meta/argument_specs.yml` -- `ansible-role-scriptorium/tasks/main.yml` -- `ansible-role-scriptorium/tests/integration` -- `ansible-role-scriptorium/README.md` - -### Preconditions - -- Stages 1 and 2 are committed and validated. -- `ansible-role-scriptorium` is clean at the stated starting commit. -- Its existing integration suite passes before modification. - -### Owning Repository - -`ansible-role-scriptorium` - -### Required Changes - -1. Add `scriptorium_config_owner: root`, `scriptorium_config_group: root`, - `scriptorium_config_directory_mode: "0755"`, and - `scriptorium_config_file_mode: "0644"` as required, defaulted public - variables. -2. Add the matching string argument-specification entries. -3. Leave source and binary parent policy unchanged. Apply the new variables - directly to the operation that creates - `scriptorium_config_path | dirname`. -4. Replace the template task's fixed configuration metadata with the new - variables. Do not add a second convergence pass or preliminary inspection. -5. Document the generic interface and standalone defaults. Do not add Narratio - or D&D assumptions to this reusable role. -6. Keep the existing native profile-inspection and clean-repeat suite focused; - do not add file metadata checks. - -### Validation - -Run from `ansible-role-scriptorium`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: syntax and lint pass, representative native Scriptorium -inspection remains successful, the immediate repeats report `changed=0` and -`failed=0`, and only intended Scriptorium role files are modified. - -### Completion Criteria - -- Defaults, argument specification, tasks, and README expose one coherent - generic ownership interface. -- Standalone configuration remains `root:root`, directory mode `0755`, and - file mode `0644` by default. -- No new task or test merely re-proves trusted module behavior. - -### Commit - -Commit intent: `Make Scriptorium configuration ownership configurable` - -## Stage 4: Expose Narratio Configuration Ownership - -### Objective - -Separate Narratio's generic configuration-file policy from its runtime identity -and writable-root policy, preserving the current standalone defaults while -allowing a composing role to make configuration service-owned. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- `ansible-role-narratio/defaults/main.yml` -- `ansible-role-narratio/meta/argument_specs.yml` -- `ansible-role-narratio/tasks/main.yml` -- `ansible-role-narratio/tests/integration` -- `ansible-role-narratio/README.md` - -### Preconditions - -- Stages 1 through 3 are committed and validated. -- `ansible-role-narratio` is clean at the stated starting commit. -- Its existing integration suite passes before modification. - -### Owning Repository - -`ansible-role-narratio` - -### Required Changes - -1. Add `narratio_config_owner: root`, - `narratio_config_group: "{{ narratio_group }}"`, - `narratio_config_directory_mode: "0750"`, and - `narratio_config_file_mode: "0640"` as required, defaulted public inputs. - The group default deliberately follows the role's existing configurable - service group. -2. Add matching string argument-specification entries. -3. Use the four variables directly in the existing configuration-directory - and pipeline-template tasks. -4. Do not change creation of `narratio_user` or `narratio_group`, the three - mutable Narratio roots, the campaign registry root, source checkout, binary, - application fields, or task ordering. -5. Document the new interface and its standalone relationship to - `narratio_group`. Make clear that configuration ownership is independent of - writable runtime-root ownership. -6. Retain the existing native validation, representative configuration, and - immediate clean-repeat behavior. Do not add metadata assertions. - -### Validation - -Run from `ansible-role-narratio`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: syntax and lint pass, Narratio natively validates baseline and -representative configurations as its service account, all immediate repeats -are clean, and only intended Narratio role files are modified. - -### Completion Criteria - -- The configuration interface defaults to the prior standalone result: - `root:{{ narratio_group }}`, directory mode `0750`, and file mode `0640`. -- Runtime identity and mutable-root behavior remain unchanged. -- Configuration directory and template tasks are the sole production owners of - their respective metadata. - -### Commit - -Commit intent: `Make Narratio configuration ownership configurable` - -## Stage 5: Apply the Suite Configuration Ownership Policy - -### Objective - -Make Narratio establish the selected runtime identity first, then use the four -standalone interfaces to converge every application configuration and -pipeline-owned Narratio fragment under the D&D suite policy. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- the four standalone-role commits produced by Stages 1 through 4 -- `ansible-role-dnd-pipeline/defaults/main.yml` -- `ansible-role-dnd-pipeline/meta/argument_specs.yml` -- `ansible-role-dnd-pipeline/meta/main.yml` -- `ansible-role-dnd-pipeline/requirements.yml` -- `ansible-role-dnd-pipeline/tasks/main.yml` -- `ansible-role-dnd-pipeline/tests/integration` - -### Preconditions - -- Stages 1 through 4 are committed, validated, and otherwise clean. -- Each new standalone-role commit is reachable from its canonical origin. Stop - and report the hashes if a fresh Git or Galaxy fetch cannot resolve them. -- `ansible-role-dnd-pipeline` is clean at its stated starting commit or an - expected reviewed descendant. -- The existing pipeline integration suite passes before modification. - -### Owning Repository - -`ansible-role-dnd-pipeline` - -### Required Changes - -1. Add the required suite defaults and matching argument-specification entries: - `dnd_pipeline_runtime_user: narratio`, - `dnd_pipeline_runtime_group: narratio`, - `dnd_pipeline_config_directory_mode: "0755"`, and - `dnd_pipeline_config_file_mode: "0644"`. -2. Reorder `meta/main.yml` so `rakestraw.narratio` is the first dependency and - therefore creates the selected service account and group before any other - configuration-bearing role uses them. Preserve the remaining dependency - roles and all existing application wiring. -3. Pass the runtime user and group to `narratio_user` and `narratio_group`. - Pass the runtime user, runtime group, suite directory mode, and suite file - mode to the four new `narratio_config_*` variables. -4. Pass the same four suite values to the corresponding `audita_config_*`, - `notarius_config_*`, and `scriptorium_config_*` variables. Do not apply a - corrective ownership task after a dependency completes. -5. Update `requirements.yml` to pin the Audita, Notarius, Scriptorium, and - Narratio dependencies to the exact commits produced by Stages 1 through 4. - Keep canonical Git URLs and immutable commit hashes; do not use branches or - local-path substitutes. -6. Apply the selected runtime group to the pipeline-managed prompt-library - root. Apply the suite configuration owner, group, directory mode, and file - mode directly to the existing Narratio fragment directory and template - loops. Campaign and prompt Git content remains root-managed and - world-readable. -7. Do not add ACL or package tasks in this stage. Do not change application - versions, native configuration fields, assets, Notarius enablement, or the - Feature 0010 cache path. - -### Validation - -Run from `ansible-role-dnd-pipeline`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: a fresh isolated role installation resolves the four new -immutable commits; Narratio runs first without missing-identity failures; all -five applications and the assembled Narratio configuration remain natively -usable; the immediate baseline repeat reports `changed=0` and `failed=0`; and -only intended pipeline-role files are modified. - -### Completion Criteria - -- One suite-level identity and configuration-mode policy is passed through the - four generic role interfaces. -- All pipeline-owned Narratio configuration uses the same policy directly. -- Dependency order and immutable pins refer to the completed standalone stages. -- No follow-up task fights a dependency role's ownership or mode state. -- Existing pipeline behavior remains valid and immediately idempotent. - -### Commit - -Commit intent: `Apply shared configuration ownership to the D&D pipeline` - -## Stage 6: Establish Shared Writable-Root ACLs - -### Objective - -Apply the settled setgid and inherited-access policy to the three existing -Narratio writable roots using direct package and ACL convergence. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- `ansible-role-narratio/tasks/main.yml` -- `ansible-role-dnd-pipeline/collections/requirements.yml` -- `ansible-role-dnd-pipeline/tasks/main.yml` -- the official `ansible.posix.acl` 2.2.0 module documentation - -### Preconditions - -- Stage 5 is committed and validated. -- The pipeline role creates the runtime identity and Narratio creates - `/var/lib/narratio`, `/var/spool/narratio`, and `/var/cache/narratio` as the - selected user and group with mode `2775` before pipeline tasks run. -- `ansible.posix` 2.2.0 and Ubuntu's `acl` package remain available. - -### Owning Repository - -`ansible-role-dnd-pipeline` - -### Required Changes - -1. Add `ansible.posix` version `2.2.0` to - `collections/requirements.yml`, retaining the existing - `community.general` pin. -2. Add one direct privileged `ansible.builtin.apt` task for package `acl` with - `state: present`, `update_cache: true`, and `cache_valid_time: 3600`. -3. Use the smallest clear `ansible.posix.acl` loop or loops to manage access - and default entries on exactly `/var/lib/narratio`, - `/var/spool/narratio`, and `/var/cache/narratio`. For each root, converge - entries equivalent to `u::rwx`, `g::rwx`, `o::r-x`, and `m::rwx` for both - access and default ACLs. -4. Apply `become: true` to the package and ACL tasks. Keep ACL convergence - non-recursive: manage the roots and inheritance for new descendants, not - pre-existing descendants. -5. Do not add `stat`, `getfacl`, shell commands, handlers, ACL facts, manual - change detection, wrapper umasks, or fallback permission repair to - production tasks. Do not create `/var/cache/notarius` or `secrets/`. - -### Validation - -Run from `ansible-role-dnd-pipeline`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: the private collection bootstrap installs both pinned -collections; syntax and production-profile lint pass; ACL convergence succeeds -on all three existing roots; all existing native checks pass; and the -immediate repeat reports `changed=0` and `failed=0`. - -### Completion Criteria - -- The collection and host-package requirements are explicit and pinned where - applicable. -- Each shared root retains mode `2775` from the Narratio role and has the - selected access and default ACL entries. -- Production logic uses only direct package and ACL state management and does - not recursively mutate existing content. -- Existing pipeline validation and clean convergence remain green. - -### Commit - -Commit intent: `Manage shared pipeline access with ACLs` - -## Stage 7: Exercise Cross-Identity Pipeline Access - -### Objective - -Prove the suite's user-visible read and shared-write contract with one isolated -human-operator fixture while retaining the existing focused integration suite. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- `ansible-role-dnd-pipeline/tests/integration` -- `ansible-role-dnd-pipeline/tests/converge.yml` -- `ansible-role-dnd-pipeline/tasks/main.yml` - -### Preconditions - -- Stages 1 through 6 are committed and validated. -- The integration driver can create and remove one uniquely named test-only - local account through privilege escalation without touching an existing - human account. -- The service account, selected group, managed configuration, and three shared - roots exist through ordinary baseline convergence. - -### Owning Repository - -`ansible-role-dnd-pipeline` - -### Required Changes - -1. Retain the driver's isolated role and collection installation, immutable - asset inputs, native application checks, explicit configurable-behavior - cases, cleanup boundary, and immediate clean repeats. -2. Create one uniquely named test-only operator account after baseline - convergence and add only that account to the selected runtime group. This - is integration fixture setup, not production role behavior. Ensure cleanup - removes only the fixture account and its explicitly named test content on - both success and failure; never modify a real operator account. -3. As the test operator, run one existing native Narratio configuration - validation or inspection command against the same managed configuration and - campaign used by the service account. This proves the supported human - invocation boundary without duplicating every application check. -4. Under one uniquely named child of a shared Narratio root, create ordinary - content as the service account with a restrictive ordinary umask and modify - or read it as the test operator. Then create representative content as the - operator and modify or read it as the service account. Use actual access as - the assertion; do not parse mode bits or `getfacl` output. -5. Use one existing unprivileged account outside the shared group to read a - representative non-secret configuration or test artifact, establishing the - deliberate world-readable boundary. Do not grant that account write access - or add it to the shared group. -6. Keep one immediate identical role repeat after the new policy is active and - require `changed=0` and `failed=0`. Test-created descendants must not cause - recursive role changes. -7. Do not test every root, every application configuration, every ACL entry, or - Ansible's file, user, group, package, template, or ACL implementation. Do - not create credentials or a secrets fixture. - -### Validation - -Run from `ansible-role-dnd-pipeline`: - -```text -tests/integration -git diff --check -git status --short -``` - -Expected result: all prior checks remain green; the service account and one -existing-group-member fixture use the same Narratio configuration; both -identities exchange representative shared-root content despite a restrictive -ordinary umask; an account outside the group can read but is never granted -write access; cleanup removes only test-owned state; and the immediate role -repeat reports `changed=0` and `failed=0`. - -### Completion Criteria - -- Tests observe the supported operating contract rather than filesystem - metadata or task implementation. -- The human-user fixture is isolated, uniquely named, and reliably cleaned up. -- One representative root and configuration path provide sufficient coverage; - no exhaustive access matrix is added. -- The complete integration entry point remains the sole supported test command - and is immediately idempotent. - -### Commit - -Commit intent: `Test shared pipeline access across users` - -## Stage 8: Document the Shared Execution Model - -### Objective - -Document the standalone ownership interfaces and the pipeline's opinionated -service identity, readable configuration, shared writable state, operator -prerequisites, and secret boundary. - -### Required Policy Review - -Before beginning this stage, read: - -- `AGENTS.md` -- `docs/orientation.md` -- `docs/conventions.md` -- `docs/ansible.md` -- `docs/testing.md` -- `docs/roadmap/features/0009-shared-pipeline-filesystem-and-execution.md` -- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md` -- the four standalone-role READMEs updated in Stages 1 through 4 -- `ansible-role-dnd-pipeline/README.md` - -### Preconditions - -- Stages 1 through 7 are committed and validated. -- All final variable names, dependency pins, task behavior, and integration - commands are stable and match the feature roadmap. - -### Owning Repository - -`ansible-role-dnd-pipeline` - -### Required Changes - -1. Add the four suite variables to the pipeline README and explain that they - are deliberate D&D policy passed to the standalone roles rather than - standalone defaults. -2. Document dependency order: Narratio establishes the runtime user and group - before the remaining configuration-bearing dependencies run. -3. Document `narratio:narratio`, directory mode `0755`, and file mode `0644` - for application configuration, including the pipeline-owned Narratio - fragments. Explain that this ordinary configuration is Ansible-managed and - intentionally world-readable, not operator-edited in place. -4. Document the three shared roots, their `2775` setgid mode, inherited ACL - policy, and supported invocation as either the service account or a human - account already belonging to the runtime group. Use the term **setgid**, not - sticky bit. -5. State clearly that the production role does not select human users or manage - their group membership. Provide a concise consumer-side inventory or - operational example without embedding a particular human username. -6. Explain that configuration, transcripts, caches, generated artifacts, - campaign data, prompts, and logs are treated as non-secret D&D content. API - keys and credentials are deferred to the future restricted `secrets/` - subtree; do not imply that this feature creates it. -7. Update validation documentation to describe the representative native - operator check, actual shared-write exchange, world-readable check, and - immediate clean repeat without promising exhaustive permission testing. - -### Validation - -Run from `ansible-role-dnd-pipeline`: - -```text -tests/integration -git diff --check HEAD -git status --short -``` - -Expected result: the complete suite remains syntax-clean, lint-clean, natively -valid, cross-identity usable, and immediately idempotent; documentation matches -the implemented interface and paths; and no whitespace errors are reported. - -### Completion Criteria - -- Consumers can distinguish standalone defaults from suite overrides. -- The service-user and existing-group-member invocation paths, setgid/ACL - behavior, world-readable boundary, and deferred secrets boundary are clear. -- Documentation does not promise group-membership management, recursive - migration, Notarius v0.7.0 integration, or secret delivery. -- All five changed repositories remain valid after the documentation commit. - -### Commit - -Commit intent: `Document the shared pipeline execution model` - -## Final Validation and Handoff - -After Stage 8, run each owning repository's complete integration entry point: - -```text -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 -``` - -Then, from the workspace root, run: - -```text -git diff --check -./scripts/status -``` - -The final handoff must: - -- identify all eight implementation commit hashes and confirm every changed - repository has a clean working tree; -- confirm syntax and production-profile lint pass in all five changed roles; -- confirm every standalone role's native behavior and immediate clean repeat - pass; -- confirm the pipeline installs the exact immutable standalone commits, - applies the configuration and ACL policy, supports representative - cross-identity access, and immediately reports `changed=0` and `failed=0`; -- confirm no application source, asset, collection, Seriatim role, secret, - human operator account, or unrelated repository was modified; -- summarize any deviation, blocker, or deferred work, including whether - dependency publication required a coordination pause; -- report any production complexity beyond the planned public variables, - direct task substitutions, dependency wiring, one package task, and the - minimum clear ACL loop or loops, together with the acceptance criterion that - required it; and -- leave Feature 0009 `ready` or `in_progress` for independent review rather - than marking it `done`. - -## Progress Notes - -Stages 1 through 4 and the dependency-publication checkpoint are complete. -Resume at Stage 5. Continue recording only concise stage commit hashes and -blockers here; preserve detailed evidence in the stage commits and final -handoff. - -- [x] Stage 1 complete — `ansible-role-audita` commit `66ebea9`; full - integration, native validation, and clean repeats passed. No deviations. -- [x] Stage 2 complete — `ansible-role-notarius` commit `e9ae2dc`; full - integration, native validation, version selection, and clean repeats passed. - No deviations. -- [x] Stage 3 complete — `ansible-role-scriptorium` commit `8b4c86e`; full - integration, native profile inspection, and clean repeats passed. No - deviations. -- [x] Stage 4 complete — `ansible-role-narratio` commit `eeb1105`; full - integration, native validation, and clean repeats passed. No deviations. -- [x] Dependency publication checkpoint complete — the four Stage 1–4 commits - are available from their canonical `origin/main` branches at the exact - immutable revisions listed above. Stage 5 may begin. -- [x] Stage 5 complete — `ansible-role-dnd-pipeline` commit `901ae35`; full - isolated integration, immutable dependency installation, native validation, - and clean repeats passed. No deviations. -- [x] Stage 6 complete — `ansible-role-dnd-pipeline` commit `dddc5ee`; full - isolated integration, ACL convergence, native validation, and clean repeats - passed. No deviations. -- [x] Stage 7 complete — `ansible-role-dnd-pipeline` commit `f53da82`; full - isolated integration, cross-identity access, native validation, and clean - repeats passed. No deviations. -- [x] Stage 8 complete — `ansible-role-dnd-pipeline` commit `608d5be`; full - isolated integration, documentation validation, and clean repeats passed. - No deviations. +Select and approve the next unit of work before replacing this notice with a +new staged implementation plan. diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index e62434f..741f918 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -1,6 +1,6 @@ # Feature 0009 Remediation Review -Status: open +Status: resolved Reviewed implementation commits: @@ -8,164 +8,83 @@ Reviewed implementation commits: - `e9ae2dc Make Notarius configuration ownership configurable` - `8b4c86e Make Scriptorium configuration ownership configurable` - `eeb1105 Make Narratio configuration ownership configurable` +- `901ae35 Apply shared configuration ownership to the D&D pipeline` +- `dddc5ee Manage shared pipeline access with ACLs` +- `f53da82 Test shared pipeline access across users` +- `608d5be Document the shared pipeline execution model` ## Review Summary -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. +The production architecture and behavioral coverage implement Feature 0009 as +planned. The four standalone roles expose generic configuration ownership and +mode controls, and the pipeline selects its opinionated service-owned, +world-readable policy through those interfaces. Narratio establishes the +runtime identity first. The pipeline then installs ACL support and directly +converges access and default ACLs on the three existing shared roots. Focused +integration coverage exercises actual cross-identity configuration access and +bidirectional writes under a restrictive umask while preserving immediate clean +convergence. -Feature 0009 as a whole is not implemented. The pipeline repository remains at -pre-feature commit `3e253d7`; Stages 5 through 8 have not been executed. The -publication blocker encountered after Stage 4 has now been cleared: all four -standalone commits are available from their canonical origins. The following -findings therefore describe the remaining target architecture rather than -defects in the completed standalone commits. +No production code or test-suite remediation is required. One small consumer +documentation inconsistency remains. -## Finding 1: The Pipeline Does Not Select the Shared Configuration Policy +## Finding 1: Operator Support Is Documented Inconsistently -Severity: high +Severity: low -`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. +`ansible-role-dnd-pipeline/README.md:201-217` first lists "operator access" as +deferred, then correctly states that invocation by an existing member of the +selected runtime group is supported. The likely deferred concern is operator +selection and group-membership management, not operator access itself. -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. +The adjacent YAML fragment defines an otherwise unexplained +`operator_group_members` variable but shows no consumer task or role that uses +it. As written, copying the example does not manage any membership and may lead +a reader to believe that the pipeline role consumes that variable. ### Required Remediation -- Use the four published, immutable standalone-role commits recorded above; - do not replace their 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. +- Replace "operator access" in the deferred list with the precise deferred + behavior: operator selection and group-membership management. +- Replace the inert variable fragment with a concise, complete consumer-side + example that actually adds a selected account to the runtime group, or omit + the example and state the prerequisite directly. +- Keep human account and membership management outside the production pipeline + role. -## Finding 2: Shared Writable-Root ACL Convergence Is Absent +## Resolution -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/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 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 - -- 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 4: Pipeline Consumer Documentation Is Stale - -Severity: medium - -`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 - -- 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. +Resolved in pipeline-role commit `b15fe8d`. The deferred-work summary now +names operator selection and group-membership management rather than operator +access. The shared-filesystem section retains existing-group-member invocation +as supported behavior and provides a complete consumer-owned +`ansible.builtin.user` example that adds a selected account to the runtime +group. No production role behavior changed. ## Required Validation -After remediation, run the complete integration entry point in each changed -role: - -```text -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 -``` - -Then run from the workspace root: +After the documentation correction, run: ```text +cd ansible-role-dnd-pipeline && tests/integration git diff --check -./scripts/status ``` -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. +The expected result remains successful native configuration checks, +representative cross-identity access, and immediate repeats with `changed=0` +and `failed=0`. ## Review Validation Evidence -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. +The independent review inspected the complete diffs for all eight stage +commits and confirmed that every dependency pin resolves to the intended +standalone-role commit. `git diff --check` passed across all five changed role +repositories. The complete pipeline `tests/integration` entry point passed its +isolated dependency installation, syntax check, production-profile lint, +native application checks, cross-identity access exercise, configurable +profile and version cases, and immediate clean repeats. All repositories were +clean before this review document was revised. -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. -After review, each standalone commit was pushed to its canonical `origin/main` -branch and the local and remote-tracking revisions were confirmed identical. +After remediation, the complete pipeline integration entry point and +`git diff --check` passed again. The test fixture was removed and the baseline +Seriatim version and pipeline configuration were restored during cleanup. diff --git a/docs/status.md b/docs/status.md index c7a3903..b08b73b 100644 --- a/docs/status.md +++ b/docs/status.md @@ -1,10 +1,10 @@ # Workspace Status -Last updated: 2026-09-14 +Last updated: 2026-09-15 Current milestone: M1-03 suite-level pipeline role -Current focus: Independently review the completed Feature 0009 implementation. +Current focus: Select the next unit of work. | ID | Deliverable | Owner | State | Evidence or next step | | --- | --- | --- | --- | --- | @@ -15,7 +15,7 @@ Current focus: Independently review the completed Feature 0009 implementation. | 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 | done | Feature 0003 roadmap fixes the Notarius configuration interface | | M1-02 | Standalone application roles | role repositories | done | All five standalone roles implemented and independently reviewed | -| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | in_progress | Feature 0009 implementation and final validation are complete; await independent review | +| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | in_progress | Feature 0009 is complete; select the next suite-policy feature | | 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 | @@ -25,8 +25,8 @@ Current focus: Independently review the completed Feature 0009 implementation. | F0006 | Establish pipeline-role composition | ansible-role-dnd-pipeline | done | Implemented and validated through remediation commit `4ea4358` | | F0007 | Deploy D&D campaigns and prompt assets | ansible-role-dnd-pipeline, campaigns, and narratio-prompts | done | Implemented and validated through remediation commit `7572fa3` | | F0008 | Define opinionated D&D processing configuration | ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `3e253d7` | -| F0009 | Establish shared pipeline filesystem and execution | configuration-bearing application roles and ansible-role-dnd-pipeline | in_progress | All eight stage commits and final role integration runs passed; see `docs/roadmap/implementation.md` | -| F0010 | Integrate D&D Notarius extraction | ansible-role-notarius and ansible-role-dnd-pipeline | proposed | Depends on Feature 0009; review `docs/roadmap/features/0010-dnd-notarius-extraction-integration.md` | +| F0009 | Establish shared pipeline filesystem and execution | configuration-bearing application roles and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `b15fe8d` | +| F0010 | Integrate D&D Notarius extraction | ansible-role-notarius and ansible-role-dnd-pipeline | proposed | Feature 0009 dependency is complete; review the roadmap before selection | | A0001 | Audit completed standalone-role test suites | workspace and standalone roles | done | Findings recorded in `docs/roadmap/test-suite-audit-findings.md` | | R0001 | Simplify completed standalone-role test suites | workspace and standalone roles | done | Role commits `e08c63c`, `d2d0b9d`, and `cfecf37` passed implementation and independent review |