868 lines
34 KiB
Markdown
868 lines
34 KiB
Markdown
# 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`:
|
||
|
||
```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.
|