365 lines
20 KiB
Markdown
365 lines
20 KiB
Markdown
# Feature 0003: Notarius Source Installation and Configuration
|
|
|
|
Status: done
|
|
|
|
## Summary
|
|
|
|
Provide a small, independently usable `rakestraw.notarius` role that installs
|
|
Notarius from a pinned Git tag, builds its executable on the managed host, and
|
|
manages its versioned YAML configuration. Reuse the established module-driven
|
|
application-role pattern while leaving D&D pipeline policy to the suite-level
|
|
role.
|
|
|
|
## Problem or Opportunity
|
|
|
|
At feature selection, the `ansible-role-notarius` repository contained only
|
|
its initial placeholder files. Notarius is one of the five required pipeline
|
|
applications and needed an independently usable installation and
|
|
native-configuration role before the suite role could compose it with
|
|
Seriatim, Audita, and the remaining applications.
|
|
|
|
Seriatim and Audita have established the preferred source-build architecture.
|
|
Notarius can use the same concise task flow, with only its native configuration
|
|
and build contract differing.
|
|
|
|
## Governing Policies
|
|
|
|
- [The Ansible house style](../../ansible.md) governs the role implementation,
|
|
its public configuration variables, and its template behavior.
|
|
- [The testing house style](../../testing.md) governs repository-local
|
|
validation. Tests exercise role-owned behavior through the public interface
|
|
without snapshotting current defaults, tracing task implementation, or
|
|
rechecking postconditions owned by trusted Ansible modules.
|
|
|
|
## Scope
|
|
|
|
- Implement `ansible-role-notarius` 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 Notarius tag `v0.6.0` by default under the root-owned
|
|
path `/usr/local/src/notarius`.
|
|
- Build Notarius with its upstream release build contract and install the
|
|
native executable at `/usr/local/bin/notarius`.
|
|
- Rebuild when the Git checkout changes or the binary is absent.
|
|
- Converge the installed binary to `root:root` ownership and mode `0755`.
|
|
- Manage a versioned Notarius YAML configuration at
|
|
`/usr/local/etc/notarius/config.yml`, owned by `root:root` with mode `0644`.
|
|
- Default the managed configuration to the minimal valid mapping
|
|
`{"version": 4}`, allowing Notarius's built-in defaults to govern behavior.
|
|
- Expose native configuration through field-specific role variables. Give the
|
|
required schema version a concrete default and make every optional setting
|
|
nullable so omitted settings remain owned by Notarius.
|
|
- Keep defaults, argument specifications, README, metadata, dependency
|
|
declaration, and focused local tests consistent with this contract.
|
|
|
|
## Non-goals
|
|
|
|
- A D&D pipeline definition, module selection, LLM profile, concurrency
|
|
policy, output paths, cache policy, or other suite-specific configuration.
|
|
- A raw mapping for the complete configuration document, a template override,
|
|
or competing configuration interfaces.
|
|
- Role defaults copied from Notarius merely to reproduce the application's
|
|
built-in defaults in YAML.
|
|
- Decomposing the open-ended `pipelines` map into role variables for every
|
|
possible pipeline, step, lane, binding, validator, option, or reference.
|
|
- API keys, secret values, environment files, or another secret-delivery
|
|
mechanism.
|
|
- PromptKit profiles or other externally maintained prompt content.
|
|
- Creation or management of the `narratio` account, operator groups, campaign
|
|
data, runtime output, debug, cache, checkpoint, or transcript directories.
|
|
- Installation or configuration of another pipeline application.
|
|
- Services, scheduling, removal behavior, or pipeline composition.
|
|
- Prebuilt release artifacts or cross-compilation.
|
|
- Production execution of Notarius to validate the build 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.
|
|
- A shared build helper role or dedicated platform-matrix infrastructure.
|
|
|
|
## Target End State
|
|
|
|
On an Ubuntu 26.04 `amd64` or `arm64` host, applying the role with defaults
|
|
installs or confirms Git and Go, checks out Notarius `v0.6.0` at
|
|
`/usr/local/src/notarius`, builds `/usr/local/bin/notarius`, and writes
|
|
`/usr/local/etc/notarius/config.yml`. Source and installed files have the
|
|
stated root ownership and permissions, and the configuration contains
|
|
`version: 4`.
|
|
|
|
When a caller sets an optional configuration variable, the corresponding
|
|
native field appears in the correct YAML section. Null fields are absent, as
|
|
are parent sections with no selected descendants. Explicit false, zero, empty
|
|
string, empty collection, and other non-null values are rendered and left to
|
|
Notarius's native validation. `notarius_pipelines` represents the native
|
|
open-ended `pipelines` field as one mapping rather than attempting to mirror
|
|
its extensible internal schema in Ansible variables. Callers may define
|
|
pipeline-map fragments in separate inventory files and compose them into the
|
|
final value with ordinary Ansible/Jinja expressions.
|
|
|
|
An immediate second application reports no changes. A changed Git checkout or
|
|
missing binary causes one build; configuration changes converge independently
|
|
through the ordinary `ansible.builtin.template` operation.
|
|
|
|
Repository-local tests exercise the real role through its public variables.
|
|
They use the default invocation only as a smoke test, explicitly select
|
|
immutable `v0.5.0` to prove version selection, exercise missing-binary recovery
|
|
with a caller-supplied Go executable, and render one representative
|
|
configuration covering null omission, intentional falsey values, and
|
|
caller-side pipeline composition. Application-native commands verify the
|
|
selected release and configuration validity, and immediate repeated
|
|
applications verify convergence.
|
|
|
|
## Repository Ownership
|
|
|
|
- `ansible-role-notarius` owns the role implementation, public interface,
|
|
configuration serialization, metadata, dependency declaration, README, and
|
|
repository-local validation.
|
|
- `../notarius` is the read-only authority for build, CLI, and configuration
|
|
contracts.
|
|
- `rakestraw-ansible` is a read-only style and deployment-policy reference.
|
|
- `ansible-role-dnd-pipeline` will later own the D&D-specific configuration
|
|
supplied through the standalone role's field-specific variables.
|
|
- `ansible-workspace-dnd` owns this roadmap, the eventual staged plan, and
|
|
aggregate status.
|
|
- All other repositories remain unchanged.
|
|
|
|
## Constraints and Settled Decisions
|
|
|
|
- The selected release is tag `v0.6.0`, which resolves to commit
|
|
`77ae132e5609916da40dcd4fcc749c000a63cbac`.
|
|
- The release declares Go 1.25.5. The suite-standard Go Snap channel remains
|
|
`1.26/stable` and satisfies that requirement.
|
|
- The upstream release build uses package `./cmd/notarius`, `CGO_ENABLED=0`,
|
|
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flag
|
|
`-X gitea.maximumdirect.net/eric/notarius/internal/buildinfo.Override=<version>`.
|
|
- `notarius --version` prints `notarius <version>`. This is test evidence, not
|
|
an additional production rebuild trigger or post-build convergence task.
|
|
- Notarius configuration schema version 4 explicitly supports a document
|
|
containing only `version: 4`, with omitted values supplied by application
|
|
defaults.
|
|
- `notarius_config_version` names the schema version so `notarius_version`
|
|
remains unambiguously the selected application release.
|
|
- Optional configuration variables are declared with YAML null defaults.
|
|
Template conditions use `is not none`, and parent mappings are emitted only
|
|
when at least one descendant is non-null.
|
|
- The native `pipelines` field is exposed as the nullable
|
|
`notarius_pipelines` mapping. It is one field-specific variable, not a raw
|
|
mapping for the complete document; the role serializes its value without
|
|
defining a parallel schema for pipeline internals.
|
|
- Pipeline composition belongs to the caller. For example, inventory may
|
|
define `notarius_pipeline_group_one` and `notarius_pipeline_group_two` as
|
|
mappings and set `notarius_pipelines` to
|
|
`{{ notarius_pipeline_group_one | combine(notarius_pipeline_group_two) }}`.
|
|
The role accepts and renders the resulting mapping without its own merge or
|
|
precedence mechanism.
|
|
- Strings and mappings are serialized with Ansible or Jinja filters rather
|
|
than hand-written YAML quoting.
|
|
- `notarius config validate --config <path>` validates a managed configuration
|
|
without requiring a pipeline selection. It is used only by tests.
|
|
- Configuration discovery uses an explicit CLI path, then `NOTARIUS_CONFIG`,
|
|
then `/usr/local/etc/notarius/config.yml`; the role manages the installed
|
|
default path.
|
|
- Configuration contains no secrets by default. Consumers arrange any secret
|
|
environment variables outside this feature.
|
|
- Tasks that install dependencies or manage root-owned 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.
|
|
- Tag `v0.5.0` remains buildable with the same Go requirement, package, linker
|
|
symbol, and configuration schema and is the explicit immutable release used
|
|
for focused native version-selection coverage.
|
|
|
|
## Fixed Public Interface
|
|
|
|
Provide these installation variables:
|
|
|
|
| Variable | Default | Purpose |
|
|
| --- | --- | --- |
|
|
| `notarius_version` | `v0.6.0` | Git revision and release value supplied to the build |
|
|
| `notarius_repository_url` | `https://gitea.maximumdirect.net/eric/notarius.git` | Source repository |
|
|
| `notarius_source_dir` | `/usr/local/src/notarius` | Managed source checkout |
|
|
| `notarius_binary_path` | `/usr/local/bin/notarius` | Installed executable |
|
|
| `notarius_manage_build_dependencies` | `true` | Whether to install Git and Go |
|
|
| `notarius_go_snap_channel` | `1.26/stable` | Go Snap channel |
|
|
| `notarius_go_binary` | `/snap/bin/go` | Go executable used for the build |
|
|
| `notarius_config_path` | `/usr/local/etc/notarius/config.yml` | Managed configuration file |
|
|
|
|
Provide these configuration variables:
|
|
|
|
| Variable | Default | Native field |
|
|
| --- | --- | --- |
|
|
| `notarius_config_version` | `4` | `version` |
|
|
| `notarius_promptkit_profile_dir` | `null` | `promptkit.profile_dir` |
|
|
| `notarius_promptkit_profile_file` | `null` | `promptkit.profile_file` |
|
|
| `notarius_promptkit_local_backend_endpoint` | `null` | `promptkit.local_backend.endpoint` |
|
|
| `notarius_promptkit_local_backend_concurrency_limit` | `null` | `promptkit.local_backend.concurrency_limit` |
|
|
| `notarius_pipelines` | `null` | `pipelines` |
|
|
| `notarius_concurrency_total_llm` | `null` | `concurrency.total_llm` |
|
|
| `notarius_concurrency_stage_workers_extract` | `null` | `concurrency.stage_workers.extract` |
|
|
| `notarius_output_directory` | `null` | `output.directory` |
|
|
| `notarius_cache_chunk_plans_mode` | `null` | `cache.chunk_plans.mode` |
|
|
| `notarius_cache_chunk_plans_directory` | `null` | `cache.chunk_plans.directory` |
|
|
| `notarius_cache_checkpoints_enabled` | `null` | `cache.checkpoints.enabled` |
|
|
| `notarius_cache_checkpoints_directory` | `null` | `cache.checkpoints.directory` |
|
|
| `notarius_debug_directory` | `null` | `debug.directory` |
|
|
|
|
The package, build flags, linker symbol, environment values, file ownership,
|
|
and modes are fixed implementation details. The selected version is both the
|
|
Git revision and the value supplied to the upstream linker flag.
|
|
|
|
Argument specifications type each value according to its native shape. The
|
|
role does not reproduce semantic relationships such as the mutual exclusion
|
|
of PromptKit profile sources or the requirement for a local-backend endpoint;
|
|
Notarius owns those constraints. The `notarius_pipelines` value is a mapping
|
|
whose nested structure is governed by Notarius's versioned configuration
|
|
contract.
|
|
|
|
## Simplest Viable Implementation
|
|
|
|
The expected implementation is approximately nine ordinary tasks in one
|
|
readable task file:
|
|
|
|
1. Assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`.
|
|
2. Install Git with `ansible.builtin.apt`, including
|
|
`cache_valid_time: 3600`, when dependency management is enabled.
|
|
3. Install the classic Go Snap from `notarius_go_snap_channel` with
|
|
`community.general.snap` when dependency management is enabled.
|
|
4. Create source, binary, and configuration parent directories with one
|
|
`ansible.builtin.file` loop.
|
|
5. Check out `notarius_version` with `ansible.builtin.git`, `force: true`, and
|
|
register the module result.
|
|
6. Inspect whether `notarius_binary_path` exists with
|
|
`ansible.builtin.stat`.
|
|
7. Run the upstream Go build through `notarius_go_binary` when the checkout
|
|
changed or the binary is absent.
|
|
8. Converge recursive source ownership and binary ownership and mode with one
|
|
item-driven `ansible.builtin.file` loop.
|
|
9. Render the field-specific configuration with one
|
|
`ansible.builtin.template` task, conditionally emitting optional fields and
|
|
parent sections at `notarius_config_path`.
|
|
|
|
Apply task-level privilege escalation only where required. Use `argv` for the
|
|
build command and put its two conditions directly on the build task. Do not
|
|
add a rebuild fact, handler, handler flush, executable discovery, compiler or
|
|
version interrogation, configuration assembly facts, preliminary
|
|
configuration probes, or post-operation validation to production tasks.
|
|
|
|
## Rationale and Alternatives
|
|
|
|
Notarius has the same installation mechanics as the completed Seriatim and
|
|
Audita roles: declarative dependency and checkout management surrounding one
|
|
imperative build command. Binary existence is the only state probe Ansible
|
|
needs because it controls whether that command must run.
|
|
|
|
Field-specific variables are the ordinary ergonomic interface for inventory
|
|
and composing roles. Nullable defaults expose and type that interface without
|
|
freezing Notarius's built-in defaults into Ansible. Conditional rendering
|
|
preserves the distinction between omission and an intentionally falsey value.
|
|
|
|
The pipeline definitions are the deliberate exception to leaf-level
|
|
variables. `pipelines` is itself an open-ended map whose nested keys depend on
|
|
registered modules and evolve with the application's native schema. Exposing
|
|
that native field as one nullable mapping keeps the interface practical while
|
|
still avoiding a raw complete-document mapping or merge semantics. The suite
|
|
role can later supply its maintained D&D pipeline through
|
|
`notarius_pipelines` and supply operating policy through the other variables.
|
|
|
|
This boundary also supports modular inventory. A consumer can keep one or
|
|
more pipeline mappings in separate `host_vars`, `group_vars`, or included
|
|
variable files and combine them when assigning `notarius_pipelines`. Because
|
|
the native value is a mapping keyed by pipeline ID, dictionary composition
|
|
uses Ansible's `combine` filter; list concatenation with `+` applies only to
|
|
list-valued data. The role receives the already composed native mapping and
|
|
does not need custom loading, merging, or precedence behavior.
|
|
|
|
Leaving optional variables undefined would produce the same minimal file but
|
|
would weaken interface documentation and argument validation. Section-level
|
|
dictionaries would be less ergonomic for ordinary inventory values. A raw
|
|
complete configuration mapping would force consumers to replace the required
|
|
version and unrelated sections together and would conflict with the workspace
|
|
convention of one field-specific interface.
|
|
|
|
Managing `/usr/local/etc/notarius/config.yml` follows the application's own
|
|
configuration discovery contract and aligns locally installed software with
|
|
its configuration.
|
|
|
|
## Acceptance Criteria
|
|
|
|
### Required Role Behavior
|
|
|
|
- The role rejects unsupported distributions, Ubuntu releases, and
|
|
architectures before modifying application state.
|
|
- On a supported host, the role installs the selected Notarius source release
|
|
with its upstream build contract. The default selection for this feature is
|
|
tag `v0.6.0`, resolving to commit
|
|
`77ae132e5609916da40dcd4fcc749c000a63cbac`.
|
|
- The role converges the source tree, binary, and configuration to the paths,
|
|
ownership, and modes defined above using the responsible Ansible modules.
|
|
- The default template renders the minimal valid configuration containing the
|
|
required schema version and leaves optional policy to Notarius.
|
|
- A non-null optional variable renders its corresponding native field. Null
|
|
values and parent sections without a selected descendant are omitted;
|
|
intentional falsey values are preserved.
|
|
- Independently defined inventory mappings can be combined into
|
|
`notarius_pipelines`, and the resulting pipeline IDs and definitions are
|
|
rendered without structural rewriting by the role.
|
|
- 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 `notarius_go_binary`.
|
|
- Tasks requiring elevated access use task-level privilege escalation, so the
|
|
role does not require play-level escalation.
|
|
- Defaults, argument specifications, template behavior, and documentation
|
|
remain aligned with the public interface without introducing a parallel raw
|
|
configuration or template-override interface.
|
|
- Production tasks contain no role-private build state, redundant probes,
|
|
application self-tests, or other behavior outside the selected invariants.
|
|
- No repository other than `ansible-role-notarius` and the workspace control
|
|
repository is modified.
|
|
|
|
### Required Validation
|
|
|
|
- Syntax checking and production-profile ansible-lint pass.
|
|
- A default invocation provides a smoke test through the installed CLI and
|
|
native configuration validator, followed immediately by a role application
|
|
reporting no changes. The test does not assert that the role's current
|
|
default release or complete default document remains unchanged.
|
|
- A focused version-selection case explicitly requests immutable tag `v0.5.0`
|
|
and verifies that the installed CLI reports `notarius v0.5.0`.
|
|
- 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 rendered values,
|
|
selected omissions, intentional falsey values, and caller-side composition
|
|
of two pipeline mappings. The native Notarius validator accepts the result,
|
|
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 file or package postconditions, or an exhaustive negative
|
|
platform matrix.
|
|
|
|
## Dependencies and Follow-up Work
|
|
|
|
The managed host requires access to the Notarius Git repository, Ubuntu Snap
|
|
infrastructure, and Go module sources. Actual transcript processing also needs
|
|
a configured pipeline, input artifacts, PromptKit assets and endpoints, and
|
|
secret environment variables; those belong to consumers or later suite-level
|
|
work.
|
|
|
|
The role was implemented in `ansible-role-notarius` commits `287fc4a` and
|
|
`733a194`, then finalized by remediation commit `eb4f511`. Its complete
|
|
integration suite passes. The pipeline role can now supply its D&D definitions
|
|
through `notarius_pipelines` and select the other field-specific values.
|
|
|
|
## Potential Future Hardening
|
|
|
|
- Build into a temporary path before replacing the installed executable.
|
|
- Verify source signatures or release checksums.
|
|
- Detect compiler, build-command, or out-of-band binary changes.
|
|
- Validate configuration during production convergence.
|
|
- Manage a dedicated runtime account, secret environment, state paths,
|
|
service, or schedule if later operating requirements select them.
|
|
- Add broader Ubuntu release and architecture test coverage only if future
|
|
platform behavior warrants it.
|