api

package
v0.0.0-...-e1638d3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package api — RFC 7807 Problem Detail error responses for the HELM API.

Package api — autonomy_handler.go serves the GlobalAutonomyState projection.

GET /api/autonomy/state

This handler computes GlobalAutonomyState on each request by reading from authoritative stores. It does NOT cache — the caller rate-limits via polling interval or subscribes via WebSocket for push.

Package api — decision_handler.go serves DecisionRequest CRUD.

Endpoints:

GET  /api/decisions            — list pending decisions for org
POST /api/decisions/:id/resolve — resolve a decision with chosen option
POST /api/decisions             — create a new decision (internal use)

Package api provides the OpenAI-compatible proxy endpoint for HELM. Enabled via HELM_ENABLE_OPENAI_PROXY=1, this intercepts tool calls through the PEP boundary, enforcing governance on every operation.

Package api implements the HELM Governance REST API.

Endpoints:

POST /api/v1/evaluate       — Evaluate a tool call through governance
GET  /api/v1/receipts/:id   — Retrieve a receipt
POST /api/v1/receipts/:id/complete — Record execution outcome
GET  /api/v1/verify/:session — Verify receipt chain for a session
GET  /api/v1/health         — Health check

This server backs Python, TypeScript, and Rust SDKs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HandleOpenAIProxy

func HandleOpenAIProxy(w http.ResponseWriter, r *http.Request)

func IdempotencyMiddleware

func IdempotencyMiddleware(store IdempotencyStorer) func(http.Handler) http.Handler

IdempotencyMiddleware ensures that mutating requests with an Idempotency-Key header are processed exactly once. Duplicate requests receive the cached response. When using MemoryIdempotencyStore, concurrent duplicate requests are serialized to prevent TOCTOU races.

func WithContextRateLimit

func WithContextRateLimit(next http.Handler, limitPerTenant int) http.Handler

WithContextRateLimit enforces rate limits based on context values (e.g. TenantID). This requires the context to be populated previously (e.g. by auth middleware).

func WriteBadRequest

func WriteBadRequest(w http.ResponseWriter, detail string)

WriteBadRequest writes a 400 error response.

func WriteConflict

func WriteConflict(w http.ResponseWriter, detail string)

WriteConflict writes a 409 error response (used for idempotency).

func WriteError

func WriteError(w http.ResponseWriter, status int, title, detail string)

WriteError writes an RFC 7807 Problem Detail JSON response.

func WriteErrorR

func WriteErrorR(w http.ResponseWriter, r *http.Request, status int, title, detail string)

WriteErrorR writes an RFC 7807 response enriched with request context (trace_id from X-Request-ID, instance from request URI).

func WriteForbidden

func WriteForbidden(w http.ResponseWriter, detail string)

WriteForbidden writes a 403 error response.

func WriteInternal

func WriteInternal(w http.ResponseWriter, err error)

WriteInternal writes a 500 error response. The err parameter is logged but NEVER exposed to the client.

func WriteMethodNotAllowed

func WriteMethodNotAllowed(w http.ResponseWriter)

WriteMethodNotAllowed writes a 405 error response.

func WriteNotFound

func WriteNotFound(w http.ResponseWriter, detail string)

WriteNotFound writes a 404 error response.

func WriteTooManyRequests

func WriteTooManyRequests(w http.ResponseWriter, retryAfterSecs int)

WriteTooManyRequests writes a 429 error response with Retry-After header.

func WriteUnauthorized

func WriteUnauthorized(w http.ResponseWriter, detail string)

WriteUnauthorized writes a 401 error response.

Types

type AddKeyRequest

type AddKeyRequest struct {
	TenantID  string `json:"tenant_id"`
	KeyID     string `json:"key_id"`
	PublicKey string `json:"public_key"` // hex-encoded Ed25519 public key
}

AddKeyRequest is the wire format for adding a trusted key.

type ApproveHandler

type ApproveHandler struct {
	// contains filtered or unexported fields
}

ApproveHandler handles POST /api/v1/kernel/approve This is the backend half of the HITL bridge. The frontend uses WebCrypto API to sign the intent hash, and this handler verifies the signature cryptographically.

func NewApproveHandler

func NewApproveHandler(allowedKeys []string) *ApproveHandler

NewApproveHandler creates a new approval handler with an authorized key list. Uses time.Now as the default clock; override with WithClock for testing.

func (*ApproveHandler) GetPendingApprovals

func (h *ApproveHandler) GetPendingApprovals() []*contracts.ApprovalRequest

GetPendingApprovals returns all pending approval requests.

func (*ApproveHandler) HandleApprove

func (h *ApproveHandler) HandleApprove(w http.ResponseWriter, r *http.Request)

HandleApprove processes a cryptographic approval from the operator UI.

Flow:

  1. Parse ApprovalReceipt from request body
  2. Verify the intent exists in pending queue
  3. Decode the approver's Ed25519 public key
  4. Verify the signature over IntentHash
  5. Mark the approval as APPROVED with the receipt
  6. Return 200 with the signed receipt

func (*ApproveHandler) RegisterPendingApproval

func (h *ApproveHandler) RegisterPendingApproval(req *contracts.ApprovalRequest)

RegisterPendingApproval adds an intent to the pending approval queue.

func (*ApproveHandler) WithClock

func (h *ApproveHandler) WithClock(clock func() time.Time) *ApproveHandler

WithClock overrides the time source for deterministic testing.

type AutonomyControlProvider

type AutonomyControlProvider interface {
	AutonomyStateProvider

	// SetGlobalMode transitions the org to a new global mode.
	SetGlobalMode(mode contracts.GlobalMode)

	// GetCurrentPosture returns the current posture for policy validation.
	GetCurrentPosture() contracts.Posture

	// GetCurrentGlobalMode returns the current global mode.
	GetCurrentGlobalMode() contracts.GlobalMode
}

AutonomyControlProvider extends AutonomyStateProvider with mutation capabilities. This allows the control endpoint to change the global mode.

type AutonomyHandler

type AutonomyHandler struct {
	// contains filtered or unexported fields
}

AutonomyHandler serves autonomy-related API endpoints.

func NewAutonomyHandler

func NewAutonomyHandler(provider AutonomyStateProvider) *AutonomyHandler

NewAutonomyHandler creates a new AutonomyHandler.

func (*AutonomyHandler) HandleControl

func (h *AutonomyHandler) HandleControl(w http.ResponseWriter, r *http.Request)

HandleControl serves POST /api/autonomy/control. Accepts {"action": "PAUSE|RUN|FREEZE|ISLAND"} and applies the mode transition.

func (*AutonomyHandler) HandleGetState

func (h *AutonomyHandler) HandleGetState(w http.ResponseWriter, r *http.Request)

HandleGetState serves GET /api/autonomy/state. Returns the current GlobalAutonomyState projection for the authenticated org.

func (*AutonomyHandler) Register

func (h *AutonomyHandler) Register(mux *http.ServeMux, adminAuth func(http.Handler) http.Handler)

Register mounts the autonomy routes on the given mux. The control endpoint requires admin auth (H-2: fail-closed if HELM_ADMIN_API_KEY unset). State endpoint is read-only and does not require auth.

type AutonomyStateProvider

type AutonomyStateProvider interface {
	// ComputeState derives the current GlobalAutonomyState from truth stores.
	ComputeState(orgID string) (*contracts.GlobalAutonomyState, error)
}

AutonomyStateProvider is the interface for computing the current autonomy state. Implementors should read from authoritative stores (ledger, event store, etc.) and return a derived projection.

type ContextResult

type ContextResult struct {
	QueryID string `json:"query_id"`
}

ContextResult represents a search result.

type DecisionHandler

type DecisionHandler struct {
	// contains filtered or unexported fields
}

DecisionHandler serves DecisionRequest API endpoints.

func NewDecisionHandler

func NewDecisionHandler(store DecisionStore) *DecisionHandler

NewDecisionHandler creates a new DecisionHandler.

func (*DecisionHandler) HandleDecisionByID

func (h *DecisionHandler) HandleDecisionByID(w http.ResponseWriter, r *http.Request)

HandleDecisionByID handles POST /api/decisions/:id/resolve.

func (*DecisionHandler) HandleDecisions

func (h *DecisionHandler) HandleDecisions(w http.ResponseWriter, r *http.Request)

HandleDecisions handles GET (list) and POST (create) on /api/decisions.

func (*DecisionHandler) Register

func (h *DecisionHandler) Register(mux *http.ServeMux)

Register mounts the decision routes on the given mux.

type DecisionStore

type DecisionStore interface {
	// List returns all decisions matching the given status filter (empty = all).
	List(orgID string, statusFilter contracts.DecisionRequestStatus) ([]contracts.DecisionRequest, error)

	// Get returns a single decision by ID.
	Get(id string) (*contracts.DecisionRequest, error)

	// Create persists a new DecisionRequest. Returns error if ID already exists.
	Create(dr *contracts.DecisionRequest) error

	// Update persists changes to an existing DecisionRequest.
	Update(dr *contracts.DecisionRequest) error
}

DecisionStore is the interface for persisting DecisionRequests. This abstraction allows swapping in-memory for ledger-backed storage.

type EvaluateRequest

type EvaluateRequest struct {
	Tool        string         `json:"tool"`
	Args        map[string]any `json:"args"`
	AgentID     string         `json:"agent_id"`
	EffectLevel string         `json:"effect_level"`
	SessionID   string         `json:"session_id"`
	Context     map[string]any `json:"context"`
}

EvaluateRequest is the JSON body sent by SDKs.

type EvaluateResponse

type EvaluateResponse struct {
	Allow        bool   `json:"allow"`
	Verdict      string `json:"verdict"`
	ReceiptID    string `json:"receipt_id"`
	DecisionID   string `json:"decision_id"`
	DecisionHash string `json:"decision_hash"`
	ReasonCode   string `json:"reason_code"`
	PolicyRef    string `json:"policy_ref"`
	LamportClock uint64 `json:"lamport_clock"`
}

EvaluateResponse is the JSON response sent back to SDKs.

type GlobalRateLimiter

type GlobalRateLimiter struct {
	// contains filtered or unexported fields
}

GlobalRateLimiter manages per-IP rate limiters.

func NewGlobalRateLimiter

func NewGlobalRateLimiter(rps, burst int) *GlobalRateLimiter

NewGlobalRateLimiter creates a new rate limiter. rps: requests per second allowed. burst: maximum burst size.

func (*GlobalRateLimiter) Middleware

func (rl *GlobalRateLimiter) Middleware(next http.Handler) http.Handler

Middleware returns a Handler that enforces rate limits.

func (*GlobalRateLimiter) WithTrustProxy

func (rl *GlobalRateLimiter) WithTrustProxy(trust bool) *GlobalRateLimiter

WithTrustProxy enables extraction of client IP from X-Forwarded-For / X-Real-IP headers. Only enable when HELM is behind a trusted reverse proxy.

type IdempotencyStorer

type IdempotencyStorer interface {
	Check(key string) (*cachedResponse, bool)
	Set(key string, statusCode int, headers http.Header, body []byte) error
}

IdempotencyStorer defines the interface for idempotency backends.

type InMemoryAutonomyProvider

type InMemoryAutonomyProvider struct {
	// contains filtered or unexported fields
}

InMemoryAutonomyProvider is a simple in-memory implementation of AutonomyStateProvider. It holds the current state and provides methods to update it. Production deployments should replace this with a ledger-backed implementation.

func NewInMemoryAutonomyProvider

func NewInMemoryAutonomyProvider() *InMemoryAutonomyProvider

NewInMemoryAutonomyProvider creates a provider with defaults.

func (*InMemoryAutonomyProvider) AddDecisionRequest

func (p *InMemoryAutonomyProvider) AddDecisionRequest(dr contracts.DecisionRequest)

AddDecisionRequest adds a decision to the blocker queue.

func (*InMemoryAutonomyProvider) AddRun

AddRun adds a run summary to the active runs.

func (*InMemoryAutonomyProvider) ComputeState

ComputeState derives GlobalAutonomyState from the in-memory state.

func (*InMemoryAutonomyProvider) GetCurrentGlobalMode

func (p *InMemoryAutonomyProvider) GetCurrentGlobalMode() contracts.GlobalMode

GetCurrentGlobalMode returns the current global mode.

func (*InMemoryAutonomyProvider) GetCurrentPosture

func (p *InMemoryAutonomyProvider) GetCurrentPosture() contracts.Posture

GetCurrentPosture returns the current posture.

func (*InMemoryAutonomyProvider) SetGlobalMode

func (p *InMemoryAutonomyProvider) SetGlobalMode(mode contracts.GlobalMode)

SetGlobalMode updates the global mode.

func (*InMemoryAutonomyProvider) SetPosture

func (p *InMemoryAutonomyProvider) SetPosture(posture contracts.Posture)

SetPosture updates the current posture.

type InMemoryDecisionStore

type InMemoryDecisionStore struct {
	// contains filtered or unexported fields
}

InMemoryDecisionStore is a simple in-memory DecisionStore. Production deployments should use a ledger-backed store.

func NewInMemoryDecisionStore

func NewInMemoryDecisionStore() *InMemoryDecisionStore

NewInMemoryDecisionStore creates an empty in-memory store.

func (*InMemoryDecisionStore) Create

Create adds a new decision to the store.

func (*InMemoryDecisionStore) Get

Get returns a decision by ID.

func (*InMemoryDecisionStore) List

List returns decisions filtered by org and status.

func (*InMemoryDecisionStore) Update

Update replaces an existing decision in the store.

type IngestRequest

type IngestRequest struct {
	TenantID string `json:"tenant_id"`
	SourceID string `json:"source_id"`
}

IngestRequest represents a request to ingest data from a source.

type IngestResponse

type IngestResponse struct {
	BatchID     string `json:"batch_id"`
	ReceiptID   string `json:"receipt_id"`
	EntityCount int    `json:"entity_count"`
	ChunkCount  int    `json:"chunk_count"`
	MerkleRoot  string `json:"merkle_root"`
	DecisionID  string `json:"decision_id"`
}

IngestResponse represents the result of an ingestion request.

type MemoryIdempotencyStore

type MemoryIdempotencyStore struct {
	// contains filtered or unexported fields
}

MemoryIdempotencyStore holds cached responses keyed by idempotency key (in-memory).

func NewIdempotencyStore

func NewIdempotencyStore(ttl time.Duration) *MemoryIdempotencyStore

NewIdempotencyStore creates a new in-memory idempotency store.

func (*MemoryIdempotencyStore) Acquire

func (s *MemoryIdempotencyStore) Acquire(key string) (*cachedResponse, bool)

Acquire attempts to claim exclusive processing rights for a key. Returns (cached, true) if a cached response exists, (nil, true) if the caller wins the race, or blocks until the first processor finishes and returns its cached response.

func (*MemoryIdempotencyStore) Check

func (s *MemoryIdempotencyStore) Check(key string) (*cachedResponse, bool)

Check returns a cached response if existing and valid.

func (*MemoryIdempotencyStore) Release

func (s *MemoryIdempotencyStore) Release(key string)

Release marks a key as no longer inflight and wakes any waiters.

func (*MemoryIdempotencyStore) Set

func (s *MemoryIdempotencyStore) Set(key string, statusCode int, headers http.Header, body []byte) error

Set stores a response.

type MemoryService

type MemoryService struct{}

MemoryService is the OSS kernel memory API boundary. Full memory/ingestion pipelines are outside the kernel TCB.

func NewMemoryService

func NewMemoryService() *MemoryService

NewMemoryService creates the bounded kernel memory service.

func (*MemoryService) HandleIngest

func (s *MemoryService) HandleIngest(w http.ResponseWriter, r *http.Request)

HandleIngest handles the /memory/ingest endpoint.

func (*MemoryService) HandleSearch

func (s *MemoryService) HandleSearch(w http.ResponseWriter, r *http.Request)

HandleSearch handles the /memory/search endpoint.

func (*MemoryService) Ingest

Ingest reports that the full ingestion pipeline is outside OSS kernel scope.

func (*MemoryService) Search

func (s *MemoryService) Search(ctx context.Context, query, tenantID string, maxResults int) (*ContextResult, error)

Search creates a kernel-scoped query handle for callers that need a receiptable boundary.

type OpenAIChatRequest

type OpenAIChatRequest struct {
	Model             string          `json:"model"`
	Messages          []OpenAIMessage `json:"messages"`
	Stream            bool            `json:"stream,omitempty"`
	ToolChoice        any             `json:"tool_choice,omitempty"`         // API-001: "auto", "none", "required", or {"type":"function","function":{"name":"..."}}
	ParallelToolCalls *bool           `json:"parallel_tool_calls,omitempty"` // API-001: Enable/disable parallel tool execution
	ResponseFormat    any             `json:"response_format,omitempty"`     // API-002: {"type":"json_object"} or {"type":"json_schema","json_schema":{...}}
	MaxTokens         *int            `json:"max_tokens,omitempty"`
	Temperature       *float64        `json:"temperature,omitempty"`
	TopP              *float64        `json:"top_p,omitempty"`
}

OpenAIChatRequest is the OpenAI-compatible request format. API-001/002: Includes tool_choice, parallel_tool_calls, and response_format for upstream provider pass-through.

type OpenAIChatResponse

type OpenAIChatResponse struct {
	ID      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`
	Model   string `json:"model"`
	Choices []struct {
		Index        int           `json:"index"`
		Message      OpenAIMessage `json:"message"`
		FinishReason string        `json:"finish_reason"`
	} `json:"choices"`
	Usage struct {
		PromptTokens     int `json:"prompt_tokens"`
		CompletionTokens int `json:"completion_tokens"`
		TotalTokens      int `json:"total_tokens"`
	} `json:"usage"`
}

OpenAIChatResponse is the OpenAI-compatible response format.

type OpenAIMessage

type OpenAIMessage struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

OpenAIMessage represents a message in the OpenAI chat format.

type OpenAIProxyConfig

type OpenAIProxyConfig struct {
	UpstreamURL  string `json:"upstream_url"`
	DefaultModel string `json:"default_model"`
}

OpenAIProxyConfig configures the OpenAI-compatible proxy.

type PostgresIdempotencyStore

type PostgresIdempotencyStore struct {
	// contains filtered or unexported fields
}

PostgresIdempotencyStore provides durable idempotency enforcement backed by PostgreSQL. Replaces the volatile InMemoryIdempotencyStore to survive process restarts.

func NewPostgresIdempotencyStore

func NewPostgresIdempotencyStore(db *sql.DB, ttl time.Duration) *PostgresIdempotencyStore

NewPostgresIdempotencyStore creates a new PostgreSQL-backed idempotency store.

func (*PostgresIdempotencyStore) Check

func (s *PostgresIdempotencyStore) Check(key string) (*cachedResponse, bool)

Check returns a cached response if the idempotency key was seen before and is within TTL.

func (*PostgresIdempotencyStore) Cleanup

func (s *PostgresIdempotencyStore) Cleanup()

Cleanup removes expired idempotency keys older than the TTL.

func (*PostgresIdempotencyStore) Set

func (s *PostgresIdempotencyStore) Set(key string, statusCode int, headers http.Header, body []byte) error

Set stores an idempotency key and its response. Fail-closed: returns error if persistence fails. Callers must handle this for protected actions.

type ProblemDetail

type ProblemDetail struct {
	// Type is a URI reference that identifies the problem type.
	Type string `json:"type"`
	// Title is a short, human-readable summary of the problem type.
	Title string `json:"title"`
	// Status is the HTTP status code.
	Status int `json:"status"`
	// Detail is a human-readable explanation specific to this occurrence.
	Detail string `json:"detail,omitempty"`
	// Instance is a URI reference identifying the specific occurrence.
	Instance string `json:"instance,omitempty"`
	// TraceID links to the distributed trace for this request.
	TraceID string `json:"trace_id,omitempty"`
}

ProblemDetail implements RFC 7807 (Problem Details for HTTP APIs). All API error responses must use this format.

func (*ProblemDetail) Error

func (p *ProblemDetail) Error() string

Error implements the error interface.

type Receipt

type Receipt struct {
	ReceiptID    string         `json:"receipt_id"`
	DecisionID   string         `json:"decision_id"`
	EffectID     string         `json:"effect_id"`
	Status       string         `json:"status"`
	Timestamp    string         `json:"timestamp"`
	ExecutorID   string         `json:"executor_id,omitempty"`
	Signature    string         `json:"signature"`
	PrevHash     string         `json:"prev_hash"`
	LamportClock uint64         `json:"lamport_clock"`
	DecisionHash string         `json:"decision_hash"`
	ArgsHash     string         `json:"args_hash,omitempty"`
	Metadata     map[string]any `json:"metadata,omitempty"`
}

Receipt stored in-memory.

type RevokeKeyRequest

type RevokeKeyRequest struct {
	TenantID string `json:"tenant_id"`
	KeyID    string `json:"key_id"`
}

RevokeKeyRequest is the wire format for revoking a trusted key.

type SearchRequest

type SearchRequest struct {
	Query      string `json:"query"`
	TenantID   string `json:"tenant_id"`
	MaxResults int    `json:"max_results"`
}

SearchRequest represents a memory search.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the HELM Governance REST API server.

func NewServer

func NewServer(cfg ServerConfig) *Server

NewServer creates a new HELM API server.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(addr string) error

ListenAndServe starts the API server with production-grade timeouts.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

type ServerConfig

type ServerConfig struct {
	PDP            pdp.PolicyDecisionPoint
	Addr           string   // e.g., ":8443"
	AllowedOrigins []string // CORS allowed origins (nil = no CORS headers emitted)
}

ServerConfig configures the API server.

type TrustKeyHandler

type TrustKeyHandler struct {
	Registry *registry.TrustRegistry
}

TrustKeyHandler provides HTTP handlers for trust key management.

func (*TrustKeyHandler) HandleAddKey

func (h *TrustKeyHandler) HandleAddKey(w http.ResponseWriter, r *http.Request)

HandleAddKey handles POST /api/v1/trust/keys/add.

func (*TrustKeyHandler) HandleRevokeKey

func (h *TrustKeyHandler) HandleRevokeKey(w http.ResponseWriter, r *http.Request)

HandleRevokeKey handles POST /api/v1/trust/keys/revoke.

Directories

Path Synopsis
Package trust provides HTTP API handlers for the Trust Registry.
Package trust provides HTTP API handlers for the Trust Registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL