Compare commits

...

26 Commits

Author SHA1 Message Date
539c75cb18 Record the first suite release implementation 2026-09-17 20:08:09 +00:00
fc8f5709b0 Mark public release validation complete 2026-09-17 20:07:08 +00:00
0e0034ef02 Mark collection release published 2026-09-17 20:03:11 +00:00
40ca08a352 Mark collection release candidate complete 2026-09-17 19:20:26 +00:00
956c50cc2f Mark pipeline role release published 2026-09-17 19:16:27 +00:00
e24e8d0d05 Mark application role tags published 2026-09-17 18:57:34 +00:00
943ece7a65 Mark application role release validation complete 2026-09-17 18:56:42 +00:00
b98fb5783f Plan the first coordinated suite release 2026-09-17 18:44:56 +00:00
253d283234 Complete the D&D collection assembly 2026-09-17 14:24:03 +00:00
8f57e1bcf5 Mark Feature 0012 handoff complete 2026-09-17 03:46:56 +00:00
b359eee321 Record the Feature 0012 implementation 2026-09-17 03:46:47 +00:00
2b1448ab91 Mark collection integration testing complete 2026-09-17 03:46:10 +00:00
ec3c0b9706 Mark pipeline subtree import complete 2026-09-17 03:32:19 +00:00
1a81db660e Mark collection foundation stage complete 2026-09-17 03:30:14 +00:00
bc1cf31f0e Mark collection usage documentation complete 2026-09-17 03:28:59 +00:00
9a86cdb57e Plan the D&D collection assembly 2026-09-17 03:26:04 +00:00
54a2362c02 Close Feature 0011 after remediation 2026-09-16 21:37:17 +00:00
d2bd48cc99 Record the pipeline credential implementation 2026-09-16 20:06:35 +00:00
731a799873 Mark pipeline credential documentation stage complete 2026-09-16 20:06:05 +00:00
bbc8d25d64 Mark pipeline credential delivery stage complete 2026-09-16 19:51:05 +00:00
9b0949f2ac Mark Narratio upgrade stage complete 2026-09-16 19:24:46 +00:00
358051af98 Prepare the managed credential implementation sprint 2026-09-16 19:12:42 +00:00
6d9b4b87f8 Complete the D&D Notarius integration feature 2026-09-15 22:19:28 +00:00
7ac9220e87 Record the D&D Notarius integration implementation 2026-09-15 21:01:19 +00:00
7f8ce88b43 Record documentation and testing completion 2026-09-15 21:00:45 +00:00
5b2effd68a Record completion of the D&D pipeline integration 2026-09-15 20:49:10 +00:00
9 changed files with 1899 additions and 581 deletions

View File

@@ -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.

View File

@@ -1,6 +1,6 @@
# Feature 0010: D&D Notarius Extraction Integration # Feature 0010: D&D Notarius Extraction Integration
Status: ready Status: done
## Summary ## Summary

View File

@@ -0,0 +1,389 @@
# Feature 0011: Managed Pipeline Credentials and Notarius Reuse
Status: done
## 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 from environment-variable names
to string file contents. Each supplied entry means that the named credential
file must be present with that content; 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 values as strings
before constructing a destination path.
- Write supplied credential files as the selected runtime user and group with
mode `0640`.
- Suppress credential values from Ansible task output during validation,
creation, and updates.
- 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, 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 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 }}"
```
The role owns only the supplied named entries for this invocation 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.
- Credential values are written as supplied strings. ConfigKit and the typed
application reference own any nonempty-value requirement when a credential
is selected for use.
- 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, and one copy loop for supplied entries. 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.
Omitted files remain unmanaged so consumers can combine Ansible-managed
credentials with another provisioning mechanism. Credential removal and
directory mirroring remain outside this feature until an operator-facing
lifecycle requirement is expressly selected.
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 string values.
- Invalid names and non-string values fail before any destination outside the
declared secret directory can be constructed.
- Supplied entries converge to regular files with the selected runtime
ownership and mode `0640`; 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.
- A distinctive synthetic secret never appears in captured integration output.
- The baseline credential application reports `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 an explicit credential-removal or directory-lifecycle contract if an
operator need is identified.
- Add platform-specific mandatory-access-control policy for credential files.

View File

@@ -0,0 +1,304 @@
# Feature 0012: Assemble the D&D Collection
Status: done
## Summary
Turn the existing `ansible-collection-dnd` repository into a valid, buildable
`rakestraw.dnd` Ansible collection that exposes the independently developed
pipeline role as `rakestraw.dnd.pipeline`. The collection will carry a
self-contained snapshot of the pipeline role, publish the collection
dependencies Ansible can resolve natively, and provide one consumer bootstrap
manifest for the five Git-hosted application roles.
## Problem or Opportunity
The standalone application roles and the opinionated pipeline role are now
implemented and independently tested, but the collection repository still
contains only a placeholder README and repository metadata. A consumer cannot
build or install `rakestraw.dnd`, invoke the intended fully qualified role
name, or reproduce the reviewed combination of application-role dependencies
from that repository.
The pipeline role must remain independently developed, versioned, and usable.
At the same time, the collection artifact must contain the role it advertises;
it cannot depend on a sibling checkout, a symbolic link, or workspace-only
tooling at runtime. The assembly boundary therefore needs an explicit,
repeatable source-import convention and focused integration coverage of the
packaged result.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs collection metadata,
dependency declarations, documentation, and the preference for native
Ansible packaging behavior.
- [The testing house style](../../testing.md) governs behavior-oriented,
state-based validation and the avoidance of tests that merely restate file
layout or implementation details.
- [The MVP roadmap](../mvp.md) establishes the collection name, independently
released role repositories, Git-hosted application-role dependencies, and
the collection as the compatibility record for an assembled release.
- Features [0006](0006-pipeline-role-composition-foundation.md) through
[0011](0011-managed-pipeline-credential-delivery.md) define the pipeline
role behavior being assembled; this feature does not reopen those contracts.
## Scope
- Add valid Ansible Galaxy metadata for collection namespace `rakestraw`, name
`dnd`, development version `0.1.0`, the repository's existing license and
README, and its supported Ansible version.
- Declare the exact `ansible.posix` and `community.general` versions already
selected by the pipeline role as collection dependencies.
- Import the complete standalone pipeline-role repository into
`roles/pipeline` as a squashed Git subtree at an explicitly reviewed commit.
- Treat `ansible-role-dnd-pipeline` as authoritative: changes are made and
reviewed there first, then deliberately imported into the collection. Do
not edit role behavior directly beneath the collection's subtree prefix.
- Document the initial subtree import and subsequent update commands so the
source relationship is reproducible without custom tooling or private
knowledge.
- Ensure the standalone pipeline role's collection-facing documentation
distinguishes its standalone role name and invocation from
`rakestraw.dnd.pipeline` use without changing its public behavior.
- Add `meta/runtime.yml` with `requires_ansible: ">=2.18.0"`, matching the
implemented roles' supported baseline.
- Add one root `requirements.yml` that combines the five Git-hosted
application-role dependencies with the two collection dependencies needed
to bootstrap the assembled suite.
- Pin application roles to the exact reviewed commits already selected by the
standalone pipeline role during development. Keep the root bootstrap
manifest and the imported role's dependency manifests consistent.
- Configure collection builds to omit development-only content embedded in the
role subtree, including its integration suite, local Ansible configuration,
and nested dependency manifests. Retain operator-facing role documentation
and licensing in the source collection unless Ansible packaging requires
otherwise.
- Replace the collection's placeholder README with concise instructions for
dependency bootstrap, collection build and installation, FQCN invocation,
subtree provenance and updates, supported platform, and the distinction
between development commit pins and future released role tags.
- Add a focused collection integration suite that starts with isolated role
and collection paths, installs the root bootstrap manifest and the locally
built collection artifact, invokes `rakestraw.dnd.pipeline`, validates the
assembled pipeline through the applications' native configuration
interfaces, and verifies an immediate second application converges with no
reported changes.
## Non-goals
- Publishing the collection to Ansible Galaxy, Automation Hub, Gitea, or any
other registry.
- Creating the first collection release tag or application-role release tags.
- Replacing development commit pins with immutable role tags before those tags
exist.
- Vendoring any of the five standalone application roles into the collection.
- Moving authoritative pipeline-role development into the collection
repository or permitting collection-local role forks.
- Changing pipeline defaults, host convergence, application versions,
application configuration, asset deployment, credentials, or runtime
behavior.
- Adding collection plugins, modules, filters, playbooks, execution
environments, CI workflows, release automation, or a general-purpose sync
framework.
- Repeating every standalone pipeline integration scenario inside the
collection suite or asserting the exact contents of metadata and manifests
as an implementation snapshot.
- Supporting installation without network access. The collection artifact is
self-contained for the pipeline role, but its declared external role and
collection dependencies must still be made available to Ansible.
## Target End State
The collection repository has this durable shape:
```text
ansible-collection-dnd/
├── galaxy.yml
├── meta/
│ └── runtime.yml
├── requirements.yml
├── roles/
│ └── pipeline/ imported pipeline-role subtree
├── tests/
│ ├── converge.yml
│ ├── integration assembled-artifact behavior test
│ └── inventory
├── LICENSE
└── README.md
```
`ansible-galaxy collection build` produces a valid
`rakestraw-dnd-0.1.0.tar.gz` artifact. After the documented bootstrap installs
the root dependency manifest and the built artifact into clean Ansible paths,
a consumer can invoke:
```yaml
- name: Install and configure the D&D transcript pipeline
hosts: pipeline_hosts
roles:
- role: rakestraw.dnd.pipeline
```
The collection contains ordinary role files at `roles/pipeline`; it has no
runtime link to the standalone repository. Git history records that directory
as a squashed subtree import from `ansible-role-dnd-pipeline`. Maintainers make
pipeline changes in the standalone repository, validate and commit them there,
then update the collection subtree from the desired reviewed commit.
The root bootstrap manifest is the consumer-facing compatibility manifest for
development. It contains the same five application-role sources and reviewed
commit pins as the imported pipeline role, plus exact versions of
`ansible.posix` and `community.general`. The collection's Galaxy metadata also
declares those two collection dependencies because Ansible can resolve them as
native collection dependencies. This intentional duplication serves two
different installation boundaries and must remain consistent.
Development-only files may remain in the subtree source for faithful
provenance, but they are excluded from the built artifact. The collection's
own integration suite exercises the artifact rather than the repository role
directory, with role and collection paths isolated from ordinary user
installations.
## Repository Ownership
- `ansible-collection-dnd` owns collection metadata, the consumer bootstrap
manifest, the imported pipeline snapshot, collection-facing documentation,
build exclusions, and assembled-artifact integration coverage.
- `ansible-role-dnd-pipeline` remains authoritative for all pipeline-role code,
defaults, templates, dependency metadata, standalone documentation, and its
comprehensive integration suite. This feature changes only the wording
needed to document both standalone and collection use.
- The five standalone application-role repositories remain authoritative for
their roles and are read-only inputs to this feature.
- `campaigns` and `narratio-prompts` remain independently managed asset
repositories and are read-only integration inputs.
- `ansible-workspace-dnd` owns this feature roadmap, progress tracking, and the
later independent review record.
- Application source repositories and `rakestraw-ansible` remain unchanged.
## Constraints and Settled Decisions
- The collection is `rakestraw.dnd`; the bundled role's FQCN is
`rakestraw.dnd.pipeline`.
- A squashed Git subtree is the selected incorporation mechanism. It yields a
normal, self-contained collection artifact while preserving an auditable
upstream relationship and avoiding submodule checkout requirements,
symbolic links, manual copying, or custom synchronization state.
- The subtree prefix is `roles/pipeline`, and the standalone pipeline
repository remains the only place where role behavior is authored.
- The first development build uses collection version `0.1.0`. This version
enables ordinary Galaxy build and install validation but does not itself
authorize publication or establish a release tag.
- Development dependencies use exact reviewed commits. A later release pass
must replace all application-role commit pins with immutable role release
tags and revalidate the assembled artifact before publishing.
- Collection dependencies remain exactly `ansible.posix` 2.2.0 and
`community.general` 13.3.0, matching the existing reviewed pipeline
manifests.
- Galaxy metadata cannot install arbitrary standalone Git roles. The root
unified requirements manifest and documented bootstrap are therefore part
of the collection's public installation contract.
- The collection integration suite must not receive dependencies from the
developer's normal Ansible paths. Its success must demonstrate that the
documented manifest and built artifact are sufficient.
- The collection suite owns only the packaging boundary: buildability,
dependency bootstrap, FQCN resolution, representative assembled behavior,
native configuration acceptance, and convergence. Detailed pipeline feature
matrices remain in the standalone role's tests.
- The collection does not add probes, manifests, checksums, copied-file
comparisons, or private state to police the subtree. Git and the documented
subtree workflow are the provenance mechanism.
## Simplest Viable Implementation
Use Ansible's conventional collection layout and metadata directly. Import the
reviewed pipeline repository with ordinary `git subtree add --squash`, then
exclude only the subtree's development fixtures and nested bootstrap files
from Galaxy builds. No wrapper role, generated role, symbolic link, submodule,
or synchronization script is required.
Derive the root unified dependency manifest directly from the pipeline role's
two existing manifests. The only deliberate duplication is the collection
dependency declaration in `galaxy.yml`, because the artifact and the source
bootstrap have distinct native Ansible dependency interfaces.
Use one representative integration path: build into a temporary directory,
install dependencies and the artifact into isolated temporary Ansible paths,
apply `rakestraw.dnd.pipeline` using the same offline synthetic inputs already
proven by the standalone suite, run native application configuration
validation, and apply the play a second time to assert `changed=0` and
`failed=0`. This tests the behavior unique to collection assembly without
duplicating the standalone role's full test matrix.
## Rationale and Alternatives
A squashed subtree is preferable to a Git submodule because Ansible collection
archives require real role content and should build correctly from an ordinary
checkout without a second initialization step. It is preferable to a symbolic
link because archive behavior and installed collection paths would be fragile.
It is preferable to an unrecorded copy because subtree history retains the
source relationship and provides a standard update command. Squashing avoids
injecting the pipeline repository's entire development history into the
collection while still recording each reviewed import.
Moving the role permanently into the collection would simplify assembly, but
would discard the settled requirement that the suite role remain independently
developed, tested, versioned, and usable. A thin collection wrapper that
depends on `rakestraw.dnd_pipeline` would avoid source import but would not
actually bundle the role or satisfy the desired FQCN without adding another
runtime dependency layer.
Keeping one unified root requirements file gives consumers one bootstrap
command for both dependency kinds. Retaining the imported role's own
requirements files in source preserves standalone repository fidelity; build
exclusion prevents those nested development interfaces from confusing users
of the installed artifact.
## Acceptance Criteria
- The collection repository is recognized by `ansible-galaxy` as
`rakestraw.dnd` version `0.1.0` and builds successfully from a clean checkout.
- The built archive contains `roles/pipeline` and excludes the imported role's
development-only integration suite, local Ansible configuration, and nested
dependency manifests.
- The role content at `roles/pipeline` is traceable to a documented reviewed
commit of `ansible-role-dnd-pipeline` through the repository's squashed
subtree history.
- The standalone pipeline README accurately documents both
`rakestraw.dnd_pipeline` and `rakestraw.dnd.pipeline` consumption without
changing role behavior.
- `meta/runtime.yml` selects Ansible 2.18 or newer, and Galaxy metadata declares
the exact two collection dependencies used by the pipeline.
- The root bootstrap manifest contains all five standalone application roles
at the same reviewed commits used by the imported pipeline role and the
exact two required collections.
- Collection documentation provides sufficient commands to install the
bootstrap dependencies, build and install the artifact, invoke the pipeline
FQCN, and update the subtree from a future reviewed pipeline commit.
- The integration suite starts with isolated Ansible role and collection
paths, installs only the declared bootstrap inputs and built artifact, and
resolves `rakestraw.dnd.pipeline` without access to a sibling role checkout.
- The representative assembled deployment passes the applications' native
configuration validation and an immediate identical second run reports
`changed=0` and `failed=0`.
- Existing standalone pipeline-role validation continues to pass after its
documentation-only change.
- No application role, application source, asset behavior, or pipeline host
convergence behavior changes as part of this feature.
## Dependencies and Follow-up Work
- Features 0001 through 0011 and their reviewed role commits are prerequisites.
- A subsequent release feature must create immutable role tags, replace
development commit pins, select the release collection version, validate the
tagged combination, create release notes and tags, and publish or distribute
the artifact.
- CI automation may later run the collection integration suite after a local,
repeatable workflow exists.
## Potential Future Hardening
- Sign collection artifacts or publish checksums and software bills of
materials when a distribution threat model requires them.
- Automate subtree provenance checks and dependency-pin synchronization if
manual collection updates become frequent enough to justify that machinery.

View File

@@ -0,0 +1,285 @@
# Feature 0013: Publish the First Coordinated Suite Release
Status: in_progress
## Summary
Publish the reviewed D&D pipeline as the first immutable, remotely installable
release of its five application roles, standalone pipeline role, and
`rakestraw.dnd` collection. The release establishes `v0.1.0` tags in the
projects' public Gitea repositories, replaces development commit pins with
those role tags, and makes the built `rakestraw-dnd-0.1.0.tar.gz` collection
artifact available from the collection's Gitea release.
## Problem or Opportunity
The application roles, pipeline role, and collection have been implemented,
reviewed, and tested as one compatible suite. Their current dependency
manifests still select application roles by development commit, however, and
none of the seven Ansible repositories has an immutable release tag. The
collection documentation consequently describes a development build rather
than a published release, and a consumer cannot bootstrap the reviewed suite
entirely from named releases and a published collection artifact.
The initial release should turn the existing reviewed compatibility set into a
durable public installation boundary without changing application behavior or
introducing release automation. It must prove that the release is consumable
from Gitea alone rather than from sibling repositories or unpublished local
artifacts.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs dependency manifests,
collection packaging, and concise consumer documentation.
- [The testing house style](../../testing.md) governs release validation. The
feature reuses behavior-oriented repository suites and adds only validation
specific to the remote publication boundary.
- [The planning policy](../../planning.md) governs the cross-repository
implementation and review workflow.
- [The MVP roadmap](../mvp.md) defines independent role releases, immutable
release pins, the collection as the compatibility record, and public Gitea
as the release source.
- [Feature 0012](0012-collection-assembly.md) defines the authoritative
pipeline subtree, unified consumer manifest, and assembled-artifact testing
boundary that this feature releases without redesigning.
## Scope
- Publish `v0.1.0` as the initial release of each standalone application role:
`rakestraw.audita`, `rakestraw.narratio`, `rakestraw.notarius`,
`rakestraw.seriatim`, and `rakestraw.scriptorium`.
- Point those application-role tags at the exact reviewed commits already
selected by the pipeline compatibility manifest. No application-role code
or default changes are part of release preparation.
- Replace the five development commit pins in the authoritative pipeline
role's root dependency manifest with the corresponding immutable `v0.1.0`
role tags.
- Update the pipeline documentation to describe the released dependency pins
and its standalone installation path without changing its role interface or
runtime behavior.
- Validate and publish `v0.1.0` of the standalone pipeline role after its
release manifest and documentation are complete.
- Import the published pipeline `v0.1.0` state into the collection's
`roles/pipeline` subtree using the established remote-only, squashed subtree
workflow.
- Replace the collection's five application-role commit pins with the same
`v0.1.0` tags used by the authoritative pipeline role, retaining the exact
`ansible.posix` and `community.general` version pins already selected.
- Retain collection version `0.1.0` in `galaxy.yml`, update collection
documentation from development-build language to released installation
instructions, and identify the release as the compatibility record for the
seven selected component versions.
- Create and push public, immutable `v0.1.0` tags for all seven Ansible
repositories.
- Build `rakestraw-dnd-0.1.0.tar.gz` from the tagged collection content and
create a concise public Gitea `v0.1.0` collection release whose attachment
is that exact artifact.
- Validate that a clean consumer can obtain the tag-pinned dependency manifest
and collection archive from their public Gitea URLs, install them into
isolated Ansible paths, invoke `rakestraw.dnd.pipeline`, and obtain an
immediate clean repeat.
- Record the completed release and its immutable compatibility set in the
workspace status and durable release-facing documentation.
## Non-goals
- Changing application versions, role defaults, pipeline configuration,
filesystem policy, credentials, assets, or deployed runtime behavior.
- Synchronizing future versions of independently released roles. The shared
initial version is a convenient baseline, not a lockstep release policy.
- Publishing the collection to Ansible Galaxy, Automation Hub, or another
package registry.
- Vendoring the five application roles into the collection or changing the
selected pipeline subtree model.
- Adding CI/CD, a release script, a changelog generator, dependency-update
automation, or a general-purpose release framework.
- Adding tests that snapshot manifest text, tag names, defaults, task traces,
or other implementation details. Release validation should exercise the
public installation and deployed behavior.
- Signing tags or artifacts, generating checksums or software bills of
materials, mirroring dependencies, or adding other supply-chain hardening.
- Defining upgrade, downgrade, removal, scheduling, or optional human-operator
account management.
## Target End State
Each public application-role repository has an immutable `v0.1.0` tag for the
exact role revision already reviewed as part of the assembled suite:
| Role | Released revision |
| --- | --- |
| `rakestraw.audita` | `66ebea9a47ce82bfdbdc5e2855f3dfaaff8e2a16` |
| `rakestraw.narratio` | `292d8669e7aad5cfe80b0c469d22b6177e8cf0f1` |
| `rakestraw.notarius` | `14a38e04e35ef524d6a97fa7fb5a04981a0a2161` |
| `rakestraw.seriatim` | `e08c63c0b078658bdfa2d10a2e6e1e4f9372a075` |
| `rakestraw.scriptorium` | `8b4c86e48e7d8655e479b26dc510bf01683a0c8f` |
The standalone pipeline role has its own immutable public `v0.1.0` tag. Its
role dependency manifest selects all five application roles with
`version: v0.1.0`, and its collection dependency manifest retains
`ansible.posix` 2.2.0 and `community.general` 13.3.0. The pipeline release is
independently installable under `rakestraw.dnd_pipeline`.
The collection's `roles/pipeline` subtree is a faithful squashed import of the
published pipeline `v0.1.0` release. Its consumer-facing `requirements.yml`
contains the same five role tags and collection versions as the standalone
pipeline manifests. `galaxy.yml` remains version `0.1.0`, and the collection
repository has an immutable `v0.1.0` tag and corresponding public Gitea
release to carry the built artifact.
The collection release includes the archive produced from that released tree,
named `rakestraw-dnd-0.1.0.tar.gz`. Its public release notes identify the exact
five application-role versions, pipeline-role version, native collection
dependencies, supported platform, and consumer bootstrap steps. A consumer
can fetch the tagged manifest and archive through public Gitea URLs and
install the suite without access to this development workspace.
## Repository Ownership
- The five standalone application-role repositories own their respective
`v0.1.0` tags. Their reviewed role content remains unchanged by this
feature.
- `ansible-role-dnd-pipeline` owns its tag-pinned role manifest, standalone
release documentation, and `v0.1.0` tag.
- `ansible-collection-dnd` owns the released pipeline subtree, unified
tag-pinned consumer manifest, collection release documentation, collection
tag, built artifact, and Gitea release attachment.
- `ansible-workspace-dnd` owns this roadmap, cross-repository compatibility
record, active implementation plan, progress tracking, and independent
release review.
- The application source repositories, campaign repository, prompt-library
repository, and `rakestraw-ansible` are unchanged release inputs.
## Constraints and Settled Decisions
- Public repositories beneath
`https://gitea.maximumdirect.net/eric/` are the authoritative publication
channel for this release.
- Every Ansible repository uses initial release tag `v0.1.0`. The collection's
Galaxy version remains the corresponding unprefixed `0.1.0`, as required by
collection metadata and artifact naming.
- Tags are immutable release boundaries. A release candidate must be validated
before its tag is created and pushed; published tags must not be moved to
repair a failed release.
- The five application-role tags identify the exact reviewed commits shown in
the target end state. Release metadata must not create otherwise unnecessary
commits in those repositories.
- Released role dependency manifests use tag names, not branches or commit
hashes. Application repositories remain independently versioned after this
shared initial baseline.
- The pipeline repository remains authoritative. Its release must be pushed
to Gitea before the collection imports the `v0.1.0` revision through the
documented remote-only subtree command.
- The collection tag identifies the exact source tree from which the attached
artifact is built. The attached file must not be rebuilt from a later or
dirty tree while retaining the same version.
- The public collection release attachment is the selected binary publication
interface. The repository tag remains the source publication interface.
- Consumer validation must not use sibling checkouts, normal user Ansible
paths, preinstalled project roles, or an unpublished local collection
archive.
- The collection's Gitea release description and existing repository
documentation are
sufficient for the initial release. This feature does not introduce
repository-local changelog files solely to duplicate those notes.
## Simplest Viable Implementation
Use ordinary Git tags, one collection Gitea release, existing Ansible
dependency manifests, the established subtree command, and `ansible-galaxy
collection build`. The five application roles need validation and tags only.
The pipeline and collection need small manifest and documentation changes
before their respective release tags are created.
Reuse the existing repository-local integration entry points as release gates.
The collection integration suite already exercises isolated dependency
bootstrap, archive construction and installation, FQCN resolution, native
application behavior, and clean repeated convergence. Adapt its inputs only as
necessary to consume the release tags, and use a focused final smoke path to
download the published manifest and attached archive from Gitea. Do not add a
second release framework or duplicate the detailed behavior matrices owned by
the standalone repositories.
Publication is intentionally manual for the first release. The work does not
yet justify release scripts, workflow files, persistent staging state, or a
new packaging service.
## Rationale and Alternatives
Immutable role tags give consumers meaningful versions while preserving the
settled model of independently released repositories. Publishing only commit
hashes would be reproducible but would not establish the named release
contract required by the MVP. Publishing branches would not be immutable.
Using `v0.1.0` for every initial role and the collection makes the first
compatibility baseline easy to understand. Future role releases remain
independent, and future collection releases record whatever combination is
then supported; no synchronized-version policy is implied.
Attaching the Galaxy-built archive to the public Gitea collection release
provides a direct installation artifact without introducing another registry.
Requiring consumers to clone and build the collection would expose unnecessary
development steps, while publishing to Ansible Galaxy or Automation Hub would
add an unselected distribution channel and account lifecycle.
Manual publication is appropriate for one initial release and keeps the
release contract visible. Automation can be considered after repeated release
work demonstrates a stable process worth encoding.
## Acceptance Criteria
- Each application-role repository advertises a public, immutable `v0.1.0`
tag at the exact reviewed revision listed in this roadmap.
- Each application role's existing syntax, lint, integration, and clean-repeat
validation passes for the candidate being tagged; no role behavior is
changed merely to create the release.
- The pipeline role's released manifest selects all five application roles by
`v0.1.0`, and its collection dependency versions remain unchanged.
- The pipeline's existing validation installs its application-role
dependencies from the public Gitea tags, exercises the role through its
public interface, and passes its immediate clean repeat.
- The pipeline repository advertises a public, immutable `v0.1.0` tag at the
validated release commit.
- The collection subtree matches the published pipeline `v0.1.0` tree outside
repository-specific Git metadata and records the remote Gitea import in Git
history.
- The collection's root manifest uses the same five `v0.1.0` application-role
pins and exact native collection versions as the released pipeline role.
- `ansible-galaxy collection build` from the collection release candidate
produces `rakestraw-dnd-0.1.0.tar.gz`, and the existing artifact-boundary
exclusions remain effective.
- The collection's existing integration suite passes against the release
candidate, including isolated bootstrap, installed-artifact FQCN use,
representative native application checks, and immediate `changed=0` and
`failed=0` convergence.
- The collection repository advertises a public, immutable `v0.1.0` tag and
matching Gitea release. The archive attached to that release is the artifact
built from the tagged tree.
- A clean remote-only smoke validation downloads the public tag-pinned
manifest and public collection attachment, installs into isolated paths,
resolves `rakestraw.dnd.pipeline`, and completes with a clean immediate
repeat without referencing any sibling repository or unpublished artifact.
- Release-facing documentation no longer describes collection `0.1.0` or the
role release tags as future or unpublished, and it gives the complete public
Gitea installation path without requiring the development workspace.
- All participating repositories are clean, their release commits and tags
are present upstream, and workspace status records the published
compatibility baseline.
## Dependencies and Follow-up Work
Feature 0012 and its remediation must remain complete. Credentials capable of
pushing commits and tags and creating the public collection Gitea release and
attachment must be available during implementation.
Potential later features include release automation, publication to an Ansible
registry, independently versioned follow-up releases, optional suite-level
operator membership management, and defined upgrade, downgrade, or removal
behavior. None is required for the initial release.
## Potential Future Hardening
- Signed Git tags or release artifacts.
- Published checksums, provenance attestations, or software bills of
materials.
- Automated verification and publication in a controlled CI environment.

File diff suppressed because it is too large Load Diff

View File

@@ -106,6 +106,13 @@ role will manage the native configuration needed to connect to it.
- The collection bundles and exposes the independently developed suite-level - The collection bundles and exposes the independently developed suite-level
role as `rakestraw.dnd.pipeline`, providing one opinionated interface for role as `rakestraw.dnd.pipeline`, providing one opinionated interface for
consumers. consumers.
- The collection incorporates the pipeline role at `roles/pipeline` as a
squashed Git subtree. The standalone pipeline repository remains
authoritative; maintainers change and validate the role there, then import
a reviewed commit into the collection rather than editing the subtree copy.
- The subtree makes the collection artifact self-contained for its bundled
role without requiring submodule initialization, symbolic links, sibling
repositories, or custom synchronization tooling.
- The pipeline role owns compatible application-version selection, - The pipeline role owns compatible application-version selection,
cross-application configuration, D&D campaign deployment, prompt-library cross-application configuration, D&D campaign deployment, prompt-library
deployment, operator access, the pipeline-wide secret-delivery policy, and deployment, operator access, the pipeline-wide secret-delivery policy, and
@@ -135,6 +142,10 @@ role will manage the native configuration needed to connect to it.
collection dependencies. During active development, the Git roles are collection dependencies. During active development, the Git roles are
pinned to reviewed commits; released manifests replace those commits with pinned to reviewed commits; released manifests replace those commits with
immutable role release tags. immutable role release tags.
- The collection supplies one consumer-facing root `requirements.yml` that
combines those same Git-hosted role pins with the shared collection
dependencies. Its Galaxy metadata separately declares the native collection
dependencies that Ansible can resolve while installing a collection.
- The pipeline role composes the five roles through ordinary Ansible role - The pipeline role composes the five roles through ordinary Ansible role
dependency metadata. It exposes suite-prefixed variables for the small set dependency metadata. It exposes suite-prefixed variables for the small set
of values the suite must coordinate, and does not duplicate every downstream of values the suite must coordinate, and does not duplicate every downstream
@@ -172,13 +183,24 @@ application-role releases in one source repository.
- Development dependency manifests may temporarily refer to branches or - Development dependency manifests may temporarily refer to branches or
commits while the roles are changing rapidly. commits while the roles are changing rapidly.
- The projects' public repositories beneath
`https://gitea.maximumdirect.net/eric/` are the authoritative release
sources. Standalone roles are published through immutable Git tags.
- Every released dependency manifest must pin each Git-hosted role dependency - Every released dependency manifest must pin each Git-hosted role dependency
to an immutable role release tag. to an immutable role release tag.
- The collection release is the compatibility record for the exact set of - The collection release is the compatibility record for the exact set of
application-role versions it composes. application-role versions it composes.
- A collection release consists of its immutable repository tag, matching
Gitea release, and the `ansible-galaxy collection build` archive produced
from that tagged tree and attached to the Gitea release.
- Collection integration tests must install and exercise the same pinned role - Collection integration tests must install and exercise the same pinned role
combination delivered to consumers, starting from an environment in which combination delivered to consumers, starting from an environment in which
the dependencies are not already installed. the dependencies are not already installed.
- Collection integration tests build and install the collection artifact into
isolated Ansible paths, resolve `rakestraw.dnd.pipeline`, validate one
representative assembled deployment through native application interfaces,
and confirm immediate convergence. Detailed pipeline feature matrices remain
the standalone pipeline role's testing responsibility.
- Updating one application role in the suite requires updating its pinned - Updating one application role in the suite requires updating its pinned
version in the collection, validating the assembled suite, and releasing a version in the collection, validating the assembled suite, and releasing a
new collection version. Unrelated application-role repositories remain new collection version. Unrelated application-role repositories remain
@@ -255,9 +277,28 @@ 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 from valid
environment-variable names to string file contents. Supplied entries manage
the corresponding files; omitted names remain unmanaged. Credential values
are expected to come from encrypted inventory such as Ansible Vault and are
suppressed from task output. Credential removal and directory mirroring are
outside the MVP.
- 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 +350,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
@@ -376,10 +418,5 @@ managed host. The prompt-library checkout retains its upstream `prompts/` and
The following areas require investigation and decisions before implementation: The following areas require investigation and decisions before implementation:
- The mechanism used to incorporate the independently developed pipeline role
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
dependency and testing policies above

View File

@@ -1,90 +1,173 @@
# Feature 0009 Remediation Review # Feature 0012 Remediation Review
Status: resolved Status: resolved
Reviewed implementation commits: Reviewed implementation commits:
- `66ebea9 Make Audita configuration ownership configurable` - `600eb21 Document standalone and collection pipeline usage`
- `e9ae2dc Make Notarius configuration ownership configurable` - `3f7f82e Establish the D&D collection foundation`
- `8b4c86e Make Scriptorium configuration ownership configurable` - `c84aa0d Merge commit '5dbae8a' as 'roles/pipeline'`
- `eeb1105 Make Narratio configuration ownership configurable` - `10ad31c Test the assembled D&D collection`
- `901ae35 Apply shared configuration ownership to the D&D pipeline`
- `dddc5ee Manage shared pipeline access with ACLs`
- `f53da82 Test shared pipeline access across users`
- `608d5be Document the shared pipeline execution model`
## Review Summary ## Review Summary
The production architecture and behavioral coverage implement Feature 0009 as Feature 0012 implements the principal target architecture. The standalone
planned. The four standalone roles expose generic configuration ownership and pipeline repository remains authoritative, and collection history records its
mode controls, and the pipeline selects its opinionated service-owned, exact `600eb21` snapshot as a squashed subtree at `roles/pipeline`. The
world-readable policy through those interfaces. Narratio establishes the collection has valid Galaxy and runtime metadata, exact native collection
runtime identity first. The pipeline then installs ACL support and directly dependencies, one unified bootstrap manifest for the five Git-hosted roles,
converges access and default ACLs on the three existing shared roots. Focused focused build exclusions, and an isolated artifact-level integration entry
integration coverage exercises actual cross-identity configuration access and point. The collection builds as `rakestraw.dnd` 0.1.0 and exposes
bidirectional writes under a restrictive umask while preserving immediate clean `rakestraw.dnd.pipeline`.
convergence.
No production code or test-suite remediation is required. One small consumer Two low-severity issues were found and are now resolved. The collection's
documentation inconsistency remains. subtree maintenance examples derived a commit from the local sibling
repository but told Git to fetch that commit from a remote which did not
contain it at review time. Separately, the collection integration driver
repeated secret-redaction assertions already owned by the standalone pipeline
suite; those assertions did not validate collection assembly and strengthened
the collection test contract beyond the selected packaging boundary.
## Finding 1: Operator Support Is Documented Inconsistently ## Finding 1: Subtree Maintenance Commands Mix Local and Remote Sources
Severity: low Severity: low
`ansible-role-dnd-pipeline/README.md:201-217` first lists "operator access" as `ansible-collection-dnd/README.md:51-63` obtains `pipeline_commit` from
deferred, then correctly states that invocation by an existing member of the `../ansible-role-dnd-pipeline`, but passes the Gitea URL as the repository
selected runtime group is supported. The likely deferred concern is operator argument to both `git subtree add` and `git subtree pull`. The reviewed
selection and group-membership management, not operator access itself. pipeline commit was seven commits ahead of `origin/main` at review time; the
remote advertised `b15fe8d`, not imported commit `600eb21`. The documented
command therefore could not reproduce the current import.
The adjacent YAML fragment defines an otherwise unexplained The collection artifact already contains the imported role, so consumers do
`operator_group_members` variable but shows no consumer task or role that uses not run these commands or need a sibling checkout. The commands are the
it. As written, copying the example does not manage any membership and may lead maintainer-facing assembly interface and should also be portable outside this
a reader to believe that the pipeline role consumes that variable. workspace. The durable contract should therefore use Gitea exclusively: first
push the reviewed pipeline commit or tag to the authoritative repository, then
identify that remote revision explicitly and import it from the same URL.
### Required Remediation ### Required Remediation
- Replace "operator access" in the deferred list with the precise deferred - Remove the sibling-repository `git rev-parse` commands from both subtree
behavior: operator selection and group-membership management. examples.
- Replace the inert variable fragment with a concise, complete consumer-side - Define an explicit `pipeline_revision` placeholder representing a reviewed
example that actually adds a selected account to the runtime group, or omit commit or immutable tag that has already been pushed to Gitea, and pass that
the example and state the prerequisite directly. revision with the authoritative Gitea URL to both `git subtree add` and
- Keep human account and membership management outside the production pipeline `git subtree pull`.
role. - State concisely that a pipeline revision must be committed, reviewed, and
pushed to the authoritative repository before collection assembly imports
it. Do not prescribe a branch name or require a release tag during active
development; a pushed full commit ID remains valid.
- Do not add a configured remote, sibling-path assumption, synchronization
script, lock file, or private provenance state.
- Do not rewrite subtree history or reimport the current role. This is a
collection-owned documentation correction only.
- Confirm that Gitea contains the selected pipeline revision, then validate
the corrected initial command in a disposable Git repository without using
the local sibling repository as the subtree source.
## Finding 2: The Collection Test Duplicates Secret-Redaction Coverage
Severity: low
`ansible-collection-dnd/tests/integration:19-20` defines two synthetic values
solely so lines 74-75 can search the first convergence log for them. Secret-safe
task output is pipeline behavior established by Feature 0011 and already
covered by `ansible-role-dnd-pipeline/tests/integration`. The collection owns
artifact construction, bootstrap installation, FQCN resolution, representative
assembled behavior, and clean repeated convergence; it does not own a second
credential-redaction contract.
The implementation plan required synthetic credentials so native
configuration could be exercised without real provider values, but it did not
require the collection to retest Feature 0011 redaction. These two assertions
are therefore an inadvertent strengthening by the implementing agent and
conflict with the roadmap's instruction to keep detailed pipeline feature
coverage in the standalone role.
The native Seriatim, Audita, Notarius, Scriptorium, and Narratio checks are not
part of this finding. They are state-based, inexpensive, and implement the
roadmap's express requirement for representative native validation of the
assembled suite.
### Required Remediation
- Retain distinctive synthetic credential contents in the collection
convergence variables; no real credential or live provider call may enter
the suite.
- Remove the two shell variables used only for log searching and remove the two
secret-content grep assertions.
- Retain isolated dependency installation, archive boundary checks, FQCN
syntax and lint validation, the selected native application checks, and the
immediate `changed=0 failed=0` repeat.
- Do not replace the removed assertions with another collection-level
credential, log, file-content, or implementation-trace test.
## Resolution ## Resolution
Resolved in pipeline-role commit `b15fe8d`. The deferred-work summary now Resolved in collection commits `556b6ed` and `da67b34`.
names operator selection and group-membership management rather than operator
access. The shared-filesystem section retains existing-group-member invocation The collection README now uses an explicit `PUSHED_COMMIT_OR_TAG` revision and
as supported behavior and provides a complete consumer-owned the authoritative Gitea URL for both initial and subsequent subtree imports.
`ansible.builtin.user` example that adds a selected account to the runtime It states that the selected revision must be committed, reviewed, and pushed
group. No production role behavior changed. before collection assembly. The examples no longer inspect or depend on a
sibling checkout. A disposable repository successfully imported the exact
commit advertised by Gitea through the documented remote-only command shape.
The collection integration driver retains its distinctive synthetic
credential inputs but no longer defines separate values solely for log
searching or duplicates the standalone pipeline suite's two redaction
assertions. Its artifact, dependency, FQCN, native application, and clean
repeat coverage remain unchanged.
## Required Validation ## Required Validation
After the documentation correction, run: After remediation, run:
```text ```text
cd ansible-role-dnd-pipeline && tests/integration cd ansible-collection-dnd
bash -n tests/integration
tests/integration
git diff --check git diff --check
``` ```
The expected result remains successful native configuration checks, The result must demonstrate isolated dependency bootstrap, collection build
representative cross-identity access, and immediate repeats with `changed=0` and artifact installation, FQCN resolution, the retained native application
and `failed=0`. checks, and immediate clean convergence. The built artifact must still include
`roles/pipeline/tasks/main.yml` and exclude the selected development-only
subtree content.
Validate the corrected subtree example against Gitea in a disposable Git
repository without modifying the real collection history or relying on the
local sibling repository as the source. The standalone pipeline integration
suite does not need to be rerun for these collection-only documentation and
test-scope changes.
## Review Validation Evidence ## Review Validation Evidence
The independent review inspected the complete diffs for all eight stage The review compared the complete standalone pipeline repository with
commits and confirmed that every dependency pin resolves to the intended `roles/pipeline`; the trees are byte-for-byte identical outside Git metadata.
standalone-role commit. `git diff --check` passed across all five changed role The root bootstrap manifest's role and collection sections exactly match the
repositories. The complete pipeline `tests/integration` entry point passed its two imported pipeline manifests, and `galaxy.yml` declares the same native
isolated dependency installation, syntax check, production-profile lint, collection versions.
native application checks, cross-identity access exercise, configurable
profile and version cases, and immediate clean repeats. All repositories were
clean before this review document was revised.
After remediation, the complete pipeline integration entry point and A fresh collection build produced
`git diff --check` passed again. The test fixture was removed and the baseline `rakestraw-dnd-0.1.0.tar.gz`. The archive contains the pipeline task entry
Seriatim version and pipeline configuration were restored during cleanup. point and omits the selected nested tests, Ansible configuration, dependency
manifests, and Git ignore file. Installing that artifact into a temporary
collection path made `rakestraw.dnd.pipeline` discoverable. A separate
isolated bootstrap installed the unified requirements, after which syntax
checking and production-profile ansible-lint passed.
`bash -n ansible-collection-dnd/tests/integration`, manifest consistency
checks, `git diff --check`, and collection repository integrity checks also
passed during review.
After remediation, the remote-only subtree command successfully imported the
revision advertised by Gitea into a disposable repository, and a fresh
collection build succeeded. The complete collection integration entry point
then passed isolated dependency installation, artifact construction and
installation, syntax checking, production-profile lint, all retained native
application checks, and two recaps with `changed=0` and `failed=0`. The
standalone pipeline suite was not rerun because neither remediation changed
the authoritative pipeline role.

View File

@@ -1,11 +1,10 @@
# Workspace Status # Workspace Status
Last updated: 2026-09-15 Last updated: 2026-09-17
Current milestone: M1-03 suite-level pipeline role Current milestone: First coordinated suite release
Current focus: Publish the completed Notarius role revision required to resume Current focus: Independently review the Feature 0013 implementation.
Feature 0010.
| ID | Deliverable | Owner | State | Evidence or next step | | ID | Deliverable | Owner | State | Evidence or next step |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
@@ -16,8 +15,8 @@ Feature 0010.
| 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 | blocked | Publish the completed Notarius role revision, then resume Feature 0010 | | M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | done | Features 0006 through 0011 completed through remediation commit `de1b191` |
| M1-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism | | M1-04 | Collection assembly | ansible-collection-dnd | done | Implemented and independently reviewed through collection remediation commit `da67b34` |
| 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 |
| F0003 | Install and configure Notarius | ansible-role-notarius | done | Implemented and validated through remediation commit `eb4f511` | | F0003 | Install and configure Notarius | ansible-role-notarius | done | Implemented and validated through remediation commit `eb4f511` |
@@ -27,7 +26,10 @@ Feature 0010.
| F0007 | Deploy D&D campaigns and prompt assets | ansible-role-dnd-pipeline, campaigns, and narratio-prompts | done | Implemented and validated through remediation commit `7572fa3` | | F0007 | Deploy D&D campaigns and prompt assets | ansible-role-dnd-pipeline, campaigns, and narratio-prompts | done | Implemented and validated through remediation commit `7572fa3` |
| 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 | blocked | Stage 1 completed in Notarius role commit `14a38e04e35ef524d6a97fa7fb5a04981a0a2161`; publish it to the canonical origin before Stage 2 | | 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 | done | Implemented and independently reviewed through remediation commit `de1b191` |
| F0012 | Assemble the D&D collection | ansible-collection-dnd and ansible-role-dnd-pipeline | done | Pipeline `600eb21` assembled and validated through collection remediation commit `da67b34` |
| F0013 | Publish the first coordinated suite release | all Ansible repositories and workspace | in_progress | Public `v0.1.0` tags: Audita `66ebea9`, Narratio `292d866`, Notarius `14a38e0`, Seriatim `e08c63c`, Scriptorium `8b4c86e`, pipeline `7c2bad8`, collection `63e8f3f`; [collection release](https://gitea.maximumdirect.net/eric/ansible-collection-dnd/releases/tag/v0.1.0) |
| 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 |