diff --git a/defaults/main.yml b/defaults/main.yml index b1e17b6..4e9d9f4 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,6 +1,6 @@ --- dnd_pipeline_audita_version: v0.9.1 -dnd_pipeline_narratio_version: v2.0.0 +dnd_pipeline_narratio_version: v2.1.0 dnd_pipeline_notarius_version: v0.7.0 dnd_pipeline_seriatim_version: v1.5.0 dnd_pipeline_scriptorium_version: v0.13.0 @@ -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_secrets: {} dnd_pipeline_config_directory_mode: "0755" dnd_pipeline_config_file_mode: "0644" dnd_pipeline_campaigns_repository_url: https://gitea.maximumdirect.net/eric/campaigns.git @@ -31,7 +32,7 @@ dnd_pipeline_audita_llm_proposal_timeout: 900s dnd_pipeline_audita_llm_proposal_max_retries: 3 dnd_pipeline_audita_llm_validation_base_url: https://inference.ai.rakestrawhome.com/v1 dnd_pipeline_audita_llm_validation_model: google/gemma-4-31b-it -dnd_pipeline_audita_llm_validation_api_key_env: AUDITA_VALIDATION_LLM_API_KEY +dnd_pipeline_audita_llm_validation_api_key_env: AUDITA_LLM_API_KEY dnd_pipeline_audita_llm_validation_timeout: 900s dnd_pipeline_audita_llm_validation_max_retries: 3 dnd_pipeline_audita_concurrency_total_llm: 4 @@ -214,6 +215,8 @@ dnd_pipeline_narratio_trim_bounds_prompt_id: dnd.session_bounds dnd_pipeline_narratio_trim_bounds_transcript_input_name: transcript dnd_pipeline_narratio_trim_bounds_output_path: artifacts/session_bounds.json dnd_pipeline_narratio_notarius_pipeline_id: dnd-session +dnd_pipeline_narratio_notarius_llm_api_key: OPENROUTER_API_KEY +dnd_pipeline_narratio_notarius_resume: true dnd_pipeline_narratio_notarius_references: party: narratio.input.party players: narratio.input.players diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml index cf550cb..52f7506 100644 --- a/meta/argument_specs.yml +++ b/meta/argument_specs.yml @@ -43,6 +43,10 @@ argument_specs: type: str required: true description: Shared group for suite-managed configuration. + dnd_pipeline_secrets: + type: dict + required: true + description: Explicit credential-file names and values managed beneath Narratio's secrets directory. dnd_pipeline_config_directory_mode: type: str required: true @@ -248,6 +252,14 @@ argument_specs: type: str required: true description: Notarius pipeline selected by Narratio. + dnd_pipeline_narratio_notarius_llm_api_key: + type: str + required: true + description: Environment-variable name forwarded by Narratio to Notarius. + dnd_pipeline_narratio_notarius_resume: + type: bool + required: true + description: Whether ordinary Narratio extraction requests Notarius checkpoint reuse. dnd_pipeline_narratio_notarius_references: type: dict required: true diff --git a/meta/main.yml b/meta/main.yml index 4a99970..d0b175d 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -42,11 +42,14 @@ dependencies: narratio_seriatim_binary: /usr/local/bin/seriatim narratio_audita_binary: /usr/local/bin/audita narratio_audita_config_path: /usr/local/etc/audita/config.yml + narratio_audita_llm_api_key: "{{ dnd_pipeline_audita_llm_proposal_api_key_env }}" narratio_notarius_binary: /usr/local/bin/notarius narratio_notarius_config_path: /usr/local/etc/notarius/config.yml narratio_notarius_enabled: true narratio_notarius_pipeline_id: "{{ dnd_pipeline_narratio_notarius_pipeline_id }}" narratio_notarius_working_directory: /usr/local/etc/notarius + narratio_notarius_llm_api_key: "{{ dnd_pipeline_narratio_notarius_llm_api_key }}" + narratio_notarius_resume: "{{ dnd_pipeline_narratio_notarius_resume }}" narratio_notarius_references: "{{ dnd_pipeline_narratio_notarius_references }}" narratio_notarius_outputs: "{{ dnd_pipeline_narratio_notarius_outputs }}" narratio_scriptorium_binary: /usr/local/bin/scriptorium diff --git a/requirements.yml b/requirements.yml index ecaa32d..bb8af90 100644 --- a/requirements.yml +++ b/requirements.yml @@ -19,4 +19,4 @@ roles: - name: rakestraw.narratio src: https://gitea.maximumdirect.net/eric/ansible-role-narratio.git scm: git - version: eeb1105590e638c1f46b42c98a5dbbce4ddeea86 + version: 292d8669e7aad5cfe80b0c469d22b6177e8cf0f1 diff --git a/tasks/main.yml b/tasks/main.yml index 6c5ab6e..6e89cb6 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,6 +7,51 @@ update_cache: true cache_valid_time: 3600 +- name: Validate managed Narratio credential entries + ansible.builtin.assert: + that: + - item.key is string + - item.key is match('^[A-Za-z_][A-Za-z0-9_]*$') + - item.value is none or (item.value is string and item.value | length > 0) + loop: "{{ dnd_pipeline_secrets | dict2items }}" + loop_control: + label: "{{ item.key }}" + no_log: true + +- name: Create the Narratio secrets directory + become: true + ansible.builtin.file: + path: /usr/local/etc/narratio/secrets + state: directory + owner: "{{ dnd_pipeline_runtime_user }}" + group: "{{ dnd_pipeline_runtime_group }}" + mode: "0750" + +- name: Converge managed Narratio credentials + become: true + ansible.builtin.copy: + content: "{{ item.value }}" + dest: "/usr/local/etc/narratio/secrets/{{ item.key }}" + owner: "{{ dnd_pipeline_runtime_user }}" + group: "{{ dnd_pipeline_runtime_group }}" + mode: "0640" + loop: "{{ dnd_pipeline_secrets | dict2items }}" + loop_control: + label: "{{ item.key }}" + when: item.value is not none + no_log: true + +- name: Remove explicitly unmanaged Narratio credentials + become: true + ansible.builtin.file: + path: "/usr/local/etc/narratio/secrets/{{ item.key }}" + state: absent + loop: "{{ dnd_pipeline_secrets | dict2items }}" + loop_control: + label: "{{ item.key }}" + when: item.value is none + no_log: true + - name: Create the Notarius cache root become: true ansible.builtin.file: diff --git a/tests/integration b/tests/integration index ed216cd..f7cc9de 100755 --- a/tests/integration +++ b/tests/integration @@ -22,6 +22,8 @@ operator_user="dnd_f0009_${$}" shared_fixture_root="/var/cache/notarius/${operator_user}" service_fixture_file="$shared_fixture_root/service.txt" operator_fixture_file="$shared_fixture_root/operator.txt" +synthetic_audita_api_key='audita-pipeline-synthetic-value' +synthetic_notarius_api_key='notarius-pipeline-synthetic-value' baseline_args=( -e 'dnd_pipeline_whisperx_transcribe_url=http://127.0.0.1:8000/transcribe' -e "dnd_pipeline_campaigns_repository_url=file://$campaigns_repository" @@ -29,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_secrets\":{\"AUDITA_LLM_API_KEY\":\"$synthetic_audita_api_key\",\"OPENROUTER_API_KEY\":\"$synthetic_notarius_api_key\"}}" ) cleanup() { @@ -49,7 +52,8 @@ require_clean_recap() { run_converge() { output_file=$1 shift - "$ansible_playbook" -i "$inventory" "$@" "$converge" | tee "$output_file" + env -u AUDITA_LLM_API_KEY -u OPENROUTER_API_KEY \ + "$ansible_playbook" -i "$inventory" "$@" "$converge" | tee "$output_file" } cd "$repository_root" @@ -91,9 +95,15 @@ narratio_effective_config="$test_tmp/narratio-effective.yml" --config /usr/local/etc/narratio/pipeline.yml --campaign centaurs \ > "$narratio_effective_config" grep -Fq 'enabled: true' "$narratio_effective_config" +grep -Fq 'llm_api_key: AUDITA_LLM_API_KEY' "$narratio_effective_config" grep -Fq 'pipeline_id: dnd-session' "$narratio_effective_config" +grep -Fq 'llm_api_key: OPENROUTER_API_KEY' "$narratio_effective_config" +grep -Fq 'resume: true' "$narratio_effective_config" +! grep -Fq 'chunk_cache:' "$narratio_effective_config" grep -Fq 'party: narratio.input.party' "$narratio_effective_config" grep -Fq 'lane_id: item-registry' "$narratio_effective_config" +! grep -Fq "$synthetic_audita_api_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config" +! grep -Fq "$synthetic_notarius_api_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config" /usr/bin/sudo -u narratio /usr/local/bin/narratio config artifacts \ --config /usr/local/etc/narratio/pipeline.yml --campaign centaurs | \ awk -F '\t' '$1 == "session_recap" && $4 == "true" { found = 1 } END { exit !found }'