@riffdb/better-auth 0.0.0-stage → 0.2.1

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.
Files changed (226) hide show
  1. package/DESIGN.md +273 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +27 -0
  4. package/README.md +323 -2
  5. package/dist/adapter.d.ts +34 -0
  6. package/dist/adapter.d.ts.map +1 -0
  7. package/dist/adapter.js +1600 -0
  8. package/dist/adapter.js.map +1 -0
  9. package/dist/generated/client.d.ts +2166 -0
  10. package/dist/generated/client.d.ts.map +1 -0
  11. package/dist/generated/client.js +2454 -0
  12. package/dist/generated/client.js.map +1 -0
  13. package/dist/index.d.ts +7 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +7 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/plugin-dispatch.d.ts +37 -0
  18. package/dist/plugin-dispatch.d.ts.map +1 -0
  19. package/dist/plugin-dispatch.js +293 -0
  20. package/dist/plugin-dispatch.js.map +1 -0
  21. package/dist/profile-contract.d.ts +63 -0
  22. package/dist/profile-contract.d.ts.map +1 -0
  23. package/dist/profile-contract.js +543 -0
  24. package/dist/profile-contract.js.map +1 -0
  25. package/dist/profile-plan.d.ts +69 -0
  26. package/dist/profile-plan.d.ts.map +1 -0
  27. package/dist/profile-plan.js +180 -0
  28. package/dist/profile-plan.js.map +1 -0
  29. package/dist/profile.d.ts +48 -0
  30. package/dist/profile.d.ts.map +1 -0
  31. package/dist/profile.js +132 -0
  32. package/dist/profile.js.map +1 -0
  33. package/dist/profiles/custom-fields/profile.d.ts +3 -0
  34. package/dist/profiles/custom-fields/profile.d.ts.map +1 -0
  35. package/dist/profiles/custom-fields/profile.js +475 -0
  36. package/dist/profiles/custom-fields/profile.js.map +1 -0
  37. package/dist/profiles/custom-fields/src/generated/client.d.ts +2710 -0
  38. package/dist/profiles/custom-fields/src/generated/client.d.ts.map +1 -0
  39. package/dist/profiles/custom-fields/src/generated/client.js +2663 -0
  40. package/dist/profiles/custom-fields/src/generated/client.js.map +1 -0
  41. package/dist/profiles/runtime/profile.d.ts +3 -0
  42. package/dist/profiles/runtime/profile.d.ts.map +1 -0
  43. package/dist/profiles/runtime/profile.js +1065 -0
  44. package/dist/profiles/runtime/profile.js.map +1 -0
  45. package/dist/profiles/runtime/src/generated/client.d.ts +4274 -0
  46. package/dist/profiles/runtime/src/generated/client.d.ts.map +1 -0
  47. package/dist/profiles/runtime/src/generated/client.js +4607 -0
  48. package/dist/profiles/runtime/src/generated/client.js.map +1 -0
  49. package/dist/runtime-materialize.d.ts +10 -0
  50. package/dist/runtime-materialize.d.ts.map +1 -0
  51. package/dist/runtime-materialize.js +344 -0
  52. package/dist/runtime-materialize.js.map +1 -0
  53. package/dist/runtime-profile.d.ts +34 -0
  54. package/dist/runtime-profile.d.ts.map +1 -0
  55. package/dist/runtime-profile.js +203 -0
  56. package/dist/runtime-profile.js.map +1 -0
  57. package/dist/testing.d.ts +11 -0
  58. package/dist/testing.d.ts.map +1 -0
  59. package/dist/testing.js +12 -0
  60. package/dist/testing.js.map +1 -0
  61. package/generated/go/client.go +2250 -0
  62. package/generated/mcp/tools.json +13922 -0
  63. package/generated/python/client.py +4454 -0
  64. package/generated/riffdb.application.exact.json +1 -0
  65. package/generated/riffdb.contract.bundle +0 -0
  66. package/generated/rust/client.rs +6524 -0
  67. package/package.json +83 -4
  68. package/profiles/custom-fields/generated/go/client.go +2578 -0
  69. package/profiles/custom-fields/generated/mcp/tools.json +15998 -0
  70. package/profiles/custom-fields/generated/python/client.py +5141 -0
  71. package/profiles/custom-fields/generated/riffdb.application.exact.json +1 -0
  72. package/profiles/custom-fields/generated/riffdb.contract.bundle +0 -0
  73. package/profiles/custom-fields/generated/rust/client.rs +7980 -0
  74. package/profiles/custom-fields/profile.ts +474 -0
  75. package/profiles/custom-fields/riffdb/contract.riff +568 -0
  76. package/profiles/custom-fields/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
  77. package/profiles/custom-fields/riffdb/queries/admin_users_contains_asc.riffq +24 -0
  78. package/profiles/custom-fields/riffdb/queries/admin_users_contains_desc.riffq +24 -0
  79. package/profiles/custom-fields/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
  80. package/profiles/custom-fields/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
  81. package/profiles/custom-fields/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
  82. package/profiles/custom-fields/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
  83. package/profiles/custom-fields/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
  84. package/profiles/custom-fields/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
  85. package/profiles/custom-fields/riffdb/queries/find_account_by_id.riffq +24 -0
  86. package/profiles/custom-fields/riffdb/queries/find_account_by_provider.riffq +26 -0
  87. package/profiles/custom-fields/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
  88. package/profiles/custom-fields/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
  89. package/profiles/custom-fields/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
  90. package/profiles/custom-fields/riffdb/queries/find_credential_account.riffq +25 -0
  91. package/profiles/custom-fields/riffdb/queries/find_expired_verification_ids.riffq +17 -0
  92. package/profiles/custom-fields/riffdb/queries/find_latest_verification.riffq +20 -0
  93. package/profiles/custom-fields/riffdb/queries/find_session_by_id.riffq +20 -0
  94. package/profiles/custom-fields/riffdb/queries/find_session_by_token.riffq +20 -0
  95. package/profiles/custom-fields/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
  96. package/profiles/custom-fields/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
  97. package/profiles/custom-fields/riffdb/queries/find_user_by_email.riffq +16 -0
  98. package/profiles/custom-fields/riffdb/queries/find_user_by_id.riffq +15 -0
  99. package/profiles/custom-fields/riffdb/queries/find_verification_by_id.riffq +19 -0
  100. package/profiles/custom-fields/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
  101. package/profiles/custom-fields/riffdb/queries/profile_account_with_user_by_provider.riffq +31 -0
  102. package/profiles/custom-fields/riffdb/queries/profile_session_with_user_by_id.riffq +14 -0
  103. package/profiles/custom-fields/riffdb/queries/profile_session_with_user_by_token.riffq +14 -0
  104. package/profiles/custom-fields/riffdb/queries/profile_sessions_with_users_by_token_set.riffq +25 -0
  105. package/profiles/custom-fields/riffdb/queries/profile_user_with_accounts_by_email.riffq +19 -0
  106. package/profiles/custom-fields/riffdb/queries/profile_user_with_accounts_by_id.riffq +19 -0
  107. package/profiles/custom-fields/riffdb.application.json +217 -0
  108. package/profiles/custom-fields/riffdb.application.lock.json +1 -0
  109. package/profiles/custom-fields/riffdb.toml +3 -0
  110. package/profiles/custom-fields/src/generated/client.ts +3096 -0
  111. package/profiles/organization-security/materialization.json +51 -0
  112. package/profiles/organization-security/riffdb/contract.riff +778 -0
  113. package/profiles/organization-security/riffdb/queries/find_account_by_id.riffq +18 -0
  114. package/profiles/organization-security/riffdb/queries/find_invitation_by_email.riffq +17 -0
  115. package/profiles/organization-security/riffdb/queries/find_invitation_by_id.riffq +18 -0
  116. package/profiles/organization-security/riffdb/queries/find_invitation_by_organization_id.riffq +17 -0
  117. package/profiles/organization-security/riffdb/queries/find_member_by_id.riffq +18 -0
  118. package/profiles/organization-security/riffdb/queries/find_member_by_user_id.riffq +17 -0
  119. package/profiles/organization-security/riffdb/queries/find_organization_by_id.riffq +16 -0
  120. package/profiles/organization-security/riffdb/queries/find_organization_by_slug.riffq +16 -0
  121. package/profiles/organization-security/riffdb/queries/find_session_by_id.riffq +18 -0
  122. package/profiles/organization-security/riffdb/queries/find_session_by_token.riffq +16 -0
  123. package/profiles/organization-security/riffdb/queries/find_team_by_id.riffq +18 -0
  124. package/profiles/organization-security/riffdb/queries/find_team_member_by_id.riffq +18 -0
  125. package/profiles/organization-security/riffdb/queries/find_team_member_by_membership_key.riffq +16 -0
  126. package/profiles/organization-security/riffdb/queries/find_team_member_by_team_id.riffq +17 -0
  127. package/profiles/organization-security/riffdb/queries/find_two_factor_by_id.riffq +18 -0
  128. package/profiles/organization-security/riffdb/queries/find_two_factor_by_secret.riffq +17 -0
  129. package/profiles/organization-security/riffdb/queries/find_user_by_email.riffq +16 -0
  130. package/profiles/organization-security/riffdb/queries/find_user_by_id.riffq +16 -0
  131. package/profiles/organization-security/riffdb/queries/find_verification_by_id.riffq +16 -0
  132. package/profiles/organization-security/riffdb/queries/find_verification_by_identifier.riffq +17 -0
  133. package/profiles/organization-security/riffdb.application.json +172 -0
  134. package/profiles/organization-security/riffdb.toml +7 -0
  135. package/profiles/organization-security.profile.json +980 -0
  136. package/profiles/runtime/generated/go/client.go +4511 -0
  137. package/profiles/runtime/generated/mcp/tools.json +30004 -0
  138. package/profiles/runtime/generated/python/client.py +9337 -0
  139. package/profiles/runtime/generated/riffdb.application.exact.json +1 -0
  140. package/profiles/runtime/generated/riffdb.contract.bundle +0 -0
  141. package/profiles/runtime/generated/rust/client.rs +13297 -0
  142. package/profiles/runtime/profile.ts +1064 -0
  143. package/profiles/runtime/riffdb/contract.riff +1053 -0
  144. package/profiles/runtime/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
  145. package/profiles/runtime/riffdb/queries/admin_users_contains_asc.riffq +24 -0
  146. package/profiles/runtime/riffdb/queries/admin_users_contains_desc.riffq +24 -0
  147. package/profiles/runtime/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
  148. package/profiles/runtime/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
  149. package/profiles/runtime/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
  150. package/profiles/runtime/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
  151. package/profiles/runtime/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
  152. package/profiles/runtime/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
  153. package/profiles/runtime/riffdb/queries/find_account_by_id.riffq +24 -0
  154. package/profiles/runtime/riffdb/queries/find_account_by_provider.riffq +26 -0
  155. package/profiles/runtime/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
  156. package/profiles/runtime/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
  157. package/profiles/runtime/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
  158. package/profiles/runtime/riffdb/queries/find_credential_account.riffq +25 -0
  159. package/profiles/runtime/riffdb/queries/find_expired_verification_ids.riffq +17 -0
  160. package/profiles/runtime/riffdb/queries/find_latest_verification.riffq +20 -0
  161. package/profiles/runtime/riffdb/queries/find_session_by_id.riffq +20 -0
  162. package/profiles/runtime/riffdb/queries/find_session_by_token.riffq +20 -0
  163. package/profiles/runtime/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
  164. package/profiles/runtime/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
  165. package/profiles/runtime/riffdb/queries/find_user_by_email.riffq +16 -0
  166. package/profiles/runtime/riffdb/queries/find_user_by_id.riffq +15 -0
  167. package/profiles/runtime/riffdb/queries/find_verification_by_id.riffq +19 -0
  168. package/profiles/runtime/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
  169. package/profiles/runtime/riffdb/queries/profile_account_with_user_by_provider.riffq +31 -0
  170. package/profiles/runtime/riffdb/queries/profile_invitation_by_email.riffq +17 -0
  171. package/profiles/runtime/riffdb/queries/profile_invitation_by_id.riffq +17 -0
  172. package/profiles/runtime/riffdb/queries/profile_invitation_by_organization_email_status.riffq +19 -0
  173. package/profiles/runtime/riffdb/queries/profile_invitation_by_organization_id.riffq +17 -0
  174. package/profiles/runtime/riffdb/queries/profile_invitation_by_organization_status.riffq +18 -0
  175. package/profiles/runtime/riffdb/queries/profile_member_by_id.riffq +27 -0
  176. package/profiles/runtime/riffdb/queries/profile_member_by_organization.riffq +20 -0
  177. package/profiles/runtime/riffdb/queries/profile_member_by_organization_created_at_asc.riffq +20 -0
  178. package/profiles/runtime/riffdb/queries/profile_member_by_organization_created_at_desc.riffq +20 -0
  179. package/profiles/runtime/riffdb/queries/profile_member_by_organization_role_asc.riffq +20 -0
  180. package/profiles/runtime/riffdb/queries/profile_member_by_organization_role_desc.riffq +20 -0
  181. package/profiles/runtime/riffdb/queries/profile_member_by_organization_user.riffq +28 -0
  182. package/profiles/runtime/riffdb/queries/profile_member_by_user.riffq +27 -0
  183. package/profiles/runtime/riffdb/queries/profile_organization_by_id.riffq +27 -0
  184. package/profiles/runtime/riffdb/queries/profile_organization_by_slug.riffq +27 -0
  185. package/profiles/runtime/riffdb/queries/profile_session_with_user_by_id.riffq +14 -0
  186. package/profiles/runtime/riffdb/queries/profile_session_with_user_by_token.riffq +14 -0
  187. package/profiles/runtime/riffdb/queries/profile_sessions_with_users_by_token_set.riffq +25 -0
  188. package/profiles/runtime/riffdb/queries/profile_two_factor_by_id.riffq +17 -0
  189. package/profiles/runtime/riffdb/queries/profile_two_factor_by_user.riffq +17 -0
  190. package/profiles/runtime/riffdb/queries/profile_user_with_accounts_by_email.riffq +19 -0
  191. package/profiles/runtime/riffdb/queries/profile_user_with_accounts_by_id.riffq +19 -0
  192. package/profiles/runtime/riffdb/queries/profile_users_by_id_set.riffq +8 -0
  193. package/profiles/runtime/riffdb.application.json +324 -0
  194. package/profiles/runtime/riffdb.application.lock.json +1 -0
  195. package/profiles/runtime/riffdb.toml +3 -0
  196. package/profiles/runtime/src/generated/client.ts +5186 -0
  197. package/riffdb/contract.riff +547 -0
  198. package/riffdb/queries/admin_users_all_email_asc.riffq +24 -0
  199. package/riffdb/queries/admin_users_contains_asc.riffq +24 -0
  200. package/riffdb/queries/admin_users_contains_desc.riffq +24 -0
  201. package/riffdb/queries/admin_users_email_contains_created_desc.riffq +24 -0
  202. package/riffdb/queries/admin_users_email_contains_image_asc.riffq +24 -0
  203. package/riffdb/queries/admin_users_ends_with_asc.riffq +24 -0
  204. package/riffdb/queries/admin_users_ends_with_desc.riffq +24 -0
  205. package/riffdb/queries/admin_users_starts_with_asc.riffq +24 -0
  206. package/riffdb/queries/admin_users_starts_with_desc.riffq +24 -0
  207. package/riffdb/queries/find_account_by_id.riffq +24 -0
  208. package/riffdb/queries/find_account_by_provider.riffq +26 -0
  209. package/riffdb/queries/find_accounts_by_user_id.riffq +25 -0
  210. package/riffdb/queries/find_accounts_by_user_provider.riffq +27 -0
  211. package/riffdb/queries/find_active_sessions_by_user_id.riffq +23 -0
  212. package/riffdb/queries/find_credential_account.riffq +25 -0
  213. package/riffdb/queries/find_expired_verification_ids.riffq +17 -0
  214. package/riffdb/queries/find_latest_verification.riffq +20 -0
  215. package/riffdb/queries/find_session_by_id.riffq +20 -0
  216. package/riffdb/queries/find_session_by_token.riffq +20 -0
  217. package/riffdb/queries/find_sessions_by_token_set.riffq +20 -0
  218. package/riffdb/queries/find_sessions_by_user_id.riffq +21 -0
  219. package/riffdb/queries/find_user_by_email.riffq +16 -0
  220. package/riffdb/queries/find_user_by_id.riffq +15 -0
  221. package/riffdb/queries/find_verification_by_id.riffq +19 -0
  222. package/riffdb/queries/find_verifications_by_identifier.riffq +21 -0
  223. package/riffdb.application.json +187 -0
  224. package/riffdb.application.lock.json +1 -0
  225. package/scripts/real-riffdb-runner.mjs +333 -0
  226. package/src/generated/client.ts +2746 -0
@@ -0,0 +1,1053 @@
1
+ contract BetterAuthRuntime version 1 {
2
+
3
+ entity User {
4
+ key (organization_id: uuid, user_id: uuid)
5
+ field name: string<256>
6
+ field email: string<320>
7
+ field email_verified: bool
8
+ field image: optional<string<2048>>
9
+ field created_at: timestamp
10
+ field updated_at: timestamp
11
+ field revision: u64
12
+ field date_field: optional<timestamp>
13
+ field locale: optional<string<2048>>
14
+ field two_factor_enabled: optional<bool>
15
+ index by_id (organization_id, user_id)
16
+ unique user_email (organization_id, email)
17
+ index by_email (organization_id, email, user_id) cover(name, email_verified, image, created_at, updated_at, revision, date_field, locale, two_factor_enabled)
18
+ index search_email (organization_id, email, user_id) text_key(email, binary_utf8_v1) cover(name, email_verified, image, created_at, updated_at, revision, date_field, locale, two_factor_enabled)
19
+ index by_created_at (organization_id, created_at, user_id) cover(name, email, email_verified, image, updated_at, revision, date_field, locale, two_factor_enabled)
20
+ index by_image (organization_id, image, user_id) presence(image) cover(name, email, email_verified, created_at, updated_at, revision, date_field, locale, two_factor_enabled)
21
+
22
+ }
23
+
24
+ entity Account {
25
+ key (organization_id: uuid, user_id: uuid, id: uuid)
26
+ field account_id: string<256>
27
+ field provider_id: string<64>
28
+ field secret access_token: optional<string<4096>>
29
+ field secret refresh_token: optional<string<4096>>
30
+ field access_token_expires_at: optional<timestamp>
31
+ field refresh_token_expires_at: optional<timestamp>
32
+ field scope: optional<string<2048>>
33
+ field secret id_token: optional<string<8192>>
34
+ field secret password: optional<string<1024>>
35
+ field created_at: timestamp
36
+ field updated_at: timestamp
37
+ field revision: u64
38
+ unique account_row_id (organization_id, id)
39
+ unique provider_identity (organization_id, provider_id, account_id)
40
+ index by_id (organization_id, id, user_id)
41
+ index by_provider (organization_id, provider_id, account_id, user_id, id)
42
+ index by_user (organization_id, user_id, id)
43
+ index by_user_provider (organization_id, user_id, provider_id, id)
44
+ reference account_user (organization_id, user_id) -> User(organization_id, user_id)
45
+ delete_policy no_inbound
46
+ }
47
+
48
+ entity Session {
49
+ key (organization_id: uuid, user_id: uuid, id: uuid)
50
+ field secret token: string<512>
51
+ field expires_at: timestamp
52
+ field ip_address: optional<string<128>>
53
+ field user_agent: optional<string<2048>>
54
+ field created_at: timestamp
55
+ field updated_at: timestamp
56
+ field revision: u64
57
+ field active_organization_id: optional<string<2048>>
58
+ unique session_token (organization_id, token)
59
+ unique session_id (organization_id, id)
60
+ index by_token (organization_id, token, user_id, id)
61
+ index by_id (organization_id, id, user_id)
62
+ index by_user (organization_id, user_id, id)
63
+ index by_user_expiry (organization_id, user_id, expires_at, id)
64
+ reference session_user (organization_id, user_id) -> User(organization_id, user_id)
65
+ delete_policy no_inbound
66
+ }
67
+
68
+ entity Verification {
69
+ key (organization_id: uuid, verification_id: uuid)
70
+ field identifier: string<1024>
71
+ field secret value: string<4096>
72
+ field expires_at: timestamp
73
+ field created_at: timestamp
74
+ field updated_at: timestamp
75
+ field revision: u64
76
+ index by_identifier_created (organization_id, identifier, created_at, verification_id)
77
+ index by_expiry (organization_id, expires_at, verification_id)
78
+ delete_policy no_inbound
79
+ }
80
+
81
+ entity AccountPasswordUpdate {
82
+ key (organization_id: uuid, user_id: uuid, account_id: uuid)
83
+ field provider_id: string<64>
84
+ field secret password: optional<string<1024>>
85
+ field updated_at: timestamp
86
+ field expected_revision: u64
87
+ }
88
+
89
+ entity Tenant {
90
+ key (organization_id: uuid)
91
+ delete_policy no_inbound
92
+ }
93
+
94
+ entity Invitation {
95
+ key (organization_id: uuid, invitation_id: uuid)
96
+ field created_at: timestamp
97
+ field email: string<320>
98
+ field expires_at: timestamp
99
+ field inviter_id: uuid
100
+ field org_id: uuid
101
+ field role: optional<string<256>>
102
+ field status: string<32>
103
+ field revision: u64
104
+ index by_email (organization_id, email, invitation_id) text_key(email, binary_utf8_v1)
105
+ index by_inviter_id (organization_id, inviter_id, invitation_id)
106
+ index by_org_id (organization_id, org_id, invitation_id)
107
+ index by_org_status (organization_id, org_id, status, invitation_id)
108
+ index by_org_email_status (organization_id, org_id, email, status, invitation_id)
109
+ reference invitation_inviter_id (organization_id, inviter_id) -> User(organization_id, user_id)
110
+ reference invitation_organization_id (organization_id, org_id) -> Organization(organization_id, org_id)
111
+ delete_policy no_inbound
112
+ }
113
+
114
+ entity Member {
115
+ key (organization_id: uuid, member_id: uuid)
116
+ field created_at: timestamp
117
+ field org_id: uuid
118
+ field role: string<256>
119
+ field user_id: uuid
120
+ field revision: u64
121
+ unique membership (organization_id, org_id, user_id)
122
+ index by_org_id (organization_id, org_id, member_id)
123
+ index by_user_id (organization_id, user_id, member_id)
124
+ index by_role (organization_id, role, member_id) text_key(role, binary_utf8_v1)
125
+ index by_created_at (organization_id, created_at, member_id)
126
+ index by_org_user (organization_id, org_id, user_id, member_id)
127
+ index by_org_role (organization_id, org_id, role, member_id) text_key(role, binary_utf8_v1)
128
+ index by_org_created_at (organization_id, org_id, created_at, member_id)
129
+ reference member_organization_id (organization_id, org_id) -> Organization(organization_id, org_id)
130
+ reference member_user (organization_id, user_id) -> User(organization_id, user_id)
131
+ delete_policy no_inbound
132
+ }
133
+
134
+ entity Organization {
135
+ key (organization_id: uuid, org_id: uuid)
136
+ field created_at: timestamp
137
+ field logo: optional<string<2048>>
138
+ field metadata: optional<string<2048>>
139
+ field name: string<256>
140
+ field slug: string<256>
141
+ field member_count: i64
142
+ field invitation_count: i64
143
+ field revision: u64
144
+ unique unique_slug (organization_id, slug)
145
+ index by_slug (organization_id, slug, org_id) text_key(slug, binary_utf8_v1)
146
+ delete_policy cascade {
147
+ relationship Member.member_organization_id using Member.by_org_id maximum 100
148
+ relationship Invitation.invitation_organization_id using Invitation.by_org_id maximum 100
149
+ }
150
+ }
151
+
152
+ entity TwoFactor {
153
+ key (organization_id: uuid, two_factor_id: uuid)
154
+ field secret backup_codes: string<2048>
155
+ field secret failed_verification_count: i64
156
+ field secret locked_until: optional<timestamp>
157
+ field secret secret: string<2048>
158
+ field user_id: uuid
159
+ field verified: bool
160
+ field locked_until_millis: i64
161
+ field revision: u64
162
+ unique two_factor_user (organization_id, user_id)
163
+ index by_user_id (organization_id, user_id, two_factor_id)
164
+ reference two_factor_user (organization_id, user_id) -> User(organization_id, user_id)
165
+ delete_policy no_inbound
166
+ }
167
+
168
+ aggregate TenantData {
169
+ root Tenant
170
+ child User
171
+ child Account
172
+ child Session
173
+ child Verification
174
+ child AccountPasswordUpdate
175
+ child Invitation
176
+ child Member
177
+ child Organization
178
+ child TwoFactor
179
+ partition_by organization_id
180
+ conflict_key (organization_id)
181
+ }
182
+
183
+ command CreateUser {
184
+ input request_id: uuid
185
+ input organization_id: uuid
186
+ input id: uuid
187
+ input name: string<256>
188
+ input email: string<320>
189
+ input email_verified: bool
190
+ input image: optional<string<2048>>
191
+ input created_at: timestamp
192
+ input updated_at: timestamp
193
+ input date_field: optional<timestamp>
194
+ input locale: optional<string<2048>>
195
+ input two_factor_enabled: optional<bool>
196
+ idempotency_key request_id
197
+ create User(organization_id, id) as user else UserAlreadyExists {}
198
+ set user.name = name
199
+ set user.email = email
200
+ set user.email_verified = email_verified
201
+ set user.image = image
202
+ set user.created_at = created_at
203
+ set user.updated_at = updated_at
204
+ set user.date_field = date_field
205
+ set user.locale = locale
206
+ set user.two_factor_enabled = two_factor_enabled
207
+ set user.revision = 1
208
+ return UserCreated {}
209
+ }
210
+
211
+ command CreateAccount {
212
+ input request_id: uuid
213
+ input organization_id: uuid
214
+ input user_id: uuid
215
+ input id: uuid
216
+ input account_id: string<256>
217
+ input provider_id: string<64>
218
+ input access_token: optional<string<4096>>
219
+ input refresh_token: optional<string<4096>>
220
+ input access_token_expires_at: optional<timestamp>
221
+ input refresh_token_expires_at: optional<timestamp>
222
+ input scope: optional<string<2048>>
223
+ input id_token: optional<string<8192>>
224
+ input password: optional<string<1024>>
225
+ input created_at: timestamp
226
+ input updated_at: timestamp
227
+ idempotency_key request_id
228
+ read User(organization_id, user_id) as owner else AccountUserMissing {}
229
+ create Account(organization_id, user_id, id) as account else AccountAlreadyExists {}
230
+ set account.account_id = account_id
231
+ set account.provider_id = provider_id
232
+ set account.access_token = access_token
233
+ set account.refresh_token = refresh_token
234
+ set account.access_token_expires_at = access_token_expires_at
235
+ set account.refresh_token_expires_at = refresh_token_expires_at
236
+ set account.scope = scope
237
+ set account.id_token = id_token
238
+ set account.password = password
239
+ set account.created_at = created_at
240
+ set account.updated_at = updated_at
241
+ set account.revision = 1
242
+ return AccountCreated {}
243
+ }
244
+
245
+ command CreateSession {
246
+ input request_id: uuid
247
+ input organization_id: uuid
248
+ input user_id: uuid
249
+ input id: uuid
250
+ input token: string<512>
251
+ input expires_at: timestamp
252
+ input ip_address: optional<string<128>>
253
+ input user_agent: optional<string<2048>>
254
+ input created_at: timestamp
255
+ input updated_at: timestamp
256
+ input active_organization_id: optional<string<2048>>
257
+ idempotency_key request_id
258
+ read User(organization_id, user_id) as owner else SessionUserMissing {}
259
+ create Session(organization_id, user_id, id) as session else SessionAlreadyExists {}
260
+ set session.token = token
261
+ set session.expires_at = expires_at
262
+ set session.ip_address = ip_address
263
+ set session.user_agent = user_agent
264
+ set session.created_at = created_at
265
+ set session.updated_at = updated_at
266
+ set session.active_organization_id = active_organization_id
267
+ set session.revision = 1
268
+ return SessionCreated {}
269
+ }
270
+
271
+ command CreateVerification {
272
+ input request_id: uuid
273
+ input organization_id: uuid
274
+ input id: uuid
275
+ input identifier: string<1024>
276
+ input value: string<4096>
277
+ input expires_at: timestamp
278
+ input created_at: timestamp
279
+ input updated_at: timestamp
280
+ idempotency_key request_id
281
+ create Verification(organization_id, id) as verification else VerificationAlreadyExists {}
282
+ set verification.identifier = identifier
283
+ set verification.value = value
284
+ set verification.expires_at = expires_at
285
+ set verification.created_at = created_at
286
+ set verification.updated_at = updated_at
287
+ set verification.revision = 1
288
+ return VerificationCreated {}
289
+ }
290
+
291
+ command CreateSignupGraph {
292
+ input request_id: uuid
293
+ input organization_id: uuid
294
+ input user_id: uuid
295
+ input user_name: string<256>
296
+ input user_email: string<320>
297
+ input user_email_verified: bool
298
+ input user_image: optional<string<2048>>
299
+ input user_created_at: timestamp
300
+ input user_updated_at: timestamp
301
+ input account_id: uuid
302
+ input external_account_id: string<256>
303
+ input provider_id: string<64>
304
+ input account_password: optional<string<1024>>
305
+ input account_created_at: timestamp
306
+ input account_updated_at: timestamp
307
+ input session_id: uuid
308
+ input session_token: string<512>
309
+ input session_expires_at: timestamp
310
+ input session_ip_address: optional<string<128>>
311
+ input session_user_agent: optional<string<2048>>
312
+ input session_created_at: timestamp
313
+ input session_updated_at: timestamp
314
+ input user_date_field: optional<timestamp>
315
+ input user_locale: optional<string<2048>>
316
+ input user_two_factor_enabled: optional<bool>
317
+ input session_active_organization_id: optional<string<2048>>
318
+ idempotency_key request_id
319
+ create User(organization_id, user_id) as user else SignupUserExists {}
320
+ create Account(organization_id, user_id, account_id) as account else SignupAccountExists {}
321
+ create Session(organization_id, user_id, session_id) as session else SignupSessionExists {}
322
+ set user.name = user_name
323
+ set user.email = user_email
324
+ set user.email_verified = user_email_verified
325
+ set user.image = user_image
326
+ set user.created_at = user_created_at
327
+ set user.updated_at = user_updated_at
328
+ set user.date_field = user_date_field
329
+ set user.locale = user_locale
330
+ set user.two_factor_enabled = user_two_factor_enabled
331
+ set user.revision = 1
332
+ set account.account_id = external_account_id
333
+ set account.provider_id = provider_id
334
+ set account.access_token = null
335
+ set account.refresh_token = null
336
+ set account.access_token_expires_at = null
337
+ set account.refresh_token_expires_at = null
338
+ set account.scope = null
339
+ set account.id_token = null
340
+ set account.password = account_password
341
+ set account.created_at = account_created_at
342
+ set account.updated_at = account_updated_at
343
+ set account.revision = 1
344
+ set session.token = session_token
345
+ set session.expires_at = session_expires_at
346
+ set session.ip_address = session_ip_address
347
+ set session.user_agent = session_user_agent
348
+ set session.created_at = session_created_at
349
+ set session.updated_at = session_updated_at
350
+ set session.active_organization_id = session_active_organization_id
351
+ set session.revision = 1
352
+ return SignupGraphCreated {}
353
+ }
354
+
355
+ command CreateOAuthUserGraph {
356
+ input request_id: uuid
357
+ input organization_id: uuid
358
+ input user_id: uuid
359
+ input user_name: string<256>
360
+ input user_email: string<320>
361
+ input user_email_verified: bool
362
+ input user_image: optional<string<2048>>
363
+ input user_created_at: timestamp
364
+ input user_updated_at: timestamp
365
+ input account_id: uuid
366
+ input external_account_id: string<256>
367
+ input provider_id: string<64>
368
+ input access_token: optional<string<4096>>
369
+ input refresh_token: optional<string<4096>>
370
+ input access_token_expires_at: optional<timestamp>
371
+ input refresh_token_expires_at: optional<timestamp>
372
+ input scope: optional<string<2048>>
373
+ input id_token: optional<string<8192>>
374
+ input password: optional<string<1024>>
375
+ input account_created_at: timestamp
376
+ input account_updated_at: timestamp
377
+ input user_date_field: optional<timestamp>
378
+ input user_locale: optional<string<2048>>
379
+ input user_two_factor_enabled: optional<bool>
380
+ idempotency_key request_id
381
+ create User(organization_id, user_id) as user else OAuthUserExists {}
382
+ create Account(organization_id, user_id, account_id) as account else OAuthAccountExists {}
383
+ set user.name = user_name
384
+ set user.email = user_email
385
+ set user.email_verified = user_email_verified
386
+ set user.image = user_image
387
+ set user.created_at = user_created_at
388
+ set user.updated_at = user_updated_at
389
+ set user.date_field = user_date_field
390
+ set user.locale = user_locale
391
+ set user.two_factor_enabled = user_two_factor_enabled
392
+ set user.revision = 1
393
+ set account.account_id = external_account_id
394
+ set account.provider_id = provider_id
395
+ set account.access_token = access_token
396
+ set account.refresh_token = refresh_token
397
+ set account.access_token_expires_at = access_token_expires_at
398
+ set account.refresh_token_expires_at = refresh_token_expires_at
399
+ set account.scope = scope
400
+ set account.id_token = id_token
401
+ set account.password = password
402
+ set account.created_at = account_created_at
403
+ set account.updated_at = account_updated_at
404
+ set account.revision = 1
405
+ return OAuthUserGraphCreated {}
406
+ }
407
+
408
+ command UpdateUser {
409
+ input request_id: uuid
410
+ input organization_id: uuid
411
+ input user_id: uuid
412
+ input expected_revision: u64
413
+ input name: string<256>
414
+ input email: string<320>
415
+ input email_verified: bool
416
+ input image: optional<string<2048>>
417
+ input updated_at: timestamp
418
+ input date_field: optional<timestamp>
419
+ input locale: optional<string<2048>>
420
+ input two_factor_enabled: optional<bool>
421
+ idempotency_key request_id
422
+ mutate User(organization_id, user_id) as user else UserUpdateMissing {}
423
+ require current_revision: user.revision == expected_revision else UserUpdateStale {}
424
+ set user.name = name checked_by current_revision
425
+ set user.email = email checked_by current_revision
426
+ set user.email_verified = email_verified checked_by current_revision
427
+ set user.image = image checked_by current_revision
428
+ set user.updated_at = updated_at checked_by current_revision
429
+ set user.date_field = date_field checked_by current_revision
430
+ set user.locale = locale checked_by current_revision
431
+ set user.two_factor_enabled = two_factor_enabled checked_by current_revision
432
+ set user.revision = user.revision + 1
433
+ return UserUpdated {}
434
+ }
435
+
436
+ command UpdateSession {
437
+ input request_id: uuid
438
+ input organization_id: uuid
439
+ input user_id: uuid
440
+ input session_id: uuid
441
+ input expected_revision: u64
442
+ input expires_at: timestamp
443
+ input ip_address: optional<string<128>>
444
+ input user_agent: optional<string<2048>>
445
+ input updated_at: timestamp
446
+ input active_organization_id: optional<string<2048>>
447
+ idempotency_key request_id
448
+ mutate Session(organization_id, user_id, session_id) as session else SessionUpdateMissing {}
449
+ require current_revision: session.revision == expected_revision else SessionUpdateStale {}
450
+ set session.expires_at = expires_at checked_by current_revision
451
+ set session.ip_address = ip_address checked_by current_revision
452
+ set session.user_agent = user_agent checked_by current_revision
453
+ set session.updated_at = updated_at checked_by current_revision
454
+ set session.active_organization_id = active_organization_id checked_by current_revision
455
+ set session.revision = session.revision + 1
456
+ return SessionUpdated {}
457
+ }
458
+
459
+ command UpdateAccount {
460
+ input request_id: uuid
461
+ input organization_id: uuid
462
+ input user_id: uuid
463
+ input account_id: uuid
464
+ input expected_revision: u64
465
+ input external_account_id: string<256>
466
+ input provider_id: string<64>
467
+ input access_token: optional<string<4096>>
468
+ input refresh_token: optional<string<4096>>
469
+ input access_token_expires_at: optional<timestamp>
470
+ input refresh_token_expires_at: optional<timestamp>
471
+ input scope: optional<string<2048>>
472
+ input id_token: optional<string<8192>>
473
+ input password: optional<string<1024>>
474
+ input updated_at: timestamp
475
+ idempotency_key request_id
476
+ mutate Account(organization_id, user_id, account_id) as account else AccountUpdateMissing {}
477
+ require current_revision: account.revision == expected_revision else AccountUpdateStale {}
478
+ set account.account_id = external_account_id checked_by current_revision
479
+ set account.provider_id = provider_id checked_by current_revision
480
+ set account.access_token = access_token checked_by current_revision
481
+ set account.refresh_token = refresh_token checked_by current_revision
482
+ set account.access_token_expires_at = access_token_expires_at checked_by current_revision
483
+ set account.refresh_token_expires_at = refresh_token_expires_at checked_by current_revision
484
+ set account.scope = scope checked_by current_revision
485
+ set account.id_token = id_token checked_by current_revision
486
+ set account.password = password checked_by current_revision
487
+ set account.updated_at = updated_at checked_by current_revision
488
+ set account.revision = account.revision + 1
489
+ return AccountUpdated {}
490
+ }
491
+
492
+ command UpdateVerification {
493
+ input request_id: uuid
494
+ input organization_id: uuid
495
+ input verification_id: uuid
496
+ input expected_revision: u64
497
+ input value: string<4096>
498
+ input expires_at: timestamp
499
+ input updated_at: timestamp
500
+ idempotency_key request_id
501
+ mutate Verification(organization_id, verification_id) as verification else VerificationUpdateMissing {}
502
+ require current_revision: verification.revision == expected_revision else VerificationUpdateStale {}
503
+ set verification.value = value checked_by current_revision
504
+ set verification.expires_at = expires_at checked_by current_revision
505
+ set verification.updated_at = updated_at checked_by current_revision
506
+ set verification.revision = verification.revision + 1
507
+ return VerificationUpdated {}
508
+ }
509
+
510
+ bulk command DeleteSession {
511
+ input request_id: uuid
512
+ input organization_id: uuid
513
+ input user_id: uuid
514
+ input session_ids: list<uuid, 1..32>
515
+ idempotency_key request_id
516
+ for session_id in session_ids {
517
+ delete Session(organization_id, user_id, session_id) as session else SessionMissing {}
518
+ }
519
+ return SessionDeleted {}
520
+ }
521
+
522
+ bulk command DeleteAccount {
523
+ input request_id: uuid
524
+ input organization_id: uuid
525
+ input user_id: uuid
526
+ input account_ids: list<uuid, 1..32>
527
+ idempotency_key request_id
528
+ for account_id in account_ids {
529
+ delete Account(organization_id, user_id, account_id) as account else AccountMissing {}
530
+ }
531
+ return AccountDeleted {}
532
+ }
533
+
534
+ bulk command DeleteVerification {
535
+ input request_id: uuid
536
+ input organization_id: uuid
537
+ input verification_ids: list<uuid, 1..32>
538
+ idempotency_key request_id
539
+ for verification_id in verification_ids {
540
+ delete Verification(organization_id, verification_id) as verification else VerificationMissing {}
541
+ }
542
+ return VerificationDeleted {}
543
+ }
544
+
545
+ bulk command ConsumeVerificationSet {
546
+ input request_id: uuid
547
+ input organization_id: uuid
548
+ input verification_ids: list<uuid, 1..32>
549
+ idempotency_key request_id
550
+ for verification_id in verification_ids {
551
+ delete Verification(organization_id, verification_id) as verification else VerificationConsumeMissing {}
552
+ }
553
+ return VerificationSetConsumed {}
554
+ }
555
+
556
+ command ConsumeVerification {
557
+ input request_id: uuid
558
+ input organization_id: uuid
559
+ input verification_id: uuid
560
+ idempotency_key request_id
561
+ delete Verification(organization_id, verification_id) as verification else VerificationConsumeMissing {}
562
+ return VerificationConsumed {
563
+ verification_id: verification.verification_id,
564
+ identifier: verification.identifier,
565
+ value: verification.value reveals verification.value,
566
+ expires_at: verification.expires_at,
567
+ created_at: verification.created_at,
568
+ updated_at: verification.updated_at,
569
+ revision: verification.revision
570
+ }
571
+ }
572
+
573
+ bulk command UpdateAccountPasswords {
574
+ input request_id: uuid
575
+ input organization_id: uuid
576
+ input user_id: uuid
577
+ input updates: list<AccountPasswordUpdate, 1..8>
578
+ idempotency_key request_id
579
+ for update in updates {
580
+ mutate Account(organization_id, user_id, update.account_id) as account else PasswordAccountMissing {}
581
+ require provider_matches: account.provider_id == update.provider_id else PasswordProviderMismatch {}
582
+ require current_revision: account.revision == update.expected_revision else PasswordAccountStale {}
583
+ set account.password = update.password checked_by current_revision
584
+ set account.updated_at = update.updated_at checked_by current_revision
585
+ set account.revision = account.revision + 1
586
+ }
587
+ return AccountPasswordsUpdated {}
588
+ }
589
+
590
+ command ConsumeVerificationSnapshot {
591
+ input request_id: uuid
592
+ input organization_id: uuid
593
+ input verification_id: uuid
594
+ input expected_revision: u64
595
+ idempotency_key request_id
596
+ delete Verification(organization_id, verification_id) as verification else VerificationConsumeMissing {}
597
+ require snapshot: verification.revision == expected_revision else VerificationConsumeStale {}
598
+ return VerificationConsumed {}
599
+ }
600
+
601
+ bulk command ResetCredentialPassword {
602
+ input request_id: uuid
603
+ input organization_id: uuid
604
+ input verification_ids: list<uuid, 1..1>
605
+ input verification_revision: u64
606
+ input user_id: uuid
607
+ input external_account_id: string<256>
608
+ input account_id: uuid
609
+ input account_revision: u64
610
+ input password: string<1024>
611
+ input updated_at: timestamp
612
+ idempotency_key request_id
613
+ mutate Account(organization_id, user_id, account_id) as account else PasswordAccountMissing {}
614
+ for verification_id in verification_ids {
615
+ delete Verification(organization_id, verification_id) as verification else VerificationConsumeMissing {}
616
+ require verification_snapshot: verification.revision == verification_revision else VerificationConsumeStale {}
617
+ }
618
+ require credential_provider: account.provider_id == "credential" else PasswordProviderMismatch {}
619
+ require credential_identity: account.account_id == external_account_id else PasswordProviderMismatch {}
620
+ require account_snapshot: account.revision == account_revision else PasswordAccountStale {}
621
+ set account.password = password checked_by account_snapshot
622
+ set account.updated_at = updated_at checked_by account_snapshot
623
+ set account.revision = account.revision + 1
624
+ return CredentialPasswordReset {}
625
+ }
626
+
627
+ command UpdateCredentialPassword {
628
+ input request_id: uuid
629
+ input organization_id: uuid
630
+ input user_id: uuid
631
+ input account_id: uuid
632
+ input external_account_id: string<256>
633
+ input expected_revision: u64
634
+ input password: string<1024>
635
+ input updated_at: timestamp
636
+ idempotency_key request_id
637
+ mutate Account(organization_id, user_id, account_id) as account else PasswordAccountMissing {}
638
+ require credential_provider: account.provider_id == "credential" else PasswordProviderMismatch {}
639
+ require credential_identity: account.account_id == external_account_id else PasswordProviderMismatch {}
640
+ require account_snapshot: account.revision == expected_revision else PasswordAccountStale {}
641
+ set account.password = password checked_by account_snapshot
642
+ set account.updated_at = updated_at checked_by account_snapshot
643
+ set account.revision = account.revision + 1
644
+ return CredentialPasswordUpdated {}
645
+ }
646
+
647
+ command CreateInvitation {
648
+ input request_id: uuid
649
+ input organization_id: uuid
650
+ input invitation_id: uuid
651
+ input created_at: timestamp
652
+ input email: string<320>
653
+ input expires_at: timestamp
654
+ input inviter_id: uuid
655
+ input org_id: uuid
656
+ input role: optional<string<256>>
657
+ input status: string<32>
658
+ idempotency_key request_id
659
+ read User(organization_id, inviter_id) as parent_inviter_id else InvitationParentMissing {}
660
+ mutate Organization(organization_id, org_id) as parent_org_id else InvitationParentMissing {}
661
+ create Invitation(organization_id, invitation_id) as record else InvitationAlreadyExists {}
662
+ require capacity: parent_org_id.invitation_count < 100 else CapacityExceeded {}
663
+ set record.created_at = created_at
664
+ set record.email = email
665
+ set record.expires_at = expires_at
666
+ set record.inviter_id = inviter_id
667
+ set record.org_id = org_id
668
+ set record.role = role
669
+ set record.status = status
670
+ set record.revision = 1
671
+ set parent_org_id.invitation_count = parent_org_id.invitation_count + 1
672
+ set parent_org_id.revision = parent_org_id.revision + 1
673
+ return InvitationCreated {}
674
+ }
675
+
676
+ command UpdateInvitation {
677
+ input request_id: uuid
678
+ input organization_id: uuid
679
+ input invitation_id: uuid
680
+ input expected_revision: u64
681
+ input created_at: timestamp
682
+ input email: string<320>
683
+ input expires_at: timestamp
684
+ input inviter_id: uuid
685
+ input org_id: uuid
686
+ input role: optional<string<256>>
687
+ input status: string<32>
688
+ idempotency_key request_id
689
+ read User(organization_id, inviter_id) as parent_inviter_id else InvitationParentMissing {}
690
+ read Organization(organization_id, org_id) as parent_org_id else InvitationParentMissing {}
691
+ mutate Invitation(organization_id, invitation_id) as record else InvitationMissing {}
692
+ require current_revision: record.revision == expected_revision else Stale {}
693
+ set record.created_at = created_at checked_by current_revision
694
+ set record.email = email checked_by current_revision
695
+ set record.expires_at = expires_at checked_by current_revision
696
+ set record.inviter_id = inviter_id checked_by current_revision
697
+ set record.org_id = org_id checked_by current_revision
698
+ set record.role = role checked_by current_revision
699
+ set record.status = status checked_by current_revision
700
+ set record.revision = record.revision + 1
701
+ return InvitationUpdated {}
702
+ }
703
+
704
+ bulk command DeleteInvitation {
705
+ input request_id: uuid
706
+ input organization_id: uuid
707
+ input org_id: uuid
708
+ input ids: list<uuid, 1..1>
709
+ idempotency_key request_id
710
+ mutate Organization(organization_id, org_id) as parent else OrganizationMissing {}
711
+ for id in ids {
712
+ delete Invitation(organization_id, id) as record else InvitationMissing {}
713
+ require same_organization: record.org_id == org_id else OrganizationMismatch {}
714
+ }
715
+ require counted: parent.invitation_count > 0 else CounterInconsistent {}
716
+ set parent.invitation_count = parent.invitation_count - 1 checked_by counted
717
+ set parent.revision = parent.revision + 1
718
+ return InvitationDeleted {}
719
+ }
720
+
721
+ command CreateMember {
722
+ input request_id: uuid
723
+ input organization_id: uuid
724
+ input member_id: uuid
725
+ input created_at: timestamp
726
+ input org_id: uuid
727
+ input role: string<256>
728
+ input user_id: uuid
729
+ idempotency_key request_id
730
+ mutate Organization(organization_id, org_id) as parent_org_id else MemberParentMissing {}
731
+ read User(organization_id, user_id) as parent_user_id else MemberParentMissing {}
732
+ create Member(organization_id, member_id) as record else MemberAlreadyExists {}
733
+ require capacity: parent_org_id.member_count < 100 else CapacityExceeded {}
734
+ set record.created_at = created_at
735
+ set record.org_id = org_id
736
+ set record.role = role
737
+ set record.user_id = user_id
738
+ set record.revision = 1
739
+ set parent_org_id.member_count = parent_org_id.member_count + 1
740
+ set parent_org_id.revision = parent_org_id.revision + 1
741
+ return MemberCreated {}
742
+ }
743
+
744
+ command UpdateMember {
745
+ input request_id: uuid
746
+ input organization_id: uuid
747
+ input member_id: uuid
748
+ input expected_revision: u64
749
+ input created_at: timestamp
750
+ input org_id: uuid
751
+ input role: string<256>
752
+ input user_id: uuid
753
+ idempotency_key request_id
754
+ read Organization(organization_id, org_id) as parent_org_id else MemberParentMissing {}
755
+ read User(organization_id, user_id) as parent_user_id else MemberParentMissing {}
756
+ mutate Member(organization_id, member_id) as record else MemberMissing {}
757
+ require current_revision: record.revision == expected_revision else Stale {}
758
+ set record.created_at = created_at checked_by current_revision
759
+ set record.org_id = org_id checked_by current_revision
760
+ set record.role = role checked_by current_revision
761
+ set record.user_id = user_id checked_by current_revision
762
+ set record.revision = record.revision + 1
763
+ return MemberUpdated {}
764
+ }
765
+
766
+ bulk command DeleteMember {
767
+ input request_id: uuid
768
+ input organization_id: uuid
769
+ input org_id: uuid
770
+ input ids: list<uuid, 1..1>
771
+ idempotency_key request_id
772
+ mutate Organization(organization_id, org_id) as parent else OrganizationMissing {}
773
+ for id in ids {
774
+ delete Member(organization_id, id) as record else MemberMissing {}
775
+ require same_organization: record.org_id == org_id else OrganizationMismatch {}
776
+ }
777
+ require counted: parent.member_count > 0 else CounterInconsistent {}
778
+ set parent.member_count = parent.member_count - 1 checked_by counted
779
+ set parent.revision = parent.revision + 1
780
+ return MemberDeleted {}
781
+ }
782
+
783
+ command CreateOrganization {
784
+ input request_id: uuid
785
+ input organization_id: uuid
786
+ input org_id: uuid
787
+ input created_at: timestamp
788
+ input logo: optional<string<2048>>
789
+ input metadata: optional<string<2048>>
790
+ input name: string<256>
791
+ input slug: string<256>
792
+ idempotency_key request_id
793
+ create Organization(organization_id, org_id) as record else OrganizationAlreadyExists {}
794
+ set record.created_at = created_at
795
+ set record.logo = logo
796
+ set record.metadata = metadata
797
+ set record.name = name
798
+ set record.slug = slug
799
+ set record.member_count = 0
800
+ set record.invitation_count = 0
801
+ set record.revision = 1
802
+ return OrganizationCreated {}
803
+ }
804
+
805
+ command UpdateOrganization {
806
+ input request_id: uuid
807
+ input organization_id: uuid
808
+ input org_id: uuid
809
+ input expected_revision: u64
810
+ input created_at: timestamp
811
+ input logo: optional<string<2048>>
812
+ input metadata: optional<string<2048>>
813
+ input name: string<256>
814
+ input slug: string<256>
815
+ idempotency_key request_id
816
+ mutate Organization(organization_id, org_id) as record else OrganizationMissing {}
817
+ require current_revision: record.revision == expected_revision else Stale {}
818
+ set record.created_at = created_at checked_by current_revision
819
+ set record.logo = logo checked_by current_revision
820
+ set record.metadata = metadata checked_by current_revision
821
+ set record.name = name checked_by current_revision
822
+ set record.slug = slug checked_by current_revision
823
+ set record.revision = record.revision + 1
824
+ return OrganizationUpdated {}
825
+ }
826
+
827
+ bulk command DeleteOrganization {
828
+ input request_id: uuid
829
+ input organization_id: uuid
830
+ input ids: list<uuid, 1..1>
831
+ idempotency_key request_id
832
+ for id in ids {
833
+ delete Organization(organization_id, id) as record else OrganizationMissing {}
834
+ cascade CascadeLimitExceeded {}
835
+ }
836
+ return OrganizationDeleted {}
837
+ }
838
+
839
+ command CreateTwoFactor {
840
+ input request_id: uuid
841
+ input organization_id: uuid
842
+ input two_factor_id: uuid
843
+ input backup_codes: string<2048>
844
+ input failed_verification_count: i64
845
+ input locked_until: optional<timestamp>
846
+ input secret: string<2048>
847
+ input user_id: uuid
848
+ input verified: bool
849
+ input locked_until_millis: i64
850
+ idempotency_key request_id
851
+ read User(organization_id, user_id) as parent_user_id else TwoFactorParentMissing {}
852
+ create TwoFactor(organization_id, two_factor_id) as record else TwoFactorAlreadyExists {}
853
+ set record.backup_codes = backup_codes
854
+ set record.failed_verification_count = failed_verification_count
855
+ set record.locked_until = locked_until
856
+ set record.secret = secret
857
+ set record.user_id = user_id
858
+ set record.verified = verified
859
+ set record.locked_until_millis = locked_until_millis
860
+ set record.revision = 1
861
+ return TwoFactorCreated {}
862
+ }
863
+
864
+ command UpdateTwoFactor {
865
+ input request_id: uuid
866
+ input organization_id: uuid
867
+ input two_factor_id: uuid
868
+ input expected_revision: u64
869
+ input backup_codes: string<2048>
870
+ input failed_verification_count: i64
871
+ input locked_until: optional<timestamp>
872
+ input secret: string<2048>
873
+ input user_id: uuid
874
+ input verified: bool
875
+ input locked_until_millis: i64
876
+ idempotency_key request_id
877
+ read User(organization_id, user_id) as parent_user_id else TwoFactorParentMissing {}
878
+ mutate TwoFactor(organization_id, two_factor_id) as record else TwoFactorMissing {}
879
+ require current_revision: record.revision == expected_revision else Stale {}
880
+ set record.backup_codes = backup_codes checked_by current_revision
881
+ set record.failed_verification_count = failed_verification_count checked_by current_revision
882
+ set record.locked_until = locked_until checked_by current_revision
883
+ set record.secret = secret checked_by current_revision
884
+ set record.user_id = user_id checked_by current_revision
885
+ set record.verified = verified checked_by current_revision
886
+ set record.locked_until_millis = locked_until_millis checked_by current_revision
887
+ set record.revision = record.revision + 1
888
+ return TwoFactorUpdated {}
889
+ }
890
+
891
+ bulk command DeleteTwoFactor {
892
+ input request_id: uuid
893
+ input organization_id: uuid
894
+ input ids: list<uuid, 1..100>
895
+ idempotency_key request_id
896
+ for id in ids {
897
+ delete TwoFactor(organization_id, id) as record else TwoFactorMissing {}
898
+ }
899
+ return TwoFactorDeleted {}
900
+ }
901
+
902
+ command IncrementTwoFactorFailure {
903
+ input request_id: uuid
904
+ input organization_id: uuid
905
+ input two_factor_id: uuid
906
+ idempotency_key request_id
907
+ mutate TwoFactor(organization_id, two_factor_id) as record else Missing {}
908
+ require guard_0: record.failed_verification_count < 1000000 else GuardFailed {}
909
+ set record.failed_verification_count = record.failed_verification_count + 1 checked_by guard_0
910
+ set record.revision = record.revision + 1
911
+ return Changed {
912
+ two_factor_id: record.two_factor_id,
913
+ backup_codes: record.backup_codes reveals record.backup_codes,
914
+ failed_verification_count: record.failed_verification_count reveals record.failed_verification_count,
915
+ locked_until: record.locked_until reveals record.locked_until,
916
+ secret: record.secret reveals record.secret,
917
+ user_id: record.user_id,
918
+ verified: record.verified,
919
+ revision: record.revision
920
+ }
921
+ }
922
+
923
+ command LockTwoFactor {
924
+ input request_id: uuid
925
+ input organization_id: uuid
926
+ input two_factor_id: uuid
927
+ input minimum_failures: i64
928
+ input locked_until: optional<timestamp>
929
+ input locked_until_millis: i64
930
+ idempotency_key request_id
931
+ mutate TwoFactor(organization_id, two_factor_id) as record else Missing {}
932
+ require guard_0: record.failed_verification_count >= minimum_failures else GuardFailed {}
933
+ set record.locked_until = locked_until checked_by guard_0
934
+ set record.locked_until_millis = locked_until_millis checked_by guard_0
935
+ set record.revision = record.revision + 1
936
+ return Changed {
937
+ two_factor_id: record.two_factor_id,
938
+ backup_codes: record.backup_codes reveals record.backup_codes,
939
+ failed_verification_count: record.failed_verification_count reveals record.failed_verification_count,
940
+ locked_until: record.locked_until reveals record.locked_until,
941
+ secret: record.secret reveals record.secret,
942
+ user_id: record.user_id,
943
+ verified: record.verified,
944
+ revision: record.revision
945
+ }
946
+ }
947
+
948
+ command ResetExpiredTwoFactor {
949
+ input request_id: uuid
950
+ input organization_id: uuid
951
+ input two_factor_id: uuid
952
+ input before_millis: i64
953
+ idempotency_key request_id
954
+ mutate TwoFactor(organization_id, two_factor_id) as record else Missing {}
955
+ require guard_0: record.locked_until_millis > 0 && record.locked_until_millis <= before_millis else GuardFailed {}
956
+ set record.failed_verification_count = 0 checked_by guard_0
957
+ set record.locked_until = null checked_by guard_0
958
+ set record.locked_until_millis = 0 checked_by guard_0
959
+ set record.revision = record.revision + 1
960
+ return Changed {
961
+ two_factor_id: record.two_factor_id,
962
+ backup_codes: record.backup_codes reveals record.backup_codes,
963
+ failed_verification_count: record.failed_verification_count reveals record.failed_verification_count,
964
+ locked_until: record.locked_until reveals record.locked_until,
965
+ secret: record.secret reveals record.secret,
966
+ user_id: record.user_id,
967
+ verified: record.verified,
968
+ revision: record.revision
969
+ }
970
+ }
971
+
972
+ command ReplaceTwoFactorBackupCodes {
973
+ input request_id: uuid
974
+ input organization_id: uuid
975
+ input two_factor_id: uuid
976
+ input expected: string<2048>
977
+ input replacement: string<2048>
978
+ idempotency_key request_id
979
+ mutate TwoFactor(organization_id, two_factor_id) as record else Missing {}
980
+ require guard_0: record.backup_codes == expected else GuardFailed {}
981
+ set record.backup_codes = replacement checked_by guard_0
982
+ set record.revision = record.revision + 1
983
+ return Changed {
984
+ two_factor_id: record.two_factor_id,
985
+ backup_codes: record.backup_codes reveals record.backup_codes,
986
+ failed_verification_count: record.failed_verification_count reveals record.failed_verification_count,
987
+ locked_until: record.locked_until reveals record.locked_until,
988
+ secret: record.secret reveals record.secret,
989
+ user_id: record.user_id,
990
+ verified: record.verified,
991
+ revision: record.revision
992
+ }
993
+ }
994
+
995
+ command TransitionInvitation {
996
+ input request_id: uuid
997
+ input organization_id: uuid
998
+ input invitation_id: uuid
999
+ input expected: string<32>
1000
+ input replacement: string<32>
1001
+ idempotency_key request_id
1002
+ mutate Invitation(organization_id, invitation_id) as record else Missing {}
1003
+ require guard_0: record.status == expected else GuardFailed {}
1004
+ set record.status = replacement checked_by guard_0
1005
+ set record.revision = record.revision + 1
1006
+ return Changed {
1007
+ invitation_id: record.invitation_id,
1008
+ created_at: record.created_at,
1009
+ email: record.email,
1010
+ expires_at: record.expires_at,
1011
+ inviter_id: record.inviter_id,
1012
+ org_id: record.org_id,
1013
+ role: record.role,
1014
+ status: record.status,
1015
+ revision: record.revision
1016
+ }
1017
+ }
1018
+
1019
+ command CreateMemberAndActivateOrganization {
1020
+ input request_id: uuid
1021
+ input organization_id: uuid
1022
+ input member_id: uuid
1023
+ input created_at: timestamp
1024
+ input org_id: uuid
1025
+ input role: string<256>
1026
+ input user_id: uuid
1027
+ input session_user_id: uuid
1028
+ input session_id: uuid
1029
+ input session_revision: u64
1030
+ input session_updated_at: timestamp
1031
+ input session_active_organization_id: optional<string<2048>>
1032
+ idempotency_key request_id
1033
+ mutate Organization(organization_id, org_id) as parent_org_id else MemberParentMissing {}
1034
+ read User(organization_id, user_id) as parent_user_id else MemberParentMissing {}
1035
+ create Member(organization_id, member_id) as record else MemberAlreadyExists {}
1036
+ mutate Session(organization_id, session_user_id, session_id) as session else SessionMissing {}
1037
+ require session_snapshot: session.revision == session_revision else Stale {}
1038
+ require session_owner: session.user_id == user_id else SessionOwnerMismatch {}
1039
+ require capacity: parent_org_id.member_count < 100 else CapacityExceeded {}
1040
+ set record.created_at = created_at
1041
+ set record.org_id = org_id
1042
+ set record.role = role
1043
+ set record.user_id = user_id
1044
+ set record.revision = 1
1045
+ set parent_org_id.member_count = parent_org_id.member_count + 1
1046
+ set parent_org_id.revision = parent_org_id.revision + 1
1047
+ set session.active_organization_id = session_active_organization_id checked_by session_snapshot
1048
+ set session.updated_at = session_updated_at checked_by session_snapshot
1049
+ set session.revision = session.revision + 1
1050
+ return MemberCreated {}
1051
+ }
1052
+
1053
+ }