Skip to main content

Monitor drift and runtime

The Monitor tab is what you watch after launch. It answers "is the live policy still what I thought it was?" — but not yet "how is the live traffic looking?"

What the UI does

The Monitor tab shows the activity stream from GET /authsec/resource-servers/:id/drift-events. Each event is a discrete change to the live policy after activation. The header warns "Application not launched" if state != 'ready' — drift events only accumulate after activation, so pre-launch the tab is empty by definition.

The plan calls out two known gaps:

  • Detailed runtime metrics (policy health, denied call counts, insufficient_scope rate) — coming. Backend endpoint not built yet.
  • Per-tool call latency / throughput — coming. Same status.

For now, the SDK's own logs are the operational signal of choice; see Workaround section below.

The drift events catalog

Events are written to resource_server_drift_events whenever a post-activation policy change happens. Five types today:

event_typeWhen it firesPayload
scope_deletedAdmin deletes a scope after launch{prior_scope_id, prior_scope_name, tools_affected: int}
tool_unmappedA tool's scope mapping was removed{tool_name, prior_scope_id}
default_role_disabledThe access policy was switched off{prior_default_role}
default_role_changedThe default role was swapped for a different one{prior_default_role, new_default_role}
secret_rotatedIntrospection secret was rotated{rotated_by, rotated_at}

Each row has id, rs_id, event_type, event_payload (JSONB), occurred_at, occurred_by (admin user UUID).

Why drift events matter

Once an application is live, every change has runtime consequences:

  • Delete a scope → tokens already issued with that scope still pass validation, but new tokens won't carry it. Effectively a slow rollback.
  • Unmap a tool → next SDK policy refresh, that tool starts returning 403 to everyone.
  • Disable default role → new users get nothing on first login. Existing bindings persist.
  • Rotate the secret → old SDK instances start failing introspection until they're restarted with the new credentials.

Drift events make these changes auditable. If a customer reports "tool started returning 403 at 2pm Tuesday," the drift event log is your first stop.

Dismissing events

Click the dismiss icon on a row. POST /authsec/resource-servers/:id/drift-events/:event_id/dismiss marks the event acknowledged. The row stays in the database — dismissal is bookkeeping, not deletion.

Workaround: MCP server logs

Until the runtime metrics endpoints ship, the Go SDK's structured logging is your best signal. Wire it into your observability stack:

cfg := authsec.Config{
// ...
Logger: slog.New(slog.NewJSONHandler(os.Stdout, nil)),
}

The SDK emits structured events for:

  • Every token validation attempt (success and failure)
  • Every authorization decision (allow / deny with reason)
  • Every policy refresh from the scope matrix client
  • Manifest publish results

Most observability backends (Datadog, Honeycomb, Grafana Loki) can ingest JSON log lines and let you build counters and dashboards on top. A reasonable starting set of dashboards:

  • Authorization denials by tool_name and reason (5xx vs 403 vs 401)
  • Token validation latency p50/p95
  • Policy refresh failures

This isn't a replacement for the eventual Monitor tab — admins still want the in-product view — but it's what you have today.

What's coming

The plan lists these as TODO, not done:

  • GET /authsec/resource-servers/:id/metrics — request totals, denial rates, error breakdown by reason. Aggregated server-side.
  • GET /authsec/resource-servers/:id/access-logs — per-request audit trail with user_id, client_id, tool_name, timestamp, outcome. Useful for "who called what when."
  • Real-time event stream — WebSocket or SSE feed of drift events plus access logs as they happen, so the Monitor tab updates without polling.

When these land, this page will document them with the same structure as the drift events catalog above.

Auth scheme

EndpointAuth
GET /authsec/resource-servers/:id/drift-eventsAdmin JWT
POST /authsec/resource-servers/:id/drift-events/:event_id/dismissAdmin JWT

None of these are SDK-facing.