spine-framework 0.4.4 → 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 (283) 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/hash-api-key.ts +183 -79
  15. package/.framework/functions/_shared/logging.ts +562 -224
  16. package/.framework/functions/_shared/middleware.ts +47 -44
  17. package/.framework/functions/admin-data.ts +39 -28
  18. package/.framework/functions/ai-agents.ts +10 -6
  19. package/.framework/functions/api-keys.ts +301 -122
  20. package/.framework/functions/apps.ts +43 -26
  21. package/.framework/functions/cil-ingest.ts +48 -15
  22. package/.framework/functions/debug-auth.ts +14 -8
  23. package/.framework/functions/deliveries.ts +39 -12
  24. package/.framework/functions/embeddings.ts +145 -76
  25. package/.framework/functions/integration-outbound.ts +67 -27
  26. package/.framework/functions/integrations.ts +254 -127
  27. package/.framework/functions/logs.ts +273 -133
  28. package/.framework/functions/observability.ts +277 -147
  29. package/.framework/functions/pipeline-executions.ts +1 -1
  30. package/.framework/functions/pipelines.ts +14 -9
  31. package/.framework/functions/prompt-configs.ts +7 -4
  32. package/.framework/functions/roles.ts +8 -5
  33. package/.framework/functions/security.ts +30 -17
  34. package/.framework/functions/system-cron.ts +240 -127
  35. package/.framework/functions/tests.ts +7 -6
  36. package/.framework/functions/timers.ts +310 -107
  37. package/.framework/functions/triggers.ts +28 -13
  38. package/.framework/functions/types.ts +13 -10
  39. package/.framework/migrations/069_log_stats_window.sql +54 -0
  40. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  41. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  42. package/.framework/migrations/072_slug_autofill.sql +77 -0
  43. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  44. package/.framework/src/apps/admin/index.tsx +1141 -775
  45. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  46. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  47. package/.framework/src/components/admin/AdminSidebar.tsx +88 -79
  48. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  49. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  50. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  51. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  52. package/.framework/src/components/layout/Sidebar.tsx +300 -177
  53. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  54. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  55. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  56. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  57. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  58. package/.framework/src/components/ui/sheet.tsx +24 -26
  59. package/.framework/src/components/ui/textarea.tsx +74 -48
  60. package/.framework/src/hooks/useEntityList.ts +12 -9
  61. package/.framework/src/hooks/useListSchema.ts +108 -58
  62. package/.framework/src/instructions/README.md +57 -0
  63. package/.framework/src/instructions/ai-agents.md +69 -0
  64. package/.framework/src/instructions/alerts.md +80 -0
  65. package/.framework/src/instructions/api-keys.md +87 -0
  66. package/.framework/src/instructions/apps.md +77 -0
  67. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  68. package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
  69. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  70. package/.framework/src/instructions/concepts/automation.md +186 -0
  71. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  72. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  73. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  74. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  75. package/.framework/src/instructions/concepts/observability.md +116 -0
  76. package/.framework/src/instructions/concepts/permissions.md +150 -0
  77. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  78. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  79. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  80. package/.framework/src/instructions/deliveries.md +59 -0
  81. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  82. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  83. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  84. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  85. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  86. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  87. package/.framework/src/instructions/integrations.md +96 -0
  88. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  89. package/.framework/src/instructions/invites.md +60 -0
  90. package/.framework/src/instructions/kb.md +80 -0
  91. package/.framework/src/instructions/logs.md +77 -0
  92. package/.framework/src/instructions/observability.md +61 -0
  93. package/.framework/src/instructions/operations/deployment.md +115 -0
  94. package/.framework/src/instructions/operations/migrations.md +125 -0
  95. package/.framework/src/instructions/operations/security-checklist.md +148 -0
  96. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  97. package/.framework/src/instructions/operations/upgrade.md +116 -0
  98. package/.framework/src/instructions/pipeline-executions.md +62 -0
  99. package/.framework/src/instructions/pipelines.md +78 -0
  100. package/.framework/src/instructions/prompts.md +95 -0
  101. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  102. package/.framework/src/instructions/reference/api/auth.md +113 -0
  103. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  104. package/.framework/src/instructions/reference/app-manifest.md +150 -0
  105. package/.framework/src/instructions/reference/cli.md +124 -0
  106. package/.framework/src/instructions/reference/database.md +132 -0
  107. package/.framework/src/instructions/reference/design-schema.md +280 -0
  108. package/.framework/src/instructions/reference/env-vars.md +133 -0
  109. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  110. package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
  111. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  112. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  113. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  114. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  115. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  116. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  117. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  118. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  119. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  120. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  121. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  122. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  123. package/.framework/src/instructions/reference/functions/index.md +103 -0
  124. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  125. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  126. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  127. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  128. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  129. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  130. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  131. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  132. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  133. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  134. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  135. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  136. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  137. package/.framework/src/instructions/reference/functions/security.md +140 -0
  138. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  139. package/.framework/src/instructions/reference/functions/system.md +106 -0
  140. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  141. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  142. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  143. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  144. package/.framework/src/instructions/reference/functions/types.md +146 -0
  145. package/.framework/src/instructions/reference/seeds.md +126 -0
  146. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  147. package/.framework/src/instructions/reference/spine-config.md +114 -0
  148. package/.framework/src/instructions/roles.md +80 -0
  149. package/.framework/src/instructions/runtime-detail.md +70 -0
  150. package/.framework/src/instructions/runtime-list.md +77 -0
  151. package/.framework/src/instructions/security.md +67 -0
  152. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  153. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  154. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  155. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  156. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  157. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  158. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  159. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  160. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  161. package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
  162. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  163. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  164. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  165. package/.framework/src/instructions/testing.md +59 -0
  166. package/.framework/src/instructions/timers.md +82 -0
  167. package/.framework/src/instructions/triggers.md +69 -0
  168. package/.framework/src/instructions/types.md +93 -0
  169. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  170. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  171. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  172. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  173. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  174. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  175. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  176. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  177. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  178. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  179. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  180. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  181. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  182. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  183. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  184. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  185. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  186. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  187. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  188. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  189. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  190. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  191. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  192. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  193. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  194. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  195. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  196. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  197. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  198. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  199. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  200. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  201. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  202. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  203. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  204. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  205. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  206. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  207. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  208. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  209. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  210. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  211. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  212. package/.framework/templates/agent/AGENTS.md +150 -0
  213. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  214. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  215. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  216. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  217. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
  218. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  219. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
  220. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
  221. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
  222. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  223. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  224. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  225. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  226. package/.framework/templates/project.json +4 -1
  227. package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
  228. package/.framework/tests/unit/agent-files.test.ts +355 -0
  229. package/.framework/tests/unit/agent-runner.test.ts +479 -44
  230. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  231. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  232. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  233. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  234. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  235. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  236. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  237. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  238. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  239. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  240. package/.framework/tests/unit/system-cron.test.ts +240 -0
  241. package/.framework/tests/unit/timers.test.ts +159 -0
  242. package/README.md +125 -166
  243. package/config/tsconfig.cli.json +2 -2
  244. package/package.json +15 -4
  245. package/templates/project/package-lock.json +2 -2
  246. package/.framework/docs/admin-routes.md +0 -76
  247. package/.framework/docs/api-docs-progress.md +0 -38
  248. package/.framework/docs/api-governance.md +0 -146
  249. package/.framework/docs/api-testing-results.md +0 -212
  250. package/.framework/docs/assembly-launch-guide.md +0 -138
  251. package/.framework/docs/audit-results.md +0 -590
  252. package/.framework/docs/db-api-inventory.md +0 -95
  253. package/.framework/docs/gap-remediation-backlog.md +0 -103
  254. package/.framework/docs/ui-adoption-verification.md +0 -111
  255. package/.framework/docs/ui-api-coverage.md +0 -84
  256. package/.framework/docs/v2-compatibility-audit.md +0 -228
  257. package/.framework/mcp/index.ts +0 -133
  258. package/.framework/mcp/load-env.ts +0 -60
  259. package/.framework/mcp/shared/app-manifest.ts +0 -275
  260. package/.framework/mcp/shared/db.ts +0 -477
  261. package/.framework/mcp/shared/kb.ts +0 -118
  262. package/.framework/mcp/tools/architect.ts +0 -431
  263. package/.framework/mcp/tools/cil/context.ts +0 -345
  264. package/.framework/mcp/tools/cil/graph.ts +0 -242
  265. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  266. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  267. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  268. package/.framework/mcp/tools/cil/project.ts +0 -791
  269. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  270. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  271. package/.framework/mcp/tools/cil/search.ts +0 -97
  272. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  273. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  274. package/.framework/mcp/tools/kb/delete.ts +0 -139
  275. package/.framework/mcp/tools/kb/index.ts +0 -52
  276. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  277. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  278. package/.framework/mcp/tools/kb/publish.ts +0 -100
  279. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  280. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  281. package/.framework/mcp/tools/kb/search.ts +0 -101
  282. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  283. package/.framework/mcp/tools/observability.ts +0 -510
@@ -1,12 +1,28 @@
1
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent=""]
2
- // CIL[DOC-MACRO purpose="Defines the admin API key detail/create page module and imports its dependencies."]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Provides the React page component, UI primitives, hooks, and utilities for creating and viewing API keys in the admin console."]
4
- // CIL[DOC-CONTEXT module="api-key-management" layer="pages/admin" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/label.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"]
5
- // CIL[DOC-CONTRACT inputs="none" outputs="TSX page module" errors="none" side_effects="none"]
6
- // CIL[DOC-MICRO logic_summary="Imports React, router, UI components, icons, hooks, and utilities for the API key detail page." notable_decisions="[]"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
- // CIL[DOC-AUDIENCE audience="developers, ai"]
1
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx"]
2
+ /**
3
+ * @module APIKeyDetailPage
4
+ * @audience both
5
+ * @layer shared-core
6
+ * @stability stable
7
+ *
8
+ * This module provides the UI for managing API keys within the admin section of the application. It allows users to view, create, and delete API keys, handling state and side effects related to API interactions.
9
+ * INVARIANT: Users must have appropriate permissions to access this page and perform actions on API keys.
10
+ *
11
+ * @seeAlso useApi (custom hook for API interactions).
12
+ * @seeAlso apiFetch (utility for making API requests).
13
+ * @seeAlso PageInstructions (provides guidance on using the page).
14
+ *
15
+ * @cil-generated
16
+ */
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
10
26
 
11
27
 
12
28
 
@@ -20,6 +36,7 @@ import { Textarea } from '../../components/ui/textarea'
20
36
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../components/ui/select'
21
37
  import { Checkbox } from '../../components/ui/checkbox'
22
38
  import { Label } from '../../components/ui/label'
39
+ import { AppSelect } from '../../components/admin/EntitySelect'
23
40
  import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card'
24
41
  import { Skeleton } from '../../components/ui/skeleton'
25
42
  import { Alert, AlertDescription, AlertTitle } from '../../components/ui/alert'
@@ -27,30 +44,37 @@ import { ArrowLeft, Key, RefreshCw, Trash2, AlertCircle, Copy, Check } from 'luc
27
44
  import { useApi } from '../../hooks/useApi'
28
45
  import { apiFetch } from '../../lib/api'
29
46
  import { formatDateTime } from '../../lib/utils'
30
- import { PageInstructions } from '../../components/admin/PageInstructions'
31
-
32
- // CIL[DOC-VECTOR type="context" content="purpose='Defines the admin API key detail/create page module and imports its dependencies.'; No verified external callers; imports: .framework/src/components/ui/button.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/textarea.tsx"]
33
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
34
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
35
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
36
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
37
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
38
47
  // CIL[END stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:module_header:module_header"]
39
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKey:interface" type="interface" identity="APIKey" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:module_header:module_header"]
40
- // CIL[DOC-MACRO purpose="Defines the API key record shape used by the admin detail page."]
41
- // CIL[DOC-RESPONSIBILITY responsibility="Provides the TypeScript contract for API key objects loaded, edited, and rendered by the page."]
42
- // CIL[DOC-CONTEXT module="api-key-management" layer="pages/admin" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/label.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/APIKeyDetailPage.tsx"]
43
- // CIL[DOC-CONTRACT inputs="none" outputs="interface type" errors="none" side_effects="none"]
44
- // CIL[DOC-MICRO logic_summary="Describes all fields on an API key including id, name, key_type, rate_limit, permissions, scopes, metadata, machine_type, created_by, and timestamps." notable_decisions="[]"]
45
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
46
- // CIL[DOC-STABILITY stability="stable"]
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKey:interface" type="interface" identity="APIKey" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx"]
65
+ /**
66
+ * The APIKey interface defines the structure of an API key object used within the application, encapsulating its properties and metadata. It provides a consistent representation of API keys across the system.
67
+ *
68
+ * @sideEffects none
69
+ * @stability internal
70
+ * @cil-generated
71
+ */
47
72
  interface APIKey {
48
73
  id: string
49
74
  name: string
50
75
  integration_id?: string
51
76
  app_id?: string
52
77
  key_type: 'inbound' | 'outbound' | 'internal' | 'cli'
53
- key_value?: string
54
78
  key_prefix: string
55
79
  is_active: boolean
56
80
  permissions?: Record<string, any>
@@ -66,46 +90,69 @@ interface APIKey {
66
90
  created_at: string
67
91
  updated_at: string
68
92
  }
69
- // CIL[DOC-VECTOR type="context" content="purpose='Defines the API key record shape used by the admin detail page.'; No verified external callers; imports: .framework/src/components/ui/button.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/textarea.tsx"]
70
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
71
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
72
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
73
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
74
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
75
93
  // CIL[END stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKey:interface"]
76
94
 
77
95
 
78
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:KEY_TYPE_OPTIONS:constant" type="constant" identity="KEY_TYPE_OPTIONS" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:module_header:module_header"]
79
- // CIL[DOC-MACRO purpose="Defines the selectable labels for API key types."]
80
- // CIL[DOC-RESPONSIBILITY responsibility="Maps key type values to human-readable labels shown in the Key Type select control."]
81
- // CIL[DOC-CONTEXT module="api-key-management" layer="pages/admin" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/label.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/APIKeyDetailPage.tsx"]
82
- // CIL[DOC-CONTRACT inputs="none" outputs="constant array of option objects" errors="none" side_effects="none"]
83
- // CIL[DOC-MICRO logic_summary="Array of option objects with value and label for inbound, outbound, internal, and cli key types." notable_decisions="[]"]
84
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
85
- // CIL[DOC-STABILITY stability="stable"]
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:KEY_TYPE_OPTIONS:constant" type="constant" identity="KEY_TYPE_OPTIONS" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx"]
112
+ /**
113
+ * KEY_TYPE_OPTIONS defines a structured set of options for categorizing different types of API keys used in the application. It helps in organizing keys based on their intended use cases.
114
+ *
115
+ * @sideEffects none
116
+ * @stability internal
117
+ * @cil-generated
118
+ */
86
119
  const KEY_TYPE_OPTIONS = [
87
120
  { value: 'inbound', label: 'Inbound (External callers to Spine)' },
88
121
  { value: 'outbound', label: 'Outbound (Spine to external services)' },
89
122
  { value: 'internal', label: 'Internal (Spine-to-Spine)' },
90
123
  { value: 'cli', label: 'CLI / Script' }
91
124
  ]
92
- // CIL[DOC-VECTOR type="context" content="purpose='Defines the selectable labels for API key types.'; No verified external callers; imports: .framework/src/components/ui/button.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/textarea.tsx"]
93
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
94
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
95
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
96
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
97
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
98
125
  // CIL[END stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:KEY_TYPE_OPTIONS:constant"]
99
126
 
100
127
 
101
- // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKeyDetailPage:component" type="component" identity="APIKeyDetailPage" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:module_header:module_header"]
102
- // CIL[DOC-MACRO purpose="Renders the admin page for creating a new API key and viewing an existing API key."]
103
- // CIL[DOC-RESPONSIBILITY responsibility="Handles form state, API fetch, submission, JSON parsing, and rendering the create/read-only UI for API keys."]
104
- // CIL[DOC-CONTEXT module="api-key-management" layer="pages/admin" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/alert.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/label.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/APIKeyDetailPage.tsx"]
105
- // CIL[DOC-CONTRACT inputs="route id parameter, API key response, user form input" outputs="TSX UI, navigation" errors="fetchError, form validation and submission errors, JSON parse errors" side_effects="POST to /api/api-keys, navigator.clipboard.writeText, setTimeout navigation, React state changes"]
106
- // CIL[DOC-MICRO logic_summary="Renders the admin page for creating or viewing API keys. Manages form state with useState and useEffect, fetches the API key via useApi, parses JSON inputs for permissions, scopes and metadata, submits to /api/api-keys, shows a generated key once, and renders read-only summary or error alerts." notable_decisions="[\"Uses separate JSON string state for permissions, scopes, and metadata to allow text editing.\",\"Existing API keys are shown read-only with the key value masked.\",\"Only the create mode handles submission and receives a one-time generated key.\"]"]
107
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
108
- // CIL[DOC-STABILITY stability="stable"]
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKeyDetailPage:component" type="component" identity="APIKeyDetailPage" parent="~/.framework/src/pages/admin/APIKeyDetailPage.tsx"]
144
+ /**
145
+ * The APIKeyDetailPage component manages the creation and editing of API keys, providing a user interface for inputting key details and submitting them to the server. It handles both the retrieval of existing API key data and the submission of new or updated key information.
146
+ *
147
+ * @macro Component responsible for managing API key details in an admin interface.
148
+ * @micro Utilizes React hooks for state management and side effects, including fetching API key data and handling form submissions.
149
+ * @outputSpec JSX.Element — renders the API key detail page UI
150
+ * @sideEffects Makes API calls to fetch and submit API key data
151
+ * @stability internal
152
+ * @calls useParams, useNavigate, useApi, apiFetch
153
+ * @errorHandling none
154
+ * @cil-generated
155
+ */
109
156
  export function APIKeyDetailPage() {
110
157
  const { id } = useParams<{ id: string }>()
111
158
  const navigate = useNavigate()
@@ -131,7 +178,9 @@ export function APIKeyDetailPage() {
131
178
  const [isSubmitting, setIsSubmitting] = useState(false)
132
179
  const [error, setError] = useState<string | null>(null)
133
180
  const [generatedKey, setGeneratedKey] = useState<string | null>(null)
181
+ const [createdKeyId, setCreatedKeyId] = useState<string | null>(null)
134
182
  const [copied, setCopied] = useState(false)
183
+ const [isRevoking, setIsRevoking] = useState(false)
135
184
 
136
185
  const { data: apiKey, loading, error: fetchError } = useApi<APIKey>(
137
186
  async () => {
@@ -186,8 +235,8 @@ export function APIKeyDetailPage() {
186
235
  })
187
236
  if (!response.ok) throw new Error('Failed to create API key')
188
237
  const result = await response.json()
189
- setGeneratedKey(result.key_value || result.data?.key_value)
190
- setTimeout(() => navigate(`/spine-framework/admin/configs/api-keys/${result.id || result.data?.id}`), 3000)
238
+ setGeneratedKey(result.data?.raw_key ?? result.raw_key)
239
+ setCreatedKeyId(result.id || result.data?.id)
191
240
  } catch (err) {
192
241
  setError(err instanceof Error ? err.message : 'Failed to create API key')
193
242
  } finally {
@@ -221,49 +270,6 @@ export function APIKeyDetailPage() {
221
270
  <Button variant="ghost" onClick={() => navigate(-1)}><ArrowLeft className="h-5 w-5" /></Button>
222
271
  <h1 className="text-2xl font-bold">{apiKey.name}</h1>
223
272
  </div>
224
- <PageInstructions
225
- description="Create an API key and set its permissions, rate limits, and expiration."
226
- sections={[
227
- { title: 'What this API key controls', content: 'API keys authenticate callers to Spine. A key controls which callers are accepted, how fast they can call, and which permissions they carry.' },
228
- { title: 'Fields explained', content: <ul className="list-disc pl-4 space-y-1">
229
- <li><strong>Name</strong> — string, required. A human-readable label. Missing name blocks creation.</li>
230
- <li><strong>Integration ID</strong> — string. Optional UUID of the integration this key is for.</li>
231
- <li><strong>App ID</strong> — string. Optional UUID of the owning app.</li>
232
- <li><strong>Key Type</strong> — select. inbound, outbound, internal, or cli. Determines which direction the key is used and how it is validated.</li>
233
- <li><strong>Prefix</strong> — string. The public prefix that appears before the generated secret. Default is "sk_". The create API may override this with the generated prefix.</li>
234
- <li><strong>Rate Limit (requests/min)</strong> — number 1-10000. Enforces a cap on calls per minute. Missing or 0 may prevent usage.</li>
235
- <li><strong>Expires At</strong> — date. Optional expiration. After this date the key is rejected.</li>
236
- <li><strong>Machine Type</strong> — string. The machine principal type, e.g. integration.</li>
237
- <li><strong>Internal</strong> — checkbox. Marks a key for internal service-to-service use.</li>
238
- <li><strong>Active</strong> — checkbox. Inactive keys are rejected.</li>
239
- <li><strong>Permissions (JSON)</strong> — JSON object. Defines allowed actions/resources. Invalid JSON fails creation.</li>
240
- <li><strong>Scopes (JSON)</strong> — JSON array of scope strings. Invalid JSON fails creation.</li>
241
- <li><strong>Metadata (JSON)</strong> — JSON object. Optional notes such as environment. Invalid JSON fails creation.</li>
242
- </ul> },
243
- { title: 'Options and values', content: <ul className="list-disc pl-4 space-y-1">
244
- <li><strong>inbound</strong>: External callers into Spine APIs.</li>
245
- <li><strong>outbound</strong>: Spine calling external services.</li>
246
- <li><strong>internal</strong>: Service-to-service calls within Spine.</li>
247
- <li><strong>cli</strong>: Scripts or command-line tooling.</li>
248
- </ul> },
249
- { title: 'Downstream impact', content: <ul className="list-disc pl-4 space-y-1">
250
- <li>API gateway validates the key on every call. An inactive, expired, or missing key is rejected.</li>
251
- <li>Rate limits are enforced at the edge; a misconfigured limit may throttle or deny callers.</li>
252
- <li>Permission JSON is parsed and used for authorization checks. Badly shaped permissions may grant too much or too little access.</li>
253
- </ul> },
254
- { title: 'How to create, save, and validate', content: <ol className="list-decimal pl-4 space-y-1">
255
- <li>Only create mode is available; existing keys are shown read-only with the value masked.</li>
256
- <li>Fill Name, Key Type, and Rate Limit. Provide valid JSON for Permissions and Metadata.</li>
257
- <li>Submit the form. A one-time key is generated and shown; copy it immediately because it cannot be retrieved again.</li>
258
- <li>Validation checks required fields, rate limit range, and valid JSON.</li>
259
- </ol> },
260
- { title: 'Common mistakes', content: <ul className="list-disc pl-4 space-y-1">
261
- <li>Forgetting to copy the generated key before leaving the page.</li>
262
- <li>Entering Permissions as a comma-separated list instead of JSON.</li>
263
- <li>Setting Rate Limit to 0, which blocks all requests.</li>
264
- </ul> },
265
- ]}
266
- />
267
273
  <Card><CardContent className="p-6">
268
274
  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
269
275
  <div className="flex justify-between"><span className="text-muted-foreground">Key Type</span><span>{apiKey.key_type}</span></div>
@@ -273,8 +279,46 @@ export function APIKeyDetailPage() {
273
279
  <div className="flex justify-between"><span className="text-muted-foreground">Usage</span><span>{apiKey.usage_count} requests</span></div>
274
280
  <div className="flex justify-between"><span className="text-muted-foreground">Created</span><span>{formatDateTime(apiKey.created_at)}</span></div>
275
281
  </div>
276
- <div className="mt-4"><span className="text-muted-foreground">Key Value</span><div className="mt-1 font-mono text-sm bg-muted p-3 rounded">{apiKey.key_value || '***'}</div></div>
277
282
  </CardContent></Card>
283
+ {apiKey.is_active && (
284
+ <div className="flex justify-end">
285
+ <Button
286
+ variant="destructive"
287
+ disabled={isRevoking}
288
+ onClick={async () => {
289
+ if (!confirm('Revoke this API key? It will stop working immediately.')) return
290
+ setIsRevoking(true)
291
+ try {
292
+ /**
293
+ * The constant 'res' holds the response from an API call to revoke an API key, determining the success of the operation and handling navigation. It is essential for managing the revocation process of API keys.
294
+ *
295
+ * @throws Error — if the response is not ok, indicating a failure to revoke the API key.
296
+ * @sideEffects Makes an external API call to '/api/api-keys?action=revoke'.
297
+ * @stability internal
298
+ * @calls apiFetch, navigate
299
+ * @errorHandling Alerts the user with an error message if the revocation fails.
300
+ * @cil-generated
301
+ */
302
+ const res = await apiFetch('/api/api-keys?action=revoke', {
303
+ method: 'POST',
304
+ headers: { 'Content-Type': 'application/json' },
305
+ body: JSON.stringify({ id: apiKey.id }),
306
+ })
307
+ if (!res.ok) throw new Error('Failed to revoke API key')
308
+ navigate('/spine-framework/admin/configs/api-keys')
309
+ } catch (err) {
310
+ setError(err instanceof Error ? err.message : 'Failed to revoke API key')
311
+ } finally {
312
+ setIsRevoking(false)
313
+ }
314
+ }}
315
+ >
316
+ <Trash2 className="h-4 w-4 mr-2" />
317
+ {isRevoking ? 'Revoking…' : 'Revoke Key'}
318
+ </Button>
319
+ </div>
320
+ )}
321
+ {error && <Alert variant="destructive"><AlertCircle className="h-4 w-4" /><AlertTitle>Error</AlertTitle><AlertDescription>{error}</AlertDescription></Alert>}
278
322
  </div>
279
323
  )
280
324
  }
@@ -287,7 +331,7 @@ export function APIKeyDetailPage() {
287
331
  <Alert><AlertCircle className="h-4 w-4" /><AlertTitle>Save this key now</AlertTitle><AlertDescription>You won't be able to see it again. Copy it now and store it securely.</AlertDescription></Alert>
288
332
  <Card><CardContent className="p-6">
289
333
  <div className="flex items-center gap-2"><code className="flex-1 bg-muted p-4 rounded font-mono text-lg">{generatedKey}</code><Button size="icon" onClick={handleCopy}>{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}</Button></div>
290
- <Button className="mt-4" onClick={() => navigate('/spine-framework/admin/configs/api-keys')}>Done</Button>
334
+ <Button className="mt-4" onClick={() => navigate(`/spine-framework/admin/configs/api-keys/${createdKeyId}`)}>Done</Button>
291
335
  </CardContent></Card>
292
336
  </div>
293
337
  )
@@ -299,49 +343,6 @@ export function APIKeyDetailPage() {
299
343
  <Button variant="ghost" onClick={() => navigate(-1)}><ArrowLeft className="h-5 w-5" /></Button>
300
344
  <h1 className="text-2xl font-bold">Create API Key</h1>
301
345
  </div>
302
- <PageInstructions
303
- description="Create an API key and set its permissions, rate limits, and expiration."
304
- sections={[
305
- { title: 'What this API key controls', content: 'API keys authenticate callers to Spine. A key controls which callers are accepted, how fast they can call, and which permissions they carry.' },
306
- { title: 'Fields explained', content: <ul className="list-disc pl-4 space-y-1">
307
- <li><strong>Name</strong> — string, required. A human-readable label. Missing name blocks creation.</li>
308
- <li><strong>Integration ID</strong> — string. Optional UUID of the integration this key is for.</li>
309
- <li><strong>App ID</strong> — string. Optional UUID of the owning app.</li>
310
- <li><strong>Key Type</strong> — select. inbound, outbound, internal, or cli. Determines which direction the key is used and how it is validated.</li>
311
- <li><strong>Prefix</strong> — string. The public prefix that appears before the generated secret. Default is "sk_". The create API may override this with the generated prefix.</li>
312
- <li><strong>Rate Limit (requests/min)</strong> — number 1-10000. Enforces a cap on calls per minute. Missing or 0 may prevent usage.</li>
313
- <li><strong>Expires At</strong> — date. Optional expiration. After this date the key is rejected.</li>
314
- <li><strong>Machine Type</strong> — string. The machine principal type, e.g. integration.</li>
315
- <li><strong>Internal</strong> — checkbox. Marks a key for internal service-to-service use.</li>
316
- <li><strong>Active</strong> — checkbox. Inactive keys are rejected.</li>
317
- <li><strong>Permissions (JSON)</strong> — JSON object. Defines allowed actions/resources. Invalid JSON fails creation.</li>
318
- <li><strong>Scopes (JSON)</strong> — JSON array of scope strings. Invalid JSON fails creation.</li>
319
- <li><strong>Metadata (JSON)</strong> — JSON object. Optional notes such as environment. Invalid JSON fails creation.</li>
320
- </ul> },
321
- { title: 'Options and values', content: <ul className="list-disc pl-4 space-y-1">
322
- <li><strong>inbound</strong>: External callers into Spine APIs.</li>
323
- <li><strong>outbound</strong>: Spine calling external services.</li>
324
- <li><strong>internal</strong>: Service-to-service calls within Spine.</li>
325
- <li><strong>cli</strong>: Scripts or command-line tooling.</li>
326
- </ul> },
327
- { title: 'Downstream impact', content: <ul className="list-disc pl-4 space-y-1">
328
- <li>API gateway validates the key on every call. An inactive, expired, or missing key is rejected.</li>
329
- <li>Rate limits are enforced at the edge; a misconfigured limit may throttle or deny callers.</li>
330
- <li>Permission JSON is parsed and used for authorization checks. Badly shaped permissions may grant too much or too little access.</li>
331
- </ul> },
332
- { title: 'How to create, save, and validate', content: <ol className="list-decimal pl-4 space-y-1">
333
- <li>Only create mode is available; existing keys are shown read-only with the value masked.</li>
334
- <li>Fill Name, Key Type, and Rate Limit. Provide valid JSON for Permissions and Metadata.</li>
335
- <li>Submit the form. A one-time key is generated and shown; copy it immediately because it cannot be retrieved again.</li>
336
- <li>Validation checks required fields, rate limit range, and valid JSON.</li>
337
- </ol> },
338
- { title: 'Common mistakes', content: <ul className="list-disc pl-4 space-y-1">
339
- <li>Forgetting to copy the generated key before leaving the page.</li>
340
- <li>Entering Permissions as a comma-separated list instead of JSON.</li>
341
- <li>Setting Rate Limit to 0, which blocks all requests.</li>
342
- </ul> },
343
- ]}
344
- />
345
346
  {error && <Alert variant="destructive"><AlertCircle className="h-4 w-4" /><AlertTitle>Error</AlertTitle><AlertDescription>{error}</AlertDescription></Alert>}
346
347
  <form onSubmit={handleSubmit} className="space-y-6">
347
348
  <Card><CardContent className="p-6 space-y-4">
@@ -349,7 +350,7 @@ export function APIKeyDetailPage() {
349
350
  <div className="space-y-2"><Label>Name *</Label><Input value={formData.name} onChange={e => setFormData({...formData, name: e.target.value})} required placeholder="e.g., Production API Key" /></div>
350
351
  <div className="space-y-2"><Label>Key Type</Label><Select value={formData.key_type} onValueChange={v => setFormData({...formData, key_type: v as 'inbound' | 'outbound' | 'internal' | 'cli'})}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent>{KEY_TYPE_OPTIONS.map(opt => <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>)}</SelectContent></Select></div>
351
352
  <div className="space-y-2"><Label>Integration ID</Label><Input value={formData.integration_id} onChange={e => setFormData({...formData, integration_id: e.target.value})} placeholder="Optional integration UUID" /></div>
352
- <div className="space-y-2"><Label>App ID</Label><Input value={formData.app_id} onChange={e => setFormData({...formData, app_id: e.target.value})} placeholder="Optional app UUID" /></div>
353
+ <div className="space-y-2"><Label>App</Label><AppSelect value={formData.app_id} onChange={v => setFormData({...formData, app_id: v})} /></div>
353
354
  <div className="space-y-2"><Label>Prefix</Label><Input value={formData.key_prefix} onChange={e => setFormData({...formData, key_prefix: e.target.value})} placeholder="e.g., sk_" /></div>
354
355
  <div className="space-y-2"><Label>Rate Limit (requests/min)</Label><Input type="number" value={formData.rate_limit} onChange={e => setFormData({...formData, rate_limit: parseInt(e.target.value)})} min={1} max={10000} /></div>
355
356
  <div className="space-y-2"><Label>Expires At</Label><Input type="date" value={formData.expires_at} onChange={e => setFormData({...formData, expires_at: e.target.value})} /></div>
@@ -368,10 +369,10 @@ export function APIKeyDetailPage() {
368
369
  </div>
369
370
  )
370
371
  }
371
- // CIL[DOC-VECTOR type="context" content="purpose='Renders the admin page for creating a new API key and viewing an existing API key.'; No verified external callers; imports: .framework/src/components/ui/button.tsx,.framework/src/components/ui/input.tsx,.framework/src/components/ui/textarea.tsx"]
372
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
373
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
374
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
375
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
376
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
377
- // CIL[END stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKeyDetailPage:component"]
372
+ // CIL[END stable_id="~/.framework/src/pages/admin/APIKeyDetailPage.tsx:APIKeyDetailPage:component"]
373
+
374
+
375
+
376
+
377
+
378
+