@fuzdev/fuz_app 0.67.1 → 0.69.0

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 (235) hide show
  1. package/dist/actions/perform_action.d.ts.map +1 -1
  2. package/dist/actions/perform_action.js +10 -3
  3. package/dist/auth/CLAUDE.md +99 -5
  4. package/dist/auth/account_queries.d.ts +87 -4
  5. package/dist/auth/account_queries.d.ts.map +1 -1
  6. package/dist/auth/account_queries.js +107 -17
  7. package/dist/auth/account_schema.d.ts +19 -0
  8. package/dist/auth/account_schema.d.ts.map +1 -1
  9. package/dist/auth/account_schema.js +8 -0
  10. package/dist/auth/admin_action_specs.d.ts +170 -3
  11. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  12. package/dist/auth/admin_action_specs.js +148 -4
  13. package/dist/auth/admin_actions.d.ts +4 -14
  14. package/dist/auth/admin_actions.d.ts.map +1 -1
  15. package/dist/auth/admin_actions.js +246 -40
  16. package/dist/auth/audit_log_ddl.d.ts +10 -1
  17. package/dist/auth/audit_log_ddl.d.ts.map +1 -1
  18. package/dist/auth/audit_log_ddl.js +13 -4
  19. package/dist/auth/audit_log_schema.d.ts +34 -1
  20. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  21. package/dist/auth/audit_log_schema.js +73 -0
  22. package/dist/auth/auth_ddl.d.ts +2 -2
  23. package/dist/auth/auth_ddl.d.ts.map +1 -1
  24. package/dist/auth/auth_ddl.js +10 -2
  25. package/dist/auth/cell_action_specs.d.ts +1295 -0
  26. package/dist/auth/cell_action_specs.d.ts.map +1 -0
  27. package/dist/auth/cell_action_specs.js +397 -0
  28. package/dist/auth/cell_actions.d.ts +63 -0
  29. package/dist/auth/cell_actions.d.ts.map +1 -0
  30. package/dist/auth/cell_actions.js +546 -0
  31. package/dist/auth/cell_audit_action_specs.d.ts +131 -0
  32. package/dist/auth/cell_audit_action_specs.d.ts.map +1 -0
  33. package/dist/auth/cell_audit_action_specs.js +70 -0
  34. package/dist/auth/cell_audit_actions.d.ts +18 -0
  35. package/dist/auth/cell_audit_actions.d.ts.map +1 -0
  36. package/dist/auth/cell_audit_actions.js +59 -0
  37. package/dist/auth/cell_audit_events.d.ts +28 -0
  38. package/dist/auth/cell_audit_events.d.ts.map +1 -0
  39. package/dist/auth/cell_audit_events.js +42 -0
  40. package/dist/auth/cell_audit_metadata.d.ts +48 -0
  41. package/dist/auth/cell_audit_metadata.d.ts.map +1 -0
  42. package/dist/auth/cell_audit_metadata.js +46 -0
  43. package/dist/auth/cell_authorize.d.ts +88 -0
  44. package/dist/auth/cell_authorize.d.ts.map +1 -0
  45. package/dist/auth/cell_authorize.js +172 -0
  46. package/dist/auth/cell_data_schema.d.ts +44 -0
  47. package/dist/auth/cell_data_schema.d.ts.map +1 -0
  48. package/dist/auth/cell_data_schema.js +42 -0
  49. package/dist/auth/cell_field_action_specs.d.ts +244 -0
  50. package/dist/auth/cell_field_action_specs.d.ts.map +1 -0
  51. package/dist/auth/cell_field_action_specs.js +136 -0
  52. package/dist/auth/cell_field_actions.d.ts +34 -0
  53. package/dist/auth/cell_field_actions.d.ts.map +1 -0
  54. package/dist/auth/cell_field_actions.js +153 -0
  55. package/dist/auth/cell_field_audit_metadata.d.ts +30 -0
  56. package/dist/auth/cell_field_audit_metadata.d.ts.map +1 -0
  57. package/dist/auth/cell_field_audit_metadata.js +28 -0
  58. package/dist/auth/cell_grant_action_specs.d.ts +333 -0
  59. package/dist/auth/cell_grant_action_specs.d.ts.map +1 -0
  60. package/dist/auth/cell_grant_action_specs.js +148 -0
  61. package/dist/auth/cell_grant_actions.d.ts +50 -0
  62. package/dist/auth/cell_grant_actions.d.ts.map +1 -0
  63. package/dist/auth/cell_grant_actions.js +208 -0
  64. package/dist/auth/cell_grant_audit_metadata.d.ts +75 -0
  65. package/dist/auth/cell_grant_audit_metadata.d.ts.map +1 -0
  66. package/dist/auth/cell_grant_audit_metadata.js +54 -0
  67. package/dist/auth/cell_item_action_specs.d.ts +331 -0
  68. package/dist/auth/cell_item_action_specs.d.ts.map +1 -0
  69. package/dist/auth/cell_item_action_specs.js +182 -0
  70. package/dist/auth/cell_item_actions.d.ts +37 -0
  71. package/dist/auth/cell_item_actions.d.ts.map +1 -0
  72. package/dist/auth/cell_item_actions.js +204 -0
  73. package/dist/auth/cell_item_audit_metadata.d.ts +35 -0
  74. package/dist/auth/cell_item_audit_metadata.d.ts.map +1 -0
  75. package/dist/auth/cell_item_audit_metadata.js +32 -0
  76. package/dist/auth/cell_relation_visibility.d.ts +32 -0
  77. package/dist/auth/cell_relation_visibility.d.ts.map +1 -0
  78. package/dist/auth/cell_relation_visibility.js +57 -0
  79. package/dist/auth/deps.d.ts +9 -0
  80. package/dist/auth/deps.d.ts.map +1 -1
  81. package/dist/auth/role_grant_queries.d.ts +30 -0
  82. package/dist/auth/role_grant_queries.d.ts.map +1 -1
  83. package/dist/auth/role_grant_queries.js +54 -0
  84. package/dist/auth/signup_routes.d.ts +0 -3
  85. package/dist/auth/signup_routes.d.ts.map +1 -1
  86. package/dist/auth/signup_routes.js +9 -3
  87. package/dist/auth/standard_rpc_actions.d.ts +5 -5
  88. package/dist/auth/standard_rpc_actions.js +4 -4
  89. package/dist/db/CLAUDE.md +118 -0
  90. package/dist/db/cell_audit_queries.d.ts +26 -0
  91. package/dist/db/cell_audit_queries.d.ts.map +1 -0
  92. package/dist/db/cell_audit_queries.js +53 -0
  93. package/dist/db/cell_ddl.d.ts +151 -0
  94. package/dist/db/cell_ddl.d.ts.map +1 -0
  95. package/dist/db/cell_ddl.js +247 -0
  96. package/dist/db/cell_field_queries.d.ts +105 -0
  97. package/dist/db/cell_field_queries.d.ts.map +1 -0
  98. package/dist/db/cell_field_queries.js +113 -0
  99. package/dist/db/cell_grant_queries.d.ts +132 -0
  100. package/dist/db/cell_grant_queries.d.ts.map +1 -0
  101. package/dist/db/cell_grant_queries.js +145 -0
  102. package/dist/db/cell_history_ddl.d.ts +38 -0
  103. package/dist/db/cell_history_ddl.d.ts.map +1 -0
  104. package/dist/db/cell_history_ddl.js +61 -0
  105. package/dist/db/cell_item_queries.d.ts +107 -0
  106. package/dist/db/cell_item_queries.d.ts.map +1 -0
  107. package/dist/db/cell_item_queries.js +119 -0
  108. package/dist/db/cell_queries.d.ts +327 -0
  109. package/dist/db/cell_queries.d.ts.map +1 -0
  110. package/dist/db/cell_queries.js +431 -0
  111. package/dist/db/fact_ddl.d.ts +38 -0
  112. package/dist/db/fact_ddl.d.ts.map +1 -0
  113. package/dist/db/fact_ddl.js +71 -0
  114. package/dist/db/fact_queries.d.ts +140 -0
  115. package/dist/db/fact_queries.d.ts.map +1 -0
  116. package/dist/db/fact_queries.js +161 -0
  117. package/dist/db/fact_store.d.ts +112 -0
  118. package/dist/db/fact_store.d.ts.map +1 -0
  119. package/dist/db/fact_store.js +225 -0
  120. package/dist/server/app_server.d.ts +1 -7
  121. package/dist/server/app_server.d.ts.map +1 -1
  122. package/dist/server/app_server.js +1 -5
  123. package/dist/server/env.d.ts +2 -0
  124. package/dist/server/env.d.ts.map +1 -1
  125. package/dist/server/env.js +6 -0
  126. package/dist/server/fact_write.d.ts +32 -0
  127. package/dist/server/fact_write.d.ts.map +1 -0
  128. package/dist/server/fact_write.js +56 -0
  129. package/dist/server/file_fact_fetcher.d.ts +42 -0
  130. package/dist/server/file_fact_fetcher.d.ts.map +1 -0
  131. package/dist/server/file_fact_fetcher.js +60 -0
  132. package/dist/server/file_fact_url.d.ts +53 -0
  133. package/dist/server/file_fact_url.d.ts.map +1 -0
  134. package/dist/server/file_fact_url.js +52 -0
  135. package/dist/server/serve_fact_route.d.ts +78 -0
  136. package/dist/server/serve_fact_route.d.ts.map +1 -0
  137. package/dist/server/serve_fact_route.js +205 -0
  138. package/dist/testing/CLAUDE.md +142 -6
  139. package/dist/testing/app_server.d.ts +46 -0
  140. package/dist/testing/app_server.d.ts.map +1 -1
  141. package/dist/testing/app_server.js +67 -8
  142. package/dist/testing/audit_completeness.d.ts.map +1 -1
  143. package/dist/testing/audit_completeness.js +67 -1
  144. package/dist/testing/cross_backend/account_lifecycle.d.ts +10 -0
  145. package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -0
  146. package/dist/testing/cross_backend/account_lifecycle.js +144 -0
  147. package/dist/testing/cross_backend/actor_lookup.d.ts +10 -0
  148. package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -0
  149. package/dist/testing/cross_backend/actor_lookup.js +83 -0
  150. package/dist/testing/cross_backend/actor_search.d.ts +6 -0
  151. package/dist/testing/cross_backend/actor_search.d.ts.map +1 -0
  152. package/dist/testing/cross_backend/actor_search.js +92 -0
  153. package/dist/testing/cross_backend/app_settings.d.ts +6 -0
  154. package/dist/testing/cross_backend/app_settings.d.ts.map +1 -0
  155. package/dist/testing/cross_backend/app_settings.js +95 -0
  156. package/dist/testing/cross_backend/backend_config.d.ts +1 -1
  157. package/dist/testing/cross_backend/capabilities.d.ts +29 -7
  158. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  159. package/dist/testing/cross_backend/capabilities.js +3 -1
  160. package/dist/testing/cross_backend/cell_cross_helpers.d.ts +39 -0
  161. package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +1 -0
  162. package/dist/testing/cross_backend/cell_cross_helpers.js +45 -0
  163. package/dist/testing/cross_backend/cell_crud.d.ts +4 -0
  164. package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -0
  165. package/dist/testing/cross_backend/cell_crud.js +168 -0
  166. package/dist/testing/cross_backend/cell_grant_role.d.ts +8 -0
  167. package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -0
  168. package/dist/testing/cross_backend/cell_grant_role.js +102 -0
  169. package/dist/testing/cross_backend/cell_relations.d.ts +4 -0
  170. package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -0
  171. package/dist/testing/cross_backend/cell_relations.js +229 -0
  172. package/dist/testing/cross_backend/conformance_case.d.ts +144 -0
  173. package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -0
  174. package/dist/testing/cross_backend/conformance_case.js +132 -0
  175. package/dist/testing/cross_backend/conformance_table.d.ts +46 -0
  176. package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -0
  177. package/dist/testing/cross_backend/conformance_table.js +199 -0
  178. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  179. package/dist/testing/cross_backend/default_backend_configs.js +6 -2
  180. package/dist/testing/cross_backend/default_spine_surface.d.ts +17 -9
  181. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
  182. package/dist/testing/cross_backend/default_spine_surface.js +20 -12
  183. package/dist/testing/cross_backend/origin.d.ts +10 -0
  184. package/dist/testing/cross_backend/origin.d.ts.map +1 -0
  185. package/dist/testing/cross_backend/origin.js +73 -0
  186. package/dist/testing/cross_backend/setup.d.ts +22 -40
  187. package/dist/testing/cross_backend/setup.d.ts.map +1 -1
  188. package/dist/testing/cross_backend/setup.js +39 -5
  189. package/dist/testing/cross_backend/testing_reset_actions.d.ts +90 -2
  190. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  191. package/dist/testing/cross_backend/testing_reset_actions.js +91 -3
  192. package/dist/testing/cross_backend/xfail.d.ts +15 -0
  193. package/dist/testing/cross_backend/xfail.d.ts.map +1 -0
  194. package/dist/testing/cross_backend/xfail.js +37 -0
  195. package/dist/testing/entities.d.ts.map +1 -1
  196. package/dist/testing/entities.js +4 -0
  197. package/dist/testing/integration.d.ts +2 -3
  198. package/dist/testing/integration.d.ts.map +1 -1
  199. package/dist/testing/integration.js +20 -85
  200. package/dist/testing/rate_limiting.d.ts +1 -1
  201. package/dist/testing/rpc_helpers.d.ts +3 -3
  202. package/dist/testing/sse_round_trip.d.ts +1 -1
  203. package/dist/testing/stubs.d.ts.map +1 -1
  204. package/dist/testing/stubs.js +0 -1
  205. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  206. package/dist/testing/ws_round_trip.js +4 -0
  207. package/dist/ui/AdminAccounts.svelte +84 -35
  208. package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
  209. package/dist/ui/AdminSessions.svelte +21 -23
  210. package/dist/ui/AdminSessions.svelte.d.ts.map +1 -1
  211. package/dist/ui/CLAUDE.md +17 -26
  212. package/dist/ui/OpenSignupToggle.svelte +2 -5
  213. package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -1
  214. package/dist/ui/account_sessions_state.svelte.d.ts +9 -10
  215. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  216. package/dist/ui/account_sessions_state.svelte.js +7 -17
  217. package/dist/ui/admin_accounts_state.svelte.d.ts +41 -20
  218. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  219. package/dist/ui/admin_accounts_state.svelte.js +52 -22
  220. package/dist/ui/admin_invites_state.svelte.d.ts +8 -11
  221. package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
  222. package/dist/ui/admin_invites_state.svelte.js +7 -16
  223. package/dist/ui/admin_rpc_adapters.d.ts +6 -2
  224. package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
  225. package/dist/ui/admin_rpc_adapters.js +5 -1
  226. package/dist/ui/admin_sessions_state.svelte.d.ts +6 -10
  227. package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
  228. package/dist/ui/admin_sessions_state.svelte.js +4 -14
  229. package/dist/ui/app_settings_state.svelte.d.ts +8 -12
  230. package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
  231. package/dist/ui/app_settings_state.svelte.js +6 -16
  232. package/dist/ui/audit_log_state.svelte.d.ts +9 -8
  233. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  234. package/dist/ui/audit_log_state.svelte.js +8 -20
  235. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"role_grant_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_queries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"role_grant_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_queries.ts"],"names":[],"mappings":"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"}
@@ -211,6 +211,60 @@ export const query_account_has_global_role = async (deps, account_id, role) => {
211
211
  ) AS exists`, [account_id, role]);
212
212
  return row?.exists ?? false;
213
213
  };
214
+ /**
215
+ * Like `query_account_has_global_role`, but only counts the grant when the
216
+ * **account itself is active** (`deleted_at IS NULL`). Used by the last-admin
217
+ * branch of the removability guard: a soft-deleted admin can't log in and is
218
+ * excluded from `query_count_active_accounts_with_global_role`, so the guard
219
+ * must use the same active-account predicate when testing whether the *target*
220
+ * is an admin — otherwise removing an already-tombstoned admin is falsely
221
+ * blocked as `cannot_delete_last_admin` even though it can't lower the active
222
+ * count. The keeper branch deliberately uses the unconditional
223
+ * `query_account_has_global_role` (a keeper is never removable regardless of
224
+ * tombstone state).
225
+ *
226
+ * @param deps - query dependencies
227
+ * @param account_id - the account to check
228
+ * @param role - the role to check for (e.g. `ROLE_ADMIN`)
229
+ * @returns `true` if the account is active and any of its actors holds an active global `role` grant
230
+ */
231
+ export const query_account_has_active_global_role = async (deps, account_id, role) => {
232
+ const row = await deps.db.query_one(`SELECT EXISTS(
233
+ SELECT 1 FROM role_grant rg
234
+ JOIN actor act ON act.id = rg.actor_id
235
+ JOIN account a ON a.id = act.account_id
236
+ WHERE a.id = $1
237
+ AND a.deleted_at IS NULL
238
+ AND rg.role = $2
239
+ AND rg.scope_id IS NULL
240
+ AND rg.revoked_at IS NULL
241
+ AND (rg.expires_at IS NULL OR rg.expires_at > NOW())
242
+ ) AS exists`, [account_id, role]);
243
+ return row?.exists ?? false;
244
+ };
245
+ /**
246
+ * Count **active** accounts (`deleted_at IS NULL`) holding an active global
247
+ * role_grant for `role`. Used by the last-admin guard on `account_delete` /
248
+ * `account_purge`: a soft-deleted account's admin grant isn't revoked, so a
249
+ * plain grant count would include tombstoned (unusable) admins — this joins
250
+ * `account` and excludes them, counting only admins that can actually log in.
251
+ *
252
+ * @param deps - query dependencies
253
+ * @param role - the role to count (e.g. `ROLE_ADMIN`)
254
+ * @returns the number of distinct active accounts with an active global `role` grant
255
+ */
256
+ export const query_count_active_accounts_with_global_role = async (deps, role) => {
257
+ const row = await deps.db.query_one(`SELECT COUNT(DISTINCT a.id) AS count
258
+ FROM account a
259
+ JOIN actor act ON act.account_id = a.id
260
+ JOIN role_grant rg ON rg.actor_id = act.id
261
+ WHERE a.deleted_at IS NULL
262
+ AND rg.role = $1
263
+ AND rg.scope_id IS NULL
264
+ AND rg.revoked_at IS NULL
265
+ AND (rg.expires_at IS NULL OR rg.expires_at > NOW())`, [role]);
266
+ return Number(row?.count ?? 0);
267
+ };
214
268
  /**
215
269
  * List all role_grants for an actor (including revoked/expired).
216
270
  */
@@ -11,7 +11,6 @@ import { z } from 'zod';
11
11
  import { type RouteSpec } from '../http/route_spec.js';
12
12
  import { type RateLimiter } from '../rate_limiter.js';
13
13
  import type { RouteFactoryDeps } from './deps.js';
14
- import type { AppSettings } from './app_settings_schema.js';
15
14
  import type { AuthSessionRouteOptions } from './account_routes.js';
16
15
  /**
17
16
  * Default minimum wall-clock time (ms) for a signup denial (403 / 409) response.
@@ -40,8 +39,6 @@ export declare const DEFAULT_SIGNUP_FAIL_JITTER_MS = 25;
40
39
  export interface SignupRouteOptions extends AuthSessionRouteOptions {
41
40
  /** Rate limiter for signup attempts, keyed by submitted username. Pass `null` to disable. */
42
41
  signup_account_rate_limiter: RateLimiter | null;
43
- /** Mutable ref to app settings — when `open_signup` is true, invite check is skipped. */
44
- app_settings: AppSettings;
45
42
  /**
46
43
  * Minimum wall-clock time (ms) for signup denial responses (403 / 409).
47
44
  * Set to `0` or a negative number to disable (e.g., in tests). Default
@@ -1 +1 @@
1
- {"version":3,"file":"signup_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAatB,OAAO,EAAkB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAA+B,KAAK,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAOhD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,qBAAqB,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAQhD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE,6FAA6F;IAC7F,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,yFAAyF;IACzF,YAAY,EAAE,WAAW,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID,0FAA0F;AAC1F,eAAO,MAAM,WAAW;;;;kBAItB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;;;;;;;kBAIvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,gBAAgB,EACtB,SAAS,kBAAkB,KACzB,KAAK,CAAC,SAAS,CAmLjB,CAAC"}
1
+ {"version":3,"file":"signup_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AActB,OAAO,EAAkB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAA+B,KAAK,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAQhD,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,qBAAqB,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAQhD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE,6FAA6F;IAC7F,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID,0FAA0F;AAC1F,eAAO,MAAM,WAAW;;;;kBAItB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;;;;;;;kBAIvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,gBAAgB,EACtB,SAAS,kBAAkB,KACzB,KAAK,CAAC,SAAS,CAwLjB,CAAC"}
@@ -11,6 +11,7 @@ import { z } from 'zod';
11
11
  import { Uuid } from '@fuzdev/fuz_util/id.js';
12
12
  import { create_session_and_set_cookie } from './session_middleware.js';
13
13
  import { query_create_account_with_actor } from './account_queries.js';
14
+ import { query_app_settings_load } from './app_settings_queries.js';
14
15
  import { query_invite_find_unclaimed_match_for_update, query_invite_claim_unscoped, } from './invite_queries.js';
15
16
  import { Username, Email } from '../primitive_schemas.js';
16
17
  import { Password } from './password.js';
@@ -74,7 +75,7 @@ export const SignupOutput = z.strictObject({
74
75
  */
75
76
  export const create_signup_route_specs = (deps, options) => {
76
77
  const { keyring, password } = deps;
77
- const { session_options, ip_rate_limiter, signup_account_rate_limiter, app_settings, signup_fail_floor_ms = DEFAULT_SIGNUP_FAIL_FLOOR_MS, signup_fail_jitter_ms = DEFAULT_SIGNUP_FAIL_JITTER_MS, } = options;
78
+ const { session_options, ip_rate_limiter, signup_account_rate_limiter, signup_fail_floor_ms = DEFAULT_SIGNUP_FAIL_FLOOR_MS, signup_fail_jitter_ms = DEFAULT_SIGNUP_FAIL_JITTER_MS, } = options;
78
79
  return [
79
80
  {
80
81
  method: 'POST',
@@ -111,6 +112,11 @@ export const create_signup_route_specs = (deps, options) => {
111
112
  return rate_limit_exceeded_response(c, check.retry_after);
112
113
  }
113
114
  }
115
+ // Load the open-signup toggle fresh from the DB on every
116
+ // request — the authoritative source, so multiple server
117
+ // processes never serve a stale in-memory value. Bounded by
118
+ // the per-IP + per-account rate limiters above.
119
+ const { open_signup } = await query_app_settings_load(route);
114
120
  // Start the denial-time floor concurrently with failure work.
115
121
  // Observed response time for 403 / 409 is `max(work, delay)`
116
122
  // so the cheap `no_match` path (no Argon2, find returns
@@ -138,7 +144,7 @@ export const create_signup_route_specs = (deps, options) => {
138
144
  reason,
139
145
  ...(invite && { invite_id: invite.id }),
140
146
  ...(email != null && { email }),
141
- ...(app_settings.open_signup && { open_signup: true }),
147
+ ...(open_signup && { open_signup: true }),
142
148
  },
143
149
  });
144
150
  };
@@ -153,7 +159,7 @@ export const create_signup_route_specs = (deps, options) => {
153
159
  // loser's `find_for_update` returns no row (winner
154
160
  // flipped `claimed_at`) and falls through to
155
161
  // `ERROR_NO_MATCHING_INVITE`. No race window.
156
- if (!app_settings.open_signup) {
162
+ if (!open_signup) {
157
163
  invite = await query_invite_find_unclaimed_match_for_update(tx_deps, email ?? null, username);
158
164
  if (!invite) {
159
165
  throw new NoMatchingInviteError();
@@ -8,8 +8,8 @@
8
8
  * `create_account_actions`).
9
9
  *
10
10
  * Option routing: shared `roles` flows to both admin and role-grant-offer;
11
- * `app_settings` goes to admin only; `default_ttl_ms` and `authorize` go
12
- * to role-grant-offer only; `max_tokens` goes to account only;
11
+ * `default_ttl_ms` and `authorize` go to role-grant-offer only; `max_tokens`
12
+ * goes to account only;
13
13
  * shared `connection_closer` flows to admin + account (role-grant-offer ignores);
14
14
  * `notification_sender` reaches role-grant-offer transparently (admin + account
15
15
  * ignore it).
@@ -27,7 +27,7 @@ import type { RpcAction } from '../actions/action_rpc.js';
27
27
  /**
28
28
  * Options for `create_standard_rpc_actions`.
29
29
  *
30
- * Composes `AdminActionOptions` (`roles`, `app_settings`),
30
+ * Composes `AdminActionOptions` (`roles`),
31
31
  * `RoleGrantOfferActionOptions` (`roles`, `default_ttl_ms`, `authorize`), and
32
32
  * `AccountActionOptions` (`max_tokens`). `roles` is shared between admin
33
33
  * and role-grant-offer — the caller supplies it once and the helper threads
@@ -49,13 +49,13 @@ export interface StandardRpcActionsDeps extends Pick<RouteFactoryDeps, 'log' | '
49
49
  /**
50
50
  * Build the combined admin + role-grant-offer + account RPC action set.
51
51
  *
52
- * Spreads `create_admin_actions(deps, {roles, app_settings})`,
52
+ * Spreads `create_admin_actions(deps, {roles})`,
53
53
  * `create_role_grant_offer_actions(deps, {roles, default_ttl_ms, authorize})`,
54
54
  * and `create_account_actions(deps, {max_tokens})`. The shared `roles`
55
55
  * option flows to admin + role-grant-offer.
56
56
  *
57
57
  * @param deps - `StandardRpcActionsDeps` (`log`, `audit` from `RouteFactoryDeps`; optional `notification_sender` for WS fan-out)
58
- * @param options - role schema, optional app-settings ref, role-grant-offer config, account config
58
+ * @param options - role schema, role-grant-offer config, account config
59
59
  * @returns RPC actions to pass as `rpc_endpoints` or spread into `create_rpc_endpoint`
60
60
  */
61
61
  export declare const create_standard_rpc_actions: (deps: StandardRpcActionsDeps, options?: StandardRpcActionsOptions) => Array<RpcAction>;
@@ -8,8 +8,8 @@
8
8
  * `create_account_actions`).
9
9
  *
10
10
  * Option routing: shared `roles` flows to both admin and role-grant-offer;
11
- * `app_settings` goes to admin only; `default_ttl_ms` and `authorize` go
12
- * to role-grant-offer only; `max_tokens` goes to account only;
11
+ * `default_ttl_ms` and `authorize` go to role-grant-offer only; `max_tokens`
12
+ * goes to account only;
13
13
  * shared `connection_closer` flows to admin + account (role-grant-offer ignores);
14
14
  * `notification_sender` reaches role-grant-offer transparently (admin + account
15
15
  * ignore it).
@@ -24,13 +24,13 @@ import { create_account_actions } from './account_actions.js';
24
24
  /**
25
25
  * Build the combined admin + role-grant-offer + account RPC action set.
26
26
  *
27
- * Spreads `create_admin_actions(deps, {roles, app_settings})`,
27
+ * Spreads `create_admin_actions(deps, {roles})`,
28
28
  * `create_role_grant_offer_actions(deps, {roles, default_ttl_ms, authorize})`,
29
29
  * and `create_account_actions(deps, {max_tokens})`. The shared `roles`
30
30
  * option flows to admin + role-grant-offer.
31
31
  *
32
32
  * @param deps - `StandardRpcActionsDeps` (`log`, `audit` from `RouteFactoryDeps`; optional `notification_sender` for WS fan-out)
33
- * @param options - role schema, optional app-settings ref, role-grant-offer config, account config
33
+ * @param options - role schema, role-grant-offer config, account config
34
34
  * @returns RPC actions to pass as `rpc_endpoints` or spread into `create_rpc_endpoint`
35
35
  */
36
36
  export const create_standard_rpc_actions = (deps, options = {}) => [
@@ -0,0 +1,118 @@
1
+ # db/
2
+
3
+ > Database layer: the `Db` abstraction over pg + PGlite, the migration
4
+ > runner, and the cell content-primitive schema + queries.
5
+
6
+ For server assembly, `QueryDeps`, and migration-runner contract see the
7
+ root ../../../CLAUDE.md and ../../../docs/architecture.md /
8
+ ../../../docs/migrations.md.
9
+
10
+ **CLAUDE.md is a map; TSDoc is the detail.** Per-symbol semantics live on
11
+ the code.
12
+
13
+ ## Generic db infrastructure
14
+
15
+ - `db.ts` — `Db` abstraction over pg + PGlite, `query` / `query_one` /
16
+ `transaction`, `no_nested_transaction` guard.
17
+ - `create_db.ts` — URL-based driver auto-detection (`postgres` /
18
+ `pglite-file` / `pglite-memory`); registers the int8 parser so
19
+ `BIGSERIAL` columns read as JS numbers.
20
+ - `db_pg.ts` / `db_pglite.ts` — driver adapters.
21
+ - `migrate.ts` — advisory-lock migration runner (`run_migrations`,
22
+ `baseline`), `Migration` / `MigrationNamespace` / `MigrationError`.
23
+ - `query_deps.ts` — `QueryDeps = {db}`, the first param to every `query_*`.
24
+ - `assert_row.ts` — `assert_row(row, context)` for INSERT … RETURNING.
25
+ - `pg_error.ts` — `is_pg_unique_violation` (Postgres `23505`).
26
+ - `sql_identifier.ts` — `assert_valid_sql_identifier`.
27
+ - `status.ts` — CLI DB status utility.
28
+
29
+ ## Cell layer
30
+
31
+ The universal mutable content primitive: a single `cell` table whose `data`
32
+ JSONB is interpreted by view shape, with normalized relation + ACL sibling
33
+ tables. `cell.refs` carries `blake3:` fact hashes auto-extracted from `data`
34
+ on every write (cells-by-fact discovery). `path` is the **global** namespace
35
+ axis — no tenant/hub scoping; globally unique on active rows. Soft delete via
36
+ `deleted_at`; most indexes are partial on `deleted_at IS NULL`.
37
+
38
+ The wire schemas + RPC handlers + authz predicates for this layer live in
39
+ `auth/` — see `auth/CLAUDE.md` §Cell layer. The DDL/query split here is:
40
+
41
+ - **`cell_ddl.ts`** — `cell` + `cell_grant` + `cell_field` + `cell_item`
42
+ tables; single-migration `CELL_MIGRATION_NS` (namespace `fuz_cell`).
43
+ `cell.visibility cell_visibility NOT NULL DEFAULT 'private'` (PG ENUM
44
+ `('private', 'public')`) — a top-level access-control column, peer to
45
+ `cell_grant`, not a `data` field. Nullable `created_by` / `updated_by`
46
+ FKs to `actor` (NULL = system origin). GIN on `data` / `refs`; global
47
+ partial-unique on `path`.
48
+ - **`cell_history_ddl.ts`** — dormant `cell_history` table
49
+ (`CELL_HISTORY_MIGRATION_NS`, namespace `fuz_cell_history`), FK → `cell.id`.
50
+ Ships present-but-unwritten; no snapshot lifecycle yet.
51
+ - **`cell_queries.ts`** — `query_cell_create / get / get_by_path / update /
52
+ delete`, `_list_by_data_kind / _list_by_creator / _list_by_ref`, the
53
+ generic `query_cell_list` (filter + SQL-side visibility predicate mirroring
54
+ `can_view_cell`), and `query_cell_load_many` (bulk id load, no visibility
55
+ filter — feeds the strict relation-read filter). `cell.refs` derived from
56
+ `data` via `extract_refs` on create/update. `CellRow.grant_count` is a
57
+ derived projection (correlated subquery on `idx_cell_grant_cell`).
58
+ - **`cell_grant_queries.ts`** — resource-side ACL: `query_cell_grant_create`
59
+ (UPSERT on the partial unique index, actor- vs role-shaped principal),
60
+ `_get`, `_delete` (returns deleted row), `_list_for_cell`,
61
+ `_list_for_cells` (bulk, for the relation-read filter), and
62
+ `query_cell_grants_for_caller_in_cells` (caller-matched enrichment for
63
+ `shared_with: 'me'`).
64
+ - **`cell_field_queries.ts`** — named relations (`(source_id, name) →
65
+ target_id`): `query_cell_field_set` (UPSERT), `_get`, `_delete`,
66
+ `_list_for_source` (`{limit, name_after}`), `_list_for_target`. Reads JOIN
67
+ cell with `deleted_at IS NULL` so dangling relations don't surface.
68
+ - **`cell_item_queries.ts`** — ordered children (`(parent_id, position) →
69
+ child_id`, fractional-index keyed): `query_cell_item_insert` (throws
70
+ `23505` on collision), `_get`, `_move`, `_delete`, `_list_for_parent`
71
+ (`{limit, position_after}`), `_list_for_child`. Same soft-delete JOIN.
72
+ - **`cell_audit_queries.ts`** — `query_audit_log_list_by_cell`: matches
73
+ `audit_log` rows whose `metadata` names the cell on any of six cell-domain
74
+ keys (`cell_id` / `source_id` / `new_id` / `parent_id` / `child_id` /
75
+ `target_id`), bitmap-OR over the metadata GIN.
76
+
77
+ ## Fact layer
78
+
79
+ Content-addressed byte store. Cells reference facts by blake3 hash
80
+ (`cell.refs`, auto-extracted from `data`); the fact layer stores the bytes.
81
+ Optional — minimal consumers never migrate it.
82
+
83
+ - **`fact_ddl.ts`** — `facts` (content-addressed bytes: embedded `bytes` xor
84
+ `external_url`, CHECK enforces exactly one) + `fact_refs` (declared
85
+ dependency edges; `target_hash` deliberately not an FK, for federation) +
86
+ `memos` (`(fn_id, input_hash) → output_hash`). `FACT_MIGRATION_NS`, namespace
87
+ `fuz_facts`.
88
+ - **`fact_queries.ts`** — mechanical `query_put_fact` (idempotent `ON CONFLICT
89
+ DO NOTHING`), `_put_fact_refs`, `_get_fact` / `_get_fact_meta` / `_has_fact`
90
+ / `_get_fact_refs`, `_delete_fact` (returns `{size, external_url}` for
91
+ external unlink), and the cell-coupled orphan queries `query_orphan_facts_list`
92
+ / `_select_for_delete` (a fact is orphan when no active `cell.refs` names it).
93
+ - **`fact_store.ts`** — `PgFactStore implements FactStore` (the interface lives
94
+ in `@fuzdev/fuz_util/fact_store.js`): embedded-vs-`put_ref` split by
95
+ `embedded_threshold`, JSON ref auto-extract, idempotent put, verify-on-read
96
+ for external content via an injected `FactExternalFetcher`. The filesystem
97
+ fetcher + write/serve plumbing live under `server/` (`file_fact_url.ts`,
98
+ `file_fact_fetcher.ts`, `fact_write.ts`, `serve_fact_route.ts`).
99
+
100
+ ### Migration namespace order
101
+
102
+ FK dependency dictates order; consumers register via `migration_namespaces`
103
+ on `create_app_backend` (after the built-in `fuz_auth` namespace). The fact
104
+ namespace is independent (no FK to cell) but conventionally sits between cell
105
+ and cell_history:
106
+
107
+ ```
108
+ auth_migration_ns (built-in, fuz_auth)
109
+ → CELL_MIGRATION_NS (fuz_cell — FKs actor.id)
110
+ → FACT_MIGRATION_NS (fuz_facts — no external FK; optional)
111
+ → CELL_HISTORY_MIGRATION_NS (fuz_cell_history — FKs cell.id)
112
+ ```
113
+
114
+ ### Pre-stable migration policy
115
+
116
+ Pre-stable: when an introducing migration needs to change shape, **rewrite
117
+ the original in place** rather than appending a follow-up — consumers
118
+ re-bootstrap dev DBs on upgrade. See ../../../docs/migrations.md.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Audit-log query for the per-cell timeline. Matches rows whose
3
+ * `metadata` jsonb names the cell on any of the keys used by cell-domain
4
+ * event envelopes — `cell_id` (cell mutations + grants), `source_id` /
5
+ * `new_id` (clone), `source_id` / `target_id` (cell_field events),
6
+ * `parent_id` / `child_id` (cell_item events).
7
+ *
8
+ * Each `metadata @> '{...}'::jsonb` clause hits the existing GIN on
9
+ * `audit_log.metadata`; Postgres bitmap-ORs the index scans together.
10
+ *
11
+ * @module
12
+ */
13
+ import type { QueryDeps } from './query_deps.js';
14
+ import type { AuditLogEvent } from '../auth/audit_log_schema.js';
15
+ import type { Uuid } from '@fuzdev/fuz_util/id.js';
16
+ export interface CellAuditListOptions {
17
+ limit: number;
18
+ /** Cursor — return rows with `seq < before`. */
19
+ before?: number;
20
+ }
21
+ /**
22
+ * Fetch audit rows mentioning `cell_id` on any cell-domain metadata key.
23
+ * Ordered newest-first by `seq` for cursor pagination through `before`.
24
+ */
25
+ export declare const query_audit_log_list_by_cell: (deps: QueryDeps, cell_id: Uuid, options: CellAuditListOptions) => Promise<Array<AuditLogEvent>>;
26
+ //# sourceMappingURL=cell_audit_queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cell_audit_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_audit_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAoBjD,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,SAAS,EACf,SAAS,IAAI,EACb,SAAS,oBAAoB,KAC3B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAwB9B,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Audit-log query for the per-cell timeline. Matches rows whose
3
+ * `metadata` jsonb names the cell on any of the keys used by cell-domain
4
+ * event envelopes — `cell_id` (cell mutations + grants), `source_id` /
5
+ * `new_id` (clone), `source_id` / `target_id` (cell_field events),
6
+ * `parent_id` / `child_id` (cell_item events).
7
+ *
8
+ * Each `metadata @> '{...}'::jsonb` clause hits the existing GIN on
9
+ * `audit_log.metadata`; Postgres bitmap-ORs the index scans together.
10
+ *
11
+ * @module
12
+ */
13
+ /**
14
+ * Metadata-jsonb keys cell-domain events use to name the cell. This
15
+ * array is the **only** source these key strings can come from —
16
+ * `query_audit_log_list_by_cell` interpolates them directly into
17
+ * `jsonb_build_object('<key>', ...)` (no SQL parameterization), so
18
+ * any caller-controllable input here would be a SQL injection. The
19
+ * list is frozen alongside the audit metadata envelopes; extending it
20
+ * means extending those envelopes too.
21
+ */
22
+ const CELL_AUDIT_METADATA_KEYS = [
23
+ 'cell_id',
24
+ 'source_id',
25
+ 'new_id',
26
+ 'parent_id',
27
+ 'child_id',
28
+ 'target_id',
29
+ ];
30
+ /**
31
+ * Fetch audit rows mentioning `cell_id` on any cell-domain metadata key.
32
+ * Ordered newest-first by `seq` for cursor pagination through `before`.
33
+ */
34
+ export const query_audit_log_list_by_cell = async (deps, cell_id, options) => {
35
+ const params = [];
36
+ let i = 1;
37
+ const cell_id_placeholder = `$${i++}`;
38
+ params.push(cell_id);
39
+ // One JSONB containment predicate per metadata key. The cell id is
40
+ // shared across all keys, so we reuse `$1` rather than allocating a
41
+ // fresh placeholder per clause — keeps the prepared statement plan
42
+ // stable and the param list small.
43
+ const containment_predicates = CELL_AUDIT_METADATA_KEYS.map((key) => `metadata @> jsonb_build_object('${key}', ${cell_id_placeholder}::text)`);
44
+ const conditions = [`(${containment_predicates.join(' OR ')})`];
45
+ if (options.before !== undefined) {
46
+ conditions.push(`seq < $${i++}`);
47
+ params.push(options.before);
48
+ }
49
+ const where = `WHERE ${conditions.join(' AND ')}`;
50
+ const limit_placeholder = `$${i++}`;
51
+ params.push(options.limit);
52
+ return deps.db.query(`SELECT * FROM audit_log ${where} ORDER BY seq DESC LIMIT ${limit_placeholder}`, params);
53
+ };
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Cell PG schema.
3
+ *
4
+ * The universal content primitive: a single `cell` table whose `data` JSONB
5
+ * is interpreted by view shape. Parent→child membership and named
6
+ * relationships live in two sibling tables — `cell_item` (ordered
7
+ * children, fractional-indexing keyed) and `cell_field` (named edges).
8
+ * `refs text[]` carries `blake3:` fact hashes auto-extracted from `data`
9
+ * by application code on every write.
10
+ *
11
+ * Soft delete via `deleted_at`. Most indexes are partial on
12
+ * `deleted_at IS NULL` so active-cell queries skip tombstones.
13
+ *
14
+ * `path` is the global namespace axis — a partial unique index enforces
15
+ * uniqueness across all active rows (PostgreSQL UNIQUE constraints don't
16
+ * support WHERE clauses, so it's expressed as a partial unique index). It
17
+ * additionally filters on `deleted_at IS NULL` so a soft-deleted cell
18
+ * doesn't block reuse of its path. Path writes are admin-only at the
19
+ * action layer; user-namespaced paths are a future extension.
20
+ *
21
+ * **Ownership columns** (`created_by`, `updated_by`) are nullable FKs to
22
+ * `actor`: NULL = system origin (well-known cells, daemon/agent cells).
23
+ * The non-admin authz path treats NULL `created_by` as admin-only via an
24
+ * explicit equality check (`auth/cell_authorize.ts`).
25
+ *
26
+ * **Timestamp naming** (`created_at`, `updated_at`) aligns with fuz_app's
27
+ * `_at`-everywhere convention used by `account`, `actor`, `audit_log`,
28
+ * `role_grant`, etc.
29
+ *
30
+ * **Single-migration shape**: `cell_v0` creates the canonical
31
+ * cell + cell_grant + cell_field + cell_item layout in one shot from the
32
+ * live exported constants.
33
+ *
34
+ * @module
35
+ */
36
+ import type { Migration, MigrationNamespace } from './migrate.js';
37
+ /**
38
+ * `cell_visibility` enum — access-control axis for a cell. Lives as a
39
+ * top-level column (not inside `data`) because visibility is access
40
+ * control, not content metadata. `cell_grant` is the other ACL surface;
41
+ * keeping visibility as a peer column (not a JSON field) co-locates
42
+ * access-control state and lets the planner reason about it directly.
43
+ *
44
+ * Ships with two states (`'private'`, `'public'`); a third (unlisted /
45
+ * public-link) folds in via `ALTER TYPE` when public-link sharing lands.
46
+ *
47
+ * Wrapped in a `DO` block so the migration can replay idempotently —
48
+ * `CREATE TYPE` has no `IF NOT EXISTS` variant in PostgreSQL.
49
+ */
50
+ export declare const CELL_VISIBILITY_TYPE = "\nDO $$ BEGIN\n\tCREATE TYPE cell_visibility AS ENUM ('private', 'public');\nEXCEPTION WHEN duplicate_object THEN NULL;\nEND $$";
51
+ /**
52
+ * `cell` table — universal content primitive: identity + content only.
53
+ * Parent→child membership lives in `cell_item`; named relations live in
54
+ * `cell_field`. Includes the `created_by` / `updated_by` ownership columns.
55
+ *
56
+ * `visibility` is the access-control axis — `private` (default) is
57
+ * restricted to admin / owner / `cell_grant`-admitted callers; `public`
58
+ * admits everyone, including unauthenticated visitors. Lives as a
59
+ * top-level column so the auth predicate reads off the row directly
60
+ * rather than reaching into `data`.
61
+ *
62
+ * `path` is the global namespace axis (no tenant/hub scoping) — globally
63
+ * unique on active rows via `idx_cell_path_unique`.
64
+ */
65
+ export declare const CELL_SCHEMA = "\nCREATE TABLE IF NOT EXISTS cell (\n\tid UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n\tdata JSONB NOT NULL,\n\tvisibility cell_visibility NOT NULL DEFAULT 'private',\n\tpath TEXT,\n\trefs TEXT[],\n\tcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\tupdated_at TIMESTAMPTZ,\n\tdeleted_at TIMESTAMPTZ,\n\tcreated_by UUID REFERENCES actor(id) ON DELETE SET NULL,\n\tupdated_by UUID REFERENCES actor(id) ON DELETE SET NULL\n)";
66
+ /**
67
+ * Cell indexes — all active-only, partial on `deleted_at IS NULL`.
68
+ *
69
+ * - `idx_cell_active`: active-cell list/scan ordered by creation.
70
+ * - `idx_cell_path_unique`: global `path` uniqueness + read-side path
71
+ * lookup. Partial on path + active so reused paths after soft delete are
72
+ * allowed.
73
+ * - `idx_cell_data`: shape-driven queries (`data ? 'kind'`, `data @> ...`).
74
+ * - `idx_cell_refs`: cells-by-fact discovery (cross-cell reference graph).
75
+ * - `idx_cell_created_by`: "cells this actor created" queries.
76
+ *
77
+ * Parent↔child membership and named relations live in sibling tables;
78
+ * see `CELL_ITEM_INDEXES` / `CELL_FIELD_INDEXES` below.
79
+ */
80
+ export declare const CELL_INDEXES: Array<string>;
81
+ /**
82
+ * `cell_grant` table — resource-side ACL for cells. Each row admits a
83
+ * principal (actor or `(role, scope_id)`) at a `level` (`viewer` or
84
+ * `editor`). Owner is implicit (`cell.created_by`); the table never carries
85
+ * owner rows.
86
+ *
87
+ * The single-principal arm is actor-grain (`actor_id` FK); the other arm is
88
+ * role-shaped (`(role, scope_id)`). The CHECK enforces exactly one arm.
89
+ */
90
+ export declare const CELL_GRANT_SCHEMA = "\nCREATE TABLE IF NOT EXISTS cell_grant (\n\tid UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n\tcell_id UUID NOT NULL REFERENCES cell(id) ON DELETE CASCADE,\n\tlevel TEXT NOT NULL CHECK (level IN ('viewer', 'editor')),\n\tactor_id UUID REFERENCES actor(id) ON DELETE CASCADE,\n\trole TEXT,\n\tscope_id UUID,\n\tgranted_by UUID REFERENCES actor(id) ON DELETE SET NULL,\n\tcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\tCHECK (\n\t\t(actor_id IS NOT NULL AND role IS NULL AND scope_id IS NULL) OR\n\t\t(actor_id IS NULL AND role IS NOT NULL)\n\t)\n)";
91
+ /**
92
+ * `cell_grant` indexes.
93
+ *
94
+ * - `idx_cell_grant_cell`: forward lookup ("who has access to this cell?").
95
+ * - `idx_cell_grant_actor`: reverse lookup ("which cells does this actor have access to?").
96
+ * - `idx_cell_grant_role_scope`: reverse lookup for role-shaped principals.
97
+ * - `idx_cell_grant_unique_actor`: prevents duplicate actor-shaped grants for the same cell.
98
+ * Re-granting updates `level` via UPSERT on this index.
99
+ * - `idx_cell_grant_unique_role_scope`: same, for role-shaped grants.
100
+ * `NULLS NOT DISTINCT` so two rows with the same `(cell_id, role)` and
101
+ * `scope_id IS NULL` collide — without it, default NULL-distinct
102
+ * semantics would let duplicate null-scope role grants slip past the
103
+ * re-share UPSERT path. Requires PostgreSQL 15+ (pglite tracks PG 16).
104
+ */
105
+ export declare const CELL_GRANT_INDEXES: Array<string>;
106
+ /**
107
+ * `cell_field` table — named relation (`(source_id, name) → target_id`).
108
+ * One target per name per source — JSON-object keys are unique. Multiplicity
109
+ * is expressed by composition (`foo.tags = collection_cell` whose `items[]`
110
+ * are the tags), not by allowing duplicate `(source_id, name)` rows.
111
+ */
112
+ export declare const CELL_FIELD_SCHEMA = "\nCREATE TABLE IF NOT EXISTS cell_field (\n\tsource_id UUID NOT NULL REFERENCES cell(id) ON DELETE CASCADE,\n\tname TEXT NOT NULL,\n\ttarget_id UUID NOT NULL REFERENCES cell(id) ON DELETE CASCADE,\n\tcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\tPRIMARY KEY (source_id, name)\n)";
113
+ /**
114
+ * `cell_field` indexes.
115
+ *
116
+ * - PK on `(source_id, name)` covers forward lookup ("what does this cell
117
+ * point to via field X?") and the per-source fields list.
118
+ * - `idx_cell_field_target` covers reverse lookup ("which cells link to
119
+ * this target?").
120
+ *
121
+ * Soft-delete is filtered by JOIN at the read boundary; no partial indexes
122
+ * here on `deleted_at` (would force index churn on cell soft-delete
123
+ * toggles, and the join filter is sufficient).
124
+ */
125
+ export declare const CELL_FIELD_INDEXES: Array<string>;
126
+ /**
127
+ * `cell_item` table — ordered child membership keyed by an opaque
128
+ * fractional-indexing string. `(parent_id, position)` PK enforces one cell
129
+ * per slot; the same `child_id` may appear at multiple positions (the
130
+ * primitive is JSON-array-shaped — ordered multiset, not set). Domain
131
+ * dedup rules ride on top in helpers.
132
+ */
133
+ export declare const CELL_ITEM_SCHEMA = "\nCREATE TABLE IF NOT EXISTS cell_item (\n\tparent_id UUID NOT NULL REFERENCES cell(id) ON DELETE CASCADE,\n\tposition TEXT NOT NULL,\n\tchild_id UUID NOT NULL REFERENCES cell(id) ON DELETE CASCADE,\n\tcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\tPRIMARY KEY (parent_id, position)\n)";
134
+ /**
135
+ * `cell_item` indexes.
136
+ *
137
+ * - PK on `(parent_id, position)` covers ordered scans for the per-parent
138
+ * items list (`SELECT ... ORDER BY position`).
139
+ * - `idx_cell_item_child` covers reverse lookup ("which parents contain
140
+ * this child?").
141
+ */
142
+ export declare const CELL_ITEM_INDEXES: Array<string>;
143
+ /** Tables created by `CELL_MIGRATION_NS`, in drop order (children first). */
144
+ export declare const CELL_DROP_TABLES: readonly ["cell_field", "cell_item", "cell_grant", "cell"];
145
+ /** Cell migrations. */
146
+ export declare const CELL_MIGRATIONS: Array<Migration>;
147
+ /** Namespace identifier for cell migrations. */
148
+ export declare const CELL_MIGRATION_NAMESPACE = "fuz_cell";
149
+ /** Migration namespace consumed by `run_migrations`. */
150
+ export declare const CELL_MIGRATION_NS: MigrationNamespace;
151
+ //# sourceMappingURL=cell_ddl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cell_ddl.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/cell_ddl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAC,SAAS,EAAE,kBAAkB,EAAC,MAAM,cAAc,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,oIAI1B,CAAC;AAER;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,4aAYtB,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,MAAM,CAYtC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,0iBAc5B,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAW5C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,+RAO5B,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAE5C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,qSAO3B,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAG3C,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,4DAA6D,CAAC;AAE3F,uBAAuB;AACvB,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,SAAS,CAuB5C,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAEnD,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,kBAG/B,CAAC"}