Skip to content

Let users claim unowned developer profiles - #154

Merged
admdly merged 2 commits into
mainfrom
feat/author-claims
Jul 26, 2026
Merged

Let users claim unowned developer profiles#154
admdly merged 2 commits into
mainfrom
feat/author-claims

Conversation

@admdly

@admdly admdly commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a claim/approve/reject flow so a signed-in user can request ownership of an unowned ("legacy") developer profile (owner_user_id IS NULL) instead of needing a moderator to hand it over out-of-band.
  • A claim never changes ownership by itself — only a moderator's approval does, and approving one claim auto-rejects any other pending claims on the same profile.
  • New migration 0007_add_author_claims.sql: author_claims table with a partial unique index enforcing one pending claim per (author, claimant).
  • New routes: POST /authors/{id}/claim, GET /authors/claims/mine, GET /authors/claims (moderator), POST /authors/claims/{id}/approve (moderator), POST /authors/claims/{id}/reject (moderator).
  • Also fixes an unrelated pre-existing typecheck failure in versions/v1/index.ts: bearerAuth({ token }) wasn't inferring its Env generic from the options object and fell back to the default Env, which didn't match the route's VersionsEnv context.

Adds a claim/approve/reject flow so a signed-in user can request
ownership of a legacy (owner_user_id IS NULL) profile instead of
needing a moderator to do it out-of-band. A claim never changes
ownership by itself; approval moves ownership atomically and
auto-rejects any other pending claims on the same profile.

Also fixes an unrelated pre-existing typecheck failure in
versions/v1: bearerAuth({ token }) couldn't infer its Env generic
from the options object and fell back to the default Env, which
didn't match the route's VersionsEnv context.

Claude-Session: https://claude.ai/code/session_01Co1bu2gU5kEHN65KooNUHN
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 26, 2026

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
api a7af6f7 Commit Preview URL

Branch Preview URL
Jul 26 2026, 05:03 PM

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 7 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/services/extensions/v2/index.ts
Comment thread src/services/extensions/v2/index.ts
Comment thread src/services/extensions/v2/authors-database.ts Outdated
Comment thread src/services/extensions/v2/authors-database.ts Outdated
Comment thread src/services/extensions/v2/db/migrations/0007_add_author_claims.sql
@admdly admdly self-assigned this Jul 26, 2026
- claim(): fold the "author still unowned" and "claimant owns
  nothing else" checks into the INSERT itself (EXISTS/NOT EXISTS),
  closing a TOCTOU window where a claim could be created just after
  the profile was claimed or transferred elsewhere.
- approveClaim(): wrap the preflight ownership reads in try/catch so
  a DB failure there returns a structured DATABASE_ERROR instead of
  throwing; move the batch-support check before any mutation; guard
  the ownership UPDATE with `owner_user_id IS NULL` and gate the
  auto-reject-competing-claims statement on `changes() = 1`, so two
  concurrent approvals of different pending claims on the same
  profile can't both move ownership (the loser now reverts its claim
  to pending and returns CONFLICT).
- Migration: add a partial index on (created_at) WHERE status =
  'pending' so the moderator queue query doesn't need a separate
  sort as claim history grows.

Verified the ownership race fix against real local D1 by manually
interleaving two claims' status-transition and ownership-UPDATE
statements in the vulnerable order.

Claude-Session: https://claude.ai/code/session_01Co1bu2gU5kEHN65KooNUHN

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 3 files (changes from recent commits).

Requires human review: Adds a new claim flow for profile ownership with a database migration and new public endpoints. This is a new feature with product and operational tradeoffs (moderator approval, pending claim enforcement) that require human sign-off.

Re-trigger cubic

@admdly
admdly merged commit 81b1d1a into main Jul 26, 2026
9 checks passed
@admdly
admdly deleted the feat/author-claims branch July 26, 2026 17:09
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