Skip to content

fix(openapi): give every 401-declaring operation the credential it actually wants (#9707) - #9758

Merged
JSONbored merged 1 commit into
mainfrom
fix/openapi-internal-security-9707
Jul 29, 2026
Merged

fix(openapi): give every 401-declaring operation the credential it actually wants (#9707)#9758
JSONbored merged 1 commit into
mainfrom
fix/openapi-internal-security-9707

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #9707.

The defect

applySecurityMetadata only fills a stanza in when requiresApiToken(path) is true. That returns false for /v1/internal/* and for the anchor-attempt ingest — not because either is open, but because each carries its own credential check. So those operations ended up with the security key entirely absent while still publishing a 401.

[] and undefined are not the same claim. [] is OpenAPI's explicit "this operation needs no credential"; undefined is "not stated". An operation that declares a 401 while saying nothing leaves a generated client with no credential to send, and a reader unable to tell it apart from a genuinely public route.

The existing parity tests are structurally blind to it: both filter on operation.security being present, so an absent stanza satisfies neither.

The fix

The five named operations move to registerRouteSpec entries that declare their auth, so the stanza derives from the declaration rather than from a second path-prefix model of the same policy. The four /v1/internal/* ones emit LoopOverBearer; the anchor-attempt ingest emits OrbBearer, since LOOPOVER_LEDGER_ANCHOR_REPORT_TOKEN is an ingest bearer and not a LoopOver API token.

Every response code survives the move, including the 503 and the 413/422 pair. The provider segment keeps its claude-code | codex enum — registerRouteSpec now accepts a declared params that overrides the derived z.string() one, for the rare closed-set segment.

The assertion pulled in three more families

The new test asserts that no operation declares a 401 with an absent stanza. That turned up eight offenders, not five, and each needed a different answer:

Answer
POST /v1/github/webhook Genuinely gated, by an HMAC over the raw body — it now declares the signature scheme
The three device-flow entry points How a caller obtains a credential; their 401 means "that code is not authorized", not "you forgot a token" → public, which emits []
POST /v1/auth/logout Revokes whatever identity the request carries and answers 200 either way → public too; advertising a credential would be a requirement no gate enforces
Three /v1/internal/jobs/* routes Gated by the same middleware as every sibling; left silent only because they had no /run form to be tabled with

Those last three are also #9706's territory. This PR moves only their auth declaration, because the assertion cannot pass while they stay silent; #9706 still owns that family's duplicate registrations and misreported statuses.

Fix-what-you-find

OrbWebhookSignature published name: "x-loopover-signature" — a string that appears nowhere else in src/. Both webhook handlers read x-hub-signature-256 (src/orb/webhook.ts:25, src/github/webhook.ts:101). A client generated from this document signed the right body and sent it under a header the server never looks at, earning a 401 it could not diagnose.

Validation

  • Both new assertions fail on main: expected [ 'POST /v1/github/webhook', …(12) ] to deeply equal [] and expected 'x-loopover-signature' to be 'x-hub-signature-256'.
  • Regenerated openapi.json confirms it: 0 operations declare a 401 without a scheme, down from 13.
  • npx vitest run --changed=origin/main: 1923 passed, 143 files. tsc --noEmit clean; the ratchet passes in both directions.

…tually wants (#9707)

applySecurityMetadata only fills a stanza in when requiresApiToken(path) is true, and that
returns false for /v1/internal/* and for the anchor-attempt ingest -- not because either is
open, but because each carries its OWN credential check. Those operations therefore ended up
with the security key entirely ABSENT while still publishing a 401. `[]` and undefined are not
the same claim: `[]` is OpenAPI's explicit "this operation needs no credential", undefined is
"not stated". A generated client for the provider-credential rotation surface had no credential
to send, and a reader could not tell those routes apart from a genuinely public one.

The five named operations move to registerRouteSpec entries that declare their auth, so the
stanza derives from the declaration rather than from a second path-prefix model of the same
policy. The four internal ones emit LoopOverBearer; the anchor-attempt ingest emits OrbBearer,
since LOOPOVER_LEDGER_ANCHOR_REPORT_TOKEN is an ingest bearer and not a LoopOver API token.
Every response code survives the move, including the 503 and the 413/422 pair, and the
provider segment keeps its claude-code | codex enum -- registerRouteSpec now accepts a declared
`params` that overrides the derived string one, for the rare closed-set segment.

The new assertion is that NO operation declares a 401 with an absent stanza, which turned up
three more families the two existing parity tests are blind to (both filter on security being
present, so an absent one satisfies neither). The GitHub webhook is genuinely gated and now
says so; the device-flow entry points are how a caller OBTAINS a credential, so they declare
`public` -- their 401 means "that code is not authorized", not "you forgot a token"; and three
internal job routes were left silent only because they had no /run sibling to be tabled with.
#9706 still owns that family's duplicate registrations and misreported statuses.

Fix-what-you-find: OrbWebhookSignature published `x-loopover-signature`, a string that appears
nowhere else in src/. Both webhook handlers read `x-hub-signature-256`, so a client generated
from this document signed the right body and sent it under a header the server never looks at,
earning a 401 it could not diagnose.
@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-29 07:23:26 UTC

6 files · 1 AI reviewer · no blockers · readiness 83/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR closes #9707 by giving five credential-gated operations (four /v1/internal/* routes plus the anchor-attempt ingest) a declared `auth` on their `registerRouteSpec` entries so the security stanza derives from the declaration rather than the broken `requiresApiToken` path-prefix heuristic, and adds a parity test asserting no operation publishes a 401 with an undefined `security` key. The assertion correctly widened scope to eight offenders (webhook signature header fix, three device-flow endpoints, logout, three internal job routes), and the diff traces each fix to the right layer — moving `registerPath` calls out of spec.ts into the declarative tables and deleting the old duplicate registrations. The webhook signature header correction (`x-loopover-signature` → `x-hub-signature-256`) is grounded with concrete file:line citations to both handlers reading the correct header, and the openapi.json diff matches the source changes for every route inspected.

Nits — 6 non-blocking
  • The description claims the eight offenders include 'three job routes... gated by the /v1/internal/* middleware like every one of their siblings,' but the diff moves them into `SILENT_401` rather than `CREDENTIAL_GATED` alongside the other four /v1/internal/* routes with no explanation for the split — worth a one-line comment distinguishing the two buckets beyond just narrative grouping.
  • src/openapi/define-route.ts:157 — `params` overriding logic duplicates the derived-vs-declared ternary inline; a named helper would make the precedence read clearer at the call site.
  • The external brief flags a low test-to-code ratio (0.11); the two new assertions in openapi-security-parity.test.ts are structural (spec-shape checks) rather than route-behavior tests, so per-route auth correctness (e.g., that `/v1/decision-ledger/anchor-attempts` really requires `OrbBearer` and not `LoopOverBearer`) relies on the broad parity sweep rather than a targeted case.
  • Consider a short top-of-file comment in internal-and-public-route-specs.ts noting why the three job routes landed in SILENT_401 instead of CREDENTIAL_GATED, since both buckets are /v1/internal/* auth-only moves.
  • Since openapi(internal-jobs): de-duplicate job operations and publish real handler statuses #9706 is cited as owning 'the wider cleanup' of the job-route family, link it explicitly in the SILENT_401 comment or PR description to avoid the reader having to guess the boundary between this fix and that follow-up.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #9707
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 14 registered-repo PR(s), 13 merged, 359 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 14 PR(s), 359 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The PR moves all five named operations (three provider-credentials, bounties/import, anchor-attempts) into SpecEntry rows with explicit auth ('internal' or 'orb'), removes the corresponding registerPath blocks from spec.ts, preserves the 503/413/422 response codes, adds the required 'no absent security with 401' test asserting an empty offender list, and updates the openapi.json with the correct L

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: not available
  • Official Gittensor activity: 14 PR(s), 359 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 4 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Decision record
  • action: merge · clause: success
  • config: 19beb4c3290f8700058ff8a483aa62cd039f22df6a152306fe2b044b18b785e1 · pack: oss-anti-slop · ci: passed
  • record: d3958d49f01479729a57bc4c867a0dd55936b6a883bbe1a7bad4a50cda91ef5a (schema v5, head 1e19944)
Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before /
before /
after /
after /
/ mobile before / (mobile)
before / (mobile)
after / (mobile)
after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

Scroll preview
Route Before (production) After (this PR's preview)
/ before / (scroll)
before / (scroll)
after / (scroll)
after / (scroll)

A short scroll-through clip (desktop) — click either thumbnail to open the full animation. Evidence for scroll-linked behavior a single screenshot can't show.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored self-assigned this Jul 29, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
loopover-ui 1e19944 Commit Preview URL

Branch Preview URL
Jul 29 2026, 07:00 AM

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 731 bytes (0.01%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
loopover-ui 7.81MB 731 bytes (0.01%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: loopover-ui

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/add-scalar-classes-BnHY5uVm.js (New) 2.16MB 2.16MB 100.0% 🚀
assets/tanstack-vendor-gopR17mF.js (New) 914.41kB 914.41kB 100.0% 🚀
openapi.json 499 bytes 715.25kB 0.07%
assets/docs.fumadocs-spike-api-reference-CZWLQldh.js (New) 443.45kB 443.45kB 100.0% 🚀
assets/AgentScalarChatInterface.vue-BDt8ncwb.js (New) 201.7kB 201.7kB 100.0% 🚀
assets/modal-j8IcsL2_.js (New) 184.5kB 184.5kB 100.0% 🚀
assets/client-BznQraoz.js (New) 151.47kB 151.47kB 100.0% 🚀
assets/maintainer-panel-BKHY5aJk.js (New) 78.99kB 78.99kB 100.0% 🚀
assets/routes-DmeFSX8Y.js (New) 35.96kB 35.96kB 100.0% 🚀
assets/owner-panel-qInmqo7U.js (New) 27.92kB 27.92kB 100.0% 🚀
assets/app-BY3Sc2ko.js (New) 25.78kB 25.78kB 100.0% 🚀
assets/ui-vendor-Cvt5jSzJ.js (New) 24.57kB 24.57kB 100.0% 🚀
assets/miner-panel-k3-6H4jh.js (New) 20.24kB 20.24kB 100.0% 🚀
assets/app.runs-Cls0Yini.js (New) 20.22kB 20.22kB 100.0% 🚀
assets/api._op-Bu53w3VP.js (New) 17.57kB 17.57kB 100.0% 🚀
assets/self-hosting-docs-audit-D8Z75SLI.js (New) 16.6kB 16.6kB 100.0% 🚀
assets/docs._slug-DHhaHFMY.js (New) 15.52kB 15.52kB 100.0% 🚀
assets/playground-panel-n_rVv_4f.js (New) 14.42kB 14.42kB 100.0% 🚀
assets/fairness-B9pn97gE.js (New) 12.16kB 12.16kB 100.0% 🚀
assets/app.audit-BFNSKI3Q.js (New) 10.08kB 10.08kB 100.0% 🚀
assets/app.config-generator-CCnUUImh.js (New) 10.06kB 10.06kB 100.0% 🚀
assets/maintainers-B0-ahFas.js (New) 8.06kB 8.06kB 100.0% 🚀
assets/miners-DfxO4Miy.js (New) 7.91kB 7.91kB 100.0% 🚀
assets/agents-TWV16pts.js (New) 7.74kB 7.74kB 100.0% 🚀
assets/commands-panel-DGP0VDLl.js (New) 6.65kB 6.65kB 100.0% 🚀
assets/maintainer-workflow-kQNbVWLl.js (New) 6.52kB 6.52kB 100.0% 🚀
assets/digest-panel-pIhckz8h.js (New) 6.15kB 6.15kB 100.0% 🚀
assets/repos._owner._repo.quality-Vto6bo3t.js (New) 6.14kB 6.14kB 100.0% 🚀
assets/docs-nav-VYh7_Kx5.js (New) 6.01kB 6.01kB 100.0% 🚀
assets/docs.index-Z6fHPLKa.js (New) 5.95kB 5.95kB 100.0% 🚀
assets/api.index-9aWIW_Hq.js (New) 4.7kB 4.7kB 100.0% 🚀
assets/docs-BemzBQnd.js (New) 2.7kB 2.7kB 100.0% 🚀
assets/api-Bzd0GSzk.js (New) 2.69kB 2.69kB 100.0% 🚀
assets/docs-page-cU1AIpya.js (New) 2.1kB 2.1kB 100.0% 🚀
assets/table-xxyDZalR.js (New) 1.75kB 1.75kB 100.0% 🚀
assets/app.workbench-D4RzwJJj.js (New) 1.58kB 1.58kB 100.0% 🚀
assets/tabs-hc6d2ZLv.js (New) 1.39kB 1.39kB 100.0% 🚀
assets/app.repos-hYeO1VTe.js (New) 1.07kB 1.07kB 100.0% 🚀
assets/input-5nKtO_QE.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/file-cog-BCbuKhKF.js (New) 758 bytes 758 bytes 100.0% 🚀
assets/app.maintainer-D3Tlhmgp.js (New) 502 bytes 502 bytes 100.0% 🚀
assets/app.owner-BwdnqF62.js (New) 474 bytes 474 bytes 100.0% 🚀
assets/app.commands-D_bFyDCP.js (New) 455 bytes 455 bytes 100.0% 🚀
assets/app.playground-BQEb_Tlc.js (New) 442 bytes 442 bytes 100.0% 🚀
assets/index-0KtxvBws.js (New) 438 bytes 438 bytes 100.0% 🚀
assets/app.digest-C8KNehFb.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/eye-off-upnp6ti6.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/app.miner-BES3tiy7.js (New) 422 bytes 422 bytes 100.0% 🚀
assets/key-round-BcHmUncq.js (New) 355 bytes 355 bytes 100.0% 🚀
assets/bot-Vflida55.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/trash-2-Buw-6ZKx.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/save-CF_tbrf1.js (New) 327 bytes 327 bytes 100.0% 🚀
assets/git-pull-request-arrow-Bu6nchrw.js (New) 321 bytes 321 bytes 100.0% 🚀
assets/list-checks-BALOt43W.js (New) 279 bytes 279 bytes 100.0% 🚀
assets/compass-8zbm3mLi.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/history-CqaxdqbK.js (New) 237 bytes 237 bytes 100.0% 🚀
assets/message-square-kY-q7LWC.js (New) 233 bytes 233 bytes 100.0% 🚀
assets/lock-BZ0jo8aB.js (New) 206 bytes 206 bytes 100.0% 🚀
assets/rotate-cw--qlZFpoj.js (New) 201 bytes 201 bytes 100.0% 🚀
assets/play-DhccWzL1.js (New) 190 bytes 190 bytes 100.0% 🚀
assets/circle-check-CW2tsKuv.js (New) 178 bytes 178 bytes 100.0% 🚀
assets/search-UyJfSfKb.js (New) 174 bytes 174 bytes 100.0% 🚀
assets/add-scalar-classes-2SL-Rzs2.js (Deleted) -2.16MB 0 bytes -100.0% 🗑️
assets/tanstack-vendor-BwlvtABd.js (Deleted) -914.18kB 0 bytes -100.0% 🗑️
assets/docs.fumadocs-spike-api-reference-BRXvqice.js (Deleted) -443.45kB 0 bytes -100.0% 🗑️
assets/AgentScalarChatInterface.vue-JTsh0nvN.js (Deleted) -201.7kB 0 bytes -100.0% 🗑️
assets/modal-CIC-O_5q.js (Deleted) -184.5kB 0 bytes -100.0% 🗑️
assets/client-Cyr7nRmY.js (Deleted) -151.47kB 0 bytes -100.0% 🗑️
assets/maintainer-panel-Cp0aaZo7.js (Deleted) -78.99kB 0 bytes -100.0% 🗑️
assets/routes-D0DSNxQw.js (Deleted) -35.96kB 0 bytes -100.0% 🗑️
assets/owner-panel-CqBS3rDM.js (Deleted) -27.92kB 0 bytes -100.0% 🗑️
assets/app-Cojn4Gvu.js (Deleted) -25.78kB 0 bytes -100.0% 🗑️
assets/ui-vendor-Dt6M7DxF.js (Deleted) -24.57kB 0 bytes -100.0% 🗑️
assets/miner-panel-CQvjOZXh.js (Deleted) -20.24kB 0 bytes -100.0% 🗑️
assets/app.runs-BzEyLeQ8.js (Deleted) -20.22kB 0 bytes -100.0% 🗑️
assets/api._op-BbLM0eAQ.js (Deleted) -17.57kB 0 bytes -100.0% 🗑️
assets/self-hosting-docs-audit-c9PnxQeV.js (Deleted) -16.6kB 0 bytes -100.0% 🗑️
assets/docs._slug-C_jeRW4p.js (Deleted) -15.52kB 0 bytes -100.0% 🗑️
assets/playground-panel-kz0_aeDT.js (Deleted) -14.42kB 0 bytes -100.0% 🗑️
assets/fairness-DvZUVzLG.js (Deleted) -12.16kB 0 bytes -100.0% 🗑️
assets/app.audit-*.js (Deleted) -10.08kB 0 bytes -100.0% 🗑️
assets/app.config-generator-Coh7tzzI.js (Deleted) -10.06kB 0 bytes -100.0% 🗑️
assets/maintainers-5t-HpI9d.js (Deleted) -8.06kB 0 bytes -100.0% 🗑️
assets/miners-CCzRuLBu.js (Deleted) -7.91kB 0 bytes -100.0% 🗑️
assets/agents-CrQZUoJD.js (Deleted) -7.74kB 0 bytes -100.0% 🗑️
assets/commands-panel-oQKf-h-q.js (Deleted) -6.65kB 0 bytes -100.0% 🗑️
assets/maintainer-workflow-DXgdGxxw.js (Deleted) -6.52kB 0 bytes -100.0% 🗑️
assets/digest-panel-CCbk6rTm.js (Deleted) -6.15kB 0 bytes -100.0% 🗑️
assets/repos._owner._repo.quality-S7Qkc1PF.js (Deleted) -6.14kB 0 bytes -100.0% 🗑️
assets/docs-nav-BlIzMLO8.js (Deleted) -6.01kB 0 bytes -100.0% 🗑️
assets/docs.index-B0WcOk-b.js (Deleted) -5.95kB 0 bytes -100.0% 🗑️
assets/api.index-DLwpJvJk.js (Deleted) -4.7kB 0 bytes -100.0% 🗑️
assets/docs-CK5pbQGa.js (Deleted) -2.7kB 0 bytes -100.0% 🗑️
assets/api-CyG75yOm.js (Deleted) -2.69kB 0 bytes -100.0% 🗑️
assets/docs-page-C3G0iEfn.js (Deleted) -2.1kB 0 bytes -100.0% 🗑️
assets/table-CZv0xQge.js (Deleted) -1.75kB 0 bytes -100.0% 🗑️
assets/app.workbench-61yEF8-c.js (Deleted) -1.58kB 0 bytes -100.0% 🗑️
assets/tabs-4WGVrzeG.js (Deleted) -1.39kB 0 bytes -100.0% 🗑️
assets/app.repos-DVj6_oee.js (Deleted) -1.07kB 0 bytes -100.0% 🗑️
assets/input-D9J2WXQd.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/file-cog-Dop_7mwQ.js (Deleted) -758 bytes 0 bytes -100.0% 🗑️
assets/app.maintainer-Dm8n-jh-.js (Deleted) -502 bytes 0 bytes -100.0% 🗑️
assets/app.owner-IVMtAv_5.js (Deleted) -474 bytes 0 bytes -100.0% 🗑️
assets/app.commands-BWAUUWOc.js (Deleted) -455 bytes 0 bytes -100.0% 🗑️
assets/app.playground-DMsq4Zar.js (Deleted) -442 bytes 0 bytes -100.0% 🗑️
assets/index-Dbsba8fU.js (Deleted) -438 bytes 0 bytes -100.0% 🗑️
assets/app.digest-Dtbar_vt.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/eye-off-B6WzhEjg.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/app.miner-1XOFPe9a.js (Deleted) -422 bytes 0 bytes -100.0% 🗑️
assets/key-round-DH1JGu5F.js (Deleted) -355 bytes 0 bytes -100.0% 🗑️
assets/bot-denl_M7C.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/trash-2-DaR2EU1B.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/save-BJ-b5LyN.js (Deleted) -327 bytes 0 bytes -100.0% 🗑️
assets/git-pull-request-arrow-irQTyjxI.js (Deleted) -321 bytes 0 bytes -100.0% 🗑️
assets/list-checks-BHEhNgEx.js (Deleted) -279 bytes 0 bytes -100.0% 🗑️
assets/compass-Be02QJ3n.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/history-BL3pWnqF.js (Deleted) -237 bytes 0 bytes -100.0% 🗑️
assets/message-square-BGcb528s.js (Deleted) -233 bytes 0 bytes -100.0% 🗑️
assets/lock-JqKClIvJ.js (Deleted) -206 bytes 0 bytes -100.0% 🗑️
assets/rotate-cw-BZoK1WU4.js (Deleted) -201 bytes 0 bytes -100.0% 🗑️
assets/play-DvF2zpmk.js (Deleted) -190 bytes 0 bytes -100.0% 🗑️
assets/circle-check-DMw1swAr.js (Deleted) -178 bytes 0 bytes -100.0% 🗑️
assets/search-DxPOWxyH.js (Deleted) -174 bytes 0 bytes -100.0% 🗑️

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 29, 2026
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.45%. Comparing base (e95afc0) to head (1e19944).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9758      +/-   ##
==========================================
- Coverage   90.27%   89.45%   -0.82%     
==========================================
  Files         904      904              
  Lines      113213   113210       -3     
  Branches    26859    26859              
==========================================
- Hits       102202   101275     -927     
- Misses       9680    10846    +1166     
+ Partials     1331     1089     -242     
Flag Coverage Δ
backend 94.06% <100.00%> (-1.48%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/openapi/define-route.ts 97.22% <100.00%> (ø)
src/openapi/internal-and-public-route-specs.ts 100.00% <100.00%> (ø)
src/openapi/spec.ts 99.28% <ø> (-0.02%) ⬇️

... and 3 files with indirect coverage changes

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@JSONbored
JSONbored merged commit 7e3986f into main Jul 29, 2026
11 checks passed
@JSONbored
JSONbored deleted the fix/openapi-internal-security-9707 branch July 29, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openapi(security): five credential-gated operations publish a 401 with no security scheme

1 participant