nuxt-observe 0.0.2
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/README.md +92 -0
- package/dist/module.d.mts +7 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +393 -0
- package/dist/runtime/app/assets/css/main.css +1 -0
- package/dist/runtime/app/components/ObserveActivityFeed.d.vue.ts +13 -0
- package/dist/runtime/app/components/ObserveActivityFeed.vue +77 -0
- package/dist/runtime/app/components/ObserveActivityFeed.vue.d.ts +13 -0
- package/dist/runtime/app/components/ObserveActivityTable.d.vue.ts +30 -0
- package/dist/runtime/app/components/ObserveActivityTable.vue +187 -0
- package/dist/runtime/app/components/ObserveActivityTable.vue.d.ts +30 -0
- package/dist/runtime/app/components/ObserveCan.d.vue.ts +27 -0
- package/dist/runtime/app/components/ObserveCan.vue +16 -0
- package/dist/runtime/app/components/ObserveCan.vue.d.ts +27 -0
- package/dist/runtime/app/components/ObserveErrorsTable.d.vue.ts +19 -0
- package/dist/runtime/app/components/ObserveErrorsTable.vue +105 -0
- package/dist/runtime/app/components/ObserveErrorsTable.vue.d.ts +19 -0
- package/dist/runtime/app/components/ObserveHealthHero.d.vue.ts +16 -0
- package/dist/runtime/app/components/ObserveHealthHero.vue +114 -0
- package/dist/runtime/app/components/ObserveHealthHero.vue.d.ts +16 -0
- package/dist/runtime/app/components/ObserveJourneySearch.d.vue.ts +13 -0
- package/dist/runtime/app/components/ObserveJourneySearch.vue +55 -0
- package/dist/runtime/app/components/ObserveJourneySearch.vue.d.ts +13 -0
- package/dist/runtime/app/components/ObserveJourneyTimeline.d.vue.ts +14 -0
- package/dist/runtime/app/components/ObserveJourneyTimeline.vue +119 -0
- package/dist/runtime/app/components/ObserveJourneyTimeline.vue.d.ts +14 -0
- package/dist/runtime/app/components/ObserveLogDetail.d.vue.ts +12 -0
- package/dist/runtime/app/components/ObserveLogDetail.vue +187 -0
- package/dist/runtime/app/components/ObserveLogDetail.vue.d.ts +12 -0
- package/dist/runtime/app/components/ObserveLogLevelBadge.d.vue.ts +10 -0
- package/dist/runtime/app/components/ObserveLogLevelBadge.vue +29 -0
- package/dist/runtime/app/components/ObserveLogLevelBadge.vue.d.ts +10 -0
- package/dist/runtime/app/components/ObserveLogsFilterBar.d.vue.ts +20 -0
- package/dist/runtime/app/components/ObserveLogsFilterBar.vue +134 -0
- package/dist/runtime/app/components/ObserveLogsFilterBar.vue.d.ts +20 -0
- package/dist/runtime/app/components/ObserveLogsTable.d.vue.ts +20 -0
- package/dist/runtime/app/components/ObserveLogsTable.vue +92 -0
- package/dist/runtime/app/components/ObserveLogsTable.vue.d.ts +20 -0
- package/dist/runtime/app/components/ObservePeriodSelector.d.vue.ts +3 -0
- package/dist/runtime/app/components/ObservePeriodSelector.vue +22 -0
- package/dist/runtime/app/components/ObservePeriodSelector.vue.d.ts +3 -0
- package/dist/runtime/app/components/ObserveRegressionAlert.d.vue.ts +12 -0
- package/dist/runtime/app/components/ObserveRegressionAlert.vue +27 -0
- package/dist/runtime/app/components/ObserveRegressionAlert.vue.d.ts +12 -0
- package/dist/runtime/app/components/ObserveServiceSwitcher.d.vue.ts +3 -0
- package/dist/runtime/app/components/ObserveServiceSwitcher.vue +49 -0
- package/dist/runtime/app/components/ObserveServiceSwitcher.vue.d.ts +3 -0
- package/dist/runtime/app/components/ObserveServicesTable.d.vue.ts +15 -0
- package/dist/runtime/app/components/ObserveServicesTable.vue +109 -0
- package/dist/runtime/app/components/ObserveServicesTable.vue.d.ts +15 -0
- package/dist/runtime/app/components/ObserveStatCard.d.vue.ts +14 -0
- package/dist/runtime/app/components/ObserveStatCard.vue +34 -0
- package/dist/runtime/app/components/ObserveStatCard.vue.d.ts +14 -0
- package/dist/runtime/app/components/charts/ObserveErrorRateChart.client.d.vue.ts +15 -0
- package/dist/runtime/app/components/charts/ObserveErrorRateChart.client.vue +170 -0
- package/dist/runtime/app/components/charts/ObserveErrorRateChart.client.vue.d.ts +15 -0
- package/dist/runtime/app/components/charts/ObserveServiceBreakdownChart.client.d.vue.ts +17 -0
- package/dist/runtime/app/components/charts/ObserveServiceBreakdownChart.client.vue +208 -0
- package/dist/runtime/app/components/charts/ObserveServiceBreakdownChart.client.vue.d.ts +17 -0
- package/dist/runtime/app/components/charts/ObserveVersionAdoptionChart.client.d.vue.ts +14 -0
- package/dist/runtime/app/components/charts/ObserveVersionAdoptionChart.client.vue +208 -0
- package/dist/runtime/app/components/charts/ObserveVersionAdoptionChart.client.vue.d.ts +14 -0
- package/dist/runtime/app/components/charts/ObserveVersionCompareChart.client.d.vue.ts +14 -0
- package/dist/runtime/app/components/charts/ObserveVersionCompareChart.client.vue +190 -0
- package/dist/runtime/app/components/charts/ObserveVersionCompareChart.client.vue.d.ts +14 -0
- package/dist/runtime/app/components/charts/ObserveVolumeChart.client.d.vue.ts +16 -0
- package/dist/runtime/app/components/charts/ObserveVolumeChart.client.vue +199 -0
- package/dist/runtime/app/components/charts/ObserveVolumeChart.client.vue.d.ts +16 -0
- package/dist/runtime/app/components/charts/chart-core.d.ts +64 -0
- package/dist/runtime/app/components/charts/chart-core.js +136 -0
- package/dist/runtime/app/components/settings/ObserveApiKeyPanel.d.vue.ts +8 -0
- package/dist/runtime/app/components/settings/ObserveApiKeyPanel.vue +145 -0
- package/dist/runtime/app/components/settings/ObserveApiKeyPanel.vue.d.ts +8 -0
- package/dist/runtime/app/components/settings/ObserveApiKeyRevealModal.d.vue.ts +19 -0
- package/dist/runtime/app/components/settings/ObserveApiKeyRevealModal.vue +106 -0
- package/dist/runtime/app/components/settings/ObserveApiKeyRevealModal.vue.d.ts +19 -0
- package/dist/runtime/app/components/settings/ObserveAssignmentEditor.d.vue.ts +12 -0
- package/dist/runtime/app/components/settings/ObserveAssignmentEditor.vue +67 -0
- package/dist/runtime/app/components/settings/ObserveAssignmentEditor.vue.d.ts +12 -0
- package/dist/runtime/app/components/settings/ObserveGroupFormModal.d.vue.ts +18 -0
- package/dist/runtime/app/components/settings/ObserveGroupFormModal.vue +60 -0
- package/dist/runtime/app/components/settings/ObserveGroupFormModal.vue.d.ts +18 -0
- package/dist/runtime/app/components/settings/ObserveGroupMembershipEditor.d.vue.ts +20 -0
- package/dist/runtime/app/components/settings/ObserveGroupMembershipEditor.vue +21 -0
- package/dist/runtime/app/components/settings/ObserveGroupMembershipEditor.vue.d.ts +20 -0
- package/dist/runtime/app/components/settings/ObserveOriginAllowlistEditor.d.vue.ts +15 -0
- package/dist/runtime/app/components/settings/ObserveOriginAllowlistEditor.vue +63 -0
- package/dist/runtime/app/components/settings/ObserveOriginAllowlistEditor.vue.d.ts +15 -0
- package/dist/runtime/app/components/settings/ObserveServiceEditForm.d.vue.ts +38 -0
- package/dist/runtime/app/components/settings/ObserveServiceEditForm.vue +216 -0
- package/dist/runtime/app/components/settings/ObserveServiceEditForm.vue.d.ts +38 -0
- package/dist/runtime/app/components/settings/ObserveServiceFormModal.d.vue.ts +37 -0
- package/dist/runtime/app/components/settings/ObserveServiceFormModal.vue +192 -0
- package/dist/runtime/app/components/settings/ObserveServiceFormModal.vue.d.ts +37 -0
- package/dist/runtime/app/components/settings/ObserveServiceTypeBadge.d.vue.ts +11 -0
- package/dist/runtime/app/components/settings/ObserveServiceTypeBadge.vue +18 -0
- package/dist/runtime/app/components/settings/ObserveServiceTypeBadge.vue.d.ts +11 -0
- package/dist/runtime/app/components/settings/ObserveSettingsServicesTable.d.vue.ts +19 -0
- package/dist/runtime/app/components/settings/ObserveSettingsServicesTable.vue +132 -0
- package/dist/runtime/app/components/settings/ObserveSettingsServicesTable.vue.d.ts +19 -0
- package/dist/runtime/app/components/settings/ObserveUserFormModal.d.vue.ts +27 -0
- package/dist/runtime/app/components/settings/ObserveUserFormModal.vue +108 -0
- package/dist/runtime/app/components/settings/ObserveUserFormModal.vue.d.ts +27 -0
- package/dist/runtime/app/components/settings/ObserveVersionTrackingField.d.vue.ts +17 -0
- package/dist/runtime/app/components/settings/ObserveVersionTrackingField.vue +20 -0
- package/dist/runtime/app/components/settings/ObserveVersionTrackingField.vue.d.ts +17 -0
- package/dist/runtime/app/composables/useObserveAbility.d.ts +15 -0
- package/dist/runtime/app/composables/useObserveAbility.js +20 -0
- package/dist/runtime/app/composables/useObserveActivity.d.ts +22 -0
- package/dist/runtime/app/composables/useObserveActivity.js +44 -0
- package/dist/runtime/app/composables/useObserveApiKeys.d.ts +15 -0
- package/dist/runtime/app/composables/useObserveApiKeys.js +19 -0
- package/dist/runtime/app/composables/useObserveAssignments.d.ts +19 -0
- package/dist/runtime/app/composables/useObserveAssignments.js +16 -0
- package/dist/runtime/app/composables/useObserveErrors.d.ts +33 -0
- package/dist/runtime/app/composables/useObserveErrors.js +85 -0
- package/dist/runtime/app/composables/useObserveGroups.d.ts +27 -0
- package/dist/runtime/app/composables/useObserveGroups.js +33 -0
- package/dist/runtime/app/composables/useObserveJourney.d.ts +19 -0
- package/dist/runtime/app/composables/useObserveJourney.js +19 -0
- package/dist/runtime/app/composables/useObserveLogFacets.d.ts +11 -0
- package/dist/runtime/app/composables/useObserveLogFacets.js +21 -0
- package/dist/runtime/app/composables/useObserveLogs.d.ts +28 -0
- package/dist/runtime/app/composables/useObserveLogs.js +100 -0
- package/dist/runtime/app/composables/useObserveMigrations.d.ts +17 -0
- package/dist/runtime/app/composables/useObserveMigrations.js +49 -0
- package/dist/runtime/app/composables/useObserveOverview.d.ts +14 -0
- package/dist/runtime/app/composables/useObserveOverview.js +23 -0
- package/dist/runtime/app/composables/useObservePeriod.d.ts +11 -0
- package/dist/runtime/app/composables/useObservePeriod.js +18 -0
- package/dist/runtime/app/composables/useObserveRollout.d.ts +20 -0
- package/dist/runtime/app/composables/useObserveRollout.js +55 -0
- package/dist/runtime/app/composables/useObserveScope.d.ts +13 -0
- package/dist/runtime/app/composables/useObserveScope.js +17 -0
- package/dist/runtime/app/composables/useObserveServices.d.ts +26 -0
- package/dist/runtime/app/composables/useObserveServices.js +33 -0
- package/dist/runtime/app/composables/useObserveStats.d.ts +14 -0
- package/dist/runtime/app/composables/useObserveStats.js +23 -0
- package/dist/runtime/app/composables/useObserveUsers.d.ts +29 -0
- package/dist/runtime/app/composables/useObserveUsers.js +33 -0
- package/dist/runtime/app/layouts/observe.d.vue.ts +13 -0
- package/dist/runtime/app/layouts/observe.vue +138 -0
- package/dist/runtime/app/layouts/observe.vue.d.ts +13 -0
- package/dist/runtime/app/middleware/observe-auth.global.d.ts +9 -0
- package/dist/runtime/app/middleware/observe-auth.global.js +8 -0
- package/dist/runtime/app/pages/activity.d.vue.ts +3 -0
- package/dist/runtime/app/pages/activity.vue +54 -0
- package/dist/runtime/app/pages/activity.vue.d.ts +3 -0
- package/dist/runtime/app/pages/error-detail.d.vue.ts +3 -0
- package/dist/runtime/app/pages/error-detail.vue +190 -0
- package/dist/runtime/app/pages/error-detail.vue.d.ts +3 -0
- package/dist/runtime/app/pages/errors.d.vue.ts +3 -0
- package/dist/runtime/app/pages/errors.vue +47 -0
- package/dist/runtime/app/pages/errors.vue.d.ts +3 -0
- package/dist/runtime/app/pages/journey.d.vue.ts +3 -0
- package/dist/runtime/app/pages/journey.vue +96 -0
- package/dist/runtime/app/pages/journey.vue.d.ts +3 -0
- package/dist/runtime/app/pages/log-detail.d.vue.ts +3 -0
- package/dist/runtime/app/pages/log-detail.vue +35 -0
- package/dist/runtime/app/pages/log-detail.vue.d.ts +3 -0
- package/dist/runtime/app/pages/login.d.vue.ts +3 -0
- package/dist/runtime/app/pages/login.vue +69 -0
- package/dist/runtime/app/pages/login.vue.d.ts +3 -0
- package/dist/runtime/app/pages/logs.d.vue.ts +3 -0
- package/dist/runtime/app/pages/logs.vue +36 -0
- package/dist/runtime/app/pages/logs.vue.d.ts +3 -0
- package/dist/runtime/app/pages/metrics.d.vue.ts +3 -0
- package/dist/runtime/app/pages/metrics.vue +68 -0
- package/dist/runtime/app/pages/metrics.vue.d.ts +3 -0
- package/dist/runtime/app/pages/overview.d.vue.ts +3 -0
- package/dist/runtime/app/pages/overview.vue +65 -0
- package/dist/runtime/app/pages/overview.vue.d.ts +3 -0
- package/dist/runtime/app/pages/rollout.d.vue.ts +3 -0
- package/dist/runtime/app/pages/rollout.vue +188 -0
- package/dist/runtime/app/pages/rollout.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/group-detail.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/group-detail.vue +149 -0
- package/dist/runtime/app/pages/settings/group-detail.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/groups.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/groups.vue +107 -0
- package/dist/runtime/app/pages/settings/groups.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/index.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/index.vue +47 -0
- package/dist/runtime/app/pages/settings/index.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/migrations.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/migrations.vue +275 -0
- package/dist/runtime/app/pages/settings/migrations.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/service-detail.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/service-detail.vue +133 -0
- package/dist/runtime/app/pages/settings/service-detail.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/services.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/services.vue +66 -0
- package/dist/runtime/app/pages/settings/services.vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/users/[id].d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/users/[id].vue +243 -0
- package/dist/runtime/app/pages/settings/users/[id].vue.d.ts +3 -0
- package/dist/runtime/app/pages/settings/users/index.d.vue.ts +3 -0
- package/dist/runtime/app/pages/settings/users/index.vue +129 -0
- package/dist/runtime/app/pages/settings/users/index.vue.d.ts +3 -0
- package/dist/runtime/options.d.ts +1 -0
- package/dist/runtime/options.js +1 -0
- package/dist/runtime/server/api/observe/activity.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/activity.get.js +30 -0
- package/dist/runtime/server/api/observe/auth/login.post.d.ts +4 -0
- package/dist/runtime/server/api/observe/auth/login.post.js +13 -0
- package/dist/runtime/server/api/observe/auth/logout.post.d.ts +4 -0
- package/dist/runtime/server/api/observe/auth/logout.post.js +6 -0
- package/dist/runtime/server/api/observe/auth/me.get.d.ts +2 -0
- package/dist/runtime/server/api/observe/auth/me.get.js +3 -0
- package/dist/runtime/server/api/observe/errors/[fingerprint].get.d.ts +3 -0
- package/dist/runtime/server/api/observe/errors/[fingerprint].get.js +56 -0
- package/dist/runtime/server/api/observe/errors/index.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/errors/index.get.js +41 -0
- package/dist/runtime/server/api/observe/facets.get.d.ts +8 -0
- package/dist/runtime/server/api/observe/facets.get.js +12 -0
- package/dist/runtime/server/api/observe/groups/[id]/assignments.put.d.ts +3 -0
- package/dist/runtime/server/api/observe/groups/[id]/assignments.put.js +12 -0
- package/dist/runtime/server/api/observe/groups/[id]/services.put.d.ts +5 -0
- package/dist/runtime/server/api/observe/groups/[id]/services.put.js +13 -0
- package/dist/runtime/server/api/observe/groups/[id].delete.d.ts +5 -0
- package/dist/runtime/server/api/observe/groups/[id].delete.js +11 -0
- package/dist/runtime/server/api/observe/groups/[id].get.d.ts +6 -0
- package/dist/runtime/server/api/observe/groups/[id].get.js +14 -0
- package/dist/runtime/server/api/observe/groups/[id].patch.d.ts +3 -0
- package/dist/runtime/server/api/observe/groups/[id].patch.js +12 -0
- package/dist/runtime/server/api/observe/groups/index.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/groups/index.get.js +7 -0
- package/dist/runtime/server/api/observe/groups/index.post.d.ts +3 -0
- package/dist/runtime/server/api/observe/groups/index.post.js +11 -0
- package/dist/runtime/server/api/observe/health.get.d.ts +6 -0
- package/dist/runtime/server/api/observe/health.get.js +10 -0
- package/dist/runtime/server/api/observe/ingest/frogger.d.ts +5 -0
- package/dist/runtime/server/api/observe/ingest/frogger.js +42 -0
- package/dist/runtime/server/api/observe/ingest.d.ts +5 -0
- package/dist/runtime/server/api/observe/ingest.js +38 -0
- package/dist/runtime/server/api/observe/journey.get.d.ts +9 -0
- package/dist/runtime/server/api/observe/journey.get.js +31 -0
- package/dist/runtime/server/api/observe/logs/[id].get.d.ts +3 -0
- package/dist/runtime/server/api/observe/logs/[id].get.js +19 -0
- package/dist/runtime/server/api/observe/logs.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/logs.get.js +54 -0
- package/dist/runtime/server/api/observe/migrations/index.get.d.ts +9 -0
- package/dist/runtime/server/api/observe/migrations/index.get.js +14 -0
- package/dist/runtime/server/api/observe/migrations/run.post.d.ts +13 -0
- package/dist/runtime/server/api/observe/migrations/run.post.js +35 -0
- package/dist/runtime/server/api/observe/overview.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/overview.get.js +19 -0
- package/dist/runtime/server/api/observe/rollout/compare.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/rollout/compare.get.js +24 -0
- package/dist/runtime/server/api/observe/rollout/regressions.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/rollout/regressions.get.js +31 -0
- package/dist/runtime/server/api/observe/rollout/versions.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/rollout/versions.get.js +20 -0
- package/dist/runtime/server/api/observe/services/[id]/assignments.put.d.ts +7 -0
- package/dist/runtime/server/api/observe/services/[id]/assignments.put.js +12 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/[keyId]/rotate.post.d.ts +4 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/[keyId]/rotate.post.js +14 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/[keyId].delete.d.ts +4 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/[keyId].delete.js +14 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/index.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/index.get.js +10 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/index.post.d.ts +3 -0
- package/dist/runtime/server/api/observe/services/[id]/keys/index.post.js +11 -0
- package/dist/runtime/server/api/observe/services/[id]/restore.post.d.ts +4 -0
- package/dist/runtime/server/api/observe/services/[id]/restore.post.js +11 -0
- package/dist/runtime/server/api/observe/services/[id].delete.d.ts +11 -0
- package/dist/runtime/server/api/observe/services/[id].delete.js +11 -0
- package/dist/runtime/server/api/observe/services/[id].get.d.ts +3 -0
- package/dist/runtime/server/api/observe/services/[id].get.js +12 -0
- package/dist/runtime/server/api/observe/services/[id].patch.d.ts +3 -0
- package/dist/runtime/server/api/observe/services/[id].patch.js +13 -0
- package/dist/runtime/server/api/observe/services/index.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/services/index.get.js +7 -0
- package/dist/runtime/server/api/observe/services/index.post.d.ts +3 -0
- package/dist/runtime/server/api/observe/services/index.post.js +16 -0
- package/dist/runtime/server/api/observe/stats.get.d.ts +3 -0
- package/dist/runtime/server/api/observe/stats.get.js +28 -0
- package/dist/runtime/server/api/observe/users/[id]/assignments.put.d.ts +3 -0
- package/dist/runtime/server/api/observe/users/[id]/assignments.put.js +14 -0
- package/dist/runtime/server/api/observe/users/[id].delete.d.ts +4 -0
- package/dist/runtime/server/api/observe/users/[id].delete.js +15 -0
- package/dist/runtime/server/api/observe/users/[id].get.d.ts +3 -0
- package/dist/runtime/server/api/observe/users/[id].get.js +11 -0
- package/dist/runtime/server/api/observe/users/[id].patch.d.ts +3 -0
- package/dist/runtime/server/api/observe/users/[id].patch.js +25 -0
- package/dist/runtime/server/api/observe/users/index.get.d.ts +8 -0
- package/dist/runtime/server/api/observe/users/index.get.js +7 -0
- package/dist/runtime/server/api/observe/users/index.post.d.ts +3 -0
- package/dist/runtime/server/api/observe/users/index.post.js +29 -0
- package/dist/runtime/server/auth/authorization.d.ts +7 -0
- package/dist/runtime/server/auth/authorization.js +5 -0
- package/dist/runtime/server/auth/provider.d.ts +17 -0
- package/dist/runtime/server/auth/provider.js +44 -0
- package/dist/runtime/server/auth/providers/config-provider.d.ts +18 -0
- package/dist/runtime/server/auth/providers/config-provider.js +54 -0
- package/dist/runtime/server/auth/providers/db-provider.d.ts +16 -0
- package/dist/runtime/server/auth/providers/db-provider.js +42 -0
- package/dist/runtime/server/auth/providers/jwt-provider.d.ts +24 -0
- package/dist/runtime/server/auth/providers/jwt-provider.js +72 -0
- package/dist/runtime/server/migrations/0001-services-kind.d.ts +8 -0
- package/dist/runtime/server/migrations/0001-services-kind.js +14 -0
- package/dist/runtime/server/migrations/0002-services-type.d.ts +7 -0
- package/dist/runtime/server/migrations/0002-services-type.js +14 -0
- package/dist/runtime/server/migrations/0003-services-deleted-at.d.ts +6 -0
- package/dist/runtime/server/migrations/0003-services-deleted-at.js +14 -0
- package/dist/runtime/server/migrations/0004-logs-error-fingerprint.d.ts +11 -0
- package/dist/runtime/server/migrations/0004-logs-error-fingerprint.js +15 -0
- package/dist/runtime/server/migrations/0005-users-columns.d.ts +9 -0
- package/dist/runtime/server/migrations/0005-users-columns.js +25 -0
- package/dist/runtime/server/migrations/index.d.ts +13 -0
- package/dist/runtime/server/migrations/index.js +13 -0
- package/dist/runtime/server/migrations/types.d.ts +15 -0
- package/dist/runtime/server/migrations/types.js +0 -0
- package/dist/runtime/server/plugins/observe-migrate.server.d.ts +2 -0
- package/dist/runtime/server/plugins/observe-migrate.server.js +18 -0
- package/dist/runtime/server/tasks/backfill-fingerprints.d.ts +11 -0
- package/dist/runtime/server/tasks/backfill-fingerprints.js +41 -0
- package/dist/runtime/server/tasks/purge.d.ts +5 -0
- package/dist/runtime/server/tasks/purge.js +12 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/server/utils/activity-query.d.ts +28 -0
- package/dist/runtime/server/utils/activity-query.js +70 -0
- package/dist/runtime/server/utils/api-keys.d.ts +48 -0
- package/dist/runtime/server/utils/api-keys.js +67 -0
- package/dist/runtime/server/utils/authz.d.ts +50 -0
- package/dist/runtime/server/utils/authz.js +60 -0
- package/dist/runtime/server/utils/db/users.d.ts +91 -0
- package/dist/runtime/server/utils/db/users.js +128 -0
- package/dist/runtime/server/utils/db.d.ts +10 -0
- package/dist/runtime/server/utils/db.js +5 -0
- package/dist/runtime/server/utils/frogger-adapter.d.ts +40 -0
- package/dist/runtime/server/utils/frogger-adapter.js +97 -0
- package/dist/runtime/server/utils/groups.d.ts +35 -0
- package/dist/runtime/server/utils/groups.js +59 -0
- package/dist/runtime/server/utils/ingest-cors.d.ts +23 -0
- package/dist/runtime/server/utils/ingest-cors.js +27 -0
- package/dist/runtime/server/utils/journey.d.ts +20 -0
- package/dist/runtime/server/utils/journey.js +44 -0
- package/dist/runtime/server/utils/logs.d.ts +50 -0
- package/dist/runtime/server/utils/logs.js +154 -0
- package/dist/runtime/server/utils/loop-guard.d.ts +11 -0
- package/dist/runtime/server/utils/loop-guard.js +11 -0
- package/dist/runtime/server/utils/migrate.d.ts +21 -0
- package/dist/runtime/server/utils/migrate.js +144 -0
- package/dist/runtime/server/utils/migration-runner.d.ts +42 -0
- package/dist/runtime/server/utils/migration-runner.js +129 -0
- package/dist/runtime/server/utils/observe-errors.d.ts +58 -0
- package/dist/runtime/server/utils/observe-errors.js +206 -0
- package/dist/runtime/server/utils/overview.d.ts +20 -0
- package/dist/runtime/server/utils/overview.js +119 -0
- package/dist/runtime/server/utils/provisioning.d.ts +62 -0
- package/dist/runtime/server/utils/provisioning.js +299 -0
- package/dist/runtime/server/utils/rate-limit.d.ts +11 -0
- package/dist/runtime/server/utils/rate-limit.js +22 -0
- package/dist/runtime/server/utils/require-observe-session.d.ts +15 -0
- package/dist/runtime/server/utils/require-observe-session.js +25 -0
- package/dist/runtime/server/utils/rollout.d.ts +19 -0
- package/dist/runtime/server/utils/rollout.js +56 -0
- package/dist/runtime/server/utils/scope.d.ts +14 -0
- package/dist/runtime/server/utils/scope.js +28 -0
- package/dist/runtime/server/utils/seed.d.ts +18 -0
- package/dist/runtime/server/utils/seed.js +70 -0
- package/dist/runtime/server/utils/services.d.ts +91 -0
- package/dist/runtime/server/utils/services.js +142 -0
- package/dist/runtime/server/utils/stats-query.d.ts +40 -0
- package/dist/runtime/server/utils/stats-query.js +104 -0
- package/dist/runtime/shared/auth/roles.d.ts +34 -0
- package/dist/runtime/shared/auth/roles.js +6 -0
- package/dist/runtime/shared/auth/schema.d.ts +85 -0
- package/dist/runtime/shared/auth/schema.js +41 -0
- package/dist/runtime/shared/auth/types.d.ts +68 -0
- package/dist/runtime/shared/auth/types.js +0 -0
- package/dist/runtime/shared/rbac/capabilities.d.ts +46 -0
- package/dist/runtime/shared/rbac/capabilities.js +48 -0
- package/dist/runtime/shared/schema/activity.d.ts +77 -0
- package/dist/runtime/shared/schema/activity.js +22 -0
- package/dist/runtime/shared/schema/adapters/frogger.d.ts +52 -0
- package/dist/runtime/shared/schema/adapters/frogger.js +17 -0
- package/dist/runtime/shared/schema/batch.d.ts +33 -0
- package/dist/runtime/shared/schema/batch.js +9 -0
- package/dist/runtime/shared/schema/error-fingerprint.d.ts +53 -0
- package/dist/runtime/shared/schema/error-fingerprint.js +47 -0
- package/dist/runtime/shared/schema/errors-query.d.ts +136 -0
- package/dist/runtime/shared/schema/errors-query.js +47 -0
- package/dist/runtime/shared/schema/event.d.ts +48 -0
- package/dist/runtime/shared/schema/event.js +41 -0
- package/dist/runtime/shared/schema/frogger-map.d.ts +62 -0
- package/dist/runtime/shared/schema/frogger-map.js +30 -0
- package/dist/runtime/shared/schema/index.d.ts +17 -0
- package/dist/runtime/shared/schema/index.js +17 -0
- package/dist/runtime/shared/schema/journey.d.ts +99 -0
- package/dist/runtime/shared/schema/journey.js +96 -0
- package/dist/runtime/shared/schema/levels.d.ts +37 -0
- package/dist/runtime/shared/schema/levels.js +72 -0
- package/dist/runtime/shared/schema/log-row.d.ts +31 -0
- package/dist/runtime/shared/schema/log-row.js +0 -0
- package/dist/runtime/shared/schema/logs-query.d.ts +91 -0
- package/dist/runtime/shared/schema/logs-query.js +72 -0
- package/dist/runtime/shared/schema/migrations.d.ts +34 -0
- package/dist/runtime/shared/schema/migrations.js +0 -0
- package/dist/runtime/shared/schema/overview.d.ts +78 -0
- package/dist/runtime/shared/schema/overview.js +9 -0
- package/dist/runtime/shared/schema/provisioning.d.ts +230 -0
- package/dist/runtime/shared/schema/provisioning.js +52 -0
- package/dist/runtime/shared/schema/registry.d.ts +115 -0
- package/dist/runtime/shared/schema/registry.js +27 -0
- package/dist/runtime/shared/schema/rollout.d.ts +103 -0
- package/dist/runtime/shared/schema/rollout.js +66 -0
- package/dist/runtime/shared/schema/stats.d.ts +64 -0
- package/dist/runtime/shared/schema/stats.js +15 -0
- package/dist/runtime/shared/schema/tiers.d.ts +5 -0
- package/dist/runtime/shared/schema/tiers.js +9 -0
- package/dist/runtime/shared/types/module-options.d.ts +119 -0
- package/dist/runtime/shared/types/module-options.js +13 -0
- package/dist/runtime/shared/types/storage.d.ts +31 -0
- package/dist/runtime/shared/types/storage.js +0 -0
- package/dist/runtime/shared/utils/format-relative.d.ts +7 -0
- package/dist/runtime/shared/utils/format-relative.js +11 -0
- package/dist/runtime/shared/utils/frogger-snippet.d.ts +19 -0
- package/dist/runtime/shared/utils/frogger-snippet.js +33 -0
- package/dist/runtime/shared/utils/observe-config.d.ts +9 -0
- package/dist/runtime/shared/utils/observe-config.js +17 -0
- package/dist/runtime/shared/utils/period.d.ts +13 -0
- package/dist/runtime/shared/utils/period.js +15 -0
- package/dist/runtime/shared/utils/slug.d.ts +1 -0
- package/dist/runtime/shared/utils/slug.js +5 -0
- package/dist/runtime/shared/utils/uuid.d.ts +187 -0
- package/dist/runtime/shared/utils/uuid.js +345 -0
- package/dist/runtime/types/nuxt-auth-utils-imports.d.ts +25 -0
- package/dist/runtime/types/observe-app-imports.d.ts +20 -0
- package/dist/runtime/types/session.d.ts +17 -0
- package/dist/schema.d.mts +1318 -0
- package/dist/schema.mjs +629 -0
- package/dist/types.d.mts +3 -0
- package/package.json +93 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AuthProvider } from '../../../shared/auth/types.js';
|
|
2
|
+
import type { ObserveUser } from '../../../shared/auth/schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Crypto is INJECTED, never statically imported (CP5-HANDOFF §3.4): nuxt-auth-utils'
|
|
5
|
+
* hashPassword/verifyPassword transitively pull '#imports', which a node-env vitest
|
|
6
|
+
* cannot transform. getAuthProvider() supplies the ambient Nitro auto-imports in
|
|
7
|
+
* production; tests supply real scrypt (from @adonisjs/hash) or deterministic fakes.
|
|
8
|
+
* This mirrors the repo-wide `opts.db ?? useObserveDb()` injection convention.
|
|
9
|
+
*
|
|
10
|
+
* The whole provider is a pure factory so CP16 can reuse it verbatim as the gated
|
|
11
|
+
* bootstrap-admin fallback (roles.ts lifecycle note) without touching this file.
|
|
12
|
+
*/
|
|
13
|
+
export interface ConfigProviderDeps {
|
|
14
|
+
users: ObserveUser[];
|
|
15
|
+
hashPassword: (plain: string) => Promise<string>;
|
|
16
|
+
verifyPassword: (hash: string, plain: string) => Promise<boolean>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createConfigAuthProvider(deps: ConfigProviderDeps): AuthProvider;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ALL } from "../../../shared/auth/roles.js";
|
|
2
|
+
function isScryptHash(material) {
|
|
3
|
+
return material.startsWith("$scrypt$");
|
|
4
|
+
}
|
|
5
|
+
export function createConfigAuthProvider(deps) {
|
|
6
|
+
const { users, hashPassword, verifyPassword } = deps;
|
|
7
|
+
let map;
|
|
8
|
+
let dummyHash;
|
|
9
|
+
async function buildMap() {
|
|
10
|
+
const m = /* @__PURE__ */ new Map();
|
|
11
|
+
for (const u of users) {
|
|
12
|
+
const material = u.passwordHash ?? (u.passwordEnv ? process.env[u.passwordEnv] : void 0);
|
|
13
|
+
if (!material) {
|
|
14
|
+
console.warn(`[observe] auth user "${u.name}" has no password material (passwordHash/passwordEnv); skipping`);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const passwordHash = isScryptHash(material) ? material : await hashPassword(material);
|
|
18
|
+
const assignment = u.role === "admin" ? { services: [ALL], groups: [ALL] } : { services: u.assignedServices ?? [], groups: u.assignedGroups ?? [] };
|
|
19
|
+
const principal = {
|
|
20
|
+
sub: u.name,
|
|
21
|
+
name: u.name,
|
|
22
|
+
role: u.role,
|
|
23
|
+
assignment,
|
|
24
|
+
provider: "config"
|
|
25
|
+
};
|
|
26
|
+
m.set(u.name, { principal, passwordHash });
|
|
27
|
+
}
|
|
28
|
+
return m;
|
|
29
|
+
}
|
|
30
|
+
async function getDummyHash() {
|
|
31
|
+
dummyHash ??= await hashPassword("observe-anti-enumeration-dummy");
|
|
32
|
+
return dummyHash;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
id: "config",
|
|
36
|
+
async authenticate(credentials) {
|
|
37
|
+
if (!("password" in credentials)) {
|
|
38
|
+
return { ok: false, reason: "config provider needs name+password" };
|
|
39
|
+
}
|
|
40
|
+
map ??= await buildMap();
|
|
41
|
+
const entry = map.get(credentials.name);
|
|
42
|
+
if (!entry) {
|
|
43
|
+
await verifyPassword(await getDummyHash(), credentials.password);
|
|
44
|
+
return { ok: false, reason: "unknown user" };
|
|
45
|
+
}
|
|
46
|
+
const ok = await verifyPassword(entry.passwordHash, credentials.password);
|
|
47
|
+
return ok ? { ok: true, principal: entry.principal } : { ok: false, reason: "bad password" };
|
|
48
|
+
},
|
|
49
|
+
async resolvePrincipal(sub) {
|
|
50
|
+
map ??= await buildMap();
|
|
51
|
+
return map.get(sub)?.principal ?? null;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AuthProvider } from '../../../shared/auth/types.js';
|
|
2
|
+
import type { Database } from '../../utils/db.js';
|
|
3
|
+
/**
|
|
4
|
+
* DB-backed dashboard auth (CP16). Crypto is INJECTED (same reason as config-provider:
|
|
5
|
+
* hashPassword/verifyPassword transitively pull '#imports', which a node-env vitest can't
|
|
6
|
+
* transform). getAuthProvider() supplies the ambient Nitro auto-imports; tests supply real
|
|
7
|
+
* scrypt or deterministic fakes. `configFallback` is a createConfigAuthProvider(...) result
|
|
8
|
+
* used ONLY while the DB has zero enabled admins (the gated bootstrap-admin window).
|
|
9
|
+
*/
|
|
10
|
+
export interface DbProviderDeps {
|
|
11
|
+
hashPassword: (plain: string) => Promise<string>;
|
|
12
|
+
verifyPassword: (hash: string, plain: string) => Promise<boolean>;
|
|
13
|
+
configFallback: AuthProvider;
|
|
14
|
+
db?: Database;
|
|
15
|
+
}
|
|
16
|
+
export declare function createDbAuthProvider(deps: DbProviderDeps): AuthProvider;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getUserByUsername,
|
|
3
|
+
getUserById,
|
|
4
|
+
getUserAssignments,
|
|
5
|
+
countAdmins,
|
|
6
|
+
principalFromUser
|
|
7
|
+
} from "../../utils/db/users.js";
|
|
8
|
+
export function createDbAuthProvider(deps) {
|
|
9
|
+
const { hashPassword, verifyPassword, configFallback, db } = deps;
|
|
10
|
+
const opts = db ? { db } : {};
|
|
11
|
+
let dummyHash;
|
|
12
|
+
const getDummyHash = async () => dummyHash ??= await hashPassword("observe-anti-enumeration-dummy");
|
|
13
|
+
async function assemble(userId, row) {
|
|
14
|
+
const assignment = await getUserAssignments(userId, opts);
|
|
15
|
+
return principalFromUser(row, assignment);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
id: "db",
|
|
19
|
+
async authenticate(credentials, event) {
|
|
20
|
+
if (!("password" in credentials)) {
|
|
21
|
+
return { ok: false, reason: "db provider needs name+password" };
|
|
22
|
+
}
|
|
23
|
+
const { name, password } = credentials;
|
|
24
|
+
const user = await getUserByUsername(name, opts);
|
|
25
|
+
if (user && !user.disabled && user.password_hash) {
|
|
26
|
+
const ok = await verifyPassword(user.password_hash, password);
|
|
27
|
+
if (ok) return { ok: true, principal: await assemble(user.id, user) };
|
|
28
|
+
} else {
|
|
29
|
+
await verifyPassword(await getDummyHash(), password);
|
|
30
|
+
}
|
|
31
|
+
if (await countAdmins(opts) === 0) {
|
|
32
|
+
return configFallback.authenticate(credentials, event);
|
|
33
|
+
}
|
|
34
|
+
return { ok: false, reason: "bad credentials" };
|
|
35
|
+
},
|
|
36
|
+
async resolvePrincipal(sub) {
|
|
37
|
+
const user = await getUserById(sub, opts);
|
|
38
|
+
if (!user || user.disabled) return null;
|
|
39
|
+
return await assemble(user.id, user);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { AuthProvider, Role } from '../../../shared/auth/types.js';
|
|
2
|
+
import type { Database } from '../../utils/db.js';
|
|
3
|
+
/**
|
|
4
|
+
* External-JWT verification (CP16). VERIFY only, never issue. Maps verified claims to a
|
|
5
|
+
* Principal. Any verification failure resolves to { ok:false } (never throws): the Bearer
|
|
6
|
+
* path wants a clean 401, not a 500. Stateless, so resolvePrincipal is not meaningful.
|
|
7
|
+
*/
|
|
8
|
+
export interface JwtConfig {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
algorithms?: Array<'HS256' | 'RS256'>;
|
|
11
|
+
secret?: string;
|
|
12
|
+
publicKey?: string;
|
|
13
|
+
jwksUri?: string;
|
|
14
|
+
issuer?: string;
|
|
15
|
+
audience?: string;
|
|
16
|
+
clockTolerance?: string;
|
|
17
|
+
roleClaim?: string;
|
|
18
|
+
subjectClaim?: string;
|
|
19
|
+
assignmentsClaim?: string;
|
|
20
|
+
roleMap?: Record<string, Role>;
|
|
21
|
+
claimsSource?: 'token' | 'db';
|
|
22
|
+
db?: Database;
|
|
23
|
+
}
|
|
24
|
+
export declare function createJwtAuthProvider(cfg: JwtConfig): AuthProvider;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jwtVerify, importSPKI, createRemoteJWKSet } from "jose";
|
|
2
|
+
import { ALL } from "../../../shared/auth/roles.js";
|
|
3
|
+
import { assignmentSchema } from "../../../shared/auth/schema.js";
|
|
4
|
+
import { findUserByIdentity, getUserAssignments } from "../../utils/db/users.js";
|
|
5
|
+
function wildcardIfAdmin(role, assignment) {
|
|
6
|
+
return role === "admin" ? { services: [ALL], groups: [ALL] } : assignment;
|
|
7
|
+
}
|
|
8
|
+
export function createJwtAuthProvider(cfg) {
|
|
9
|
+
const roleClaim = cfg.roleClaim ?? "observe_role";
|
|
10
|
+
const subjectClaim = cfg.subjectClaim ?? "sub";
|
|
11
|
+
const assignmentsClaim = cfg.assignmentsClaim ?? "observe_assignment";
|
|
12
|
+
const claimsSource = cfg.claimsSource ?? "token";
|
|
13
|
+
const dbOpts = cfg.db ? { db: cfg.db } : {};
|
|
14
|
+
const rsAlg = cfg.algorithms?.find((a) => a === "RS256") ?? "RS256";
|
|
15
|
+
let keyPromise;
|
|
16
|
+
const getKey = () => keyPromise ??= (async () => {
|
|
17
|
+
if (cfg.jwksUri) return createRemoteJWKSet(new URL(cfg.jwksUri));
|
|
18
|
+
if (cfg.publicKey) return await importSPKI(cfg.publicKey, rsAlg);
|
|
19
|
+
if (cfg.secret) return new TextEncoder().encode(cfg.secret);
|
|
20
|
+
return null;
|
|
21
|
+
})();
|
|
22
|
+
return {
|
|
23
|
+
id: "jwt",
|
|
24
|
+
async authenticate(credentials) {
|
|
25
|
+
if (!("token" in credentials)) {
|
|
26
|
+
return { ok: false, reason: "jwt provider needs a token" };
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const key = await getKey();
|
|
30
|
+
if (!key) return { ok: false, reason: "jwt provider not configured" };
|
|
31
|
+
const { payload } = await jwtVerify(credentials.token, key, {
|
|
32
|
+
// Empty strings arrive from the materialised runtimeConfig defaults; treat as unset
|
|
33
|
+
// so jose does not require iss/aud to equal '' (see module.ts jwtConfig).
|
|
34
|
+
issuer: cfg.issuer || void 0,
|
|
35
|
+
audience: cfg.audience || void 0,
|
|
36
|
+
algorithms: cfg.algorithms,
|
|
37
|
+
clockTolerance: cfg.clockTolerance || void 0
|
|
38
|
+
});
|
|
39
|
+
const sub = payload[subjectClaim];
|
|
40
|
+
if (typeof sub !== "string" || !sub) return { ok: false, reason: "no subject claim" };
|
|
41
|
+
const rawRole = payload[roleClaim];
|
|
42
|
+
const role = typeof rawRole === "string" && cfg.roleMap?.[rawRole] || "viewer";
|
|
43
|
+
if (claimsSource === "db") {
|
|
44
|
+
const user = await findUserByIdentity("jwt", sub, dbOpts);
|
|
45
|
+
if (!user || user.disabled) return { ok: false, reason: "unknown or disabled identity" };
|
|
46
|
+
const assignment2 = await getUserAssignments(user.id, dbOpts);
|
|
47
|
+
const principal2 = {
|
|
48
|
+
sub,
|
|
49
|
+
name: user.display_name ?? user.username,
|
|
50
|
+
role,
|
|
51
|
+
assignment: wildcardIfAdmin(role, assignment2),
|
|
52
|
+
provider: "jwt"
|
|
53
|
+
};
|
|
54
|
+
return { ok: true, principal: principal2 };
|
|
55
|
+
}
|
|
56
|
+
const parsed = assignmentSchema.safeParse(payload[assignmentsClaim]);
|
|
57
|
+
const assignment = parsed.success ? parsed.data : { services: [], groups: [] };
|
|
58
|
+
const name = typeof payload.name === "string" ? payload.name : sub;
|
|
59
|
+
const principal = {
|
|
60
|
+
sub,
|
|
61
|
+
name,
|
|
62
|
+
role,
|
|
63
|
+
assignment: wildcardIfAdmin(role, assignment),
|
|
64
|
+
provider: "jwt"
|
|
65
|
+
};
|
|
66
|
+
return { ok: true, principal };
|
|
67
|
+
} catch {
|
|
68
|
+
return { ok: false, reason: "verification failed" };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Migration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adopted from the pre-CP17 `ensureServicesKindColumn` helper. A fresh DB already has
|
|
4
|
+
* `kind` from OBSERVE_DDL (the PRAGMA guard sees it and skips); a pre-CP10.5 DB has the
|
|
5
|
+
* column added here, backfilling existing rows to 'server'. The guard keeps re-running a
|
|
6
|
+
* no-op, so recording it on the very first CP17 boot never touches existing data.
|
|
7
|
+
*/
|
|
8
|
+
export declare const m0001AddServicesKind: Migration;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const m0001AddServicesKind = {
|
|
2
|
+
id: "0001-services-kind",
|
|
3
|
+
class: "additive",
|
|
4
|
+
description: "Add services.kind column (server/browser)",
|
|
5
|
+
async up(db, log) {
|
|
6
|
+
const cols = await db.prepare(`PRAGMA table_info('services')`).all();
|
|
7
|
+
if (!cols.some((c) => c.name === "kind")) {
|
|
8
|
+
log("adding services.kind column");
|
|
9
|
+
await db.exec(`ALTER TABLE services ADD COLUMN kind TEXT NOT NULL DEFAULT 'server'`);
|
|
10
|
+
} else {
|
|
11
|
+
log("services.kind already present, skipping");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Migration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adopted from the pre-CP17 `ensureServicesTypeColumn` helper. Mirrors the kind column:
|
|
4
|
+
* a fresh DB already has `type` from OBSERVE_DDL; a pre-CP11 DB gets it added here,
|
|
5
|
+
* backfilling existing rows to 'service'. Guarded so a re-run is a no-op.
|
|
6
|
+
*/
|
|
7
|
+
export declare const m0002AddServicesType: Migration;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const m0002AddServicesType = {
|
|
2
|
+
id: "0002-services-type",
|
|
3
|
+
class: "additive",
|
|
4
|
+
description: "Add services.type column (UI badge category)",
|
|
5
|
+
async up(db, log) {
|
|
6
|
+
const cols = await db.prepare(`PRAGMA table_info('services')`).all();
|
|
7
|
+
if (!cols.some((c) => c.name === "type")) {
|
|
8
|
+
log("adding services.type column");
|
|
9
|
+
await db.exec(`ALTER TABLE services ADD COLUMN type TEXT NOT NULL DEFAULT 'service'`);
|
|
10
|
+
} else {
|
|
11
|
+
log("services.type already present, skipping");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Migration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adopted from the pre-CP17 `ensureServicesDeletedAtColumn` helper (CP11 soft-delete).
|
|
4
|
+
* NULL default = every pre-existing row is active. Guarded so a re-run is a no-op.
|
|
5
|
+
*/
|
|
6
|
+
export declare const m0003AddServicesDeletedAt: Migration;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const m0003AddServicesDeletedAt = {
|
|
2
|
+
id: "0003-services-deleted-at",
|
|
3
|
+
class: "additive",
|
|
4
|
+
description: "Add services.deleted_at soft-delete marker",
|
|
5
|
+
async up(db, log) {
|
|
6
|
+
const cols = await db.prepare(`PRAGMA table_info('services')`).all();
|
|
7
|
+
if (!cols.some((c) => c.name === "deleted_at")) {
|
|
8
|
+
log("adding services.deleted_at column");
|
|
9
|
+
await db.exec(`ALTER TABLE services ADD COLUMN deleted_at INTEGER NULL`);
|
|
10
|
+
} else {
|
|
11
|
+
log("services.deleted_at already present, skipping");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Migration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adopted from the pre-CP17 `ensureLogsErrorFingerprintColumn` helper (CP14). A fresh DB
|
|
4
|
+
* already has the column from OBSERVE_DDL; a pre-CP14 DB gets it added here, leaving every
|
|
5
|
+
* existing row NULL until the backfill task runs. The index is created here (not in
|
|
6
|
+
* OBSERVE_DDL) so the column is guaranteed to exist first on a pre-CP14 DB: the ALTER above
|
|
7
|
+
* runs before it, whereas running the index inside the DDL batch would fail on the still-
|
|
8
|
+
* columnless table. Composite so the GROUP BY scan and the `= ? ORDER BY time` drill-down
|
|
9
|
+
* both ride it. Both statements are guarded/`IF NOT EXISTS`, so a re-run is a no-op.
|
|
10
|
+
*/
|
|
11
|
+
export declare const m0004AddLogsErrorFingerprint: Migration;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const m0004AddLogsErrorFingerprint = {
|
|
2
|
+
id: "0004-logs-error-fingerprint",
|
|
3
|
+
class: "additive",
|
|
4
|
+
description: "Add logs.error_fingerprint column + index",
|
|
5
|
+
async up(db, log) {
|
|
6
|
+
const cols = await db.prepare(`PRAGMA table_info('logs')`).all();
|
|
7
|
+
if (!cols.some((c) => c.name === "error_fingerprint")) {
|
|
8
|
+
log("adding logs.error_fingerprint column");
|
|
9
|
+
await db.exec(`ALTER TABLE logs ADD COLUMN error_fingerprint TEXT`);
|
|
10
|
+
} else {
|
|
11
|
+
log("logs.error_fingerprint already present, skipping");
|
|
12
|
+
}
|
|
13
|
+
await db.exec(`CREATE INDEX IF NOT EXISTS idx_logs_fingerprint ON logs(error_fingerprint, time)`);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Migration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adopted from the pre-CP17 `ensureUsersColumns` helper (CP16). A fresh DB already has
|
|
4
|
+
* role/disabled/created_by/updated_at from the OBSERVE_DDL `users` block; a pre-CP16 DB
|
|
5
|
+
* (username + password_hash + source only) gets them added here so a clean install and a
|
|
6
|
+
* migrated install converge on the same shape. Defaults match the DDL, so existing rows
|
|
7
|
+
* backfill to role='viewer', disabled=0. Each ADD is guarded, so a re-run is a no-op.
|
|
8
|
+
*/
|
|
9
|
+
export declare const m0005AddUsersColumns: Migration;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const m0005AddUsersColumns = {
|
|
2
|
+
id: "0005-users-columns",
|
|
3
|
+
class: "additive",
|
|
4
|
+
description: "Add users role/disabled/created_by/updated_at columns",
|
|
5
|
+
async up(db, log) {
|
|
6
|
+
const cols = await db.prepare(`PRAGMA table_info('users')`).all();
|
|
7
|
+
const has = (name) => cols.some((c) => c.name === name);
|
|
8
|
+
if (!has("role")) {
|
|
9
|
+
log("adding users.role column");
|
|
10
|
+
await db.exec(`ALTER TABLE users ADD COLUMN role TEXT NOT NULL DEFAULT 'viewer'`);
|
|
11
|
+
}
|
|
12
|
+
if (!has("disabled")) {
|
|
13
|
+
log("adding users.disabled column");
|
|
14
|
+
await db.exec(`ALTER TABLE users ADD COLUMN disabled INTEGER NOT NULL DEFAULT 0`);
|
|
15
|
+
}
|
|
16
|
+
if (!has("created_by")) {
|
|
17
|
+
log("adding users.created_by column");
|
|
18
|
+
await db.exec(`ALTER TABLE users ADD COLUMN created_by TEXT NULL`);
|
|
19
|
+
}
|
|
20
|
+
if (!has("updated_at")) {
|
|
21
|
+
log("adding users.updated_at column");
|
|
22
|
+
await db.exec(`ALTER TABLE users ADD COLUMN updated_at INTEGER NULL`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Migration } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The ordered migration registry shipped with the package. Publishing a new module
|
|
4
|
+
* version = appending a descriptor here. Rules:
|
|
5
|
+
* - Ordering is by array position and MUST match ascending `id`. The runner sorts
|
|
6
|
+
* defensively, but authors keep them in order.
|
|
7
|
+
* - Never reorder and never edit a migration's `up()` after it has shipped in a release:
|
|
8
|
+
* a change alters its checksum and triggers a drift warning. A correction is a NEW
|
|
9
|
+
* migration with a new id.
|
|
10
|
+
* - The first five entries are the adopted pre-CP17 `ensure*` helpers, all idempotent
|
|
11
|
+
* `additive` migrations, so recording them on the first CP17 boot is a safe no-op.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MIGRATIONS: readonly Migration[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { m0001AddServicesKind } from "./0001-services-kind.js";
|
|
2
|
+
import { m0002AddServicesType } from "./0002-services-type.js";
|
|
3
|
+
import { m0003AddServicesDeletedAt } from "./0003-services-deleted-at.js";
|
|
4
|
+
import { m0004AddLogsErrorFingerprint } from "./0004-logs-error-fingerprint.js";
|
|
5
|
+
import { m0005AddUsersColumns } from "./0005-users-columns.js";
|
|
6
|
+
export const MIGRATIONS = [
|
|
7
|
+
m0001AddServicesKind,
|
|
8
|
+
m0002AddServicesType,
|
|
9
|
+
m0003AddServicesDeletedAt,
|
|
10
|
+
m0004AddLogsErrorFingerprint,
|
|
11
|
+
m0005AddUsersColumns
|
|
12
|
+
// future entries appended here, never reordered, never edited after shipping
|
|
13
|
+
];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Database } from '../utils/db.js';
|
|
2
|
+
import type { MigrationClass } from '../../shared/schema/migrations.js';
|
|
3
|
+
export type { MigrationClass };
|
|
4
|
+
/** Sink the runner passes into up(); every line is streamed to the admin console. */
|
|
5
|
+
export type MigrationLog = (line: string) => void;
|
|
6
|
+
export interface Migration {
|
|
7
|
+
/** Sortable, unique, stable forever once shipped. Convention: 'NNNN-kebab-summary'. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** 'additive' = auto-runs at boot; 'destructive' = held for an admin click. */
|
|
10
|
+
class: MigrationClass;
|
|
11
|
+
/** Human summary shown in the pending list and console header. */
|
|
12
|
+
description: string;
|
|
13
|
+
/** Idempotent forward migration. Runs inside a transaction the runner opens. */
|
|
14
|
+
up: (db: Database, log: MigrationLog) => Promise<void>;
|
|
15
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineNitroPlugin, useRuntimeConfig } from "nitropack/runtime";
|
|
2
|
+
import { ensureObserveSchema } from "../utils/migrate.js";
|
|
3
|
+
import { purgeOldLogs } from "../utils/logs.js";
|
|
4
|
+
import { seedObserveRegistry } from "../utils/seed.js";
|
|
5
|
+
export default defineNitroPlugin(async () => {
|
|
6
|
+
await ensureObserveSchema();
|
|
7
|
+
try {
|
|
8
|
+
const observe = useRuntimeConfig().observe;
|
|
9
|
+
await seedObserveRegistry(observe);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
console.error("[observe] registry seed failed", e);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
await purgeOldLogs();
|
|
15
|
+
} catch (e) {
|
|
16
|
+
console.error("[observe] boot purge failed", e);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recompute error_fingerprint for error-bearing rows whose fingerprint is missing or
|
|
3
|
+
* stale (not the current `v1:` algorithm). Manual/one-shot: run after the CP14 migration
|
|
4
|
+
* lands on an existing DB, or after an algorithm bump. Keyed off the `v1:` prefix so a
|
|
5
|
+
* future v2 is detectable and re-backfillable without touching already-current rows. The
|
|
6
|
+
* "row carries an error" predicate is the flat error_* columns (there is no error_json).
|
|
7
|
+
*/
|
|
8
|
+
declare const _default: import("nitropack/types").Task<{
|
|
9
|
+
updated: number;
|
|
10
|
+
}>;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defineTask } from "nitropack/runtime";
|
|
2
|
+
import { fingerprintError } from "../../shared/schema/error-fingerprint.js";
|
|
3
|
+
import { useObserveDb } from "../utils/db.js";
|
|
4
|
+
const BATCH = 500;
|
|
5
|
+
export default defineTask({
|
|
6
|
+
meta: { name: "observe:backfill-fingerprints", description: "Recompute error fingerprints for rows with NULL or non-v1 fingerprint" },
|
|
7
|
+
async run() {
|
|
8
|
+
const db = useObserveDb();
|
|
9
|
+
let updated = 0;
|
|
10
|
+
for (; ; ) {
|
|
11
|
+
const rows = await db.prepare(
|
|
12
|
+
`SELECT id, error_name, error_message, error_stack, error_code
|
|
13
|
+
FROM logs
|
|
14
|
+
WHERE (error_name IS NOT NULL OR error_message IS NOT NULL OR error_stack IS NOT NULL OR error_code IS NOT NULL)
|
|
15
|
+
AND (error_fingerprint IS NULL OR error_fingerprint NOT LIKE 'v1:%')
|
|
16
|
+
ORDER BY id
|
|
17
|
+
LIMIT ?`
|
|
18
|
+
).all(BATCH);
|
|
19
|
+
if (rows.length === 0) break;
|
|
20
|
+
await db.sql`BEGIN`;
|
|
21
|
+
try {
|
|
22
|
+
for (const r of rows) {
|
|
23
|
+
const { fingerprint } = fingerprintError({
|
|
24
|
+
name: r.error_name ?? void 0,
|
|
25
|
+
message: r.error_message ?? void 0,
|
|
26
|
+
stack: r.error_stack ?? void 0,
|
|
27
|
+
code: r.error_code ?? void 0
|
|
28
|
+
});
|
|
29
|
+
await db.sql`UPDATE logs SET error_fingerprint = ${fingerprint} WHERE id = ${r.id}`;
|
|
30
|
+
}
|
|
31
|
+
await db.sql`COMMIT`;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
await db.sql`ROLLBACK`;
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
updated += rows.length;
|
|
37
|
+
if (rows.length < BATCH) break;
|
|
38
|
+
}
|
|
39
|
+
return { result: { updated } };
|
|
40
|
+
}
|
|
41
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineTask } from "nitropack/runtime";
|
|
2
|
+
import { purgeOldLogs } from "../utils/logs.js";
|
|
3
|
+
import { purgeExpiredServices } from "../utils/services.js";
|
|
4
|
+
import { SERVICE_DELETE_RETENTION_MS } from "../utils/provisioning.js";
|
|
5
|
+
export default defineTask({
|
|
6
|
+
meta: { name: "observe:purge", description: "Delete observe logs older than retentionDays and purge expired soft-deleted services" },
|
|
7
|
+
async run() {
|
|
8
|
+
const { deleted } = await purgeOldLogs();
|
|
9
|
+
const { purged } = await purgeExpiredServices(SERVICE_DELETE_RETENTION_MS);
|
|
10
|
+
return { result: { deleted, servicesPurged: purged } };
|
|
11
|
+
}
|
|
12
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ActivityData, ActivityDimension, ActivitySort } from '../../shared/schema/activity.js';
|
|
2
|
+
import { type Database } from './db.js';
|
|
3
|
+
/**
|
|
4
|
+
* CP10 ranked aggregate behind GET /api/observe/activity: a GROUP BY over the canonical
|
|
5
|
+
* route/feature columns of `logs`, ordered by the requested sort. Same contract as the
|
|
6
|
+
* CP7 getOverview / CP8 getStats helpers: takes a RESOLVED scope (string[] | '*'), not an
|
|
7
|
+
* event — the handler runs requireCapability/getAllowedServiceIds/resolveEffectiveScope
|
|
8
|
+
* first — so this stays pure and node-testable via `opts.db`.
|
|
9
|
+
*
|
|
10
|
+
* Two prepared statements per request: the ranked list (Query A) and a cheap totals pass
|
|
11
|
+
* (Query B) that detects the degraded state — logs exist in the window but none carry the
|
|
12
|
+
* dimension (the frogger route/feature emit gap CP15 closes). No N+1: keys are their own
|
|
13
|
+
* labels. The window is always time-bounded, riding idx_logs_service_time when scoped and
|
|
14
|
+
* idx_logs_time for admin.
|
|
15
|
+
*/
|
|
16
|
+
interface DbOpts {
|
|
17
|
+
db?: Database;
|
|
18
|
+
}
|
|
19
|
+
export interface ActivityFilters {
|
|
20
|
+
dimension: ActivityDimension;
|
|
21
|
+
env?: string;
|
|
22
|
+
level?: number;
|
|
23
|
+
q?: string;
|
|
24
|
+
sort: ActivitySort;
|
|
25
|
+
limit: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function getActivity(scope: string[] | '*', from: number, to: number, filters: ActivityFilters, opts?: DbOpts): Promise<ActivityData>;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useObserveDb } from "./db.js";
|
|
2
|
+
import { escapeLike } from "./logs.js";
|
|
3
|
+
const DIMENSION_EXPR = {
|
|
4
|
+
auto: { key: "COALESCE(route, feature)", present: "(route IS NOT NULL OR feature IS NOT NULL)" },
|
|
5
|
+
route: { key: "route", present: "route IS NOT NULL" },
|
|
6
|
+
feature: { key: "feature", present: "feature IS NOT NULL" }
|
|
7
|
+
};
|
|
8
|
+
const SORT_EXPR = {
|
|
9
|
+
count: "count DESC",
|
|
10
|
+
errors: "errors DESC, count DESC",
|
|
11
|
+
errorRate: "(errors * 1.0 / count) DESC, count DESC",
|
|
12
|
+
lastSeen: "lastSeen DESC"
|
|
13
|
+
};
|
|
14
|
+
export async function getActivity(scope, from, to, filters, opts = {}) {
|
|
15
|
+
if (scope !== "*" && scope.length === 0) return { items: [], total: 0, withKey: 0, degraded: false };
|
|
16
|
+
const db = opts.db ?? useObserveDb();
|
|
17
|
+
const dim = DIMENSION_EXPR[filters.dimension];
|
|
18
|
+
const scoped = scope === "*" ? { clause: "", params: [] } : { clause: `AND service_id IN (${scope.map(() => "?").join(",")})`, params: [...scope] };
|
|
19
|
+
const filt = [];
|
|
20
|
+
const filtParams = [];
|
|
21
|
+
if (filters.env != null) {
|
|
22
|
+
filt.push("AND env = ?");
|
|
23
|
+
filtParams.push(filters.env);
|
|
24
|
+
}
|
|
25
|
+
if (filters.level != null) {
|
|
26
|
+
filt.push("AND level = ?");
|
|
27
|
+
filtParams.push(filters.level);
|
|
28
|
+
}
|
|
29
|
+
const where = `WHERE time >= ? AND time <= ? ${scoped.clause} ${filt.join(" ")}`;
|
|
30
|
+
const baseParams = [from, to, ...scoped.params, ...filtParams];
|
|
31
|
+
const qClause = filters.q ? `AND ${dim.key} LIKE ? ESCAPE '\\'` : "";
|
|
32
|
+
const listParams = [
|
|
33
|
+
...baseParams,
|
|
34
|
+
...filters.q ? [`%${escapeLike(filters.q)}%`] : [],
|
|
35
|
+
filters.limit
|
|
36
|
+
];
|
|
37
|
+
const listRows = await db.prepare(
|
|
38
|
+
`SELECT ${dim.key} AS key,
|
|
39
|
+
SUM(route IS NOT NULL) AS routeHits,
|
|
40
|
+
COUNT(*) AS count,
|
|
41
|
+
SUM(level = 0) AS errors,
|
|
42
|
+
MAX(time) AS lastSeen,
|
|
43
|
+
MIN(time) AS firstSeen
|
|
44
|
+
FROM logs
|
|
45
|
+
${where} AND ${dim.present} ${qClause}
|
|
46
|
+
GROUP BY key
|
|
47
|
+
ORDER BY ${SORT_EXPR[filters.sort]}
|
|
48
|
+
LIMIT ?`
|
|
49
|
+
).all(...listParams);
|
|
50
|
+
const totalsRow = await db.prepare(
|
|
51
|
+
`SELECT COUNT(*) AS total,
|
|
52
|
+
COALESCE(SUM(${dim.present}), 0) AS withKey
|
|
53
|
+
FROM logs ${where}`
|
|
54
|
+
).get(...baseParams);
|
|
55
|
+
const items = listRows.map((r) => {
|
|
56
|
+
const errors = r.errors ?? 0;
|
|
57
|
+
return {
|
|
58
|
+
key: r.key,
|
|
59
|
+
dim: filters.dimension === "auto" ? r.routeHits > 0 ? "route" : "feature" : filters.dimension,
|
|
60
|
+
count: r.count,
|
|
61
|
+
errors,
|
|
62
|
+
errorRate: r.count ? errors / r.count : 0,
|
|
63
|
+
lastSeen: r.lastSeen,
|
|
64
|
+
firstSeen: r.firstSeen
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
const total = totalsRow.total;
|
|
68
|
+
const withKey = totalsRow.withKey ?? 0;
|
|
69
|
+
return { items, total, withKey, degraded: total > 0 && withKey === 0 };
|
|
70
|
+
}
|