Transfer organization ownership
Este contenido aún no está disponible en su idioma.
Moving an organization to a different owner has no screen in the application. Organization owners cannot do it themselves, so it is an operator action, run either from the instance’s command line or through the Colonel API.
This page is the procedure. For what your users see, and what they will have read before they ask you, see Ownership and transfer.
Prerequisites
Section titled “Prerequisites”- Shell access to a configured application environment, run from the repository root, with the datastore reachable. The command boots the application.
- The organization’s identifier.
ORGaccepts the organization’s public ID (extid), its internal ID (objid), a Stripe customer or subscription ID, or one of its custom-domain hostnames. - The incoming owner’s identifier.
NEW_OWNERaccepts an email address, a customerextid, or a Rodauth account ID. - The incoming owner must already be an active member of the organization. The transfer does not create the membership. One confirmation is not allowed to both create a membership and hand it ownership.
- For the API route instead of the shell: the
colonelrole, and the organization’s name to type as confirmation.
bin/ots org ... and bin/ots organization ... are aliases for
bin/ots organizations .... All three reach the same command.
Confirm the membership first
Section titled “Confirm the membership first”Read the organization before changing it:
bin/ots organizations show ORGIf the incoming owner is not listed as an active member, add them. The add is also preview-by-default, so this is two commands:
bin/ots memberships add ORG CUSTOMERbin/ots memberships add ORG CUSTOMER --applyAttempting a transfer to a non-member exits non-zero and tells you to run
memberships add first. It changes nothing.
Normal path
Section titled “Normal path”Preview
Section titled “Preview”bin/ots organizations transfer-ownership ORG NEW_OWNERA bare run is a preview. It writes no organization or membership data, prints the plan, and exits. The plan names the current owner, the incoming owner, the role the outgoing owner will land on, and how many owner memberships would be demoted.
Read the demotion count. The data model permits more than one owner membership, and the transfer demotes every owner other than the incoming one. A count above one means the organization was already in a state worth understanding before you write to it.
A preview is recorded as an observation on the access trail rather than as a change.
bin/ots organizations transfer-ownership ORG NEW_OWNER --apply| Option | Effect |
|---|---|
--apply |
The write gate. -y, --yes and -f are aliases for it. |
--dry-run |
Restates the default. It does not add a preview that a bare run lacks. |
--demote-to ROLE |
The outgoing owner’s role afterwards: admin (the default) or member. owner is refused. |
--json |
Machine-readable output. A non-success status still exits non-zero. |
The write gate on this command is not a property of every command on the
instance. Elsewhere in the CLI the same intent is spelled --run, --confirm
or --repair, and some commands write with no gate at all. Check
the CLI reference for the command in front of you rather
than assuming this one’s spelling.
Through the Colonel API
Section titled “Through the Colonel API”POST /api/colonel/organizations/:org_id/transfer-ownershipThe request body takes new_owner and an optional demote_to. The route
requires the colonel role, and the logic re-checks it. The confirmation it
asks for is the organization’s name, not its ID.
This route has no preview. The shared operation defaults to a dry run, and this adapter pins that off, so the call applies as soon as the confirmation matches. An API call is not the equivalent of a bare CLI run.
Observable success
Section titled “Observable success”- The command prints the organization ID, the previous owner’s public ID (or
(none)) and the new owner’s public ID, then the number of previous owners demoted and the role they were demoted to. - Exit status is 0.
bin/ots organizations show ORGlists the new owner with theownerrole, and the previous owner with the role you chose.bin/ots organizations doctor ORGreports nomembership_role_syncfinding.- The audit trail gains one
organization.transfer_ownershipevent with a success result, plus onemembership.set_roleevent per role change the transfer made. Three events for a routine transfer is the expected shape, not a double recording.
If the previous owner pointer referred to no live customer, the command says so and reports that it repaired it. That is a successful outcome, not a warning to act on.
When nothing needed to change
Section titled “When nothing needed to change”If the named member is already the sole owner and the stored owner pointer already agrees, the command reports that and exits 0 without writing. A partial state, where the member has the owner role but the stored pointer disagrees, deliberately does not short-circuit: the transfer proceeds and repairs the pointer.
What a transfer does not do
Section titled “What a transfer does not do”None of these are oversights, so do not plan around changing them.
- The outgoing owner is not removed. They are demoted. There is no
removevalue for--demote-to. Removing them would break the account checks for anyone whose default organization points at this one. - Billing does not move. The Stripe customer, subscription, billing email and email hash are organization fields. The subscription already belongs to the organization rather than to the person who owned it.
- The organization’s contact email is not changed. It is the organization’s identity in a uniqueness index, and changing it is separate work.
- The record of who created the organization is never rewritten. It is immutable audit state. A consequence worth knowing: on a transferred organization the owner pointer and the creator record permanently disagree, so the housekeeping chore that reconciles them logs a warning for that organization indefinitely. That is expected.
- Admins and members keep their roles. Only the two owner-side roles move.
Failure handling
Section titled “Failure handling”The transfer is refused before writing
Section titled “The transfer is refused before writing”Two refusals exit non-zero and change nothing:
| Printed reason | Meaning | What to do |
|---|---|---|
| not an active member | The incoming owner has no active membership. | Run memberships add ORG CUSTOMER --apply, then transfer. |
--demote-to must be one of |
The role you named is not a demotable role. | Use admin or member. |
Both are recorded on the audit trail as a failed attempt, and both print the same guidance whether you were previewing or applying.
The transfer fails part-way through
Section titled “The transfer fails part-way through”The ordering is forced rather than chosen, and a partial failure only makes sense once you know it. The sole-owner guard refuses to demote the only owner, and at the start of a transfer the outgoing owner is the only owner. So the operation promotes the incoming owner first, then moves the stored owner pointer, then demotes the others.
Between the first and third steps the organization has two owner memberships.
During that window bin/ots organizations doctor reports its
membership_role_sync check as a finding, and that check is marked
unrepairable, so the doctor will not fix it.
If a step after the promotion raises, the operation attempts a best-effort rollback before re-raising: it restores the stored owner pointer and the incoming owner’s previous role. Memberships that were already demoted stay demoted. The failure is audited, and the transfer is not recorded as a success.
Recovery is to re-run the transfer, not to run the doctor.
bin/ots organizations transfer-ownership ORG NEW_OWNER --applyThe operation is idempotent and demotes every other active owner, so a second
applied run finishes the job. Keep --apply on the repeat: a bare rerun only
previews, which will not close the window.
If the rollback itself fails, the command logs that separately and still reports the original failure. Read both lines, because the organization may be left in the two-owner state.
An owner membership with no backing customer
Section titled “An owner membership with no backing customer”If an outgoing owner membership refers to a customer record that no longer
exists, the transfer logs that it skipped that membership and continues. The
remaining stale membership is for bin/ots organizations doctor to report;
the transfer will not fabricate a customer in order to demote one.
Recovery limits
Section titled “Recovery limits”- There is no undo. To reverse a completed transfer, run a new transfer in the other direction. The previous owner must still be an active member for that to be accepted, which they will be, because a transfer demotes rather than removes them.
- Re-running converges, but it does not restore the outgoing owner’s original
role. Each run demotes to whatever
--demote-tosays on that run, defaulting toadmin. If the outgoing owner was a plain member before a mistaken transfer, reversing the transfer will not put them back there. - A rolled-back failure writes no success event, so the audit trail is not a
reliable record of whether a partial write survived. Check the organization
with
organizations showandorganizations doctorrather than inferring its state from an exit status.
Related
Section titled “Related”- Ownership and transfer for the end-user side of this procedure.
- Roles and permissions for what each membership role grants.
- CLI reference for every command’s write gate, scope and external effects.
- Self-hosting for the rest of the operator surface.