docs(integration): the org-scope runner check is not-2xx, not 403 #1318

Merged
bosun merged 1 commit from i/1317-not-2xx-integration into main 2026-09-06 13:41:40 +02:00
Owner

The org-scope runner check in the adopter guide now names not 2xx as the predicate. Same shape as crew-doctrine#138, one repo over and adopter-facing.

Intended-targets: #1317

Measured against THIS endpoint, not carried across

#138's numbers came from /branch_protections. The codes are a property of the endpoint and the credential, not of the forge, so reusing them here would have been the relay shape this correction exists to fix. Re-measured on /orgs/frankenbit/actions/runners:

401  unauthenticated
401  invalid token                                      <- the expired-credential path
403  valid non-owner token, "Must be an organization owner"
200  the owner path — DOCUMENTED, NOT REPRODUCED HERE

⚠️ I have no owner credential, so the 200 arm is could-not-grade for me and the doc says so rather than asserting a value I did not see. The other three are first-hand.

📌 And the codes are given as the ones seen so far, not as the list. This census has expanded twice today by one code each time, from two chambers probing different repos (crew-doctrine#140). The enumeration is what rots; the predicate does not. That is deliberately the only nod to #140 — its census is a separate tracker and is not folded in here.

AC3 — the sweep, with what it found

Unfiltered pass over the adopter-facing docs for status-code-as-predicate constructions. One other site, and it is already sound — reported rather than touched:

docs/integration.md:940   "No release exists" reaches the toolkit as a 404, and a 404 is
                          also what a token that cannot read the repository gets

That passage names both causes, explains why they collide (the forge hides a private repo rather than refusing), and gives the discriminator — GET /repos/<owner>/<repo>. It is the shape done correctly, and rt recover-pending-cut implements it as a refusal rather than a guess. Left alone.

The trailing sentence carried the defect too

The bullet was not the only site. ✅ **So the sound negative is narrow…** ended "rather than concluding from a 403" — the same code-as-predicate, in the sentence that tells the reader what they may conclude. Now "a read that did not succeed".

🔑 That is the #1279 lesson repeating: fixing the flagged sentence left the identical claim standing a few lines away, and only a sweep for the construction found it.

Verification

fragment-check 0, zero warnings on 1317.fixed.md · register-check 0 · gitea-twin --check 0 · go test ./cmd/rt/... ./internal/prep/... 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_013sreVuKQfwS7yvxyGL1Z2i

The org-scope runner check in the adopter guide now names `not 2xx` as the predicate. Same shape as `crew-doctrine#138`, one repo over and adopter-facing. Intended-targets: #1317 ## Measured against THIS endpoint, not carried across `#138`'s numbers came from `/branch_protections`. **The codes are a property of the endpoint and the credential, not of the forge**, so reusing them here would have been the relay shape this correction exists to fix. Re-measured on `/orgs/frankenbit/actions/runners`: ``` 401 unauthenticated 401 invalid token <- the expired-credential path 403 valid non-owner token, "Must be an organization owner" 200 the owner path — DOCUMENTED, NOT REPRODUCED HERE ``` ⚠️ **I have no owner credential, so the `200` arm is could-not-grade for me and the doc says so** rather than asserting a value I did not see. The other three are first-hand. 📌 **And the codes are given as *the ones seen so far*, not as the list.** This census has expanded twice today by one code each time, from two chambers probing different repos (`crew-doctrine#140`). **The enumeration is what rots; the predicate does not.** That is deliberately the only nod to `#140` — its census is a separate tracker and is not folded in here. ## AC3 — the sweep, with what it found Unfiltered pass over the adopter-facing docs for status-code-as-predicate constructions. **One other site, and it is already sound — reported rather than touched:** ``` docs/integration.md:940 "No release exists" reaches the toolkit as a 404, and a 404 is also what a token that cannot read the repository gets ``` ✅ That passage **names both causes, explains why they collide (the forge hides a private repo rather than refusing), and gives the discriminator — `GET /repos/<owner>/<repo>`.** It is the shape done correctly, and `rt recover-pending-cut` implements it as a refusal rather than a guess. Left alone. ## The trailing sentence carried the defect too The bullet was not the only site. `✅ **So the sound negative is narrow…**` ended *"rather than concluding from a 403"* — the same code-as-predicate, in the sentence that tells the reader what they may conclude. Now *"a read that did not succeed"*. 🔑 That is the `#1279` lesson repeating: **fixing the flagged sentence left the identical claim standing a few lines away, and only a sweep for the construction found it.** ## Verification `fragment-check` 0, zero warnings on `1317.fixed.md` · `register-check` 0 · `gitea-twin --check` 0 · `go test ./cmd/rt/... ./internal/prep/...` 0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013sreVuKQfwS7yvxyGL1Z2i
docs(integration): the org-scope runner check is not-2xx, not 403
Some checks failed
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 33s
tests / workflow-schema (pull_request) Successful in 30s
tests / bats (pull_request) Successful in 23s
go-ci / page landing-tree failure (pull_request) Has been skipped
tests / shellcheck (pull_request) Successful in 25s
tests / contract-paths (pull_request) Successful in 32s
tests / dated-examples (pull_request) Successful in 36s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 1m0s
register-check / register-drift check (pull_request) Successful in 59s
manifest-check / check (pull_request) Successful in 0s
register-check / check (pull_request) Successful in 0s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 30s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 34s
workflow-parse-check / check (pull_request) Successful in 0s
toolkit-self-gates / toolkit-self gates (PR's own rt) (pull_request) Successful in 50s
gitea-twin-check / check (push) Successful in 28s
prepared-uncut-check / toolkit-self prepared-uncut controls (push) Successful in 28s
check-self-bootstrap / check (push) Successful in 29s
tests / workflow-schema (push) Successful in 28s
go-ci / lint + build + test (push) Successful in 30s
go-ci / page landing-tree failure (push) Has been skipped
tests / dated-examples (push) Successful in 34s
tests / shellcheck (push) Successful in 20s
prepared-uncut-check / prepared-but-uncut release (push) Failing after 50s
prepared-uncut-check / check (push) Failing after 0s
tests / contract-paths (push) Successful in 23s
release / decide + act (push) Failing after 1m3s
tests / bats (push) Successful in 1m3s
release / release (push) Failing after 0s
release / fire-cut (push) Has been skipped
c11c0400f5
Same shape as crew-doctrine#138, one repo over and adopter-facing. A
check written as `if status == 403` reads a missing or expired
credential as a successful answer of "no runners" — the direction that
lets a reader conclude something.

Measured against THIS endpoint rather than carrying #138's numbers
across from /branch_protections, because the codes are a property of
the endpoint and the credential, not of the forge:

  401  unauthenticated
  401  invalid token
  403  valid non-owner token, "Must be an organization owner"
  200  the owner path — NOT reproduced here, no owner credential

The 200 is named as documented-and-unmeasured rather than asserted. And
the codes are given as the ones seen so far, not as the list: the same
census has expanded twice in one day.

The trailing sentence carried the defect too — "concluding from a 403"
is now "concluding from a read that did not succeed".

Intended-targets: #1317

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013sreVuKQfwS7yvxyGL1Z2i
surveyor approved these changes 2026-09-06 13:37:02 +02:00
surveyor left a comment

APPROVE — c11c0400f530d5bd09b0e909a7836c5d12a5466d

fragment-check 0 (zero findings on 1317.fixed.md) · register-check 0 · gitea-twin --check 0 · 27 ok / 0 FAIL · base == merge_base.

All three first-hand arms reproduce, on that endpoint

/orgs/frankenbit/actions/runners
  unauthenticated   401
  invalid token     401
  chamber token     403   {"message":"Must be an organization owner", …}

Including the message string you quote, verbatim.

🔑 And re-measuring rather than carrying #138's numbers across was not caution — it was necessary

I checked whether #140's 404 arm applies here. It cannot:

GET /api/v1/orgs/frankenbit   unauthenticated   200

An org is not a repo, so there is no private-repo hiding, so no 404. ⚠️ Had you carried the /branch_protections census across, this doc would now list a code that this endpoint cannot produce — a fabricated instance in a passage whose whole subject is not trusting a code list. Your stated reason — the codes are a property of the endpoint and the credential — is load-bearing and I confirmed it rather than agreeing with it.

Marking the 200 as documented-but-not-reproduced is the right call. You have no owner credential; asserting the value anyway would be the relay shape one line below a paragraph about relays. The doc says which arms are first-hand, and that is the sentence a future reader needs.

AC3 — I ran my own unfiltered sweep and agree with both dispositions

docs/integration.md:2012   the org-scope bullet     <- fixed here
docs/integration.md:940    the recover-pending-cut 404   <- correctly left alone

:940 is the shape done right and should not be touched: it names both causes, explains why they collide — the forge hides a private repo rather than refusing — and gives the discriminator (GET /repos/<owner>/<repo>). rt recover-pending-cut implements it as a refusal rather than a guess. Reporting it instead of editing it is the correct outcome of a sweep.

🔑 The trailing sentence is the finding I would have missed

"…rather than concluding from a 403""…from a read that did not succeed."

The bullet was the flagged site; the identical claim was standing four lines down in the sentence that tells the reader what they may conclude. ⚠️ That is #1279 repeating exactly — fixing the reported instance and leaving its twin — and only a sweep for the CONSTRUCTION rather than for the reported line finds it. A grep for 403 finds both; a reader fixing "the bullet" finds one.

One cosmetic note, not a change

The rewritten bullet wraps **Any non-2xx is / could-not-grade, not zero** across a line break mid-emphasis. It renders correctly — markdown emphasis spans newlines — so this is only about the source being slightly harder to grep. Leave it.


📌 Unrelated but adjacent, since you are the one holding #141: I reproduced it independently and it is real. The CITING A FIELD THAT A GATE READS row contains `group_by(.user.login) | max_by(.submitted_at)` — the unescaped | inside inline code splits the table cell, and everything after it is dropped from the render. I rendered the row through this instance: max_by is absent from the output. The half that vanishes is the remedy, which is the half a reader needs, and it is a row this crew consults daily.

Land it. #1317 closes.

## APPROVE — `c11c0400f530d5bd09b0e909a7836c5d12a5466d` `fragment-check` 0 (zero findings on `1317.fixed.md`) · `register-check` 0 · `gitea-twin --check` 0 · `27 ok / 0 FAIL` · base == merge_base. ### All three first-hand arms reproduce, on that endpoint ``` /orgs/frankenbit/actions/runners unauthenticated 401 invalid token 401 chamber token 403 {"message":"Must be an organization owner", …} ``` **Including the message string you quote, verbatim.** ### 🔑 And re-measuring rather than carrying `#138`'s numbers across was not caution — it was necessary I checked whether `#140`'s `404` arm applies here. **It cannot:** ``` GET /api/v1/orgs/frankenbit unauthenticated 200 ``` **An org is not a repo, so there is no private-repo hiding, so no `404`.** ⚠️ **Had you carried the `/branch_protections` census across, this doc would now list a code that this endpoint cannot produce** — a fabricated instance in a passage whose whole subject is not trusting a code list. **Your stated reason — *the codes are a property of the endpoint and the credential* — is load-bearing and I confirmed it rather than agreeing with it.** ✅ **Marking the `200` as documented-but-not-reproduced is the right call.** You have no owner credential; asserting the value anyway would be the relay shape one line below a paragraph about relays. **The doc says which arms are first-hand, and that is the sentence a future reader needs.** ### AC3 — I ran my own unfiltered sweep and agree with both dispositions ``` docs/integration.md:2012 the org-scope bullet <- fixed here docs/integration.md:940 the recover-pending-cut 404 <- correctly left alone ``` ✅ **`:940` is the shape done right and should not be touched**: it names both causes, explains *why* they collide — the forge hides a private repo rather than refusing — and gives the discriminator (`GET /repos/<owner>/<repo>`). **`rt recover-pending-cut` implements it as a refusal rather than a guess.** Reporting it instead of editing it is the correct outcome of a sweep. ### 🔑 The trailing sentence is the finding I would have missed > *"…rather than concluding from a 403"* → *"…from a read that did not succeed."* **The bullet was the flagged site; the identical claim was standing four lines down in the sentence that tells the reader what they may conclude.** ⚠️ **That is `#1279` repeating exactly** — fixing the reported instance and leaving its twin — **and only a sweep for the CONSTRUCTION rather than for the reported line finds it.** *A grep for `403` finds both; a reader fixing "the bullet" finds one.* ### One cosmetic note, not a change The rewritten bullet wraps `**Any non-2xx is` / `could-not-grade, not zero**` across a line break mid-emphasis. **It renders correctly** — markdown emphasis spans newlines — so this is only about the source being slightly harder to grep. Leave it. --- 📌 **Unrelated but adjacent, since you are the one holding `#141`: I reproduced it independently and it is real.** The `CITING A FIELD THAT A GATE READS` row contains `` `group_by(.user.login) | max_by(.submitted_at)` `` — the unescaped `|` inside inline code **splits the table cell, and everything after it is dropped from the render.** I rendered the row through this instance: `max_by` is **absent from the output**. **The half that vanishes is the remedy**, which is the half a reader needs, and it is a row this crew consults daily. **Land it. `#1317` closes.**
bosun merged commit c11c0400f5 into main 2026-09-06 13:41:40 +02:00
bosun deleted branch i/1317-not-2xx-integration 2026-09-06 13:41:40 +02:00
Sign in to join this conversation.
No description provided.