feat: phase 3 observability — IMS telemetry merge

Port IMS telemetry into Primora conventions:

- core.components/core.events (migration 00004 + sqlc) scoped to projects
- POST /api/v1/ingest — single or <=500-event batches via project prm_
  keys (X-Primora-Key alias), auto-registering components, permissive CORS
- Issues: fingerprint-grouped errors with count/severity/first+last seen
- Reads: events w/ filters + before-cursor, components, stats (1h/24h/7d/30d
  bucketed series + component health + totals + metric names), metric
  series (avg/p50/p95/max)
- GET .../telemetry/stream — project-scoped SSE through an in-process hub
  (buffered subs, drop-on-slow, 25s keepalives); ?api_key=/?token= auth
  for EventSource
- Telemetry page: health/issues/events/metrics/integrate tabs, live badge,
  390px-clean; demo stubs
- @primora/client SDK (createPrimoraClient: capture*/heartbeat/installAuto,
  queued keepalive flushes)
- MCP: primora_list_issues/list_events/telemetry_stats/metric_series
- IMS README deprecation note pointing here

Also fixes workspace pins to 0.3.0 — npm ci in the frontend image was
resolving the unpublished 0.2.0 spec from the registry.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-16 16:21:03 +02:00
1 parent 6507eee606
commit 8cfddf9184
60 files changed
+3694 -30

No files matched your search

+9
View File
@@ -70,6 +70,15 @@ func (h *HTTPHandler) Register(router *gin.Engine) {
api.GET("/collections/:collectionID/documents/:documentID", h.getDocument)
api.PATCH("/collections/:collectionID/documents/:documentID", h.updateDocument)
api.DELETE("/collections/:collectionID/documents/:documentID", h.deleteDocument)
api.OPTIONS("/ingest", h.ingestOptions)
api.POST("/ingest", h.ingest)
api.GET("/projects/:projectID/events", h.listEvents)
api.GET("/projects/:projectID/issues", h.listIssues)
api.GET("/projects/:projectID/components", h.listComponents)
api.DELETE("/projects/:projectID/components/:componentID", h.deleteComponent)
api.GET("/projects/:projectID/telemetry/stats", h.telemetryStats)
api.GET("/projects/:projectID/telemetry/metrics/series", h.metricSeries)
api.GET("/projects/:projectID/telemetry/stream", h.telemetryStream)
api.GET("/db/status", h.dbxStatus)
api.GET("/projects/:projectID/db-connections", h.listDBConnections)
api.POST("/projects/:projectID/db-connections", h.createDBConnection)