## Status

Accepted (2026-08-23) for ACTIVITY-WP-0035.

## Context

The Event Bridge principle says activity-core answers when, what, and where and does not execute domain work. Production nevertheless contains three useful operations whose complete outcome is a small scheduled maintenance action:

- ingest at most three Repo Manager-selected immutable sources into SBOM Nexus;
- prune Forgejo package versions under live-image protection; and
- invoke the fixed CNPG Option A backup tool for an explicit target list.

Historically the latter two ran through a generic `shell` context resolver. That made a mutating subprocess look like a read and left extension policy to convention. Removing the operations would recreate bespoke cron; accepting arbitrary shell would make activity-core a general executor.

## Decision

### 1. Bounded operations are a narrow implementation exception

The governing when/what/where responsibility does not gain a general “how.” A bounded operation is allowed only when the operation itself is the declared automation outcome and all admission requirements below are code-reviewable.

The initial allowlist is exactly:

1. `sbom_nexus_ingest`
2. `forgejo_package_prune`
3. `cnpg_option_a_backup`

Adding an operation requires updating the code-owned registry, this ADR (or a successor), tests, credential route, and evidence contract. A string in a definition cannot register an operation.

### 2. Admission is fail closed during file sync

Each registry entry declares:

- source type and query;
- whether mutation intent is `apply` or `dry_run` and that it is explicit;
- fixed or maximum target bounds;
- canonical implementation and allowed configuration;
- idempotency and Temporal retry semantics;
- maximum execution timeout;
- credential owner/route; and
- mandatory non-secret evidence mode.

Unknown `shell` queries are refused unless separately registered as read-only. Known operation queries with missing, malformed, or over-limit safety fields are refused before database projection or Temporal schedule reconciliation.

### 3. Context resolution is read-only

The workflow first resolves and freezes context. Mutations then run in an explicit bounded-operation stage and merge only normalized outcomes into the snapshot before evidence and rule/instruction evaluation.

SBOM selection remains a read in the context phase; its fixed selection is the input to the operation stage. Package prune and backup have no discovery read inside activity-core and bind a pending marker until their operation completes.

### 4. Retry behavior is operation-specific

- SBOM ingest uses stable per-run/per-repository idempotency keys and heartbeat checkpoints, so Activity retries resume the frozen batch.
- Forgejo prune and CNPG backup have no activity-core-verifiable remote idempotency receipt. Their operation activity therefore has one Temporal attempt; a failure remains visible for operator reconciliation rather than risking an automatic second mutation.

This does not preclude future safe retries after the platform tools expose a durable operation receipt.

### 5. Evidence is mandatory and bounded

Every operation must produce an allowlisted summary through a configured report/evidence sink. Raw subprocess output, tokens, provider payloads, archive URLs, kubeconfigs, and credential material are not evidence.

## Rejected alternatives

- Keep mutating shell resolvers. Rejected because resolution should be a replayable read and the generic dispatcher hides mutation admission.
- Generic command activity. Rejected because command text/path from a definition is remote code execution by configuration.
- Move every operation to a rein. Rejected for these fixed platform operations; it adds an agent execution constellation without judgement or repository work. Operations that exceed this ADR's bounds do belong there.
- Remove all local operations. Rejected because it recreates scattered cron and loses Temporal/evidence guarantees for established maintenance.

## Consequences

- Definition parsing gains a central operation-policy validator.
- The workflow gains an explicit operation stage.
- The generic `shell` resolver becomes read-only.
- Existing definitions migrate without widening targets or permissions.
- The registry is intentionally small and architectural review is required to expand it.