Skip to content

fix: manager-scoped prepare, paced manual requests and per-repository index collection - #11

Merged
qiansc merged 1 commit into
mainfrom
fix/prepare-access-and-index-collection
Nov 4, 2026
Merged

qiansc merged 1 commit into
mainfrom
fix/prepare-access-and-index-collection

Conversation

@qiansc

@qiansc qiansc commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Background

  • Index preparation permission was an admin-only per-token flag ("Allow index preparation"). Preparation should follow repository management: site administrators, the service credential, and a repository's managers, whether through a session or their personal token.
  • Repeated triggers could add queue load. Identical in-flight work should be reused, and new manual work paced per repository.
  • Expired index generations piled up. Collection took the global exclusive lock, so any sync, index build, plugin read or disk sample anywhere skipped the round. It removed at most one generation a minute, discarded its errors and did not refresh disk usage. Expired indexes also counted against the repository budget, which could block the latest index, while manual cleanup required that latest index.

Changes

Prepare permission

  • AuthorizePrepare: site administrators and the service credential; personal tokens whose owner is currently an administrator; the repository's managers (session or token). Everyone else gets 403.
  • Personal tokens may call POST /api/admin/v1/repo/prepare; all other management routes stay closed to them.
  • MCP checks every call per repository and lists prepare only for tokens whose owner is an administrator or manages at least one repository (cached for a minute; failures fall back to read-only).
  • The token option and its allow_prepare field are removed. The field is still accepted and ignored on creation for cached pages.
  • The search page shows "Prepare this version" to repository managers too.

Pacing

  • A request identical to queued or running work (same group, kind and revision) returns that job.
  • New manual work from the website, HTTP or MCP is limited to one request per repository every 30 seconds; otherwise 429 RATE_LIMITED with Retry-After. One request queuing every monorepo group counts once. Scheduler and worker follow-up work, including head indexes after a manual sync, is not paced.
  • Idempotency receipts drop the oldest beyond 256 instead of returning QUEUE_FULL for the whole repository.

Index collection

  • Collection works repository by repository under that repository's own preparation slot. A busy repository is deferred to the next round instead of blocking the round. Each round has a 30-second budget with no one-generation cap, and the starting repository rotates.
  • Collection also runs right after a sync applies retention, and before a job would fail on the repository storage budget (then the budget is measured again).
  • After removal, the repository is marked for a fresh disk sample.
  • Status (pending expired generations and bytes, deferred repositories, last reclaim, last issue as a fixed code) is exposed in statistics and instance heartbeats, shown on the status page, and logged as index_collection.
  • Manual Clean old indexes falls back to removing only expired indexes when a latest index is not ready (expired_only in the preview), keeping every retained version's index and every job.

Risks

  • Collection no longer takes the global write lock. Retention revokes versions under the query lock, so collected generations have no readers. Builds of the same repository are excluded by the repository slot, and manifests younger than five minutes are never collected.
  • The first rounds after deployment may reclaim a large backlog, with brief disk IO.
  • Tokens of users who neither administer the site nor manage the repository can no longer prepare.

Backward compatibility

  • New persisted field manual_queued_at; when missing, there is no pacing. expired_only and index_collection are additive.
  • NewWithPrepareAuthorization now passes the repository to its guard (internal API).

Testing

  • New tests: pacing (join, refusal with retry-after, multi-group, worker follow-ups, receipt eviction); per-repository collection (busy deferral, young manifests, removed repositories, disk resample flag); reclaim before a budget refusal; expired-only cleanup fallback; prepare permission matrix.
  • go vet, go test ./... and node scripts/check-web.mjs pass.

🤖 Generated with Claude Code

… index collection

- Prepare: site administrators, the service credential and repository
  managers (session or personal token); personal tokens may call the HTTP
  prepare route; MCP lists prepare only for tokens that can use it. The
  admin-only "allow index preparation" token option is removed.
- Manual requests join identical queued or running work; new work is paced
  to one per repository every 30 seconds (429 RATE_LIMITED, Retry-After).
  Idempotency receipts drop the oldest instead of blocking the repository.
- Index collection runs per repository under its own slot with a 30-second
  round budget, after retention and before a storage-budget refusal, marks
  disk usage for resampling and reports its status; manual cleanup falls
  back to expired indexes when the latest index is not ready.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qiansc
qiansc merged commit 6b5734e into main Nov 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant