@authrim/setup 0.1.134 → 0.1.136
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/dist/core/cloudflare.d.ts.map +1 -1
- package/dist/core/cloudflare.js +15 -0
- package/dist/core/cloudflare.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +55 -31
- package/dist/web/api.js.map +1 -1
- package/migrations/000_fresh_schema.sql +1966 -0
- package/migrations/admin/001_admin_users.sql +189 -0
- package/migrations/admin/002_admin_rbac.sql +256 -0
- package/migrations/admin/003_admin_audit.sql +175 -0
- package/migrations/admin/004_admin_security.sql +132 -0
- package/migrations/admin/005_admin_abac_rebac.sql +345 -0
- package/migrations/admin/006_admin_setup_tokens.sql +91 -0
- package/migrations/pii/001_pii_initial.sql +466 -0
- package/migrations/pii/002_pii_log_tables.sql +139 -0
- package/migrations/pii/003_tombstone_timestamps.sql +12 -0
- package/migrations/pii/004_cleanup_admin_from_pii.sql +50 -0
- package/package.json +2 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
-- =============================================================================
|
|
2
|
+
-- Migration: Admin Users and Sessions (D1_ADMIN)
|
|
3
|
+
-- =============================================================================
|
|
4
|
+
-- Created: 2025-01-22
|
|
5
|
+
-- Description: Creates admin_users, admin_sessions, and admin_passkeys tables.
|
|
6
|
+
-- Part of Admin/EndUser separation architecture.
|
|
7
|
+
--
|
|
8
|
+
-- IMPORTANT: This migration is for D1_ADMIN (dedicated Admin database).
|
|
9
|
+
-- Completely separate from D1_CORE (EndUser data).
|
|
10
|
+
--
|
|
11
|
+
-- Architecture:
|
|
12
|
+
-- - admin_users: Admin user accounts (GDPR exempt - no PII separation needed)
|
|
13
|
+
-- - admin_sessions: Admin session management
|
|
14
|
+
-- - admin_passkeys: WebAuthn/Passkey credentials for Admin users
|
|
15
|
+
-- =============================================================================
|
|
16
|
+
|
|
17
|
+
-- =============================================================================
|
|
18
|
+
-- admin_users Table
|
|
19
|
+
-- =============================================================================
|
|
20
|
+
-- Admin user accounts stored in D1_ADMIN database.
|
|
21
|
+
-- Contains authentication and profile data for admin users.
|
|
22
|
+
-- GDPR exempt - no PII separation required.
|
|
23
|
+
--
|
|
24
|
+
-- Status values:
|
|
25
|
+
-- - active: Normal active account
|
|
26
|
+
-- - suspended: Temporarily suspended (can be reactivated)
|
|
27
|
+
-- - locked: Locked due to failed login attempts (auto-unlock possible)
|
|
28
|
+
-- =============================================================================
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS admin_users (
|
|
31
|
+
-- Primary key (UUID v4)
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
|
|
34
|
+
-- Multi-tenant support
|
|
35
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
36
|
+
|
|
37
|
+
-- Admin user profile
|
|
38
|
+
email TEXT NOT NULL,
|
|
39
|
+
email_verified INTEGER DEFAULT 0,
|
|
40
|
+
name TEXT,
|
|
41
|
+
|
|
42
|
+
-- Authentication
|
|
43
|
+
password_hash TEXT,
|
|
44
|
+
|
|
45
|
+
-- Account status
|
|
46
|
+
is_active INTEGER DEFAULT 1,
|
|
47
|
+
status TEXT NOT NULL DEFAULT 'active', -- active | suspended | locked
|
|
48
|
+
|
|
49
|
+
-- MFA settings
|
|
50
|
+
mfa_enabled INTEGER DEFAULT 0,
|
|
51
|
+
mfa_method TEXT, -- totp | passkey | both | null
|
|
52
|
+
totp_secret_encrypted TEXT,
|
|
53
|
+
|
|
54
|
+
-- Login tracking
|
|
55
|
+
last_login_at INTEGER,
|
|
56
|
+
last_login_ip TEXT,
|
|
57
|
+
failed_login_count INTEGER DEFAULT 0,
|
|
58
|
+
locked_until INTEGER, -- UNIX timestamp, null if not locked
|
|
59
|
+
|
|
60
|
+
-- Audit fields
|
|
61
|
+
created_by TEXT, -- Admin user ID who created this account
|
|
62
|
+
created_at INTEGER NOT NULL,
|
|
63
|
+
updated_at INTEGER NOT NULL,
|
|
64
|
+
|
|
65
|
+
-- Unique constraint for email per tenant
|
|
66
|
+
UNIQUE(tenant_id, email)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
-- =============================================================================
|
|
70
|
+
-- Indexes for admin_users
|
|
71
|
+
-- =============================================================================
|
|
72
|
+
|
|
73
|
+
-- Tenant-scoped email lookup (primary auth query)
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_admin_users_tenant_email ON admin_users(tenant_id, email);
|
|
75
|
+
|
|
76
|
+
-- Active users filter
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_admin_users_active ON admin_users(tenant_id, is_active);
|
|
78
|
+
|
|
79
|
+
-- Status filter (for admin dashboard)
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_admin_users_status ON admin_users(tenant_id, status);
|
|
81
|
+
|
|
82
|
+
-- Last login tracking (for security audit)
|
|
83
|
+
CREATE INDEX IF NOT EXISTS idx_admin_users_last_login ON admin_users(last_login_at);
|
|
84
|
+
|
|
85
|
+
-- =============================================================================
|
|
86
|
+
-- admin_sessions Table
|
|
87
|
+
-- =============================================================================
|
|
88
|
+
-- Admin session management stored in D1_ADMIN database.
|
|
89
|
+
-- Separate from EndUser sessions in SessionStore Durable Object.
|
|
90
|
+
--
|
|
91
|
+
-- Unlike EndUser sessions (stored in Durable Objects for horizontal scaling),
|
|
92
|
+
-- Admin sessions are stored in D1 for:
|
|
93
|
+
-- - Simpler management (fewer admin users)
|
|
94
|
+
-- - Direct SQL queries for security monitoring
|
|
95
|
+
-- - Easy invalidation of all sessions for a user
|
|
96
|
+
-- =============================================================================
|
|
97
|
+
|
|
98
|
+
CREATE TABLE IF NOT EXISTS admin_sessions (
|
|
99
|
+
-- Session ID (UUID v4)
|
|
100
|
+
id TEXT PRIMARY KEY,
|
|
101
|
+
|
|
102
|
+
-- Multi-tenant support
|
|
103
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
104
|
+
|
|
105
|
+
-- Reference to admin user
|
|
106
|
+
admin_user_id TEXT NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE,
|
|
107
|
+
|
|
108
|
+
-- Client information
|
|
109
|
+
ip_address TEXT,
|
|
110
|
+
user_agent TEXT,
|
|
111
|
+
|
|
112
|
+
-- Session lifecycle
|
|
113
|
+
created_at INTEGER NOT NULL,
|
|
114
|
+
expires_at INTEGER NOT NULL,
|
|
115
|
+
last_activity_at INTEGER,
|
|
116
|
+
|
|
117
|
+
-- MFA status for this session
|
|
118
|
+
mfa_verified INTEGER DEFAULT 0,
|
|
119
|
+
mfa_verified_at INTEGER
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
-- =============================================================================
|
|
123
|
+
-- Indexes for admin_sessions
|
|
124
|
+
-- =============================================================================
|
|
125
|
+
|
|
126
|
+
-- User's active sessions lookup
|
|
127
|
+
CREATE INDEX IF NOT EXISTS idx_admin_sessions_user ON admin_sessions(admin_user_id);
|
|
128
|
+
|
|
129
|
+
-- Tenant-scoped session lookup
|
|
130
|
+
CREATE INDEX IF NOT EXISTS idx_admin_sessions_tenant ON admin_sessions(tenant_id);
|
|
131
|
+
|
|
132
|
+
-- Expired session cleanup
|
|
133
|
+
CREATE INDEX IF NOT EXISTS idx_admin_sessions_expires ON admin_sessions(expires_at);
|
|
134
|
+
|
|
135
|
+
-- Activity monitoring
|
|
136
|
+
CREATE INDEX IF NOT EXISTS idx_admin_sessions_activity ON admin_sessions(last_activity_at);
|
|
137
|
+
|
|
138
|
+
-- =============================================================================
|
|
139
|
+
-- admin_passkeys Table
|
|
140
|
+
-- =============================================================================
|
|
141
|
+
-- WebAuthn/Passkey credentials for Admin users.
|
|
142
|
+
-- Enables passwordless authentication for admin accounts.
|
|
143
|
+
-- =============================================================================
|
|
144
|
+
|
|
145
|
+
CREATE TABLE IF NOT EXISTS admin_passkeys (
|
|
146
|
+
-- Passkey ID (UUID v4)
|
|
147
|
+
id TEXT PRIMARY KEY,
|
|
148
|
+
|
|
149
|
+
-- Reference to admin user
|
|
150
|
+
admin_user_id TEXT NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE,
|
|
151
|
+
|
|
152
|
+
-- WebAuthn credential data
|
|
153
|
+
credential_id TEXT UNIQUE NOT NULL, -- Base64url-encoded credential ID
|
|
154
|
+
public_key TEXT NOT NULL, -- COSE public key (Base64url-encoded)
|
|
155
|
+
counter INTEGER DEFAULT 0, -- Signature counter for replay protection
|
|
156
|
+
|
|
157
|
+
-- User-friendly name for this passkey
|
|
158
|
+
device_name TEXT,
|
|
159
|
+
|
|
160
|
+
-- Transports (json array: usb, ble, nfc, internal, hybrid)
|
|
161
|
+
transports_json TEXT,
|
|
162
|
+
|
|
163
|
+
-- Attestation data (optional, for enterprise requirements)
|
|
164
|
+
attestation_type TEXT, -- none | indirect | direct | enterprise
|
|
165
|
+
aaguid TEXT, -- Authenticator Attestation GUID
|
|
166
|
+
|
|
167
|
+
-- Lifecycle
|
|
168
|
+
created_at INTEGER NOT NULL,
|
|
169
|
+
last_used_at INTEGER
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
-- =============================================================================
|
|
173
|
+
-- Indexes for admin_passkeys
|
|
174
|
+
-- =============================================================================
|
|
175
|
+
|
|
176
|
+
-- User's passkeys lookup
|
|
177
|
+
CREATE INDEX IF NOT EXISTS idx_admin_passkeys_user ON admin_passkeys(admin_user_id);
|
|
178
|
+
|
|
179
|
+
-- Credential ID lookup (for authentication)
|
|
180
|
+
CREATE INDEX IF NOT EXISTS idx_admin_passkeys_credential ON admin_passkeys(credential_id);
|
|
181
|
+
|
|
182
|
+
-- =============================================================================
|
|
183
|
+
-- Migration Complete
|
|
184
|
+
-- =============================================================================
|
|
185
|
+
-- Next steps:
|
|
186
|
+
-- 1. Apply 002_admin_rbac.sql for role management
|
|
187
|
+
-- 2. Apply 003_admin_audit.sql for audit logging
|
|
188
|
+
-- 3. Apply 004_admin_security.sql for IP allowlist
|
|
189
|
+
-- =============================================================================
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
-- =============================================================================
|
|
2
|
+
-- Migration: Admin RBAC (D1_ADMIN)
|
|
3
|
+
-- =============================================================================
|
|
4
|
+
-- Created: 2025-01-22
|
|
5
|
+
-- Description: Creates admin_roles and admin_role_assignments tables.
|
|
6
|
+
-- Implements Role-Based Access Control for Admin users.
|
|
7
|
+
--
|
|
8
|
+
-- IMPORTANT: This migration is for D1_ADMIN (dedicated Admin database).
|
|
9
|
+
-- Separate from EndUser RBAC in D1_CORE.
|
|
10
|
+
--
|
|
11
|
+
-- Architecture:
|
|
12
|
+
-- - admin_roles: Role definitions with permission sets
|
|
13
|
+
-- - admin_role_assignments: Links admin users to roles
|
|
14
|
+
--
|
|
15
|
+
-- Hierarchy levels (higher = more privilege):
|
|
16
|
+
-- - super_admin: 100 (full system access)
|
|
17
|
+
-- - security_admin: 90 (security settings, audit logs)
|
|
18
|
+
-- - admin: 80 (user/client management)
|
|
19
|
+
-- - support: 40 (read + limited write for support tasks)
|
|
20
|
+
-- - viewer: 20 (read-only access)
|
|
21
|
+
-- =============================================================================
|
|
22
|
+
|
|
23
|
+
-- =============================================================================
|
|
24
|
+
-- admin_roles Table
|
|
25
|
+
-- =============================================================================
|
|
26
|
+
-- Role definitions for Admin RBAC.
|
|
27
|
+
-- Each role has a set of permissions (stored as JSON array).
|
|
28
|
+
--
|
|
29
|
+
-- Role types:
|
|
30
|
+
-- - system: Built-in system roles (cannot be modified/deleted)
|
|
31
|
+
-- - builtin: Default roles (can be modified but not deleted)
|
|
32
|
+
-- - custom: User-created roles (fully customizable)
|
|
33
|
+
-- =============================================================================
|
|
34
|
+
|
|
35
|
+
CREATE TABLE IF NOT EXISTS admin_roles (
|
|
36
|
+
-- Role ID (UUID v4)
|
|
37
|
+
id TEXT PRIMARY KEY,
|
|
38
|
+
|
|
39
|
+
-- Multi-tenant support
|
|
40
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
41
|
+
|
|
42
|
+
-- Role identification
|
|
43
|
+
name TEXT NOT NULL, -- Machine-readable name (e.g., 'super_admin')
|
|
44
|
+
display_name TEXT, -- Human-readable name (e.g., 'Super Administrator')
|
|
45
|
+
description TEXT,
|
|
46
|
+
|
|
47
|
+
-- Permissions (JSON array of permission strings)
|
|
48
|
+
-- Format: ["admin:users:read", "admin:users:write", "admin:clients:*"]
|
|
49
|
+
permissions_json TEXT NOT NULL DEFAULT '[]',
|
|
50
|
+
|
|
51
|
+
-- Hierarchy level (for permission inheritance and delegation)
|
|
52
|
+
-- Higher level = more privilege
|
|
53
|
+
-- Users can only assign roles with lower hierarchy level
|
|
54
|
+
hierarchy_level INTEGER DEFAULT 0,
|
|
55
|
+
|
|
56
|
+
-- Role type
|
|
57
|
+
role_type TEXT NOT NULL DEFAULT 'custom', -- system | builtin | custom
|
|
58
|
+
|
|
59
|
+
-- System role flag (cannot be modified or deleted)
|
|
60
|
+
is_system INTEGER DEFAULT 0,
|
|
61
|
+
|
|
62
|
+
-- Lifecycle
|
|
63
|
+
created_at INTEGER NOT NULL,
|
|
64
|
+
updated_at INTEGER NOT NULL,
|
|
65
|
+
|
|
66
|
+
-- Unique constraint for role name per tenant
|
|
67
|
+
UNIQUE(tenant_id, name)
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
-- =============================================================================
|
|
71
|
+
-- Indexes for admin_roles
|
|
72
|
+
-- =============================================================================
|
|
73
|
+
|
|
74
|
+
-- Tenant-scoped role lookup
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_admin_roles_tenant ON admin_roles(tenant_id);
|
|
76
|
+
|
|
77
|
+
-- Role name lookup
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_admin_roles_name ON admin_roles(tenant_id, name);
|
|
79
|
+
|
|
80
|
+
-- Role type filter
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_admin_roles_type ON admin_roles(role_type);
|
|
82
|
+
|
|
83
|
+
-- Hierarchy level (for delegation checks)
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_admin_roles_hierarchy ON admin_roles(hierarchy_level);
|
|
85
|
+
|
|
86
|
+
-- =============================================================================
|
|
87
|
+
-- admin_role_assignments Table
|
|
88
|
+
-- =============================================================================
|
|
89
|
+
-- Links admin users to roles.
|
|
90
|
+
-- Supports scoped assignments (global, tenant, organization).
|
|
91
|
+
--
|
|
92
|
+
-- Scope types:
|
|
93
|
+
-- - global: Role applies to all tenants (super_admin only)
|
|
94
|
+
-- - tenant: Role applies to specific tenant
|
|
95
|
+
-- - org: Role applies to specific organization within tenant
|
|
96
|
+
-- =============================================================================
|
|
97
|
+
|
|
98
|
+
CREATE TABLE IF NOT EXISTS admin_role_assignments (
|
|
99
|
+
-- Assignment ID (UUID v4)
|
|
100
|
+
id TEXT PRIMARY KEY,
|
|
101
|
+
|
|
102
|
+
-- Multi-tenant support
|
|
103
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
104
|
+
|
|
105
|
+
-- References
|
|
106
|
+
admin_user_id TEXT NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE,
|
|
107
|
+
admin_role_id TEXT NOT NULL REFERENCES admin_roles(id) ON DELETE CASCADE,
|
|
108
|
+
|
|
109
|
+
-- Scope of this assignment
|
|
110
|
+
scope_type TEXT NOT NULL DEFAULT 'tenant', -- global | tenant | org
|
|
111
|
+
scope_id TEXT, -- org_id if scope_type = 'org', null otherwise
|
|
112
|
+
|
|
113
|
+
-- Expiration (for temporary assignments)
|
|
114
|
+
expires_at INTEGER, -- UNIX timestamp, null for permanent
|
|
115
|
+
|
|
116
|
+
-- Audit fields
|
|
117
|
+
assigned_by TEXT, -- Admin user ID who made this assignment
|
|
118
|
+
created_at INTEGER NOT NULL,
|
|
119
|
+
|
|
120
|
+
-- Unique constraint: one role per user per scope
|
|
121
|
+
UNIQUE(admin_user_id, admin_role_id, scope_type, scope_id)
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
-- =============================================================================
|
|
125
|
+
-- Indexes for admin_role_assignments
|
|
126
|
+
-- =============================================================================
|
|
127
|
+
|
|
128
|
+
-- User's role lookup (primary query for authorization)
|
|
129
|
+
CREATE INDEX IF NOT EXISTS idx_admin_role_assignments_user ON admin_role_assignments(admin_user_id);
|
|
130
|
+
|
|
131
|
+
-- Role assignment lookup
|
|
132
|
+
CREATE INDEX IF NOT EXISTS idx_admin_role_assignments_role ON admin_role_assignments(admin_role_id);
|
|
133
|
+
|
|
134
|
+
-- Tenant-scoped assignments
|
|
135
|
+
CREATE INDEX IF NOT EXISTS idx_admin_role_assignments_tenant ON admin_role_assignments(tenant_id);
|
|
136
|
+
|
|
137
|
+
-- Scope-based filtering
|
|
138
|
+
CREATE INDEX IF NOT EXISTS idx_admin_role_assignments_scope ON admin_role_assignments(scope_type, scope_id);
|
|
139
|
+
|
|
140
|
+
-- Expiration tracking (for cleanup jobs)
|
|
141
|
+
CREATE INDEX IF NOT EXISTS idx_admin_role_assignments_expires ON admin_role_assignments(expires_at);
|
|
142
|
+
|
|
143
|
+
-- =============================================================================
|
|
144
|
+
-- Default Roles (System Roles)
|
|
145
|
+
-- =============================================================================
|
|
146
|
+
-- Insert default roles with predefined permissions.
|
|
147
|
+
-- These are system roles that cannot be modified or deleted.
|
|
148
|
+
-- =============================================================================
|
|
149
|
+
|
|
150
|
+
-- super_admin: Full system access (hierarchy: 100)
|
|
151
|
+
INSERT OR IGNORE INTO admin_roles (
|
|
152
|
+
id, tenant_id, name, display_name, description,
|
|
153
|
+
permissions_json, hierarchy_level, role_type, is_system,
|
|
154
|
+
created_at, updated_at
|
|
155
|
+
) VALUES (
|
|
156
|
+
'role_super_admin',
|
|
157
|
+
'default',
|
|
158
|
+
'super_admin',
|
|
159
|
+
'Super Administrator',
|
|
160
|
+
'Full system access - all permissions granted',
|
|
161
|
+
'["*"]',
|
|
162
|
+
100,
|
|
163
|
+
'system',
|
|
164
|
+
1,
|
|
165
|
+
strftime('%s', 'now') * 1000,
|
|
166
|
+
strftime('%s', 'now') * 1000
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
-- security_admin: Security and audit management (hierarchy: 90)
|
|
170
|
+
INSERT OR IGNORE INTO admin_roles (
|
|
171
|
+
id, tenant_id, name, display_name, description,
|
|
172
|
+
permissions_json, hierarchy_level, role_type, is_system,
|
|
173
|
+
created_at, updated_at
|
|
174
|
+
) VALUES (
|
|
175
|
+
'role_security_admin',
|
|
176
|
+
'default',
|
|
177
|
+
'security_admin',
|
|
178
|
+
'Security Administrator',
|
|
179
|
+
'Security settings, audit logs, IP restrictions',
|
|
180
|
+
'["admin:audit:*", "admin:security:*", "admin:ip_allowlist:*", "admin:sessions:read", "admin:sessions:revoke", "admin:users:read"]',
|
|
181
|
+
90,
|
|
182
|
+
'system',
|
|
183
|
+
1,
|
|
184
|
+
strftime('%s', 'now') * 1000,
|
|
185
|
+
strftime('%s', 'now') * 1000
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
-- admin: User and client management (hierarchy: 80)
|
|
189
|
+
INSERT OR IGNORE INTO admin_roles (
|
|
190
|
+
id, tenant_id, name, display_name, description,
|
|
191
|
+
permissions_json, hierarchy_level, role_type, is_system,
|
|
192
|
+
created_at, updated_at
|
|
193
|
+
) VALUES (
|
|
194
|
+
'role_admin',
|
|
195
|
+
'default',
|
|
196
|
+
'admin',
|
|
197
|
+
'Administrator',
|
|
198
|
+
'User and client management, basic operations',
|
|
199
|
+
'["admin:users:*", "admin:clients:*", "admin:scopes:*", "admin:roles:read", "admin:settings:read", "admin:audit:read"]',
|
|
200
|
+
80,
|
|
201
|
+
'system',
|
|
202
|
+
1,
|
|
203
|
+
strftime('%s', 'now') * 1000,
|
|
204
|
+
strftime('%s', 'now') * 1000
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
-- support: Support operations (hierarchy: 40)
|
|
208
|
+
INSERT OR IGNORE INTO admin_roles (
|
|
209
|
+
id, tenant_id, name, display_name, description,
|
|
210
|
+
permissions_json, hierarchy_level, role_type, is_system,
|
|
211
|
+
created_at, updated_at
|
|
212
|
+
) VALUES (
|
|
213
|
+
'role_support',
|
|
214
|
+
'default',
|
|
215
|
+
'support',
|
|
216
|
+
'Support',
|
|
217
|
+
'Read access with limited write for support tasks',
|
|
218
|
+
'["admin:users:read", "admin:users:unlock", "admin:sessions:read", "admin:sessions:revoke", "admin:clients:read", "admin:audit:read"]',
|
|
219
|
+
40,
|
|
220
|
+
'system',
|
|
221
|
+
1,
|
|
222
|
+
strftime('%s', 'now') * 1000,
|
|
223
|
+
strftime('%s', 'now') * 1000
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
-- viewer: Read-only access (hierarchy: 20)
|
|
227
|
+
INSERT OR IGNORE INTO admin_roles (
|
|
228
|
+
id, tenant_id, name, display_name, description,
|
|
229
|
+
permissions_json, hierarchy_level, role_type, is_system,
|
|
230
|
+
created_at, updated_at
|
|
231
|
+
) VALUES (
|
|
232
|
+
'role_viewer',
|
|
233
|
+
'default',
|
|
234
|
+
'viewer',
|
|
235
|
+
'Viewer',
|
|
236
|
+
'Read-only access to admin dashboard',
|
|
237
|
+
'["admin:users:read", "admin:clients:read", "admin:roles:read", "admin:settings:read"]',
|
|
238
|
+
20,
|
|
239
|
+
'system',
|
|
240
|
+
1,
|
|
241
|
+
strftime('%s', 'now') * 1000,
|
|
242
|
+
strftime('%s', 'now') * 1000
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
-- =============================================================================
|
|
246
|
+
-- Migration Complete
|
|
247
|
+
-- =============================================================================
|
|
248
|
+
-- Permission format: admin:<resource>:<action>
|
|
249
|
+
-- Resources: users, clients, roles, scopes, settings, audit, security, ip_allowlist, sessions
|
|
250
|
+
-- Actions: read, write, delete, * (all)
|
|
251
|
+
-- Special: "*" grants all permissions
|
|
252
|
+
--
|
|
253
|
+
-- Next steps:
|
|
254
|
+
-- 1. Apply 003_admin_audit.sql for audit logging
|
|
255
|
+
-- 2. Apply 004_admin_security.sql for IP allowlist
|
|
256
|
+
-- =============================================================================
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
-- =============================================================================
|
|
2
|
+
-- Migration: Admin Audit Log (D1_ADMIN)
|
|
3
|
+
-- =============================================================================
|
|
4
|
+
-- Created: 2025-01-22
|
|
5
|
+
-- Description: Creates admin_audit_log table for Admin operations auditing.
|
|
6
|
+
-- Separate from EndUser audit logs.
|
|
7
|
+
--
|
|
8
|
+
-- IMPORTANT: This migration is for D1_ADMIN (dedicated Admin database).
|
|
9
|
+
-- Provides complete audit trail for Admin operations.
|
|
10
|
+
--
|
|
11
|
+
-- Architecture:
|
|
12
|
+
-- - admin_audit_log: All admin actions with before/after state
|
|
13
|
+
-- - Supports filtering by action, user, resource, severity
|
|
14
|
+
-- - Designed for compliance and security monitoring
|
|
15
|
+
--
|
|
16
|
+
-- Retention: Default 7 years (configurable via settings)
|
|
17
|
+
-- =============================================================================
|
|
18
|
+
|
|
19
|
+
-- =============================================================================
|
|
20
|
+
-- admin_audit_log Table
|
|
21
|
+
-- =============================================================================
|
|
22
|
+
-- Comprehensive audit log for all Admin operations.
|
|
23
|
+
-- Captures who did what, when, from where, and the before/after state.
|
|
24
|
+
--
|
|
25
|
+
-- Severity levels:
|
|
26
|
+
-- - debug: Detailed debugging info (usually filtered in production)
|
|
27
|
+
-- - info: Normal operations (login, view actions)
|
|
28
|
+
-- - warn: Potentially concerning actions (failed auth, permission denied)
|
|
29
|
+
-- - error: Errors that need attention
|
|
30
|
+
-- - critical: Security-sensitive actions (role changes, IP allowlist changes)
|
|
31
|
+
-- =============================================================================
|
|
32
|
+
|
|
33
|
+
CREATE TABLE IF NOT EXISTS admin_audit_log (
|
|
34
|
+
-- Audit entry ID (UUID v4)
|
|
35
|
+
id TEXT PRIMARY KEY,
|
|
36
|
+
|
|
37
|
+
-- Multi-tenant support
|
|
38
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
39
|
+
|
|
40
|
+
-- Who performed the action
|
|
41
|
+
admin_user_id TEXT, -- May be null for system actions or failed auth
|
|
42
|
+
admin_email TEXT, -- Denormalized for easier querying
|
|
43
|
+
|
|
44
|
+
-- What action was performed
|
|
45
|
+
action TEXT NOT NULL, -- e.g., 'admin.login', 'user.create', 'client.update'
|
|
46
|
+
|
|
47
|
+
-- Target resource
|
|
48
|
+
resource_type TEXT, -- e.g., 'admin_user', 'client', 'role', 'settings'
|
|
49
|
+
resource_id TEXT, -- ID of the affected resource
|
|
50
|
+
|
|
51
|
+
-- Result
|
|
52
|
+
result TEXT NOT NULL, -- 'success' | 'failure' | 'error'
|
|
53
|
+
error_code TEXT, -- Error code if result is 'failure' or 'error'
|
|
54
|
+
error_message TEXT, -- Error details
|
|
55
|
+
|
|
56
|
+
-- Severity level
|
|
57
|
+
severity TEXT NOT NULL DEFAULT 'info', -- debug | info | warn | error | critical
|
|
58
|
+
|
|
59
|
+
-- Request context
|
|
60
|
+
ip_address TEXT,
|
|
61
|
+
user_agent TEXT,
|
|
62
|
+
request_id TEXT, -- Correlation ID for request tracing
|
|
63
|
+
session_id TEXT, -- Admin session ID
|
|
64
|
+
|
|
65
|
+
-- State changes
|
|
66
|
+
before_json TEXT, -- JSON snapshot before change (null for create/read)
|
|
67
|
+
after_json TEXT, -- JSON snapshot after change (null for delete/read)
|
|
68
|
+
|
|
69
|
+
-- Additional metadata
|
|
70
|
+
metadata_json TEXT, -- Additional context (e.g., affected fields, reason)
|
|
71
|
+
|
|
72
|
+
-- Timestamp
|
|
73
|
+
created_at INTEGER NOT NULL
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
-- =============================================================================
|
|
77
|
+
-- Indexes for admin_audit_log
|
|
78
|
+
-- =============================================================================
|
|
79
|
+
|
|
80
|
+
-- Time-based queries (most common pattern)
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_created_at ON admin_audit_log(created_at DESC);
|
|
82
|
+
|
|
83
|
+
-- Tenant-scoped time queries
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_tenant_time ON admin_audit_log(tenant_id, created_at DESC);
|
|
85
|
+
|
|
86
|
+
-- User activity lookup
|
|
87
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_user ON admin_audit_log(admin_user_id, created_at DESC);
|
|
88
|
+
|
|
89
|
+
-- Action type filtering
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_action ON admin_audit_log(action, created_at DESC);
|
|
91
|
+
|
|
92
|
+
-- Resource tracking
|
|
93
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_resource ON admin_audit_log(resource_type, resource_id, created_at DESC);
|
|
94
|
+
|
|
95
|
+
-- Severity filtering (for alerts and monitoring)
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_severity ON admin_audit_log(severity, created_at DESC);
|
|
97
|
+
|
|
98
|
+
-- Result filtering (for error tracking)
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_result ON admin_audit_log(result, created_at DESC);
|
|
100
|
+
|
|
101
|
+
-- IP address tracking (for security investigation)
|
|
102
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_ip ON admin_audit_log(ip_address, created_at DESC);
|
|
103
|
+
|
|
104
|
+
-- Request correlation
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_request ON admin_audit_log(request_id);
|
|
106
|
+
|
|
107
|
+
-- =============================================================================
|
|
108
|
+
-- Standard Action Types
|
|
109
|
+
-- =============================================================================
|
|
110
|
+
-- These are the standard action types for audit logging.
|
|
111
|
+
-- Format: <category>.<action>
|
|
112
|
+
--
|
|
113
|
+
-- Authentication:
|
|
114
|
+
-- - admin.login.success
|
|
115
|
+
-- - admin.login.failure
|
|
116
|
+
-- - admin.logout
|
|
117
|
+
-- - admin.mfa.setup
|
|
118
|
+
-- - admin.mfa.verify
|
|
119
|
+
-- - admin.passkey.register
|
|
120
|
+
-- - admin.passkey.authenticate
|
|
121
|
+
--
|
|
122
|
+
-- Admin User Management:
|
|
123
|
+
-- - admin_user.create
|
|
124
|
+
-- - admin_user.read
|
|
125
|
+
-- - admin_user.update
|
|
126
|
+
-- - admin_user.delete
|
|
127
|
+
-- - admin_user.suspend
|
|
128
|
+
-- - admin_user.activate
|
|
129
|
+
-- - admin_user.unlock
|
|
130
|
+
-- - admin_user.password.reset
|
|
131
|
+
--
|
|
132
|
+
-- Role Management:
|
|
133
|
+
-- - admin_role.create
|
|
134
|
+
-- - admin_role.update
|
|
135
|
+
-- - admin_role.delete
|
|
136
|
+
-- - admin_role.assign
|
|
137
|
+
-- - admin_role.revoke
|
|
138
|
+
--
|
|
139
|
+
-- Security:
|
|
140
|
+
-- - ip_allowlist.add
|
|
141
|
+
-- - ip_allowlist.remove
|
|
142
|
+
-- - ip_allowlist.update
|
|
143
|
+
-- - session.revoke
|
|
144
|
+
-- - session.revoke_all
|
|
145
|
+
--
|
|
146
|
+
-- Settings:
|
|
147
|
+
-- - settings.update
|
|
148
|
+
-- - settings.read
|
|
149
|
+
--
|
|
150
|
+
-- EndUser Management (actions on EndUsers from Admin):
|
|
151
|
+
-- - user.create
|
|
152
|
+
-- - user.read
|
|
153
|
+
-- - user.update
|
|
154
|
+
-- - user.delete
|
|
155
|
+
-- - user.suspend
|
|
156
|
+
-- - user.activate
|
|
157
|
+
--
|
|
158
|
+
-- Client Management:
|
|
159
|
+
-- - client.create
|
|
160
|
+
-- - client.read
|
|
161
|
+
-- - client.update
|
|
162
|
+
-- - client.delete
|
|
163
|
+
-- - client.secret.rotate
|
|
164
|
+
-- =============================================================================
|
|
165
|
+
|
|
166
|
+
-- =============================================================================
|
|
167
|
+
-- Migration Complete
|
|
168
|
+
-- =============================================================================
|
|
169
|
+
-- Audit log is now ready for use.
|
|
170
|
+
-- All admin operations should write to this table.
|
|
171
|
+
--
|
|
172
|
+
-- Next steps:
|
|
173
|
+
-- 1. Apply 004_admin_security.sql for IP allowlist
|
|
174
|
+
-- 2. Implement admin audit log writer utility
|
|
175
|
+
-- =============================================================================
|