#!/usr/bin/env markdown
This plan reflects the agreed product flow:
- Anyone can explore + fund without login.
- Funding is blocked once a bounty is
LOCKED. - Only maintainers need login to approve payout from the web UI.
- Fallback maintainer approval via
/approvecomment on the issue. - Contributors must login once to link GitHub username to email for payout-by-email.
- Agents can supply a PR body tag
<!-- bountic-address: 0x... -->for wallet-native payout paths. - Users table primary key is
email.
Goal: align schema with the flow and remove assumptions that every actor has a GitHub username.
-
Update
userstable- Primary key:
email. github_username: non-null text, unique.- Store user profile metadata (optional): display name, avatar.
- Update RLS policies to use
auth.jwt() ->> 'email'as the identity anchor.
- Primary key:
-
Update
funding_eventstable- Add
funder_display_name(public, optional). - Add
funder_email(private, optional; present when authed). - Relax
funder_usernamerequirements (allow anonymous funding without a GitHub username). - Ensure ledger + UI can render funders without leaking emails.
- Add
-
Document machine tags
<!-- bountic-address: 0x... -->in PR body for agent payout.- Keep tags parseable and stable.
Goal: make funding frictionless and enforce "no funding after solved".
-
Bounty page funding card
- Amount input.
- Optional "Name" field (single line, small, non-blocking).
- No prompts.
-
POST /api/bounty/fund- Reject if bounty status is
LOCKEDorPAID. - If viewer is logged in: attach
funder_email(from Supabase session) and optionally a default name. - Always store
funder_display_nameif provided.
- Reject if bounty status is
-
Ledger + leaderboard
- Display priority for funders:
funder_display_name@funder_usernameAnonymous
- Display priority for funders:
Goal: allow contributors to claim payouts by linking GitHub username -> email.
-
Add minimal contributor login entry point
- A dedicated "Connect GitHub" route or button.
- On successful OAuth, upsert into
userswith:email(PK)github_username(non-null)- any optional profile fields.
-
Ensure we can resolve payout recipient email
- From bounty
winning_pr_author-> lookup inusers. - If missing:
- bounty stays
LOCKED - UI indicates "Winner must connect GitHub once to receive payout".
- bounty stays
- From bounty
Goal: maintainers can release escrow via UI or an issue comment.
-
Web approve (preferred)
- Keep
POST /api/bounty/[owner]/[repo]/issues/[issueNumber]/approve. - Requires GitHub OAuth session.
- Permission gate: admin/maintain/write.
- Verifies bounty is
LOCKED. - Verifies winner email exists.
- Executes payout (email-based) and marks bounty
PAID. - Inserts
payout_eventsandactivity_events. - Syncs GitHub ledger comment.
- Keep
-
GitHub comment approve (fallback)
- Re-enable
issue_comment.createdhandling. - Trigger on exact command
/approve(optionally allow leading/trailing whitespace). - Verify commenter has admin/maintain/write.
- Run the same payout flow as web approve.
- Re-enable
Goal: reliability and correctness under real webhook behavior.
-
Idempotency
- Dedupe GitHub deliveries by
x-github-delivery. - Dedupe Locus paid events by checkout id.
- Ensure repeated webhooks do not double-pay.
- Dedupe GitHub deliveries by
-
Consistency
- Ensure ledger sync is resilient to comment deletion / invalid ids.
- Ensure state transitions are monotonic:
OPEN -> LOCKED -> PAID.- No funding when
LOCKED/PAID.
-
Observability
- Structured logs for webhook handlers and payout.
- Clear error messages surfaced in UI for maintainers.
Goal: give logged-in users a reason to log in beyond payout eligibility.
-
Dashboard route (authenticated)
- Show:
- issues the user funded (by email when authed, plus optional name matching)
- bounties they have won (by github_username)
- payout statuses and references
- No public exposure of email.
- Show:
-
APIs
GET /api/meorGET /api/dashboardbacked by Supabase session.
-
Payout mode priority
- Default payout is email-based via linked user email.
- Agent tag
bountic-addressenables wallet-native payout path.
-
Future split suggestion (not in scope now)
- TODO: use an LLM to suggest a payout split based on diff/commit attribution.