TL;DR
The invite-acceptance code path in entu/api/routes/auth/index.get.js has TWO branches that call replaceInviteWithCredentials. The second one ("Same entity: clean up orphaned invite property") enables a useful self-link workflow that isn't documented as a supported pattern: an already-logged-in user can add additional entu_user entries (additional verified emails / OAuth providers) to their OWN person without admin intervention.
How the self-link flow works
- User clicks "Add login email" in the app (logged in as person P)
- App creates a placeholder
entu_user property on P: { type: 'entu_user', invite: <token>, email: 'new@example.com' }
- App sends an email to
new@example.com with an invite link containing a JWT referencing entity P
- User clicks link → e-mail OAuth flow → Entu's auth detects invite param →
existingEntry.user._id === inviteData.entityId branch fires → replaceInviteWithCredentials swaps the placeholder with real { uid, email, provider: 'e-mail' }
- P now has two (or more)
entu_user entries; future invitations/logins to either address resolve to P
Implication
Apps building on Entu don't need to build their own email-verification round-trip for "add another email to my profile" use cases. The existing invite mechanism handles it.
Polyphony adopted this for its email-trust model (see polyphony case study C6 — https://github.com/entu/research/blob/main/docs/case-studies/2026-05-polyphony-on-entu.md).
Suggested doc note
At https://www.entu.ee/api/authentication/ or https://www.entu.ee/configuration/users/: document the self-link pattern as a supported workflow:
- "To add additional verified emails (or OAuth provider links) to an existing person, use the invite mechanism as a self-link: create a placeholder
entu_user on the user's own person with an invite token, send the invite to the new address, the OAuth completion will swap the placeholder with real credentials."
TL;DR
The invite-acceptance code path in
entu/api/routes/auth/index.get.jshas TWO branches that callreplaceInviteWithCredentials. The second one ("Same entity: clean up orphaned invite property") enables a useful self-link workflow that isn't documented as a supported pattern: an already-logged-in user can add additionalentu_userentries (additional verified emails / OAuth providers) to their OWN person without admin intervention.How the self-link flow works
entu_userproperty on P:{ type: 'entu_user', invite: <token>, email: 'new@example.com' }new@example.comwith an invite link containing a JWT referencing entity PexistingEntry.user._id === inviteData.entityIdbranch fires →replaceInviteWithCredentialsswaps the placeholder with real{ uid, email, provider: 'e-mail' }entu_userentries; future invitations/logins to either address resolve to PImplication
Apps building on Entu don't need to build their own email-verification round-trip for "add another email to my profile" use cases. The existing invite mechanism handles it.
Polyphony adopted this for its email-trust model (see polyphony case study C6 —
https://github.com/entu/research/blob/main/docs/case-studies/2026-05-polyphony-on-entu.md).Suggested doc note
At https://www.entu.ee/api/authentication/ or https://www.entu.ee/configuration/users/: document the self-link pattern as a supported workflow:
entu_useron the user's own person with an invite token, send the invite to the new address, the OAuth completion will swap the placeholder with real credentials."