@happyvertical/smrt-users 0.53.3 → 0.53.5
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/AGENTS.md +43 -2
- package/README.md +185 -2
- package/agents/retention.md +14 -7
- package/dist/chunks/{TerminalAuthService-DoadwiqV.js → TerminalAuthService-BdB_0vDA.js} +3373 -2121
- package/dist/chunks/TerminalAuthService-BdB_0vDA.js.map +1 -0
- package/dist/collections/CliAuthApproveLimitCollection.d.ts +4 -0
- package/dist/collections/CliAuthApproveLimitCollection.d.ts.map +1 -1
- package/dist/collections/CliAuthRequestCollection.d.ts.map +1 -1
- package/dist/collections/LoginAttemptCollection.d.ts +105 -0
- package/dist/collections/LoginAttemptCollection.d.ts.map +1 -0
- package/dist/collections/LoginAuditEventCollection.d.ts +19 -0
- package/dist/collections/LoginAuditEventCollection.d.ts.map +1 -0
- package/dist/collections/PinCredentialCollection.d.ts +26 -0
- package/dist/collections/PinCredentialCollection.d.ts.map +1 -0
- package/dist/collections/SessionCollection.d.ts +33 -1
- package/dist/collections/SessionCollection.d.ts.map +1 -1
- package/dist/collections/index.d.ts +3 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +144 -31
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +3245 -1990
- package/dist/models/CliAuthApproveLimit.d.ts +8 -1
- package/dist/models/CliAuthApproveLimit.d.ts.map +1 -1
- package/dist/models/LoginAttempt.d.ts +59 -0
- package/dist/models/LoginAttempt.d.ts.map +1 -0
- package/dist/models/LoginAuditEvent.d.ts +49 -0
- package/dist/models/LoginAuditEvent.d.ts.map +1 -0
- package/dist/models/PinCredential.d.ts +31 -0
- package/dist/models/PinCredential.d.ts.map +1 -0
- package/dist/models/Session.d.ts +69 -1
- package/dist/models/Session.d.ts.map +1 -1
- package/dist/models/index.d.ts +4 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/retention.d.ts +7 -1
- package/dist/retention.d.ts.map +1 -1
- package/dist/services/DeviceCredentialService.d.ts +348 -0
- package/dist/services/DeviceCredentialService.d.ts.map +1 -0
- package/dist/services/LoginAttemptLimiter.d.ts +227 -0
- package/dist/services/LoginAttemptLimiter.d.ts.map +1 -0
- package/dist/services/MobileAuthService.d.ts.map +1 -1
- package/dist/services/OperationPermissionService.d.ts.map +1 -1
- package/dist/services/SessionPermissionContext.d.ts.map +1 -1
- package/dist/services/SessionService.d.ts +56 -1
- package/dist/services/SessionService.d.ts.map +1 -1
- package/dist/services/TerminalAuthService.d.ts +18 -3
- package/dist/services/TerminalAuthService.d.ts.map +1 -1
- package/dist/services/index.d.ts +4 -2
- package/dist/services/index.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +679 -9
- package/dist/sveltekit/device-credential-handlers.d.ts +60 -0
- package/dist/sveltekit/device-credential-handlers.d.ts.map +1 -0
- package/dist/sveltekit/index.d.ts +10 -0
- package/dist/sveltekit/index.d.ts.map +1 -1
- package/dist/sveltekit/types.d.ts +6 -0
- package/dist/sveltekit/types.d.ts.map +1 -1
- package/dist/sveltekit.js +184 -4
- package/dist/sveltekit.js.map +1 -1
- package/package.json +12 -12
- package/dist/chunks/TerminalAuthService-DoadwiqV.js.map +0 -1
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-users",
|
|
6
|
-
"packageVersion": "0.53.
|
|
6
|
+
"packageVersion": "0.53.5",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
10
|
+
"manifest": "272762d139d7b14daf501ff723c9e5587f0acdb46f60f405f1bf65d7f04dc9c6",
|
|
11
|
+
"packageJson": "fc0002c8def67fa279b4b897489ea8cb0ff3e2986122d8b67f4995fae1a82a4f",
|
|
12
|
+
"agents": "a0c6228ba98d46fc4bb2d39d6cc857c0a8a15571661169d2f8ffdbd9c1b0b966",
|
|
13
13
|
"moduleDoc:agents/permissions.md": "5f6c0afab7e1fd0887b0d29b5a5b5ab2635694207bade70145d3cbfdb62ba78c",
|
|
14
14
|
"moduleDoc:agents/oidc-provisioning.md": "5efa607ff23b9a693391e0c02670324a8cea4114d4968c9718f10a763da919c6",
|
|
15
15
|
"moduleDoc:agents/mobile-auth.md": "25e85e83f43e3a46383a92fa809f3a003b4545c3026e78dbe1bccbbc35161e18",
|
|
16
16
|
"moduleDoc:agents/terminal-auth-testing.md": "8a84c16a19e381427aed81d3b1882344c427fe22a70e87f5ac2db836b1a6822d",
|
|
17
|
-
"moduleDoc:agents/retention.md": "
|
|
17
|
+
"moduleDoc:agents/retention.md": "073874bf16ce3fbbc503157679dc7fe69800fb39a59e40299bcc713f099bf3d8"
|
|
18
18
|
},
|
|
19
19
|
"exports": [
|
|
20
20
|
".",
|
|
@@ -968,6 +968,133 @@
|
|
|
968
968
|
"tags": [],
|
|
969
969
|
"risks": []
|
|
970
970
|
},
|
|
971
|
+
{
|
|
972
|
+
"name": "UsersLoginAttemptCollection",
|
|
973
|
+
"qualifiedName": "@happyvertical/smrt-users:UsersLoginAttemptCollection",
|
|
974
|
+
"collection": "usersloginattempts",
|
|
975
|
+
"tableName": "users_login_attempts",
|
|
976
|
+
"packageName": "@happyvertical/smrt-users",
|
|
977
|
+
"extends": "SmrtCollection",
|
|
978
|
+
"fields": [],
|
|
979
|
+
"relationships": [],
|
|
980
|
+
"methods": [
|
|
981
|
+
"deleteIdle",
|
|
982
|
+
"recordFailure",
|
|
983
|
+
"releaseAttempt",
|
|
984
|
+
"reserveAttempt"
|
|
985
|
+
],
|
|
986
|
+
"methodSignatures": [
|
|
987
|
+
{
|
|
988
|
+
"name": "deleteIdle",
|
|
989
|
+
"async": true,
|
|
990
|
+
"params": [
|
|
991
|
+
"options?: object"
|
|
992
|
+
],
|
|
993
|
+
"returns": "Promise<number>"
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
"name": "recordFailure",
|
|
997
|
+
"async": true,
|
|
998
|
+
"params": [
|
|
999
|
+
"input: RecordLoginFailureInput"
|
|
1000
|
+
],
|
|
1001
|
+
"returns": "Promise<RecordedLoginFailure>"
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
"name": "releaseAttempt",
|
|
1005
|
+
"async": true,
|
|
1006
|
+
"params": [
|
|
1007
|
+
"limiterKey: string",
|
|
1008
|
+
"windowStartedAt: string",
|
|
1009
|
+
"options?: object"
|
|
1010
|
+
],
|
|
1011
|
+
"returns": "Promise<void>"
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
"name": "reserveAttempt",
|
|
1015
|
+
"async": true,
|
|
1016
|
+
"params": [
|
|
1017
|
+
"input: ReserveLoginAttemptInput"
|
|
1018
|
+
],
|
|
1019
|
+
"returns": "Promise<LoginAttemptReservation>"
|
|
1020
|
+
}
|
|
1021
|
+
],
|
|
1022
|
+
"surfaces": [],
|
|
1023
|
+
"withheldSurfaces": [
|
|
1024
|
+
{
|
|
1025
|
+
"kind": "api",
|
|
1026
|
+
"operation": "deleteIdle",
|
|
1027
|
+
"code": "api-disabled",
|
|
1028
|
+
"reason": "api is disabled",
|
|
1029
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAttemptCollection"
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
"kind": "api",
|
|
1033
|
+
"operation": "recordFailure",
|
|
1034
|
+
"code": "api-disabled",
|
|
1035
|
+
"reason": "api is disabled",
|
|
1036
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAttemptCollection"
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
"kind": "api",
|
|
1040
|
+
"operation": "releaseAttempt",
|
|
1041
|
+
"code": "api-disabled",
|
|
1042
|
+
"reason": "api is disabled",
|
|
1043
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAttemptCollection"
|
|
1044
|
+
},
|
|
1045
|
+
{
|
|
1046
|
+
"kind": "api",
|
|
1047
|
+
"operation": "reserveAttempt",
|
|
1048
|
+
"code": "api-disabled",
|
|
1049
|
+
"reason": "api is disabled",
|
|
1050
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAttemptCollection"
|
|
1051
|
+
}
|
|
1052
|
+
],
|
|
1053
|
+
"relationshipFeatures": [
|
|
1054
|
+
"uuidColumns"
|
|
1055
|
+
],
|
|
1056
|
+
"tags": [],
|
|
1057
|
+
"risks": []
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
"name": "UsersLoginAuditEventCollection",
|
|
1061
|
+
"qualifiedName": "@happyvertical/smrt-users:UsersLoginAuditEventCollection",
|
|
1062
|
+
"collection": "usersloginauditevents",
|
|
1063
|
+
"tableName": "users_login_audit_events",
|
|
1064
|
+
"packageName": "@happyvertical/smrt-users",
|
|
1065
|
+
"extends": "SmrtCollection",
|
|
1066
|
+
"fields": [],
|
|
1067
|
+
"relationships": [],
|
|
1068
|
+
"methods": [
|
|
1069
|
+
"deleteOlderThan"
|
|
1070
|
+
],
|
|
1071
|
+
"methodSignatures": [
|
|
1072
|
+
{
|
|
1073
|
+
"name": "deleteOlderThan",
|
|
1074
|
+
"async": true,
|
|
1075
|
+
"params": [
|
|
1076
|
+
"maxAgeMs: number",
|
|
1077
|
+
"options?: object"
|
|
1078
|
+
],
|
|
1079
|
+
"returns": "Promise<number>"
|
|
1080
|
+
}
|
|
1081
|
+
],
|
|
1082
|
+
"surfaces": [],
|
|
1083
|
+
"withheldSurfaces": [
|
|
1084
|
+
{
|
|
1085
|
+
"kind": "api",
|
|
1086
|
+
"operation": "deleteOlderThan",
|
|
1087
|
+
"code": "api-disabled",
|
|
1088
|
+
"reason": "api is disabled",
|
|
1089
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAuditEventCollection"
|
|
1090
|
+
}
|
|
1091
|
+
],
|
|
1092
|
+
"relationshipFeatures": [
|
|
1093
|
+
"uuidColumns"
|
|
1094
|
+
],
|
|
1095
|
+
"tags": [],
|
|
1096
|
+
"risks": []
|
|
1097
|
+
},
|
|
971
1098
|
{
|
|
972
1099
|
"name": "UsersMagicLinkTokenCollection",
|
|
973
1100
|
"qualifiedName": "@happyvertical/smrt-users:UsersMagicLinkTokenCollection",
|
|
@@ -1752,6 +1879,77 @@
|
|
|
1752
1879
|
"tags": [],
|
|
1753
1880
|
"risks": []
|
|
1754
1881
|
},
|
|
1882
|
+
{
|
|
1883
|
+
"name": "UsersPinCredentialCollection",
|
|
1884
|
+
"qualifiedName": "@happyvertical/smrt-users:UsersPinCredentialCollection",
|
|
1885
|
+
"collection": "userspincredentials",
|
|
1886
|
+
"tableName": "users_pin_credentials",
|
|
1887
|
+
"packageName": "@happyvertical/smrt-users",
|
|
1888
|
+
"extends": "SmrtCollection",
|
|
1889
|
+
"fields": [],
|
|
1890
|
+
"relationships": [],
|
|
1891
|
+
"methods": [
|
|
1892
|
+
"deleteByUserId",
|
|
1893
|
+
"findByUserId",
|
|
1894
|
+
"upsertForUser"
|
|
1895
|
+
],
|
|
1896
|
+
"methodSignatures": [
|
|
1897
|
+
{
|
|
1898
|
+
"name": "deleteByUserId",
|
|
1899
|
+
"async": true,
|
|
1900
|
+
"params": [
|
|
1901
|
+
"userId: string"
|
|
1902
|
+
],
|
|
1903
|
+
"returns": "Promise<boolean>"
|
|
1904
|
+
},
|
|
1905
|
+
{
|
|
1906
|
+
"name": "findByUserId",
|
|
1907
|
+
"async": true,
|
|
1908
|
+
"params": [
|
|
1909
|
+
"userId: string"
|
|
1910
|
+
],
|
|
1911
|
+
"returns": "Promise<UsersPinCredential | null>"
|
|
1912
|
+
},
|
|
1913
|
+
{
|
|
1914
|
+
"name": "upsertForUser",
|
|
1915
|
+
"async": true,
|
|
1916
|
+
"params": [
|
|
1917
|
+
"userId: string",
|
|
1918
|
+
"write: PinCredentialWrite"
|
|
1919
|
+
],
|
|
1920
|
+
"returns": "Promise<UsersPinCredential>"
|
|
1921
|
+
}
|
|
1922
|
+
],
|
|
1923
|
+
"surfaces": [],
|
|
1924
|
+
"withheldSurfaces": [
|
|
1925
|
+
{
|
|
1926
|
+
"kind": "api",
|
|
1927
|
+
"operation": "deleteByUserId",
|
|
1928
|
+
"code": "api-disabled",
|
|
1929
|
+
"reason": "api is disabled",
|
|
1930
|
+
"objectName": "@happyvertical/smrt-users:UsersPinCredentialCollection"
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
"kind": "api",
|
|
1934
|
+
"operation": "findByUserId",
|
|
1935
|
+
"code": "api-disabled",
|
|
1936
|
+
"reason": "api is disabled",
|
|
1937
|
+
"objectName": "@happyvertical/smrt-users:UsersPinCredentialCollection"
|
|
1938
|
+
},
|
|
1939
|
+
{
|
|
1940
|
+
"kind": "api",
|
|
1941
|
+
"operation": "upsertForUser",
|
|
1942
|
+
"code": "api-disabled",
|
|
1943
|
+
"reason": "api is disabled",
|
|
1944
|
+
"objectName": "@happyvertical/smrt-users:UsersPinCredentialCollection"
|
|
1945
|
+
}
|
|
1946
|
+
],
|
|
1947
|
+
"relationshipFeatures": [
|
|
1948
|
+
"uuidColumns"
|
|
1949
|
+
],
|
|
1950
|
+
"tags": [],
|
|
1951
|
+
"risks": []
|
|
1952
|
+
},
|
|
1755
1953
|
{
|
|
1756
1954
|
"name": "ResourceGrantCollection",
|
|
1757
1955
|
"qualifiedName": "@happyvertical/smrt-users:ResourceGrantCollection",
|
|
@@ -2300,10 +2498,13 @@
|
|
|
2300
2498
|
"deleteExpired",
|
|
2301
2499
|
"deleteUserSessions",
|
|
2302
2500
|
"findByUser",
|
|
2501
|
+
"findChildren",
|
|
2303
2502
|
"findValidSession",
|
|
2304
2503
|
"getSessionData",
|
|
2504
|
+
"revokeChildren",
|
|
2305
2505
|
"revokeSession",
|
|
2306
2506
|
"revokeUserSessions",
|
|
2507
|
+
"revokeUserSessionsByAuthMethod",
|
|
2307
2508
|
"setSessionData",
|
|
2308
2509
|
"setSessionTenant",
|
|
2309
2510
|
"touch"
|
|
@@ -2349,6 +2550,14 @@
|
|
|
2349
2550
|
],
|
|
2350
2551
|
"returns": "Promise<Session[]>"
|
|
2351
2552
|
},
|
|
2553
|
+
{
|
|
2554
|
+
"name": "findChildren",
|
|
2555
|
+
"async": true,
|
|
2556
|
+
"params": [
|
|
2557
|
+
"parentSessionId: string"
|
|
2558
|
+
],
|
|
2559
|
+
"returns": "Promise<Session[]>"
|
|
2560
|
+
},
|
|
2352
2561
|
{
|
|
2353
2562
|
"name": "findValidSession",
|
|
2354
2563
|
"async": true,
|
|
@@ -2366,6 +2575,15 @@
|
|
|
2366
2575
|
],
|
|
2367
2576
|
"returns": "Promise<T | undefined>"
|
|
2368
2577
|
},
|
|
2578
|
+
{
|
|
2579
|
+
"name": "revokeChildren",
|
|
2580
|
+
"async": true,
|
|
2581
|
+
"params": [
|
|
2582
|
+
"parentSessionId: string",
|
|
2583
|
+
"options?: object"
|
|
2584
|
+
],
|
|
2585
|
+
"returns": "Promise<number>"
|
|
2586
|
+
},
|
|
2369
2587
|
{
|
|
2370
2588
|
"name": "revokeSession",
|
|
2371
2589
|
"async": true,
|
|
@@ -2382,6 +2600,16 @@
|
|
|
2382
2600
|
],
|
|
2383
2601
|
"returns": "Promise<number>"
|
|
2384
2602
|
},
|
|
2603
|
+
{
|
|
2604
|
+
"name": "revokeUserSessionsByAuthMethod",
|
|
2605
|
+
"async": true,
|
|
2606
|
+
"params": [
|
|
2607
|
+
"userId: string",
|
|
2608
|
+
"authMethod: SessionAuthMethod",
|
|
2609
|
+
"options?: object"
|
|
2610
|
+
],
|
|
2611
|
+
"returns": "Promise<number>"
|
|
2612
|
+
},
|
|
2385
2613
|
{
|
|
2386
2614
|
"name": "setSessionData",
|
|
2387
2615
|
"async": true,
|
|
@@ -2421,6 +2649,30 @@
|
|
|
2421
2649
|
"path": "/sessions/createSession",
|
|
2422
2650
|
"method": "POST"
|
|
2423
2651
|
},
|
|
2652
|
+
{
|
|
2653
|
+
"kind": "api",
|
|
2654
|
+
"name": "sessions.findChildren",
|
|
2655
|
+
"operation": "findChildren",
|
|
2656
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection",
|
|
2657
|
+
"path": "/sessions/findChildren",
|
|
2658
|
+
"method": "POST"
|
|
2659
|
+
},
|
|
2660
|
+
{
|
|
2661
|
+
"kind": "api",
|
|
2662
|
+
"name": "sessions.revokeChildren",
|
|
2663
|
+
"operation": "revokeChildren",
|
|
2664
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection",
|
|
2665
|
+
"path": "/sessions/revokeChildren",
|
|
2666
|
+
"method": "POST"
|
|
2667
|
+
},
|
|
2668
|
+
{
|
|
2669
|
+
"kind": "api",
|
|
2670
|
+
"name": "sessions.revokeUserSessionsByAuthMethod",
|
|
2671
|
+
"operation": "revokeUserSessionsByAuthMethod",
|
|
2672
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection",
|
|
2673
|
+
"path": "/sessions/revokeUserSessionsByAuthMethod",
|
|
2674
|
+
"method": "POST"
|
|
2675
|
+
},
|
|
2424
2676
|
{
|
|
2425
2677
|
"kind": "api",
|
|
2426
2678
|
"name": "sessions.findValidSession",
|
|
@@ -2515,6 +2767,24 @@
|
|
|
2515
2767
|
"operation": "createSession",
|
|
2516
2768
|
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2517
2769
|
},
|
|
2770
|
+
{
|
|
2771
|
+
"kind": "cli",
|
|
2772
|
+
"name": "sessioncollection_findChildren",
|
|
2773
|
+
"operation": "findChildren",
|
|
2774
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2775
|
+
},
|
|
2776
|
+
{
|
|
2777
|
+
"kind": "cli",
|
|
2778
|
+
"name": "sessioncollection_revokeChildren",
|
|
2779
|
+
"operation": "revokeChildren",
|
|
2780
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2781
|
+
},
|
|
2782
|
+
{
|
|
2783
|
+
"kind": "cli",
|
|
2784
|
+
"name": "sessioncollection_revokeUserSessionsByAuthMethod",
|
|
2785
|
+
"operation": "revokeUserSessionsByAuthMethod",
|
|
2786
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2787
|
+
},
|
|
2518
2788
|
{
|
|
2519
2789
|
"kind": "cli",
|
|
2520
2790
|
"name": "sessioncollection_findValidSession",
|
|
@@ -2587,6 +2857,24 @@
|
|
|
2587
2857
|
"operation": "createSession",
|
|
2588
2858
|
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2589
2859
|
},
|
|
2860
|
+
{
|
|
2861
|
+
"kind": "mcp",
|
|
2862
|
+
"name": "sessioncollection_findchildren",
|
|
2863
|
+
"operation": "findChildren",
|
|
2864
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2865
|
+
},
|
|
2866
|
+
{
|
|
2867
|
+
"kind": "mcp",
|
|
2868
|
+
"name": "sessioncollection_revokechildren",
|
|
2869
|
+
"operation": "revokeChildren",
|
|
2870
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2871
|
+
},
|
|
2872
|
+
{
|
|
2873
|
+
"kind": "mcp",
|
|
2874
|
+
"name": "sessioncollection_revokeusersessionsbyauthmethod",
|
|
2875
|
+
"operation": "revokeUserSessionsByAuthMethod",
|
|
2876
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
2877
|
+
},
|
|
2590
2878
|
{
|
|
2591
2879
|
"kind": "mcp",
|
|
2592
2880
|
"name": "sessioncollection_findvalidsession",
|
|
@@ -4652,6 +4940,166 @@
|
|
|
4652
4940
|
"tags": [],
|
|
4653
4941
|
"risks": []
|
|
4654
4942
|
},
|
|
4943
|
+
{
|
|
4944
|
+
"name": "UsersLoginAttempt",
|
|
4945
|
+
"qualifiedName": "@happyvertical/smrt-users:UsersLoginAttempt",
|
|
4946
|
+
"collection": "usersloginattempts",
|
|
4947
|
+
"tableName": "users_login_attempts",
|
|
4948
|
+
"packageName": "@happyvertical/smrt-users",
|
|
4949
|
+
"extends": "SmrtObject",
|
|
4950
|
+
"fields": [
|
|
4951
|
+
{
|
|
4952
|
+
"name": "limiterKey",
|
|
4953
|
+
"type": "text",
|
|
4954
|
+
"required": true,
|
|
4955
|
+
"columnType": "TEXT"
|
|
4956
|
+
},
|
|
4957
|
+
{
|
|
4958
|
+
"name": "scope",
|
|
4959
|
+
"type": "text",
|
|
4960
|
+
"required": true,
|
|
4961
|
+
"columnType": "TEXT"
|
|
4962
|
+
},
|
|
4963
|
+
{
|
|
4964
|
+
"name": "attemptCount",
|
|
4965
|
+
"type": "integer",
|
|
4966
|
+
"required": true,
|
|
4967
|
+
"columnType": "INTEGER",
|
|
4968
|
+
"default": 0
|
|
4969
|
+
},
|
|
4970
|
+
{
|
|
4971
|
+
"name": "windowStartedAt",
|
|
4972
|
+
"type": "datetime",
|
|
4973
|
+
"required": true,
|
|
4974
|
+
"columnType": "TIMESTAMP"
|
|
4975
|
+
},
|
|
4976
|
+
{
|
|
4977
|
+
"name": "failureStreak",
|
|
4978
|
+
"type": "integer",
|
|
4979
|
+
"required": true,
|
|
4980
|
+
"columnType": "INTEGER",
|
|
4981
|
+
"default": 0
|
|
4982
|
+
},
|
|
4983
|
+
{
|
|
4984
|
+
"name": "lockedUntil",
|
|
4985
|
+
"type": "datetime",
|
|
4986
|
+
"required": false,
|
|
4987
|
+
"columnType": "TIMESTAMP"
|
|
4988
|
+
},
|
|
4989
|
+
{
|
|
4990
|
+
"name": "lastFailedAt",
|
|
4991
|
+
"type": "datetime",
|
|
4992
|
+
"required": false,
|
|
4993
|
+
"columnType": "TIMESTAMP"
|
|
4994
|
+
},
|
|
4995
|
+
{
|
|
4996
|
+
"name": "retainUntil",
|
|
4997
|
+
"type": "datetime",
|
|
4998
|
+
"required": true,
|
|
4999
|
+
"columnType": "TIMESTAMP"
|
|
5000
|
+
}
|
|
5001
|
+
],
|
|
5002
|
+
"relationships": [],
|
|
5003
|
+
"methods": [],
|
|
5004
|
+
"surfaces": [],
|
|
5005
|
+
"relationshipFeatures": [
|
|
5006
|
+
"uuidColumns"
|
|
5007
|
+
],
|
|
5008
|
+
"tags": [],
|
|
5009
|
+
"risks": []
|
|
5010
|
+
},
|
|
5011
|
+
{
|
|
5012
|
+
"name": "UsersLoginAuditEvent",
|
|
5013
|
+
"qualifiedName": "@happyvertical/smrt-users:UsersLoginAuditEvent",
|
|
5014
|
+
"collection": "usersloginauditevents",
|
|
5015
|
+
"tableName": "users_login_audit_events",
|
|
5016
|
+
"packageName": "@happyvertical/smrt-users",
|
|
5017
|
+
"extends": "SmrtObject",
|
|
5018
|
+
"fields": [
|
|
5019
|
+
{
|
|
5020
|
+
"name": "kind",
|
|
5021
|
+
"type": "text",
|
|
5022
|
+
"required": true,
|
|
5023
|
+
"columnType": "TEXT"
|
|
5024
|
+
},
|
|
5025
|
+
{
|
|
5026
|
+
"name": "outcome",
|
|
5027
|
+
"type": "text",
|
|
5028
|
+
"required": true,
|
|
5029
|
+
"columnType": "TEXT"
|
|
5030
|
+
},
|
|
5031
|
+
{
|
|
5032
|
+
"name": "subjectKeyHash",
|
|
5033
|
+
"type": "text",
|
|
5034
|
+
"required": false,
|
|
5035
|
+
"columnType": "TEXT"
|
|
5036
|
+
},
|
|
5037
|
+
{
|
|
5038
|
+
"name": "sourceKeyHash",
|
|
5039
|
+
"type": "text",
|
|
5040
|
+
"required": false,
|
|
5041
|
+
"columnType": "TEXT"
|
|
5042
|
+
},
|
|
5043
|
+
{
|
|
5044
|
+
"name": "retryAfterSeconds",
|
|
5045
|
+
"type": "integer",
|
|
5046
|
+
"required": false,
|
|
5047
|
+
"columnType": "INTEGER"
|
|
5048
|
+
},
|
|
5049
|
+
{
|
|
5050
|
+
"name": "occurredAt",
|
|
5051
|
+
"type": "datetime",
|
|
5052
|
+
"required": true,
|
|
5053
|
+
"columnType": "TIMESTAMP"
|
|
5054
|
+
},
|
|
5055
|
+
{
|
|
5056
|
+
"name": "metadata",
|
|
5057
|
+
"type": "text",
|
|
5058
|
+
"required": false,
|
|
5059
|
+
"columnType": "TEXT"
|
|
5060
|
+
}
|
|
5061
|
+
],
|
|
5062
|
+
"relationships": [],
|
|
5063
|
+
"methods": [
|
|
5064
|
+
"getMetadata",
|
|
5065
|
+
"setMetadata"
|
|
5066
|
+
],
|
|
5067
|
+
"methodSignatures": [
|
|
5068
|
+
{
|
|
5069
|
+
"name": "getMetadata",
|
|
5070
|
+
"returns": "Record<string, unknown>"
|
|
5071
|
+
},
|
|
5072
|
+
{
|
|
5073
|
+
"name": "setMetadata",
|
|
5074
|
+
"params": [
|
|
5075
|
+
"value: Record<string, unknown>"
|
|
5076
|
+
],
|
|
5077
|
+
"returns": "void"
|
|
5078
|
+
}
|
|
5079
|
+
],
|
|
5080
|
+
"surfaces": [],
|
|
5081
|
+
"withheldSurfaces": [
|
|
5082
|
+
{
|
|
5083
|
+
"kind": "api",
|
|
5084
|
+
"operation": "getMetadata",
|
|
5085
|
+
"code": "api-disabled",
|
|
5086
|
+
"reason": "api is disabled",
|
|
5087
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAuditEvent"
|
|
5088
|
+
},
|
|
5089
|
+
{
|
|
5090
|
+
"kind": "api",
|
|
5091
|
+
"operation": "setMetadata",
|
|
5092
|
+
"code": "api-disabled",
|
|
5093
|
+
"reason": "api is disabled",
|
|
5094
|
+
"objectName": "@happyvertical/smrt-users:UsersLoginAuditEvent"
|
|
5095
|
+
}
|
|
5096
|
+
],
|
|
5097
|
+
"relationshipFeatures": [
|
|
5098
|
+
"uuidColumns"
|
|
5099
|
+
],
|
|
5100
|
+
"tags": [],
|
|
5101
|
+
"risks": []
|
|
5102
|
+
},
|
|
4655
5103
|
{
|
|
4656
5104
|
"name": "UsersMagicLinkToken",
|
|
4657
5105
|
"qualifiedName": "@happyvertical/smrt-users:UsersMagicLinkToken",
|
|
@@ -5271,6 +5719,66 @@
|
|
|
5271
5719
|
"tags": [],
|
|
5272
5720
|
"risks": []
|
|
5273
5721
|
},
|
|
5722
|
+
{
|
|
5723
|
+
"name": "UsersPinCredential",
|
|
5724
|
+
"qualifiedName": "@happyvertical/smrt-users:UsersPinCredential",
|
|
5725
|
+
"collection": "userspincredentials",
|
|
5726
|
+
"tableName": "users_pin_credentials",
|
|
5727
|
+
"packageName": "@happyvertical/smrt-users",
|
|
5728
|
+
"extends": "SmrtObject",
|
|
5729
|
+
"fields": [
|
|
5730
|
+
{
|
|
5731
|
+
"name": "userId",
|
|
5732
|
+
"type": "foreignKey",
|
|
5733
|
+
"required": true,
|
|
5734
|
+
"related": "User",
|
|
5735
|
+
"columnType": "UUID"
|
|
5736
|
+
},
|
|
5737
|
+
{
|
|
5738
|
+
"name": "version",
|
|
5739
|
+
"type": "integer",
|
|
5740
|
+
"required": true,
|
|
5741
|
+
"columnType": "INTEGER",
|
|
5742
|
+
"default": 1
|
|
5743
|
+
},
|
|
5744
|
+
{
|
|
5745
|
+
"name": "mustReset",
|
|
5746
|
+
"type": "boolean",
|
|
5747
|
+
"required": true,
|
|
5748
|
+
"columnType": "BOOLEAN",
|
|
5749
|
+
"default": false
|
|
5750
|
+
},
|
|
5751
|
+
{
|
|
5752
|
+
"name": "rotatedAt",
|
|
5753
|
+
"type": "datetime",
|
|
5754
|
+
"required": false,
|
|
5755
|
+
"columnType": "TIMESTAMP"
|
|
5756
|
+
},
|
|
5757
|
+
{
|
|
5758
|
+
"name": "rotatedBy",
|
|
5759
|
+
"type": "text",
|
|
5760
|
+
"required": false,
|
|
5761
|
+
"columnType": "TEXT"
|
|
5762
|
+
}
|
|
5763
|
+
],
|
|
5764
|
+
"relationships": [
|
|
5765
|
+
{
|
|
5766
|
+
"name": "userId",
|
|
5767
|
+
"type": "foreignKey",
|
|
5768
|
+
"required": true,
|
|
5769
|
+
"related": "User",
|
|
5770
|
+
"columnType": "UUID"
|
|
5771
|
+
}
|
|
5772
|
+
],
|
|
5773
|
+
"methods": [],
|
|
5774
|
+
"surfaces": [],
|
|
5775
|
+
"relationshipFeatures": [
|
|
5776
|
+
"foreignKey",
|
|
5777
|
+
"uuidColumns"
|
|
5778
|
+
],
|
|
5779
|
+
"tags": [],
|
|
5780
|
+
"risks": []
|
|
5781
|
+
},
|
|
5274
5782
|
{
|
|
5275
5783
|
"name": "ResourceGrant",
|
|
5276
5784
|
"qualifiedName": "@happyvertical/smrt-users:ResourceGrant",
|
|
@@ -5796,6 +6304,12 @@
|
|
|
5796
6304
|
"required": false,
|
|
5797
6305
|
"columnType": "JSON",
|
|
5798
6306
|
"default": {}
|
|
6307
|
+
},
|
|
6308
|
+
{
|
|
6309
|
+
"name": "authMethod",
|
|
6310
|
+
"type": "text",
|
|
6311
|
+
"required": false,
|
|
6312
|
+
"columnType": "TEXT"
|
|
5799
6313
|
}
|
|
5800
6314
|
],
|
|
5801
6315
|
"relationships": [
|
|
@@ -5816,8 +6330,12 @@
|
|
|
5816
6330
|
],
|
|
5817
6331
|
"methods": [
|
|
5818
6332
|
"extend",
|
|
6333
|
+
"getAbsoluteExpiry",
|
|
5819
6334
|
"getData",
|
|
6335
|
+
"getIdleSeconds",
|
|
6336
|
+
"getPermissionCeiling",
|
|
5820
6337
|
"isExpired",
|
|
6338
|
+
"isLayered",
|
|
5821
6339
|
"isRevoked",
|
|
5822
6340
|
"isValid",
|
|
5823
6341
|
"recordActivity",
|
|
@@ -5835,6 +6353,10 @@
|
|
|
5835
6353
|
],
|
|
5836
6354
|
"returns": "void"
|
|
5837
6355
|
},
|
|
6356
|
+
{
|
|
6357
|
+
"name": "getAbsoluteExpiry",
|
|
6358
|
+
"returns": "Date | null"
|
|
6359
|
+
},
|
|
5838
6360
|
{
|
|
5839
6361
|
"name": "getData",
|
|
5840
6362
|
"params": [
|
|
@@ -5842,10 +6364,22 @@
|
|
|
5842
6364
|
],
|
|
5843
6365
|
"returns": "T | undefined"
|
|
5844
6366
|
},
|
|
6367
|
+
{
|
|
6368
|
+
"name": "getIdleSeconds",
|
|
6369
|
+
"returns": "number | null"
|
|
6370
|
+
},
|
|
6371
|
+
{
|
|
6372
|
+
"name": "getPermissionCeiling",
|
|
6373
|
+
"returns": "string[] | null"
|
|
6374
|
+
},
|
|
5845
6375
|
{
|
|
5846
6376
|
"name": "isExpired",
|
|
5847
6377
|
"returns": "boolean"
|
|
5848
6378
|
},
|
|
6379
|
+
{
|
|
6380
|
+
"name": "isLayered",
|
|
6381
|
+
"returns": "boolean"
|
|
6382
|
+
},
|
|
5849
6383
|
{
|
|
5850
6384
|
"name": "isRevoked",
|
|
5851
6385
|
"returns": "boolean"
|
|
@@ -5946,6 +6480,30 @@
|
|
|
5946
6480
|
"operation": "delete",
|
|
5947
6481
|
"objectName": "@happyvertical/smrt-users:Session"
|
|
5948
6482
|
},
|
|
6483
|
+
{
|
|
6484
|
+
"kind": "cli",
|
|
6485
|
+
"name": "session_isLayered",
|
|
6486
|
+
"operation": "isLayered",
|
|
6487
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6488
|
+
},
|
|
6489
|
+
{
|
|
6490
|
+
"kind": "cli",
|
|
6491
|
+
"name": "session_getAbsoluteExpiry",
|
|
6492
|
+
"operation": "getAbsoluteExpiry",
|
|
6493
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6494
|
+
},
|
|
6495
|
+
{
|
|
6496
|
+
"kind": "cli",
|
|
6497
|
+
"name": "session_getIdleSeconds",
|
|
6498
|
+
"operation": "getIdleSeconds",
|
|
6499
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6500
|
+
},
|
|
6501
|
+
{
|
|
6502
|
+
"kind": "cli",
|
|
6503
|
+
"name": "session_getPermissionCeiling",
|
|
6504
|
+
"operation": "getPermissionCeiling",
|
|
6505
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6506
|
+
},
|
|
5949
6507
|
{
|
|
5950
6508
|
"kind": "cli",
|
|
5951
6509
|
"name": "session_isValid",
|
|
@@ -6021,6 +6579,13 @@
|
|
|
6021
6579
|
"reason": "not listed in api.include",
|
|
6022
6580
|
"objectName": "@happyvertical/smrt-users:Session"
|
|
6023
6581
|
},
|
|
6582
|
+
{
|
|
6583
|
+
"kind": "api",
|
|
6584
|
+
"operation": "getAbsoluteExpiry",
|
|
6585
|
+
"code": "not-included",
|
|
6586
|
+
"reason": "not listed in api.include",
|
|
6587
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6588
|
+
},
|
|
6024
6589
|
{
|
|
6025
6590
|
"kind": "api",
|
|
6026
6591
|
"operation": "getData",
|
|
@@ -6028,6 +6593,20 @@
|
|
|
6028
6593
|
"reason": "not listed in api.include",
|
|
6029
6594
|
"objectName": "@happyvertical/smrt-users:Session"
|
|
6030
6595
|
},
|
|
6596
|
+
{
|
|
6597
|
+
"kind": "api",
|
|
6598
|
+
"operation": "getIdleSeconds",
|
|
6599
|
+
"code": "not-included",
|
|
6600
|
+
"reason": "not listed in api.include",
|
|
6601
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6602
|
+
},
|
|
6603
|
+
{
|
|
6604
|
+
"kind": "api",
|
|
6605
|
+
"operation": "getPermissionCeiling",
|
|
6606
|
+
"code": "not-included",
|
|
6607
|
+
"reason": "not listed in api.include",
|
|
6608
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6609
|
+
},
|
|
6031
6610
|
{
|
|
6032
6611
|
"kind": "api",
|
|
6033
6612
|
"operation": "isExpired",
|
|
@@ -6035,6 +6614,13 @@
|
|
|
6035
6614
|
"reason": "not listed in api.include",
|
|
6036
6615
|
"objectName": "@happyvertical/smrt-users:Session"
|
|
6037
6616
|
},
|
|
6617
|
+
{
|
|
6618
|
+
"kind": "api",
|
|
6619
|
+
"operation": "isLayered",
|
|
6620
|
+
"code": "not-included",
|
|
6621
|
+
"reason": "not listed in api.include",
|
|
6622
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
6623
|
+
},
|
|
6038
6624
|
{
|
|
6039
6625
|
"kind": "api",
|
|
6040
6626
|
"operation": "isRevoked",
|
|
@@ -8404,6 +8990,30 @@
|
|
|
8404
8990
|
"path": "/sessions/createSession",
|
|
8405
8991
|
"method": "POST"
|
|
8406
8992
|
},
|
|
8993
|
+
{
|
|
8994
|
+
"kind": "api",
|
|
8995
|
+
"name": "sessions.findChildren",
|
|
8996
|
+
"operation": "findChildren",
|
|
8997
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection",
|
|
8998
|
+
"path": "/sessions/findChildren",
|
|
8999
|
+
"method": "POST"
|
|
9000
|
+
},
|
|
9001
|
+
{
|
|
9002
|
+
"kind": "api",
|
|
9003
|
+
"name": "sessions.revokeChildren",
|
|
9004
|
+
"operation": "revokeChildren",
|
|
9005
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection",
|
|
9006
|
+
"path": "/sessions/revokeChildren",
|
|
9007
|
+
"method": "POST"
|
|
9008
|
+
},
|
|
9009
|
+
{
|
|
9010
|
+
"kind": "api",
|
|
9011
|
+
"name": "sessions.revokeUserSessionsByAuthMethod",
|
|
9012
|
+
"operation": "revokeUserSessionsByAuthMethod",
|
|
9013
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection",
|
|
9014
|
+
"path": "/sessions/revokeUserSessionsByAuthMethod",
|
|
9015
|
+
"method": "POST"
|
|
9016
|
+
},
|
|
8407
9017
|
{
|
|
8408
9018
|
"kind": "api",
|
|
8409
9019
|
"name": "sessions.findValidSession",
|
|
@@ -8498,6 +9108,24 @@
|
|
|
8498
9108
|
"operation": "createSession",
|
|
8499
9109
|
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
8500
9110
|
},
|
|
9111
|
+
{
|
|
9112
|
+
"kind": "cli",
|
|
9113
|
+
"name": "sessioncollection_findChildren",
|
|
9114
|
+
"operation": "findChildren",
|
|
9115
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
9116
|
+
},
|
|
9117
|
+
{
|
|
9118
|
+
"kind": "cli",
|
|
9119
|
+
"name": "sessioncollection_revokeChildren",
|
|
9120
|
+
"operation": "revokeChildren",
|
|
9121
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
9122
|
+
},
|
|
9123
|
+
{
|
|
9124
|
+
"kind": "cli",
|
|
9125
|
+
"name": "sessioncollection_revokeUserSessionsByAuthMethod",
|
|
9126
|
+
"operation": "revokeUserSessionsByAuthMethod",
|
|
9127
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
9128
|
+
},
|
|
8501
9129
|
{
|
|
8502
9130
|
"kind": "cli",
|
|
8503
9131
|
"name": "sessioncollection_findValidSession",
|
|
@@ -8570,6 +9198,24 @@
|
|
|
8570
9198
|
"operation": "createSession",
|
|
8571
9199
|
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
8572
9200
|
},
|
|
9201
|
+
{
|
|
9202
|
+
"kind": "mcp",
|
|
9203
|
+
"name": "sessioncollection_findchildren",
|
|
9204
|
+
"operation": "findChildren",
|
|
9205
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
9206
|
+
},
|
|
9207
|
+
{
|
|
9208
|
+
"kind": "mcp",
|
|
9209
|
+
"name": "sessioncollection_revokechildren",
|
|
9210
|
+
"operation": "revokeChildren",
|
|
9211
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
9212
|
+
},
|
|
9213
|
+
{
|
|
9214
|
+
"kind": "mcp",
|
|
9215
|
+
"name": "sessioncollection_revokeusersessionsbyauthmethod",
|
|
9216
|
+
"operation": "revokeUserSessionsByAuthMethod",
|
|
9217
|
+
"objectName": "@happyvertical/smrt-users:SessionCollection"
|
|
9218
|
+
},
|
|
8573
9219
|
{
|
|
8574
9220
|
"kind": "mcp",
|
|
8575
9221
|
"name": "sessioncollection_findvalidsession",
|
|
@@ -10150,6 +10796,30 @@
|
|
|
10150
10796
|
"operation": "delete",
|
|
10151
10797
|
"objectName": "@happyvertical/smrt-users:Session"
|
|
10152
10798
|
},
|
|
10799
|
+
{
|
|
10800
|
+
"kind": "cli",
|
|
10801
|
+
"name": "session_isLayered",
|
|
10802
|
+
"operation": "isLayered",
|
|
10803
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
10804
|
+
},
|
|
10805
|
+
{
|
|
10806
|
+
"kind": "cli",
|
|
10807
|
+
"name": "session_getAbsoluteExpiry",
|
|
10808
|
+
"operation": "getAbsoluteExpiry",
|
|
10809
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
10810
|
+
},
|
|
10811
|
+
{
|
|
10812
|
+
"kind": "cli",
|
|
10813
|
+
"name": "session_getIdleSeconds",
|
|
10814
|
+
"operation": "getIdleSeconds",
|
|
10815
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
10816
|
+
},
|
|
10817
|
+
{
|
|
10818
|
+
"kind": "cli",
|
|
10819
|
+
"name": "session_getPermissionCeiling",
|
|
10820
|
+
"operation": "getPermissionCeiling",
|
|
10821
|
+
"objectName": "@happyvertical/smrt-users:Session"
|
|
10822
|
+
},
|
|
10153
10823
|
{
|
|
10154
10824
|
"kind": "cli",
|
|
10155
10825
|
"name": "session_isValid",
|
|
@@ -10583,14 +11253,14 @@
|
|
|
10583
11253
|
],
|
|
10584
11254
|
"prompts": [],
|
|
10585
11255
|
"relationshipsV2": {
|
|
10586
|
-
"foreignKeyFields":
|
|
11256
|
+
"foreignKeyFields": 26,
|
|
10587
11257
|
"crossPackageRefFields": 1,
|
|
10588
11258
|
"junctionCollections": 0,
|
|
10589
11259
|
"hierarchicalObjects": 0,
|
|
10590
11260
|
"polymorphicAssociations": 0,
|
|
10591
|
-
"uuidColumns":
|
|
11261
|
+
"uuidColumns": 100
|
|
10592
11262
|
},
|
|
10593
|
-
"agentDoc": "# @happyvertical/smrt-users\n\nMulti-tenant identity, RBAC, hierarchical tenants, sessions, and SvelteKit auth.\n\n## Modules\n\nRead only the module relevant to the change; protocol and provisioning details\nare not prerequisites for unrelated user-package work.\n\n| Module | Scope | Module doc |\n|---|---|---|\n| `src/services/PermissionResolver.ts` | permission precedence, inherited memberships, guards, RLS, role seeding | [agents/permissions.md](agents/permissions.md) |\n| `src/services/OidcLoginService.ts`, collections and OIDC handlers | identity reconciliation, transaction boundaries, migration readiness | [agents/oidc-provisioning.md](agents/oidc-provisioning.md) |\n| `src/services/MobileAuthService.ts` | mobile handshake, bearer sessions, bootstrap extension boundary | [agents/mobile-auth.md](agents/mobile-auth.md) |\n| `src/services/TerminalAuthService.ts`, `src/collections/
|
|
11263
|
+
"agentDoc": "# @happyvertical/smrt-users\n\nMulti-tenant identity, RBAC, hierarchical tenants, sessions, and SvelteKit auth.\n\n## Modules\n\nRead only the module relevant to the change; protocol and provisioning details\nare not prerequisites for unrelated user-package work.\n\n| Module | Scope | Module doc |\n|---|---|---|\n| `src/services/PermissionResolver.ts` | permission precedence, inherited memberships, guards, RLS, role seeding | [agents/permissions.md](agents/permissions.md) |\n| `src/services/OidcLoginService.ts`, collections and OIDC handlers | identity reconciliation, transaction boundaries, migration readiness | [agents/oidc-provisioning.md](agents/oidc-provisioning.md) |\n| `src/services/MobileAuthService.ts` | mobile handshake, bearer sessions, bootstrap extension boundary | [agents/mobile-auth.md](agents/mobile-auth.md) |\n| `src/services/TerminalAuthService.ts`, `src/services/LoginAttemptLimiter.ts`, `src/collections/LoginAttemptCollection.ts` | terminal approval concurrency, shared login budget and lockout (#3273), retry-safe database fixtures | [agents/terminal-auth-testing.md](agents/terminal-auth-testing.md) |\n| `src/services/DeviceCredentialService.ts` | per-person PIN layered on a device session (#3276), verifier seam for other credential kinds | this file, \"Security boundaries\" |\n| `src/retention.ts` | expired session/token/CLI-auth reaping and retention sweep wiring | [agents/retention.md](agents/retention.md) |\n\n## Models and authority\n\n- Users are global; tenant access comes through Membership (unique user/tenant).\n User email is normalized and globally unique through readonly nullable\n `emailKey`. `profileId` is a unique cross-package reference: at most one User\n owns each non-null Profile.\n- Tenant uses STI and a materialized hierarchy, maximum depth 10.\n `hierarchyPath`/`hierarchyLevel` are derived from `parentTenantId` by\n `Tenant.save()` on every save (any caller-supplied value is recomputed) and\n descendants are re-materialized when they change; never hand-maintain them.\n Legacy rows are backfilled with `smrt db:materialize-tenant-hierarchy`\n (`materializeTenantHierarchy()`). Tests that need a corrupt path must write it\n with raw SQL (#3036).\n- Role with `tenantId = null` is available to all tenants; `isSystem` prevents\n deletion. `inheritsToDescendants` is opt-in. Seed owner/admin/member/viewer\n through `RoleCollection.seedSystemRoles()` at application initialization.\n- Group roles apply only in their own tenant. Use `getGroupIdsForTenant()`,\n never cross-tenant `getGroupIds()`, for authorization.\n- Upward visibility is opt-in and read-only: `permissions.ancestorRead`\n ({ roles, collections, maxDepth? }) lets a DESCENDANT membership contribute\n declared `<collection>.read` at an ancestor, only when no membership resolved\n there, intersected with BOTH the role's own catalog grants and the\n principal's effective permissions in that descendant, and only for SYSTEM\n roles (a tenant-scoped role sharing a declared slug is ignored). Off by default, never\n write, never lateral, and never row visibility — sibling rows stay scoped by\n tenancy/RLS. Read the permissions module before changing it.\n- Membership DENY always wins. Direct inactive membership blocks inherited\n authority; a direct active membership pins resolution instead of unioning it\n with ancestors. Read the permissions module before changing these rules.\n- AccessRequest has no generated API/MCP/CLI operations; access it through\n `AccessRequestService`. Its JSON field is `requestContext`, not reserved\n slug-scoping `context`.\n\n## Security boundaries\n\n- Generated REST/MCP operations on identity/RBAC models are list/get only.\n Route authentication does not authorize authority mutations, and these models\n are not tenant-scoped. Use permission-gated services or explicitly checked\n consumer handlers. CLI remains a local-operator surface. Preserve the\n registry assertions in `security-audit-1400.test.ts`.\n- Resource guards take the resource tenant, not the session tenant. Omit a\n session membership when targeting a different tenant; mismatches fail closed.\n `loadSessionContext().tenantAuthorization` must be checked by required-tenant\n consumers: null membership can represent inherited authority.\n- Sessions use secure UUIDs; TTL is seconds (default seven days). Access marks\n expired sessions EXPIRED. Magic-link tokens are single use.\n- `Session.authMethod` is server-set at mint time and never read from the\n client; every mint site in this package sets it. A session with\n `parentSessionId` is valid only while its parent validates\n (`loadSessionContext` enforces this; there is no FK cascade by design), may\n not switch to a tenant other than the parent's, and is revoked with its\n parent by `destroySession`.\n- Credential sign-ins reserve through `LoginAttemptLimiter` BEFORE credential\n work and key the subject on the submitted identifier, never a resolved user,\n so unknown and wrong take the same path. Reservations are fail-closed: keep\n them on failure, release on success or abort, never skip the reserve.\n Limiter writes are raw SQL and bypass the change feed; the audit sink is the\n observability seam, and it must never throw into the sign-in path.\n- `DeviceCredentialService` accepts a person credential only from a\n first-class session whose `authMethod` is a device-enrollment method\n (`terminal` by default) and that the host's `assertEnrolledDevice` confirms.\n A layered or PIN session can never administer PINs regardless of\n permissions. PIN hashes carry a per-row salt and the configured pepper;\n treat an unset pepper as a production misconfiguration.\n- A person session carries the PERSON's authority (resolved from their own\n membership on every load), never the device account's. `Session.data` keys\n in `SESSION_DATA_KEYS` are server-set controls enforced by the model:\n `permissionCeiling` only ever intersects (malformed fails closed to none)\n and suppresses `superAdminBypass`/`systemContext`; `absoluteExpiresAt`\n bounds `extend()` and `isValid()`; `idleSeconds` overrides the resolving\n service's TTL policy. Never write them from client input. The ceiling is a\n sign-in snapshot; `singleOccupant` revokes other children only AFTER a\n successful mint. A `mustReset` sign-in mints with an empty ceiling and\n `setPin` ends that session; do not grant it authority another way.\n- A layered session whose tenant differs from its parent's never loads (null\n is allowed: narrower). Limiter rows carry `retain_until`; retention must\n not fall back to a process-wide horizon.\n- `Session.parentSessionId` is the parent's bearer: sensitive, never a\n `list()` filter (raw-SQL id reads, which also keep revocation sweeps free of\n caller list bounds), never serialized to clients. `users.pin.manage` reaches\n only people whose every active membership is in the actor's tenant (the PIN\n is global per person). A sign-in re-checks the verified\n credential generation AFTER the mint (`stillValid`); keep that ordering.\n Operation guards deny outside a session's ceiling; `loadPersonSession`\n re-checks device enrollment.\n- Tenant switching verifies active membership before writing and rotates the\n session ID for non-null targets, revoking the old session. Persist the returned\n `SwitchTenantResult.sessionId`; `switchSessionTenant()` updates the cookie and\n preserves its security settings. Failed switches mutate nothing; null clears\n do not rotate, and layered sessions never rotate (a replacement would escape\n the revocation sweeps they depend on). Layers do not nest. `SessionCollection.setSessionTenant()` is unguarded and must\n never receive an untrusted tenant ID.\n- OIDC provisioning is atomic and fail-closed. Preserve exact issuer/subject\n identifiers, claim-source email verification, unique global Person ownership,\n and transaction-bound reconciliation. Read the OIDC module and canonical\n scenario matrix before changing any provisioning path.\n\n## Entry points and validation\n\n`src/sveltekit/` owns `createSessionHandler`, `createSessionCookie`,\n`destroySessionCookie`, and `switchSessionTenant`. Use README integration examples\nrather than copying application setup into these instructions.\n\nFrom the repository root:\n\n```bash\npnpm --filter @happyvertical/smrt-users test\npnpm --filter @happyvertical/smrt-users typecheck\npnpm --filter @happyvertical/smrt-users test:postgres\n```\n\nStart with the relevant test file via `test -- src/__tests__/<file>.test.ts`.\nRun `test:postgres` for RLS, principal context, OIDC, or terminal-auth database\nchanges. `typecheck` includes Svelte accessibility checks; plain `tsc` is\ninsufficient. Follow root knowledge freshness checks before shipping.\n",
|
|
10594
11264
|
"moduleDocs": [
|
|
10595
11265
|
{
|
|
10596
11266
|
"path": "agents/permissions.md",
|
|
@@ -10615,7 +11285,7 @@
|
|
|
10615
11285
|
{
|
|
10616
11286
|
"path": "agents/retention.md",
|
|
10617
11287
|
"module": "retention",
|
|
10618
|
-
"content": "# smrt-users/credential retention\n\nModule semantics for `src/retention.ts` and the three `deleteExpired()` paths\nit drives. Package orientation, the permission model, and the security rules\nthat apply before editing anything live in [../AGENTS.md](../AGENTS.md) — read\nthat first.\n\n## Credential retention (#2375)\n\n`SessionCollection.deleteExpired()`,\n`UsersMagicLinkTokenCollection.deleteExpired()` and\n`UsersCliAuthRequestCollection.deleteExpired()` all existed, and all waited for\nan application to remember to call them. Expired credential rows are the worst\nkind of unbounded growth: worthless the moment they expire, and exactly the\nrows an attacker would like to still find in the table.\n\n`src/retention.ts` contributes the three to the framework retention sweep in\n`@happyvertical/smrt-core`, so `smrt db:prune` and a running jobs `TaskRunner`\nreap them.\n\n- **The entry point registers on import.** `src/index.ts` calls\n `registerUserRetentionTasks()`, so any process that loaded this package\n contributes the tasks — including `smrt db:prune`, which imports the package\n optionally for exactly that reason. Registering is not scheduling: nothing is\n deleted until something runs a sweep.\n- **Task names** are `users-sessions`, `users-magic-link-tokens`,\n `users-cli-auth-requests` — prefixed with the package's short name because
|
|
11288
|
+
"content": "# smrt-users/credential retention\n\nModule semantics for `src/retention.ts` and the three `deleteExpired()` paths\nit drives. Package orientation, the permission model, and the security rules\nthat apply before editing anything live in [../AGENTS.md](../AGENTS.md) — read\nthat first.\n\n## Credential retention (#2375)\n\n`SessionCollection.deleteExpired()`,\n`UsersMagicLinkTokenCollection.deleteExpired()` and\n`UsersCliAuthRequestCollection.deleteExpired()` all existed, and all waited for\nan application to remember to call them. Expired credential rows are the worst\nkind of unbounded growth: worthless the moment they expire, and exactly the\nrows an attacker would like to still find in the table.\n\n`src/retention.ts` contributes the three to the framework retention sweep in\n`@happyvertical/smrt-core`, so `smrt db:prune` and a running jobs `TaskRunner`\nreap them.\n\n- **The entry point registers on import.** `src/index.ts` calls\n `registerUserRetentionTasks()`, so any process that loaded this package\n contributes the tasks — including `smrt db:prune`, which imports the package\n optionally for exactly that reason. Registering is not scheduling: nothing is\n deleted until something runs a sweep.\n- **Task names** are `users-sessions`, `users-magic-link-tokens`,\n `users-cli-auth-requests`, `users-login-attempts`, `users-login-audit-events`\n — prefixed with the package's short name because the retention registry is\n one process-global namespace. Opt one out with\n `runRetentionSweep(db, { tasks: { 'users-sessions': false } })` or\n `smrt db:prune --skip users-sessions`; `unregisterUserRetentionTasks()`\n removes all of them.\n- **The credential tasks have no retention window to configure.** An expired\n credential has nothing worth retaining, so each deletes only already-expired\n rows. An application that keeps expired sessions for audit should opt the\n task out and archive them itself. The two #3273 tasks differ: limiter rows\n are pruned once past their own `retain_until` — written by the limiter from\n its configured window and streak-forgiveness horizon, so a custom-configured\n limiter is never swept early — and never while a lockout is live; audit\n events are pruned after\n `DEFAULT_LOGIN_AUDIT_RETENTION_DAYS` (90). A host that needs longer audit\n retention opts `users-login-audit-events` out and archives.\n- **All three are a single counted DELETE**, not a hydrate-and-delete loop.\n They now run unattended on a timer, and a per-row delete that throws part-way\n leaves the rest of the expired rows un-reaped — the #1400 reasoning that\n already applied to sessions, now applied to the other two. Counting first\n also gives a usable figure where `rowCount` is not populated, and is what\n makes `{ dryRun }` preview the same predicate rather than an estimate. The\n count and the delete are not one transaction, so the figure is approximate\n under concurrent writers.\n- **`expiresAt` is `@field({ indexed: true })`** on `Session`,\n `UsersMagicLinkToken` and `UsersCliAuthRequest`: the prune predicate scans\n that column on every pass.\n- **CLI bearer handoff is single-use.** An approved request becomes `consumed`\n and clears its `sessionId` when one poller wins the exchange. The CLI\n retention task deletes pending requests past their TTL, requests already\n marked `expired` by lazy expiry, and consumed history; it retains approved\n requests until exchange so a near-expiry approval cannot orphan its bearer\n session.\n"
|
|
10619
11289
|
}
|
|
10620
11290
|
]
|
|
10621
11291
|
}
|