Skip to content

feat: bounty lifecycle for plugin requests - #29

Merged
debba merged 5 commits into
mainfrom
feat/request-bounty-lifecycle
Oct 13, 2026
Merged

debba merged 5 commits into
mainfrom
feat/request-bounty-lifecycle

Conversation

@debba

@debba debba commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Closes #28. Website counterpart: TabularisDB/website#34.

What changes

Plugin requests become the backend of the tabularis.dev Bounty Board.

Status Visible to Reached by
pending admins, requester every new request
approved everyone admin approval in /admin/requests, with bounty metadata
rejected admins, requester admin rejection (optional reason)
fulfilled everyone a plugin with the same slug is approved and has an ingested manifest

A claim never closes a request: an approved request with claims shows as in progress until the plugin is in the catalog. Claims stay non-exclusive.

API

  • Migration (SQLite, Postgres, MySQL):
    • plugin_requests gets status, review fields, fulfilled_plugin_id/fulfilled_at, bounty (JSON) and updated_at.
    • plugin_request_claims gets repo_url/scaffolded_at.
    • Existing requests migrate to approved.
  • GET /api/requests:
    • Gets a status filter. The default is approved,fulfilled; pending and rejected are returned only to admins and to the requester.
    • Each request now includes bounty, claimers (with GitHub avatar and repo), votedByMe and fulfilledPlugin.
  • GET /api/requests/:idOrSlug is new.
  • PATCH /api/admin/requests/:id (adminUpdateRequest) approves, rejects, reopens or fulfills a request and edits its bounty metadata.
  • Claims and upvotes only accept approved requests. Releasing a claim always works.
  • Fulfillment no longer deletes the request at submit. fulfillRequestForPlugin runs:
    • on admin approval (single and bulk);
    • whenever a manifest is applied.
  • POST /api/requests/:id/scaffold (scaffoldRequest):
    • Runs the published @tabularis/create-plugin@0.4.1 CLIs (driver or theme) in a temp dir, with name = request slug.
    • Creates the repo (user or org) and pushes a single initial commit through the Git Data API, then records the repo on the claim.
    • GitHub needs the workflow scope to push CI files. When it's missing, the endpoint returns 403 with a reauthUrl. That URL calls /auth/:instance?scope=workflow, which adds the scope only on demand.
  • Webhook events: request.approved, request.rejected, request.claimed, request.unclaimed, request.scaffolded, request.fulfilled. There is also a Static site rebuild preset (deploy hook).
  • GET /auth/return?to= sends an already signed-in user back to an ALLOWED_ORIGINS URL. safeReturnTo moved to lib/return-to.ts.
  • bun run import:bounties [file-or-url] [--map a=b] [--dry-run] imports the 31 curated bounties from the website. It is idempotent per slug: shipped entries are linked to their plugin, and entries built into the app stay unlinked.
  • The Dockerfile keeps the create-plugin template READMEs out of the *.md prune.

Frontend

  • /admin/requests: a review queue with Pending, Approved, Shipped and Rejected tabs, plus an editor for the bounty details. A badge on the nav shows how many requests are pending.
  • /requests:
    • Shows pending (your own), in progress and shipped badges, the claimers with their repos, a link to the shipped plugin, and the votes you've cast.
    • Adds a Start building dialog that creates the scaffolded repo and shows the local command (npm create @tabularis/plugin@latest <slug>).
  • /login: if you're already signed in, it now follows a trusted absolute return_to (through /auth/return) instead of sending you to /.
  • /submit?repo=<url> preselects the repository.
  • en and it messages; other locales fall back to en.

Deploy notes

  • After migrating, run bun run import:bounties against production once. Check it first with --dry-run.
  • Create a webhook with the Static site rebuild preset for request.approved, request.rejected, request.claimed, request.unclaimed and request.fulfilled, pointing at the tabularis.dev Vercel deploy hook.
  • packages/tabularium-rs/openapi.json is left for the next SDK release refresh, as usual.

Testing

  • bun test (api): 630 pass. New suites: request-lifecycle.test.ts and request-scaffold.test.ts (with GitHub mocked; the real CLI runs). The /auth/return test is in safe-return-to.test.ts.
  • bun run check (frontend): 0 errors, 0 warnings. bun test tests (frontend): 35 pass.
  • I ran the importer twice against a fresh SQLite DB: the first run created 31 requests, the second updated the same 31.
  • Not exercised against real GitHub: creating the repo and the workflow re-authorization.

debba added 3 commits October 13, 2026 22:09
…nties

Requests now go through pending -> approved/rejected -> fulfilled and carry
bounty board metadata. Claims stay non-exclusive and can record the
repository scaffolded for them with @tabularis/create-plugin. A request ships
when the plugin with its slug is approved and has an ingested manifest,
instead of being deleted at submit. Every transition emits a request.*
webhook, and a deploy-hook preset rebuilds static sites that bake the data in.

Also adds GET /auth/return so an already signed-in user is sent back to a
trusted origin, the optional GitHub workflow scope, and a one-off importer
for the tabularis.dev bounty list.

Refs #28
…affolding

/admin/requests reviews pending requests and edits their bounty details.
/requests shows review, in-progress and shipped states, claimers with their
repositories, the viewer's votes, and a Start building dialog that creates
the scaffolded repository. /login follows a trusted absolute return_to when
already signed in, and /submit preselects ?repo=.

Refs #28
@debba debba self-assigned this Oct 13, 2026
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
tabularium-docs Skipped Skipped Oct 13, 2026 8:22pm UTC
tabularium-website Skipped Skipped Oct 13, 2026 8:22pm UTC

Request Review

get_request, toggle_upvote, toggle_request_claim and scaffold_request run as
the delegated user (votedByMe/claimedByMe, workflow-scope answer), and
admin_update_request reviews pending requests as the admin, audited.

Refs #28
@debba

debba commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Added MCP coverage (tests/routes/mcp-requests.test.ts): the new operations are exposed as get_request, scaffold_request (requests:write) and admin_update_request (admin:requests:write). They are tested end to end through the MCP SDK as the delegated user and admin, alongside the existing list_requests, toggle_upvote and toggle_request_claim. MCP scope docs are updated. API suite: 633 pass.

@vercel
vercel Bot temporarily deployed to Preview – tabularium-website October 13, 2026 20:20 Inactive
German, Spanish, French and Simplified Chinese for the request lifecycle,
admin review and Start building dialog.

Refs #28
@vercel
vercel Bot temporarily deployed to Preview – tabularium-docs October 13, 2026 20:22 Inactive
@vercel
vercel Bot temporarily deployed to Preview – tabularium-website October 13, 2026 20:22 Inactive
@debba
debba merged commit ea7f4ad into main Oct 13, 2026
11 checks passed

This branch was previously deployed

2 inactive deployments
Preview – tabularium-website — 064538bd Deployed Oct 13, 2026 by vercel[bot]
Preview – tabularium-docs — 064538bd Deployed Oct 13, 2026 by vercel[bot]
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.

[Feat]: Bounty lifecycle for plugin requests (review, in-progress claims, scaffolded repos, fulfillment, webhooks)

1 participant