Prepare the managed credential implementation sprint
This commit is contained in:
@@ -48,6 +48,13 @@ file modes are `0750` and `0640`, respectively, with
|
|||||||
shared credentials. Configuration may contain credential reference names but
|
shared credentials. Configuration may contain credential reference names but
|
||||||
never raw credential values.
|
never raw credential values.
|
||||||
|
|
||||||
|
Narratio's general operational guidance recommends `0700` directories and
|
||||||
|
`0600` files for a single-user credential store. The suite deliberately grants
|
||||||
|
group read/traverse access instead: membership in the selected `narratio`
|
||||||
|
runtime group authorizes both pipeline execution and use of its shared provider
|
||||||
|
credentials. Deployments that do not trust every group member require a
|
||||||
|
different per-user credential policy and are outside this decision.
|
||||||
|
|
||||||
Version-controlled campaign and prompt assets may remain root-managed because
|
Version-controlled campaign and prompt assets may remain root-managed because
|
||||||
Git is authoritative, but they are world-readable. The suite does not add
|
Git is authoritative, but they are world-readable. The suite does not add
|
||||||
confidentiality controls to non-secret D&D content.
|
confidentiality controls to non-secret D&D content.
|
||||||
|
|||||||
@@ -0,0 +1,392 @@
|
|||||||
|
# Feature 0011: Managed Pipeline Credentials and Notarius Reuse
|
||||||
|
|
||||||
|
Status: ready
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Upgrade the generic Narratio role and D&D pipeline to Narratio v2.1.0, manage
|
||||||
|
provider credentials through Narratio's conventional ConfigKit secrets
|
||||||
|
directory, and use the release's typed Notarius credential and checkpoint-reuse
|
||||||
|
controls. Credential values remain outside ordinary application YAML and are
|
||||||
|
readable only by the selected runtime user and group. Ordinary pipeline runs
|
||||||
|
reuse compatible Notarius checkpoints, while forced extraction retains
|
||||||
|
Narratio's native refresh behavior.
|
||||||
|
|
||||||
|
## Problem or Opportunity
|
||||||
|
|
||||||
|
The pipeline role currently writes credential reference names but manages no
|
||||||
|
credential values. A caller must prepare the invoking environment through an
|
||||||
|
external mechanism before a real run can reach the selected model providers.
|
||||||
|
|
||||||
|
The installed Narratio v2.0.0 release also cannot forward a selected provider
|
||||||
|
credential to Notarius. Its Notarius child receives a restricted environment,
|
||||||
|
and the v2.0 configuration contract exposes no typed credential field. The
|
||||||
|
pipeline records Notarius checkpoints but cannot ask Notarius to reuse them.
|
||||||
|
|
||||||
|
Narratio v2.1.0, immutable tag `v2.1.0` at `c45e042`, resolves both application
|
||||||
|
contract gaps. It adds optional `notarius.llm_api_key`, `notarius.resume`, and
|
||||||
|
`notarius.chunk_cache` fields without requiring migration of existing v2
|
||||||
|
configuration. The credential field resolves through the existing process
|
||||||
|
environment or secrets-directory bootstrap, forwards only the exact selected
|
||||||
|
name and value, and participates in the application's existing redaction
|
||||||
|
boundary. Ordinary extraction may request checkpoint reuse; forced extraction
|
||||||
|
omits resume and refreshes the active chunk plan.
|
||||||
|
|
||||||
|
The suite separately configures Audita proposal and validation with different
|
||||||
|
environment names even though both use the same endpoint and model. Narratio's
|
||||||
|
Audita boundary accepts one typed credential. This feature therefore
|
||||||
|
coordinates both suite-default Audita sections on `AUDITA_LLM_API_KEY` while
|
||||||
|
retaining their existing independently overrideable variables.
|
||||||
|
|
||||||
|
## Governing Policies
|
||||||
|
|
||||||
|
- [The Ansible house style](../../ansible.md) governs the direct desired-state
|
||||||
|
implementation, native configuration interface, and ordinary module
|
||||||
|
convergence.
|
||||||
|
- [The testing house style](../../testing.md) governs synthetic, native,
|
||||||
|
behavior-oriented validation without live provider calls or filesystem
|
||||||
|
metadata assertions.
|
||||||
|
- [The MVP roadmap](../mvp.md) assigns pipeline-wide secret delivery,
|
||||||
|
application-version coordination, and cache policy to the suite role.
|
||||||
|
- [Decision 0002](../../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
|
||||||
|
defines the selected runtime group as the authorization boundary and fixes
|
||||||
|
`0750` directory and `0640` file modes for shared credential material.
|
||||||
|
- [Feature 0009](0009-shared-pipeline-filesystem-and-execution.md) establishes
|
||||||
|
the service-user and existing-group-member invocation model.
|
||||||
|
- [Feature 0010](0010-dnd-notarius-extraction-integration.md) establishes the
|
||||||
|
Notarius pipeline, FHS cache roots, automatic chunk-plan reuse, and checkpoint
|
||||||
|
recording extended by this feature.
|
||||||
|
- Narratio's immutable v2.1.0 release documentation and current configuration
|
||||||
|
and Notarius integration references are authoritative for the application
|
||||||
|
fields, resolution semantics, forced-run behavior, and redaction contract.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
- Advance the standalone Narratio role's selected application release from
|
||||||
|
v2.0.0 to v2.1.0 without changing its established source-build task flow.
|
||||||
|
- Expose the three new native optional fields through nullable, field-specific
|
||||||
|
role variables: `narratio_notarius_llm_api_key`,
|
||||||
|
`narratio_notarius_resume`, and `narratio_notarius_chunk_cache`.
|
||||||
|
- Keep the standalone role generic. All three variables default to null and
|
||||||
|
are omitted unless a caller selects them, leaving Narratio's native defaults
|
||||||
|
in control.
|
||||||
|
- Advance the pipeline role's compatible Narratio application version to
|
||||||
|
v2.1.0 and pin its Narratio role dependency to the reviewed revision that
|
||||||
|
provides the new interface.
|
||||||
|
- Use `/usr/local/etc/narratio/secrets`, the conventional directory adjacent
|
||||||
|
to `/usr/local/etc/narratio/pipeline.yml`, as the suite's sole managed
|
||||||
|
credential location.
|
||||||
|
- Create that directory as the selected pipeline runtime user and group with
|
||||||
|
mode `0750`.
|
||||||
|
- Add one public `dnd_pipeline_secrets` mapping. Keys are environment-variable
|
||||||
|
names. A non-null string value means that the named credential file must be
|
||||||
|
present with that content; null means that the specifically named managed
|
||||||
|
credential file must be absent. An omitted key is unmanaged.
|
||||||
|
- Default `dnd_pipeline_secrets` to an empty mapping so the role never invents
|
||||||
|
credentials and remains usable with externally prepared process environment
|
||||||
|
values.
|
||||||
|
- Validate selected keys as environment-variable names and reject empty
|
||||||
|
non-null values before constructing a destination path.
|
||||||
|
- Write non-null credential files as the selected runtime user and group with
|
||||||
|
mode `0640`, and remove only names explicitly assigned null.
|
||||||
|
- Suppress credential values from Ansible task output during validation,
|
||||||
|
creation, updates, and removal.
|
||||||
|
- Keep ordinary application configuration limited to non-secret credential
|
||||||
|
reference names.
|
||||||
|
- Coordinate Audita proposal and validation on the suite-default
|
||||||
|
`AUDITA_LLM_API_KEY` name and pass that name through the standalone Narratio
|
||||||
|
role's existing `narratio_audita_llm_api_key` interface.
|
||||||
|
- Add `dnd_pipeline_narratio_notarius_llm_api_key`, default it to
|
||||||
|
`OPENROUTER_API_KEY` for Notarius's selected production profile, and pass it
|
||||||
|
through Narratio's typed Notarius credential field.
|
||||||
|
- Add `dnd_pipeline_narratio_notarius_resume`, default it to true, and pass it
|
||||||
|
through Narratio so ordinary extraction requests reuse of the checkpoints
|
||||||
|
already recorded by the suite's Notarius configuration.
|
||||||
|
- Expose Narratio's native `notarius.chunk_cache` in the standalone role but do
|
||||||
|
not duplicate it behind a suite variable or set it from the pipeline role.
|
||||||
|
The suite already configures Notarius's ordinary chunk-plan mode as `auto`;
|
||||||
|
Narratio v2.1.0 independently owns its forced-extraction refresh override.
|
||||||
|
- Preserve Scriptorium's application-owned `api_key_env` profile selection.
|
||||||
|
Narratio's secrets bootstrap supplies the selected environment value and the
|
||||||
|
existing Scriptorium adapter passes that named credential to its child.
|
||||||
|
- Document the mapping interface, Ansible Vault inventory pattern, process
|
||||||
|
environment precedence, shared-group authorization boundary, explicit null
|
||||||
|
removal, application credential flow, and checkpoint-reuse policy.
|
||||||
|
- Add focused integration coverage using distinctive synthetic values and
|
||||||
|
native Narratio configuration loading. No default test contacts a model
|
||||||
|
provider.
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
- Storing raw credentials in Narratio, Audita, Notarius, or Scriptorium YAML.
|
||||||
|
- Providing real credentials, unencrypted example values, or a default secret
|
||||||
|
mapping.
|
||||||
|
- Implementing Ansible Vault, choosing a vault password mechanism, or requiring
|
||||||
|
one specific inventory encryption workflow.
|
||||||
|
- Integrating an external secret manager, cloud vault, hardware-backed key
|
||||||
|
store, or dynamic credential broker.
|
||||||
|
- Making the pipeline role authoritative for files omitted from
|
||||||
|
`dnd_pipeline_secrets`, purging the whole directory, or recursively changing
|
||||||
|
pre-existing content.
|
||||||
|
- Adding a launcher script, shell profile, environment file, systemd unit,
|
||||||
|
scheduler, or persistent service merely to inject credentials.
|
||||||
|
- Passing arbitrary caller-defined environment variables through Narratio's
|
||||||
|
subprocess boundary.
|
||||||
|
- Managing human accounts or their membership in the runtime group.
|
||||||
|
- Running Audita, Notarius, or Scriptorium against a live endpoint during the
|
||||||
|
default integration suites.
|
||||||
|
- Testing Notarius checkpoint reuse end to end in the Ansible role. Narratio
|
||||||
|
and Notarius own that behavior; the role validates the selected native
|
||||||
|
configuration and immediate Ansible convergence.
|
||||||
|
- Setting Narratio's optional `notarius.chunk_cache` field redundantly when
|
||||||
|
the deployed Notarius configuration already selects `auto`.
|
||||||
|
- Changing Narratio's native forced-extraction refresh policy.
|
||||||
|
- Rotating credentials, retaining prior values, validating provider
|
||||||
|
authorization, or recovering deliberately corrupted secret files.
|
||||||
|
- Adding storage or publishing credentials before the suite selects a storage
|
||||||
|
or publishing feature.
|
||||||
|
- Modifying any upstream application source.
|
||||||
|
|
||||||
|
## Target End State
|
||||||
|
|
||||||
|
The standalone Narratio role installs v2.1.0 by default and can render all
|
||||||
|
three new Notarius fields when a caller supplies them. It owns no credential
|
||||||
|
files and selects no D&D-specific credential or cache policy.
|
||||||
|
|
||||||
|
The pipeline role owns this conventional restricted subtree:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/etc/narratio/
|
||||||
|
├── pipeline.yml
|
||||||
|
└── secrets/ narratio:narratio 0750
|
||||||
|
├── AUDITA_LLM_API_KEY narratio:narratio 0640
|
||||||
|
└── OPENROUTER_API_KEY narratio:narratio 0640
|
||||||
|
```
|
||||||
|
|
||||||
|
The filenames are suite-selected reference names, never credential values.
|
||||||
|
The selected runtime user and group remain configurable through the existing
|
||||||
|
pipeline interface.
|
||||||
|
|
||||||
|
A consumer may keep encrypted values in inventory and select explicit removal
|
||||||
|
without embedding any value in ordinary configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dnd_pipeline_secrets:
|
||||||
|
AUDITA_LLM_API_KEY: "{{ vault_dnd_audita_llm_api_key }}"
|
||||||
|
OPENROUTER_API_KEY: "{{ vault_dnd_openrouter_api_key }}"
|
||||||
|
RETIRED_PROVIDER_KEY: null
|
||||||
|
```
|
||||||
|
|
||||||
|
The role owns only these three named entries for this invocation. It converges
|
||||||
|
the first two to regular files, removes the third, and leaves every omitted
|
||||||
|
name alone. The actual `vault_dnd_*` values belong in encrypted inventory and
|
||||||
|
must not appear in examples, plans, test logs, commits, or ordinary generated
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
When Narratio runs without `--secrets-dir`, it discovers the sibling directory
|
||||||
|
and loads its immediate regular files before resolving the pipeline. An
|
||||||
|
already-set process environment value wins over the corresponding file. The
|
||||||
|
base and `testing` profiles use the same delivery mechanism; profiles select
|
||||||
|
models and application profiles, not a second credential store.
|
||||||
|
|
||||||
|
The suite deliberately uses `narratio:narratio`, directory mode `0750`, and
|
||||||
|
file mode `0640` rather than Narratio's general single-user recommendation of
|
||||||
|
`0700` and `0600`. Membership in the selected runtime group is an explicit
|
||||||
|
authorization to invoke this pipeline with its shared provider credentials.
|
||||||
|
No world access is granted. Deployments that do not trust every group member
|
||||||
|
must use separate process-environment or `--secrets-dir` provisioning and are
|
||||||
|
outside this shared-operator policy.
|
||||||
|
|
||||||
|
Audita's proposal and validation configuration both reference
|
||||||
|
`AUDITA_LLM_API_KEY` by default. Narratio resolves that typed reference and
|
||||||
|
passes the value explicitly to the Audita child. Callers may still override
|
||||||
|
the existing Audita reference variables, but a custom split-key design also
|
||||||
|
requires an application boundary capable of forwarding both values and is not
|
||||||
|
promised by this feature.
|
||||||
|
|
||||||
|
Narratio's effective Notarius configuration names `OPENROUTER_API_KEY`, or a
|
||||||
|
caller-selected replacement, through `notarius.llm_api_key`. Narratio resolves
|
||||||
|
the named secret and forwards only that exact name and value to Notarius. It
|
||||||
|
does not infer a provider from Notarius configuration or forward unrelated
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
Ordinary extraction sets `notarius.resume: true`. Notarius continues to own
|
||||||
|
checkpoint recording, identity, and storage beneath the configured
|
||||||
|
`/var/cache/notarius/checkpoints` root. Narratio requests reuse but does not
|
||||||
|
inspect the cache. The pipeline leaves Narratio's `notarius.chunk_cache` field
|
||||||
|
unset because the Notarius root configuration already selects `auto` at the
|
||||||
|
native owner. Forced extraction follows Narratio v2.1.0 behavior: resume is
|
||||||
|
omitted and the active chunk plan is refreshed without deleting unrelated
|
||||||
|
cache content.
|
||||||
|
|
||||||
|
Scriptorium continues to select credential names through its PromptKit
|
||||||
|
profiles. The Narratio process receives those names from the secret bootstrap,
|
||||||
|
and its existing adapter forwards the selected profile credential.
|
||||||
|
|
||||||
|
## Repository Ownership
|
||||||
|
|
||||||
|
- `../narratio` at immutable tag `v2.1.0` is the read-only application
|
||||||
|
authority for secrets bootstrap, typed Notarius credential forwarding,
|
||||||
|
checkpoint reuse, forced refresh, and subprocess redaction.
|
||||||
|
- `ansible-role-narratio` advances the application release and exposes the
|
||||||
|
three native Notarius fields through its generic field-specific interface.
|
||||||
|
It does not manage secret files or select suite policy.
|
||||||
|
- `ansible-role-dnd-pipeline` owns the conventional secrets directory, managed
|
||||||
|
credential mapping, suite-level Audita and Notarius reference coordination,
|
||||||
|
checkpoint-reuse selection, consumer documentation, and behavioral tests.
|
||||||
|
- `ansible-workspace-dnd` owns this roadmap, the settled MVP policy, progress,
|
||||||
|
and independent review record.
|
||||||
|
- The Audita, Notarius, and Scriptorium application roles remain unchanged;
|
||||||
|
they continue to own only their native configuration interfaces.
|
||||||
|
- The collection, asset, remaining application, and reference repositories
|
||||||
|
remain unchanged.
|
||||||
|
|
||||||
|
## Constraints and Settled Decisions
|
||||||
|
|
||||||
|
- Raw credential bytes never enter ordinary application YAML, Git-tracked
|
||||||
|
examples, workspace plans, or committed test fixtures.
|
||||||
|
- The role manages secret values only through `ansible.builtin.copy` content
|
||||||
|
or an equally direct secret-safe module operation with `no_log: true`.
|
||||||
|
- The conventional directory path is fixed because automatic Narratio
|
||||||
|
discovery depends on its relationship to the fixed root pipeline document.
|
||||||
|
- Credential filenames must match the environment-variable grammar accepted
|
||||||
|
by ConfigKit. Validation exists to prevent a caller-controlled key from
|
||||||
|
becoming a path outside the secrets directory.
|
||||||
|
- Empty credential values are invalid. Null means explicit absence and is
|
||||||
|
distinct from an empty string.
|
||||||
|
- An omitted mapping key is outside the role's ownership. Exact-directory
|
||||||
|
mirroring and deletion of unlisted files are intentionally excluded.
|
||||||
|
- The shared runtime group is an authorization group. Its members may read the
|
||||||
|
managed credentials; all other local users are denied access.
|
||||||
|
- The suite's group-readable credential policy deliberately differs from
|
||||||
|
Narratio's general single-user mode recommendation. ConfigKit does not
|
||||||
|
enforce those recommended modes, and the selected policy grants no world
|
||||||
|
access.
|
||||||
|
- Application adapters, rather than Ansible, own the secure transfer of loaded
|
||||||
|
values to child processes. Ansible does not create wrappers or reconstruct
|
||||||
|
the subprocess environment.
|
||||||
|
- Notarius's root configuration remains the single owner of ordinary
|
||||||
|
chunk-plan mode. Narratio's native `resume` field expresses the distinct
|
||||||
|
request to load compatible recorded checkpoints.
|
||||||
|
- Production convergence performs no provider call, credential validity test,
|
||||||
|
cache probe, content checksum bookkeeping, backup, or post-write reread.
|
||||||
|
|
||||||
|
## Simplest Viable Implementation Shape
|
||||||
|
|
||||||
|
The standalone Narratio role needs only a release update and three nullable
|
||||||
|
field-specific variables rendered through its existing template. It remains
|
||||||
|
generic and does not own credential files or suite policy.
|
||||||
|
|
||||||
|
The pipeline role needs one empty credential mapping, two Narratio Notarius
|
||||||
|
policy variables, coordinated Audita reference defaults, and ordinary
|
||||||
|
dependency wiring. Credential convergence consists of one directory task, one
|
||||||
|
validation loop, one copy loop for non-null entries, and one file loop for
|
||||||
|
explicit null removals. Both secret-bearing loops suppress their output.
|
||||||
|
|
||||||
|
Documentation and focused native integration coverage complete the public
|
||||||
|
interface. No state probe, handler, template assembly, manifest, wrapper,
|
||||||
|
directory scan, or role-private bookkeeping is required. The validation loop
|
||||||
|
is deliberate: the mapping key becomes a filesystem path, so rejecting
|
||||||
|
anything other than a valid environment-variable name protects the declared
|
||||||
|
destination boundary.
|
||||||
|
|
||||||
|
## Rationale and Alternatives
|
||||||
|
|
||||||
|
Narratio's native ConfigKit bootstrap is preferable to a shell wrapper or
|
||||||
|
service-specific environment file because every pipeline-loading command uses
|
||||||
|
the same application-owned behavior, whether invoked by the service account or
|
||||||
|
an authorized human operator. It also preserves the application's existing
|
||||||
|
environment-precedence and redaction rules.
|
||||||
|
|
||||||
|
A mapping is more ergonomic for inventory than a list of file objects because
|
||||||
|
the native identity of each entry is already its environment-variable name.
|
||||||
|
Null provides explicit removal without making an empty mapping destructive or
|
||||||
|
requiring a filesystem scan. Omitted files remain available for consumers that
|
||||||
|
combine Ansible-managed credentials with another provisioning mechanism.
|
||||||
|
|
||||||
|
Per-user `0700` directories would follow Narratio's general recommendation but
|
||||||
|
would require separate keys or an additional invocation convention for every
|
||||||
|
authorized human. The selected shared group already defines who may execute
|
||||||
|
the suite with shared state, so group-readable and world-inaccessible
|
||||||
|
credentials provide the intended operational model with less duplication.
|
||||||
|
|
||||||
|
Selecting Narratio checkpoint reuse completes the suite's earlier decision to
|
||||||
|
enable every available Notarius cache. Duplicating `chunk_cache: auto` in both
|
||||||
|
Narratio and Notarius configuration would add no ordinary behavior, so the
|
||||||
|
pipeline leaves the optional Narratio override unset and relies on each
|
||||||
|
application's documented ownership boundary.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- The standalone Narratio role installs an explicitly selected v2.1.0 and can
|
||||||
|
render representative non-null and falsey values for
|
||||||
|
`narratio_notarius_llm_api_key`, `narratio_notarius_resume`, and
|
||||||
|
`narratio_notarius_chunk_cache` while omitting null values.
|
||||||
|
- The pipeline role selects Narratio v2.1.0 and pins the reviewed standalone
|
||||||
|
role revision that provides its native fields.
|
||||||
|
- The pipeline role creates `/usr/local/etc/narratio/secrets` with the selected
|
||||||
|
runtime ownership and suite credential-directory mode.
|
||||||
|
- `dnd_pipeline_secrets` defaults to an empty mapping and accepts valid
|
||||||
|
environment names with nonempty string or null values.
|
||||||
|
- Invalid names and empty non-null values fail before any destination outside
|
||||||
|
the declared secret directory can be constructed.
|
||||||
|
- Non-null entries converge to regular files with the selected runtime
|
||||||
|
ownership and mode `0640`; null entries converge to absence; omitted names
|
||||||
|
remain unmanaged.
|
||||||
|
- Credential values are suppressed from Ansible output and never appear in
|
||||||
|
application YAML, generated examples, native effective-configuration output,
|
||||||
|
test logs, or committed fixtures.
|
||||||
|
- Audita proposal and validation use `AUDITA_LLM_API_KEY` by default, and
|
||||||
|
Narratio's typed Audita field names that reference so the adapter explicitly
|
||||||
|
supplies the loaded value.
|
||||||
|
- Narratio's effective pipeline selects `OPENROUTER_API_KEY` through the typed
|
||||||
|
Notarius field and selects checkpoint resume for ordinary extraction.
|
||||||
|
- Narratio's optional chunk-cache override remains absent from the suite
|
||||||
|
configuration while Notarius's effective root configuration continues to
|
||||||
|
select `auto`.
|
||||||
|
- Scriptorium continues to receive the credential named by its selected
|
||||||
|
profile through the existing adapter behavior.
|
||||||
|
- A synthetic pipeline integration invocation with the relevant ambient
|
||||||
|
variables unset loads credentials through the conventional directory and
|
||||||
|
succeeds at native offline configuration validation as the service account
|
||||||
|
and one existing-group-member fixture.
|
||||||
|
- One representative explicit-null transition makes the selected synthetic
|
||||||
|
credential unavailable through the native bootstrap boundary without
|
||||||
|
inspecting module results or file metadata.
|
||||||
|
- A distinctive synthetic secret never appears in captured integration output.
|
||||||
|
- The baseline and representative credential applications each report
|
||||||
|
`changed=0` and `failed=0` on an immediate identical repeat.
|
||||||
|
- Syntax checking, production-profile lint, and the complete standalone
|
||||||
|
Narratio and pipeline integration entry points pass.
|
||||||
|
- No live provider, WhisperX service, storage backend, model call, or
|
||||||
|
application cache execution occurs in default tests.
|
||||||
|
|
||||||
|
## Dependencies and Follow-up Work
|
||||||
|
|
||||||
|
- Features 0005, 0006, 0008, 0009, and 0010 are complete prerequisites.
|
||||||
|
- Narratio v2.1.0 at immutable tag `c45e042` satisfies the former typed
|
||||||
|
Notarius credential and cache-control prerequisite.
|
||||||
|
- The completed upstream feature request was removed from Narratio's active
|
||||||
|
roadmap during its v2.1.0 release cleanup; the release reference now owns the
|
||||||
|
delivered behavior.
|
||||||
|
- The standalone Narratio-role commit produced by this feature must be
|
||||||
|
available from its canonical Git origin before the pipeline's isolated
|
||||||
|
dependency test can use it.
|
||||||
|
- Collection assembly should follow this feature so the first assembled
|
||||||
|
collection packages a pipeline with complete credential delivery and cache
|
||||||
|
reuse.
|
||||||
|
- Storage and publishing policy may later add S3 or other credential reference
|
||||||
|
names to consumer inventory without changing the file-delivery mechanism.
|
||||||
|
- Operator selection, group-membership management, services, scheduling,
|
||||||
|
upgrades, removal, and external secret-manager integration remain separate
|
||||||
|
features.
|
||||||
|
|
||||||
|
## Potential Future Hardening
|
||||||
|
|
||||||
|
- Integrate a dedicated external secret manager or short-lived credential
|
||||||
|
broker.
|
||||||
|
- Support distinct per-operator secret directories for deployments that do
|
||||||
|
not treat runtime-group membership as shared credential authorization.
|
||||||
|
- Add explicit credential rotation orchestration and provider-side validity
|
||||||
|
checks.
|
||||||
|
- Add platform-specific mandatory-access-control policy for credential files.
|
||||||
@@ -1,12 +1,617 @@
|
|||||||
# Implementation Plan
|
# Implementation Plan 0011: Managed Pipeline Credentials and Notarius Reuse
|
||||||
|
|
||||||
Status: pending
|
Status: ready
|
||||||
|
|
||||||
No implementation plan is currently active. Feature 0010 was implemented,
|
Target executor: GPT-5.6-Terra
|
||||||
independently reviewed, and completed through pipeline-role remediation commit
|
|
||||||
`bbf01e1`. Its durable scope, decisions, and acceptance criteria remain in
|
|
||||||
[Feature 0010](features/0010-dnd-notarius-extraction-integration.md), and the
|
|
||||||
completed review record remains in [the remediation document](remediation.md).
|
|
||||||
|
|
||||||
Select and approve the next unit of work before replacing this notice with a
|
Feature roadmap:
|
||||||
new staged implementation plan.
|
`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-narratio` generic. 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_secrets` key 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: true` to 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_cache` unset in the pipeline role. The
|
||||||
|
deployed Notarius root configuration remains the sole owner of ordinary
|
||||||
|
`auto` chunk-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 `main` at these reviewed
|
||||||
|
starting commits:
|
||||||
|
|
||||||
|
| Repository | Starting commit |
|
||||||
|
| --- | --- |
|
||||||
|
| `ansible-role-narratio` | `eeb1105590e638c1f46b42c98a5dbbce4ddeea86` |
|
||||||
|
| `ansible-role-dnd-pipeline` | `bbf01e107a5e4e70a2abd6c696bfdb9ccc38bd7e` |
|
||||||
|
|
||||||
|
- The Narratio role matches `origin/main`. The pipeline role is intentionally
|
||||||
|
ahead of its canonical origin and must not be reset or replaced.
|
||||||
|
- `../narratio` is clean at immutable tag `v2.1.0`, commit
|
||||||
|
`c45e042462b77a8873b4215edc40e3840149db34`.
|
||||||
|
- Narratio v2.1.0 adds optional `notarius.llm_api_key`, `notarius.resume`, and
|
||||||
|
`notarius.chunk_cache` fields without requiring migration of existing v2
|
||||||
|
configuration. Its conventional secrets bootstrap loads immediate regular
|
||||||
|
files from a sibling `secrets/` 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_KEY` as the credential name for the
|
||||||
|
OpenRouter backend selected by the suite's production Notarius profile.
|
||||||
|
- The workspace `.venv` provides 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`, and `ansible-role-scriptorium`.
|
||||||
|
- `ansible-collection-dnd`, all asset repositories, `rakestraw-ansible`, and
|
||||||
|
every other repository in `workspace.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.md`
|
||||||
|
- `docs/orientation.md`
|
||||||
|
- `docs/conventions.md`
|
||||||
|
- `docs/ansible.md`
|
||||||
|
- `docs/testing.md`
|
||||||
|
- `docs/roadmap/features/0011-managed-pipeline-credential-delivery.md`
|
||||||
|
- `docs/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.yml`
|
||||||
|
- `ansible-role-narratio/defaults/main.yml`
|
||||||
|
- `ansible-role-narratio/meta/argument_specs.yml`
|
||||||
|
- `ansible-role-narratio/templates/pipeline.yml.j2`
|
||||||
|
- `ansible-role-narratio/tests/integration`
|
||||||
|
- `ansible-role-narratio/tests/representative.yml`
|
||||||
|
- `ansible-role-narratio/tests/verify-baseline.yml`
|
||||||
|
- `ansible-role-narratio/tests/verify-config.yml`
|
||||||
|
- `ansible-role-narratio/README.md`
|
||||||
|
|
||||||
|
### Preconditions
|
||||||
|
|
||||||
|
- `ansible-role-narratio` is clean at its stated starting commit.
|
||||||
|
- Its existing `tests/integration` entry 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
|
||||||
|
|
||||||
|
1. Advance `narratio_version` from `v2.0.0` to `v2.1.0`. Do not change the
|
||||||
|
established source checkout, build condition, metadata convergence, or
|
||||||
|
application-account task flow.
|
||||||
|
2. Add these optional public variables beside the existing Notarius variables,
|
||||||
|
each defaulted to null:
|
||||||
|
`narratio_notarius_llm_api_key`, `narratio_notarius_resume`, and
|
||||||
|
`narratio_notarius_chunk_cache`.
|
||||||
|
3. Add matching optional argument-specification entries. Use `str` for the
|
||||||
|
credential reference and chunk-cache mode and `bool` for resume. Do not
|
||||||
|
duplicate Narratio's native enum or secret-resolution validation in the
|
||||||
|
role.
|
||||||
|
4. Extend the existing `notarius` template section and its parent-emission
|
||||||
|
condition. Render `llm_api_key`, `resume`, and `chunk_cache` only when their
|
||||||
|
corresponding variable `is not none`; preserve intentional `false` for
|
||||||
|
resume and serialize every value with the template's established filter.
|
||||||
|
5. 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.
|
||||||
|
6. 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.
|
||||||
|
7. 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.
|
||||||
|
8. Extend the representative configuration case with a synthetic environment
|
||||||
|
reference, `resume: false` as 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.
|
||||||
|
9. Observe the three representative fields and baseline null omission through
|
||||||
|
the repository's existing focused configuration checks. Retain native
|
||||||
|
`narratio config validate` coverage and immediate clean repeated
|
||||||
|
convergence. Do not test ConfigKit's resolution precedence or Narratio's
|
||||||
|
subprocess forwarding implementation.
|
||||||
|
|
||||||
|
### Validation
|
||||||
|
|
||||||
|
Run from `ansible-role-narratio`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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.md`
|
||||||
|
- `docs/orientation.md`
|
||||||
|
- `docs/conventions.md`
|
||||||
|
- `docs/ansible.md`
|
||||||
|
- `docs/testing.md`
|
||||||
|
- `docs/roadmap/features/0011-managed-pipeline-credential-delivery.md`
|
||||||
|
- `docs/decisions/0001-minimal-module-driven-ansible.md`
|
||||||
|
- `docs/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.md`
|
||||||
|
- `ansible-role-dnd-pipeline/defaults/main.yml`
|
||||||
|
- `ansible-role-dnd-pipeline/meta/argument_specs.yml`
|
||||||
|
- `ansible-role-dnd-pipeline/meta/main.yml`
|
||||||
|
- `ansible-role-dnd-pipeline/requirements.yml`
|
||||||
|
- `ansible-role-dnd-pipeline/tasks/main.yml`
|
||||||
|
- `ansible-role-dnd-pipeline/tests/converge.yml`
|
||||||
|
- `ansible-role-dnd-pipeline/tests/integration`
|
||||||
|
|
||||||
|
### Preconditions
|
||||||
|
|
||||||
|
- Stage 1 is committed, validated, and clean.
|
||||||
|
- The Stage 1 commit is reachable from the canonical
|
||||||
|
`ansible-role-narratio` Git origin. Stop and report the hash if a fresh
|
||||||
|
Galaxy installation cannot resolve it.
|
||||||
|
- `ansible-role-dnd-pipeline` is clean at its stated starting commit or an
|
||||||
|
expected reviewed descendant.
|
||||||
|
- Its existing `tests/integration` entry point passes before modification.
|
||||||
|
|
||||||
|
### Owning Repository
|
||||||
|
|
||||||
|
`ansible-role-dnd-pipeline`
|
||||||
|
|
||||||
|
### Required Changes
|
||||||
|
|
||||||
|
1. Set `dnd_pipeline_narratio_version: v2.1.0` and pin the
|
||||||
|
`rakestraw.narratio` entry in `requirements.yml` to the exact Stage 1
|
||||||
|
commit. Retain the canonical Git URL and all unrelated dependency pins.
|
||||||
|
2. 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.
|
||||||
|
3. Add required, defaulted
|
||||||
|
`dnd_pipeline_narratio_notarius_llm_api_key: OPENROUTER_API_KEY` as a string
|
||||||
|
and `dnd_pipeline_narratio_notarius_resume: true` as a boolean. Do not add a
|
||||||
|
suite variable for Narratio's optional chunk-cache override.
|
||||||
|
4. Change the suite default for
|
||||||
|
`dnd_pipeline_audita_llm_validation_api_key_env` from
|
||||||
|
`AUDITA_VALIDATION_LLM_API_KEY` to `AUDITA_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.
|
||||||
|
5. Pass `dnd_pipeline_audita_llm_proposal_api_key_env` through Narratio's
|
||||||
|
`narratio_audita_llm_api_key` interface. Pass the new Notarius reference and
|
||||||
|
resume variables through `narratio_notarius_llm_api_key` and
|
||||||
|
`narratio_notarius_resume`. Do not pass
|
||||||
|
`narratio_notarius_chunk_cache`; Notarius's root `auto` setting remains in
|
||||||
|
control for ordinary runs.
|
||||||
|
6. Before any task interpolates a mapping key into a path, validate every
|
||||||
|
`dnd_pipeline_secrets | dict2items` entry in one `ansible.builtin.assert`
|
||||||
|
loop. Require a string key matching `^[A-Za-z_][A-Za-z0-9_]*$` and a value
|
||||||
|
that is either null or a nonempty string. Apply `no_log: true` to the entire
|
||||||
|
validation task. Do not normalize, trim, rename, or infer keys or values.
|
||||||
|
7. Create `/usr/local/etc/narratio/secrets` with one ordinary
|
||||||
|
`ansible.builtin.file` task using the selected runtime user and group and
|
||||||
|
fixed mode `0750`. Do not recursively alter existing entries.
|
||||||
|
8. Converge non-null mapping entries with one `ansible.builtin.copy` loop to
|
||||||
|
`/usr/local/etc/narratio/secrets/<key>`, using the selected runtime user and
|
||||||
|
group and fixed mode `0640`. Write only the supplied value; do not append
|
||||||
|
metadata, encode it, back it up, or reread it. Apply `no_log: true`.
|
||||||
|
9. Converge null entries to absence with one `ansible.builtin.file` loop over
|
||||||
|
the same mapping. Remove only the exact validated named file and apply
|
||||||
|
`no_log: true`. An empty mapping and omitted keys must leave existing
|
||||||
|
directory entries untouched.
|
||||||
|
10. 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.
|
||||||
|
11. Adapt the existing integration driver's baseline arguments to supply
|
||||||
|
distinctive synthetic values for `AUDITA_LLM_API_KEY` and
|
||||||
|
`OPENROUTER_API_KEY` through `dnd_pipeline_secrets`, with both ambient
|
||||||
|
variables explicitly unset. Preserve isolated dependency installation and
|
||||||
|
cleanup restoration.
|
||||||
|
12. Extend the existing native Narratio effective-configuration check to
|
||||||
|
observe the two public credential reference names and `resume: true` while
|
||||||
|
confirming that Narratio's `chunk_cache` override is absent. Retain the
|
||||||
|
native Notarius check that its root chunk-plan mode is `auto`, the service
|
||||||
|
and existing-group-member validation paths, and the baseline clean repeat.
|
||||||
|
|
||||||
|
### Validation
|
||||||
|
|
||||||
|
Run from `ansible-role-dnd-pipeline`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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.md`
|
||||||
|
- `docs/orientation.md`
|
||||||
|
- `docs/conventions.md`
|
||||||
|
- `docs/ansible.md`
|
||||||
|
- `docs/testing.md`
|
||||||
|
- `docs/roadmap/features/0011-managed-pipeline-credential-delivery.md`
|
||||||
|
- `docs/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.md`
|
||||||
|
- `ansible-role-dnd-pipeline/README.md`
|
||||||
|
- `ansible-role-dnd-pipeline/tests/integration`
|
||||||
|
- `ansible-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
|
||||||
|
|
||||||
|
1. 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.
|
||||||
|
2. Document `dnd_pipeline_secrets` as 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.
|
||||||
|
3. 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.
|
||||||
|
4. Document the fixed conventional path, `0750` directory and `0640` file
|
||||||
|
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.
|
||||||
|
5. Document the coordinated `AUDITA_LLM_API_KEY` default, the typed
|
||||||
|
`OPENROUTER_API_KEY` Notarius reference, Scriptorium's existing
|
||||||
|
profile-owned reference behavior, ordinary checkpoint resume, Notarius's
|
||||||
|
root-owned `auto` chunk cache, and Narratio's forced refresh behavior.
|
||||||
|
6. 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.
|
||||||
|
7. 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.
|
||||||
|
8. Require an immediate identical repeat of the explicit-null state to report
|
||||||
|
`changed=0` and `failed=0`, then restore the baseline credential mapping so
|
||||||
|
cleanup and later tests remain deterministic.
|
||||||
|
9. 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.
|
||||||
|
10. 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.
|
||||||
|
11. 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`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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.md`
|
||||||
|
- `docs/orientation.md`
|
||||||
|
- `docs/conventions.md`
|
||||||
|
- `docs/planning.md`
|
||||||
|
- `docs/roadmap/features/0011-managed-pipeline-credential-delivery.md`
|
||||||
|
- `docs/roadmap/implementation.md`
|
||||||
|
- `docs/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
|
||||||
|
|
||||||
|
1. Update this plan's Progress Notes with the three implementation commit
|
||||||
|
hashes and concise validation results.
|
||||||
|
2. Update `docs/status.md` so Feature 0011 is `in_progress`, its evidence names
|
||||||
|
the implementation commits, and the current focus is independent review of
|
||||||
|
the completed implementation.
|
||||||
|
3. Keep the feature roadmap `ready`; do not mark Feature 0011 `done`, clean the
|
||||||
|
durable roadmap, or create or revise `docs/roadmap/remediation.md`. Those
|
||||||
|
actions belong to independent review and closeout.
|
||||||
|
4. Do not change implementation repositories or unrelated workspace policy in
|
||||||
|
this stage.
|
||||||
|
|
||||||
|
### Validation
|
||||||
|
|
||||||
|
Run from the workspace root:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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:
|
||||||
|
|
||||||
|
```text
|
||||||
|
cd ansible-role-narratio && tests/integration
|
||||||
|
cd ../ansible-role-dnd-pipeline && tests/integration
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, from the workspace root, run:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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_progress` for independent review rather than marking
|
||||||
|
it `done`.
|
||||||
|
|
||||||
|
## Progress Notes
|
||||||
|
|
||||||
|
- Planning complete; implementation has not begun.
|
||||||
|
|||||||
@@ -255,9 +255,27 @@ application-role releases in one source repository.
|
|||||||
- Debug output is not enabled by the MVP. Any later debug feature must either
|
- Debug output is not enabled by the MVP. Any later debug feature must either
|
||||||
produce world-readable non-secret D&D diagnostics or identify and justify a
|
produce world-readable non-secret D&D diagnostics or identify and justify a
|
||||||
narrower application contract before deployment.
|
narrower application contract before deployment.
|
||||||
- Credential material will live beneath a restricted `secrets/` subdirectory
|
- Credential material lives beneath the conventional
|
||||||
owned by `narratio:narratio`, with directories mode `0750` and files mode
|
`/usr/local/etc/narratio/secrets` subdirectory owned by
|
||||||
`0640`. Ordinary configuration contains only credential reference names.
|
`narratio:narratio`, with directory mode `0750` and file mode `0640`.
|
||||||
|
Membership in the `narratio` group is an explicit authorization to use the
|
||||||
|
suite's shared credentials. This deliberately differs from Narratio's
|
||||||
|
general single-user `0700` and `0600` recommendation while retaining no
|
||||||
|
world access. Ordinary configuration contains only credential reference
|
||||||
|
names.
|
||||||
|
- The pipeline role exposes one empty-by-default credential mapping. Non-null
|
||||||
|
entries manage files named for valid environment variables; null explicitly
|
||||||
|
removes the named file; omitted names remain unmanaged. Credential values
|
||||||
|
are expected to come from encrypted inventory such as Ansible Vault and are
|
||||||
|
suppressed from task output.
|
||||||
|
- Narratio's native ConfigKit secrets bootstrap owns loading these files and
|
||||||
|
process-environment precedence. The suite does not add a wrapper, shell
|
||||||
|
profile, service environment file, or parallel credential loader.
|
||||||
|
- The suite coordinates Audita proposal and validation on the
|
||||||
|
`AUDITA_LLM_API_KEY` reference and selects `OPENROUTER_API_KEY` for
|
||||||
|
Notarius's production extraction profile. Narratio v2.1.0 resolves those
|
||||||
|
typed references and forwards only the selected credentials to the
|
||||||
|
corresponding subprocesses.
|
||||||
- [Decision 0002](../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
|
- [Decision 0002](../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
|
||||||
records the complete rationale and boundary for this policy.
|
records the complete rationale and boundary for this policy.
|
||||||
|
|
||||||
@@ -309,8 +327,9 @@ application-role releases in one source repository.
|
|||||||
cache beneath `/var/cache/notarius`. That FHS cache root is owned by the
|
cache beneath `/var/cache/notarius`. That FHS cache root is owned by the
|
||||||
`narratio` account and group with mode `2775` and the suite's shared default
|
`narratio` account and group with mode `2775` and the suite's shared default
|
||||||
ACL policy. Notarius v0.7.0 leaves cache-entry access to that deployment
|
ACL policy. Notarius v0.7.0 leaves cache-entry access to that deployment
|
||||||
policy. Chunk plans are reused automatically; checkpoints are recorded but
|
policy. Chunk plans are reused automatically. Narratio v2.1.0 requests reuse
|
||||||
Narratio does not yet request their reuse.
|
of compatible recorded checkpoints during ordinary extraction; forced
|
||||||
|
extraction omits checkpoint loading and refreshes the active chunk plan.
|
||||||
- The standalone Notarius role exposes Notarius v0.7.0's native ConfigKit
|
- The standalone Notarius role exposes Notarius v0.7.0's native ConfigKit
|
||||||
import list while remaining independent of D&D content. The pipeline role
|
import list while remaining independent of D&D content. The pipeline role
|
||||||
owns an imported `pipelines/dnd-session.yml` fragment containing its
|
owns an imported `pipelines/dnd-session.yml` fragment containing its
|
||||||
@@ -378,7 +397,6 @@ The following areas require investigation and decisions before implementation:
|
|||||||
|
|
||||||
- The mechanism used to incorporate the independently developed pipeline role
|
- The mechanism used to incorporate the independently developed pipeline role
|
||||||
into collection releases
|
into collection releases
|
||||||
- Secret injection and storage
|
|
||||||
- Optional suite-level operator-selection and group-membership management
|
- Optional suite-level operator-selection and group-membership management
|
||||||
- Upgrade, downgrade, and removal behavior
|
- Upgrade, downgrade, and removal behavior
|
||||||
- Collection bootstrap and end-to-end validation details beyond the locked
|
- Collection bootstrap and end-to-end validation details beyond the locked
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Workspace Status
|
# Workspace Status
|
||||||
|
|
||||||
Last updated: 2026-09-15
|
Last updated: 2026-09-16
|
||||||
|
|
||||||
Current milestone: M1-03 suite-level pipeline role
|
Current milestone: M1-03 suite-level pipeline role
|
||||||
|
|
||||||
Current focus: Select the next unit of work.
|
Current focus: Begin the Feature 0011 implementation sprint.
|
||||||
|
|
||||||
| ID | Deliverable | Owner | State | Evidence or next step |
|
| ID | Deliverable | Owner | State | Evidence or next step |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
@@ -15,7 +15,7 @@ Current focus: Select the next unit of work.
|
|||||||
| M0-05 | Suite-level role repository | ansible-role-dnd-pipeline | done | Repository created and added to `workspace.yml` |
|
| M0-05 | Suite-level role repository | ansible-role-dnd-pipeline | done | Repository created and added to `workspace.yml` |
|
||||||
| M1-01 | Remaining MVP design decisions | workspace | done | Feature 0003 roadmap fixes the Notarius configuration interface |
|
| M1-01 | Remaining MVP design decisions | workspace | done | Feature 0003 roadmap fixes the Notarius configuration interface |
|
||||||
| M1-02 | Standalone application roles | role repositories | done | All five standalone roles implemented and independently reviewed |
|
| M1-02 | Standalone application roles | role repositories | done | All five standalone roles implemented and independently reviewed |
|
||||||
| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | in_progress | Feature 0010 is complete; select the next suite-policy feature |
|
| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | in_progress | Execute the ready Feature 0011 implementation plan |
|
||||||
| M1-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism |
|
| M1-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism |
|
||||||
| F0001 | Install Seriatim from pinned source | ansible-role-seriatim | done | Implementation, integration coverage, and final remediation completed through `fb8dc41` |
|
| F0001 | Install Seriatim from pinned source | ansible-role-seriatim | done | Implementation, integration coverage, and final remediation completed through `fb8dc41` |
|
||||||
| F0002 | Install and configure Audita | ansible-role-audita | done | Field-specific configuration completed in `e61f02f` and `847c4c3`; full suite passed |
|
| F0002 | Install and configure Audita | ansible-role-audita | done | Field-specific configuration completed in `e61f02f` and `847c4c3`; full suite passed |
|
||||||
@@ -27,6 +27,7 @@ Current focus: Select the next unit of work.
|
|||||||
| F0008 | Define opinionated D&D processing configuration | ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `3e253d7` |
|
| F0008 | Define opinionated D&D processing configuration | ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `3e253d7` |
|
||||||
| F0009 | Establish shared pipeline filesystem and execution | configuration-bearing application roles and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `b15fe8d` |
|
| F0009 | Establish shared pipeline filesystem and execution | configuration-bearing application roles and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `b15fe8d` |
|
||||||
| F0010 | Integrate D&D Notarius extraction | ansible-role-notarius and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `bbf01e1` |
|
| F0010 | Integrate D&D Notarius extraction | ansible-role-notarius and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `bbf01e1` |
|
||||||
|
| F0011 | Deliver pipeline credentials and Notarius reuse | ansible-role-narratio and ansible-role-dnd-pipeline | ready | Staged implementation plan is ready at `docs/roadmap/implementation.md` |
|
||||||
| A0001 | Audit completed standalone-role test suites | workspace and standalone roles | done | Findings recorded in `docs/roadmap/test-suite-audit-findings.md` |
|
| A0001 | Audit completed standalone-role test suites | workspace and standalone roles | done | Findings recorded in `docs/roadmap/test-suite-audit-findings.md` |
|
||||||
| R0001 | Simplify completed standalone-role test suites | workspace and standalone roles | done | Role commits `e08c63c`, `d2d0b9d`, and `cfecf37` passed implementation and independent review |
|
| R0001 | Simplify completed standalone-role test suites | workspace and standalone roles | done | Role commits `e08c63c`, `d2d0b9d`, and `cfecf37` passed implementation and independent review |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user