-
-
Notifications
You must be signed in to change notification settings - Fork 92
Description
Summary
Create a new @fedify/debugger package that provides an embedded real-time ActivityPub debug dashboard. It works as a proxy implementing the Federation interface, wrapping the original federation object and serving an SSR-based web UI using Hono internally.
This issue is a concrete implementation of #234, based on the architecture decision in #323 (OTel-based approach) and the FedifySpanExporter implemented in #497.
Design
A proxy implementing the Federation interface
The debugger fully implements Federation<TContextData>. It overrides only the fetch() method; all other methods (startQueue, processQueuedTask, createContext, setActorDispatcher, etc.) are delegated to the inner Federation object as-is.
This means it can be used as a drop-in replacement anywhere a Federation object is expected, including existing framework integration packages (@fedify/hono, @fedify/express, @fedify/h3, etc.):
import { createFederationDebugger } from "@fedify/debugger";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import { federation } from "@fedify/hono";
import { Hono } from "hono";
import {
NodeTracerProvider,
SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-node";
const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
ttl: Temporal.Duration.from({ hours: 1 }),
});
const tracerProvider = new NodeTracerProvider();
tracerProvider.addSpanProcessor(new SimpleSpanProcessor(exporter));
const fed = createFederation({ kv, tracerProvider });
// Wrap federation with debugger:
const dbg = createFederationDebugger(fed, { exporter });
// Use with any framework integration as-is:
const app = new Hono();
app.use(federation(dbg, (ctx) => undefined));How fetch() works
Request
│
├─ /__debug__/* → Hono app (SSR dashboard)
│ ├─ GET / → traces list page
│ ├─ GET /traces/:id → trace detail page
│ └─ GET /api/traces → JSON API (polling)
│
└─ everything else → federation.fetch()
Requests matching the debugger path prefix are handled by the internal Hono app. Everything else is delegated to the original Federation.fetch(). This is implemented by intercepting requests at the point where the onNotFound callback would be invoked.
Internal implementation
Hono is included as a regular dependency (not a peer dependency, since it is an internal implementation detail):
- Routing: debugger path matching
- JSX SSR: dashboard page rendering via
hono/jsx - Static assets: CSS embedded inline
API
interface FederationDebuggerOptions {
/** The path prefix for the debug dashboard. Defaults to "/__debug__". */
path?: string;
/** The FedifySpanExporter to query trace data from. */
exporter: FedifySpanExporter;
}
function createFederationDebugger<TContextData>(
federation: Federation<TContextData>,
options: FederationDebuggerOptions,
): Federation<TContextData>;The return type is Federation<TContextData> itself, so it can be used as a drop-in replacement in any context where a Federation object is expected.
MVP scope
Pages
-
Traces list (
GET /__debug__/)- Displays recent traces via
exporter.getRecentTraces() - Shows trace ID (first 8 characters), activity types, timestamp, and activity count for each trace
- Each trace links to its detail page
- Displays recent traces via
-
Trace detail (
GET /__debug__/traces/:traceId)- Displays all activities in a trace via
exporter.getActivitiesByTraceId(traceId) - Shows direction (inbound/outbound), activity type, actor, and timestamp for each activity
- Expandable activity JSON
- Signature verification details for inbound activities
- Target inbox URL for outbound activities
- Displays all activities in a trace via
Polling-based updates
- JSON API (
GET /__debug__/api/traces)- Returns
getRecentTraces()as JSON - The frontend polls this endpoint periodically to refresh the list
- Implemented with a simple inline
<script>
- Returns
Out of scope (future work)
- WebSocket/SSE-based real-time streaming
- Filtering UI by activity type, actor, or direction
- Retry queue management
- Authentication/access control for production environments
Package structure
packages/debugger/
├── deno.json
├── package.json
├── tsdown.config.ts
└── src/
├── mod.ts # createFederationDebugger()
├── mod.test.ts
└── views/
├── layout.tsx # HTML layout
├── traces-list.tsx # Traces list page
└── trace-detail.tsx # Trace detail page
Dependencies
| Dependency | Type | Reason |
|---|---|---|
@fedify/fedify |
peerDependencies |
Federation, FedifySpanExporter |
hono |
dependencies |
Internal routing and JSX SSR |
Metadata
Metadata
Assignees
Labels
Type
Projects
Status