Documentation
¶
Overview ¶
Package stream — additions: the `agents.*` HTTP handler. Like `tools.*` and `memory.*`, the eight Agents-page methods are one-shot request/response — POST JSON in, JSON out — and the handler lives in the stream package because its identity + scope-claim gating reuses the same `resolveIdentity` / `auth.HasScope` machinery the subscription surface uses.
Route shape:
POST /v1/agents/{method}
where {method} is the canonical method's verb suffix:
list | get | tools | memory | governance | skills | permissions | metrics
The handler reads identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers (fallback), decodes the JSON body into the method-specific wire request, dispatches into the agentsprotocol.Service, and encodes the response. On failure, a JSON error body with the canonical Protocol Code, identical in shape to the REST control transport's error body.
All eight `agents.*` methods are READ-ONLY projections of the Agent Registry. The five agent-control verbs the Console exposes (Pause / Drain / Restart / Force-Stop / Deregister) are NOT served here — they are the EXISTING shipped `registry.*` control verbs and Harbor mints no control method (CLAUDE.md §13).
Identity is mandatory: a missing / incomplete (tenant, user, session) triple fails closed with CodeIdentityRequired (401). `agent_id` is a registration identity, not an isolation filter — the runtime scopes by the tuple, never by `agent_id` (CLAUDE.md §6).
Package stream — additions: the `auth.*` HTTP handler. Like `tools.*` and `tasks.*`, the single `auth.*` method (`auth.rotate_token`) is one-shot request/response — POST JSON in, JSON out — and the handler lives in the stream package because its identity + scope-claim gating reuses the same `resolveIdentity` / `auth.HasScope` machinery the subscription surface uses.
Route shape:
POST /v1/auth/{method}
where {method} is the canonical method's verb suffix:
rotate_token
`auth.rotate_token` is the ONE net-new Protocol method Harbor ships — the Console Settings page is otherwise a pure consumer of the 72f / 72g posture surfaces. It is an ADMIN method: it rotates the operator's current Protocol-auth token and requires the verified `auth.ScopeAdmin` claim (closed two-scope set — there is NO `auth.admin` scope). A request without the claim is rejected 403 with the canonical CodeIdentityScopeRequired Code. Every successful rotation emits a redacted `audit.admin_scope_used` event through the shipped audit.Redactor (the emit lives in auth.RotateSurface — the handler never bypasses the audit redactor; CLAUDE.md §7 rule 6, §13).
Package stream — additions: the Console Flows-page HTTP handler. Like `events.aggregate` and `pause.list`, these are one-shot request/response endpoints — POST JSON in, JSON out. They live in the stream package because their identity + cross-tenant scope-claim gating is the same one Subscribe / Aggregate / PauseList use, and they share the route prefix family the Console surface registers.
Route shapes (all POST):
POST /v1/flows/list — paginated flow catalog POST /v1/flows/describe — a flow's engine-graph description POST /v1/flows/runs/list — a flow's paginated run history POST /v1/flows/runs/describe — a single run's per-node timeline POST /v1/flows/run — invoke a one-shot run (mutating) POST /v1/flows/metrics — a flow's sparkline metrics
Five routes are read-only; `flows/run` mutates and is gated on the verified `auth.ScopeAdmin` claim (closed two-scope set — NO new scope is minted). Every route is identity-mandatory.
The handler emits a per-page audit event on every dispatch: `flows.page_viewed` for the five reads, `flows.run_invoked` for the mutating run. The events flow through the canonical EventBus so the Console activity feed and the audit log see Flows-page traffic.
FlowsHandler is a concurrency-safe compiled artifact — surface / bus / logger are set once at construction; ServeHTTP holds no per-request state.
Package stream — additions: the `events.aggregate` HTTP handler. Unlike `events.subscribe` (long-lived SSE), this is a one-shot request/response — POST JSON in, JSON out. It lives in the stream package because it shares the same events- subsystem dependencies and route prefix (`/v1/events*`), and its scope-claim gating is the same one Subscribe uses.
Route shape:
POST /v1/events/aggregate
The handler reads identity from r.Context() (auth.Middleware) and gates cross-tenant filters on auth.HasScope(ScopeAdmin) OR auth.HasScope(ScopeConsoleFleet). The response body is the wire EventAggregateResponse JSON; on failure, a JSON error body with the canonical Protocol Code.
Package stream — additions: the three `memory.*` read handlers. Like `events.aggregate` and `pause.list`, these are one-shot request/response — POST JSON in, JSON out — and they live in the stream package because their identity + cross-tenant scope-claim gating is the same one Subscribe / Aggregate / PauseList use, and they share the route prefix family the Console subscription surface registers.
Route shapes:
POST /v1/memory/list POST /v1/memory/get POST /v1/memory/health
The handler reads identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers (fallback), decodes the JSON body, gates cross-tenant filters on auth.HasScope(ScopeAdmin) OR auth.HasScope(ScopeConsoleFleet) — the admin closed two-scope set, NO new memory scope (audit B1) — projects the answer from the memory subsystem, and encodes the response. The response body is the wire types.Memory* JSON; on failure, a JSON error body with the canonical Protocol Code.
All three methods are READ-ONLY. The memory mutation surface (`memory.put` / `memory.delete`) is deferred to a later phase / post-V1 (page-memory.md §10); this handler ships no mutation path.
Package stream — additions: the `pause.list` HTTP handler. Like `events.aggregate`, this is a one-shot request/response — POST JSON in, JSON out — and it lives in the stream package because its identity + cross-tenant scope-claim gating is the same one Subscribe / Aggregate use, and it shares the route prefix family the Console subscription surface registers.
Route shape:
POST /v1/pause/list
The handler reads identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers (fallback), decodes the JSON body into a types.PauseListRequest, gates cross-tenant filters on auth.HasScope(ScopeAdmin), projects the snapshot from the unified pause/resume Coordinator, applies the heavy-content bypass on each row, and encodes the response. The response body is the wire types.PauseListResponse JSON; on failure, a JSON error body with the canonical Protocol Code.
pause.list is READ-ONLY against the Coordinator — it does NOT call Resume, does NOT clear checkpoints. Resume actions continue through the `resume` / `approve` / `reject` control methods. The unified pause/resume primitive is never bypassed: pause.list reads the shipped Coordinator state, it does not reinvent pause coordination (CLAUDE.md §7 rule 4, §13).
Package stream — addition: the Console Playground-page `runs.set_overrides` HTTP handler. Like the Sessions / Tasks / Flows page handlers, this is a one-shot request/response endpoint — POST JSON in, JSON out. It lives in the stream package because its identity resolution + defence-in-depth body-identity check are the same `resolveIdentity` machinery the other Console-page handlers use.
Route shape (POST):
POST /v1/runs/set_overrides — record the next-message override
The route is identity-mandatory. The override's target session (`overrides.session_id`) MUST equal the caller's verified session; the runs/protocol.Service rejects a cross-session target with CodeScopeMismatch (403). `runs.set_overrides` is NOT an admin method — it records an override for the operator's OWN session, so no cross-tenant scope claim is consulted.
RunsHandler is a concurrency-safe compiled artifact — service / logger are set once at construction; ServeHTTP holds no per-request state.
Package stream — additions: the Console Sessions-page HTTP handler. Like `events.aggregate`, `pause.list`, and the Flows-page handler, these are one-shot request/response endpoints — POST JSON in, JSON out. They live in the stream package because their identity + cross-tenant scope-claim gating is the same `resolveIdentity` / `auth.HasScope` machinery the subscription surface uses.
Route shapes (both POST):
POST /v1/sessions/list — paginated, filtered session catalog POST /v1/sessions/inspect — a single session's full snapshot
Both routes are read-only and identity-mandatory. A cross-tenant `sessions.list` filter (a `tenant_ids` entry outside the caller's verified tenant) is gated on the verified `auth.ScopeAdmin` claim (closed two-scope set — NO new scope is minted); the sessions/protocol.Service emits an `audit.admin_scope_used` event on every successful admin-scope query.
SessionsHandler is a concurrency-safe compiled artifact — service / logger are set once at construction; ServeHTTP holds no per-request state.
Package stream is the Harbor Protocol SSE event transport — the server→client half of the wire binding RFC §5.4 resolves to (SSE for events + REST/JSON for control). It is a thin adapter over the events.EventBus: a Handler opens a triple-scoped events.Subscription and frames each events.Event as an SSE block (frame.go). The SSE transport adds the wire framing and the connection lifecycle; it adds NO second event channel — the "one bus, no parallel observability channel" is load-bearing.
The route shape ¶
GET /v1/events
The identity triple is carried in request headers (X-Harbor-Tenant / X-Harbor-User / X-Harbor-Session) — a header carrier, not a query string, so the triple is not logged in access logs by default and the JWT validation slots in at the same choke point. An optional X-Harbor-Event-Type header (repeatable) narrows the subscription's event-type selector.
Identity at the edge (RFC §5.5, CLAUDE.md §6) ¶
The handler resolves the triple from the headers and rejects a request with any missing component closed — HTTP 401, before any subscription is opened. The SSE stream is ALWAYS triple-scoped: events.Filter.Admin (cross-tenant fan-in) is NOT exposed on the wire in a later phase — it needs the cryptographic scope claim Harbor adds. resolveIdentity is the single choke point slots JWT validation into.
Reconnect cursor ¶
SSE's native reconnect mechanism is the Last-Event-ID header: a client that drops echoes back the `id:` of the last frame it saw. The handler maps that onto an events.Cursor and, when the bus driver implements events.Replayer, replays the events strictly newer than the cursor before live-tailing — so a reconnecting client does not miss the gap. When the driver does not support replay (or replay is configured off), the handler live-tails from the reconnect point and emits a single explicit `stream.replay_unavailable` comment frame so the gap is SURFACED, never silently masked (CLAUDE.md §5).
Concurrent reuse ¶
Handler is a compiled artifact: the bus, the logger, the keepalive interval and the clock are set once at construction and never mutated. ServeHTTP holds no per-request state on the Handler — each request gets its own events.Subscription, its own keepalive ticker, and its own goroutine, all torn down before ServeHTTP returns. One Handler serves N concurrent streams safely; the goroutine for a stream is cancelled by that request's ctx, never by a shared handler-level ctx (CLAUDE.md §5 "Concurrency"). internal/protocol/transports/ concurrent_test.go pins it under -race.
Package stream — additions: the `tasks.*` HTTP handler. Like `tools.*` and `pause.list`, the two Tasks-page read methods are one-shot request/response — POST JSON in, JSON out — and the handler lives in the stream package because its identity + cross-tenant scope-claim gating reuses the same `resolveIdentity` / `auth.HasScope` machinery the subscription surface uses.
Route shape:
POST /v1/tasks/{method}
where {method} is the canonical method's verb suffix:
list | get
The handler reads identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers (fallback), decodes the JSON body into the method-specific wire request, computes the verified `auth.ScopeAdmin` claim (consulted by `tasks.list` only for a cross-tenant fan-in), dispatches into the tasksprotocol.Service, and encodes the response. On failure, a JSON error body with the canonical Protocol Code, identical in shape to the REST control transport's error body.
The handler is READ-ONLY: both methods are pure reads. The Console Tasks page consumes the EXISTING task-control verbs (`cancel` / `pause` / `resume` / `prioritize` / `approve` / `reject`) for mutation through the control transport — there is NO `tasks.*` mutating method (CLAUDE.md §13 "no parallel implementations").
Package stream — additions: the `tools.*` HTTP handler. Like `pause.list` and `events.aggregate`, the seven Tools- page methods are one-shot request/response — POST JSON in, JSON out — and the handler lives in the stream package because its identity + cross-tenant scope-claim gating reuses the same `resolveIdentity` / `auth.HasScope` machinery the subscription surface uses.
Route shape:
POST /v1/tools/{method}
where {method} is the canonical method's verb suffix:
list | get | describe | metrics | content_stats | set_approval_policy | revoke_oauth
The handler reads identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers (fallback), decodes the JSON body into the method-specific wire request, gates the two admin methods on the verified `auth.ScopeAdmin` claim (there is NO `tools.admin` scope), dispatches into the toolsprotocol.Service, and encodes the response. On failure, a JSON error body with the canonical Protocol Code, identical in shape to the REST control transport's error body.
The handler is READ-MOSTLY: five of the seven methods are pure reads. The two admin methods mutate runtime tool state and emit an `audit.admin_scope_used` event through the shipped audit.Redactor (the emit lives in toolsprotocol.Service — the handler never bypasses the audit redactor; CLAUDE.md §7 rule 6, §13).
Index ¶
- Constants
- Variables
- type AgentsHandler
- type AgentsOption
- type AggregateHandler
- type AggregateOption
- type AuthHandler
- type AuthOption
- type FlowsHandler
- type FlowsOption
- type FlowsPageViewedPayload
- type FlowsRunInvokedPayload
- type Handler
- type MemoryHandler
- func (h *MemoryHandler) DeleteHandler() http.Handler
- func (h *MemoryHandler) GetHandler() http.Handler
- func (h *MemoryHandler) HealthHandler() http.Handler
- func (h *MemoryHandler) ListHandler() http.Handler
- func (h *MemoryHandler) PutHandler() http.Handler
- func (h *MemoryHandler) StrategyTraceHandler() http.Handler
- type MemoryOption
- type Option
- type PauseListHandler
- type PauseListOption
- type RunsHandler
- type RunsOption
- type SessionsHandler
- type SessionsOption
- type TasksHandler
- type TasksOption
- type ToolsHandler
- type ToolsOption
Constants ¶
const ( // EventTypeFlowsPageViewed — emitted on every read dispatch // (flows.list / describe / runs.list / runs.describe / metrics). EventTypeFlowsPageViewed events.EventType = "flows.page_viewed" // EventTypeFlowsRunInvoked — emitted when a `flows.run` dispatch is // accepted. The mutating-action audit signal. EventTypeFlowsRunInvoked events.EventType = "flows.run_invoked" )
Flows-page audit event types. They flow through the canonical EventBus so the Console activity feed + audit log see Flows-page traffic. Registered from this package's init().
const ( MemoryListRoutePattern = "POST /v1/memory/list" MemoryGetRoutePattern = "POST /v1/memory/get" MemoryHealthRoutePattern = "POST /v1/memory/health" MemoryStrategyTraceRoutePattern = "POST /v1/memory/strategy_trace" MemoryPutRoutePattern = "POST /v1/memory/put" MemoryDeleteRoutePattern = "POST /v1/memory/delete" )
Memory route patterns the handler registers under. Exported so internal/protocol/transports can mount each route under the same pattern it documents.
const ( HeaderTenant = "X-Harbor-Tenant" HeaderUser = "X-Harbor-User" HeaderSession = "X-Harbor-Session" HeaderRun = "X-Harbor-Run" HeaderEventType = "X-Harbor-Event-Type" )
Identity-carrier header names. The triple travels in headers, not a query string, so it does not land in access logs by default and so the JWT validation replaces a single resolve step.
HeaderRun is optional — when present, the subscription is run-scoped (events.Filter.Run is set, so only events with a matching RunID flow through). When absent, the subscription is session-scoped (the default; every run in the session is observed). Added in PR #91per checkpoint audit WARN-5.
const AgentsRoutePattern = "POST /v1/agents/{method}"
AgentsRoutePattern is the http.ServeMux pattern the Agents handler registers under. The {method} wildcard is read via r.PathValue.
const AggregateRoutePattern = "POST /v1/events/aggregate"
AggregateRoutePattern is the http.ServeMux pattern the events-aggregate handler registers under. Exported so internal/protocol/transports can mount the handler under the same pattern it documents.
const AuthRoutePattern = "POST /v1/auth/{method}"
AuthRoutePattern is the http.ServeMux pattern the auth handler registers under. The {method} wildcard is read via r.PathValue.
const FlowsRoutePattern = "POST /v1/flows/"
FlowsRoutePattern is the http.ServeMux prefix pattern the Flows-page handler registers under. The handler internally branches on the trailing path segment to dispatch the six methods. Exported so internal/protocol/transports can mount the handler under the same prefix it documents.
const PauseListRoutePattern = "POST /v1/pause/list"
PauseListRoutePattern is the http.ServeMux pattern the pause-list handler registers under. Exported so internal/protocol/transports can mount the handler under the same pattern it documents.
const RoutePattern = "GET /v1/events"
RoutePattern is the http.ServeMux pattern the SSE transport registers under. Exported so internal/protocol/transports can mount the handler under the same pattern it documents.
const RunsRoutePattern = "POST /v1/runs/"
RunsRoutePattern is the http.ServeMux prefix pattern the Runs-page handler registers under. The handler internally branches on the trailing path segment to dispatch.
const SessionsRoutePattern = "POST /v1/sessions/"
SessionsRoutePattern is the http.ServeMux prefix pattern the Sessions-page handler registers under. The handler internally branches on the trailing path segment to dispatch the two methods.
const TasksRoutePattern = "POST /v1/tasks/{method}"
TasksRoutePattern is the http.ServeMux pattern the Tasks handler registers under. The {method} wildcard is read via r.PathValue.
const ToolsRoutePattern = "POST /v1/tools/{method}"
ToolsRoutePattern is the http.ServeMux pattern the Tools handler registers under. The {method} wildcard is read via r.PathValue.
Variables ¶
var ErrAgentsMisconfigured = errors.New("stream: agents handler missing a mandatory dependency")
ErrAgentsMisconfigured — NewAgentsHandler was called with a nil agentsprotocol.Service.
var ErrAggregateMisconfigured = errors.New("stream: aggregate handler missing a mandatory dependency")
ErrAggregateMisconfigured — NewAggregateHandler was called with a nil Aggregator.
var ErrAuthMisconfigured = errors.New("stream: auth handler missing a mandatory dependency")
ErrAuthMisconfigured — NewAuthHandler was called with a nil auth.RotateSurface.
var ErrFlowsMisconfigured = errors.New("stream: flows handler missing a mandatory dependency")
ErrFlowsMisconfigured — NewFlowsHandler was called with a nil mandatory dependency.
var ErrMemoryHandlerMisconfigured = errors.New("stream: memory handler missing a mandatory dependency")
ErrMemoryHandlerMisconfigured — NewMemoryHandler was called with a nil mandatory dependency (MemoryStore, ArtifactStore, or the heavy-content threshold was non-positive).
var ErrMisconfigured = errors.New("stream: SSE transport missing a mandatory dependency")
ErrMisconfigured — NewHandler was called with a nil EventBus.
var ErrPauseListMisconfigured = errors.New("stream: pause.list handler missing a mandatory dependency")
ErrPauseListMisconfigured — NewPauseListHandler was called with a nil mandatory dependency (Coordinator, ArtifactStore, or the heavy-content threshold was non-positive).
var ErrRunsMisconfigured = errors.New("stream: runs handler missing a mandatory dependency")
ErrRunsMisconfigured — NewRunsHandler was called with a nil runs/protocol.Service.
var ErrSessionsMisconfigured = errors.New("stream: sessions handler missing a mandatory dependency")
ErrSessionsMisconfigured — NewSessionsHandler was called with a nil sessions/protocol.Service.
var ErrTasksMisconfigured = errors.New("stream: tasks handler missing a mandatory dependency")
ErrTasksMisconfigured — NewTasksHandler was called with a nil tasksprotocol.Service.
var ErrToolsMisconfigured = errors.New("stream: tools handler missing a mandatory dependency")
ErrToolsMisconfigured — NewToolsHandler was called with a nil toolsprotocol.Service.
Functions ¶
This section is empty.
Types ¶
type AgentsHandler ¶
type AgentsHandler struct {
// contains filtered or unexported fields
}
AgentsHandler serves `POST /v1/agents/{method}`. It is the wire adapter over an agentsprotocol.Service: resolve identity, decode the request, dispatch, encode. The handler is a concurrency-safe compiled artifact — every field is set once at construction; ServeHTTP holds no per-request state.
func NewAgentsHandler ¶
func NewAgentsHandler(service *agentsprotocol.Service, opts ...AgentsOption) (*AgentsHandler, error)
NewAgentsHandler builds the Agents handler over an agentsprotocol.Service. service is mandatory — a nil fails loud with ErrAgentsMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5). The returned *AgentsHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*AgentsHandler) ServeHTTP ¶
func (h *AgentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity, decodes the method-specific wire request, dispatches into the agentsprotocol.Service, and encodes the response.
type AgentsOption ¶
type AgentsOption func(*AgentsHandler)
AgentsOption configures NewAgentsHandler at construction.
func WithAgentsLogger ¶
func WithAgentsLogger(l *slog.Logger) AgentsOption
WithAgentsLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type AggregateHandler ¶
type AggregateHandler struct {
// contains filtered or unexported fields
}
AggregateHandler serves `POST /v1/events/aggregate`. It is the wire adapter over an *events.Aggregator: decode the request body, gate on scope claim if the filter is cross-tenant, dispatch, encode the response. The handler is a concurrency-safe compiled artifact — bus and logger are set once at construction; ServeHTTP holds no per-request state.
func NewAggregateHandler ¶
func NewAggregateHandler(aggregator *events.Aggregator, opts ...AggregateOption) (*AggregateHandler, error)
NewAggregateHandler builds the events-aggregate handler over an *events.Aggregator. aggregator is mandatory — a nil fails loud with ErrAggregateMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5).
The returned *AggregateHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*AggregateHandler) ServeHTTP ¶
func (h *AggregateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers ( fallback), decodes the JSON body into an EventAggregateRequest, gates on cross-tenant scope, dispatches to the Aggregator, and encodes the response.
type AggregateOption ¶
type AggregateOption func(*AggregateHandler)
AggregateOption configures NewAggregateHandler at construction.
func WithAggregateLogger ¶
func WithAggregateLogger(l *slog.Logger) AggregateOption
WithAggregateLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type AuthHandler ¶
type AuthHandler struct {
// contains filtered or unexported fields
}
AuthHandler serves `POST /v1/auth/{method}`. It is the wire adapter over an *auth.RotateSurface: resolve identity + scopes, decode the request, dispatch, encode. The handler is a concurrency-safe compiled artifact — every field is set once at construction; ServeHTTP holds no per-request state.
func NewAuthHandler ¶
func NewAuthHandler(surface *auth.RotateSurface, opts ...AuthOption) (*AuthHandler, error)
NewAuthHandler builds the auth handler over an *auth.RotateSurface. surface is mandatory — a nil fails loud with ErrAuthMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5). The returned *AuthHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*AuthHandler) ServeHTTP ¶
func (h *AuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity + scopes, decodes the method-specific wire request, dispatches into the auth.RotateSurface, and encodes the response.
type AuthOption ¶
type AuthOption func(*AuthHandler)
AuthOption configures NewAuthHandler at construction.
func WithAuthLogger ¶
func WithAuthLogger(l *slog.Logger) AuthOption
WithAuthLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type FlowsHandler ¶
type FlowsHandler struct {
// contains filtered or unexported fields
}
FlowsHandler serves the six `POST /v1/flows/*` routes. It is the wire adapter over a *flowprotocol.Surface: decode the request, dispatch to the surface, emit the per-page audit event, encode the response.
func NewFlowsHandler ¶
func NewFlowsHandler(surface *flowprotocol.Surface, opts ...FlowsOption) (*FlowsHandler, error)
NewFlowsHandler builds the Flows-page handler over a *flowprotocol.Surface. surface is mandatory — a nil fails loud with ErrFlowsMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5).
The returned *FlowsHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*FlowsHandler) ServeHTTP ¶
func (h *FlowsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity, branches on the trailing path segment, decodes the body, dispatches to the surface, emits the audit event, and encodes the response.
type FlowsOption ¶
type FlowsOption func(*FlowsHandler)
FlowsOption configures NewFlowsHandler at construction.
func WithFlowsBus ¶
func WithFlowsBus(b events.EventBus) FlowsOption
WithFlowsBus wires the canonical events.EventBus into the handler so every dispatch emits its per-page audit event. The bus is OPTIONAL — when not supplied the handler still serves every route, but the audit events are not emitted (the handler logs the dispatch at Info instead so Flows-page traffic is never fully silent).
func WithFlowsLogger ¶
func WithFlowsLogger(l *slog.Logger) FlowsOption
WithFlowsLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type FlowsPageViewedPayload ¶
type FlowsPageViewedPayload struct {
events.SafeSealed
// Method is the canonical Protocol method name that ran.
Method string
// FlowID is the targeted flow id, when the method targets one.
FlowID string
// AdminScoped reports whether the read used the admin scope claim.
AdminScoped bool
}
FlowsPageViewedPayload is the typed payload for EventTypeFlowsPageViewed. It records which read method ran and the flow it targeted (empty for `flows.list`). It is a SafePayload — it carries no raw run output / no tool arguments (CLAUDE.md §7 rule 7).
type FlowsRunInvokedPayload ¶
type FlowsRunInvokedPayload struct {
events.SafeSealed
// FlowID is the invoked flow.
FlowID string
// RunID is the identifier of the accepted run.
RunID string
}
FlowsRunInvokedPayload is the typed payload for EventTypeFlowsRunInvoked. It records the invoked flow + the accepted run id. SafePayload — no input form, no output.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler is the Protocol SSE event transport. It is built once per Runtime process via NewHandler and shared across every stream request; ServeHTTP is safe for concurrent use by N goroutines.
func NewHandler ¶
NewHandler builds the Protocol SSE event transport over the events.EventBus. The bus is mandatory — a nil fails loud with ErrMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5).
The returned *Handler is immutable after construction and safe for concurrent use by N goroutines.
func (*Handler) ServeHTTP ¶
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves the identity triple at the edge, opens a triple-scoped events.Subscription, optionally replays from a Last-Event-ID reconnect cursor, and live-tails events as SSE frames until the client disconnects or the bus closes.
type MemoryHandler ¶
type MemoryHandler struct {
// contains filtered or unexported fields
}
MemoryHandler serves the three `memory.*` read routes. It is the wire adapter over the memory subsystem: decode the request, gate on the scope claim if the filter is cross-tenant, project the answer via internal/memory/protocol, encode the response. The handler is a safe for concurrent reuse compiled artifact — every field is set once at construction; ServeHTTP holds no per-request state.
func NewMemoryHandler ¶
func NewMemoryHandler(store memory.MemoryStore, artStore artifacts.ArtifactStore, threshold int, opts ...MemoryOption) (*MemoryHandler, error)
NewMemoryHandler builds the memory handler over a memory.MemoryStore + an artifacts.ArtifactStore. store and artStore are mandatory — a nil fails loud with ErrMemoryHandlerMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5). threshold is the configured heavy-content byte size (cfg.Artifacts.HeavyOutputThresholdBytes); a non-positive value fails loud (a zero threshold would route every value).
The returned *MemoryHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*MemoryHandler) DeleteHandler ¶ added in v1.3.0
func (h *MemoryHandler) DeleteHandler() http.Handler
DeleteHandler returns the http.Handler for `POST /v1/memory/delete`.
func (*MemoryHandler) GetHandler ¶
func (h *MemoryHandler) GetHandler() http.Handler
GetHandler returns the http.Handler for `POST /v1/memory/get`.
func (*MemoryHandler) HealthHandler ¶
func (h *MemoryHandler) HealthHandler() http.Handler
HealthHandler returns the http.Handler for `POST /v1/memory/health`.
func (*MemoryHandler) ListHandler ¶
func (h *MemoryHandler) ListHandler() http.Handler
ListHandler returns the http.Handler for `POST /v1/memory/list`.
func (*MemoryHandler) PutHandler ¶ added in v1.3.0
func (h *MemoryHandler) PutHandler() http.Handler
PutHandler returns the http.Handler for `POST /v1/memory/put`.
func (*MemoryHandler) StrategyTraceHandler ¶ added in v1.3.0
func (h *MemoryHandler) StrategyTraceHandler() http.Handler
StrategyTraceHandler returns the http.Handler for `POST /v1/memory/strategy_trace`.
type MemoryOption ¶
type MemoryOption func(*MemoryHandler)
MemoryOption configures NewMemoryHandler at construction.
func WithMemoryAggregator ¶
func WithMemoryAggregator(a *events.Aggregator) MemoryOption
WithMemoryAggregator wires the events Aggregator into the handler so the `memory.list` / `memory.health` 24-hour counters (identity-rejected / recovery-dropped) can be computed. OPTIONAL — when not supplied, those two counters report 0; the page still renders and the right-rail cards subscribe to the live event stream for the real-time view. A nil aggregator is treated as "WithMemoryAggregator not supplied".
func WithMemoryBus ¶ added in v1.3.0
func WithMemoryBus(b events.EventBus) MemoryOption
WithMemoryBus wires the events bus the admin mutation methods (`memory.put` / `memory.delete`) publish their audit events on (`memory.item_put` / `memory.item_deleted`). OPTIONAL — when not supplied, the mutations still apply but emit no audit event; the production wiring (`harbor dev`) always supplies it so the mutation is audited (page-memory.md §9). A nil bus is treated as "not supplied".
func WithMemoryDriverName ¶
func WithMemoryDriverName(name string) MemoryOption
WithMemoryDriverName sets the configured memory-driver name surfaced on each `memory.list` row's Driver field and in the `memory.health` per-scope driver mapping. Empty (the default) reports `inmem`.
func WithMemoryLogger ¶
func WithMemoryLogger(l *slog.Logger) MemoryOption
WithMemoryLogger sets the slog.Logger the handler logs decode / projection failures to. A nil logger (the default) routes to slog.Default().
type Option ¶
type Option func(*Handler)
Option configures a Handler at construction time.
func WithKeepalive ¶
WithKeepalive overrides the interval between SSE keepalive comment frames. A value below minKeepalive is clamped up to the floor; a non-positive value is ignored (the default is kept). Tests drive the keepalive path deterministically by supplying a short interval — the keepalive frame is observable on the wire, so a short interval makes the path testable without a time.Sleep-as-synchronisation antipattern.
func WithLogger ¶
WithLogger sets the slog.Logger the handler logs subscription / streaming failures to. A nil logger (the default) routes to slog.Default().
type PauseListHandler ¶
type PauseListHandler struct {
// contains filtered or unexported fields
}
PauseListHandler serves `POST /v1/pause/list`. It is the wire adapter over a pauseresume.Coordinator: decode the request, gate on scope claim if the filter is cross-tenant, project the snapshot, apply the heavy-content bypass per row, encode the response. The handler is a concurrency-safe compiled artifact — every field is set once at construction; ServeHTTP holds no per-request state.
func NewPauseListHandler ¶
func NewPauseListHandler(coord pauseresume.Coordinator, store artifacts.ArtifactStore, threshold int, opts ...PauseListOption) (*PauseListHandler, error)
NewPauseListHandler builds the pause-list handler over a pauseresume.Coordinator + an artifacts.ArtifactStore. coord and store are mandatory — a nil fails loud with ErrPauseListMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5). threshold is the configured heavy-content byte size (cfg.Artifacts.HeavyOutputThresholdBytes); a non-positive value fails loud (a zero threshold would route every payload).
The returned *PauseListHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*PauseListHandler) ServeHTTP ¶
func (h *PauseListHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity from r.Context() (auth.Middleware) or the X-Harbor-* carrier headers (fallback), decodes the JSON body into a PauseListRequest, gates cross-tenant filters on scope, projects the Coordinator snapshot, applies the heavy-content bypass, and encodes the response.
type PauseListOption ¶
type PauseListOption func(*PauseListHandler)
PauseListOption configures NewPauseListHandler at construction.
func WithPauseListBus ¶
func WithPauseListBus(b events.EventBus) PauseListOption
WithPauseListBus wires the canonical events.EventBus into the handler so the heavy-content bypass can publish a `pause.payload_artifact_routed` observation when a heavy payload is routed through the ArtifactStore. The bus is OPTIONAL — when not supplied, the bypass still happens (the heavy payload is still routed to the ArtifactStore and shipped by-reference) but the observation event is not emitted; the handler logs the bypass at Info instead so the routing is never fully silent. A nil bus is treated as "WithPauseListBus not supplied".
func WithPauseListLogger ¶
func WithPauseListLogger(l *slog.Logger) PauseListOption
WithPauseListLogger sets the slog.Logger the handler logs decode / projection failures to. A nil logger (the default) routes to slog.Default().
type RunsHandler ¶
type RunsHandler struct {
// contains filtered or unexported fields
}
RunsHandler serves the `POST /v1/runs/*` routes. It is the wire adapter over a *runsprotocol.Service: resolve identity, branch on the trailing path segment, decode the request, dispatch, encode.
func NewRunsHandler ¶
func NewRunsHandler(service *runsprotocol.Service, opts ...RunsOption) (*RunsHandler, error)
NewRunsHandler builds the Runs-page handler over a *runsprotocol.Service. service is mandatory — a nil fails loud with ErrRunsMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5).
The returned *RunsHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*RunsHandler) ServeHTTP ¶
func (h *RunsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity, branches on the trailing path segment, decodes the body, dispatches to the service, and encodes the response.
type RunsOption ¶
type RunsOption func(*RunsHandler)
RunsOption configures NewRunsHandler at construction.
func WithRunsLogger ¶
func WithRunsLogger(l *slog.Logger) RunsOption
WithRunsLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type SessionsHandler ¶
type SessionsHandler struct {
// contains filtered or unexported fields
}
SessionsHandler serves the two `POST /v1/sessions/*` routes. It is the wire adapter over a *sessionsprotocol.Service: resolve identity, branch on the trailing path segment, decode the request, dispatch, encode.
func NewSessionsHandler ¶
func NewSessionsHandler(service *sessionsprotocol.Service, opts ...SessionsOption) (*SessionsHandler, error)
NewSessionsHandler builds the Sessions-page handler over a *sessionsprotocol.Service. service is mandatory — a nil fails loud with ErrSessionsMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5).
The returned *SessionsHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*SessionsHandler) ServeHTTP ¶
func (h *SessionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity, branches on the trailing path segment, decodes the body, dispatches to the service, and encodes the response.
type SessionsOption ¶
type SessionsOption func(*SessionsHandler)
SessionsOption configures NewSessionsHandler at construction.
func WithSessionsLogger ¶
func WithSessionsLogger(l *slog.Logger) SessionsOption
WithSessionsLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type TasksHandler ¶
type TasksHandler struct {
// contains filtered or unexported fields
}
TasksHandler serves `POST /v1/tasks/{method}`. It is the wire adapter over a tasksprotocol.Service: resolve identity, decode the request, compute the admin-scope claim, dispatch, encode. The handler is a safe for concurrent reuse compiled artifact — every field is set once at construction; ServeHTTP holds no per-request state.
func NewTasksHandler ¶
func NewTasksHandler(service *tasksprotocol.Service, opts ...TasksOption) (*TasksHandler, error)
NewTasksHandler builds the Tasks handler over a tasksprotocol.Service. service is mandatory — a nil fails loud with ErrTasksMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5). The returned *TasksHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*TasksHandler) ServeHTTP ¶
func (h *TasksHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity, decodes the method-specific wire request, dispatches into the tasksprotocol.Service, and encodes the response.
type TasksOption ¶
type TasksOption func(*TasksHandler)
TasksOption configures NewTasksHandler at construction.
func WithTasksLogger ¶
func WithTasksLogger(l *slog.Logger) TasksOption
WithTasksLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().
type ToolsHandler ¶
type ToolsHandler struct {
// contains filtered or unexported fields
}
ToolsHandler serves `POST /v1/tools/{method}`. It is the wire adapter over a toolsprotocol.Service: resolve identity, decode the request, gate admin methods on scope, dispatch, encode. The handler is a safe for concurrent reuse compiled artifact — every field is set once at construction; ServeHTTP holds no per-request state.
func NewToolsHandler ¶
func NewToolsHandler(service *toolsprotocol.Service, opts ...ToolsOption) (*ToolsHandler, error)
NewToolsHandler builds the Tools handler over a toolsprotocol.Service. service is mandatory — a nil fails loud with ErrToolsMisconfigured rather than building a handler that would nil-panic on the first request (CLAUDE.md §5). The returned *ToolsHandler is immutable after construction and safe for concurrent use by N goroutines.
func (*ToolsHandler) ServeHTTP ¶
func (h *ToolsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It resolves identity, decodes the method-specific wire request, gates admin methods on scope, dispatches into the toolsprotocol.Service, and encodes the response.
type ToolsOption ¶
type ToolsOption func(*ToolsHandler)
ToolsOption configures NewToolsHandler at construction.
func WithToolsLogger ¶
func WithToolsLogger(l *slog.Logger) ToolsOption
WithToolsLogger sets the slog.Logger the handler logs decode / dispatch failures to. A nil logger (the default) routes to slog.Default().