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,4 +1,20 @@
|
|
|
1
1
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/functions/api-keys.ts"]
|
|
2
|
+
/**
|
|
3
|
+
* @module api-keys
|
|
4
|
+
* @audience both
|
|
5
|
+
* @layer shared-core
|
|
6
|
+
* @stability stable
|
|
7
|
+
*
|
|
8
|
+
* This module manages API key operations, including creation and validation, as part of the system's security framework. It serves as a middleware handler that interacts with the database and performs necessary logging and permission checks. INVARIANT: All API key operations require system admin privileges. Route patterns include /api/keys for key management operations.
|
|
9
|
+
*
|
|
10
|
+
* @seeAlso middleware.ts (provides request handling functionality).
|
|
11
|
+
* @seeAlso db.ts (interacts with the database for key storage).
|
|
12
|
+
* @seeAlso audit.ts (handles logging of operations).
|
|
13
|
+
* @seeAlso permissions.ts (ensures proper access control).
|
|
14
|
+
*
|
|
15
|
+
* @cil-generated
|
|
16
|
+
*/
|
|
17
|
+
|
|
2
18
|
|
|
3
19
|
|
|
4
20
|
|
|
@@ -29,39 +45,65 @@
|
|
|
29
45
|
|
|
30
46
|
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
40
56
|
import { createHandler } from './_shared/middleware'
|
|
41
57
|
import { adminDb } from './_shared/db'
|
|
42
58
|
import { emitLog } from './_shared/audit'
|
|
43
59
|
import { isSystemAdmin } from './_shared/principal'
|
|
44
60
|
import { sanitizeRecordData } from './_shared/permissions'
|
|
45
|
-
import { hashApiKey } from './_shared/hash-api-key'
|
|
46
|
-
|
|
47
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
48
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
49
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
50
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
51
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
61
|
+
import { hashApiKey, omitSecretFields } from './_shared/hash-api-key'
|
|
62
|
+
import { resolveAppUuid } from './_shared/logging'
|
|
52
63
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:module_header:module_header"]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// True only for platform-level principals: a system_admin role or an
|
|
67
|
+
// internal machine principal with no account binding (SYSTEM_PRINCIPAL,
|
|
68
|
+
// produced only by the INTERNAL_INVOKE_SECRET path). Machine principals
|
|
69
|
+
// resolve to the service-role adminDb via getPrincipalDb, so account-bound
|
|
70
|
+
// API keys must be scoped to their own account below.
|
|
71
|
+
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:isSystemPrincipal:function" type="function" identity="isSystemPrincipal" parent="~/.framework/functions/api-keys.ts"]
|
|
72
|
+
function isSystemPrincipal(ctx: any): boolean {
|
|
73
|
+
return isSystemAdmin(ctx.principal) || (ctx.principal?.isInternal === true && !ctx.accountId)
|
|
74
|
+
}
|
|
75
|
+
// CIL[END stable_id="~/.framework/functions/api-keys.ts:isSystemPrincipal:function"]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
53
91
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:list:constant" type="constant" identity="list" parent="~/.framework/functions/api-keys.ts"]
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
92
|
+
/**
|
|
93
|
+
* This function retrieves a list of API keys based on various query parameters and returns sanitized records. It ensures that only authorized users can access the data and applies filters based on the provided criteria.
|
|
94
|
+
*
|
|
95
|
+
* @throws Error — Account context required.
|
|
96
|
+
* @sideEffects none
|
|
97
|
+
* @stability internal
|
|
98
|
+
* @calls adminDb.from('api_keys'), ctx.db.from('api_keys'), sanitizeRecordData
|
|
99
|
+
* @cil-generated
|
|
100
|
+
*/
|
|
61
101
|
export const list = createHandler(async (ctx, _body) => {
|
|
62
102
|
const { integration_id, key_type, is_active, expires_before, expires_after, limit = 100, offset = 0 } = ctx.query || {}
|
|
63
103
|
|
|
64
|
-
|
|
104
|
+
const isSystem = isSystemPrincipal(ctx)
|
|
105
|
+
|
|
106
|
+
if (!isSystem && !ctx.accountId) {
|
|
65
107
|
throw new Error('Account context required')
|
|
66
108
|
}
|
|
67
109
|
|
|
@@ -72,6 +114,12 @@ export const list = createHandler(async (ctx, _body) => {
|
|
|
72
114
|
.select('*')
|
|
73
115
|
.order('created_at', { ascending: false })
|
|
74
116
|
|
|
117
|
+
// Machine principals run on the service-role client — pin them to their
|
|
118
|
+
// own account so they cannot enumerate other tenants' keys.
|
|
119
|
+
if (!isSystem) {
|
|
120
|
+
query = query.eq('account_id', ctx.accountId)
|
|
121
|
+
}
|
|
122
|
+
|
|
75
123
|
if (integration_id) {
|
|
76
124
|
query = query.eq('integration_id', integration_id)
|
|
77
125
|
}
|
|
@@ -97,26 +145,37 @@ export const list = createHandler(async (ctx, _body) => {
|
|
|
97
145
|
|
|
98
146
|
const sanitized = []
|
|
99
147
|
for (const key of data || []) {
|
|
100
|
-
sanitized.push(await sanitizeRecordData(ctx, key, 'api_key'))
|
|
148
|
+
sanitized.push(omitSecretFields(await sanitizeRecordData(ctx, key, 'api_key')))
|
|
101
149
|
}
|
|
102
150
|
|
|
103
151
|
return sanitized
|
|
104
152
|
})
|
|
105
|
-
// CIL[DOC-VECTOR type="context" content="purpose='List API keys for an account with optional filters'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
|
|
106
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
107
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
108
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
109
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
110
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
111
153
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:list:constant"]
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
112
169
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:get:constant" type="constant" identity="get" parent="~/.framework/functions/api-keys.ts"]
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Retrieves an API key from the database based on the provided ID in the query parameters. It ensures that the caller has the necessary permissions and sanitizes the returned data before sending it back.
|
|
172
|
+
*
|
|
173
|
+
* @throws Error — API key ID is required, Error — if there is an error fetching the API key.
|
|
174
|
+
* @sideEffects none
|
|
175
|
+
* @stability internal
|
|
176
|
+
* @calls adminDb.from('api_keys'), ctx.db.from('api_keys'), sanitizeRecordData
|
|
177
|
+
* @cil-generated
|
|
178
|
+
*/
|
|
120
179
|
export const get = createHandler(async (ctx, _body) => {
|
|
121
180
|
const { id } = ctx.query || {}
|
|
122
181
|
|
|
@@ -126,31 +185,50 @@ export const get = createHandler(async (ctx, _body) => {
|
|
|
126
185
|
|
|
127
186
|
const db = isSystemAdmin(ctx.principal) ? adminDb : ctx.db
|
|
128
187
|
|
|
129
|
-
|
|
188
|
+
let query = db
|
|
130
189
|
.from('api_keys')
|
|
131
190
|
.select('*')
|
|
132
191
|
.eq('id', id)
|
|
133
|
-
|
|
192
|
+
|
|
193
|
+
if (!isSystemPrincipal(ctx)) {
|
|
194
|
+
if (!ctx.accountId) {
|
|
195
|
+
throw new Error('Account context required')
|
|
196
|
+
}
|
|
197
|
+
query = query.eq('account_id', ctx.accountId)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const { data, error: err } = await query.single()
|
|
134
201
|
|
|
135
202
|
if (err) throw err
|
|
136
203
|
|
|
137
|
-
return await sanitizeRecordData(ctx, data, 'api_key')
|
|
204
|
+
return omitSecretFields(await sanitizeRecordData(ctx, data, 'api_key'))
|
|
138
205
|
})
|
|
139
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Fetch a single API key by ID'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
|
|
140
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
141
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
142
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
143
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
144
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
145
206
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:get:constant"]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
146
222
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:create:constant" type="constant" identity="create" parent="~/.framework/functions/api-keys.ts"]
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Creates a new API key for a specified integration and application, ensuring required fields are validated and generating a unique key. This function is essential for managing access to the API securely.
|
|
225
|
+
*
|
|
226
|
+
* @throws Error — name is required, Error — Account context required, Error — database error
|
|
227
|
+
* @sideEffects Writes a new record to the 'api_keys' table in the database and emits a log event.
|
|
228
|
+
* @stability internal
|
|
229
|
+
* @calls ctx.db.from('api_keys'), emitLog, resolveAppUuid
|
|
230
|
+
* @cil-generated
|
|
231
|
+
*/
|
|
154
232
|
export const create = createHandler(async (ctx, body) => {
|
|
155
233
|
const {
|
|
156
234
|
integration_id,
|
|
@@ -174,6 +252,35 @@ export const create = createHandler(async (ctx, body) => {
|
|
|
174
252
|
throw new Error('Account context required')
|
|
175
253
|
}
|
|
176
254
|
|
|
255
|
+
// S-011: scopes and is_internal are privilege-bearing fields. A machine
|
|
256
|
+
// caller runs on the service-role client, so accepting them verbatim let
|
|
257
|
+
// any scoped key mint a *:* or is_internal key and escalate itself past
|
|
258
|
+
// the isInternal gates elsewhere. Only system principals may request a
|
|
259
|
+
// wildcard scope or an internal key — for everyone else those are hard
|
|
260
|
+
// denials, other requested scopes are clipped to the scopes the caller
|
|
261
|
+
// itself holds, and an omitted scopes list inherits the caller's own.
|
|
262
|
+
const isSystem = isSystemPrincipal(ctx)
|
|
263
|
+
let effectiveScopes: string[] = scopes || []
|
|
264
|
+
let effectiveIsInternal = is_internal || false
|
|
265
|
+
|
|
266
|
+
if (!isSystem) {
|
|
267
|
+
if (is_internal) {
|
|
268
|
+
const e: any = new Error('Insufficient permissions to create an internal API key')
|
|
269
|
+
e.statusCode = 403
|
|
270
|
+
throw e
|
|
271
|
+
}
|
|
272
|
+
if (Array.isArray(scopes) && scopes.includes('*:*')) {
|
|
273
|
+
const e: any = new Error('Insufficient permissions to create a wildcard-scoped API key')
|
|
274
|
+
e.statusCode = 403
|
|
275
|
+
throw e
|
|
276
|
+
}
|
|
277
|
+
const callerScopes = Array.isArray(ctx.principal?.scopes) ? ctx.principal.scopes : []
|
|
278
|
+
effectiveScopes = Array.isArray(scopes)
|
|
279
|
+
? scopes.filter((s: string) => callerScopes.includes(s))
|
|
280
|
+
: callerScopes
|
|
281
|
+
effectiveIsInternal = false
|
|
282
|
+
}
|
|
283
|
+
|
|
177
284
|
const slug = body.slug || name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '')
|
|
178
285
|
|
|
179
286
|
const rawKey = `sk_${crypto.randomUUID().replace(/-/g, '')}`
|
|
@@ -181,7 +288,7 @@ export const create = createHandler(async (ctx, body) => {
|
|
|
181
288
|
|
|
182
289
|
const insertData = {
|
|
183
290
|
integration_id: integration_id || null,
|
|
184
|
-
app_id: app_id || ctx.appId || null,
|
|
291
|
+
app_id: (await resolveAppUuid(app_id || ctx.appId)) || null,
|
|
185
292
|
account_id: ctx.accountId,
|
|
186
293
|
slug,
|
|
187
294
|
name,
|
|
@@ -189,14 +296,14 @@ export const create = createHandler(async (ctx, body) => {
|
|
|
189
296
|
key_hash,
|
|
190
297
|
key_type: key_type || 'inbound',
|
|
191
298
|
permissions: permissions || [],
|
|
192
|
-
scopes:
|
|
299
|
+
scopes: effectiveScopes,
|
|
193
300
|
rate_limit: rate_limit || 100,
|
|
194
301
|
expires_at: expires_at || null,
|
|
195
302
|
metadata: metadata || {},
|
|
196
303
|
machine_type: machine_type || 'integration',
|
|
197
|
-
is_internal:
|
|
304
|
+
is_internal: effectiveIsInternal,
|
|
198
305
|
is_active: true,
|
|
199
|
-
created_by: ctx.principal?.id
|
|
306
|
+
created_by: ctx.principal?.type === 'human' ? ctx.principal.id : null
|
|
200
307
|
}
|
|
201
308
|
|
|
202
309
|
const { data, error: err } = await ctx.db
|
|
@@ -218,21 +325,32 @@ export const create = createHandler(async (ctx, body) => {
|
|
|
218
325
|
warning: 'Store this key now. It will not be shown again.'
|
|
219
326
|
}
|
|
220
327
|
})
|
|
221
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Create a new API key'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
|
|
222
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
223
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
224
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
225
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
226
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
227
328
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:create:constant"]
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
228
344
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:validate:constant" type="constant" identity="validate" parent="~/.framework/functions/api-keys.ts"]
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
345
|
+
/**
|
|
346
|
+
* Validates an API key by checking its existence and permissions in the database. This function ensures that only active keys with the required permissions can be used.
|
|
347
|
+
*
|
|
348
|
+
* @throws Error — key_value is required, Error — database error
|
|
349
|
+
* @sideEffects Database read operations.
|
|
350
|
+
* @stability internal
|
|
351
|
+
* @calls ctx.db.from('api_keys'), import('./_shared/hash-api-key')
|
|
352
|
+
* @cil-generated
|
|
353
|
+
*/
|
|
236
354
|
export const validate = createHandler(async (ctx, body) => {
|
|
237
355
|
const { key_value, required_permissions } = body
|
|
238
356
|
|
|
@@ -240,15 +358,29 @@ export const validate = createHandler(async (ctx, body) => {
|
|
|
240
358
|
throw new Error('key_value is required')
|
|
241
359
|
}
|
|
242
360
|
|
|
361
|
+
const isSystem = isSystemPrincipal(ctx)
|
|
362
|
+
if (!isSystem && !ctx.accountId) {
|
|
363
|
+
throw new Error('Account context required')
|
|
364
|
+
}
|
|
365
|
+
|
|
243
366
|
const keyPrefix = key_value.slice(0, 8)
|
|
244
367
|
|
|
245
|
-
|
|
368
|
+
let query = ctx.db
|
|
246
369
|
.from('api_keys')
|
|
247
370
|
.select('*')
|
|
248
371
|
.eq('key_prefix', keyPrefix)
|
|
249
372
|
.eq('is_active', true)
|
|
250
373
|
.or('expires_at.is.null,expires_at.gte.now()')
|
|
251
374
|
|
|
375
|
+
// Scoped callers may only validate keys belonging to their own account —
|
|
376
|
+
// ctx.db is service-role for machine principals, so without this filter a
|
|
377
|
+
// caller could probe another account's key material.
|
|
378
|
+
if (!isSystem) {
|
|
379
|
+
query = query.eq('account_id', ctx.accountId)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const { data: rows, error: err } = await query
|
|
383
|
+
|
|
252
384
|
if (err) throw err
|
|
253
385
|
if (!rows || rows.length === 0) {
|
|
254
386
|
return { is_valid: false, error: 'Invalid or inactive API key' }
|
|
@@ -283,21 +415,32 @@ export const validate = createHandler(async (ctx, body) => {
|
|
|
283
415
|
|
|
284
416
|
return { is_valid: false, error: 'Invalid or inactive API key' }
|
|
285
417
|
})
|
|
286
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Validate an API key value and optional permissions'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
|
|
287
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
288
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
289
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
290
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
291
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
292
418
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:validate:constant"]
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
293
434
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:revoke:constant" type="constant" identity="revoke" parent="~/.framework/functions/api-keys.ts"]
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
435
|
+
/**
|
|
436
|
+
* The 'revoke' constant defines a handler for deactivating an API key by its ID. It ensures that the API key ID is provided and logs the revocation action.
|
|
437
|
+
*
|
|
438
|
+
* @throws Error — if the API key ID is missing or if a database error occurs.
|
|
439
|
+
* @sideEffects Updates the 'api_keys' table in the database and emits a log event.
|
|
440
|
+
* @stability internal
|
|
441
|
+
* @calls ctx.db.from('api_keys'), emitLog
|
|
442
|
+
* @cil-generated
|
|
443
|
+
*/
|
|
301
444
|
export const revoke = createHandler(async (ctx, body) => {
|
|
302
445
|
const { id } = body
|
|
303
446
|
|
|
@@ -305,12 +448,19 @@ export const revoke = createHandler(async (ctx, body) => {
|
|
|
305
448
|
throw new Error('API key ID is required')
|
|
306
449
|
}
|
|
307
450
|
|
|
308
|
-
|
|
451
|
+
let query = ctx.db
|
|
309
452
|
.from('api_keys')
|
|
310
453
|
.update({ is_active: false, updated_at: new Date().toISOString() })
|
|
311
454
|
.eq('id', id)
|
|
312
|
-
|
|
313
|
-
|
|
455
|
+
|
|
456
|
+
if (!isSystemPrincipal(ctx)) {
|
|
457
|
+
if (!ctx.accountId) {
|
|
458
|
+
throw new Error('Account context required')
|
|
459
|
+
}
|
|
460
|
+
query = query.eq('account_id', ctx.accountId)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const { data, error: err } = await query.select().single()
|
|
314
464
|
|
|
315
465
|
if (err) throw err
|
|
316
466
|
|
|
@@ -319,27 +469,41 @@ export const revoke = createHandler(async (ctx, body) => {
|
|
|
319
469
|
{ after: { revoked_by: ctx.principal?.id } }
|
|
320
470
|
)
|
|
321
471
|
|
|
322
|
-
return data
|
|
472
|
+
return omitSecretFields(data)
|
|
323
473
|
})
|
|
324
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Deactivate an API key by ID'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
|
|
325
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
326
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
327
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
328
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
329
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
330
474
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:revoke:constant"]
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
331
490
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:listUsageLogs:constant" type="constant" identity="listUsageLogs" parent="~/.framework/functions/api-keys.ts"]
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
491
|
+
/**
|
|
492
|
+
* The listUsageLogs constant defines an asynchronous handler for retrieving API key usage logs based on various query parameters. It ensures that the account context is valid and constructs a query to fetch logs from the database.
|
|
493
|
+
*
|
|
494
|
+
* @throws Error — Account context required.
|
|
495
|
+
* @sideEffects none
|
|
496
|
+
* @stability internal
|
|
497
|
+
* @calls ctx.db.from('api_key_usage_logs'), ctx.db.select, ctx.db.eq, ctx.db.gte, ctx.db.lte, ctx.db.range
|
|
498
|
+
* @errorHandling none
|
|
499
|
+
* @cil-generated
|
|
500
|
+
*/
|
|
339
501
|
export const listUsageLogs = createHandler(async (ctx, _body) => {
|
|
340
502
|
const { api_key_id, response_status, success, date_from, date_to, limit = 100, offset = 0 } = ctx.query || {}
|
|
341
503
|
|
|
342
|
-
|
|
504
|
+
const isSystem = isSystemPrincipal(ctx)
|
|
505
|
+
|
|
506
|
+
if (!isSystem && !ctx.accountId) {
|
|
343
507
|
throw new Error('Account context required')
|
|
344
508
|
}
|
|
345
509
|
|
|
@@ -351,6 +515,10 @@ export const listUsageLogs = createHandler(async (ctx, _body) => {
|
|
|
351
515
|
`)
|
|
352
516
|
.order('created_at', { ascending: false })
|
|
353
517
|
|
|
518
|
+
if (!isSystem) {
|
|
519
|
+
query = query.eq('account_id', ctx.accountId)
|
|
520
|
+
}
|
|
521
|
+
|
|
354
522
|
if (api_key_id) {
|
|
355
523
|
query = query.eq('api_key_id', api_key_id)
|
|
356
524
|
}
|
|
@@ -376,21 +544,32 @@ export const listUsageLogs = createHandler(async (ctx, _body) => {
|
|
|
376
544
|
|
|
377
545
|
return data
|
|
378
546
|
})
|
|
379
|
-
// CIL[DOC-VECTOR type="context" content="purpose='List API key usage logs with filters'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/audit.ts"]
|
|
380
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
381
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
382
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
383
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
384
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
385
547
|
// CIL[END stable_id="~/.framework/functions/api-keys.ts:listUsageLogs:constant"]
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
|
|
386
563
|
// CIL[BEGIN stable_id="~/.framework/functions/api-keys.ts:handler:constant" type="constant" identity="handler" parent="~/.framework/functions/api-keys.ts"]
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
564
|
+
/**
|
|
565
|
+
* The handler processes API requests based on the action and method specified in the query parameters. It routes the request to the appropriate function for validation, revocation, usage logs, or general data handling.
|
|
566
|
+
*
|
|
567
|
+
* @throws Error — Invalid action or method
|
|
568
|
+
* @sideEffects none
|
|
569
|
+
* @stability internal
|
|
570
|
+
* @calls validate, revoke, listUsageLogs, get, list, create
|
|
571
|
+
* @cil-generated
|
|
572
|
+
*/
|
|
394
573
|
export const handler = createHandler(async (ctx, body) => {
|
|
395
574
|
const { action } = ctx.query || {}
|
|
396
575
|
const method = ctx.query?.method || 'GET'
|
|
@@ -425,10 +604,10 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
425
604
|
|
|
426
605
|
throw new Error('Invalid action or method')
|
|
427
606
|
})
|
|
428
|
-
// CIL[
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
607
|
+
// CIL[END stable_id="~/.framework/functions/api-keys.ts:handler:constant"]
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|