Files
ansible-workspace-dnd/docs/roadmap/implementation.md

33 KiB

Implementation Plan 0009: Shared Pipeline Filesystem and Execution

Status: ready

Target executor: GPT-5.6-Terra

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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

No implementation stages have begun. Record only concise stage commit hashes and blockers here during execution; preserve detailed evidence in the stage commits and final handoff.

  • Stage 1 complete — ansible-role-audita commit 66ebea9; full integration, native validation, and clean repeats passed. No deviations.
  • Stage 2 complete — ansible-role-notarius commit e9ae2dc; full integration, native validation, version selection, and clean repeats passed. No deviations.