# Feature 0023: Adopt Narratio v3.1.0 and Forward Scriptorium Credentials Status: done ## Summary Update the standalone Narratio role and D&D pipeline to Narratio v3.1.0 and expose its Scriptorium credential list. Deliver the coordinated change through the collection and existing deployment consumer without deploying to a host. ## Problem or Opportunity The operator's deployment to `pipeline-dnd` failed during trim bounds generation with Scriptorium reporting HTTP 401. Narratio v3.0.0 filtered provider keys out of the child environment without offering a public Scriptorium credential selection. Analyze had the same forwarding gap. Provisioning a key through Ansible alone could not repair that boundary. Upstream has released explicit Scriptorium credential forwarding in v3.1.0. The original report is preserved in Narratio commit `9389f69`; the upstream change is `44a3186`, with release documentation at `40cbf42`. These are planning references, not substitutes for the released application tag. ## Scope - Adopt Narratio v3.1.0 in the standalone role and suite version selections. - Expose its native credential-list field through the standalone role and supply overrideable D&D defaults through the pipeline role. - Refresh the Narratio role dependency, public pipeline subtree snapshot, collection dependency manifest, and existing consumer pins together. - Extend existing configuration/composition coverage and document operator credential requirements and normal retry behavior. ## Non-goals - Changing upstream applications, other application versions, models, prompts, profile selections, or the existing filesystem and credential-storage policy. - Adding a credential loader, wrapper, environment file, provider discovery, or per-stage credential-selection interface. - Live inference, deployment to a controller or `pipeline-dnd`, credential verification against providers, or modifying Vault contents. - Publishing new Ansible release tags or collection release artifacts. - Reimplementing upstream credential forwarding, redaction, or checkpoint behavior in Ansible or its test suites. ## Target End State ### Standalone Narratio role `narratio_version` defaults to `v3.1.0`. The optional public variable `narratio_scriptorium_credentials` defaults to null, is documented as a list of strings, and renders `scriptorium.credentials` in the native root pipeline file only when non-null. An explicit empty list renders `credentials: []`; nonempty lists preserve the caller's exact credential names. Include the field in the enclosing Scriptorium-section condition so it works independently of other optional Scriptorium variables. No provider-specific default belongs in the standalone role. ### D&D pipeline policy `dnd_pipeline_narratio_version` selects `v3.1.0`. `dnd_pipeline_narratio_scriptorium_credentials` defaults to `[OPENROUTER_API_KEY]` and is passed through the existing Narratio dependency variables. Inventory can replace the list, including with `[]`, or set null to omit the field through the standalone role's interface. The testing overlay inherits this list; no duplicate testing-specific setting is needed for the currently selected profiles. The existing Notarius reference to the same key remains independent. Operators selecting different providers can supply the corresponding names through the ordinary inventory interface. Credential bytes continue to come from Narratio's process environment or its existing secrets mechanism. `dnd_pipeline_secrets` remains an optional managed file-provisioning mechanism, not the only valid credential source. No new secret file or migration is needed where `OPENROUTER_API_KEY` is already provisioned. ### Upstream contract and operator handoff Narratio calls the field `pipeline.scriptorium.credentials` internally; the root pipeline YAML uses `scriptorium: {credentials: [...]}` without an extra `pipeline:` wrapper. The list applies to trim, analyze (including character families), and render-debug calls. It forwards names and resolved values without overriding Scriptorium's own provider/profile selection. Upstream resolves selected names to nonempty values at configuration load, including for commands that do not execute Scriptorium. Tests and operator guidance must account for that existing contract. Omitted/null/empty lists forward nothing; a native overlay replaces the full list. After upgrading and provisioning the selected key, retry failed trim/analyze normally; do not force successful work solely because a credential was added or rotated. See the upstream references below for the authoritative behavior. ## Repository Ownership - `ansible-role-narratio`: version default, public variable, argument spec, template, documentation, and focused configuration tests. - `ansible-role-dnd-pipeline`: suite version/credential defaults, dependency wiring and pin, documentation, and composition coverage. - `ansible-collection-dnd`: exact public pipeline subtree import, matching dependency manifest, and installed-artifact validation. - `rakestraw-ansible`: updated consumer dependency pins and concise upgrade guidance only; preserve its minimal playbook, inventory, and Vault content. - Workspace: feature tracking, later staged plan, and review evidence. - Narratio and the remaining applications/assets: read-only upstream contracts. ## Constraints and Settled Decisions Follow the [Ansible](../../ansible.md), [testing](../../testing.md), and [planning](../../planning.md) policies and the [MVP architecture](../mvp.md). Preserve generic application roles versus opinionated suite policy. Reuse the existing declarative source-build and template tasks; add no production checks. Required dependency commits must be public before external consumer use; subtree imports use public Gitea, not sibling paths. Do not alter unrelated pins. ## Simplest Viable Implementation Add one nullable standalone configuration variable and its ordinary template, argument-spec, and documentation entries. Add one suite default and dependency mapping. Advance the Narratio version and coordinated dependency pins, then reuse the existing collection import and consumer refresh workflow. No new production task or persistent state is needed. ## Acceptance Criteria - The standalone role and assembled suite build the released v3.1.0 source. Any version assertion explicitly supplies the version under test rather than freezing the current default. - Representative explicit credential names reach the deployed native configuration; null omission and explicit `[]` are supported. Extend existing cases rather than adding a separate exhaustive matrix. - Suite composition preserves an explicitly supplied credential list in base and testing configurations. Use synthetic credential values for offline native validation; do not assert today's default list as a permanent invariant. - The real role and installed collection pass their existing relevant validation, including immediate repeated convergence with no changes. Credential-forwarding internals and provider authentication remain upstream responsibilities; no live service or new subprocess simulation is required. - Collection and consumer manifests resolve the coordinated public revisions; consumer host listing/syntax checks work without deployment or Vault decryption. Leave the existing hosts-and-roles playbook unchanged. - Guidance explains load-time credential requirements, existing environment or file provisioning, dependency refresh, and ordinary retry after the fix. ## Dependencies and Follow-up Work The public Narratio v3.1.0 tag was verified on 2026-09-29 at `40cbf4243838b0a1db6caf4c8f790d914ccb96cc`, matching the reviewed release documentation and configuration contract. The release prerequisite is satisfied. Use that release rather than substituting a moving branch. The completed staged implementation plan is preserved in Git history. Required Ansible dependency commits are public as recorded below. Operational deployment and a paid/live smoke run remain separate operator activities, not feature-completion gates. ## Implementation Evidence Implementation completed on 2026-09-29. The public Narratio role revision is `758aed7a74c9a64ad02e13ff551b4f7aea16b3af`; the public D&D pipeline role revision is `0f841fd91ffc533aeec0ec688e81c24bd187a845`; the public collection revision is `002e86c9deb90820a2f1c2f55e1f4d8be59b7c96`. The consumer revision `67cc22f37f042fa12ada09547efa677022242284` is committed locally and not published, preserving its earlier local commits. The collection's imported pipeline Git tree exactly matches the public source revision. No release tag or artifact was created. The Narratio role, pipeline role, and collection each passed `bash -n tests/integration`, their full `./tests/integration` harnesses, and `git diff --check`. The role and collection harnesses passed on their first runs. The pipeline harness's first run encountered a public Git HTTPS timeout; an unchanged retry passed, including native base/testing configuration inspection and a zero-change repeat. The consumer installed the collection manifest's D&D dependencies and exact collection revision in disposable paths; `--list-hosts` selected only `pipeline-dnd`, `--syntax-check` passed, and `git diff --check` passed. No operational controller or target host was contacted. No implementation scope deviation was needed. Offline configuration and convergence checks do not prove that the operator's actual key is valid or that a live trim request will succeed. ## Independent Review and Closeout Closed on 2026-09-29 after independent review found no actionable code-quality issues or implementation gaps. Null omission, explicit empty lists, suite credential selection, testing-overlay inheritance, and coordinated dependency pins match the approved feature. No additional production machinery was added. The imported pipeline Git tree matches the authoritative source exactly. Independent shell syntax, whitespace, role syntax/lint, collection build/install, public role dependency installation, and real-inventory consumer target/syntax checks passed. Review used the recorded full integration and clean-repeat results rather than rerunning host-mutating convergence. No operational host or live provider was contacted. No remediation document change was needed. The active plan is retired. Consumer and workspace commits remain local; operational deployment and provider-key validity remain outside this closeout. ## Open Questions None identified. ## Upstream References - [Narratio v3.1.0 release notes](../../../../narratio/docs/releases/v3.1.0.md) - [Scriptorium credentials](../../../../narratio/docs/config.md#scriptorium-credentials) - [401 troubleshooting](../../../../narratio/docs/troubleshooting.md#scriptorium-returns-http-401-during-trim-or-analyze)