activity-core/activity-definitions/daily-sbom-catchup.md
tegwick 26934e25b9
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 21s
Enforce bounded operation guardrails
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a028de-e2c8-7732-8521-46a7fc5db82f
2026-08-23 12:31:13 +02:00

4.9 KiB

id name enabled owner governance status trigger context_sources
daily-sbom-catchup Daily SBOM Catch-up true custodian-agent custodian active
type cron_expression timezone misfire_policy
cron 15 9 * * 1-5 Europe/Berlin skip
type query operation required params bind_to
sbom-nexus catch_up sbom_nexus_ingest true
limit apply
3 true
context.catchup

Daily SBOM Catch-up

Enabled after production proof on 2026-08-22. Two bounded manual fires processed three distinct repositories each, spawned zero tasks, and persisted terminal no-checkout evidence. The superseded weekly schedule remains off.

Replaces weekly-sbom-staleness / flag-stale-sbom (ACTIVITY-WP-0030). The weekly check reported the backlog — 111 / 111 repos stale on 2026-08-18, 93 never scanned — and spawned one task per stale repo, so it could never close it. This definition updates N instead of reporting N.

Runs weekdays at 09:15 Berlin, after the daily triage window.

Contract

Context source sbom-nexus / catch_up (context_resolvers/sbom_nexus.py):

Direction Shape
input {"limit": 3}
output {repos, selected_count, stale_count, never_count, total_count, limit}
each repo repo_slug, last_sbom_at, sbom_age_days, has_sbom, checkout_available, optional immutable source_ref

Ranking (never-scanned first, then oldest last_sbom_at) belongs to sbom-nexus. The adapter truncates to limit so an over-long response can never widen the bounded side-effect below.

Task emission

None. This definition carries no rule block — that is the point of the replacement. tasks_spawned must stay 0 on every fire, and no Forgejo issues are emitted (ACTIVITY-WP-0022).

Evidence

id: daily-sbom-catchup-report
trusted_fields: []
model: deterministic
temperature: 0
max_tokens: 1
prompt: |
  Deterministic SBOM catch-up report from context.catchup (no LLM).
output_schema: ""
review_advisory: false
report_sinks:
  - type: state-hub-progress
    event_type: sbom_catchup
    author: activity-core
    topic_id: cee7bedf-2b48-46ef-8601-006474f2ad7a

The progress event names the repos selected, updated, and skipped with a reason (no-checkout, no-manifest, ingest-error), plus the fleet counters so never_count can be watched declining day over day.

Controlled-source outcomes additionally include source-unavailable and source-rejected. They remain terminal for the selected repository and never cause the same fire to select a replacement target.

Bounded side-effect (ACTIVITY-WP-0030-T02 / ACTIVITY-WP-0033)

params.apply: true declares the write, but context resolution remains read-only. The workflow records the already-truncated N targets in Temporal history, then a dedicated activity applies exactly that fixed set. Completed per-repository outcomes are heartbeated so an ordinary activity retry resumes after them instead of selecting or writing a second batch.

A target with an explicitly unavailable checkout is recorded through POST /sbom/{slug}/skip as no-checkout; other targets use the terminal ingest route, which returns ingested, no-manifest, or ingest-error. Each request sends a stable per-run/per-repository Idempotency-Key. Transport failures, timeouts, and malformed responses fail visibly and are never converted into a synthetic skip because the remote write may have committed. Nexus must enforce the operation key to close the remaining crash window between a committed POST and Activity Core's next heartbeat. The resulting updated and skipped arrays are part of the run context and progress report. There is no task or issue emission.

When Nexus returns a forgejo-archive-v1 source_ref, the workflow freezes it with the original target set and sends that exact object in the ingest body. Retries reuse the same full commit SHA even if the repository default branch has advanced.

Enable checklist

  1. CUST-WP-0062-T02/T03 done: sbom-nexus stood up, GET /sbom/catch-up returns oldest-N in one call. Done 2026-08-22.
  2. SBOM_NEXUS_URL reachable from the railiance01 worker.
  3. ACTIVITY-WP-0030-T02 ingest side-effect implemented and dry-run proven.
  4. weekly-sbom-staleness confirmed off in source and production (ACTIVITY-WP-0030-T03).
  5. Project into k8s/railiance/20-runtime.yaml, enabled: true, sync schedules, capture evidence via ./scripts/prod_automation_status.sh (ACTIVITY-WP-0030-T04).