Files
ansible-workspace-dnd/docs/roadmap/features/0001-seriatim-source-installation.md

222 lines
11 KiB
Markdown

# Feature 0001: Seriatim Source Installation
Status: done
## Summary
Provide a small, independently usable `rakestraw.seriatim` role that installs
Seriatim from a pinned Git tag, builds the native executable on the managed
host, and converges idempotently. This revised specification replaces the
original overengineered implementation target and establishes the preferred
module-driven style for subsequent application roles.
## Problem or Opportunity
The current role reaches the basic deployment outcome, but it does so with
manual source cleanup, compiler parsing, build-input serialization, hashes,
checksums, sidecar state, path-shape recovery, and a large defensive test
matrix. Those mechanisms are disproportionate to the MVP and obscure the
simple job of checking out a repository, building one executable, and
installing it with known metadata.
Seriatim remains the right proving ground because it has no central
configuration file. Simplifying it before implementing another role prevents
the current design from becoming an accidental suite-wide pattern.
## Scope
- Simplify `ansible-role-seriatim` into concise, idiomatic Ansible.
- 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 the selected Seriatim version from its official Git repository,
defaulting to immutable tag `v1.5.0`, under a root-owned
`/usr/local/src/seriatim`.
- Build Seriatim using the fixed upstream release build contract and install
it at `/usr/local/bin/seriatim`.
- Rebuild when the source checkout changes or the binary is absent.
- Converge the installed binary to `root:root` ownership and mode `0755`.
- Verify an explicitly selected immutable Seriatim version through the native
CLI in repository-local integration tests.
- Keep the role interface, README, metadata, and focused local tests consistent
with the simplified behavior.
- Remove obsolete build-state files and implementation machinery from the
role repository. Existing build-state data on previously managed hosts does
not need to be removed by the role.
## Non-goals
- Application configuration; Seriatim has no central configuration file.
- Creation or management of the `narratio` account or operator membership.
- Installation or configuration of any other pipeline application.
- Pipeline composition, campaign data, prompts, secrets, or scheduling.
- Installation from prebuilt release artifacts or removal behavior.
- Detecting rebuild needs from Go compiler changes, fixed build-command
changes, or out-of-band modification of an existing binary.
- Build fingerprints, binary checksums, or persistent sidecar build state.
- Transactional replacement that preserves a previous executable after a
failed local build.
- Automatic recovery from deliberately malformed paths, symbolic-link
redirection, hostile source trees, or other adversarial host state.
- A shared build helper role or abstraction.
- Dedicated platform-matrix infrastructure beyond the approved local MVP
proxy.
## Target End State
On an Ubuntu 26.04 `amd64` or `arm64` host, applying the role with default
variables installs Git and Go when requested, checks out Seriatim `v1.5.0`
under a root-owned `/usr/local/src/seriatim`, and installs a native executable at
`/usr/local/bin/seriatim`. The executable is owned by `root:root`, has mode
`0755`, and reports `seriatim version v1.5.0`.
An immediate second application makes no changes. A changed Git checkout or a
missing binary causes one build. The following application is again unchanged.
The role trusts `apt`, `community.general.snap`, `file`, and `git` to provide
their documented idempotence and change detection. It does not inspect state
before invoking those modules or maintain a parallel model of the state they
already manage.
## Repository Ownership
- `ansible-role-seriatim` owns the role implementation, defaults, metadata,
README, dependency declaration, and repository-local validation.
- `../seriatim` is the read-only authority for the build, version, and CLI
contracts.
- `rakestraw-ansible` is a read-only style reference.
- `ansible-workspace-dnd` owns this roadmap, the active implementation plan,
and cross-repository status.
- All other repositories remain unchanged.
## Constraints and Settled Decisions
- The suite MVP supports Ubuntu 26.04 and native `amd64` and `arm64` builds.
- Local execution on the current Ubuntu 26.04 development host is a sufficient
MVP integration proxy.
- Go is installed from Snap with classic confinement and defaults to channel
`1.26/stable`.
- `community.general` is an approved dependency and provides Snap management;
its version is pinned in the role's collection requirements.
- The build runs from the checked-out source using `seriatim_go_binary`
(defaulting to `/snap/bin/go`) with `GOWORK=off`, `GOTOOLCHAIN=local`,
`CGO_ENABLED=0`, `-trimpath`, package `./cmd/seriatim`, and the upstream
linker flag that injects the selected version into
`internal/buildinfo.Version`.
- The selected version is both the Git revision and the version injected into
the executable. Supporting independent source and build identities is not an
MVP requirement.
- The public interface is limited to meaningful deployment choices:
`seriatim_version`, `seriatim_repository_url`, `seriatim_source_dir`,
`seriatim_binary_path`, `seriatim_manage_build_dependencies`,
`seriatim_go_snap_channel`, and `seriatim_go_binary`.
- Build flags, linker symbols, environment values, and package paths are
implementation details, not public variables.
- Tasks that install dependencies or manage root-owned application state use
task-level privilege escalation.
- `docs/decisions/0001-minimal-module-driven-ansible.md` governs the role's
implementation style.
## Simplest Viable Implementation
The intended Seriatim implementation is approximately the following eight
ordinary tasks.
1. Assert the supported distribution, release, and architecture.
2. Install Git with `ansible.builtin.apt` when dependency management is
enabled.
3. Install Go with `community.general.snap` when dependency management is
enabled.
4. Create the source and binary parent directories with one
`ansible.builtin.file` loop.
5. Check out the selected source with `ansible.builtin.git` and register its
normal changed result.
6. Inspect whether the installed binary exists.
7. Run the upstream Go build when the Git checkout changed or the binary is
absent.
8. Converge source ownership and the installed binary's ownership and mode
with one `ansible.builtin.file` loop.
For this fixed set of two rebuild triggers, the build remains an ordinary
task with the conditions applied directly to its `when` expression. This keeps
the complete decision visible at the action site and avoids deferred execution
or a play-wide handler flush. Permission convergence then follows in its
natural task order. Do not create an intermediate `seriatim_build_required`
fact.
The implementation may combine or split a task when required for clear and
correct Ansible, but it must not add preflight checks around idempotent modules
or reintroduce persistent build-state machinery. Prefer a single readable task
file unless a split materially improves navigation.
## Rationale and Alternatives
This design uses the Git module's changed result as the natural signal that
source changed. A binary existence check is the only additional state needed
to decide whether the imperative build command must run. That preserves useful
convergence without adding unrequested drift detection or maintaining a second
database of compiler and build inputs.
Building directly to the configured binary path is intentionally simpler than
staging, checksumming, and recording a transactional installation. A failed
build will fail the play visibly; preserving an older executable in every
failure mode is not an MVP requirement.
## Acceptance Criteria
- The role rejects unsupported distributions, Ubuntu releases, and
architectures before modifying application state.
- Default execution on the local Ubuntu 26.04 host installs or confirms Git
and Go and checks out Seriatim tag `v1.5.0`.
- The role builds with the documented fixed upstream contract and installs
`/usr/local/bin/seriatim` as `root:root` mode `0755`.
- The managed source checkout is owned by `root:root`.
- `/usr/local/bin/seriatim --version` reports
`seriatim version v1.5.0`.
- An immediate second role run reports no changes.
- A missing binary causes one rebuild followed by an unchanged run.
- A changed selected version causes the Git task and build task to change and
then converges.
- The implementation contains no build-input documents, fingerprints, binary
checksums, sidecar build state, manual Git reset or clean commands, or
preliminary checks for state already managed by `apt`, Snap, `file`, or
`git`.
- Public defaults and argument specifications contain only the seven variables
named in this roadmap.
- A caller may disable dependency management and select an existing Go
executable with `seriatim_go_binary`.
- Tasks requiring superuser access use task-level privilege escalation.
- Syntax checking, ansible-lint, a focused local convergence test, and a clean
repeated run pass.
- Role documentation describes the actual concise behavior and does not claim
transactional build safety or exhaustive corruption recovery.
- No repository other than `ansible-role-seriatim` and the workspace control
repository is modified.
## Dependencies and Follow-up Work
The role requires access to the Seriatim Git repository, Ubuntu Snap
infrastructure, and Go module sources from the managed host. After this revised
implementation is reviewed, its minimal conventions can inform a fresh Audita
roadmap and the remaining application roles.
The original implementation commits remain in Git history as evidence of the
superseded design. The prior completion and remediation documents must not be
used as templates for another role.
## Potential Future Hardening
- Build in a temporary location and validate before replacing the installed
executable.
- Verify release signatures or source checksums.
- Record compiler and build-input identity for exact rebuild invalidation.
- Detect arbitrary binary modification independently of reported version.
- Protect or recover from unexpected symbolic links and malformed managed
paths.
- Add broader Ubuntu release and architecture test coverage only if future
platform behavior warrants it.
These are candidates for separately selected features if operational
experience or a changed threat model justifies them.