spine-framework 0.3.124 → 0.3.126

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 (319) hide show
  1. package/.framework/cli/commands/agents.ts +35 -37
  2. package/.framework/cli/commands/auth.ts +35 -34
  3. package/.framework/cli/commands/create-app.ts +104 -40
  4. package/.framework/cli/commands/dev.ts +104 -69
  5. package/.framework/cli/commands/doctor.ts +179 -69
  6. package/.framework/cli/commands/generate.ts +83 -143
  7. package/.framework/cli/commands/init.ts +72 -34
  8. package/.framework/cli/commands/install-app.ts +260 -125
  9. package/.framework/cli/commands/items.ts +33 -44
  10. package/.framework/cli/commands/migrate.ts +122 -40
  11. package/.framework/cli/commands/migrations.ts +33 -40
  12. package/.framework/cli/commands/pipelines.ts +31 -39
  13. package/.framework/cli/commands/status.ts +47 -23
  14. package/.framework/cli/commands/system.ts +47 -37
  15. package/.framework/cli/commands/test.ts +112 -68
  16. package/.framework/cli/commands/validate-app.ts +215 -121
  17. package/.framework/cli/context.ts +112 -130
  18. package/.framework/cli/env-loader.ts +47 -18
  19. package/.framework/cli/index.ts +81 -42
  20. package/.framework/docs/runtime-types.md +1024 -0
  21. package/.framework/functions/_shared/agent-runner.ts +1296 -961
  22. package/.framework/functions/_shared/app-manifest.ts +82 -68
  23. package/.framework/functions/_shared/audit.ts +135 -83
  24. package/.framework/functions/_shared/{cil-state.ts → cil.ts} +158 -56
  25. package/.framework/functions/_shared/db.ts +80 -126
  26. package/.framework/functions/_shared/hash-api-key.ts +63 -0
  27. package/.framework/functions/_shared/index.ts +224 -335
  28. package/.framework/functions/_shared/kb.ts +319 -0
  29. package/.framework/functions/_shared/llm.ts +92 -0
  30. package/.framework/functions/_shared/logging.ts +288 -0
  31. package/.framework/functions/_shared/middleware.ts +329 -365
  32. package/.framework/functions/_shared/outcomes.ts +36 -0
  33. package/.framework/functions/_shared/permissions.ts +359 -643
  34. package/.framework/functions/_shared/pipeline-runner.ts +243 -316
  35. package/.framework/functions/_shared/principal.ts +376 -468
  36. package/.framework/functions/_shared/resolve-credentials.ts +102 -0
  37. package/.framework/functions/_shared/resolve-ids.ts +188 -16
  38. package/.framework/functions/_shared/retry-deliveries.ts +104 -0
  39. package/.framework/functions/_shared/schema-utils.ts +611 -373
  40. package/.framework/functions/_shared/testing.ts +207 -137
  41. package/.framework/functions/_shared/tracing.ts +276 -0
  42. package/.framework/functions/_shared/trigger-engine.ts +159 -211
  43. package/.framework/functions/_shared/webhook-registration.ts +95 -81
  44. package/.framework/functions/_shared/webhook-registry.ts +153 -75
  45. package/.framework/functions/account-nodes.ts +31 -53
  46. package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
  47. package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
  48. package/.framework/functions/adapters/openai-outbound.ts +40 -0
  49. package/.framework/functions/admin-data.ts +685 -537
  50. package/.framework/functions/admin-funnel.ts +31 -20
  51. package/.framework/functions/admin-install-funnel.ts +47 -28
  52. package/.framework/functions/admin-signals.ts +47 -29
  53. package/.framework/functions/ai-agents.ts +122 -147
  54. package/.framework/functions/ai-interactions.ts +180 -90
  55. package/.framework/functions/api-keys.ts +250 -192
  56. package/.framework/functions/apps.ts +203 -197
  57. package/.framework/functions/auth.ts +98 -91
  58. package/.framework/functions/cil-agent-ingest.ts +773 -0
  59. package/.framework/functions/cil-agent.ts +592 -0
  60. package/.framework/functions/cil-callmap.ts +1227 -0
  61. package/.framework/functions/cil-config.ts +583 -0
  62. package/.framework/functions/cil-context.ts +445 -0
  63. package/.framework/functions/cil-doc.ts +1752 -0
  64. package/.framework/functions/cil-embeddings.ts +1202 -0
  65. package/.framework/functions/cil-graph.ts +585 -0
  66. package/.framework/functions/cil-ingest.ts +2416 -0
  67. package/.framework/functions/cil-pipeline.ts +318 -0
  68. package/.framework/functions/cil-project.ts +499 -0
  69. package/.framework/functions/cil-validate.ts +469 -0
  70. package/.framework/functions/debug-auth.ts +73 -53
  71. package/.framework/functions/deliveries.ts +117 -0
  72. package/.framework/functions/embeddings.ts +528 -516
  73. package/.framework/functions/eval-harness.ts +158 -106
  74. package/.framework/functions/integration-outbound.ts +311 -0
  75. package/.framework/functions/integration-routes.ts +240 -466
  76. package/.framework/functions/integrations.ts +132 -140
  77. package/.framework/functions/invites.ts +401 -201
  78. package/.framework/functions/item-progress.ts +113 -53
  79. package/.framework/functions/kb.ts +28 -0
  80. package/.framework/functions/logs.ts +239 -222
  81. package/.framework/functions/observability.ts +308 -259
  82. package/.framework/functions/pipeline-executions.ts +179 -235
  83. package/.framework/functions/pipelines.ts +163 -205
  84. package/.framework/functions/prompt-configs.ts +109 -156
  85. package/.framework/functions/roles.ts +97 -147
  86. package/.framework/functions/system-cron.ts +132 -218
  87. package/.framework/functions/system.ts +112 -52
  88. package/.framework/functions/tests.ts +32 -28
  89. package/.framework/functions/timers.ts +162 -210
  90. package/.framework/functions/triggers.ts +282 -346
  91. package/.framework/functions/types.ts +283 -400
  92. package/.framework/migrations/001_core_schema.sql +630 -0
  93. package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
  94. package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
  95. package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
  96. package/.framework/migrations/005_core_observability.sql +598 -0
  97. package/.framework/migrations/006_security_hardening_rls.sql +97 -0
  98. package/.framework/migrations/007_kb_article_list.sql +237 -0
  99. package/.framework/migrations/008_items_target.sql +8 -0
  100. package/.framework/migrations/009_roles_slug_unique.sql +11 -0
  101. package/.framework/public/spine.config.json +91 -0
  102. package/.framework/scripts/app-install-cli.ts +112 -98
  103. package/.framework/src/App.tsx +67 -20
  104. package/.framework/src/apps/admin/index.tsx +97 -27
  105. package/.framework/src/components/AppWrapper.tsx +50 -11
  106. package/.framework/src/components/CustomAppLoader.tsx +131 -22
  107. package/.framework/src/components/admin/AdminListPage.tsx +75 -8
  108. package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
  109. package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
  110. package/.framework/src/components/admin/PageInstructions.tsx +49 -0
  111. package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
  112. package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
  113. package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
  114. package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
  115. package/.framework/src/components/app-sidebar.tsx +50 -3
  116. package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
  117. package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
  118. package/.framework/src/components/kb/KBArticleList.tsx +557 -0
  119. package/.framework/src/components/layout/AppShell.tsx +54 -16
  120. package/.framework/src/components/layout/Header.tsx +50 -38
  121. package/.framework/src/components/layout/Layout.tsx +48 -32
  122. package/.framework/src/components/layout/Sidebar.tsx +167 -16
  123. package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
  124. package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
  125. package/.framework/src/components/runtime/DataFilters.tsx +78 -1
  126. package/.framework/src/components/runtime/DataHeader.tsx +32 -29
  127. package/.framework/src/components/runtime/DataListPage.tsx +161 -2
  128. package/.framework/src/components/runtime/DataStats.tsx +48 -1
  129. package/.framework/src/components/runtime/DataTable.tsx +153 -1
  130. package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
  131. package/.framework/src/components/runtime/index.ts +16 -9
  132. package/.framework/src/components/search-form.tsx +33 -1
  133. package/.framework/src/components/shared/AgentView.tsx +48 -51
  134. package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
  135. package/.framework/src/components/shared/InviteManager.tsx +113 -52
  136. package/.framework/src/components/shared/MemberList.tsx +182 -0
  137. package/.framework/src/components/shared/SchemaFields.tsx +96 -78
  138. package/.framework/src/components/ui/DataTable.tsx +86 -56
  139. package/.framework/src/components/ui/Form.tsx +188 -109
  140. package/.framework/src/components/ui/ItemCard.tsx +86 -58
  141. package/.framework/src/components/ui/ItemListView.tsx +88 -61
  142. package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
  143. package/.framework/src/components/ui/Modal.tsx +81 -4
  144. package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
  145. package/.framework/src/components/ui/accordion.tsx +97 -5
  146. package/.framework/src/components/ui/alert-dialog.tsx +225 -13
  147. package/.framework/src/components/ui/alert.tsx +113 -6
  148. package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
  149. package/.framework/src/components/ui/avatar.tsx +129 -7
  150. package/.framework/src/components/ui/badge.tsx +65 -3
  151. package/.framework/src/components/ui/breadcrumb.tsx +145 -8
  152. package/.framework/src/components/ui/button-group.tsx +81 -4
  153. package/.framework/src/components/ui/button.tsx +49 -2
  154. package/.framework/src/components/ui/calendar.tsx +65 -3
  155. package/.framework/src/components/ui/card.tsx +145 -8
  156. package/.framework/src/components/ui/carousel.tsx +129 -7
  157. package/.framework/src/components/ui/chart.tsx +161 -10
  158. package/.framework/src/components/ui/checkbox.tsx +49 -2
  159. package/.framework/src/components/ui/collapsible.tsx +81 -5
  160. package/.framework/src/components/ui/combobox.tsx +305 -20
  161. package/.framework/src/components/ui/command.tsx +177 -11
  162. package/.framework/src/components/ui/context-menu.tsx +273 -17
  163. package/.framework/src/components/ui/dialog.tsx +209 -27
  164. package/.framework/src/components/ui/direction.tsx +64 -4
  165. package/.framework/src/components/ui/drawer.tsx +193 -12
  166. package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
  167. package/.framework/src/components/ui/empty.tsx +145 -9
  168. package/.framework/src/components/ui/field.tsx +209 -14
  169. package/.framework/src/components/ui/hover-card.tsx +81 -4
  170. package/.framework/src/components/ui/input-group.tsx +162 -10
  171. package/.framework/src/components/ui/input-otp.tsx +98 -5
  172. package/.framework/src/components/ui/input.tsx +49 -2
  173. package/.framework/src/components/ui/item.tsx +225 -13
  174. package/.framework/src/components/ui/kbd.tsx +65 -3
  175. package/.framework/src/components/ui/label.tsx +49 -2
  176. package/.framework/src/components/ui/menubar.tsx +289 -17
  177. package/.framework/src/components/ui/native-select.tsx +97 -5
  178. package/.framework/src/components/ui/navigation-menu.tsx +177 -10
  179. package/.framework/src/components/ui/pagination.tsx +161 -9
  180. package/.framework/src/components/ui/popover.tsx +145 -8
  181. package/.framework/src/components/ui/progress.tsx +49 -2
  182. package/.framework/src/components/ui/radio-group.tsx +65 -3
  183. package/.framework/src/components/ui/resizable.tsx +82 -4
  184. package/.framework/src/components/ui/scroll-area.tsx +65 -3
  185. package/.framework/src/components/ui/select.tsx +193 -11
  186. package/.framework/src/components/ui/separator.tsx +49 -2
  187. package/.framework/src/components/ui/sheet.tsx +193 -11
  188. package/.framework/src/components/ui/sidebar.tsx +481 -38
  189. package/.framework/src/components/ui/skeleton.tsx +49 -2
  190. package/.framework/src/components/ui/slider.tsx +49 -2
  191. package/.framework/src/components/ui/sonner.tsx +49 -2
  192. package/.framework/src/components/ui/spinner.tsx +49 -2
  193. package/.framework/src/components/ui/switch.tsx +49 -2
  194. package/.framework/src/components/ui/table-primitives.tsx +160 -33
  195. package/.framework/src/components/ui/table.tsx +161 -9
  196. package/.framework/src/components/ui/tabs.tsx +113 -6
  197. package/.framework/src/components/ui/textarea.tsx +49 -2
  198. package/.framework/src/components/ui/toggle-group.tsx +81 -4
  199. package/.framework/src/components/ui/toggle.tsx +65 -3
  200. package/.framework/src/components/ui/tooltip.tsx +97 -5
  201. package/.framework/src/contexts/AppContext.tsx +129 -45
  202. package/.framework/src/contexts/AuthContext.tsx +187 -144
  203. package/.framework/src/hooks/use-mobile.ts +48 -2
  204. package/.framework/src/hooks/useApi.ts +208 -159
  205. package/.framework/src/hooks/useAppPath.ts +32 -23
  206. package/.framework/src/hooks/useApps.ts +51 -20
  207. package/.framework/src/hooks/useEntityList.ts +32 -78
  208. package/.framework/src/hooks/useEntityRecord.ts +35 -96
  209. package/.framework/src/hooks/useForm.ts +32 -92
  210. package/.framework/src/hooks/useListSchema.ts +49 -78
  211. package/.framework/src/hooks/useSchemaRecord.ts +114 -105
  212. package/.framework/src/lib/api.ts +195 -116
  213. package/.framework/src/lib/supabase.ts +98 -64
  214. package/.framework/src/lib/utils.ts +287 -151
  215. package/.framework/src/main.tsx +49 -3
  216. package/.framework/src/pages/DashboardPage.tsx +52 -29
  217. package/.framework/src/pages/NotFoundPage.tsx +32 -10
  218. package/.framework/src/pages/SetupPage.tsx +32 -12
  219. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
  220. package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
  221. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
  222. package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
  223. package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
  224. package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
  225. package/.framework/src/pages/admin/AppsPage.tsx +49 -2
  226. package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
  227. package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
  228. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
  229. package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
  230. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
  231. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
  232. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
  233. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
  234. package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
  235. package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
  236. package/.framework/src/pages/admin/LogsPage.tsx +422 -75
  237. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
  238. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
  239. package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
  240. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
  241. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
  242. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
  243. package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
  244. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
  245. package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
  246. package/.framework/src/pages/admin/RolesPage.tsx +171 -18
  247. package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
  248. package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
  249. package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
  250. package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
  251. package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
  252. package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
  253. package/.framework/src/pages/admin/TimersPage.tsx +48 -20
  254. package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
  255. package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
  256. package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
  257. package/.framework/src/pages/admin/TypesPage.tsx +48 -20
  258. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
  259. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
  260. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
  261. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
  262. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
  263. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
  264. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
  265. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
  266. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
  267. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  268. package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
  269. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
  270. package/.framework/src/pages/auth/LoginPage.tsx +50 -23
  271. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
  272. package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
  273. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
  274. package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
  275. package/.framework/src/types/auth.ts +128 -71
  276. package/.framework/src/types/types.ts +373 -157
  277. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
  278. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
  279. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
  280. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
  281. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
  282. package/docs/README.md +9 -130
  283. package/netlify.toml +5 -2
  284. package/package.json +13 -25
  285. package/scripts/kb-ingest-docs.ts +203 -0
  286. package/spine.config.json +65 -4
  287. package/.framework/migrations/001_schema.sql +0 -425
  288. package/.framework/migrations/002_rls_and_functions.sql +0 -763
  289. package/.framework/migrations/004_enhancements.sql +0 -43
  290. package/.framework/migrations/005_auth_user_trigger.sql +0 -105
  291. package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
  292. package/.framework/migrations/016_invites.sql +0 -27
  293. package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
  294. package/.framework/migrations/018_apps_required_roles.sql +0 -17
  295. package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
  296. package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
  297. package/.framework/migrations/021_app_domains.sql +0 -112
  298. package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
  299. package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
  300. package/.framework/migrations/024_messages_account_id.sql +0 -9
  301. package/.framework/migrations/025_retype_threads_messages.sql +0 -240
  302. package/.framework/migrations/026_fix_rls_policies.sql +0 -47
  303. package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
  304. package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
  305. package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
  306. package/.framework/migrations/030_messages_updated_by.sql +0 -6
  307. package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
  308. package/docs/APPS.md +0 -232
  309. package/docs/ARCHITECTURE.md +0 -246
  310. package/docs/INSTALL.md +0 -155
  311. package/docs/design-schema-spec.md +0 -1837
  312. package/docs/dev-guides/01-create-an-app.md +0 -183
  313. package/docs/dev-guides/02-create-a-function.md +0 -178
  314. package/docs/dev-guides/03-create-a-component.md +0 -178
  315. package/docs/dev-guides/04-webhook-handlers.md +0 -129
  316. package/docs/dev-guides/05-testing.md +0 -168
  317. package/docs/dev-guides/README.md +0 -40
  318. package/docs/npm-packages-plan.md +0 -288
  319. package/docs/spine-core--api-reference.md +0 -822
@@ -1,3 +1,21 @@
1
+
2
+
3
+
4
+ // CIL[BEGIN chunk_id="useapps_module_header_1783719596" type="module_header" identity="module_header" parent="none"]
5
+ // CIL[DOC-MACRO purpose="Define types and interfaces for app management"]
6
+ // CIL[DOC-RESPONSIBILITY responsibility="Type definitions for AppRecord and UseAppsResult"]
7
+ // CIL[DOC-CONTEXT module="useApps" layer="frontend-hook" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
8
+ // CIL[DOC-CONTRACT inputs="none" outputs="Type definitions" errors="none" side_effects="Type declarations"]
9
+ // CIL[DOC-MICRO logic_summary="Exports AppRecord interface with app metadata and UseAppsResult interface" notable_decisions="[]"]
10
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
11
+ // CIL[DOC-STABILITY stability="stable"]
12
+ // CIL[DOC-AUDIENCE audience="developer"]
13
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/migrations/015_simplify_apps_table.sql, .framework/functions/_shared/principal.ts, \."]
14
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
15
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
16
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
17
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
18
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
1
19
  import { useState, useEffect } from 'react'
2
20
  import { apiFetch } from '../lib/api'
3
21
  import { useAuth } from '../contexts/AuthContext'
@@ -14,8 +32,8 @@ export interface AppRecord {
14
32
  source: string
15
33
  config: Record<string, any>
16
34
  nav_items: any[]
17
- min_role?: string // Deprecated: use required_roles instead
18
- required_roles?: string[] // New: array of roles that can access this app
35
+ min_role?: string
36
+ required_roles?: string[]
19
37
  is_active: boolean
20
38
  is_system: boolean
21
39
  route_prefix: string | null
@@ -30,12 +48,21 @@ interface UseAppsResult {
30
48
  error: string | null
31
49
  refetch: () => void
32
50
  }
33
-
34
- /**
35
- * Fetches active apps for the current account and filters by user roles.
36
- * Apps with renderer='none' or route_prefix=null are excluded from routing
37
- * but still returned for API-only consumers.
38
- */
51
+ // CIL[END chunk_id="useapps_module_header_1783719596"]
52
+ // CIL[BEGIN chunk_id="useapps_useapps_1783719596" type="function" identity="useApps" parent="none"]
53
+ // CIL[DOC-MACRO purpose="Fetch and filter apps based on user roles and domain"]
54
+ // CIL[DOC-RESPONSIBILITY responsibility="App fetching, role-based filtering, domain matching"]
55
+ // CIL[DOC-CONTEXT module="useApps" layer="frontend-hook" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"\\\"]"]
56
+ // CIL[DOC-CONTRACT inputs="none" outputs="UseAppsResult with apps, loading, error, refetch" errors="Network errors, auth errors" side_effects="React state updates, API calls"]
57
+ // CIL[DOC-MICRO logic_summary="Fetches apps, filters by active status, domain, and user roles with system_admin override" notable_decisions="[]"]
58
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
59
+ // CIL[DOC-STABILITY stability="stable"]
60
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 1. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, \."]
61
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
62
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
63
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
64
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
65
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
39
66
  export function useApps(): UseAppsResult {
40
67
  const { user } = useAuth()
41
68
  const [apps, setApps] = useState<AppRecord[]>([])
@@ -73,30 +100,22 @@ export function useApps(): UseAppsResult {
73
100
  const appMatchesDomain = (app: AppRecord): boolean => {
74
101
  const domain = environment === 'preview' ? app.preview_domain : app.prod_domain
75
102
  if (!domain) return true
76
- // Accept both "hostname.com" and "https://hostname.com" formats
77
103
  const hostname = domain.includes('://') ? new URL(domain).hostname : domain.split(':')[0]
78
104
  return currentHost === hostname
79
105
  }
80
106
 
81
- // Filter by user's roles: include app if user has any of the required_roles,
82
- // or if app has no role restrictions
83
107
  const accessible = allApps.filter(app => {
84
108
  if (!app.is_active) return false
85
109
  if (!appMatchesDomain(app)) return false
86
110
 
87
- // Support both new required_roles array and legacy min_role
88
111
  const requiredRoles = app.required_roles || (app.min_role ? [app.min_role] : [])
89
112
 
90
- // No role restriction = accessible to all
91
113
  if (requiredRoles.length === 0) return true
92
114
 
93
- // User has no roles = no access (unless no restriction)
94
115
  if (!user.roles || user.roles.length === 0) return false
95
116
 
96
- // system_admin can access everything
97
117
  if (user.roles.includes('system_admin')) return true
98
118
 
99
- // Check if user has any of the required roles
100
119
  return requiredRoles.some(role => user.roles!.includes(role))
101
120
  })
102
121
 
@@ -115,10 +134,21 @@ export function useApps(): UseAppsResult {
115
134
 
116
135
  return { apps, loading, error, refetch: fetchApps }
117
136
  }
118
-
119
- /**
120
- * Returns only routable apps (those with a route_prefix and renderer != 'none').
121
- */
137
+ // CIL[END chunk_id="useapps_useapps_1783719596"]
138
+ // CIL[BEGIN chunk_id="useapps_useroutableapps_1783719596" type="function" identity="useRoutableApps" parent="none"]
139
+ // CIL[DOC-MACRO purpose="Filter apps to only those with routing capabilities"]
140
+ // CIL[DOC-RESPONSIBILITY responsibility="Route filtering for navigation-ready apps"]
141
+ // CIL[DOC-CONTEXT module="useApps" layer="frontend-hook" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
142
+ // CIL[DOC-CONTRACT inputs="none" outputs="UseAppsResult filtered to routable apps" errors="none" side_effects="React state updates via useApps hook"]
143
+ // CIL[DOC-MICRO logic_summary="Wraps useApps and filters results to apps with route_prefix and not 'none' renderer" notable_decisions="[]"]
144
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
145
+ // CIL[DOC-STABILITY stability="stable"]
146
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/migrations/015_simplify_apps_table.sql, \."]
147
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
148
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
149
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
150
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
151
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
122
152
  export function useRoutableApps() {
123
153
  const result = useApps()
124
154
  return {
@@ -126,3 +156,4 @@ export function useRoutableApps() {
126
156
  apps: result.apps.filter(app => app.route_prefix != null && app.renderer !== 'none')
127
157
  }
128
158
  }
159
+ // CIL[END chunk_id="useapps_useroutableapps_1783719596"]
@@ -1,43 +1,24 @@
1
- /**
2
- * @module src/hooks/useEntityList
3
- * @audience installer
4
- * @layer frontend-hook
5
- * @stability stable
6
- *
7
- * Schema-driven list data hook. Given an entity name and a minimal
8
- * `MinimalEntityListConfig`, fetches a paginated, filtered, and sorted list
9
- * from the API and exposes controls for filters, sort, and pagination.
10
- *
11
- * **How it works:**
12
- * 1. Builds query params from `entity`, `config.api`, filters, sort, and pagination
13
- * 2. Calls `apiFetch('/api/<endpoint>?action=list&...')` via `useApi`
14
- * 3. Re-fetches when `config` arrives (async schema load), or when filters change
15
- * (which also resets page to 1)
16
- *
17
- * **Auth retry:** `useApi` re-executes on route navigation, which naturally
18
- * retries after the auth session hydrates on the next tick.
19
- *
20
- * @seeAlso src/hooks/useApi.ts (useApi — underlying fetch + abort primitive)
21
- * @seeAlso src/lib/api.ts (apiFetch)
22
- * @seeAlso src/components/runtime/DataListPage.tsx (primary consumer)
23
- * @seeAlso functions/admin-data.ts (API endpoint for list action)
24
- */
25
1
 
2
+
3
+ // CIL[BEGIN chunk_id="useentitylist_module_header_1783719596" type="module_header" identity="module_header" parent="none"]
4
+ // CIL[DOC-MACRO purpose="Define entity list hook types and interfaces"]
5
+ // CIL[DOC-RESPONSIBILITY responsibility="Type definitions for entity list management"]
6
+ // CIL[DOC-CONTEXT module="useEntityList" layer="frontend-hook" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
7
+ // CIL[DOC-CONTRACT inputs="none" outputs="MinimalEntityListConfig and UseEntityListReturn interfaces" errors="none" side_effects="Type declarations"]
8
+ // CIL[DOC-MICRO logic_summary="Exports interfaces for list configuration, return values, and pagination controls" notable_decisions="[]"]
9
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
10
+ // CIL[DOC-STABILITY stability="stable"]
11
+ // CIL[DOC-AUDIENCE audience="developer"]
12
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, \."]
13
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
14
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
15
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
16
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
17
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
26
18
  import { useState, useEffect, useCallback } from 'react'
27
19
  import { useApi } from './useApi'
28
20
  import { apiFetch } from '../lib/api'
29
21
 
30
- // ─── TYPES ───────────────────────────────────────────────────────────────────
31
-
32
- /**
33
- * Minimal configuration shape consumed by `useEntityList`.
34
- *
35
- * @prop entity - Entity name (used as fallback endpoint, filter param)
36
- * @prop typeSlug - Optional type slug; appended as `type_slug` param if present
37
- * @prop api.endpoint - Netlify function base path (e.g. `'admin-data'`)
38
- * @prop api.listAction - Action string; defaults to `'list'`
39
- * @prop list.defaultSort - Initial sort field and direction
40
- */
41
22
  interface MinimalEntityListConfig {
42
23
  entity: string
43
24
  typeSlug?: string
@@ -50,19 +31,6 @@ interface MinimalEntityListConfig {
50
31
  }
51
32
  }
52
33
 
53
- /**
54
- * Return value of `useEntityList`.
55
- *
56
- * @prop data - Fetched records array (empty while loading or on error)
57
- * @prop loading - True while fetching
58
- * @prop error - Error message or null
59
- * @prop refetch - Re-execute the current query
60
- * @prop filters - Active filter values keyed by param name
61
- * @prop setFilters - Replace the active filters (resets page to 1)
62
- * @prop sort - Current sort field and direction
63
- * @prop setSort - Update sort (does not auto-reset page)
64
- * @prop pagination - page/setPage/pageSize/setPageSize/total controls
65
- */
66
34
  interface UseEntityListReturn {
67
35
  data: any[]
68
36
  loading: boolean
@@ -80,28 +48,21 @@ interface UseEntityListReturn {
80
48
  total: number
81
49
  }
82
50
  }
83
-
84
- // ─── HOOK ────────────────────────────────────────────────────────────────────
85
-
86
- /**
87
- * Fetches and manages a filtered, sorted, paginated entity list.
88
- *
89
- * @param entity - Entity name (e.g. `'accounts'`, `'items'`)
90
- * @param config - Schema-derived config; pass `null` while schema is loading
91
- * (hook is a no-op until config is non-null)
92
- * @returns `UseEntityListReturn` — see type for full details
93
- *
94
- * @inputSpec config.api.endpoint: string — function name, e.g. `'admin-data'`
95
- * @inputSpec filters: values of `''`, `undefined`, or `'all'` are omitted from params
96
- * @outputSpec data: any[] — raw API response; shape depends on entity type
97
- * @sideEffects Network request via apiFetch; React state mutations
98
- * @calledBy DataListPage.tsx
99
- *
100
- * @example
101
- * ```tsx
102
- * const { data, loading, setFilters } = useEntityList('accounts', config)
103
- * ```
104
- */
51
+ // CIL[END chunk_id="useentitylist_module_header_1783719596"]
52
+ // CIL[BEGIN chunk_id="useentitylist_useentitylist_1783719596" type="function" identity="useEntityList" parent="none"]
53
+ // CIL[DOC-MACRO purpose="Fetch and manage paginated, filtered, sorted entity lists"]
54
+ // CIL[DOC-RESPONSIBILITY responsibility="List fetching, pagination, filtering, sorting, state management"]
55
+ // CIL[DOC-CONTEXT module="useEntityList" layer="frontend-hook" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
56
+ // CIL[DOC-CONTRACT inputs="none" outputs="UseEntityListReturn with data, controls, pagination" errors="Network errors, API errors" side_effects="React state updates, API calls via apiFetch"]
57
+ // CIL[DOC-MICRO logic_summary="Builds query params from config, filters, sort, pagination; fetches via useApi; manages state" notable_decisions="[]"]
58
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
59
+ // CIL[DOC-STABILITY stability="stable"]
60
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 3. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/components/ui/dialog.tsx, .framework/src/pages/admin/RolesPage.tsx, \."]
61
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 3. Total affected: 3."]
62
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
63
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
64
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
65
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
105
66
  export function useEntityList(
106
67
  entity: string,
107
68
  config: MinimalEntityListConfig | null
@@ -116,33 +77,27 @@ export function useEntityList(
116
77
 
117
78
  const params = new URLSearchParams()
118
79
 
119
- // Support new endpoint-based API pattern
120
80
  const endpoint = config.api.endpoint || entity
121
81
  const action = config.api.listAction || 'list'
122
82
  params.append('action', action)
123
83
 
124
- // Add entity parameter for unified admin-data endpoint
125
84
  if (config.api.endpoint) {
126
85
  params.append('entity', entity)
127
86
  }
128
87
 
129
- // Add type_slug for schema-driven filtering if available
130
88
  if (config.typeSlug) {
131
89
  params.append('type_slug', config.typeSlug)
132
90
  }
133
91
 
134
- // Add filters
135
92
  Object.entries(filters).forEach(([key, value]) => {
136
93
  if (value !== undefined && value !== '' && value !== 'all') {
137
94
  params.append(key, value.toString())
138
95
  }
139
96
  })
140
97
 
141
- // Add sort
142
98
  params.append('sort_field', sort.field)
143
99
  params.append('sort_direction', sort.direction)
144
100
 
145
- // Add pagination
146
101
  params.append('limit', pageSize.toString())
147
102
  params.append('offset', ((page - 1) * pageSize).toString())
148
103
 
@@ -160,12 +115,10 @@ export function useEntityList(
160
115
  immediate: true
161
116
  })
162
117
 
163
- // Re-fetch when config arrives (schema was not ready on initial mount)
164
118
  useEffect(() => {
165
119
  if (config) execute()
166
120
  }, [config?.api.endpoint, config?.api.listAction, config?.typeSlug])
167
121
 
168
- // Reset page when filters change
169
122
  useEffect(() => {
170
123
  setPage(1)
171
124
  }, [filters])
@@ -188,3 +141,4 @@ export function useEntityList(
188
141
  }
189
142
  }
190
143
  }
144
+ // CIL[END chunk_id="useentitylist_useentitylist_1783719596"]
@@ -1,58 +1,29 @@
1
- /**
2
- * @module src/hooks/useEntityRecord
3
- * @audience installer
4
- * @layer frontend-hook
5
- * @stability stable
6
- *
7
- * Schema-driven single-record hook. Fetches a record by ID, exposes its
8
- * design schema, computes field-level read/write permissions for the
9
- * current principal, and provides save and delete mutations.
10
- *
11
- * **Field permission model:**
12
- * - `system_admin` role always gets `{ read: true, write: true }` on all fields
13
- * - Other principals: permissions are read from `design_schema.fields[n].permissions`
14
- * as role arrays; defaults to `true` if absent
15
- *
16
- * **Save routing:**
17
- * - Fields marked `fieldDef.system = true` go to top-level record columns
18
- * - All other fields are nested under the `data` JSONB column
19
- *
20
- * **Delete:** sends a `DELETE` request with the configured `deleteAction`;
21
- * hard vs. soft delete is determined by the API handler (`config.softDelete`
22
- * signals intent to the handler).
23
- *
24
- * @seeAlso src/hooks/useApi.ts (useApi + useMutation primitives)
25
- * @seeAlso src/hooks/useSchemaRecord.ts (companion for schema-driven form data)
26
- * @seeAlso src/components/runtime/DataDetailPage.tsx (primary consumer)
27
- * @seeAlso functions/admin-data.ts (API endpoint handling get/update/delete)
28
- */
29
1
 
2
+
3
+ // CIL[BEGIN chunk_id="useentityrecord_module_header_1783719596" type="module_header" identity="module_header" parent="none"]
4
+ // CIL[DOC-MACRO purpose="Define entity record hook types and interfaces"]
5
+ // CIL[DOC-RESPONSIBILITY responsibility="Type definitions for entity record management"]
6
+ // CIL[DOC-CONTEXT module="useEntityRecord" layer="frontend-hook" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
7
+ // CIL[DOC-CONTRACT inputs="none" outputs="FieldPermissions, MinimalEntityConfig, UseEntityRecordReturn interfaces" errors="none" side_effects="Type declarations"]
8
+ // CIL[DOC-MICRO logic_summary="Exports interfaces for field permissions, entity config, and record management" notable_decisions="[]"]
9
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
10
+ // CIL[DOC-STABILITY stability="stable"]
11
+ // CIL[DOC-AUDIENCE audience="developer"]
12
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
13
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
14
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
15
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
16
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
17
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
30
18
  import { useCallback } from 'react'
31
19
  import { useApi, useMutation } from './useApi'
32
20
  import { apiFetch } from '../lib/api'
33
21
  import { useAuth } from '../contexts/AuthContext'
34
22
 
35
- // ─── TYPES ───────────────────────────────────────────────────────────────────
36
-
37
- /**
38
- * Per-field read/write permission map keyed by field name.
39
- * Computed from `design_schema.fields[n].permissions` and the current user's roles.
40
- */
41
23
  interface FieldPermissions {
42
24
  [key: string]: { read: boolean; write: boolean }
43
25
  }
44
26
 
45
- /**
46
- * Minimal entity configuration consumed by `useEntityRecord`.
47
- *
48
- * @prop entity - Entity table name
49
- * @prop typeSlug - Optional type slug for schema resolution
50
- * @prop icon - Icon identifier (used by detail page header)
51
- * @prop displayField - Field name used as the record title
52
- * @prop api.endpoint - Netlify function base path
53
- * @prop api.*Action - Action strings for get/create/update/delete
54
- * @prop softDelete - Hint for the API handler (true = set is_active=false)
55
- */
56
27
  interface MinimalEntityConfig {
57
28
  entity: string
58
29
  typeSlug?: string
@@ -68,19 +39,6 @@ interface MinimalEntityConfig {
68
39
  softDelete?: boolean
69
40
  }
70
41
 
71
- /**
72
- * Return value of `useEntityRecord`.
73
- *
74
- * @prop record - Fetched record or null
75
- * @prop schema - `design_schema` extracted from the record (or nested type)
76
- * @prop fieldPermissions - Per-field `{ read, write }` map for the current user
77
- * @prop loading - True while fetching
78
- * @prop error - Error message or null
79
- * @prop refetch - Re-fetch the record
80
- * @prop save - Trigger the save mutation (create or update based on `id`)
81
- * @prop delete - Trigger the delete mutation
82
- * @prop saving / deleting - Mutation loading flags
83
- */
84
42
  interface UseEntityRecordReturn {
85
43
  record: any
86
44
  schema: any
@@ -93,30 +51,23 @@ interface UseEntityRecordReturn {
93
51
  saving: boolean
94
52
  deleting: boolean
95
53
  }
96
-
97
- // ─── HOOK ────────────────────────────────────────────────────────────────────
98
-
99
- /**
100
- * Fetches, saves, and deletes a single entity record with schema and
101
- * field-permission awareness.
102
- *
103
- * @param entity - Entity table name (e.g. `'accounts'`)
104
- * @param id - Record UUID; pass `undefined` to enter create mode
105
- * @param config - Schema-derived config; pass `null` while loading
106
- * @returns `UseEntityRecordReturn` — see type for full details
107
- *
108
- * @inputSpec id: string | undefined — undefined triggers create mode (no GET)
109
- * @outputSpec schema: DesignSchema | {} — empty object if no design_schema found
110
- * @outputSpec fieldPermissions: FieldPermissions — computed per-render
111
- * @sideEffects Network requests via apiFetch; React state mutations
112
- * @calledBy DataDetailPage.tsx
113
- *
114
- * @example
115
- * ```tsx
116
- * const { record, save, saving, fieldPermissions } =
117
- * useEntityRecord('accounts', id, config)
118
- * ```
119
- */
54
+ // CIL[END chunk_id="useentityrecord_module_header_1783719596"]
55
+ // CIL[BEGIN chunk_id="useentityrecord_useentityrecord_1783719596" type="function" identity="useEntityRecord" parent="none"]
56
+ // CIL[DOC-LEARNING topic="runtime-type:generic/entity_record" content="useEntityRecord splits a record into system fields (field.system=true, stored on the row) and data fields (stored in record.data) using record.design_schema.fields. It applies field-level permissions before saving and uses the design_schema to build the update payload."]
57
+ // CIL[DOC-NOTE type="design_schema_caveat" content="If record.design_schema is not stamped or fields is empty, all values may be treated as data and silently dropped by row-level validation or security policies."]
58
+ // CIL[DOC-MACRO purpose="Fetch, save, and delete single entity records with permissions"]
59
+ // CIL[DOC-RESPONSIBILITY responsibility="Record CRUD operations, field permissions, schema extraction"]
60
+ // CIL[DOC-CONTEXT module="useEntityRecord" layer="frontend-hook" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/functions/_shared/principal.ts\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
61
+ // CIL[DOC-CONTRACT inputs="none" outputs="UseEntityRecordReturn with record, permissions, mutations" errors="Network errors, permission errors" side_effects="React state updates, API calls via apiFetch"]
62
+ // CIL[DOC-MICRO logic_summary="Fetches record, calculates field permissions from schema, handles create/update/delete with system/custom field separation" notable_decisions="[]"]
63
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
64
+ // CIL[DOC-STABILITY stability="stable"]
65
+ // CIL[DOC-VECTOR type="context" content="Layer: frontend-hook. Direct callers: 3. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/RolesPage.tsx, .framework/functions/_shared/principal.ts, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
66
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 3. Total affected: 3."]
67
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
68
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
69
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
70
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
120
71
  export function useEntityRecord(
121
72
  entity: string,
122
73
  id: string | undefined,
@@ -124,14 +75,12 @@ export function useEntityRecord(
124
75
  ): UseEntityRecordReturn {
125
76
  const { user } = useAuth()
126
77
 
127
- // Get API configuration with safe defaults
128
78
  const endpoint = config?.api?.endpoint || entity
129
79
  const getAction = config?.api?.getAction || 'get'
130
80
  const createAction = config?.api?.createAction || 'create'
131
81
  const updateAction = config?.api?.updateAction || 'update'
132
82
  const deleteAction = config?.api?.deleteAction || 'delete'
133
83
 
134
- // Fetch record - always call useCallback to maintain hook order
135
84
  const fetchRecord = useCallback(async () => {
136
85
  if (!id) return null
137
86
 
@@ -154,17 +103,13 @@ export function useEntityRecord(
154
103
  immediate: !!id
155
104
  })
156
105
 
157
- // Extract schema from record (accounts have it at root level, items/types have it nested)
158
106
  const schema = record?.design_schema || record?.type?.design_schema || {}
159
107
 
160
- // Calculate field permissions from record's schema
161
108
  const calculatePermissions = (): FieldPermissions => {
162
109
  const permissions: FieldPermissions = {}
163
110
 
164
- // System admin gets full access
165
111
  const isSystemAdmin = user?.roles?.includes('system_admin')
166
112
 
167
- // Get all fields from record's schema
168
113
  const recordSchema = record?.design_schema?.fields
169
114
  if (!recordSchema) return permissions
170
115
 
@@ -172,7 +117,6 @@ export function useEntityRecord(
172
117
  if (isSystemAdmin) {
173
118
  permissions[fieldName] = { read: true, write: true }
174
119
  } else {
175
- // Check field-level permissions from schema
176
120
  const fieldPerms = fieldSchema?.permissions || {}
177
121
 
178
122
  const canRead = fieldPerms.read?.some((role: string) =>
@@ -192,10 +136,8 @@ export function useEntityRecord(
192
136
 
193
137
  const fieldPermissions = calculatePermissions()
194
138
 
195
- // Save mutation
196
139
  const saveMutation = useMutation(
197
140
  async (data: any) => {
198
- // Separate system fields from custom fields
199
141
  const systemData: Record<string, any> = {}
200
142
  const customData: Record<string, any> = {}
201
143
 
@@ -208,14 +150,12 @@ export function useEntityRecord(
208
150
  }
209
151
  })
210
152
 
211
- // Combine system fields with custom data in data field
212
153
  const saveData = {
213
154
  ...systemData,
214
155
  data: Object.keys(customData).length > 0 ? customData : undefined
215
156
  }
216
157
 
217
158
  if (id) {
218
- // Update
219
159
  const params = new URLSearchParams()
220
160
  params.append('action', updateAction)
221
161
  params.append('entity', entity)
@@ -236,8 +176,7 @@ export function useEntityRecord(
236
176
 
237
177
  return response.json()
238
178
  } else {
239
- // Create
240
- const createData = { entity, ...saveData }
179
+ const createData = { entity, type_slug: config?.typeSlug, ...saveData }
241
180
 
242
181
  const params = new URLSearchParams()
243
182
  params.append('action', createAction)
@@ -268,7 +207,6 @@ export function useEntityRecord(
268
207
  }
269
208
  )
270
209
 
271
- // Delete mutation
272
210
  const deleteMutation = useMutation(
273
211
  async () => {
274
212
  if (!id) throw new Error('Cannot delete: no ID provided')
@@ -306,3 +244,4 @@ export function useEntityRecord(
306
244
  deleting: deleteMutation.loading
307
245
  }
308
246
  }
247
+ // CIL[END chunk_id="useentityrecord_useentityrecord_1783719596"]