345 lines
18 KiB
Markdown
345 lines
18 KiB
Markdown
# Feature 0003: Notarius Source Installation and Configuration
|
|
|
|
Status: proposed
|
|
|
|
## 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
|
|
|
|
The `ansible-role-notarius` repository currently contains only its initial
|
|
placeholder files. Notarius is one of the five required pipeline applications
|
|
and needs an independently usable installation and native-configuration role
|
|
before the suite role can 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.
|
|
|
|
## 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 execute the installed CLI to verify the selected build and validate the
|
|
managed configuration.
|
|
|
|
## 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`, commit
|
|
`61436d7c186af57b06004e090ceac898e83cdb71`, remains buildable with the same
|
|
Go requirement, package, linker symbol, and configuration schema and may be
|
|
used for focused checkout-change coverage before restoring `v0.6.0`.
|
|
|
|
## 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
|
|
|
|
- Unsupported distributions, Ubuntu releases, and architectures fail before
|
|
application state is modified.
|
|
- Default execution on the local Ubuntu 26.04 host installs or confirms Git
|
|
and Go and checks out tag `v0.6.0` at commit
|
|
`77ae132e5609916da40dcd4fcc749c000a63cbac`.
|
|
- The role builds with the fixed upstream contract and installs
|
|
`/usr/local/bin/notarius` as a regular file owned by `root:root` with mode
|
|
`0755`.
|
|
- The managed source checkout is recursively owned by `root:root`.
|
|
- The default configuration contains exactly `version: 4` and is installed at
|
|
`/usr/local/etc/notarius/config.yml`, owned by `root:root` with mode `0644`.
|
|
- Every optional field is absent when its variable is null, including parent
|
|
sections with no selected descendants.
|
|
- A representative configuration exercises every top-level section and
|
|
validates successfully with `notarius config validate`.
|
|
- Explicit falsey non-null values, including zero and false, are rendered
|
|
rather than omitted; semantic validity remains Notarius's responsibility.
|
|
- Repository-local tests receive `notarius v0.6.0` from the installed CLI and
|
|
successfully validate the managed configuration.
|
|
- An immediate second role run reports no changes.
|
|
- A missing binary causes one rebuild followed by an unchanged run.
|
|
- A changed checkout causes one rebuild followed by an unchanged run.
|
|
- A configuration change updates only configuration state and does not rebuild
|
|
the binary.
|
|
- Dependency opt-out accepts a caller-supplied `notarius_go_binary`.
|
|
- A play connecting as an ordinary sudo-capable user can apply the role without
|
|
play-level privilege escalation.
|
|
- Defaults and argument specifications contain exactly the eight installation
|
|
variables and fourteen configuration variables in the Fixed Public
|
|
Interface.
|
|
- No raw `notarius_config` compatibility variable, template override, or
|
|
parallel configuration interface exists.
|
|
- 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.
|
|
- Production tasks contain no CLI validation, fingerprints, checksums, sidecar
|
|
state, manual Git reset or clean commands, or probes before state already
|
|
managed by APT, Snap, `file`, `git`, or `template`.
|
|
- Syntax checking, production-profile ansible-lint, focused local convergence,
|
|
CLI verification, configuration validation, and clean repeated runs pass.
|
|
- Role documentation describes actual behavior, dependency opt-out, every
|
|
public configuration variable, null-as-omission behavior, the native
|
|
`pipelines` boundary and caller-side composition example, privilege use, and
|
|
integration-test effects.
|
|
- No repository other than `ansible-role-notarius` and the workspace control
|
|
repository is modified.
|
|
|
|
## 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.
|
|
|
|
After this roadmap is approved, replace the pending notice at
|
|
`docs/roadmap/implementation.md` with a numbered staged Notarius implementation
|
|
plan. The pipeline role can supply its D&D definitions through
|
|
`notarius_pipelines` and select the other field-specific values after the
|
|
standalone interface is implemented and reviewed.
|
|
|
|
## 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 dedicated Ubuntu release and architecture test matrices.
|