mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
The IAM callback at /auth/callback reads IAM's userinfo answer and refuses an address IAM has not verified. An account is found by its linked IAM identity alone (provider hanzo, the IAM subject); an existing account that only shares the address is refused, never merged. A first sign-in makes an account only for an admin of the org the application serves or for someone an organisation invited at that verified address. Every refusal returns to /signin with a sentence saying what to do. Accepting an organisation invitation joins the signed-in person, and only when their verified address is the invited one; opening the link no longer adds whoever holds the address. The local email/password sign-up, sign-in, reset, verify-email and update routes, pages, jobs and mail are gone, as are passkey sign-in, the Google, Microsoft and generic OIDC providers, the per-organisation SSO portal and its account-link flow. Passkeys and two-factor stay for confirming a signature. The e2e suite starts sessions the way a finished IAM sign-in leaves them. Co-authored-by: Hanzo Dev <[email protected]>
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
/**
|
|
* An organisation invitation joins the person it was sent to, and nobody else.
|
|
*
|
|
* Holding the link proves the invitation was received, not who received it, so
|
|
* acceptance binds the signed-in person only when their verified address is the
|
|
* invited one.
|
|
*
|
|
* Run: npx tsx --test packages/lib/__tests__/invitation.test.ts
|
|
*/
|
|
import assert from 'node:assert/strict';
|
|
import { describe, test } from 'node:test';
|
|
|
|
import { isInvitedPerson } from '../server-only/organisation/is-invited-person';
|
|
|
|
describe('isInvitedPerson', () => {
|
|
const verified = new Date('2026-10-16T00:00:00Z');
|
|
|
|
test('the invited address, verified', () => {
|
|
assert.equal(isInvitedPerson({ email: '[email protected]', emailVerified: verified }, '[email protected]'), true);
|
|
});
|
|
|
|
test('case does not make a different person', () => {
|
|
assert.equal(isInvitedPerson({ email: '[email protected]', emailVerified: verified }, '[email protected]'), true);
|
|
});
|
|
|
|
test('a different address is refused', () => {
|
|
assert.equal(
|
|
isInvitedPerson({ email: '[email protected]', emailVerified: verified }, '[email protected]'),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test('the invited address, never verified, is refused', () => {
|
|
assert.equal(isInvitedPerson({ email: '[email protected]', emailVerified: null }, '[email protected]'), false);
|
|
});
|
|
});
|