docs(specs): record ADR-021's dist-tag verb split in S17

📝 Summary

S17 Phase 4 binds the npm dist-tag DELETE route to delete_artifact, and recorded that binding as a contested reading: ADR-021's Create row listed "dist-tag management", its Delete row listed "tags", so dist-tag removal had two readings. The spec took the Delete row, accepted a surface asymmetry, and left the ADR an owed disambiguation.

The GitLab package registry settles which reading is right. Its npm dist-tag routes authorize the PUT against create_package (Developer) and the DELETE against destroy_package (Maintainer), and its granular-access-token permission groups file create_npm_package_tag under create and delete_npm_package_tag under delete. Tag operations split by verb, not by tag kind.

ADR-021 now says so directly: handbook!20854 merged, giving the tag verbs a row each in the artifact-operations table and naming both tag kinds in all three artifact permission descriptions. So the binding S17 already requires is correct, and what changes here is the framing around it.

🔄 What changed

Spec text only, in docs/specs/S17-rest-management-api.md:

  • Security Considerations, "Write authorization". States the verb split directly — create or retarget a tag needs create_artifact, remove one needs delete_artifact, for container image tags and npm dist-tags alike. The "ADR-021 reads both ways" paragraph is gone, and so is the accepted asymmetry: the npm protocol path requires delete_artifact for removal too, so an Artifact Contributor can add a dist-tag on either surface and remove one on neither.
  • Artifact write routes (Phase 4). The ADR-021 mapping line names the npm dist-tag delete explicitly, since that is the route a reader questions.
  • Dependencies. The ADR-021 entry names both permissions Phase 4's writes bind to; container tag upsert has always been a create_artifact write.
  • Follow-ups, ADR amendments. The owed ADR-021 dist-tag item is removed, because the amendment merged. The Phase 8 items (per-artifact statistics mapping to read_artifact, and the :tag spelling) are untouched.

✅ Behavior

➖ None, and no permission mapping changes — every route keeps the permission the merged spec already assigned it. Every management route runs behind the S09 allow-all authorization stub, so nothing enforces any of this yet. S17's status field is unchanged.

🔍 Scope notes

  • docs/adr/ is a daily-synced read-only mirror and is not touched. The amendment landed upstream in handbook 638f9c576ff70a1d744ef9c65006bc703aaa93b7; the mirror picks it up on the next sync run, after which docs/adr/021_authorization.md carries the split this spec describes.
  • A grep of docs/plans/ found no plan restating the dist-tag permission binding, and S09 and S11 bind no permission to the protocol dist-tag routes, so nothing else in-tree repeats the claim. The npm action table in the authorization-enforcement work is where the protocol-side split gets enforced.

♻️ History

This MR previously carried the opposite change — moving the dist-tag DELETE to create_artifact on the reading that ADR-021's Create row governs every dist-tag verb. Checking the package registry showed that reading disagrees with the implementation being migrated from, so the branch was rewritten to keep the delete_artifact binding and amend the ADR instead.

Related to #652 (closed)

Edited by David Fernandez

Merge request reports

Loading
Loading