spine-framework 0.4.3 → 0.5.0-rc.4

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 (320) hide show
  1. package/.env.example +13 -3
  2. package/.framework/cli/commands/bootstrap.ts +392 -0
  3. package/.framework/cli/commands/dev.ts +91 -218
  4. package/.framework/cli/commands/doctor.ts +132 -26
  5. package/.framework/cli/commands/generate.ts +38 -298
  6. package/.framework/cli/commands/init.ts +20 -1
  7. package/.framework/cli/commands/migrate.ts +36 -30
  8. package/.framework/cli/commands/migrations.ts +16 -56
  9. package/.framework/cli/commands/upgrade.ts +35 -0
  10. package/.framework/cli/commands/validate-schema.ts +147 -0
  11. package/.framework/cli/context.ts +223 -110
  12. package/.framework/cli/index.ts +6 -0
  13. package/.framework/cli/lib/project-files.ts +241 -1
  14. package/.framework/functions/_shared/agent-runner.ts +1000 -81
  15. package/.framework/functions/_shared/cil.ts +2 -1
  16. package/.framework/functions/_shared/db.ts +3 -6
  17. package/.framework/functions/_shared/hash-api-key.ts +183 -79
  18. package/.framework/functions/_shared/kb.ts +61 -7
  19. package/.framework/functions/_shared/logging.ts +562 -224
  20. package/.framework/functions/_shared/message-sequence.ts +53 -0
  21. package/.framework/functions/_shared/middleware.ts +47 -44
  22. package/.framework/functions/_shared/pipeline-runner.ts +150 -37
  23. package/.framework/functions/_shared/principal.ts +9 -6
  24. package/.framework/functions/_shared/trigger-engine.ts +149 -40
  25. package/.framework/functions/admin-data.ts +48 -31
  26. package/.framework/functions/ai-agents.ts +103 -33
  27. package/.framework/functions/api-keys.ts +301 -122
  28. package/.framework/functions/apps.ts +43 -26
  29. package/.framework/functions/cil-ingest.ts +48 -15
  30. package/.framework/functions/debug-auth.ts +14 -8
  31. package/.framework/functions/deliveries.ts +39 -12
  32. package/.framework/functions/embeddings.ts +145 -76
  33. package/.framework/functions/integration-outbound.ts +67 -27
  34. package/.framework/functions/integrations.ts +254 -127
  35. package/.framework/functions/logs.ts +273 -133
  36. package/.framework/functions/observability.ts +277 -147
  37. package/.framework/functions/pipeline-executions.ts +1 -1
  38. package/.framework/functions/pipeline-runner-background.ts +120 -0
  39. package/.framework/functions/pipelines.ts +14 -9
  40. package/.framework/functions/prompt-configs.ts +7 -4
  41. package/.framework/functions/roles.ts +8 -5
  42. package/.framework/functions/security.ts +30 -17
  43. package/.framework/functions/system-cron.ts +250 -128
  44. package/.framework/functions/tests.ts +7 -6
  45. package/.framework/functions/timers.ts +310 -107
  46. package/.framework/functions/trigger-scheduler.ts +65 -5
  47. package/.framework/functions/triggers.ts +28 -13
  48. package/.framework/functions/types.ts +13 -10
  49. package/.framework/migrations/064_episode_leases.sql +196 -0
  50. package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
  51. package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
  52. package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
  53. package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
  54. package/.framework/migrations/069_log_stats_window.sql +54 -0
  55. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  56. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  57. package/.framework/migrations/072_slug_autofill.sql +77 -0
  58. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  59. package/.framework/schemas/spine.config.schema.json +62 -0
  60. package/.framework/src/App.tsx +3 -1
  61. package/.framework/src/apps/admin/index.tsx +1141 -775
  62. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  63. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  64. package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
  65. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  66. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  67. package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
  68. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  69. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  70. package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
  71. package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
  72. package/.framework/src/components/layout/Layout.tsx +4 -2
  73. package/.framework/src/components/layout/Sidebar.tsx +304 -179
  74. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  75. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  76. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  77. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  78. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  79. package/.framework/src/components/ui/sheet.tsx +24 -26
  80. package/.framework/src/components/ui/textarea.tsx +74 -48
  81. package/.framework/src/hooks/useBranding.ts +47 -0
  82. package/.framework/src/hooks/useEntityList.ts +12 -9
  83. package/.framework/src/hooks/useListSchema.ts +108 -58
  84. package/.framework/src/instructions/README.md +57 -0
  85. package/.framework/src/instructions/ai-agents.md +69 -0
  86. package/.framework/src/instructions/alerts.md +80 -0
  87. package/.framework/src/instructions/api-keys.md +87 -0
  88. package/.framework/src/instructions/apps.md +77 -0
  89. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  90. package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
  91. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  92. package/.framework/src/instructions/concepts/automation.md +186 -0
  93. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  94. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  95. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  96. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  97. package/.framework/src/instructions/concepts/observability.md +116 -0
  98. package/.framework/src/instructions/concepts/permissions.md +150 -0
  99. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  100. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  101. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  102. package/.framework/src/instructions/deliveries.md +59 -0
  103. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  104. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  105. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  106. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  107. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  108. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  109. package/.framework/src/instructions/integrations.md +96 -0
  110. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  111. package/.framework/src/instructions/invites.md +60 -0
  112. package/.framework/src/instructions/kb.md +80 -0
  113. package/.framework/src/instructions/logs.md +77 -0
  114. package/.framework/src/instructions/observability.md +61 -0
  115. package/.framework/src/instructions/operations/deployment.md +115 -0
  116. package/.framework/src/instructions/operations/migrations.md +125 -0
  117. package/.framework/src/instructions/operations/security-checklist.md +148 -0
  118. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  119. package/.framework/src/instructions/operations/upgrade.md +116 -0
  120. package/.framework/src/instructions/pipeline-executions.md +62 -0
  121. package/.framework/src/instructions/pipelines.md +78 -0
  122. package/.framework/src/instructions/prompts.md +95 -0
  123. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  124. package/.framework/src/instructions/reference/api/auth.md +113 -0
  125. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  126. package/.framework/src/instructions/reference/app-manifest.md +150 -0
  127. package/.framework/src/instructions/reference/cli.md +124 -0
  128. package/.framework/src/instructions/reference/database.md +132 -0
  129. package/.framework/src/instructions/reference/design-schema.md +280 -0
  130. package/.framework/src/instructions/reference/env-vars.md +133 -0
  131. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  132. package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
  133. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  134. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  135. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  136. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  137. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  138. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  139. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  140. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  141. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  142. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  143. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  144. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  145. package/.framework/src/instructions/reference/functions/index.md +103 -0
  146. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  147. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  148. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  149. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  150. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  151. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  152. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  153. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  154. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  155. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  156. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  157. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  158. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  159. package/.framework/src/instructions/reference/functions/security.md +140 -0
  160. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  161. package/.framework/src/instructions/reference/functions/system.md +106 -0
  162. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  163. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  164. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  165. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  166. package/.framework/src/instructions/reference/functions/types.md +146 -0
  167. package/.framework/src/instructions/reference/seeds.md +126 -0
  168. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  169. package/.framework/src/instructions/reference/spine-config.md +114 -0
  170. package/.framework/src/instructions/roles.md +80 -0
  171. package/.framework/src/instructions/runtime-detail.md +70 -0
  172. package/.framework/src/instructions/runtime-list.md +77 -0
  173. package/.framework/src/instructions/security.md +67 -0
  174. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  175. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  176. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  177. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  178. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  179. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  180. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  181. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  182. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  183. package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
  184. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  185. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  186. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  187. package/.framework/src/instructions/testing.md +59 -0
  188. package/.framework/src/instructions/timers.md +82 -0
  189. package/.framework/src/instructions/triggers.md +69 -0
  190. package/.framework/src/instructions/types.md +93 -0
  191. package/.framework/src/lib/branding.ts +128 -0
  192. package/.framework/src/pages/NoAppPage.tsx +3 -1
  193. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  194. package/.framework/src/pages/SetupPage.tsx +5 -2
  195. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  196. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  197. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  198. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  199. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  200. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  201. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  202. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  203. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  204. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  205. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  206. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  207. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  208. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  209. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  210. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  211. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  212. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  213. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  214. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  215. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  216. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  217. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  218. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  219. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  220. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  221. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  222. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  223. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  224. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  225. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  226. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  227. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  228. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  229. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  230. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  231. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  232. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  233. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  234. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  235. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  236. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  237. package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
  238. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
  239. package/.framework/src/pages/auth/LoginPage.tsx +4 -2
  240. package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
  241. package/.framework/templates/agent/AGENTS.md +150 -0
  242. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  243. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  244. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  245. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  246. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
  247. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  248. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
  249. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
  250. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
  251. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  252. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  253. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  254. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  255. package/.framework/templates/project.json +5 -1
  256. package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
  257. package/.framework/tests/unit/agent-files.test.ts +355 -0
  258. package/.framework/tests/unit/agent-runner.test.ts +496 -47
  259. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  260. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  261. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  262. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  263. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  264. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  265. package/.framework/tests/unit/episode-lease.test.ts +695 -0
  266. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  267. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  268. package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
  269. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  270. package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
  271. package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
  272. package/.framework/tests/unit/principal-cache.test.ts +15 -0
  273. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  274. package/.framework/tests/unit/system-cron.test.ts +240 -0
  275. package/.framework/tests/unit/timers.test.ts +159 -0
  276. package/.framework/tests/unit/trigger-engine.test.ts +278 -91
  277. package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
  278. package/README.md +125 -166
  279. package/config/tsconfig.cli.json +2 -2
  280. package/netlify.toml +5 -0
  281. package/package.json +15 -4
  282. package/templates/project/package-lock.json +2 -2
  283. package/.framework/docs/admin-routes.md +0 -76
  284. package/.framework/docs/api-docs-progress.md +0 -38
  285. package/.framework/docs/api-governance.md +0 -146
  286. package/.framework/docs/api-testing-results.md +0 -212
  287. package/.framework/docs/assembly-launch-guide.md +0 -138
  288. package/.framework/docs/audit-results.md +0 -590
  289. package/.framework/docs/db-api-inventory.md +0 -95
  290. package/.framework/docs/gap-remediation-backlog.md +0 -103
  291. package/.framework/docs/ui-adoption-verification.md +0 -111
  292. package/.framework/docs/ui-api-coverage.md +0 -84
  293. package/.framework/docs/v2-compatibility-audit.md +0 -228
  294. package/.framework/mcp/index.ts +0 -133
  295. package/.framework/mcp/load-env.ts +0 -60
  296. package/.framework/mcp/shared/app-manifest.ts +0 -275
  297. package/.framework/mcp/shared/db.ts +0 -477
  298. package/.framework/mcp/shared/kb.ts +0 -118
  299. package/.framework/mcp/tools/architect.ts +0 -431
  300. package/.framework/mcp/tools/cil/context.ts +0 -345
  301. package/.framework/mcp/tools/cil/graph.ts +0 -242
  302. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  303. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  304. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  305. package/.framework/mcp/tools/cil/project.ts +0 -791
  306. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  307. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  308. package/.framework/mcp/tools/cil/search.ts +0 -97
  309. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  310. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  311. package/.framework/mcp/tools/kb/delete.ts +0 -139
  312. package/.framework/mcp/tools/kb/index.ts +0 -52
  313. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  314. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  315. package/.framework/mcp/tools/kb/publish.ts +0 -100
  316. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  317. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  318. package/.framework/mcp/tools/kb/search.ts +0 -101
  319. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  320. package/.framework/mcp/tools/observability.ts +0 -510
@@ -1,42 +1,69 @@
1
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="none"]
2
- // CIL[DOC-MACRO purpose="Module header for the admin API keys list page, importing dependencies and defining the page component scope."]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Set up imports and module metadata for APIKeysPage."]
4
- // CIL[DOC-CONTEXT module="admin/api-keys" layer="page" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/admin/PageInstructions.tsx,.framework/src/components/admin/SortableTableHeader.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts"]
5
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
6
- // CIL[DOC-MICRO logic_summary="Contains import statements for the page; no runtime logic." notable_decisions="[]"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
- // CIL[DOC-AUDIENCE audience="ai-coder"]
1
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/admin/APIKeysPage.tsx"]
2
+ /**
3
+ * @module APIKeysPage
4
+ * @audience internal
5
+ * @layer app-specific
6
+ * @stability stable
7
+ *
8
+ * This module represents the API Keys management page in the admin section of the application, allowing administrators to view, create, and manage API keys. INVARIANT: The user must have admin privileges to access this page.
9
+ *
10
+ * It integrates with various UI components to provide a seamless user experience for key management.
11
+ *
12
+ * @seeAlso LoadingSpinner (provides loading feedback).
13
+ * @seeAlso Button (used for actions).
14
+ * @seeAlso AdminListPage (displays a list of API keys).
15
+ * @seeAlso useApi (custom hook for API interactions).
16
+ *
17
+ * @cil-generated
18
+ */
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
10
28
 
11
29
 
12
30
 
13
31
 
14
32
  import React, { useState } from 'react'
33
+ import { useNavigate } from 'react-router-dom'
15
34
  import { Plus, Key, CheckCircle, Clock, ShieldCheck, RefreshCw } from 'lucide-react';
16
35
  import { LoadingSpinner } from '../../components/ui/LoadingSpinner'
17
36
  import { Button } from '../../components/ui/button'
18
37
  import { AdminListPage } from '../../components/admin/AdminListPage'
19
38
  import { SortableTableHeader } from '../../components/admin/SortableTableHeader'
20
39
 
21
- import { PageInstructions } from '../../components/admin/PageInstructions'
22
40
  import { formatDateTime } from '../../lib/utils'
23
41
  import { useApi } from '../../hooks/useApi'
24
42
  import { apiFetch } from '../../lib/api'
25
- // CIL[DOC-VECTOR type="context" content="purpose='Module header for the admin API keys list page, importing dependencies and defining the page component scope.'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/admin/AdminListPage.tsx"]
26
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
27
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
28
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
29
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
30
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
31
43
  // CIL[END stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:module_header:module_header"]
32
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:apikey:interface" type="interface" identity="apikey" parent="none"]
33
- // CIL[DOC-MACRO purpose="Define the TypeScript shape of an API key record."]
34
- // CIL[DOC-RESPONSIBILITY responsibility="Provide a typed interface for API key data."]
35
- // CIL[DOC-CONTEXT module="admin/api-keys" layer="page" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/admin/PageInstructions.tsx,.framework/src/components/admin/SortableTableHeader.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/APIKeysPage.tsx"]
36
- // CIL[DOC-CONTRACT inputs="none" outputs="APIKey type definition" errors="none" side_effects="none"]
37
- // CIL[DOC-MICRO logic_summary="Describes fields for an API key including id, name, key_type, is_active, usage, integration, and creator." notable_decisions="[]"]
38
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
39
- // CIL[DOC-STABILITY stability="stable"]
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:APIKey:interface" type="interface" identity="APIKey" parent="~/.framework/src/pages/admin/APIKeysPage.tsx"]
60
+ /**
61
+ * The APIKey interface defines the structure of an API key object used for managing access to services. It includes properties for identification, status, usage metrics, and associated integration details.
62
+ *
63
+ * @sideEffects none
64
+ * @stability stable
65
+ * @cil-generated
66
+ */
40
67
  interface APIKey {
41
68
  id: string
42
69
  name: string
@@ -58,23 +85,39 @@ interface APIKey {
58
85
  }
59
86
  created_at: string
60
87
  }
61
- // CIL[DOC-VECTOR type="context" content="purpose='Define the TypeScript shape of an API key record.'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/admin/AdminListPage.tsx"]
62
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
63
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
64
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
65
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
66
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
67
- // CIL[END stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:apikey:interface"]
68
-
69
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:apikeyspage:function" type="function" identity="apikeyspage" parent="none"]
70
- // CIL[DOC-MACRO purpose="Render the admin API keys list page with search, filtering, sorting, and usage statistics."]
71
- // CIL[DOC-RESPONSIBILITY responsibility="Display and filter API keys; handle row navigation."]
72
- // CIL[DOC-CONTEXT module="admin/api-keys" layer="page" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/admin/PageInstructions.tsx,.framework/src/components/admin/SortableTableHeader.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/APIKeysPage.tsx"]
73
- // CIL[DOC-CONTRACT inputs="none (React hook props and local state)" outputs="JSX page rendering" errors="Throws if API fetch fails (handled by useApi error state)" side_effects="Fetches /api/api-keys on mount; navigates on row click"]
74
- // CIL[DOC-MICRO logic_summary="Fetches API keys, applies search/status/type filters, sorts, and renders a SortableTableHeader table with stats cards and usage instructions." notable_decisions="[]"]
75
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
76
- // CIL[DOC-STABILITY stability="stable"]
88
+ // CIL[END stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:APIKey:interface"]
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:APIKeysPage:component" type="component" identity="APIKeysPage" parent="~/.framework/src/pages/admin/APIKeysPage.tsx"]
106
+ /**
107
+ * The APIKeysPage component manages the display and interaction with API keys, allowing users to filter, sort, and navigate to detailed views of individual keys. It fetches API keys from a server and provides statistics on their status and types.
108
+ *
109
+ * @macro Component for managing and displaying API keys with filtering and sorting capabilities.
110
+ * @micro Utilizes state management and hooks to handle API calls and dynamic updates based on user input.
111
+ * @outputSpec JSX.Element
112
+ * @throws Error — if the API fetch fails
113
+ * @sideEffects fetches data from external API endpoint '/api/api-keys?action=list'
114
+ * @stability stable
115
+ * @calls useApi, apiFetch, useNavigate
116
+ * @errorHandling throws an error if the API fetch fails
117
+ * @cil-generated
118
+ */
77
119
  export function APIKeysPage() {
120
+ const navigate = useNavigate()
78
121
  const [searchTerm, setSearchTerm] = useState('')
79
122
  const [selectedStatus, setSelectedStatus] = useState('all')
80
123
  const [selectedType, setSelectedType] = useState('all')
@@ -111,7 +154,7 @@ export function APIKeysPage() {
111
154
  }
112
155
 
113
156
  const handleRowClick = (key: APIKey) => {
114
- window.location.href = `/spine-framework/admin/configs/api-keys/${key.id}`
157
+ navigate(`/spine-framework/admin/configs/api-keys/${key.id}`)
115
158
  }
116
159
 
117
160
  const sortedKeys = [...(filteredKeys || [])].sort((a, b) => {
@@ -198,7 +241,6 @@ export function APIKeysPage() {
198
241
  <AdminListPage
199
242
  title="API Keys"
200
243
  description="Manage API keys and access tokens"
201
- noPageInstructions
202
244
  newButtonText="Generate API Key"
203
245
  newButtonHref="/spine-framework/admin/configs/api-keys/new"
204
246
  statsCards={statsCards}
@@ -211,47 +253,6 @@ export function APIKeysPage() {
211
253
  emptyMessage="No API keys found"
212
254
  emptyIcon={Key}
213
255
  >
214
- <PageInstructions
215
- title="API key usage instructions"
216
- description="API keys are generated tokens that authenticate external callers or service-to-service calls. The full key is shown once after creation. Copy it immediately and store it securely."
217
- sections={[
218
- { title: '1. Inbound webhooks (authenticate callers to Spine)', content: (
219
- <div className="space-y-2">
220
- <p className="text-sm text-slate-600">
221
- Create an <code className="text-xs bg-muted px-1 rounded">inbound</code> key, optionally bound to an Integration. Send the key in the request header to <code className="text-xs bg-muted px-1 rounded">/api/integration-routes</code>:
222
- </p>
223
- <pre className="text-xs bg-muted p-2 rounded overflow-auto font-mono">{`X-Api-Key: sk_...`}</pre>
224
- <p className="text-sm text-slate-600">
225
- The Integration Broker will validate the key and route the event to the adapter defined by the integration.
226
- </p>
227
- </div>
228
- )},
229
- { title: '2. Outbound / service calls (use a key instead of an env var)', content: (
230
- <div className="space-y-2">
231
- <p className="text-sm text-slate-600">
232
- You can use a literal key value in an integration's <code className="text-xs bg-muted px-1 rounded">credentials</code> instead of <code className="text-xs bg-muted px-1 rounded">env_var</code>. Create a key, copy the value, and paste it into the integration's credentials JSON with <code className="text-xs bg-muted px-1 rounded">source: "value"</code>:
233
- </p>
234
- <pre className="text-xs bg-muted p-2 rounded overflow-auto font-mono">{JSON.stringify({ api_token: { source: 'value', value: 'sk_...' } }, null, 2)}</pre>
235
- </div>
236
- )},
237
- { title: '3. Key types', content: (
238
- <div className="space-y-2">
239
- <ul className="text-sm text-slate-600 list-disc list-inside space-y-1">
240
- <li><strong>inbound</strong> — external services calling Spine (webhooks, API clients).</li>
241
- <li><strong>outbound</strong> — Spine services calling another system, often linked to an integration.</li>
242
- <li><strong>internal</strong> — internal Spine function-to-function calls.</li>
243
- <li><strong>cli</strong> — command-line scripts and tooling.</li>
244
- </ul>
245
- </div>
246
- )},
247
- { title: '4. Rate limits, scopes, and expiration', content: (
248
- <p className="text-sm text-slate-600">
249
- Use <code className="text-xs bg-muted px-1 rounded">rate_limit</code> to throttle usage, set <code className="text-xs bg-muted px-1 rounded">expires_at</code> for short-lived keys, and define <code className="text-xs bg-muted px-1 rounded">permissions</code> / <code className="text-xs bg-muted px-1 rounded">scopes</code> as JSON arrays to restrict what the key can do.
250
- </p>
251
- )},
252
- ]}
253
- />
254
-
255
256
  {sortedKeys.length === 0 ? (
256
257
  <div className="p-8 text-center">
257
258
  <Key className="mx-auto h-12 w-12 text-slate-400" />
@@ -372,10 +373,10 @@ export function APIKeysPage() {
372
373
  </AdminListPage>
373
374
  )
374
375
  }
375
- // CIL[DOC-VECTOR type="context" content="purpose='Render the admin API keys list page with search, filtering, sorting, and usage statistics.'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/admin/AdminListPage.tsx"]
376
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
377
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
378
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
379
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
380
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
381
- // CIL[END stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:apikeyspage:function"]
376
+ // CIL[END stable_id="~/.framework/src/pages/admin/APIKeysPage.tsx:APIKeysPage:component"]
377
+
378
+
379
+
380
+
381
+
382
+
@@ -1,4 +1,4 @@
1
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:module_header:module_header"]
1
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
2
2
  // CIL[DOC-MACRO purpose="Top-level module for the admin threshold alerts configuration page"]
3
3
  // CIL[DOC-RESPONSIBILITY responsibility="Provide imports and module context for the AlertsConfigPage and AlertModal components"]
4
4
  // CIL[DOC-CONTEXT module="admin/alerts" layer="page" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts"]
@@ -17,6 +17,7 @@
17
17
 
18
18
  import React, { useState } from 'react'
19
19
  import {
20
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:module_header:module_header"]
20
21
  Bell,
21
22
  Plus,
22
23
  Edit,
@@ -39,8 +40,6 @@ import { formatDateTime } from '../../lib/utils'
39
40
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
40
41
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
41
42
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
42
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:module_header:module_header"]
43
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:ThresholdAlert:interface"]
44
43
  // CIL[DOC-MACRO purpose="Describe the shape of a threshold alert record and its embedded data"]
45
44
  // CIL[DOC-RESPONSIBILITY responsibility="Define the ThresholdAlert TypeScript interface used across the alerts page"]
46
45
  // CIL[DOC-CONTEXT module="admin/alerts" layer="type" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AlertsConfigPage.tsx"]
@@ -48,6 +47,7 @@ import { formatDateTime } from '../../lib/utils'
48
47
  // CIL[DOC-MICRO logic_summary="Declares fields for alert identity, title, status, metric, operator, threshold, window, optional pipeline linkage, and timestamps" notable_decisions="[]"]
49
48
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
50
49
  // CIL[DOC-STABILITY stability="stable"]
50
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:ThresholdAlert:interface" type="interface" identity="ThresholdAlert" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
51
51
  interface ThresholdAlert {
52
52
  id: string
53
53
  title: string
@@ -64,15 +64,14 @@ interface ThresholdAlert {
64
64
  created_at: string
65
65
  updated_at: string
66
66
  }
67
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:ThresholdAlert:interface"]
67
68
  // CIL[DOC-VECTOR type="context" content="purpose='Describe the shape of a threshold alert record and its embedded data'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/Modal.tsx"]
68
69
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
69
70
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
70
71
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
71
72
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
72
73
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
73
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:ThresholdAlert:interface"]
74
74
 
75
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:Pipeline:interface"]
76
75
  // CIL[DOC-MACRO purpose="Describe a selectable pipeline reference"]
77
76
  // CIL[DOC-RESPONSIBILITY responsibility="Define the minimal Pipeline shape used for alert pipeline selection"]
78
77
  // CIL[DOC-CONTEXT module="admin/alerts" layer="type" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AlertsConfigPage.tsx"]
@@ -80,20 +79,20 @@ interface ThresholdAlert {
80
79
  // CIL[DOC-MICRO logic_summary="Declares id and name fields for pipeline dropdown options" notable_decisions="[]"]
81
80
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
82
81
  // CIL[DOC-STABILITY stability="stable"]
82
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:Pipeline:interface" type="interface" identity="Pipeline" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
83
83
  interface Pipeline {
84
84
  id: string
85
85
  name: string
86
86
  }
87
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:Pipeline:interface"]
87
88
  // CIL[DOC-VECTOR type="context" content="purpose='Describe a selectable pipeline reference'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/Modal.tsx"]
88
89
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
89
90
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
90
91
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
91
92
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
92
93
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
93
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:Pipeline:interface"]
94
94
 
95
95
 
96
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:alert_constants:constants"]
97
96
  // CIL[DOC-MACRO purpose="Provide human-readable labels and units for alert metrics and operators"]
98
97
  // CIL[DOC-RESPONSIBILITY responsibility="Supply display maps for metric names, operators, and units used in the alert list and modal"]
99
98
  // CIL[DOC-CONTEXT module="admin/alerts" layer="presentation" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AlertsConfigPage.tsx"]
@@ -101,30 +100,36 @@ interface Pipeline {
101
100
  // CIL[DOC-MICRO logic_summary="Defines METRIC_LABELS, OPERATOR_LABELS, and UNIT_LABELS records for rendering alert details" notable_decisions="[]"]
102
101
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
103
102
  // CIL[DOC-STABILITY stability="stable"]
103
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:METRIC_LABELS:constant" type="constant" identity="METRIC_LABELS" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
104
104
  const METRIC_LABELS: Record<string, string> = {
105
105
  error_rate: 'Error Rate',
106
106
  latency_p95: 'Latency (P95)',
107
107
  pipeline_failure_rate: 'Pipeline Failure Rate',
108
108
  }
109
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:METRIC_LABELS:constant"]
109
110
 
110
111
 
111
112
 
112
113
 
113
114
 
115
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:OPERATOR_LABELS:constant" type="constant" identity="OPERATOR_LABELS" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
114
116
  const OPERATOR_LABELS: Record<string, string> = {
115
117
  gt: '>',
116
118
  lt: '<',
117
119
  }
120
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:OPERATOR_LABELS:constant"]
118
121
 
119
122
 
120
123
 
121
124
 
122
125
 
126
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:UNIT_LABELS:constant" type="constant" identity="UNIT_LABELS" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
123
127
  const UNIT_LABELS: Record<string, string> = {
124
128
  error_rate: '%',
125
129
  latency_p95: 'ms',
126
130
  pipeline_failure_rate: '%',
127
131
  }
132
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:UNIT_LABELS:constant"]
128
133
 
129
134
 
130
135
 
@@ -134,8 +139,6 @@ const UNIT_LABELS: Record<string, string> = {
134
139
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
135
140
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
136
141
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
137
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:alert_constants:constants"]
138
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertsConfigPage:component"]
139
142
  // CIL[DOC-MACRO purpose="Admin page for listing, creating, editing, toggling, and deleting threshold alerts"]
140
143
  // CIL[DOC-RESPONSIBILITY responsibility="Render the alert list, fetch alert and pipeline data, and handle alert CRUD interactions"]
141
144
  // CIL[DOC-CONTEXT module="admin/alerts" layer="page" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AlertsConfigPage.tsx"]
@@ -143,10 +146,12 @@ const UNIT_LABELS: Record<string, string> = {
143
146
  // CIL[DOC-MICRO logic_summary="Loads alerts and pipelines with useApi, builds stat cards, renders AdminListPage, and provides handlers for save, delete, toggle, and edit actions" notable_decisions="[]"]
144
147
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
145
148
  // CIL[DOC-STABILITY stability="stable"]
149
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertsConfigPage:component" type="component" identity="AlertsConfigPage" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
146
150
  export function AlertsConfigPage() {
147
151
  const [isModalOpen, setIsModalOpen] = useState(false)
148
152
  const [editingAlert, setEditingAlert] = useState<ThresholdAlert | null>(null)
149
153
  const [isDeleting, setIsDeleting] = useState(false)
154
+ const [actionError, setActionError] = useState<string | null>(null)
150
155
 
151
156
  const { data: alerts, loading, error, refetch } = useApi<ThresholdAlert[]>(
152
157
  async () => {
@@ -205,7 +210,7 @@ export function AlertsConfigPage() {
205
210
  setEditingAlert(null)
206
211
  refetch()
207
212
  } catch (err) {
208
- alert(err instanceof Error ? err.message : 'Failed to save alert')
213
+ setActionError(err instanceof Error ? err.message : 'Failed to save alert')
209
214
  }
210
215
  }
211
216
 
@@ -219,7 +224,7 @@ export function AlertsConfigPage() {
219
224
  if (!response.ok) throw new Error('Failed to delete alert')
220
225
  refetch()
221
226
  } catch (err) {
222
- alert(err instanceof Error ? err.message : 'Failed to delete alert')
227
+ setActionError(err instanceof Error ? err.message : 'Failed to delete alert')
223
228
  }
224
229
  }
225
230
 
@@ -238,7 +243,7 @@ export function AlertsConfigPage() {
238
243
  if (!response.ok) throw new Error('Failed to toggle alert')
239
244
  refetch()
240
245
  } catch (err) {
241
- window.alert(err instanceof Error ? err.message : 'Failed to toggle alert')
246
+ setActionError(err instanceof Error ? err.message : 'Failed to toggle alert')
242
247
  }
243
248
  }
244
249
 
@@ -308,6 +313,12 @@ export function AlertsConfigPage() {
308
313
  newButtonText="Create Alert"
309
314
  onNewClick={openCreateModal}
310
315
  >
316
+ {actionError && (
317
+ <div className="mx-6 mt-4 rounded-md bg-red-50 border border-red-200 px-4 py-3 text-sm text-red-700 flex justify-between items-center">
318
+ <span>{actionError}</span>
319
+ <button onClick={() => setActionError(null)} className="text-red-500 hover:text-red-700 font-medium">Dismiss</button>
320
+ </div>
321
+ )}
311
322
  {alerts && alerts.length === 0 ? (
312
323
  <div className="p-8 text-center">
313
324
  <Bell className="mx-auto h-12 w-12 text-muted-foreground" />
@@ -401,6 +412,7 @@ export function AlertsConfigPage() {
401
412
  </AdminListPage>
402
413
  )
403
414
  }
415
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertsConfigPage:component"]
404
416
 
405
417
 
406
418
  // CIL[DOC-VECTOR type="context" content="purpose='Admin page for listing, creating, editing, toggling, and deleting threshold alerts'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/Modal.tsx"]
@@ -409,8 +421,6 @@ export function AlertsConfigPage() {
409
421
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
410
422
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
411
423
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
412
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertsConfigPage:component"]
413
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModalProps:interface"]
414
424
  // CIL[DOC-MACRO purpose="Props contract for the AlertModal form component"]
415
425
  // CIL[DOC-RESPONSIBILITY responsibility="Declare the properties passed to AlertModal"]
416
426
  // CIL[DOC-CONTEXT module="admin/alerts" layer="type" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AlertsConfigPage.tsx"]
@@ -418,6 +428,7 @@ export function AlertsConfigPage() {
418
428
  // CIL[DOC-MICRO logic_summary="Defines isOpen, onClose, onSave, alert, and pipelines props for the alert edit/create modal" notable_decisions="[]"]
419
429
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
420
430
  // CIL[DOC-STABILITY stability="stable"]
431
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModalProps:interface" type="interface" identity="AlertModalProps" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
421
432
  interface AlertModalProps {
422
433
  isOpen: boolean
423
434
  onClose: () => void
@@ -425,15 +436,14 @@ interface AlertModalProps {
425
436
  alert: ThresholdAlert | null
426
437
  pipelines: Pipeline[]
427
438
  }
439
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModalProps:interface"]
428
440
  // CIL[DOC-VECTOR type="context" content="purpose='Props contract for the AlertModal form component'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/Modal.tsx"]
429
441
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
430
442
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
431
443
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
432
444
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
433
445
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
434
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModalProps:interface"]
435
446
 
436
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModal:component"]
437
447
  // CIL[DOC-MACRO purpose="Modal form for creating and editing threshold alerts"]
438
448
  // CIL[DOC-RESPONSIBILITY responsibility="Render a controlled form, manage alert state, and call onSave with form data"]
439
449
  // CIL[DOC-CONTEXT module="admin/alerts" layer="component" related_files=".framework/src/components/admin/AdminListPage.tsx,.framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/button.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AlertsConfigPage.tsx"]
@@ -441,6 +451,7 @@ interface AlertModalProps {
441
451
  // CIL[DOC-MICRO logic_summary="Initializes form state, resets state when the alert or isOpen changes, and renders a form with metric, operator, threshold, window, optional pipeline, and active toggle fields" notable_decisions="[]"]
442
452
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
443
453
  // CIL[DOC-STABILITY stability="stable"]
454
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModal:component" type="component" identity="AlertModal" parent="~/.framework/src/pages/admin/AlertsConfigPage.tsx"]
444
455
  function AlertModal({ isOpen, onClose, onSave, alert, pipelines }: AlertModalProps) {
445
456
  const [formData, setFormData] = useState({
446
457
  title: '',
@@ -624,10 +635,10 @@ function AlertModal({ isOpen, onClose, onSave, alert, pipelines }: AlertModalPro
624
635
  </Modal>
625
636
  )
626
637
  }
638
+ // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModal:component"]
627
639
  // CIL[DOC-VECTOR type="context" content="purpose='Modal form for creating and editing threshold alerts'; No verified external callers; imports: .framework/src/components/ui/LoadingSpinner.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/Modal.tsx"]
628
640
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
629
641
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
630
642
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
631
643
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
632
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
633
- // CIL[END stable_id="~/.framework/src/pages/admin/AlertsConfigPage.tsx:AlertModal:component"]
644
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
@@ -1,4 +1,4 @@
1
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent=""]
1
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/admin/AppDetailPage.tsx"]
2
2
  // CIL[DOC-MACRO purpose="Top-level imports and module entry point for the AppDetailPage admin component."]
3
3
  // CIL[DOC-RESPONSIBILITY responsibility="Declare external dependencies for the App detail admin page."]
4
4
  // CIL[DOC-CONTEXT module="admin" layer="presentation" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/select.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts"]
@@ -25,6 +25,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/ca
25
25
  import { Skeleton } from '../../components/ui/skeleton'
26
26
  import { Alert, AlertDescription, AlertTitle } from '../../components/ui/alert'
27
27
  import {
28
+ // CIL[END stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:module_header:module_header"]
28
29
  Select,
29
30
  SelectContent,
30
31
  SelectItem,
@@ -33,16 +34,13 @@ import {
33
34
  } from '../../components/ui/select'
34
35
  import { ArrowLeft, Pencil, Trash2, AlertCircle } from 'lucide-react';
35
36
  import { formatDateTime } from '../../lib/utils'
36
- import { PageInstructions } from '../../components/admin/PageInstructions'
37
37
  // CIL[DOC-VECTOR type="context" content="purpose='Top-level imports and module entry point for the AppDetailPage admin component.'; No verified external callers; imports: .framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/components/ui/button.tsx"]
38
38
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
39
39
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
40
40
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
41
41
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
42
42
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
43
- // CIL[END stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:module_header:module_header"]
44
43
 
45
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:App:interface" type="interface" identity="App" parent="~/.framework/src/pages/admin/AppDetailPage.tsx:module_header:module_header"]
46
44
  // CIL[DOC-MACRO purpose="Define the App data contract used across the admin app detail page."]
47
45
  // CIL[DOC-RESPONSIBILITY responsibility="Provide a TypeScript type describing the shape of an app record."]
48
46
  // CIL[DOC-CONTEXT module="admin" layer="domain" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/select.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AppDetailPage.tsx"]
@@ -50,6 +48,7 @@ import { PageInstructions } from '../../components/admin/PageInstructions'
50
48
  // CIL[DOC-MICRO logic_summary="Declares the App interface with fields for metadata, configuration, and runtime settings." notable_decisions="[]"]
51
49
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
52
50
  // CIL[DOC-STABILITY stability="stable"]
51
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:App:interface" type="interface" identity="App" parent="~/.framework/src/pages/admin/AppDetailPage.tsx"]
53
52
  interface App {
54
53
  id: string
55
54
  slug: string
@@ -78,15 +77,14 @@ interface App {
78
77
  created_by?: string
79
78
  account_id?: string
80
79
  }
80
+ // CIL[END stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:App:interface"]
81
81
  // CIL[DOC-VECTOR type="context" content="purpose='Define the App data contract used across the admin app detail page.'; No verified external callers; imports: .framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/components/ui/button.tsx"]
82
82
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
83
83
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
84
84
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
85
85
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
86
86
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
87
- // CIL[END stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:App:interface"]
88
87
 
89
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:AppDetailPage:component" type="component" identity="AppDetailPage" parent="~/.framework/src/pages/admin/AppDetailPage.tsx:module_header:module_header"]
90
88
  // CIL[DOC-MACRO purpose="Render and manage the admin app create/edit/detail page."]
91
89
  // CIL[DOC-RESPONSIBILITY responsibility="Display app details, support editing and saving app configuration, and handle deletion."]
92
90
  // CIL[DOC-CONTEXT module="admin" layer="presentation" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/Modal.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/select.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/lib/utils.ts,.framework/src/pages/admin/AppDetailPage.tsx"]
@@ -94,6 +92,7 @@ interface App {
94
92
  // CIL[DOC-MICRO logic_summary="Fetches app by id, manages edit state and JSON config, renders form fields, and persists changes via API." notable_decisions="[]"]
95
93
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
96
94
  // CIL[DOC-STABILITY stability="stable"]
95
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:AppDetailPage:component" type="component" identity="AppDetailPage" parent="~/.framework/src/pages/admin/AppDetailPage.tsx"]
97
96
  export function AppDetailPage() {
98
97
  const { id } = useParams<{ id: string }>()
99
98
  const navigate = useNavigate()
@@ -348,59 +347,6 @@ export function AppDetailPage() {
348
347
  )}
349
348
  </div>
350
349
  </div>
351
-
352
- <PageInstructions
353
- description="Configure an app, its metadata, and runtime settings."
354
- sections={[
355
- { title: 'What this app controls', content: 'An app is a registered application in Spine. It controls navigation visibility, which people can use it, and the JSON configuration that the app or its runtime types consume.' },
356
- { title: 'Fields explained', content: <ul className="list-disc pl-4 space-y-1">
357
- <li><strong>Name</strong> — string. The display name in the app switcher and registry.</li>
358
- <li><strong>Slug</strong> — string. A unique URL-friendly identifier. Should be set at creation and rarely changed.</li>
359
- <li><strong>Description</strong> — string. Optional short text shown in the app list.</li>
360
- <li><strong>App Type</strong> — select. system, custom, or marketplace. Drives how the app is treated by the platform.</li>
361
- <li><strong>Source</strong> — select. system, custom, or marketplace. Tracks where the app package came from.</li>
362
- <li><strong>Min Role</strong> — select. member, admin, or owner. The lowest role that can see or access the app.</li>
363
- <li><strong>Version</strong> — string. The current app version shown in the registry.</li>
364
- <li><strong>Active</strong> — select true/false. Inactive apps are hidden and cannot be opened.</li>
365
- <li><strong>System</strong> — select true/false. Marks apps that are part of the platform and should not be treated as tenant-managed.</li>
366
- <li><strong>Icon</strong> — string. An icon name used by the UI. Invalid names show no icon.</li>
367
- <li><strong>Color</strong> — select. The theme color for the app tile.</li>
368
- <li><strong>Route Prefix</strong> — string. Optional URL prefix for the app (defaults to /slug).</li>
369
- <li><strong>Renderer</strong> — select. generic, custom, or none. generic uses the design schema to render pages.</li>
370
- <li><strong>Configuration (JSON)</strong> — JSON. Runtime configuration for the app or its generic renderer.</li>
371
- <li><strong>Nav Items (JSON)</strong> — JSON. Array of navigation items for the app shell.</li>
372
- <li><strong>Integration Deps (JSON)</strong> — JSON. Array of integration slugs the app depends on.</li>
373
- <li><strong>Metadata (JSON)</strong> — JSON. Free-form metadata associated with the app.</li>
374
- </ul> },
375
- { title: 'Options and values', content: <ul className="list-disc pl-4 space-y-1">
376
- <li><strong>Type/Source</strong>: <em>system</em> for built-in apps, <em>custom</em> for account-built apps, <em>marketplace</em> for installed apps.</li>
377
- <li><strong>Min Role</strong>: <em>member</em> is most permissive, <em>admin</em> for admins, <em>owner</em> for account owners.</li>
378
- <li><strong>Active</strong>: choose Active to publish, Inactive to hide.</li>
379
- <li><strong>System</strong>: choose System to protect the app from tenant deletion.</li>
380
- <li><strong>Color</strong>: blue, green, red, yellow, purple, pink, indigo, gray, slate.</li>
381
- </ul> },
382
- { title: 'Downstream impact', content: <ul className="list-disc pl-4 space-y-1">
383
- <li>The app registry and shell navigation read these fields to decide which apps to show and who can open them.</li>
384
- <li>Generic apps use the Configuration JSON and related types to render lists and detail pages.</li>
385
- <li>Custom apps may read the slug and config to initialize routes. A missing slug or bad config can break the app.</li>
386
- </ul> },
387
- { title: 'How to create, save, and validate', content: <ol className="list-decimal pl-4 space-y-1">
388
- <li>In create mode, fill the App Information card and enter a unique slug, then choose Type, Source, and Min Role.</li>
389
- <li>Edit the Configuration JSON with valid JSON; the form warns about invalid syntax on save.</li>
390
- <li>Click Create to save, or Save Changes when editing. Use Delete to remove the app after a confirmation.</li>
391
- <li>Validation checks required fields and that the Configuration JSON is parseable.</li>
392
- </ol> },
393
- { title: 'Common mistakes', content: <ul className="list-disc pl-4 space-y-1">
394
- <li>Reusing a slug that already exists, causing a unique constraint error.</li>
395
-
396
-
397
- <li>Switching an app to Inactive while people are using it.</li>
398
-
399
- <li>Pasting non-JSON text or trailing commas in the Configuration JSON.</li>
400
- </ul> },
401
- ]}
402
- />
403
-
404
350
  <Card>
405
351
  <CardHeader>
406
352
  <CardTitle>App Information</CardTitle>
@@ -607,10 +553,10 @@ export function AppDetailPage() {
607
553
  </div>
608
554
  )
609
555
  }
556
+ // CIL[END stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:AppDetailPage:component"]
610
557
  // CIL[DOC-VECTOR type="context" content="purpose='Render and manage the admin app create/edit/detail page.'; No verified external callers; imports: .framework/src/hooks/useApi.ts,.framework/src/lib/api.ts,.framework/src/components/ui/button.tsx"]
611
558
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
612
559
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
613
560
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
614
561
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
615
562
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
616
- // CIL[END stable_id="~/.framework/src/pages/admin/AppDetailPage.tsx:AppDetailPage:component"]