27 KiB
Implementation Plan 0011: Managed Pipeline Credentials and Notarius Reuse
Status: ready
Target executor: GPT-5.6-Terra
Feature roadmap:
docs/roadmap/features/0011-managed-pipeline-credential-delivery.md
Active plan location: docs/roadmap/implementation.md
Objective
Upgrade the generic Narratio role to v2.1.0 and expose its native Notarius credential and cache controls, then have the D&D pipeline role deliver shared provider credentials through Narratio's conventional secrets directory, coordinate the Audita and Notarius credential references, and request compatible Notarius checkpoint reuse.
The feature roadmap remains authoritative for scope, rationale, target end state, and acceptance criteria. Decisions 0001 and 0002 remain authoritative for direct Ansible convergence and the shared-runtime-group authorization 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
ansible-role-narratiogeneric. It exposes Narratio's native optional fields but does not select D&D credentials, manage secret files, or own suite cache policy. - Keep credential delivery and cross-application policy in
ansible-role-dnd-pipeline. Do not modify an application source repository or move suite policy into the Audita, Notarius, or Scriptorium roles. - Never place a real credential in source, documentation, examples, test fixtures, command output, or commits. Tests may use distinctive synthetic values and must prove that those values do not appear in captured output.
- Treat a
dnd_pipeline_secretskey as untrusted path input. Validate the complete mapping before any key is interpolated into a destination path. Accept only environment-variable names matching^[A-Za-z_][A-Za-z0-9_]*$; accept only nonempty strings or null as values. - Apply
no_log: trueto every production task that evaluates, writes, or removes mapping entries. Do not expose a loop label containing a credential value. - Use direct module-owned convergence: one fixed secrets-directory task, one
validation loop, one copy loop for non-null entries, and one file loop for
explicit null entries. Do not add preliminary
stat, directory scans, recursive ownership repair, checksums, handlers, wrappers, manifests, state files, backups, or post-write validation tasks. - An omitted credential key is unmanaged. Do not mirror the mapping onto the directory, purge unlisted files, or infer that an empty mapping removes anything.
- Keep ordinary application YAML secret-free. It may contain only credential reference names.
- Leave Narratio's
notarius.chunk_cacheunset in the pipeline role. The deployed Notarius root configuration remains the sole owner of ordinaryautochunk-plan reuse, while Narratio owns its native forced-refresh behavior. - Test role-owned behavior through public role inputs and native application commands. Do not test Ansible module guarantees, inspect module results, assert task order, snapshot complete default documents, contact a live provider, or execute the application pipeline.
- Run every stage's validation before committing it. Commit each completed stage when it leaves its 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.
- The pipeline integration suite installs role dependencies from canonical Git origins. The Stage 1 Narratio-role commit must therefore be reachable from its canonical origin before Stage 2 begins. If a fresh Galaxy installation cannot resolve it, stop after Stage 1 and report the commit hash for publication; do not substitute a branch, local role path, or weakened test.
Starting State and Preconditions
-
The workspace control repository contains the reviewed Feature 0011 roadmap and this implementation plan in a clean planning commit on
main. -
Features 0001 through 0010 and the standalone-role test-suite simplification are complete.
-
The implementation repositories are clean on
mainat these reviewed starting commits:Repository Starting commit ansible-role-narratioeeb1105590e638c1f46b42c98a5dbbce4ddeea86ansible-role-dnd-pipelinebbf01e107a5e4e70a2abd6c696bfdb9ccc38bd7e -
The Narratio role matches
origin/main. The pipeline role is intentionally ahead of its canonical origin and must not be reset or replaced. -
../narratiois clean at immutable tagv2.1.0, commitc45e042462b77a8873b4215edc40e3840149db34. -
Narratio v2.1.0 adds optional
notarius.llm_api_key,notarius.resume, andnotarius.chunk_cachefields without requiring migration of existing v2 configuration. Its conventional secrets bootstrap loads immediate regular files from a siblingsecrets/directory, gives an existing process environment value precedence, and requires every configured typed reference to resolve during configuration loading. -
Notarius v0.7.0 is already selected by the suite, records checkpoints under the persistent FHS cache root, and leaves ordinary chunk-plan mode at
auto. -
PromptKit documents
OPENROUTER_API_KEYas the credential name for the OpenRouter backend selected by the suite's production Notarius profile. -
The workspace
.venvprovides Ansible Core 2.21.3 and ansible-lint 26.8.0. -
The local integration environment remains an accepted proxy for Ubuntu 26.04, supports task-level privilege escalation, and provides ordinary POSIX group and ACL behavior.
Repository Scope
Repositories that change:
ansible-role-narratio: Narratio v2.1.0 selection, three nullable native Notarius fields, generic documentation, and focused integration coverage.ansible-role-dnd-pipeline: compatible Narratio role and application pins, credential delivery, Audita and Notarius reference coordination, checkpoint reuse, consumer documentation, and focused integration coverage.ansible-workspace-dnd: implementation progress and review handoff only after the role stages are complete.
Repositories that may be inspected but must remain unchanged:
../narratio, which is the read-only v2.1.0 application authority.../notarius,../audita,../seriatim,../scriptorium, and PromptKit, which may be consulted for current native contracts.ansible-role-notarius,ansible-role-audita,ansible-role-seriatim, andansible-role-scriptorium.ansible-collection-dnd, all asset repositories,rakestraw-ansible, and every other repository inworkspace.yml.
Stage 1: Upgrade the Generic Narratio Role
Objective
Make the standalone role install Narratio v2.1.0 and expose the release's three optional Notarius fields without adding suite-specific credential or cache policy.
Required Policy Review
Before beginning this stage, read:
AGENTS.mddocs/orientation.mddocs/conventions.mddocs/ansible.mddocs/testing.mddocs/roadmap/features/0011-managed-pipeline-credential-delivery.mddocs/decisions/0001-minimal-module-driven-ansible.md../narratio/docs/releases/v2.1.0.md../narratio/docs/config.md../narratio/docs/integrations/notarius.md../narratio/examples/pipeline.full.annotated.ymlansible-role-narratio/defaults/main.ymlansible-role-narratio/meta/argument_specs.ymlansible-role-narratio/templates/pipeline.yml.j2ansible-role-narratio/tests/integrationansible-role-narratio/tests/representative.ymlansible-role-narratio/tests/verify-baseline.ymlansible-role-narratio/tests/verify-config.ymlansible-role-narratio/README.md
Preconditions
ansible-role-narratiois clean at its stated starting commit.- Its existing
tests/integrationentry point passes before modification. - The upstream files listed above remain at the reviewed immutable v2.1.0 tag.
Owning Repository
ansible-role-narratio
Required Changes
- Advance
narratio_versionfromv2.0.0tov2.1.0. Do not change the established source checkout, build condition, metadata convergence, or application-account task flow. - Add these optional public variables beside the existing Notarius variables,
each defaulted to null:
narratio_notarius_llm_api_key,narratio_notarius_resume, andnarratio_notarius_chunk_cache. - Add matching optional argument-specification entries. Use
strfor the credential reference and chunk-cache mode andboolfor resume. Do not duplicate Narratio's native enum or secret-resolution validation in the role. - Extend the existing
notariustemplate section and its parent-emission condition. Renderllm_api_key,resume, andchunk_cacheonly when their corresponding variableis not none; preserve intentionalfalsefor resume and serialize every value with the template's established filter. - Leave all three fields absent when null. Do not create a secrets directory, read an environment variable, accept a raw credential value, or select a Notarius provider in this standalone role.
- Update the README's version, optional-variable list, native Notarius field discussion, and validation summary. Explain that the credential field is an environment-variable name and that credential delivery remains the caller's responsibility. Describe resume and chunk-cache as native application choices without assigning D&D defaults.
- Update the integration suite to explicitly select v2.1.0 for the existing version-selection assertion. Continue testing version selection rather than asserting that v2.1.0 remains the default.
- Extend the representative configuration case with a synthetic environment
reference,
resume: falseas the falsey-value case, and one valid explicit chunk-cache mode. Supply a synthetic value for that named environment variable only when running Narratio's native validation or safe inspection; never put a credential value in managed YAML. - Observe the three representative fields and baseline null omission through
the repository's existing focused configuration checks. Retain native
narratio config validatecoverage and immediate clean repeated convergence. Do not test ConfigKit's resolution precedence or Narratio's subprocess forwarding implementation.
Validation
Run from ansible-role-narratio:
tests/integration
git diff --check
git status --short
Expected result: syntax and production-profile lint pass; an explicitly
selected v2.1.0 binary reports that version; baseline null values remain
omitted; representative credential-name, false resume, and chunk-cache values
load through Narratio's native configuration interface; immediate repeats
report changed=0 and failed=0; and only intended role, test, and README
files are modified.
Completion Criteria
- Defaults, argument specification, template, README, and tests expose one coherent generic interface for the three v2.1.0 fields.
- The role owns no credential value, secrets directory, D&D provider choice, or suite cache policy.
- Tests exercise the public configuration interface without snapshotting the complete default document or re-testing application internals.
- The repository is valid and the stage is committed.
- The commit is reachable from the canonical Narratio-role origin before Stage 2 begins.
Commit
Commit intent: Upgrade the Narratio role to version 2.1.0
Stage 2: Implement Pipeline Credential Delivery and Reuse Policy
Objective
Add the pipeline role's production credential-delivery tasks, coordinate its Audita and Notarius references, and enable Narratio checkpoint reuse through the reviewed Stage 1 interface.
Required Policy Review
Before beginning this stage, read:
AGENTS.mddocs/orientation.mddocs/conventions.mddocs/ansible.mddocs/testing.mddocs/roadmap/features/0011-managed-pipeline-credential-delivery.mddocs/decisions/0001-minimal-module-driven-ansible.mddocs/decisions/0002-shared-readable-pipeline-filesystem-policy.md- the committed Stage 1 changes in
ansible-role-narratio ../narratio/docs/releases/v2.1.0.md../narratio/docs/config.md../narratio/docs/integrations/audita.md../narratio/docs/integrations/notarius.md../narratio/docs/integrations/scriptorium.mdansible-role-dnd-pipeline/defaults/main.ymlansible-role-dnd-pipeline/meta/argument_specs.ymlansible-role-dnd-pipeline/meta/main.ymlansible-role-dnd-pipeline/requirements.ymlansible-role-dnd-pipeline/tasks/main.ymlansible-role-dnd-pipeline/tests/converge.ymlansible-role-dnd-pipeline/tests/integration
Preconditions
- Stage 1 is committed, validated, and clean.
- The Stage 1 commit is reachable from the canonical
ansible-role-narratioGit origin. Stop and report the hash if a fresh Galaxy installation cannot resolve it. ansible-role-dnd-pipelineis clean at its stated starting commit or an expected reviewed descendant.- Its existing
tests/integrationentry point passes before modification.
Owning Repository
ansible-role-dnd-pipeline
Required Changes
- Set
dnd_pipeline_narratio_version: v2.1.0and pin therakestraw.narratioentry inrequirements.ymlto the exact Stage 1 commit. Retain the canonical Git URL and all unrelated dependency pins. - Add
dnd_pipeline_secrets: {}as a required, defaulted dictionary in the public interface. Its keys are credential filenames/environment-variable names; values are either nonempty strings to converge or null to remove the exact named file. - Add required, defaulted
dnd_pipeline_narratio_notarius_llm_api_key: OPENROUTER_API_KEYas a string anddnd_pipeline_narratio_notarius_resume: trueas a boolean. Do not add a suite variable for Narratio's optional chunk-cache override. - Change the suite default for
dnd_pipeline_audita_llm_validation_api_key_envfromAUDITA_VALIDATION_LLM_API_KEYtoAUDITA_LLM_API_KEY. Retain the proposal and validation fields as independently overrideable public variables; do not add an equality assertion or promise split-key forwarding. - Pass
dnd_pipeline_audita_llm_proposal_api_key_envthrough Narratio'snarratio_audita_llm_api_keyinterface. Pass the new Notarius reference and resume variables throughnarratio_notarius_llm_api_keyandnarratio_notarius_resume. Do not passnarratio_notarius_chunk_cache; Notarius's rootautosetting remains in control for ordinary runs. - Before any task interpolates a mapping key into a path, validate every
dnd_pipeline_secrets | dict2itemsentry in oneansible.builtin.assertloop. Require a string key matching^[A-Za-z_][A-Za-z0-9_]*$and a value that is either null or a nonempty string. Applyno_log: trueto the entire validation task. Do not normalize, trim, rename, or infer keys or values. - Create
/usr/local/etc/narratio/secretswith one ordinaryansible.builtin.filetask using the selected runtime user and group and fixed mode0750. Do not recursively alter existing entries. - Converge non-null mapping entries with one
ansible.builtin.copyloop to/usr/local/etc/narratio/secrets/<key>, using the selected runtime user and group and fixed mode0640. Write only the supplied value; do not append metadata, encode it, back it up, or reread it. Applyno_log: true. - Converge null entries to absence with one
ansible.builtin.fileloop over the same mapping. Remove only the exact validated named file and applyno_log: true. An empty mapping and omitted keys must leave existing directory entries untouched. - Keep production convergence to those four operations: validation,
directory creation, non-null copy, and explicit-null removal. Do not add
stat,find, commands, handlers, environment files, shell profiles, launchers, services, providers, rotation, or role-private state. - Adapt the existing integration driver's baseline arguments to supply
distinctive synthetic values for
AUDITA_LLM_API_KEYandOPENROUTER_API_KEYthroughdnd_pipeline_secrets, with both ambient variables explicitly unset. Preserve isolated dependency installation and cleanup restoration. - Extend the existing native Narratio effective-configuration check to
observe the two public credential reference names and
resume: truewhile confirming that Narratio'schunk_cacheoverride is absent. Retain the native Notarius check that its root chunk-plan mode isauto, the service and existing-group-member validation paths, and the baseline clean repeat.
Validation
Run from ansible-role-dnd-pipeline:
tests/integration
git diff --check
git status --short
Expected result: isolated role installation resolves the exact Stage 1
commit; syntax and production-profile lint pass; the role converges the
synthetic credential mapping without displaying its values; Narratio natively
loads the conventional secrets directory as both the service account and the
existing-group-member fixture; its safe effective configuration names the
Audita and Notarius references and enables resume without a chunk-cache
override; Notarius retains auto; the baseline repeat reports changed=0 and
failed=0; and only intended pipeline-role files are modified.
Completion Criteria
- The suite installs Narratio v2.1.0 through the exact reviewed role revision.
- One public mapping owns only explicitly named credential files, including explicit null removal, behind complete pre-path validation and secret-safe task output.
- Audita's suite defaults use one typed reference, Notarius uses
OPENROUTER_API_KEY, and ordinary extraction requests checkpoint reuse. - The pipeline does not duplicate Notarius's chunk-plan policy or add a second credential-loading mechanism.
- The existing integration suite passes and the repository is committed.
Commit
Commit intent: Add managed credentials to the D&D pipeline
Stage 3: Document and Exercise the Credential Contract
Objective
Document the pipeline's credential and reuse policy and add the smallest behavioral coverage for validation, ownership semantics, explicit removal, redaction, authorization, and immediate idempotence.
Required Policy Review
Before beginning this stage, read:
AGENTS.mddocs/orientation.mddocs/conventions.mddocs/ansible.mddocs/testing.mddocs/roadmap/features/0011-managed-pipeline-credential-delivery.mddocs/decisions/0002-shared-readable-pipeline-filesystem-policy.md- the committed Stage 1 and Stage 2 changes
../narratio/docs/config.md../narratio/docs/cli.md../narratio/docs/integrations/notarius.mdansible-role-dnd-pipeline/README.mdansible-role-dnd-pipeline/tests/integrationansible-role-dnd-pipeline/tests/converge.yml
Preconditions
- Stages 1 and 2 are committed, validated, and clean.
- The pipeline's isolated dependency installation resolves the Stage 1 commit.
- The deployed baseline can be restored through the integration driver's existing cleanup path.
Owning Repository
ansible-role-dnd-pipeline
Required Changes
- Update the README's compatible Narratio version, Audita validation credential default, public variable documentation, and obsolete statements that API-key management and checkpoint reuse are deferred.
- Document
dnd_pipeline_secretsas an empty-by-default mapping with valid environment-variable keys, nonempty string values for presence, null for exact removal, and omission for unmanaged entries. Explain that the role neither mirrors nor purges the directory. - Include an Ansible Vault inventory pattern that references encrypted variables without showing a real credential. State that Vault is a recommended consumer workflow, not functionality implemented by the role.
- Document the fixed conventional path,
0750directory and0640file modes, selected runtime ownership, runtime-group authorization meaning, process-environment precedence, and the absence of wrappers, services, or parallel loaders. Make clear that ordinary configuration remains world-readable and secret-free while the secrets subtree does not grant world access. - Document the coordinated
AUDITA_LLM_API_KEYdefault, the typedOPENROUTER_API_KEYNotarius reference, Scriptorium's existing profile-owned reference behavior, ordinary checkpoint resume, Notarius's root-ownedautochunk cache, and Narratio's forced refresh behavior. - Add one representative expected-failure case for an invalid mapping key and one for an empty non-null value. Require each convergence to fail before any candidate destination is managed. Keep task output secret-safe, do not assert a task name or other implementation trace, and do not add an exhaustive validation matrix.
- Exercise explicit-null removal with a uniquely named synthetic credential: first manage it, select its name through the public Notarius reference variable, and confirm native configuration loading succeeds. Then converge the same mapping entry to null with the relevant ambient variable unset. Observe unavailability through an expected failure from Narratio's native configuration loader rather than by inspecting a module result or file metadata.
- Require an immediate identical repeat of the explicit-null state to report
changed=0andfailed=0, then restore the baseline credential mapping so cleanup and later tests remain deterministic. - Retain native configuration validation as the service account and the existing-group-member fixture. Add at most one representative native negative check showing that an identity outside the runtime group cannot load the credential-backed pipeline; do not build a permission matrix or assert numeric filesystem metadata.
- Capture convergence and native inspection output and fail if either distinctive synthetic credential value appears. Names may appear in safe effective configuration; values must not.
- Retain the existing baseline, testing-profile, selected-version, caller-composed Notarius pipeline, shared-cache, immutable local asset, and clean-repeat coverage. Do not contact an LLM, WhisperX, storage, or publishing endpoint; do not execute extraction or test ConfigKit, Narratio, Notarius, or trusted Ansible modules independently.
Validation
Run from ansible-role-dnd-pipeline:
tests/integration
git diff --check
git status --short
Expected result: isolated dependency installation, syntax checking, and production-profile lint pass; valid synthetic credentials load through the conventional directory for authorized identities; invalid names and empty values fail safely; explicit null makes only the selected credential unavailable through native loading and converges cleanly on repeat; no synthetic value appears in captured output; all existing representative paths continue to pass; and documentation matches the public interface.
Completion Criteria
- Consumer documentation completely describes the mapping, Vault usage, authorization boundary, credential flows, cache policy, and exclusions.
- Tests protect role-owned validation, explicit ownership semantics, redaction, authorized use, and clean repetition without testing module or application internals.
- The default suite and representative explicit-null state each converge cleanly on immediate repeat.
- The full integration suite passes and the repository is committed.
Commit
Commit intent: Document and test pipeline credential delivery
Stage 4: Record the Implementation for Review
Objective
Record the completed implementation and validation evidence in the workspace without declaring the feature complete before independent review.
Required Policy Review
Before beginning this stage, read:
AGENTS.mddocs/orientation.mddocs/conventions.mddocs/planning.mddocs/roadmap/features/0011-managed-pipeline-credential-delivery.mddocs/roadmap/implementation.mddocs/status.md
Preconditions
- Stages 1 through 3 are committed and their owning repositories are clean.
- Both complete integration entry points pass at the committed revisions.
- The workspace control repository is clean at the planning commit.
Owning Repository
ansible-workspace-dnd
Required Changes
- Update this plan's Progress Notes with the three implementation commit hashes and concise validation results.
- Update
docs/status.mdso Feature 0011 isin_progress, its evidence names the implementation commits, and the current focus is independent review of the completed implementation. - Keep the feature roadmap
ready; do not mark Feature 0011done, clean the durable roadmap, or create or revisedocs/roadmap/remediation.md. Those actions belong to independent review and closeout. - Do not change implementation repositories or unrelated workspace policy in this stage.
Validation
Run from the workspace root:
git diff --check
./scripts/status
git status --short
Expected result: the status report identifies only the intended workspace tracking edits before commit; both implementation repositories are clean; and the dashboard and progress notes point to the exact completed stage commits.
Completion Criteria
- Implementation and validation evidence is traceable across repositories.
- Feature 0011 remains awaiting independent review rather than being marked complete.
- The workspace control repository is valid and the stage is committed.
Commit
Commit intent: Record the pipeline credential implementation
Final Validation and Handoff
After Stage 4, rerun both owning repositories' complete integration entry points:
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 the Stage 1 through Stage 4 commit hashes and confirm every changed repository has a clean working tree;
- confirm syntax and production-profile lint pass in both changed roles;
- confirm the standalone role installs an explicitly selected Narratio v2.1.0, exposes all three nullable native fields, validates representative values, and immediately converges cleanly;
- confirm the pipeline installs the exact immutable Narratio-role commit, loads managed synthetic credentials for authorized identities, rejects bad mapping entries before path use, removes an explicitly null entry, suppresses credential values, requests Notarius checkpoint reuse, leaves ordinary chunk-plan mode with Notarius, and immediately converges cleanly;
- confirm no upstream application, asset, collection, unrelated standalone role, real credential, external service, or real human account was modified;
- summarize any deviation, blocker, or deferred work, including any pause required to publish the Stage 1 dependency commit;
- report any production complexity beyond the three generic Narratio fields, suite variables and dependency wiring, and the four direct credential tasks, together with the acceptance criterion that required it; and
- leave Feature 0011
in_progressfor independent review rather than marking itdone.
Progress Notes
- Planning complete; implementation has not begun.