Adds nullable user_profiles.signing_email — the address representing a user in SIGNING contexts only (EOI developer/approver signer slot, in-CRM 'your turn to sign' notification, 'awaiting my signature' hub tab). Never a login credential; better-auth identity stays single-email. NULL → user signs as their own login email. Lets a person who logs in as e.g. abbie@ sign on behalf of a shared role mailbox (sales@) without changing their login. Additive + backward-compatible: every existing user (NULL override) is byte-for-byte unaffected. - migration 0100 + drizzle column (nullable, no unique constraint) - resolveCrmUser: signing_email ?? user.email - listDocuments hub filter: match the caller's owned email SET (login + override) for awaiting_me / awaiting_them (currentUserEmail -> currentUserEmails) - ctx.user.signingEmail surfaced from the already-loaded profile (no extra query) - updateUser persists/lowercases the override; '' clears it (edit-only) - admin Edit-User form: optional 'Signing email' field - TDD: validator unit test + 3 integration tests (resolver override+fallback, updateUser persist/clear, hub awaiting_me matches override) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L2qc3xZTfif7N4Wq3QDa8X
20 lines
707 B
TypeScript
20 lines
707 B
TypeScript
import { describe, it, expect } from 'vitest';
|
|
|
|
import { updateUserSchema } from '@/lib/validators/users';
|
|
|
|
describe('updateUserSchema.signingEmail', () => {
|
|
it('accepts and preserves a valid signing email', () => {
|
|
const parsed = updateUserSchema.parse({ signingEmail: 'sales@portnimara.com' });
|
|
expect(parsed.signingEmail).toBe('sales@portnimara.com');
|
|
});
|
|
|
|
it('allows an empty string (sentinel for "clear the override")', () => {
|
|
const parsed = updateUserSchema.parse({ signingEmail: '' });
|
|
expect(parsed.signingEmail).toBe('');
|
|
});
|
|
|
|
it('rejects a malformed signing email', () => {
|
|
expect(() => updateUserSchema.parse({ signingEmail: 'not-an-email' })).toThrow();
|
|
});
|
|
});
|