21 KiB
Initial Roadmap
Purpose
This document records the decisions that define the initial MVP of the Narratio Ansible roles and D&D collection. It is the durable reference for choices that have been settled while the suite is being designed. Open questions and later ideas should remain clearly distinguished from these locked decisions.
MVP Goal
Build independently usable Ansible roles for the five Narratio applications
and compose them through a suite-level role developed in its own repository.
The rakestraw.dnd collection exposes that role as rakestraw.dnd.pipeline.
The suite-level role installs and configures the complete D&D transcript
processing pipeline on a single supported host. Operators or unattended
automation invoke Narratio commands either under the dedicated narratio
runtime identity or under a human account that belongs to the narratio
group, processing D&D session recordings into transcripts and related
artifacts.
Locked Decisions
Supported platform
- The MVP supports Ubuntu 26.04.
- The MVP supports both
amd64andarm64hosts. - The roles should be structured so support for additional distributions and releases can be added after the MVP without redesigning them.
Managed applications
The suite-level role installs and configures all five applications in the Narratio suite:
- Narratio
- Notarius
- Audita
- Seriatim
- Scriptorium
WhisperX is an external HTTP service consumed by Narratio. Deploying or managing the WhisperX service is outside the MVP scope, although the Narratio role will manage the native configuration needed to connect to it.
Application installation
- The MVP builds all five applications from their official Git repositories on the target host. This consistent model avoids making the suite depend on every upstream project publishing prebuilt artifacts.
- Released roles build an explicitly selected application release tag. Development may override the selected revision with a branch or commit.
- Source checkouts reside at
/usr/local/src/<app>and are owned byroot. - Roles build and install the binary at
/usr/local/bin/<app>withroot:rootownership and mode0755, using the application's native build command and the simplest clear Ansible task flow. - Builds use the application repository's own build contract, including any
application-specific version-injection linker flags. The common baseline is
GOWORK=off,GOTOOLCHAIN=local,CGO_ENABLED=0, and-trimpath. - Roles normally rebuild when the Git task reports a changed checkout or the binary is absent. An application-level version or smoke check may add a trigger only when its feature specification explicitly requires that production behavior. Roles do not maintain fingerprints, checksums, or sidecar build-state files for the MVP.
- Each application role exposes variables only for meaningful consumer choices, normally including its repository, selected version or revision, source directory, binary path, dependency management, Go Snap channel, and a build-tool path when dependency opt-out permits another provisioning mechanism. Fixed details of the upstream build contract need not become public variables.
Go toolchain
- Go is installed on the target host through the official Snap package using classic confinement.
- The Snap channel is configurable and should track an explicit Go minor
release channel, rather than unconstrained
latest/stable, when that channel is available for the required Go version. - The installed Go toolchain must satisfy the application's
go.modrequirement. Builds setGOTOOLCHAIN=localso provisioning does not silently download a different toolchain. - Each standalone application role can install its own build prerequisites and exposes a variable allowing that behavior to be disabled. Repeating an idempotent prerequisite task across the small roles is preferable to adding a shared-role dependency during the MVP.
Role and collection architecture
- All Ansible roles and collections in this suite use the root namespace
rakestraw. - Each of the five managed applications has a separate, targeted Ansible role in its own repository.
- Each application role owns installation and native configuration of that application.
- The Narratio application role remains application-specific even though Narratio is the runtime orchestrator for the full pipeline.
- The suite-level role is developed in the standalone
ansible-role-dnd-pipelinerepository rather than directly in the collection repository. - The application and pipeline roles are independently developed, tested, versioned, and released. An application-specific change therefore requires a release of that application's role without requiring changes or releases in unrelated role repositories.
- The collection is named
rakestraw.dnd. - The collection bundles and exposes the independently developed suite-level
role as
rakestraw.dnd.pipeline, providing one opinionated interface for consumers. - The pipeline role owns compatible application-version selection, cross-application configuration, D&D campaign deployment, prompt-library deployment, operator access, the pipeline-wide secret-delivery policy, and end-to-end validation.
- Unlike the generic standalone roles, the pipeline role deliberately supplies opinionated, D&D-specific defaults for all five applications. It expresses that policy through the standalone roles' existing field-specific variables, keeps those values overrideable through ordinary inventory precedence, and does not duplicate the application roles' templates or convergence logic.
- Pipeline defaults represent policy deliberately selected for the D&D suite; they do not mirror every upstream application default. Settings for which the suite has selected no policy remain under the application or caller's control.
- The pipeline role uses the Git-hosted standalone application roles as dependencies. This is an intentional choice for the controlled project environment despite the additional repository and dependency structure and Ansible's preference for published collection dependencies.
- Consumer installation may require a dependency manifest or bootstrap step that installs both the collection and its standalone role dependencies; a plain collection installation is not assumed to resolve arbitrary Git role dependencies by itself.
- The standalone application roles use the canonical installed names
rakestraw.audita,rakestraw.narratio,rakestraw.notarius,rakestraw.seriatim, andrakestraw.scriptorium. - The pipeline role supplies a root
requirements.ymlbootstrap manifest for those Git-hosted roles and a collection requirements manifest for shared collection dependencies. During active development, the Git roles are pinned to reviewed commits; released manifests replace those commits with immutable role release tags. - The pipeline role composes the five roles through ordinary Ansible role dependency metadata. It exposes suite-prefixed variables for the small set of values the suite must coordinate, and does not duplicate every downstream role variable behind a parallel alias.
This design keeps repository ownership and change blast radius aligned with the independently released applications while retaining a single opinionated installation interface for the complete suite. It avoids forcing each small role to become its own published collection and avoids coupling unrelated application-role releases in one source repository.
Ansible dependencies and task structure
- The standalone application roles are independently usable and prefer
ansible.builtinmodules where they directly fit the task. community.generalis treated as a stable, supported dependency. Roles may freely select its modules when appropriate, provided the collection dependency is declared and pinned for reproducible installation and tests.- The roles do not depend on the private
maximumdirect.core.ansible_role_loaderrole used by the proof of concept. - Platform-specific task selection may be added later using ordinary Ansible includes when another supported platform creates a concrete need.
- Small amounts of repeated prerequisite or installation logic are acceptable during the MVP. A shared helper role or collection plugin should be introduced only if substantial, stable shared behavior emerges.
- Ansible modules are trusted to implement their documented state transitions, idempotence, and change detection. Roles do not add preliminary existence checks, manual comparisons, or supplemental state around a module that already owns the desired behavior.
- State gathering is appropriate only when it controls behavior outside the responsible module's contract, such as deciding whether an application binary must be rebuilt.
Dependency and release reproducibility
- Development dependency manifests may temporarily refer to branches or commits while the roles are changing rapidly.
- Every released dependency manifest must pin each Git-hosted role dependency to an immutable role release tag.
- The collection release is the compatibility record for the exact set of application-role versions it composes.
- Collection integration tests must install and exercise the same pinned role combination delivered to consumers, starting from an environment in which the dependencies are not already installed.
- Updating one application role in the suite requires updating its pinned version in the collection, validating the assembled suite, and releasing a new collection version. Unrelated application-role repositories remain unchanged.
Prompt library
- The pipeline role installs Narratio's PromptKit-compatible prompt library
from the
narratio-promptsGit repository. The Scriptorium role owns its native prompt and schema directory configuration, while the pipeline role owns populating those locations with suite integration content. - The upstream repository is
https://gitea.maximumdirect.net/eric/narratio-prompts.git. - The repository is checked out at
/usr/local/share/narratio/prompt-libraryby default. Scriptorium's prompt and schema directories are the checkout'sprompts/andschemas/subdirectories. - The repository does not currently contain execution profiles. The pipeline role does not set Scriptorium's profile directory until a later suite-policy feature selects and deploys profiles.
- For the MVP, the pipeline role tracks and pulls the repository's
mainbranch. The origin, revision, and checkout root are configurable, and a caller may select an immutable commit when required. - Pinning the prompt library to a version or release is deferred until the upstream repository provides versioned releases.
Campaign registry content
- The pipeline role checks out the
campaignsGit repository directly into Narratio's campaign registry root. The upstream repository ishttps://gitea.maximumdirect.net/eric/campaigns.git. - The default campaign root remains
/usr/local/share/narratio/campaigns, and the pipeline role passes that same value to the Narratio application role. - For the MVP, the pipeline role tracks and pulls the repository's
mainbranch. The origin, revision, and campaign root are configurable, and a caller may select an immutable commit when required. - Both asset checkouts are root-managed and remotely authoritative. Operators may read the content but do not edit it on the managed host. Ordinary Git module convergence owns tracked-content updates; the role does not maintain separate revision state or purge untracked files.
Accounts, ownership, and operator access
- The standalone Narratio role creates a dedicated system
narratiouser andnarratiogroup. The account uses/var/lib/narratioas its default home and has a non-login shell. - The
narratioaccount owns the suite's application configuration and writable runtime directories;narratiois also the shared operator group. - Application source trees and installed binaries are owned by
rootand are not writable by operators or the runtime account. - The supported operational model runs
narratio runand other processing commands either as the dedicatednarratioaccount or as a human account that is already a member of thenarratiogroup. The suite does not yet select those human accounts or manage their membership. - Application configuration directories and files are owned by
narratio:narratio, use modes0755and0644, respectively, and are world-readable. Configuration remains under Ansible control rather than being routinely edited by operators on the host. - Workspace, spool, and cache roots are owned by
narratio:narratiowith mode2775. Setgid and managed default ACLs preserve shared group write access and world read/traverse access for newly created directories and files even when invocation identities have different ordinary umasks. - The pipeline role installs the host
aclpackage and uses the declared, pinnedansible.posixcollection to manage access and default ACL entries on those shared writable roots. - The campaign registry root is owned by
root:narratiowith mode0755. Its content is world-readable but is populated by the suite role and is not edited directly on the managed host. - Configuration, transcripts, caches, generated artifacts, logs, campaign data, and prompt assets are deliberately non-secret D&D content and remain world-readable. API keys and similar credentials are the sole confidential category.
- 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 narrower application contract before deployment.
- Credential material will live beneath a restricted
secrets/subdirectory owned bynarratio:narratio, with directories mode0750and files mode0640. Ordinary configuration contains only credential reference names. - Decision 0002 records the complete rationale and boundary for this policy.
Narratio configuration
- The standalone Narratio role manages the canonical root pipeline document
at
/usr/local/etc/narratio/pipeline.ymlthrough a field-specific public variable interface. - The role requires a caller-supplied WhisperX transcription URL because the field is required by Narratio and has no valid universal deployment value.
- Filesystem roots managed by the role have concrete defaults and are rendered so application configuration agrees with managed host state. Other optional application fields default to null, are omitted from the rendered document, and inherit Narratio's built-in defaults.
- Native open-ended collections such as publish outputs, Notarius references and outputs, and Scriptorium artifacts and artifact families are exposed as complete fields. Callers may compose their final values in inventory; the role does not add merge or precedence behavior.
- The root document may name ConfigKit imports, but the standalone role does not manage imported fragments or profile overlays. A caller that selects them owns their deployment.
- Credential fields contain environment-variable names, never secret values. Secret delivery remains suite-level policy.
- The standalone Narratio role owns the root pipeline document. The pipeline
role owns its D&D-specific imported processing, artifact, and artifact-family
fragments under
/usr/local/etc/narratioand selects them through an explicit orderedconfigkit.importslist. - Each ordinary artifact and artifact family is defined in a separate managed file. Explicit imports are preferred to directory globs so removed or stale files do not remain active implicitly.
- The pipeline role manages a native
profiles/testing.ymloverlay for inexpensive development and asset iteration. Production retains its frontier-oriented model/profile policy; callers select the testing overlay explicitly with Narratio's--profile testinginterface. - Base fragments and the testing overlay contain configuration and environment-variable or secret-reference names only. They never contain raw credentials.
- The D&D suite deliberately supplies Audita's complete reviewed processing
policy, including the current module sequence and tuning,
audita-v1output, thehttps://inference.ai.rakestrawhome.com/v1endpoint, andgoogle/gemma-4-31b-itfor proposal and validation. Those values remain inventory-overrideable and are suite policy rather than copies of upstream defaults. - The Narratio
testingprofile selectsgemini-flash-latestfor its Scriptorium artifacts and families. Audita initially uses the same endpoint and models in production and testing; identical values are inherited rather than duplicated in the overlay. - The D&D suite enables Notarius's
autochunk-plan cache and checkpoint cache beneath/var/cache/notarius. That FHS cache root is owned by thenarratioaccount and group with mode2775and the suite's shared default ACL policy. Notarius v0.7.0 leaves cache-entry access to that deployment policy. Chunk plans are reused automatically; checkpoints are recorded but Narratio does not yet request their reuse. - The standalone Notarius role exposes Notarius v0.7.0's native ConfigKit
import list while remaining independent of D&D content. The pipeline role
owns an imported
pipelines/dnd-session.ymlfragment containing its opinionated, inventory-composable D&D pipeline map; the standalone role continues to own only the version 5 root document. - The Narratio
testingprofile keeps the Notarius stage enabled and inherits the same D&D pipeline and extraction profile as production until a distinct testing extraction policy is selected.
Execution model
- Narratio is installed as a command-line application, not a persistent daemon.
- Scheduling Narratio invocations through cron, systemd timers, or another automation mechanism is not currently part of the locked MVP scope.
Expected Filesystem Areas
The roles align with the applications' established default locations unless a later design decision changes them:
/usr/local/etc/narratiofor Narratio configuration/usr/local/etc/audita/config.ymlfor Audita configuration/usr/local/etc/notarius/config.ymlfor Notarius configuration/usr/local/etc/notarius/pipelinesfor suite-owned imported Notarius pipeline definitions/usr/local/etc/scriptorium/config.ymlfor Scriptorium configuration/usr/local/etc/narratio/secretsfor future restricted credential material/usr/local/share/narratio/campaignsfor version-controlled campaign data/usr/local/share/narratio/prompt-libraryfor version-controlled prompts and schemas/usr/local/src/<app>for root-owned application source checkouts/usr/local/bin/<app>for root-owned application binaries/var/lib/narratiofor durable workspace and session state/var/spool/narratiofor spool data/var/cache/narratiofor cached data/var/cache/notariusfor suite-provisioned Notarius chunk-plan and checkpoint caches
The Narratio role creates and configures the campaign root; the pipeline role
populates it from the selected campaign source. /usr/local/share assumes Git
is authoritative and operators do not edit campaign content directly on the
managed host. The prompt-library checkout retains its upstream prompts/ and
schemas/ layout at the fixed root above.
Deferred Beyond the MVP
- Linux distributions and Ubuntu releases other than Ubuntu 26.04
- Architectures other than
amd64andarm64 - Installation from prebuilt application release artifacts
- Deploying or managing WhisperX
- Versioned Narratio prompt-library releases and pinning
- Versioned campaign-content releases and default release pinning
- A role-managed scheduler or persistent Narratio service
- Cryptographic artifact verification, supply-chain hardening, and protection against adversarial source or dependency infrastructure
- Transactional binary replacement and preservation of the prior executable after a local build failure
- Compiler-identity fingerprints, binary checksums, sidecar build-state files, and recovery from deliberately malformed or redirected managed paths
Design Work Still Open
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
- Upgrade, downgrade, and removal behavior
- Collection bootstrap and end-to-end validation details beyond the locked dependency and testing policies above