# Implementation Plan 0014: Enroll Existing Pipeline Operators Status: ready Target executor: GPT-5.6-Terra Feature roadmap: `docs/roadmap/features/0014-existing-pipeline-operator-enrollment.md` Active plan location: `docs/roadmap/implementation.md` ## Objective Add one empty-by-default pipeline interface that enrolls explicitly selected existing human accounts in the suite's runtime group. Implement the behavior with one account-existence lookup and one additive membership task, adapt the existing operator integration scenario, and import the reviewed result into the collection from public Gitea. The Feature 0014 roadmap remains authoritative for scope, rationale, target state, and acceptance criteria. This plan does not authorize human-account creation or removal, exact-list reconciliation, filesystem-policy changes, or a new release. ## 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 and report unexpected worktree changes or branch divergence rather than overwriting them. - Do not make unresolved product or architecture decisions during execution; stop and report the decision required. - Keep the production behavior to the roadmap's exact direct task flow: one `ansible.builtin.getent` loop followed by one `ansible.builtin.user` loop. - Do not add an assertion, registered fact, handler, command, shell operation, explicit empty-list condition, membership comparison, post-change query, sidecar state, or account abstraction. - Trust `getent` to fail for a missing key and `user` to converge additive membership. Do not reproduce either module's checks. - Test the public behavior by adapting the existing temporary-operator scenario. Do not add a missing-user test, inspect `/etc/passwd` or `/etc/group`, assert task results, or duplicate the detailed test in the collection. - Run each stage's validation before committing it. Do not proceed after a validation failure. - Commit each completed stage with the stated plain-English intent. Push the authoritative pipeline commit before importing it into the collection. - Use only the public Gitea pipeline URL for the subtree update; do not import from the local sibling repository. ## Starting State and Preconditions - Features 0009, 0011, 0012, and 0013 are complete. - This roadmap and implementation plan have been reviewed and committed in the workspace repository before execution begins. - The completed Feature 0013 closeout commits `eda361f` in the workspace and `5e695f3` in the collection are pushed to their respective `origin/main` branches before implementation begins. Preserve the Git-generated subtree squash commit that accompanies `5e695f3`. - `ansible-role-dnd-pipeline` starts clean on `main` at `78afffe`, equal to `origin/main`. - `ansible-collection-dnd` starts clean on `main` at `5e695f3`, equal to `origin/main` after the prerequisite push. - The workspace `.venv` supplies the tested `ansible-playbook`, `ansible-galaxy`, and `ansible-lint` commands used by the repository test drivers. - The local host remains the approved Ubuntu 26.04 proxy, and passwordless test-time sudo is available for the existing integration fixtures. - Git credentials can push the pipeline and collection commits to their public Gitea origins. ## Repository Scope - `ansible-role-dnd-pipeline` owns the variable, argument specification, account lookup, additive enrollment task, README, and detailed integration behavior. - `ansible-collection-dnd` receives the reviewed pipeline commit only through its established squashed subtree and validates the assembled artifact. - `ansible-workspace-dnd` records implementation progress and the review handoff after the two implementation repositories are complete. - All standalone application-role repositories, application source repositories, asset repositories, and `rakestraw-ansible` are out of scope and must remain unchanged. ## Stage 1: Implement Existing-Operator Enrollment ### Objective Give the standalone pipeline role its minimal public interface for enrolling existing human accounts and prove the behavior through the existing operator integration scenario. ### Required Policy Review Before beginning this stage, read: - `AGENTS.md` - `docs/orientation.md` - `docs/conventions.md` - `docs/ansible.md` - `docs/testing.md` - `docs/planning.md` - `docs/roadmap/features/0014-existing-pipeline-operator-enrollment.md` ### Preconditions - The workspace planning commit is present. - `ansible-role-dnd-pipeline` is clean at `78afffe` on `main`, is not behind or diverged from `origin/main`, and contains no unrelated changes. - Its Narratio dependency still creates the selected runtime group before the pipeline role's ordinary tasks execute. - The existing integration driver still contains the temporary operator and representative group-access scenario described by the roadmap. ### Owning Repository `ansible-role-dnd-pipeline` ### Required Changes 1. Add `dnd_pipeline_operator_users: []` beside the existing runtime identity defaults in `defaults/main.yml`. 2. Add the matching `meta/argument_specs.yml` entry with `type: list`, `elements: str`, and the same required/default-backed convention used by the role's other public variables. 3. Add one unprivileged `ansible.builtin.getent` task near the beginning of `tasks/main.yml`. Loop directly over `dnd_pipeline_operator_users`, use the `passwd` database and each username as `key`, and rely on the module's default missing-key failure. Do not register its result or add a separate assertion. 4. Immediately follow it with one `become: true` `ansible.builtin.user` task over the same list. Set `name` to the selected account, `groups` to `dnd_pipeline_runtime_group`, `append: true`, and `state: present`. Do not set or manage any other account property. 5. Revise the README variable reference and shared-execution section. Replace the consumer-owned membership example and deferred wording with the new interface, existing-account prerequisite, additive non-removal behavior, authorization consequence, and new-login-session caveat. 6. Adapt `tests/integration` rather than adding another scenario. Create its temporary operator before the initial role application without membership in the runtime group, pass that username through `dnd_pipeline_operator_users` for the baseline and repeated applications, and retain the existing native configuration, secret-boundary, and shared cache exercises under that identity. Reorder cleanup as necessary so any final baseline convergence occurs while the selected fixture account still exists, then remove the fixture account. 7. Retain the existing clean-repeat assertion. Do not add a negative missing-user case or assertions about module internals, task traces, the current default value, or raw account database entries. 8. Run the complete existing repository validation, commit the result, push `main` to the public pipeline origin, and record the full pushed commit for Stage 2. ### Validation Run from the workspace root: ```text (cd ansible-role-dnd-pipeline && tests/integration && git diff --check) ``` Expected result: syntax and production-profile lint pass; the temporary existing account is enrolled through the public role variable and completes the existing representative operator-access scenario; native application checks pass; the immediate identical role application reports `changed=0` and `failed=0`; and no credential value appears in test output. ### Completion Criteria - The public interface, argument specification, two direct tasks, and README implement exactly the roadmap contract. - The existing operator scenario uses the role interface rather than fixture group enrollment. - The full standalone integration suite and `git diff --check` pass. - The role repository is clean after a plain-English commit. - The exact commit is present on public `origin/main` and its full hash is available for the collection import. ### Commit Commit intent: `Add optional pipeline operator enrollment` ## Stage 2: Import the Reviewed Pipeline Change ### Objective Expose the reviewed operator interface through `rakestraw.dnd.pipeline` while preserving the authoritative-standalone-repository and collection-artifact boundaries. ### Required Policy Review Before beginning this stage, read: - `AGENTS.md` - `docs/orientation.md` - `docs/conventions.md` - `docs/ansible.md` - `docs/testing.md` - `docs/planning.md` - `docs/roadmap/features/0014-existing-pipeline-operator-enrollment.md` - `ansible-collection-dnd/README.md` ### Preconditions - Stage 1 is complete and its exact commit is publicly reachable from `https://gitea.maximumdirect.net/eric/ansible-role-dnd-pipeline.git`. - `ansible-collection-dnd` is clean at `5e695f3` on `main`, is not behind or diverged from `origin/main`, and contains no unrelated changes. - The collection's current `roles/pipeline` subtree still corresponds to the authoritative pipeline history through `78afffe`. ### Owning Repository `ansible-collection-dnd` ### Required Changes 1. Set a shell variable to the full pushed Stage 1 commit hash and run the documented remote-only update from the collection repository: ```text pipeline_revision= git subtree pull --prefix=roles/pipeline \ https://gitea.maximumdirect.net/eric/ansible-role-dnd-pipeline.git \ "$pipeline_revision" --squash -m "Import pipeline operator enrollment" ``` 2. Do not edit role behavior directly beneath `roles/pipeline`. The subtree import should carry the new default, argument specification, tasks, README, and standalone tests faithfully. 3. Do not change `galaxy.yml`, dependency manifests, collection-level tests, or release documentation. No dependency or published version changes in this feature, and the detailed behavior remains covered by Stage 1. 4. Run the existing collection integration suite against the built and installed artifact. Commit no additional files after the subtree command unless validation exposes a genuine collection-boundary issue within this feature's scope. 5. Push the resulting collection history to `origin/main` and record the resulting merge commit and Git-generated squashed subtree commit. ### Validation Run from the workspace root: ```text (cd ansible-collection-dnd && tests/integration && git diff --check) ``` Expected result: the collection builds; the archive contains the updated pipeline role while retaining its development-file exclusions; isolated dependency and artifact installation succeeds; the FQCN resolves; native representative application checks pass; and the immediate repeat reports `changed=0` and `failed=0`. ### Completion Criteria - Git history records a squashed subtree import from the exact public Stage 1 commit with the stated plain-English merge message. - No pipeline behavior was authored directly in the collection. - The existing collection suite and `git diff --check` pass without an unnecessary duplicate operator test. - The collection is clean and its new history is present on `origin/main`. ### Commit Commit intent: `Import pipeline operator enrollment` The subtree command creates the stage's merge commit and its generated squash commit; do not add an empty or redundant manual commit. ## Stage 3: Record the Implementation Handoff ### Objective Record the completed implementation evidence without marking Feature 0014 done before independent review. ### Required Policy Review Before beginning this stage, read: - `AGENTS.md` - `docs/orientation.md` - `docs/conventions.md` - `docs/planning.md` - `docs/roadmap/features/0014-existing-pipeline-operator-enrollment.md` ### Preconditions - Stages 1 and 2 are complete, committed, pushed, and validated. - Their full commit hashes and validation results are available. - The workspace repository is clean apart from the expected progress-record edits for this stage and is not behind or diverged from `origin/main`. ### Owning Repository `ansible-workspace-dnd` ### Required Changes 1. Change Feature 0014's roadmap status and status-table state to `in_progress`, indicating implementation is complete but independent review remains outstanding. 2. Update the workspace current focus and Feature 0014 evidence with the exact pipeline and collection commit hashes and the validation completed. 3. Replace this plan's Progress Notes with a concise record of the three stage states and their commits. Do not copy command logs into the repository. 4. Do not mark the feature `done`, remove the active plan, or create `docs/roadmap/remediation.md`; those are review and closeout decisions. 5. Commit the workspace handoff record with the stated plain-English message. ### Validation Run from the workspace root: ```text ./scripts/status git diff --check ``` Expected result: every repository is clean; the pipeline and collection are not ahead of or behind their origins; only the workspace handoff commit may be ahead of `origin/main`; and the dashboard points to the exact implementation evidence while retaining independent review as the next step. ### Completion Criteria - Workspace status accurately identifies Feature 0014 as implemented and awaiting review. - The roadmap remains the durable target-state record and is not polluted with execution logs. - The active plan records concise implementation evidence and contains no false completion claim. - The workspace repository is clean after the handoff commit. ### Commit Commit intent: `Record pipeline operator enrollment implementation` ## Final Validation and Handoff - Confirm Stage 1's complete standalone integration result and Stage 2's complete collection integration result. - Run `./scripts/status` and confirm every repository is clean, with no unexpected branch divergence or untracked artifact. - Report the full pipeline, collection merge, collection subtree-squash, and workspace handoff commit hashes. - Summarize any deviation from this plan, unresolved finding, or added implementation complexity and identify the acceptance criterion that required it. - Do not mark Feature 0014 `done`; implementation results require independent review first. ## Progress Notes - Stage 1 complete: `ansible-role-dnd-pipeline` `c13f726a0a846180a1aa95d110b8bbc801edaae5` implements optional enrollment of existing operators; the complete standalone integration suite passed and the commit is public on `origin/main`. - Stage 2 complete: `ansible-collection-dnd` merge `c0b0ebd13e92199f3d94e138c6cc50d1ece5dadd` imports the exact public pipeline change through squash `d292297b6ad179e4664c01ad07cddaefff12f769`; the complete collection integration suite passed and the history is public on `origin/main`.