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

10 KiB

Feature 0001: Seriatim Source Installation

Status: ready

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, the binary is absent, or the installed binary does not report the selected version.
  • Converge the installed binary to root:root ownership and mode 0755.
  • Validate a newly built binary with seriatim --version.
  • 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 patch changes, fixed build-command changes, or manually altered binary contents that still report the selected version.
  • 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, a missing binary, or a binary reporting another version 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 /snap/bin/go, 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, and seriatim_go_snap_channel.
  • Fixed executable paths, build flags, linker symbols, environment values, and package paths are implementation details, not public variables.
  • 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 ten 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. Read its version when it exists, without reporting a change.
  8. Run the upstream Go build when the Git checkout changed, the binary is absent, or its reported version differs from the selected version.
  9. Converge source ownership and the installed binary's ownership and mode with one ansible.builtin.file loop.
  10. Validate the version after a build, without reporting a change.

For this fixed set of three 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 and post-build validation then follow in their 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. The installed application's version is the only additional state needed to decide whether a binary must be built. That preserves useful convergence without 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 or a binary reporting the wrong version 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 six variables named in this roadmap.
  • 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 dedicated Ubuntu release and architecture test matrices.

These are candidates for separately selected features if operational experience or a changed threat model justifies them.