Repository navigation
feat(groups): transfer group ownership to another member - #248
Conversation
Surfaces the two-phase ownership handshake added in CGS 0.6.0 (app.certified.group.ownershipTransfer.*) as a "Transfer ownership" page in group settings, between Members & Roles and Activity Log. The owner proposes an existing member; ownership moves only once that member accepts, which proves they still control their DID. Either party can cancel, and an un-accepted proposal lapses after 7 days. - BFF route: GET status, POST propose, PUT accept, DELETE cancel. Per the CGS #27 targeting rule, `repo` goes on the querystring for the status query and in the body for the three procedures. Propose validates the DID and is rate-limited 5/10min per caller. - UI: the owner picks from eligible members and confirms; the proposed member gets Accept/Decline; either party can cancel. Transfer status is re-read after every member and role mutation, because CGS clears a pending proposal when ownership or a party's membership changes by another route. - Only the two parties ever see the page. CGS reports `pending: false` to a member who is not a party, exactly as when no transfer exists, so the UI derives visibility from that response and never tries to tell the two cases apart. Copy avoids claiming the underlying PDS account moves — per the CGS integration guide, the owner role is not proof of account control. Requires the group service to be on 0.6.0+. staging.certified.app already is; production is on 0.5.0 and answers these NSIDs with 501, so this must not reach main until that deployment is upgraded. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The "Choose the new owner" block repeated what the page description already introduced. Fold the terms — accept-before-effect, the proposer's demotion to admin, and the 7-day expiry — into the page description so they're read once, before the control, and drop the duplicate paragraph. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Surfaces the two-phase ownership handshake added in CGS 0.6.0 (
app.certified.group.ownershipTransfer.*) as a Transfer ownership page in group settings, between "Members & Roles" and "Activity Log".The owner proposes an existing member; ownership moves only once that member accepts, which proves they still control their DID. Either party can cancel, and an un-accepted proposal lapses after 7 days.
Do not merge to main until production CGS is on 0.6.0
501 MethodNotImplementedThere is deliberately no runtime capability detection or feature flag: the merge gate is the guard. Check with
curl -s https://groups.certified.app/healthbefore promotingstagingtomain.What changed
src/app/api/groups/[groupDid]/ownership-transfer/route.ts(new) —GETstatus,POSTpropose,PUTaccept,DELETEcancel throughcallGroupServiceJson. Per the CGS fix: don't force OAuth consent screen on every email login #27 targeting rule,repogoes on the querystring for the status query and in the body for the three procedures. Propose validates the DID and is rate-limited 5/10min per caller; CSRF is checked on every mutation.src/lib/groups/types.ts+api.ts— anOwnershipTransferdiscriminated union and four client functions beside the existing member/role seam.src/components/groups/org-settings.tsx— the new settings page plustransferViewerRoleandeligibleTransferTargetsas exported pure helpers. No new CSS: it reusessx-subsection,org-members__*andorg-manage__actions.Two behaviours worth reviewing closely
pending: falseto a member who is not a party, exactly as when no transfer exists, so the UI derives visibility from that response and never tries to tell those cases apart. The same reasoning applies to theNoPendingTransferthe route forwards untouched.Copy avoids claiming the underlying PDS account moves; per the CGS integration guide the
ownerrole is not proof of account control.Testing
npx tsc --noEmit,npm run lint,npm test(1310 passing) all clean; the CLAUDE.md pre-merge greps are silent.GETis 401 and a forged origin is refused.🤖 Generated with Claude Code