Skip to content

feat(hosted): admin backfill of site claims - #7823

Open
tlgimenes wants to merge 1 commit into
split/08-claim-sitefrom
split/09-admin-backfill
Open

tlgimenes wants to merge 1 commit into
split/08-claim-sitefrom
split/09-admin-backfill

Conversation

@tlgimenes

@tlgimenes tlgimenes commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Part of the v8 Studio stack, split from #7728, #7770 and #7766 (closed). Base: #7796. The top of the stack, #7843, has the same code as those three PRs combined.

Adds an admin-only route that backfills site claims for existing projects, using the claim logic from the previous PR.

What to look at: Admin-only route; the backfill is idempotent.

Stack: API track 09/11 · previous: #7821 · next: #7824

🤖 Generated with Claude Code

https://claude.ai/code/session_01WNwbSEePYNcY5YCgqZURig

Adds an admin-only route that backfills site claims for existing projects, using the claim logic from the previous PR.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WNwbSEePYNcY5YCgqZURig
@tlgimenes

Copy link
Copy Markdown
Contributor Author

Is this redundant with #7796's migration backfill? No, so this PR stays as it is. I read both.

What #7796 does (migration 235, plus the link call in tools/virtual/create.ts): it only links rows already in org_sites. Each existing row gets the single project in the same org whose metadata.siteSlug matches exactly, and every existing row is marked used (linked_at). It never creates a row. When a project names a slug that has no org_sites row, the migration skips it, and create.ts on #7796 gets an OrgSiteLinkError and leaves the project unlinked.

What this PR does (POST /api/admin/hosted/site-claims/backfill, built on backfillSiteClaims/linkProjectSite from #7822) covers the projects the migration can't reach:

  • v8 projects whose slug has no org_sites row. These are Studio-native sites that were never imported from deco.cx. feat(web): content-protocol client API; editor hooks use it #7822 claims a free slug at project create time, but projects created before feat(web): content-protocol client API; editor hooks use it #7822 deploys have no row, so ownedProjectSite refuses them and they get no hosted features. This route is the only path that claims and links them. Before claiming, it applies the same safety checks as create: not a deco.cx site, no other org's project names the slug, not reserved by a deleted org.
  • The gap between the two deploys. A project created after migration 235 runs but before feat(web): content-protocol client API; editor hooks use it #7822 ships also lands with no row. The migration is one-shot, so it never sees that project.
  • Gating and safety the migration can't do. It only touches projects whose main is Blocks v8 (mainIsV8), which needs a GitHub read, so it can't run inside a migration. It detects cross-org ambiguity (an unowned slug named by projects of two orgs gets linked to nobody). It is a dry run unless {"dryRun": false}, and it is audited (hosted_site_claims_backfill).

Where they overlap (a row exists, same org, one matching project), the migration has already linked it, and this route reports it as alreadyLinked and writes nothing. Both are idempotent, so running both is safe.

So #7823 stays in the stack, based on split/08-claim-site, and nothing above it changes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude PR authored by a coding agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant