Plan the standalone Narratio role
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
# Feature 0005: Narratio Source Installation and Configuration
|
||||
|
||||
Status: ready
|
||||
|
||||
## Summary
|
||||
|
||||
Provide a small, independently usable `rakestraw.narratio` role that installs
|
||||
Narratio from a pinned Git tag, builds its executable on the managed host,
|
||||
creates the application account and runtime directories, and manages its
|
||||
native pipeline configuration. Keep the role application-specific so the
|
||||
later suite role can supply D&D policy through its public interface without
|
||||
making the Narratio role responsible for the other applications or campaign
|
||||
content.
|
||||
|
||||
## Problem or Opportunity
|
||||
|
||||
The `ansible-role-narratio` repository contains only its initial README and
|
||||
license. Narratio is the command-line orchestrator for the transcript pipeline,
|
||||
so the complete suite cannot be composed until Narratio has an independently
|
||||
usable installation and configuration role.
|
||||
|
||||
The four completed downstream application roles establish the concise
|
||||
source-build pattern. Narratio can reuse that pattern, but its native contract
|
||||
also requires a deployment account, shared writable runtime areas, a campaign
|
||||
registry root, and a substantially larger pipeline configuration interface.
|
||||
This feature fixes those boundaries before suite composition begins.
|
||||
|
||||
## Governing Policies
|
||||
|
||||
- [The Ansible house style](../../ansible.md) governs the role implementation,
|
||||
public configuration interface, and template.
|
||||
- [The testing house style](../../testing.md) governs repository-local
|
||||
validation. Tests exercise role-owned behavior through public inputs and
|
||||
native application outcomes without snapshotting defaults, tracing tasks, or
|
||||
rechecking trusted-module postconditions.
|
||||
- [The MVP roadmap](../mvp.md) fixes the common source-build architecture,
|
||||
supported platform, filesystem layout, and standalone-role boundary.
|
||||
|
||||
## Scope
|
||||
|
||||
- Implement `ansible-role-narratio` as a conventional standalone role.
|
||||
- Support Ubuntu 26.04 on native `amd64` and `arm64` hosts.
|
||||
- Install Git and the official Go Snap with classic confinement when build
|
||||
dependency management is enabled.
|
||||
- Default the Go Snap channel to `1.26/stable`.
|
||||
- Check out immutable Narratio tag `v2.0.0` by default under
|
||||
`/usr/local/src/narratio`.
|
||||
- Build the native executable with Narratio's release build contract and
|
||||
install it at `/usr/local/bin/narratio`.
|
||||
- Rebuild when the Git checkout changes or the binary is absent.
|
||||
- Converge the source tree and installed binary to root ownership, with the
|
||||
binary at mode `0755`.
|
||||
- Create the `narratio` system group and system account with
|
||||
`/var/lib/narratio` as its home and a non-login shell.
|
||||
- Create the workspace, spool, and cache roots as group-writable,
|
||||
setgid directories owned by `narratio:narratio`.
|
||||
- Create the campaign registry as a root-managed, operator-readable content
|
||||
root; leave its contents to the suite role or another caller.
|
||||
- Manage `/usr/local/etc/narratio/pipeline.yml` as `root:narratio` with mode
|
||||
`0640` using one role-owned template.
|
||||
- Require the caller to supply the deployment-specific WhisperX transcription
|
||||
URL because Narratio has no valid universal value for this required field.
|
||||
- Give filesystem roots concrete role-owned defaults. Default other optional
|
||||
application settings to null and omit them until a caller supplies a
|
||||
non-null value, allowing Narratio to retain ownership of its built-in
|
||||
defaults.
|
||||
- Expose scalar fields individually. Expose native open-ended collections as
|
||||
one variable each, including publish outputs, Notarius references and
|
||||
outputs, and Scriptorium artifacts and artifact families.
|
||||
- Permit callers to compose those collection variables in inventory before
|
||||
assigning the final value; do not add role-owned merge or precedence logic.
|
||||
- Expose ConfigKit's explicit import list in the root document without taking
|
||||
ownership of the imported fragments or named profile overlays.
|
||||
- Keep defaults, argument specifications, README, metadata, collection
|
||||
dependency declaration, template, and focused integration tests aligned
|
||||
with this contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Installing or configuring Audita, Notarius, Seriatim, Scriptorium, WhisperX,
|
||||
or the complete D&D suite.
|
||||
- Populating campaign data, prompt libraries, profiles, schemas, or session
|
||||
documents.
|
||||
- Selecting D&D-specific pipelines, campaigns, models, prompts, artifacts,
|
||||
extraction lanes, publish rules, storage providers, or application paths.
|
||||
- Managing ConfigKit import fragments or named profile overlay files.
|
||||
- Managing credentials, secret values, a secrets directory, environment
|
||||
injection, or the pipeline-wide secret-delivery policy.
|
||||
- Adding human operator accounts to the `narratio` group; the suite role owns
|
||||
operator selection and membership.
|
||||
- A Narratio daemon, service unit, scheduler, or timer.
|
||||
- A raw mapping for the complete pipeline document, a template override, or a
|
||||
second parallel configuration interface.
|
||||
- Copying Narratio's built-in defaults into role defaults merely to render
|
||||
them back into YAML.
|
||||
- Decomposing open-ended artifact, artifact-family, reference, or output maps
|
||||
into variables for caller-defined keys.
|
||||
- Installing from published binary artifacts, cross-compiling, or supporting
|
||||
platforms outside the MVP.
|
||||
- Production execution of Narratio to validate its binary or configuration.
|
||||
- Detection of out-of-band binary modification, compiler changes, or fixed
|
||||
build-command changes.
|
||||
- Build fingerprints, checksums, sidecar state, staged replacement, manual Git
|
||||
cleanup, or special recovery for malformed or adversarial host state.
|
||||
|
||||
## Target End State
|
||||
|
||||
On a supported host, applying the role with the required
|
||||
`narratio_whisperx_transcribe_url` installs or confirms Git and Go, creates the
|
||||
Narratio account and filesystem roots, checks out Narratio `v2.0.0` at
|
||||
`/usr/local/src/narratio`, builds `/usr/local/bin/narratio`, and manages
|
||||
`/usr/local/etc/narratio/pipeline.yml`.
|
||||
|
||||
The baseline managed pipeline document contains only the caller's required
|
||||
WhisperX URL and the filesystem roots the role deliberately owns. Narratio
|
||||
continues to supply all other application defaults. When a caller sets an
|
||||
optional configuration variable, the corresponding native YAML field appears
|
||||
in the correct section. Null fields and parent mappings with no selected
|
||||
descendants are absent. Explicit false, zero, empty string, empty list, empty
|
||||
mapping, and other non-null values are serialized rather than silently
|
||||
omitted, leaving their native semantics to Narratio.
|
||||
|
||||
Native open-ended collections pass through without structural rewriting.
|
||||
Callers and composing roles may define fragments in separate inventory files
|
||||
and combine them with ordinary Ansible/Jinja expressions before assigning the
|
||||
final collection variable. The role does not merge fragments or define
|
||||
precedence among them.
|
||||
|
||||
The `narratio` account owns the mutable workspace, spool, and cache roots.
|
||||
Their setgid group-write permissions support later direct invocation by human
|
||||
operators whom the suite role adds to the `narratio` group. The root-managed
|
||||
campaign registry remains readable but not writable by those operators.
|
||||
|
||||
An immediate repeated application reports no changes. A changed checkout or a
|
||||
missing binary causes the build command to run. Account, directory, and
|
||||
configuration changes converge through their responsible Ansible modules and
|
||||
do not become build triggers.
|
||||
|
||||
## Repository Ownership
|
||||
|
||||
- `ansible-role-narratio` owns the role implementation, application account,
|
||||
runtime and campaign-root state, public variables, native root pipeline
|
||||
serialization, metadata, dependency declaration, documentation, and
|
||||
repository-local tests.
|
||||
- `../narratio` is the read-only authority for release, build, CLI,
|
||||
configuration, filesystem, and integration contracts.
|
||||
- `rakestraw-ansible` is a read-only style and historical deployment reference.
|
||||
- `ansible-role-dnd-pipeline` will later own compatible application versions,
|
||||
D&D-specific Narratio values, campaign and prompt content, secret delivery,
|
||||
and human operator membership through the standalone roles' public
|
||||
interfaces.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the eventual staged implementation
|
||||
plan, and aggregate status.
|
||||
- All other repositories remain unchanged.
|
||||
|
||||
## Constraints and Settled Decisions
|
||||
|
||||
- The selected default release is lightweight tag `v2.0.0`, resolving to
|
||||
commit `ed4623bc415901134c765fe9cf06d59aa7891500`.
|
||||
- The release declares Go 1.26.0. The suite-standard `1.26/stable` Go Snap
|
||||
channel satisfies that requirement.
|
||||
- The native build uses package `./cmd/narratio`, `CGO_ENABLED=0`,
|
||||
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flags
|
||||
`-s -w -X gitea.maximumdirect.net/eric/narratio/internal/buildinfo.Version=<version>`.
|
||||
- `narratio version` reports the embedded selected tag and provides the native
|
||||
observable for an explicitly requested version in integration tests.
|
||||
- Narratio discovers `/usr/local/etc/narratio/pipeline.yml` before
|
||||
`/etc/narratio/pipeline.yml`; the role manages the first path by default.
|
||||
- `whisperx.transcribe_url` is the only pipeline field without an application
|
||||
default that is required for pipeline validation. The role therefore exposes
|
||||
`narratio_whisperx_transcribe_url` as a required public input rather than
|
||||
inventing a deployment endpoint.
|
||||
- Workspace, campaign, spool, and cache roots are concrete role defaults
|
||||
because the role creates and owns the corresponding filesystem state. These
|
||||
are intentional deployment policy, not a duplicate database of application
|
||||
defaults.
|
||||
- All other optional configuration variables use YAML null defaults and
|
||||
template conditions use `is not none`. Parent mappings are emitted only
|
||||
when at least one descendant is non-null.
|
||||
- Strings and collections are serialized with Ansible or Jinja filters rather
|
||||
than hand-written YAML quoting.
|
||||
- `narratio_publish_outputs`, `narratio_notarius_references`,
|
||||
`narratio_notarius_outputs`, `narratio_scriptorium_artifacts`, and
|
||||
`narratio_scriptorium_artifact_families` represent their complete native
|
||||
fields. Caller-side composition is permitted, but the role supplies no merge
|
||||
behavior.
|
||||
- Credential configuration contains environment-variable names only. Secret
|
||||
values remain outside the role and managed pipeline document.
|
||||
- The configuration directory is `root:narratio` mode `0750`; the pipeline
|
||||
file is `root:narratio` mode `0640`.
|
||||
- Mutable runtime roots are `narratio:narratio` mode `2775`. The campaign root
|
||||
is `root:narratio` mode `0755` because version-controlled content is
|
||||
populated by a separate owner and is not operator-edited on the host.
|
||||
- Tasks installing dependencies or managing privileged state use task-level
|
||||
`become: true`.
|
||||
- `community.general` supplies Snap management and is pinned to version
|
||||
`13.3.0` in the role's collection requirements.
|
||||
|
||||
## Fixed Public Interface
|
||||
|
||||
### Installation and Managed Filesystem
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `narratio_version` | `v2.0.0` | Selected Git revision and embedded build version |
|
||||
| `narratio_repository_url` | `https://gitea.maximumdirect.net/eric/narratio.git` | Source repository |
|
||||
| `narratio_source_dir` | `/usr/local/src/narratio` | Managed source checkout |
|
||||
| `narratio_binary_path` | `/usr/local/bin/narratio` | Installed executable |
|
||||
| `narratio_manage_build_dependencies` | `true` | Whether to install Git and Go |
|
||||
| `narratio_go_snap_channel` | `1.26/stable` | Go Snap channel |
|
||||
| `narratio_go_binary` | `/snap/bin/go` | Go executable used for the build |
|
||||
| `narratio_user` | `narratio` | System account owning mutable runtime state |
|
||||
| `narratio_group` | `narratio` | System group sharing mutable runtime state |
|
||||
| `narratio_config_path` | `/usr/local/etc/narratio/pipeline.yml` | Managed root pipeline document |
|
||||
| `narratio_workspace_root` | `/var/lib/narratio` | Managed workspace root and account home |
|
||||
| `narratio_campaigns_root` | `/usr/local/share/narratio/campaigns` | Managed campaign registry root |
|
||||
| `narratio_spool_root` | `/var/spool/narratio` | Managed spool root |
|
||||
| `narratio_cache_root` | `/var/cache/narratio` | Managed cache root |
|
||||
|
||||
Changing a managed root changes both its rendered pipeline value and the
|
||||
directory the role manages. The role does not infer additional arbitrary paths
|
||||
embedded inside caller-supplied open-ended collections.
|
||||
|
||||
### Pipeline Structure and Storage
|
||||
|
||||
Except where a default is shown, every variable below defaults to null and is
|
||||
omitted when null.
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_configkit_imports` | `null` | `configkit.imports` |
|
||||
| `narratio_workspace_cleanup_after_publish` | `null` | `workspace.cleanup_after_publish` |
|
||||
| `narratio_campaigns_default_campaign_id` | `null` | `campaigns.default_campaign_id` |
|
||||
| `narratio_storage_backend` | `null` | `storage.backend` |
|
||||
| `narratio_storage_s3_bucket` | `null` | `storage.s3.bucket` |
|
||||
| `narratio_storage_s3_root_prefix` | `null` | `storage.s3.root_prefix` |
|
||||
| `narratio_storage_s3_region` | `null` | `storage.s3.region` |
|
||||
| `narratio_storage_s3_endpoint` | `null` | `storage.s3.endpoint` |
|
||||
| `narratio_storage_s3_force_path_style` | `null` | `storage.s3.force_path_style` |
|
||||
| `narratio_storage_s3_access_key_id` | `null` | `storage.s3.access_key_id` environment-variable name |
|
||||
| `narratio_storage_s3_secret_access_key` | `null` | `storage.s3.secret_access_key` environment-variable name |
|
||||
| `narratio_spool_delete_audio_after_publish` | `null` | `spool.delete_audio_after_publish` |
|
||||
| `narratio_cache_s3_audio` | `null` | `cache.s3_audio` |
|
||||
| `narratio_publish_enabled` | `null` | `publish.enabled` |
|
||||
| `narratio_publish_upload_run` | `null` | `publish.upload_run` |
|
||||
| `narratio_publish_outputs` | `null` | Complete native `publish.outputs` list |
|
||||
|
||||
### WhisperX, Seriatim, and Audita
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_whisperx_transcribe_url` | required | `whisperx.transcribe_url` |
|
||||
| `narratio_whisperx_language` | `null` | `whisperx.language` |
|
||||
| `narratio_whisperx_timeout` | `null` | `whisperx.timeout` |
|
||||
| `narratio_whisperx_retries` | `null` | `whisperx.retries` |
|
||||
| `narratio_whisperx_retry_delay` | `null` | `whisperx.retry_delay` |
|
||||
| `narratio_whisperx_concurrency` | `null` | `whisperx.concurrency` |
|
||||
| `narratio_seriatim_binary` | `null` | `seriatim.binary` |
|
||||
| `narratio_seriatim_timeout` | `null` | `seriatim.timeout` |
|
||||
| `narratio_seriatim_output_schema` | `null` | `seriatim.output_schema` |
|
||||
| `narratio_seriatim_coalesce_gap` | `null` | `seriatim.coalesce_gap` |
|
||||
| `narratio_seriatim_report` | `null` | `seriatim.report` |
|
||||
| `narratio_seriatim_env_overlap_word_run_gap` | `null` | `seriatim.env.overlap_word_run_gap` |
|
||||
| `narratio_seriatim_env_overlap_word_run_reorder_window` | `null` | `seriatim.env.overlap_word_run_reorder_window` |
|
||||
| `narratio_seriatim_env_backchannel_max_duration` | `null` | `seriatim.env.backchannel_max_duration` |
|
||||
| `narratio_seriatim_env_filler_max_duration` | `null` | `seriatim.env.filler_max_duration` |
|
||||
| `narratio_audita_binary` | `null` | `audita.binary` |
|
||||
| `narratio_audita_timeout` | `null` | `audita.timeout` |
|
||||
| `narratio_audita_llm_api_key` | `null` | `audita.llm_api_key` environment-variable name |
|
||||
| `narratio_audita_modules` | `null` | `audita.modules` |
|
||||
| `narratio_audita_base_url` | `null` | `audita.base_url` |
|
||||
| `narratio_audita_model` | `null` | `audita.model` |
|
||||
| `narratio_audita_total_llm_concurrency` | `null` | `audita.total_llm_concurrency` |
|
||||
| `narratio_audita_proposal_llm_concurrency` | `null` | `audita.proposal_llm_concurrency` |
|
||||
| `narratio_audita_validation_model` | `null` | `audita.validation_model` |
|
||||
| `narratio_audita_validation_llm_concurrency` | `null` | `audita.validation_llm_concurrency` |
|
||||
| `narratio_audita_transcript_description` | `null` | `audita.transcript_description` |
|
||||
| `narratio_audita_config_path` | `null` | `audita.config_path` |
|
||||
| `narratio_audita_output_schema` | `null` | `audita.output_schema` |
|
||||
| `narratio_audita_work_dir_retention` | `null` | `audita.work_dir_retention` |
|
||||
| `narratio_audita_report` | `null` | `audita.report` |
|
||||
|
||||
### Transcript Stages and Rendering
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_normalize_output_path` | `null` | `normalize.output_path` |
|
||||
| `narratio_normalize_output_schema` | `null` | `normalize.output_schema` |
|
||||
| `narratio_normalize_report` | `null` | `normalize.report` |
|
||||
| `narratio_trim_enabled` | `null` | `trim.enabled` |
|
||||
| `narratio_trim_output_path` | `null` | `trim.output_path` |
|
||||
| `narratio_trim_bounds_prompt_id` | `null` | `trim.bounds.prompt_id` |
|
||||
| `narratio_trim_bounds_profile_id` | `null` | `trim.bounds.profile_id` |
|
||||
| `narratio_trim_bounds_transcript_input_name` | `null` | `trim.bounds.transcript_input_name` |
|
||||
| `narratio_trim_bounds_output_path` | `null` | `trim.bounds.output_path` |
|
||||
| `narratio_trim_bounds_timeout` | `null` | `trim.bounds.timeout` |
|
||||
| `narratio_trim_bounds_render_debug` | `null` | `trim.bounds.render_debug` |
|
||||
| `narratio_trim_bounds_render_output_path` | `null` | `trim.bounds.render_output_path` |
|
||||
| `narratio_trim_seriatim_report` | `null` | `trim.seriatim.report` |
|
||||
| `narratio_render_enabled` | `null` | `render.enabled` |
|
||||
| `narratio_render_format` | `null` | `render.format` |
|
||||
| `narratio_render_title` | `null` | `render.title` |
|
||||
| `narratio_render_include_timestamps` | `null` | `render.include_timestamps` |
|
||||
| `narratio_render_include_segment_ids` | `null` | `render.include_segment_ids` |
|
||||
| `narratio_render_include_metadata` | `null` | `render.include_metadata` |
|
||||
|
||||
### Scriptorium, Notarius, and Notification
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_scriptorium_binary` | `null` | `scriptorium.binary` |
|
||||
| `narratio_scriptorium_config_path` | `null` | `scriptorium.config_path` |
|
||||
| `narratio_scriptorium_timeout` | `null` | `scriptorium.timeout` |
|
||||
| `narratio_scriptorium_render_debug` | `null` | `scriptorium.render_debug` |
|
||||
| `narratio_scriptorium_artifacts` | `null` | Complete native `scriptorium.artifacts` map |
|
||||
| `narratio_scriptorium_artifact_families` | `null` | Complete native `scriptorium.artifact_families` map |
|
||||
| `narratio_notarius_enabled` | `null` | `notarius.enabled` |
|
||||
| `narratio_notarius_binary` | `null` | `notarius.binary` |
|
||||
| `narratio_notarius_config_path` | `null` | `notarius.config_path` |
|
||||
| `narratio_notarius_pipeline_id` | `null` | `notarius.pipeline_id` |
|
||||
| `narratio_notarius_timeout` | `null` | `notarius.timeout` |
|
||||
| `narratio_notarius_working_directory` | `null` | `notarius.working_directory` |
|
||||
| `narratio_notarius_references` | `null` | Complete native `notarius.references` map |
|
||||
| `narratio_notarius_outputs` | `null` | Complete native `notarius.outputs` map |
|
||||
| `narratio_notification_mode` | `null` | `notification.mode` |
|
||||
|
||||
## Simplest Viable Implementation
|
||||
|
||||
The production task flow is:
|
||||
|
||||
1. Assert the supported platform and architecture.
|
||||
2. Install Git and Go when dependency management is enabled.
|
||||
3. Create the Narratio system group and account.
|
||||
4. Create the source and configuration parent directories.
|
||||
5. Create the mutable runtime roots and read-only campaign registry root.
|
||||
6. Check out the selected Narratio revision with `ansible.builtin.git`.
|
||||
7. Inspect only whether the installed binary exists, because that result is
|
||||
needed to decide whether the imperative build command must run.
|
||||
8. Build directly to the selected binary path when the checkout changed or
|
||||
the binary is absent.
|
||||
9. Converge binary ownership and mode with `ansible.builtin.file`.
|
||||
10. Render the root pipeline document with one
|
||||
`ansible.builtin.template` task.
|
||||
|
||||
The build command uses `narratio_go_binary` and runs only under the two stated
|
||||
conditions. Ordinary modules own all other state checks. No role-private state,
|
||||
pre-build version interrogation, post-build validation, configuration
|
||||
validation, or redundant filesystem inspection belongs in production tasks.
|
||||
|
||||
The template is necessarily larger than those of the downstream roles because
|
||||
Narratio's native pipeline schema is larger. Its logic remains mechanical:
|
||||
serialize the required URL and role-owned roots, test each optional field with
|
||||
`is not none`, emit a parent section only when needed, and pass native
|
||||
collections through unchanged.
|
||||
|
||||
## Rationale and Alternatives
|
||||
|
||||
Narratio's configuration is broad, but a field-specific interface preserves
|
||||
discoverability, argument validation, stable inventory names, and a clean
|
||||
composition boundary for the suite role. A raw complete-document variable
|
||||
would make the template shorter but would discard those benefits and conflict
|
||||
with the established configuration policy. Open-ended native collections are
|
||||
kept whole because decomposing caller-defined keys would create a second schema
|
||||
and make inventory composition harder.
|
||||
|
||||
Requiring the WhisperX URL is preferable to installing a configuration that
|
||||
Narratio cannot validate or inventing an endpoint that might silently direct
|
||||
work to the wrong service. The baseline integration invocation supplies a
|
||||
non-contacted test URL; production callers supply their actual endpoint.
|
||||
|
||||
The standalone role creates the application account and directory permissions
|
||||
because those are Narratio runtime requirements. It does not select human
|
||||
operators, because membership is deployment-wide policy and belongs in the
|
||||
suite role.
|
||||
|
||||
ConfigKit imports and profiles remain available to advanced callers, but the
|
||||
role manages only the canonical root document. This avoids a parallel raw-file
|
||||
deployment subsystem. A caller that selects imports or profiles is responsible
|
||||
for installing those additional files by another role or play.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Required Role Behavior
|
||||
|
||||
- The role rejects unsupported platforms before modifying application state.
|
||||
- On a supported host, it installs the selected Narratio source release and
|
||||
builds the binary with the upstream release contract.
|
||||
- The system account, source, binary, configuration, runtime roots, and
|
||||
campaign root converge to the paths, ownership, and modes selected above
|
||||
through the responsible Ansible modules.
|
||||
- With only `narratio_whisperx_transcribe_url` supplied, the rendered pipeline
|
||||
contains that URL and the four role-owned roots, omits unselected optional
|
||||
policy, and is accepted by Narratio's native configuration validator.
|
||||
- Each non-null configuration variable renders its corresponding native field.
|
||||
Null fields and empty parent sections are omitted, while intentional falsey
|
||||
values are retained.
|
||||
- Caller-supplied open-ended collections are rendered without structural
|
||||
rewriting, and independently defined values can be composed before
|
||||
assignment.
|
||||
- A changed checkout or missing binary causes the imperative build to run. An
|
||||
immediate repeated application with unchanged inputs reports no changes.
|
||||
- Dependency opt-out accepts a caller-supplied `narratio_go_binary`.
|
||||
- Root-owned operations use task-level privilege escalation; play-level
|
||||
escalation is not required.
|
||||
- Defaults, argument specifications, template behavior, README, and metadata
|
||||
remain aligned with the public interface.
|
||||
- Production tasks contain no role-private state, redundant probes,
|
||||
application self-tests, or speculative guarantees.
|
||||
- No repository other than `ansible-role-narratio` and the workspace control
|
||||
repository is modified.
|
||||
|
||||
### Required Validation
|
||||
|
||||
- Syntax checking and production-profile ansible-lint pass.
|
||||
- A baseline invocation supplies only the required WhisperX URL, exercises the
|
||||
installed application by validating the managed pipeline as the Narratio
|
||||
account, and is followed immediately by a role application reporting no
|
||||
changes. It does not snapshot the role's current default tag or complete
|
||||
default document.
|
||||
- One explicitly selected-version case requests `v2.0.0` and verifies that
|
||||
`narratio version` reports `v2.0.0`. The assertion proves caller-controlled
|
||||
version selection, not that `v2.0.0` remains the role default.
|
||||
- One recovery case removes the binary, disables dependency management,
|
||||
supplies a caller-selected Go executable, confirms that executable is used,
|
||||
and finishes with a clean repeated application.
|
||||
- One representative configuration case verifies selected scalar and nested
|
||||
values, selected omissions, intentional falsey values, and composed
|
||||
open-ended collections. Narratio's native `config validate` accepts the
|
||||
managed pipeline, and an immediate repeated application reports no changes.
|
||||
- Tests do not assert task names or order, individual task results, exact
|
||||
current defaults, complete configuration snapshots, public-variable counts,
|
||||
trusted-module account, directory, file, package, checkout, or template
|
||||
postconditions, or an exhaustive negative platform matrix.
|
||||
|
||||
## Dependencies and Follow-up Work
|
||||
|
||||
The managed host requires access to the Narratio Git repository, Ubuntu Snap
|
||||
infrastructure, and Go module sources. Useful pipeline execution also requires
|
||||
a reachable WhisperX service, the four downstream application binaries and
|
||||
their configuration, campaign and session inputs, prompt content, and any
|
||||
selected object-storage or model credentials. Those remain caller
|
||||
responsibilities for this standalone feature.
|
||||
|
||||
After this feature, all five standalone application roles will have stable
|
||||
public interfaces. The next unit can design the suite-level pipeline role,
|
||||
including dependency composition, compatible version selection, D&D pipeline
|
||||
policy, campaign and prompt deployment, secrets, and operator group membership.
|
||||
|
||||
## Potential Future Hardening
|
||||
|
||||
- Build into a temporary path before replacing the installed executable.
|
||||
- Verify source signatures or release artifacts.
|
||||
- Detect compiler, build-command, or out-of-band binary changes.
|
||||
- Validate configuration during production convergence.
|
||||
- Manage imported fragments or profile overlays if a concrete standalone-role
|
||||
use case requires them.
|
||||
- Add a scheduler, service, or non-interactive execution environment if later
|
||||
operating requirements select one.
|
||||
- Support Narratio's published binary artifacts as part of a future suite-wide
|
||||
installation-model change.
|
||||
- Add broader platform coverage only when supported-platform behavior expands.
|
||||
Reference in New Issue
Block a user