Files
2026-09-22 19:23:17 +02:00

6.6 KiB

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.