12 KiB
Feature 0002: Audita Source Installation and Configuration
Status: done
Summary
Provide a small, independently usable rakestraw.audita role that installs
Audita from a pinned Git tag, builds its executable on the managed host, and
offers an ergonomic field-specific interface for its versioned YAML
configuration. Unspecified optional fields are omitted so Audita retains
ownership of its application defaults.
Problem or Opportunity
The completed source-installation flow is concise and correct, but the initial
configuration interface exposes only one audita_config mapping. That requires
every caller to know and reproduce Audita's native nested schema, and it does
not provide the ordinary role ergonomics expected for inventory variables.
The role should expose documented variables for individual settings and render
only values expressly selected by the caller. This permits straightforward
host_vars, group_vars, play variables, and suite-role overrides while
allowing upstream default changes to take effect automatically when a setting
is not managed by Ansible.
Scope
- Retain the completed Ubuntu 26.04
amd64andarm64source installation. - Retain default tag
v0.9.1, Go Snap channel1.26/stable, source path/usr/local/src/audita, and binary path/usr/local/bin/audita. - Retain rebuild triggers of changed Git checkout or absent binary.
- Replace the complete
audita_configmapping with typed, field-specific configuration variables. - Always render the required configuration schema version, defaulting to
1. - Define every optional configuration variable as
nullby default and omit its YAML field when it remains null. - Render nested YAML sections only when at least one setting in that section is non-null.
- Manage
/usr/local/etc/audita/config.ymlfrom a Jinja template asroot:rootmode0644. - Keep defaults, argument specifications, template, README, metadata, dependency declaration, and focused tests consistent with this contract.
Non-goals
- Copying Audita's built-in values into role defaults or the default rendered file.
- D&D-specific model selection, concurrency, thresholds, transcript context, or other suite policy.
- A parallel mapping-based configuration escape hatch or merge/precedence rules between two configuration interfaces.
- API keys or other secret values. Variables may select environment-variable names, but the role does not manage their values.
- Creation of the
narratioaccount or management of runtime, campaign, glossary, transcript, diagnostics, or secret-delivery infrastructure. - Services, scheduling, removal behavior, pipeline composition, prebuilt artifacts, or cross-compilation.
- Production execution of Audita for build or configuration validation.
- Fingerprints, checksums, sidecar state, staged replacement, manual Git cleanup, compiler inspection, or out-of-band drift detection.
Target End State
With no configuration overrides, the role writes the minimal valid document:
version: 1
When a caller sets an optional role variable, the corresponding native Audita field appears in the correct YAML section. Fields whose variables remain null are absent, including their parent sections when no child is selected. Empty lists, empty strings, zero, and other expressly supplied non-null values are rendered rather than mistaken for omission and are left for Audita to validate.
Installation and configuration converge independently. A configuration-only change does not rebuild the binary, and an immediate repeat reports no changes. Repository-local tests validate managed configurations through Audita. The current CLI has no native release-identity command, so the suite deliberately does not substitute a raw source-commit proxy for version coverage.
Repository Ownership
ansible-role-auditaowns installation, the public configuration interface, template, metadata, README, and repository-local tests.../auditais the read-only authority for build, CLI, configuration schema, and application-default contracts.rakestraw-ansibleis a read-only style reference for field-specific role variables and conditional templates; its historical values are not authoritative defaults.ansible-role-dnd-pipelinewill later own D&D-specific overrides supplied through the standalone role variables.ansible-workspace-dndowns this roadmap, the staged plan, and aggregate status.- All other repositories remain unchanged.
Constraints and Settled Decisions
- Tag
v0.9.1resolves toa84941d68168a1ed9ea7423b6477ae8218be73f9and retains the build contract already implemented and validated through role commit3a8c21f. - Audita's strict schema version is
1; all other top-level fields are optional and overlay application defaults. audita_config_versionnames the schema version soaudita_versionremains unambiguously the selected application release.- Optional variables are present in role defaults with YAML null values. This documents the interface and enables argument validation without emitting upstream defaults.
- Template conditions use
is not none, not truthiness, so expressly supplied falsey values are rendered. - String and list values must be safely encoded as YAML values rather than interpolated with hand-written quoting.
- A parent mapping is emitted only when at least one corresponding child value is non-null.
- The role does not validate Audita's semantic constraints during production convergence. Native validation remains integration-test behavior.
- Task-level
become: true,community.general13.3.0, and all existing installation decisions remain unchanged.
Fixed Public Interface
Retain these installation variables:
| Variable | Default |
|---|---|
audita_version |
v0.9.1 |
audita_repository_url |
https://gitea.maximumdirect.net/eric/audita.git |
audita_source_dir |
/usr/local/src/audita |
audita_binary_path |
/usr/local/bin/audita |
audita_manage_build_dependencies |
true |
audita_go_snap_channel |
1.26/stable |
audita_go_binary |
/snap/bin/go |
audita_config_path |
/usr/local/etc/audita/config.yml |
Provide these configuration variables:
| Variable | Default | Native field |
|---|---|---|
audita_config_version |
1 |
version |
audita_pipeline_modules |
null |
pipeline.modules |
audita_output_schema |
null |
output.schema |
audita_llm_proposal_base_url |
null |
llm.proposal.base_url |
audita_llm_proposal_model |
null |
llm.proposal.model |
audita_llm_proposal_api_key_env |
null |
llm.proposal.api_key_env |
audita_llm_proposal_timeout |
null |
llm.proposal.timeout |
audita_llm_proposal_max_retries |
null |
llm.proposal.max_retries |
audita_llm_validation_base_url |
null |
llm.validation.base_url |
audita_llm_validation_model |
null |
llm.validation.model |
audita_llm_validation_api_key_env |
null |
llm.validation.api_key_env |
audita_llm_validation_timeout |
null |
llm.validation.timeout |
audita_llm_validation_max_retries |
null |
llm.validation.max_retries |
audita_concurrency_total_llm |
null |
concurrency.total_llm |
audita_concurrency_proposal_llm |
null |
concurrency.proposal_llm |
audita_concurrency_validation_llm |
null |
concurrency.validation_llm |
audita_chunking_target_sections |
null |
chunking.target_sections |
audita_chunking_max_section_tokens |
null |
chunking.max_section_tokens |
audita_chunking_min_section_tokens |
null |
chunking.min_section_tokens |
audita_normalization_max_segment_gap |
null |
normalization.max_segment_gap |
audita_normalization_ellipsis_gap |
null |
normalization.ellipsis_gap |
audita_normalization_max_segment_duration |
null |
normalization.max_segment_duration |
audita_normalization_max_segment_tokens |
null |
normalization.max_segment_tokens |
audita_thresholds_glossary |
null |
thresholds.glossary |
audita_thresholds_homophones |
null |
thresholds.homophones |
audita_thresholds_spoken_word |
null |
thresholds.spoken_word |
audita_thresholds_grammar |
null |
thresholds.grammar |
audita_context_description |
null |
context.description |
audita_diagnostics_work_dir |
null |
diagnostics.work_dir |
audita_diagnostics_retention |
null |
diagnostics.retention |
The argument specification types values according to the native field shape. Duration-like fields accept strings or numeric seconds as supported by Audita; do not narrow the application contract unnecessarily.
Simplest Viable Implementation
Retain the existing nine-task installation flow. Make only these production changes:
- Replace
audita_configin defaults and argument specifications with the field-specific variables above. - Add
templates/config.yml.j2, always renderingversionand conditionally rendering every optional field and necessary parent mapping. - Replace the final
ansible.builtin.copytask with oneansible.builtin.templatetask using the existing destination, ownership, and mode.
Do not add configuration assembly facts, nested merge filters, validation commands, preliminary file probes, or multiple configuration tasks. The template is the direct expression of the selected configuration state.
Rationale and Alternatives
Field-specific variables are the ordinary ergonomic interface for inventory and composing roles. Nullable defaults make that interface discoverable and typed without freezing a duplicate copy of Audita's application defaults into Ansible. Conditional rendering also preserves the distinction between an unset field and a caller intentionally supplying a falsey value.
Leaving variables entirely undefined would produce the same file but weaken
interface documentation and argument validation. Section-level dictionaries
would shorten the template but require callers to understand more of the
native nested schema. Retaining audita_config beside field variables would
require unneeded merge and precedence semantics. None is preferable to the
single field-specific interface.
Acceptance Criteria
- All existing source-installation and platform acceptance criteria continue to pass without production task-flow expansion.
- Defaults and argument specifications contain exactly the eight installation variables and thirty configuration variables in the Fixed Public Interface.
- No
audita_configcompatibility variable remains. - Default convergence writes a YAML mapping containing exactly
version: 1. - Every optional field is absent when its variable is null.
- Setting a representative value in every configuration section renders the
correct nested native fields and passes
audita config validate. - Explicit falsey non-null values are rendered rather than omitted; semantic validity remains Audita's responsibility.
- Configuration changes run the template task but not the build task and reach an unchanged immediate repeat.
- The installed configuration remains a regular file owned by
root:rootwith mode0644. - Production tasks do not invoke Audita, inspect the existing configuration, or construct intermediate configuration state.
- The README documents each variable, null-as-unmanaged behavior, safe secret environment-variable naming, and the distinction between application and suite defaults.
- Syntax checking, production-profile ansible-lint, complete integration testing, native minimal and representative configuration validation, and clean repeated runs pass.
- Only
ansible-role-auditaand the workspace control repository change.
Dependencies and Follow-up Work
The existing Audita role through commit 3a8c21f is the implementation
baseline. The managed host and test prerequisites are unchanged.
The configuration amendment was completed in ansible-role-audita commits
e61f02f and 847c4c3 and validated by its complete integration suite. The
proposed Notarius roadmap should use the same nullable field-specific approach
where appropriate.
Potential Future Hardening
- Validate configuration during production convergence if later operating requirements explicitly select that behavior.
- Manage secret environment delivery, diagnostics paths, runtime accounts, or services as separate suite-level or application-level features.
- Detect source signatures, compiler drift, or out-of-band binary changes if the threat model changes.