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.
- package/.env.example +13 -3
- package/.framework/cli/commands/bootstrap.ts +392 -0
- package/.framework/cli/commands/dev.ts +91 -218
- package/.framework/cli/commands/doctor.ts +132 -26
- package/.framework/cli/commands/generate.ts +38 -298
- package/.framework/cli/commands/init.ts +20 -1
- package/.framework/cli/commands/migrate.ts +36 -30
- package/.framework/cli/commands/migrations.ts +16 -56
- package/.framework/cli/commands/upgrade.ts +35 -0
- package/.framework/cli/commands/validate-schema.ts +147 -0
- package/.framework/cli/context.ts +223 -110
- package/.framework/cli/index.ts +6 -0
- package/.framework/cli/lib/project-files.ts +241 -1
- package/.framework/functions/_shared/agent-runner.ts +1000 -81
- package/.framework/functions/_shared/cil.ts +2 -1
- package/.framework/functions/_shared/db.ts +3 -6
- package/.framework/functions/_shared/hash-api-key.ts +183 -79
- package/.framework/functions/_shared/kb.ts +61 -7
- package/.framework/functions/_shared/logging.ts +562 -224
- package/.framework/functions/_shared/message-sequence.ts +53 -0
- package/.framework/functions/_shared/middleware.ts +47 -44
- package/.framework/functions/_shared/pipeline-runner.ts +150 -37
- package/.framework/functions/_shared/principal.ts +9 -6
- package/.framework/functions/_shared/trigger-engine.ts +149 -40
- package/.framework/functions/admin-data.ts +48 -31
- package/.framework/functions/ai-agents.ts +103 -33
- package/.framework/functions/api-keys.ts +301 -122
- package/.framework/functions/apps.ts +43 -26
- package/.framework/functions/cil-ingest.ts +48 -15
- package/.framework/functions/debug-auth.ts +14 -8
- package/.framework/functions/deliveries.ts +39 -12
- package/.framework/functions/embeddings.ts +145 -76
- package/.framework/functions/integration-outbound.ts +67 -27
- package/.framework/functions/integrations.ts +254 -127
- package/.framework/functions/logs.ts +273 -133
- package/.framework/functions/observability.ts +277 -147
- package/.framework/functions/pipeline-executions.ts +1 -1
- package/.framework/functions/pipeline-runner-background.ts +120 -0
- package/.framework/functions/pipelines.ts +14 -9
- package/.framework/functions/prompt-configs.ts +7 -4
- package/.framework/functions/roles.ts +8 -5
- package/.framework/functions/security.ts +30 -17
- package/.framework/functions/system-cron.ts +250 -128
- package/.framework/functions/tests.ts +7 -6
- package/.framework/functions/timers.ts +310 -107
- package/.framework/functions/trigger-scheduler.ts +65 -5
- package/.framework/functions/triggers.ts +28 -13
- package/.framework/functions/types.ts +13 -10
- package/.framework/migrations/064_episode_leases.sql +196 -0
- package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
- package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
- package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
- package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
- package/.framework/migrations/069_log_stats_window.sql +54 -0
- package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
- package/.framework/migrations/071_timer_interval_keys.sql +96 -0
- package/.framework/migrations/072_slug_autofill.sql +77 -0
- package/.framework/migrations/073_seed_member_roles.sql +26 -0
- package/.framework/schemas/spine.config.schema.json +62 -0
- package/.framework/src/App.tsx +3 -1
- package/.framework/src/apps/admin/index.tsx +1141 -775
- package/.framework/src/components/ErrorBoundary.tsx +136 -0
- package/.framework/src/components/admin/AdminListPage.tsx +81 -73
- package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
- package/.framework/src/components/admin/EntitySelect.tsx +181 -0
- package/.framework/src/components/admin/PageInstructions.tsx +86 -127
- package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
- package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
- package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
- package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
- package/.framework/src/components/layout/Layout.tsx +4 -2
- package/.framework/src/components/layout/Sidebar.tsx +304 -179
- package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
- package/.framework/src/components/runtime/DataHeader.tsx +96 -48
- package/.framework/src/components/runtime/DataListPage.tsx +3 -26
- package/.framework/src/components/runtime/DataStats.tsx +10 -10
- package/.framework/src/components/runtime/DataTable.tsx +12 -10
- package/.framework/src/components/ui/sheet.tsx +24 -26
- package/.framework/src/components/ui/textarea.tsx +74 -48
- package/.framework/src/hooks/useBranding.ts +47 -0
- package/.framework/src/hooks/useEntityList.ts +12 -9
- package/.framework/src/hooks/useListSchema.ts +108 -58
- package/.framework/src/instructions/README.md +57 -0
- package/.framework/src/instructions/ai-agents.md +69 -0
- package/.framework/src/instructions/alerts.md +80 -0
- package/.framework/src/instructions/api-keys.md +87 -0
- package/.framework/src/instructions/apps.md +77 -0
- package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
- package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
- package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
- package/.framework/src/instructions/concepts/automation.md +186 -0
- package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
- package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
- package/.framework/src/instructions/concepts/design-schema.md +152 -0
- package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
- package/.framework/src/instructions/concepts/observability.md +116 -0
- package/.framework/src/instructions/concepts/permissions.md +150 -0
- package/.framework/src/instructions/concepts/runtime-records.md +111 -0
- package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
- package/.framework/src/instructions/concepts/spine-way.md +172 -0
- package/.framework/src/instructions/deliveries.md +59 -0
- package/.framework/src/instructions/guide/00-orientation.md +106 -0
- package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
- package/.framework/src/instructions/guide/02-project-map.md +147 -0
- package/.framework/src/instructions/guide/03-domain-model.md +223 -0
- package/.framework/src/instructions/guide/04-first-app.md +227 -0
- package/.framework/src/instructions/guide/05-glossary.md +183 -0
- package/.framework/src/instructions/integrations.md +96 -0
- package/.framework/src/instructions/internal/cil-markers.md +83 -0
- package/.framework/src/instructions/invites.md +60 -0
- package/.framework/src/instructions/kb.md +80 -0
- package/.framework/src/instructions/logs.md +77 -0
- package/.framework/src/instructions/observability.md +61 -0
- package/.framework/src/instructions/operations/deployment.md +115 -0
- package/.framework/src/instructions/operations/migrations.md +125 -0
- package/.framework/src/instructions/operations/security-checklist.md +148 -0
- package/.framework/src/instructions/operations/troubleshooting.md +170 -0
- package/.framework/src/instructions/operations/upgrade.md +116 -0
- package/.framework/src/instructions/pipeline-executions.md +62 -0
- package/.framework/src/instructions/pipelines.md +78 -0
- package/.framework/src/instructions/prompts.md +95 -0
- package/.framework/src/instructions/reference/api/admin-data.md +162 -0
- package/.framework/src/instructions/reference/api/auth.md +113 -0
- package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
- package/.framework/src/instructions/reference/app-manifest.md +150 -0
- package/.framework/src/instructions/reference/cli.md +124 -0
- package/.framework/src/instructions/reference/database.md +132 -0
- package/.framework/src/instructions/reference/design-schema.md +280 -0
- package/.framework/src/instructions/reference/env-vars.md +133 -0
- package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
- package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
- package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
- package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
- package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
- package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
- package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
- package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
- package/.framework/src/instructions/reference/functions/apps.md +140 -0
- package/.framework/src/instructions/reference/functions/auth.md +99 -0
- package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
- package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
- package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
- package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
- package/.framework/src/instructions/reference/functions/index.md +103 -0
- package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
- package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
- package/.framework/src/instructions/reference/functions/integrations.md +130 -0
- package/.framework/src/instructions/reference/functions/invites.md +182 -0
- package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
- package/.framework/src/instructions/reference/functions/kb.md +166 -0
- package/.framework/src/instructions/reference/functions/logs.md +141 -0
- package/.framework/src/instructions/reference/functions/observability.md +105 -0
- package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
- package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
- package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
- package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
- package/.framework/src/instructions/reference/functions/roles.md +121 -0
- package/.framework/src/instructions/reference/functions/security.md +140 -0
- package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
- package/.framework/src/instructions/reference/functions/system.md +106 -0
- package/.framework/src/instructions/reference/functions/tests.md +97 -0
- package/.framework/src/instructions/reference/functions/timers.md +117 -0
- package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
- package/.framework/src/instructions/reference/functions/triggers.md +140 -0
- package/.framework/src/instructions/reference/functions/types.md +146 -0
- package/.framework/src/instructions/reference/seeds.md +126 -0
- package/.framework/src/instructions/reference/shared-modules.md +127 -0
- package/.framework/src/instructions/reference/spine-config.md +114 -0
- package/.framework/src/instructions/roles.md +80 -0
- package/.framework/src/instructions/runtime-detail.md +70 -0
- package/.framework/src/instructions/runtime-list.md +77 -0
- package/.framework/src/instructions/security.md +67 -0
- package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
- package/.framework/src/instructions/tasks/add-a-role.md +96 -0
- package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
- package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
- package/.framework/src/instructions/tasks/add-a-type.md +151 -0
- package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
- package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
- package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
- package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
- package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
- package/.framework/src/instructions/tasks/test-your-code.md +108 -0
- package/.framework/src/instructions/tasks/write-a-function.md +132 -0
- package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
- package/.framework/src/instructions/testing.md +59 -0
- package/.framework/src/instructions/timers.md +82 -0
- package/.framework/src/instructions/triggers.md +69 -0
- package/.framework/src/instructions/types.md +93 -0
- package/.framework/src/lib/branding.ts +128 -0
- package/.framework/src/pages/NoAppPage.tsx +3 -1
- package/.framework/src/pages/NotFoundPage.tsx +62 -31
- package/.framework/src/pages/SetupPage.tsx +5 -2
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
- package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
- package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
- package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
- package/.framework/src/pages/admin/AppsPage.tsx +104 -66
- package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
- package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
- package/.framework/src/pages/admin/LogsPage.tsx +144 -76
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
- package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
- package/.framework/src/pages/admin/RolesPage.tsx +86 -43
- package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
- package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
- package/.framework/src/pages/admin/TimersPage.tsx +90 -62
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
- package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
- package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
- package/.framework/src/pages/admin/TypesPage.tsx +90 -48
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
- package/.framework/src/pages/auth/LoginPage.tsx +4 -2
- package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
- package/.framework/templates/agent/AGENTS.md +150 -0
- package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
- package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
- package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
- package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
- package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
- package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
- package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
- package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
- package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
- package/.framework/templates/project.json +5 -1
- package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
- package/.framework/tests/unit/agent-files.test.ts +355 -0
- package/.framework/tests/unit/agent-runner.test.ts +496 -47
- package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
- package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
- package/.framework/tests/unit/bootstrap.test.ts +242 -0
- package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
- package/.framework/tests/unit/debug-auth.test.ts +38 -0
- package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
- package/.framework/tests/unit/episode-lease.test.ts +695 -0
- package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
- package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
- package/.framework/tests/unit/logging-app-id.test.ts +75 -0
- package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
- package/.framework/tests/unit/principal-cache.test.ts +15 -0
- package/.framework/tests/unit/system-context-denial.test.ts +145 -0
- package/.framework/tests/unit/system-cron.test.ts +240 -0
- package/.framework/tests/unit/timers.test.ts +159 -0
- package/.framework/tests/unit/trigger-engine.test.ts +278 -91
- package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
- package/README.md +125 -166
- package/config/tsconfig.cli.json +2 -2
- package/netlify.toml +5 -0
- package/package.json +15 -4
- package/templates/project/package-lock.json +2 -2
- package/.framework/docs/admin-routes.md +0 -76
- package/.framework/docs/api-docs-progress.md +0 -38
- package/.framework/docs/api-governance.md +0 -146
- package/.framework/docs/api-testing-results.md +0 -212
- package/.framework/docs/assembly-launch-guide.md +0 -138
- package/.framework/docs/audit-results.md +0 -590
- package/.framework/docs/db-api-inventory.md +0 -95
- package/.framework/docs/gap-remediation-backlog.md +0 -103
- package/.framework/docs/ui-adoption-verification.md +0 -111
- package/.framework/docs/ui-api-coverage.md +0 -84
- package/.framework/docs/v2-compatibility-audit.md +0 -228
- package/.framework/mcp/index.ts +0 -133
- package/.framework/mcp/load-env.ts +0 -60
- package/.framework/mcp/shared/app-manifest.ts +0 -275
- package/.framework/mcp/shared/db.ts +0 -477
- package/.framework/mcp/shared/kb.ts +0 -118
- package/.framework/mcp/tools/architect.ts +0 -431
- package/.framework/mcp/tools/cil/context.ts +0 -345
- package/.framework/mcp/tools/cil/graph.ts +0 -242
- package/.framework/mcp/tools/cil/ingest.ts +0 -1217
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
- package/.framework/mcp/tools/cil/pipeline.ts +0 -767
- package/.framework/mcp/tools/cil/project.ts +0 -791
- package/.framework/mcp/tools/cil/retrieval.ts +0 -336
- package/.framework/mcp/tools/cil/search-core.ts +0 -454
- package/.framework/mcp/tools/cil/search.ts +0 -97
- package/.framework/mcp/tools/cil/suggest.ts +0 -186
- package/.framework/mcp/tools/cil/validate.ts +0 -1369
- package/.framework/mcp/tools/kb/delete.ts +0 -139
- package/.framework/mcp/tools/kb/index.ts +0 -52
- package/.framework/mcp/tools/kb/ingest.ts +0 -84
- package/.framework/mcp/tools/kb/list-types.ts +0 -102
- package/.framework/mcp/tools/kb/publish.ts +0 -100
- package/.framework/mcp/tools/kb/reindex.ts +0 -86
- package/.framework/mcp/tools/kb/revoke.ts +0 -85
- package/.framework/mcp/tools/kb/search.ts +0 -101
- package/.framework/mcp/tools/kb/upsert.ts +0 -125
- 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="
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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[
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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[
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"]
|