Files
Ansible/scripts/docs/ADDON_AGENTS.md
T
2026-09-22 19:23:17 +02:00

106 lines
6.6 KiB
Markdown

# AIM add-on development contract
**Core 3.3.0rc8; service/wire/event 1.0 (stable additive 1.x); Ansible Core 2.19.11.**
AIM is the independently usable Source of Truth. Add-ons own presentation, sessions,
authorization at their application boundary, approvals, queues and persistence.
They never patch Core, scrape terminal output or duplicate inventory/execution rules.
## Integration sequence
Use `aim.services.v1` or one `aimctl request` process per JSON-lines request. Discover
capabilities, current customers/hosts/hierarchy and catalog. Prepare explicit hosts and
declared options, show the normalized request and result contract for review, check
readiness under the actual worker identity, acquire a worker slot, collect fresh
credentials, and execute using the prepared revision. A stale revision requires review.
Omit unchanged options to preserve inventory/role-default precedence.
The published API is in `scripts/docs/ADDON_API.md`; the complete new result contract
is in `scripts/docs/OPERATION_RESULTS.md`. Current support and qualification are in
`ADDON_SUPPORT.md` and `VALIDATION.md`. Never infer feature support from product version
alone. `capabilities.collection_baselines` declares collection floors that add-on installers/operators must satisfy; Core does not upgrade them. Unknown optional response fields may be ignored; unknown errors fail safely.
## Purposeful output: new in this candidate
Check `capabilities.operation_results`. Catalog `result` is null or a declaration with
schema, scope, required flag, limits and resolved `data_schema`. No new execute request
field is needed. Reports are available in summary and detail mode through the final
`RunResult.operation_result` and the existing final result event. There is no new raw
stdout event. Parse final JSON without scraping PLAY/TASK text or debug bodies.
A result contains `hosts[host]` with `status`, `schema`, `data`, `error`, plus optional
`global`. Render data only when status is `available`. Missing/withheld/invalid/null is
not an empty valid report. `complete` means all declared report slots arrived and passed
validation; it does not mean the operation succeeded. Partial native runs can contain
useful data from successful or failed targets. Preserve overall status/stage/exit,
`remote_work_may_have_started`, target summary and report availability as separate facts.
Never automatically retry a `result_validation` failure: remote changes may be complete.
Use a generic bounded JSON/table renderer for unknown schemas, with optional richer
views for known schemas. Escape text/HTML/Rich markup. Do not treat null versions as
zero, pending updates as installed, excluded services as failed starts, or redacted
configuration values as absent settings. Config reports expose sections but redact
recognized secret/command fields; restrict report visibility and retention accordingly.
## Safety and identity
Core checks active OS group membership and filesystem access. This is same-UID local
execution, not per-browser-user RBAC or an untrusted-tenant sandbox. The execution
account owns its 0600 keys and private staging. `service_user` is not a local UID switch.
`runtime.private_key_owner` affects new keys only. Do not relax permissions, export keys,
add generic sudo wrappers or run the web frontend as root to bypass the boundary.
Hardened service installers must provision both applicable staging locations (process
HOME and passwd home) and narrow ReadWritePaths exceptions. Retain ProtectHome/read-only,
ProtectSystem/strict and private tmp protections. Run `aimctl staging-check` inside the
actual sandbox. Core does not create accounts, modify units or restart add-on services.
Use OneRunCredentials or a private inherited FD, never passwords in request JSON, argv,
environment, URLs, logs, queue records or databases. Queue plans, not secrets. Fresh
credentials are required for each attempt. Password inputs are native defaults, not
Custom overrides or proof of password-only authentication. Cross-UID execution is not
provided by Core; independently managed executors must already have authorized access.
## Progress and final outcomes
`progress_mode: detail` is negotiated before preparation. Correlate play/task IDs,
handle withheld names and fixed error hints, and ignore anonymous progress to avoid
duplicate rows. Keep bounded queues and responsive sinks. Raw module/exception/debug
output remains unsupported. Purposeful data is a separate final schema, not an expansion
of host_result. Target outcomes come from Core's final native per-host stats, not task
counts. An interrupted/incomplete stream must not become partial success by inference.
## Ownership and handoff
Core and add-ons release independently. Core deployment preserves add-on code/state,
operator aim.yml, inventories, Vaults and keys; add-ons preserve Core in return.
Use ZIP + checksum + the deployer, not Git or patches. Coordinate active jobs before
source replacement. Only documented retired Core files are removed on upgrade.
The nine current report schemas are documented in OPERATION_RESULTS.md and advertised
by the catalog. This candidate has local regression coverage, not new managed-host
certification. Record independent acceptance under your actual identity/sandbox/runtime.
Request new schemas/capabilities from Core instead of adding private output workarounds.
## OS patch-wave presentation (3.3.0rc8)
Patch options remain catalog-driven. Interfaces should render the advertised reboot
message/delay and the Windows-only `os_patching_rescan_after_reboot` option. Its catalog
default is false; do not silently enable "fully patch" behavior in an add-on.
Windows submits the current selected categories as one native `win_updates` wave with
module-managed Windows Update sequencing and `reboot: false`. AIM evaluates reboot policy
after the wave returns; it does not expose or own a per-update scheduler. With post-reboot
continuation disabled, an AIM-performed reboot can still be a successful Core run while
`continuation_required: true` tells the operator another patch run is needed.
`remaining_updates_known: false` means the client must not invent or persist a next-wave
list. If a final read-only search was performed, `remaining_updates_known: true` makes
`pending` authoritative for that observation only.
Render `failed_updates[].reason/message/native_code_hex` instead of parsing fatal text or
Windows event logs. `install_not_allowed` deliberately does not mean "reboot required" by
itself. If Core reports `blocked_reason: preexisting_reboot_required`, that is the separate
preflight observation. Never auto-enable reboot, post-reboot continuation, or automatic job
replay.