Squashed 'roles/pipeline/' changes from 78afffe..c13f726

c13f726 Add optional pipeline operator enrollment

git-subtree-dir: roles/pipeline
git-subtree-split: c13f726a0a846180a1aa95d110b8bbc801edaae5
This commit is contained in:
2026-09-18 12:57:00 +00:00
parent f62445ad1e
commit d292297b6a
5 changed files with 43 additions and 18 deletions

View File

@@ -90,6 +90,7 @@ group before the remaining configuration-bearing dependencies run.
| --- | --- |
| `dnd_pipeline_runtime_user` | `narratio` |
| `dnd_pipeline_runtime_group` | `narratio` |
| `dnd_pipeline_operator_users` | `[]` |
| `dnd_pipeline_config_directory_mode` | `0755` |
| `dnd_pipeline_config_file_mode` | `0644` |
@@ -259,8 +260,8 @@ inspection shows enabled sources, inferred dependencies, and generated family
members; the diff shows the overlay's profile selections without modifying
managed files.
Storage and publishing, operator selection and group-membership management,
scheduling, and end-to-end external execution remain deferred.
Storage and publishing, scheduling, and end-to-end external execution remain
deferred.
### Shared execution filesystem
@@ -269,27 +270,30 @@ scheduling, and end-to-end external execution remain deferred.
`narratio:narratio` mode `2775` **setgid** directories. Their access and
default ACLs retain owner and group write access plus world read/traverse access
for newly created content. The pipeline may run as `narratio` or as a human
account already in the selected runtime group; the production role neither
selects people nor manages their group membership. For example, a consumer
play can manage its selected operator separately:
account in the selected runtime group. Consumers can enroll selected existing
human accounts through the role interface:
```yaml
- name: Add the selected operator to the pipeline group
become: true
ansible.builtin.user:
name: "{{ pipeline_operator }}"
groups:
- "{{ dnd_pipeline_runtime_group }}"
append: true
dnd_pipeline_operator_users:
- eric
- alice
```
Every selected account must already exist; the role does not create human
accounts or manage their identity and login policy. Enrollment adds the
selected runtime group without replacing other supplementary groups. Removing
or omitting a name later does not revoke membership. A newly enrolled operator
must begin a new login session before the operating system exposes the added
supplementary group to that session.
Configuration, transcripts, caches, generated artifacts, campaign data,
prompts, and logs are non-secret D&D content. Credentials use the restricted
`/usr/local/etc/narratio/secrets` subtree, owned by the selected runtime user
and group with mode `0750`; managed files use mode `0640`. Runtime-group
membership authorizes use of these shared credentials, while the subtree grants
no world access. Ordinary configuration remains world-readable and contains
only reference names.
membership, including enrollment through `dnd_pipeline_operator_users`,
authorizes use of these shared credentials, while the subtree grants no world
access. Ordinary configuration remains world-readable and contains only
reference names.
### Managed credentials

View File

@@ -9,6 +9,7 @@ dnd_pipeline_go_snap_channel: 1.26/stable
dnd_pipeline_go_binary: /snap/bin/go
dnd_pipeline_runtime_user: narratio
dnd_pipeline_runtime_group: narratio
dnd_pipeline_operator_users: []
dnd_pipeline_secrets: {}
dnd_pipeline_config_directory_mode: "0755"
dnd_pipeline_config_file_mode: "0644"

View File

@@ -43,6 +43,11 @@ argument_specs:
type: str
required: true
description: Shared group for suite-managed configuration.
dnd_pipeline_operator_users:
type: list
elements: str
required: true
description: Existing human accounts enrolled in the shared runtime group.
dnd_pipeline_secrets:
type: dict
required: true

View File

@@ -1,4 +1,19 @@
---
- name: Validate selected pipeline operator accounts
ansible.builtin.getent:
database: passwd
key: "{{ item }}"
loop: "{{ dnd_pipeline_operator_users }}"
- name: Enroll selected pipeline operators
become: true
ansible.builtin.user:
name: "{{ item }}"
groups: "{{ dnd_pipeline_runtime_group }}"
append: true
state: present
loop: "{{ dnd_pipeline_operator_users }}"
- name: Install ACL support
become: true
ansible.builtin.apt:

View File

@@ -31,6 +31,7 @@ baseline_args=(
-e "dnd_pipeline_prompt_library_repository_url=file://$prompt_library_repository"
-e "dnd_pipeline_prompt_library_revision=$prompt_library_revision"
-e "dnd_pipeline_prompt_library_root=$prompt_library_root"
-e "{\"dnd_pipeline_operator_users\":[\"$operator_user\"]}"
-e "{\"dnd_pipeline_secrets\":{\"AUDITA_LLM_API_KEY\":\"$synthetic_audita_api_key\",\"OPENROUTER_API_KEY\":\"$synthetic_notarius_api_key\"}}"
)
@@ -38,8 +39,8 @@ cleanup() {
exit_status=$?
trap - EXIT
/usr/bin/sudo /bin/rm -rf -- "$shared_fixture_root" || true
/usr/bin/sudo /usr/sbin/userdel --remove "$operator_user" 2>/dev/null || true
"$ansible_playbook" -i "$inventory" "${baseline_args[@]}" "$converge" >/dev/null 2>&1 || true
/usr/bin/sudo /usr/sbin/userdel --remove "$operator_user" 2>/dev/null || true
rm -rf -- "$test_tmp"
exit "$exit_status"
}
@@ -70,6 +71,7 @@ printf '%s\n' \
-p "$test_tmp/roles"
"$ansible_playbook" -i "$inventory" --syntax-check "$converge"
"$workspace_venv/bin/ansible-lint" --offline --profile production "$converge"
/usr/bin/sudo /usr/sbin/useradd --create-home --shell /usr/sbin/nologin "$operator_user"
baseline_log="$test_tmp/baseline.log"
run_converge "$baseline_log" "${baseline_args[@]}"
@@ -116,8 +118,6 @@ grep -Fq 'lane_id: item-registry' "$narratio_effective_config"
/usr/bin/sudo -u narratio /usr/local/bin/narratio config diff default testing \
--config /usr/local/etc/narratio/pipeline.yml --campaign centaurs | \
awk -F '\t' '$1 != "changed" || $2 !~ /\.profile_id$/ { invalid = 1 } END { exit invalid || NR == 0 }'
/usr/bin/sudo /usr/sbin/useradd --create-home --groups narratio \
--shell /usr/sbin/nologin "$operator_user"
/usr/bin/sudo -u "$operator_user" /usr/local/bin/narratio config validate \
--config /usr/local/etc/narratio/pipeline.yml --campaign centaurs
/usr/bin/sudo -u "$operator_user" /usr/local/bin/notarius config validate \