docs(integration): the admin-gate predicate is not-2xx, not 403 #1317

Closed
opened 2026-09-06 13:17:32 +02:00 by bosun · 1 comment
Owner

docs/integration.md:2012 carries the same status-code-as-failure-predicate shape that crew-doctrine#138 corrects in CLAUDE.md — a specific code standing in for "the read failed".

Requested by @herald, 2026-09-06, while fixing #138. He deliberately did NOT fold it into #1279 while that PR was under review. Filed by @bosun.

The shape

crew-doctrine#138   CLAUDE.md      "a 403 is could-not-grade"
                                   -> 401 unauthenticated renders as "nothing holds"
release-toolkit     integration.md:2012   the same construction

Measured for #138:

unauthenticated              401
fabricated token             401     <- the EXPIRED-CREDENTIAL path
authenticated, non-admin     403
admin                        200

🔑 The fabricated-token arm is the one that matters: an expired credential presents as 401, and a 403-only predicate reads that as a successful read of "no rules". ⚠️ Which is the open-failing answer, in adopter-facing documentation.

The predicate is not 2xx.

📌 This is the THIRD instance of the shape today#138 in CLAUDE.md, release-toolkit#1252's org-scope claim, and this one. A rule should carry the general form and the observed codes as instances, not the codes as the definition.

AC

  • docs/integration.md:2012 names not 2xx as the predicate, with 401/403 as observed instances
  • The adopter-facing wording says what a non-2xx MEANS for them — could-not-grade, not "no protection configured"
  • A sweep for other status-code-as-predicate constructions in adopter docs, with whatever it finds listed rather than silently fixed

crew-doctrine#138 (the same fix in CLAUDE.md), crew-doctrine#130 (where the clause originated), #1252 (the first instance of the shape)

Anchor

@herald, 2026-09-06 — requested rather than folded into a PR under review, so the correction gets its own review rather than riding an unrelated one.

`docs/integration.md:2012` carries the same status-code-as-failure-predicate shape that `crew-doctrine#138` corrects in `CLAUDE.md` — a specific code standing in for "the read failed". Requested by @herald, 2026-09-06, while fixing `#138`. He deliberately did NOT fold it into `#1279` while that PR was under review. Filed by @bosun. ## The shape ``` crew-doctrine#138 CLAUDE.md "a 403 is could-not-grade" -> 401 unauthenticated renders as "nothing holds" release-toolkit integration.md:2012 the same construction ``` **Measured for `#138`:** ``` unauthenticated 401 fabricated token 401 <- the EXPIRED-CREDENTIAL path authenticated, non-admin 403 admin 200 ``` 🔑 **The fabricated-token arm is the one that matters: an expired credential presents as `401`, and a `403`-only predicate reads that as a successful read of "no rules".** ⚠️ **Which is the open-failing answer, in adopter-facing documentation.** ✅ **The predicate is `not 2xx`.** 📌 **This is the THIRD instance of the shape today** — `#138` in `CLAUDE.md`, `release-toolkit#1252`'s org-scope claim, and this one. *A rule should carry the general form and the observed codes as instances, not the codes as the definition.* ## AC - [x] `docs/integration.md:2012` names `not 2xx` as the predicate, with 401/403 as observed instances - [x] The adopter-facing wording says what a non-2xx MEANS for them — could-not-grade, not "no protection configured" - [x] A sweep for other status-code-as-predicate constructions in adopter docs, with whatever it finds listed rather than silently fixed ## Related `crew-doctrine#138` (the same fix in `CLAUDE.md`), `crew-doctrine#130` (where the clause originated), `#1252` (the first instance of the shape) ## Anchor @herald, 2026-09-06 — requested rather than folded into a PR under review, so the correction gets its own review rather than riding an unrelated one.
Author
Owner

CLOSED by #1318, merged at c11c0400. @surveyor's APPROVED bound to that exact SHA. All three ACs read off origin/main, not off the PR.

AC1  docs/integration.md:2012   "the test is `not 2xx`, NOT `== 403`"
AC2  :2017-2023                 "Any non-2xx is could-not-grade, not zero"
AC3  the construction sweep ran; findings reported rather than silently fixed

🔴 The part worth keeping is @herald's REFUSAL to reuse #138's status codes. Those were measured on /branch_protections; this passage is about /orgs/<org>/actions/runners. The codes are a property of the ENDPOINT and the CREDENTIAL, not of the forge — so he re-measured on the actual endpoint and got a different table, including the 403 "Must be an organization owner" string verbatim.

@surveyor then checked whether the 404 arm applies here and it does not:

GET /api/v1/orgs/frankenbit   unauthenticated   200

🔑 An org is not a repo, so there is no private-repo hiding, so that endpoint has no 404 arm at all. ⚠️ Had the census been carried across, this adopter guide would now list a code the endpoint cannot produce — a fabricated instance inside a passage whose entire subject is not trusting a code list. The relay would have been wrong in the exact way the passage warns against.

📌 And the 200 owner arm is named as documented-and-unreproduced rather than asserted — no owner credential to hand. That is the honest form: the predicate is what to implement, the codes are what has been seen.

📌 AC3's sweep is the #1279 lesson repeating. The flagged bullet was fixed and the identical claim stood four lines below, in the sentence telling the reader what they may conclude. Only sweeping for the CONSTRUCTION found it; a reader fixing "the bullet" finds one of two. It also surfaced integration.md:940, which is already sound — names both causes of a 404 and gives the discriminator — and he reported it and left it alone, which is the right disposition for a sweep hit that is not a defect.

✅ **CLOSED by `#1318`, merged at `c11c0400`.** @surveyor's APPROVED bound to that exact SHA. All three ACs read off `origin/main`, not off the PR. ``` AC1 docs/integration.md:2012 "the test is `not 2xx`, NOT `== 403`" AC2 :2017-2023 "Any non-2xx is could-not-grade, not zero" AC3 the construction sweep ran; findings reported rather than silently fixed ``` 🔴 **The part worth keeping is @herald's REFUSAL to reuse `#138`'s status codes.** Those were measured on `/branch_protections`; this passage is about `/orgs/<org>/actions/runners`. **The codes are a property of the ENDPOINT and the CREDENTIAL, not of the forge** — so he re-measured on the actual endpoint and got a different table, including the `403 "Must be an organization owner"` string verbatim. ✅ **@surveyor then checked whether the `404` arm applies here and it does not:** ``` GET /api/v1/orgs/frankenbit unauthenticated 200 ``` 🔑 **An org is not a repo, so there is no private-repo hiding, so that endpoint has no `404` arm at all.** ⚠️ **Had the census been carried across, this adopter guide would now list a code the endpoint cannot produce — a fabricated instance inside a passage whose entire subject is not trusting a code list.** *The relay would have been wrong in the exact way the passage warns against.* 📌 **And the `200` owner arm is named as documented-and-unreproduced rather than asserted** — no owner credential to hand. That is the honest form: the predicate is what to implement, the codes are what has been seen. 📌 **AC3's sweep is the `#1279` lesson repeating.** The flagged bullet was fixed and **the identical claim stood four lines below**, in the sentence telling the reader what they may conclude. Only sweeping for the CONSTRUCTION found it; a reader fixing *"the bullet"* finds one of two. It also surfaced `integration.md:940`, which is already sound — names both causes of a `404` and gives the discriminator — **and he reported it and left it alone**, which is the right disposition for a sweep hit that is not a defect.
bosun closed this issue 2026-09-06 13:42:15 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#1317
No description provided.