@oimlsmart/platform-server 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/migrations/0022_account_emails.sql +45 -0
- package/package.json +1 -1
- package/src/store/d1.ts +563 -309
- package/src/store/sqlite/op-accounts-store.ts +205 -21
- package/src/store/sqlite/schema.sql +26 -0
- package/src/store/sqlite/store.ts +17 -0
- package/src/store/sqlite.ts +32 -1
- package/src/store.ts +109 -12
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- Migration 0022 — multiple emails per account (TODO.identity-features/01):
|
|
2
|
+
-- the account gains a primary + additional addresses, each verified
|
|
3
|
+
-- independently, the sign-in and the recovery paths resolving by ANY
|
|
4
|
+
-- verified one.
|
|
5
|
+
--
|
|
6
|
+
-- The model:
|
|
7
|
+
-- - the PRIMARY address stays users.email (+ users.email_verified_at):
|
|
8
|
+
-- the OIDC `email` claim never changes shape, every existing reader
|
|
9
|
+
-- (the claims, the registry, the audit chain) is undisturbed, and the
|
|
10
|
+
-- claims keep carrying the primary on a switch;
|
|
11
|
+
-- - account_emails carries the ADDITIONAL addresses only — one row per
|
|
12
|
+
-- (account, address), verified_at NULL until the per-address ceremony
|
|
13
|
+
-- proves the mailbox. An address is globally unique across the estate
|
|
14
|
+
-- of addresses: the unique index keys it here, and the store's writes
|
|
15
|
+
-- check BOTH tables (an additional on account A blocks the address as
|
|
16
|
+
-- a primary or an additional anywhere else);
|
|
17
|
+
-- - the "primary" attribute is represented by WHERE the address lives
|
|
18
|
+
-- (the users row vs account_emails), never a flag to keep in sync —
|
|
19
|
+
-- the store's setPrimaryAccountEmail swaps the two residences with
|
|
20
|
+
-- their verification stamps;
|
|
21
|
+
-- - email_change_tokens gains `kind`: 'change' (the pre-0022 primary
|
|
22
|
+
-- replacement — the default, so existing rows read honestly) and
|
|
23
|
+
-- 'add' (the per-address verification of an account_emails row; the
|
|
24
|
+
-- row lands unverified at the request and the token's completion
|
|
25
|
+
-- stamps verified_at). The same one-time, 24 h, atomically-consumed
|
|
26
|
+
-- doctrine carries both.
|
|
27
|
+
-- schema.sql carries the same end state for fresh databases —
|
|
28
|
+
-- test/migrations.test.ts pins the UNION of every migration to
|
|
29
|
+
-- schema.sql's CREATE set.
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS account_emails (
|
|
32
|
+
user_id TEXT NOT NULL REFERENCES users(id),
|
|
33
|
+
email TEXT NOT NULL,
|
|
34
|
+
verified_at TEXT,
|
|
35
|
+
added_by TEXT,
|
|
36
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
37
|
+
PRIMARY KEY (user_id, email)
|
|
38
|
+
);
|
|
39
|
+
-- An address names at most ONE account across the estate (the sign-in
|
|
40
|
+
-- and recovery resolutions depend on it); the users.email UNIQUE covers
|
|
41
|
+
-- the primaries, this index the additionals, and the store's writes
|
|
42
|
+
-- check across both.
|
|
43
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_account_emails_email ON account_emails (email);
|
|
44
|
+
|
|
45
|
+
ALTER TABLE email_change_tokens ADD COLUMN kind TEXT NOT NULL DEFAULT 'change';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oimlsmart/platform-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "The OIML SMART platform server kernel: the store seam (ServerStore + the D1 and SQLite implementations), the canonical D1 migration set both deployments apply, the instance profile, the mailer, the RBAC map, the OIDC/OAuth client cones, and the shared role/permission vocabulary. Consumed by the smart monorepo (browser/) and the identity service.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|