Best-effort by design: refusing the change because one instance was
unreachable would leave the customer holding the password they were trying
to replace. A failure is flagged and hqsync repairs it.
Also corrects two pieces of copy this makes false — CreateInstance's doc
comment and the instance-ready email both claimed the two passwords
diverge.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A grant is a real control-plane users row with auth_source hq, not a
federation shim: the instance authenticates it with no runtime dependency
on admin. CountOtherOwners counts control-plane owners so a locally-created
owner satisfies the last-owner rule too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Admin's second and final write path into the control plane. It creates
instances and users and nothing else; inject still owns exactly three
licence fields and is untouched.
The owner's password hash is copied from the HQ account, not shared. The
two diverge on the next password change, which is accepted: propagating a
hash across two databases is worse than two passwords that started equal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>