activity-core/workplans/ACTIVITY-WP-0030-daily-sbom-catchup.md
custodian-sync bfbc37a9bd chore(consistency): renormalize lifecycle state [auto]
Updated by fix-consistency on 2026-08-18:
  - workplan status: backlog → active
2026-08-18 10:30:35 +02:00

4.1 KiB

id type title domain repo status owner topic_slug created updated parent_workplan related state_hub_workstream_id
ACTIVITY-WP-0030 workplan Daily bounded SBOM catch-up via sbom-nexus infotech activity-core active grok infotech 2026-08-18 2026-08-18 CUST-WP-0062
CUST-WP-0062
ACTIVITY-WP-0022
ADHOC-2026-06-01
bfe2945e-38df-40d1-94d4-6e4a003ef66d

Daily bounded SBOM catch-up via sbom-nexus

Goal

Replace weekly-sbom-staleness / flag-stale-sbom with a daily ActivityDefinition that:

  1. Evaluates fleet SBOM freshness through sbom-nexus (one ranked catch-up call, not a per-repo walk and not a for_each over every stale repo).
  2. Updates N SBOM snapshots for the repos that have lacked a current SBOM the longest. N defaults to 3 (catch_up_limit).

Parent coordination: CUST-WP-0062. Parked 2026-08-18 — do not start until that parent is unblocked. Do not enable this schedule until the catch-up API exists.

Current failure mode

Monday 2026-08-17 prod fire spawned 75 Run SBOM rescan for {slug} tasks. The rule is for_each: context.repos.repos where context.repo.sbom_age_days > 30. On 2026-08-18 the hub listed 111 / 111 repos stale or never scanned. The weekly check reports the backlog; it does not close it.

repo_sbom_status bulk mode already uses GET /repos/ (age from last_sbom_at) rather than N /sbom/{slug} calls. That is still the wrong shape for catch-up: the worker materialises every repo, then emits one task each. The replacement must ask sbom-nexus for only N targets and then ingest them.

Tasks

Draft definition and resolver contract

id: ACTIVITY-WP-0030-T01
status: wait
priority: high
state_hub_task_id: "b216976e-5402-4e40-b282-78c5d021df72"

Write activity-definitions/daily-sbom-catchup.md (enabled: false until cutover): weekday or daily cron, Berlin morning after triage is fine. Context source: sbom-nexus catch_up with limit default 3. Deterministic progress (event_type: sbom_catchup) listing selected / updated / skipped. No for_each over the full stale set.

Resolver contract (implement against a test double until CUST-WP-0062-T03 lands):

  • input: {limit: 3}
  • output: {repos: [...], stale_count, never_count, total_count, limit}
  • each repo: repo_slug, last_sbom_at, sbom_age_days, has_sbom, checkout_available if known

Implement ingest side-effect for N targets

id: ACTIVITY-WP-0030-T02
status: wait
priority: high
state_hub_task_id: "0d09c0d3-74bd-4f4d-8b27-5006ba010fa3"

Wait on CUST-WP-0062-T03. Bounded side-effect (SCOPE: declared purpose only): for each of the N repos, call sbom-nexus ingest using the registered checkout when present. Record skip reasons (no-checkout, no-manifest, ingest-error) in the run artefact and progress event. Do not spawn Forgejo issues (ACTIVITY-WP-0022). Do not retry a recorded skip as if it were still the oldest never-scanned repo.

Retire weekly task flood

id: ACTIVITY-WP-0030-T03
status: wait
priority: high
state_hub_task_id: "18bcfc21-616a-48a2-aac3-cdcef7579913"

After the daily job is proven on railiance01: set weekly-sbom-staleness enabled: false (or remove flag-stale-sbom), keep or drop the weekly summary report only if it no longer emits one task per repo. Update runbook / playbook. Prove one Monday window with zero SBOM task spawns and a successful daily catch-up the same week.

Prod enable and evidence

id: ACTIVITY-WP-0030-T04
status: wait
priority: medium
state_hub_task_id: "f09144f6-c7f9-41d4-b466-d8a6288e6a21"

Project the definition into k8s/railiance/20-runtime.yaml, sync schedules, and capture prod evidence via ./scripts/prod_automation_status.sh plus the sbom_catchup progress event. Confirm tasks_spawned is 0 and N updates (or documented skips) appear per fire.

Acceptance

  • Daily definition exists; weekly flood is off
  • Evaluation is one sbom-nexus catch-up call
  • Each fire updates at most N repos (default 3)
  • Progress names the repos and skip reasons
  • Railiance01 evidence for at least two successful daily fires