Documentation
¶
Overview ¶
Package handler provides the Forge-style HTTP admin API for the Chronicle audit trail library. It uses forge.Router with OpenAPI metadata decorators and typed request DTOs.
Index ¶
- type API
- type DeletePolicyRequest
- type Dependencies
- type EventsByUserRequest
- type ExportReportRequest
- type ForceCheckpointRequest
- type GetCheckpointRequest
- type GetErasureRequest
- type GetEventRequest
- type GetReportRequest
- type Guard
- type Guards
- type ListArchivesRequest
- type ListErasuresRequest
- type ListEventsRequest
- type ListReportsRequest
- type RequestErasureRequest
- type SavePolicyRequest
- type StatsResponse
- type VerifyChainRequest
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API wires all Forge-style HTTP handlers together for the Chronicle system.
It starts no spans of its own. Forge already traces every route, and the work a route hands off (verifying a chain, taking a checkpoint, erasing a subject, enforcing retention, building a report) is traced where it runs, so the same spans appear whether the API, the dashboard or your own code called it.
func New ¶
func New(deps Dependencies, router forge.Router) *API
New creates an API from handler dependencies and a Forge router.
func (*API) Handler ¶
Handler returns the fully assembled http.Handler with all routes. Use this for standalone mode outside Forge.
func (*API) RegisterRoutes ¶
RegisterRoutes registers all Chronicle API routes into the given Forge router with full OpenAPI metadata.
type DeletePolicyRequest ¶
type DeletePolicyRequest struct {
PolicyID string `path:"id" description:"Policy ID"`
}
DeletePolicyRequest is the request for deleting a retention policy.
type Dependencies ¶
type Dependencies struct {
AuditStore audit.Store
VerifyStore verify.Store
// StreamStore resolves a stream's owning app and tenant so chain
// verification can confirm the caller owns the stream it names.
StreamStore stream.Store
ErasureStore erasure.Store
// Erasure performs crypto-erasure: destroying the subject's key as well as
// recording the request and flagging their events. Without it an erasure only
// flags events, which is all that is possible when nothing encrypted them.
Erasure *erasure.Service
RetentionStore retention.Store
ReportStore compliance.ReportStore
Compliance *compliance.Engine
Retention *retention.Enforcer
Logger log.Logger
// CheckpointStore persists signed checkpoints. Optional: when nil, the
// checkpoint routes report 503 rather than panicking or 500ing, the same
// way a nil Compliance engine does for the report routes.
CheckpointStore checkpoint.Store
// Checkpointer takes a signed checkpoint on demand for POST
// /v1/checkpoints. Optional for the same reason as CheckpointStore: a
// deployment that has not configured checkpointing still gets a working
// API, just not that one write route.
Checkpointer *checkpoint.Checkpointer
// CheckpointSigner is what POST /v1/verify checks a covering
// checkpoint's signature under. It has to be supplied alongside
// CheckpointStore for the verify route to report checkpoints at all: a
// store without a signer proves nothing, since anyone who can write the
// checkpoint row could write a fabricated one.
//
// Optional, like the two above. Leave it nil and verification behaves
// exactly as it did before checkpoints existed, with coverage topping
// out at keyed.
CheckpointSigner checkpoint.Signer
// HashChain is the chain verification recomputes digests under. A
// nil value here defaults to a zero-value, unkeyed chain, which is what
// every deployment gets unless tamper_evidence.digest is "hmac". An HMAC
// deployment that forgets to set this cannot verify anything at all, so
// callers that have a keyed chain in hand should always pass it.
HashChain *hash.Chain
// Guards authenticate and authorise callers per operation class.
//
// A zero value leaves every route open to any caller that carries an app
// scope, which only protects tenants from each other — it does not stop an
// authenticated caller from purging their own app's audit history. The
// extension refuses to mount an unguarded API unless the operator opts in.
Guards Guards
}
Dependencies defines the handler dependencies.
type EventsByUserRequest ¶
type EventsByUserRequest struct {
UserID string `path:"userId" description:"User ID"`
After string `query:"after" optional:"true" description:"Events after this time (RFC3339)"`
Before string `query:"before" optional:"true" description:"Events before this time (RFC3339)"`
Limit int `query:"limit" optional:"true" description:"Maximum events to return"`
}
EventsByUserRequest is the request for fetching events by user.
type ExportReportRequest ¶
type ExportReportRequest struct {
ReportID string `path:"id" description:"Report ID"`
Format string `path:"format" description:"Export format: json, csv, markdown, html"`
}
ExportReportRequest is the request for exporting a report.
type ForceCheckpointRequest ¶
type ForceCheckpointRequest struct {
StreamID string `json:"stream_id" optional:"true" description:"Stream to checkpoint"`
}
ForceCheckpointRequest is the JSON request body for taking a checkpoint now.
StreamID is marked optional at the binding level, even though the handler requires it, so a request that omits it entirely still reaches the handler rather than failing forge's own required-field check first. That matters when the Checkpointer dependency itself is unset: the 503 for "checkpointing is not configured" needs to win over a 400 for a missing field the caller was never going to be told about anyway.
type GetCheckpointRequest ¶
type GetCheckpointRequest struct {
CheckpointID string `path:"id" description:"Checkpoint ID"`
}
GetCheckpointRequest is the request for fetching a single checkpoint.
type GetErasureRequest ¶
type GetErasureRequest struct {
ErasureID string `path:"id" description:"Erasure record ID"`
}
GetErasureRequest is the request for fetching a single erasure.
type GetEventRequest ¶
type GetEventRequest struct {
EventID string `path:"id" description:"Audit event ID"`
}
GetEventRequest is the request for fetching a single event.
type GetReportRequest ¶
type GetReportRequest struct {
ReportID string `path:"id" description:"Report ID"`
}
GetReportRequest is the request for fetching a single report.
type Guard ¶
type Guard struct {
// Middleware authenticates the caller and rejects insufficient permissions.
// Nil means the route class is unprotected.
Middleware forge.Middleware
// Provider names the OpenAPI security scheme this guard authenticates with.
Provider string
// Scopes are the permissions Middleware enforces, recorded for documentation.
Scopes []string
}
Guard protects one class of routes.
Middleware does the enforcing; Provider and Scopes exist so the generated OpenAPI spec describes the same requirement. A zero Guard leaves its routes unprotected, which is why [Guards.Validate] exists — the extension refuses to mount an unguarded API unless the operator opts in explicitly.
type Guards ¶
Guards holds one guard per operation class, graded by blast radius.
- Read covers everything that only observes: listing and fetching events, stats, reports, policies, archives, and chain verification.
- Write covers creating records that do not destroy anything: saving a retention policy, generating a compliance report.
- Admin covers the irreversible operations: enforcing retention (which purges events), deleting a policy, and requesting an erasure.
func (Guards) Unprotected ¶
Unprotected returns the names of the route classes that enforce nothing. The extension uses this to decide whether it may mount the API.
type ListArchivesRequest ¶
type ListArchivesRequest struct {
Limit int `query:"limit" optional:"true" description:"Maximum results (default: 50)"`
Offset int `query:"offset" optional:"true" description:"Number of results to skip"`
}
ListArchivesRequest is the request for listing archive records.
type ListErasuresRequest ¶
type ListErasuresRequest struct {
Limit int `query:"limit" optional:"true" description:"Maximum results (default: 50)"`
Offset int `query:"offset" optional:"true" description:"Number of results to skip"`
}
ListErasuresRequest is the request for listing erasure records.
type ListEventsRequest ¶
type ListEventsRequest struct {
Category string `query:"category" optional:"true" description:"Filter by category (comma-separated)"`
Action string `query:"action" optional:"true" description:"Filter by action (comma-separated)"`
Severity string `query:"severity" optional:"true" description:"Filter by severity (comma-separated)"`
Outcome string `query:"outcome" optional:"true" description:"Filter by outcome (comma-separated)"`
After string `query:"after" optional:"true" description:"Events after this time (RFC3339)"`
Before string `query:"before" optional:"true" description:"Events before this time (RFC3339)"`
Limit int `query:"limit" optional:"true" description:"Maximum results (default: 50, max: 1000)"`
Offset int `query:"offset" optional:"true" description:"Number of results to skip"`
Order string `query:"order" optional:"true" description:"Sort order: asc or desc (default: desc)"`
}
ListEventsRequest is the request for listing audit events.
type ListReportsRequest ¶
type ListReportsRequest struct {
Limit int `query:"limit" optional:"true" description:"Maximum results (default: 50)"`
Offset int `query:"offset" optional:"true" description:"Number of results to skip"`
}
ListReportsRequest is the request for listing compliance reports.
type RequestErasureRequest ¶
type RequestErasureRequest struct {
SubjectID string `json:"subject_id" description:"Subject ID to erase"`
Reason string `json:"reason" description:"Reason for erasure"`
RequestedBy string `json:"requested_by" description:"Who requested the erasure"`
}
RequestErasureRequest is the JSON request body for creating an erasure.
type SavePolicyRequest ¶
type SavePolicyRequest struct {
Category string `json:"category" description:"Event category to apply retention to"`
Duration string `json:"duration" description:"Retention duration (Go duration string, e.g. 720h)"`
Archive bool `json:"archive" description:"Whether to archive events before purging"`
}
SavePolicyRequest is the JSON request body for saving a retention policy.
type StatsResponse ¶
type StatsResponse struct {
TotalEvents int64 `json:"total_events"`
Categories []audit.AggregateGroup `json:"categories"`
Severities []audit.AggregateGroup `json:"severities"`
Outcomes []audit.AggregateGroup `json:"outcomes"`
RecentEvents []*audit.Event `json:"recent_events"`
}
StatsResponse contains aggregate audit event statistics.
type VerifyChainRequest ¶
type VerifyChainRequest struct {
StreamID string `json:"stream_id" description:"Stream ID to verify"`
FromSeq uint64 `json:"from_seq" description:"Starting sequence number"`
ToSeq uint64 `json:"to_seq" description:"Ending sequence number"`
}
VerifyChainRequest is the JSON request body for chain verification.