Repository navigation
Batch 2026-08-26-2: rate caps & scheduling, real availability, entitlements editor, Gotify/Zulip, support preflight - #269
Merged
Merged
Conversation
…age, validate warnings, superadmin entitlements Five specs born from the 2026-08-26 public-org rate-limit starvation incident (a 1-min check silently skipped for 7.5h while its org sat 2x over its MaxChecksPerMinute cap). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…itlements payload
… threads it cannot possibly answer Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The generated /docs/api pages bake the spec's servers: list in at build time, so every self-hosted instance advertised https://solidping.io and a reader copying an example aimed it at a host they do not run. A swizzled Base URL control (docusaurus-theme-openapi-docs@5.0.2) now offers the current origin first — except on a known docs host, where handlerWithDocsHost redirects API paths into the docs site and the spec's cloud entry is the correct answer. The spec's own servers stay selectable; only the order and the selection change.
Types for the swizzle: explicit re-exports from the theme slice, a relative import of the sibling slice, an ambient declaration for @theme/ApiItem/hooks, and the bun test files excluded from tsconfig.
The theme persists its own automatic default exactly as it persists a click, so the stored selection alone cannot tell the two apart and the host default was re-applied on every page mount. A sessionStorage marker records the URL we selected ourselves; when the restored selection differs from it, the reader chose it and we leave it alone. The resolved option list is still offered either way.
docsHostMatches strips the port from the request host but compares the configured host raw, so SP_DOCS_HOST="docs.acme.com:8443" is never redirected server-side, while the docs bundle's isKnownDocsHost strips the port from both and calls it a docs host. Hostname-only is what the bundle wants; changing the Go side would change which requests get redirected, so the divergence is named on both functions instead of silently fixed here. Also cross-references the build-time SP_DOCS_HOSTS from the runtime SP_DOCS_HOST config comment, since a prebuilt binary's docs bundle does not learn a self-hoster's docs host without a rebuild.
… Base URL Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four specs in this batch moved openapi.yaml: availability24h on the check stats aggregate, the bucketed availability endpoint, the superadmin entitlements editor, and the support reply pre-flight plus resend. Verified against the regenerated client: go build, golangci-lint (0 issues) and the full backend suite all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
/orgs/$org/checks/scheduling matched the `isChecks` breadcrumb branch but had neither a checkUid nor the `new` route id, so it fell through to the bare list rendering: a single non-clickable "Checks" crumb, identical to what the checks list page shows, with no leaf naming the page and no way to click back to the list. Add an `isScheduling` case that turns the section crumb into a back-link and appends a "Scheduling" leaf, mirroring how new/edit/result already work, plus the `nav.scheduling` key in all four locales. The E2E asserts both halves and was confirmed to fail against a build without the fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every ExampleRow put its preview in a bare grid item, and a grid item defaults to min-width:auto — so a preview whose intrinsic min-content is wider than the column widened the track instead of wrapping. At 375px the over-limit banner example (a w-full max-w-md card, 448px) did exactly that, pushing the document to 454px and giving the whole page a horizontal scrollbar. The guard was already half-present: the md grid used minmax(0,1fr), but only for the second (code) column, so neither the preview column nor the single-column mobile layout was covered. Put both tracks behind minmax(0,…) and give both children min-w-0. Verified by bisection: hiding #feedback was what dropped the document back to 375px, and after the fix no section widens it at all. Fixes the pre-existing failure in check-http-expected-status-codes.spec.ts:331, which measures whole-page overflow and so was reporting a #feedback bug from a #token-chips-input test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The E2E still encoded the pre-2026-08-26-04 link target. That spec retargeted the banner's remedy link from the Usage page to the check scheduling page, so the reader is handed the surface that can fix the overage rather than one restating the number just quoted. The unit tests moved with it; the E2E did not, and asserted the link was absent on Usage — where it is now deliberately present and no longer a self-link. Assert the destination rather than mere presence, so a future retarget cannot pass silently. Then put the "no self-link" assertion where it is actually true: the scheduling page, which had no coverage that it suppresses the link — the invariant the mis-placed assertion was reaching for. Diagnosis and proposal from specs/todos/2026-08-27-05-stale-rate-limit-banner-e2e-expectation.md. Its step 3 (renaming check-rate-limit-usage-link and org:checkRateLimit.viewUsage, whose names still say "usage") is deliberately left out: it touches files with in-flight uncommitted work, and the spec itself says to land steps 1-2 first in that case. On its step 4 — CI was not masking this behind a skipped E2E job. CI had simply never run on this branch: the batch accumulated 144 commits with zero pipeline runs until the PR was opened. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 27, 2026
Merged
fclairamb
added a commit
that referenced
this pull request
Aug 27, 2026
The batch landed as one squash commit with a non-conventional subject, so release-please parsed nothing from it and generated a v0.19.0 section listing only an unrelated Slack fix. Fill in what actually shipped: 30 features and 21 fixes, grouped by theme and attributed to #269. Only prose is added — the version header, compare link and every earlier section are untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merged
fclairamb
added a commit
that referenced
this pull request
Aug 27, 2026
## Why This repo squash-merges exclusively, and `squash_merge_commit_title` is `PR_TITLE`. A pull request title is therefore **not a label — it is the commit subject that lands on `main`**, and release-please (`release-type: simple`) parses exactly those subjects to pick the next version and build the changelog. Nothing checked that, and the failure is silent: release-please reports **success** while releasing nothing. The only tell is the release PR's head SHA never moving. [#269](#269) hit it. A 147-commit batch titled `Batch 2026-08-26-2: …` produced this on `main`: ``` e662950 Batch 2026-08-26-2: rate caps & scheduling, … (#269) ``` release-please found nothing releasable, so the release PR stayed pinned at `v0.18.4` — a patch whose changelog covered one unrelated Slack fix — while ~30 `feat` commits went unrecorded. Recovery needed a manual `Release-As:` override ([#270](#270)). ## What A `pull_request` job (`opened`, `edited`, `reopened`, `synchronize`) that validates the title as `<type>[(scope)][!]: <description>`. Allowed types track `release-please-config.json`'s `changelog-sections`, so the two cannot drift apart on what counts as releasable. On failure it writes an actionable job summary rather than only a red X. No third-party action — it is a few lines of bash, so there is no supply-chain surface. The title is passed via `env:` rather than inlined, since it is attacker-controlled text. ## Verified against the real corpus Rejects: both of #269's titles, `Update the readme`, `FEAT: …` (uppercase), `feat add …` (no colon), `feat:no space`. Accepts: `chore(release): v0.19.0` (release-please's own), `chore(deps): …` and `fix(deps): … (non-major)` (Renovate), `feat!: …`, and the repo's existing `fix(slack): …` / `fix(dash0): …` titles. An earlier draft also enforced a minimum description length. Testing showed it rejected `chore(release): v0.19.0` and would have broken **every future release** — dropped before shipping. ## Follow-up (needs a repo admin, not this PR) The job blocks nothing until it is a **required status check** on `main`. Once merged: ``` gh api -X PATCH repos/fclairamb/solidping/branches/main/protection/required_status_checks \ -f 'checks[][context]=Conventional commit title' ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integration branch for the 2026-08-26 spec batch (second run), plus follow-up fixes.
Highlights
Rate limits & fair rotation
effective_scheduled_atand rotate the deficit fairly across the org's checks instead of starving the same ones.checksPerMinutedemand/limit and daily skips exposed on the entitlements payload.Check scheduling page
/checks/schedulingpage that brings an org back under its per-minute rate cap: auto-rebalance proposal, a meter anchored on the server's own demand figure, a phone-usable table, and the period select floored at the server's 10s minimum.Internal-checks quota loophole
internalflag is refused on every check write path (create, update, import), OpenAPI no longer advertises it as writable, and internal checks draw no rate token on either gate. Includes a residue sweep query for upgrades.Check validation
Superadmin entitlements editor
Availability
Integrations
organization_providerslink no longer permanently bricks the Slack app install — both the Slack and Discord install paths heal it.Support
Docs
Follow-up fixes
Test plan
Each spec landed through the batch gate: backend suite, dash0 unit tests, targeted Playwright E2E,
tsc, and lint all green before itschore: all checks passingcommit, with an independent completeness audit per spec.🤖 Generated with Claude Code