Bulk workers no-op on non-hosted kinds where the P4 plan mandates a fail-closed typed error

The Phase 4 plan's Approach requires the bulk workers to read the re-resolved repository's kind and fail closed on any kind they carry no arm for — "a typed error that leaves the job to River's retry, never a completed no-op ... which is what lets Phase 6 widen these routes to remote repositories with no deploy-order hazard" (docs/plans/2026-08-10-s17-phase4-artifact-writes.md, Approach; restated at its Step 33 and Maven worker step).

Main implements the opposite, deliberately and test-pinned:

  • internal/managementapi/bulk_npm_worker.go:490 skips non-hosted kinds via logBatchSkipped and Work returns nil — a kind=remote batch completes successfully having applied nothing.
  • bulk_npm_worker_internal_test.go:445-460 pins the no-op ("a repository the batch may not touch is a logged no-op, not a retryable failure").
  • Maven is the same shape (bulk_maven_worker.go:449-455, mavenBulkRepositoryUnusable).

Why it blocks: the hazard is cross-binary over a shared queue. A new pod's widened route enqueues a remote delete_all, an old pod still carrying the no-op claims and completes it, and the 202'd eviction is silently lost. Only a binary deployed before the route widens closes that window, so Phase 6 Steps 31 (maven), 32 (npm), and 33 (container) gate on this conversion landing and deploying fleet-wide first. A separate job kind is ruled out by the plan (an unregistered kind strands accepted jobs).

Fix shape per worker: convert the non-hosted-kind arm from a logged whole-batch skip to a typed retryable error, flip the pinning subtest, keep the soft-deleted and wrong-format arms as no-ops (a retry cannot change those). Roughly one function plus its test per worker.

Open question for the operator: if the deployed fleet does not yet serve this surface, the ordering may be relaxable by decision — that is an amendment to the P4 plan's Approach, not something a build run may assume.

Surfaced by the Step 32 build gate check (S17 Phase 6).

Related to #314


Triage note (automated): This issue has been classified as type::bug. The bulk workers silently complete (no-op) on non-hosted repository kinds instead of returning a typed retryable error as required by the Phase 4 plan. This is a correctness defect with a real production hazard: eviction jobs can be silently lost during a rolling deploy, and Phase 6 gates on this fix landing fleet-wide first.

Labels applied: type::bug, Category:Artifact Registry, devops::package, group::package registry.

If this classification doesn't look right to you, please update the type label and let us know — we're happy to adjust!

Edited by Triage and Label issues