Help us shape the future of Go! Take the 2026 Go Developer Survey

accesslog

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package accesslog provides local, bounded access history. Its writer accepts typed metadata only; it has no field for request headers, bodies or URLs.

Index

Constants

View Source
const SchemaVersion = 1

Variables

This section is empty.

Functions

func CoarseRemote

func CoarseRemote(remote string) string

CoarseRemote retains a /24 IPv4 or /48 IPv6 prefix, never a port.

func PathForMode

func PathForMode(p, mode string) string

func SafePath

func SafePath(p string) string

SafePath is the full-mode sanitizer. Decode before splitting so escaped separators have the same conservative meaning as literal separators. Nested escaping is bounded; malformed or deeply escaped input is redacted entirely.

func ValidatePathMode

func ValidatePathMode(mode string) error

Types

type AppTraffic added in v0.3.0

type AppTraffic struct {
	App string `json:"app"`
	HTTPTraffic
}

type AuditResult

type AuditResult struct {
	Status string `json:"status"` // ok, denied, error
	Code   string `json:"code"`   // stable code, never a raw error message
}

type Count

type Count struct {
	Key      string     `json:"key"`
	Count    int        `json:"count"`
	Allowed  int        `json:"allowed"`
	Denied   int        `json:"denied"`
	LastSeen *time.Time `json:"last_seen"`
}

type Event

type Event struct {
	Via           string            `json:"via,omitempty"`
	Surface       string            `json:"surface,omitempty"`
	Changes       []mcpaudit.Change `json:"changes,omitempty"`
	SchemaVersion int               `json:"schema_version"`
	Time          time.Time         `json:"time"`
	Kind          string            `json:"kind"` // http, tcp_open, tcp_close, mcp, guest
	App           string            `json:"app"`
	Identity      Identity          `json:"identity"`
	Method        string            `json:"method,omitempty"`
	Path          string            `json:"path,omitempty"`
	Status        int               `json:"status"`
	BytesIn       int64             `json:"bytes_in"`
	BytesOut      int64             `json:"bytes_out"`
	DurationMS    float64           `json:"duration_ms"`
	Decision      string            `json:"decision"`
	Reason        string            `json:"reason,omitempty"`
	ErrorClass    string            `json:"error_class,omitempty"` // backend failure class; never a URL or address
	Grant         *Grant            `json:"grant,omitempty"`
	Connection    string            `json:"connection,omitempty"`
	MCP           *MCPAudit         `json:"mcp,omitempty"`
	Guest         *GuestDecision    `json:"guest,omitempty"`
	PathMode      string            `json:"-"` // selected per-service policy; not HTTP metadata
}

type Filter

type Filter struct {
	// AllowedApps is an authority filter applied before counts and truncation.
	// nil is unrestricted; an empty non-nil list authorizes no records.
	AllowedApps []string   `json:"-"`
	App         string     `json:"app,omitempty"`
	Who         string     `json:"who,omitempty"`
	Since       *time.Time `json:"since,omitempty"`
	Until       *time.Time `json:"until,omitempty"`
	Decision    string     `json:"decision,omitempty"`
	Limit       int        `json:"limit,omitempty"`
}

func (Filter) Validate

func (f Filter) Validate() error

type Grant

type Grant struct {
	Kind  string `json:"kind"` // person or legacy_allow
	Entry string `json:"entry"`
}

type GuestDecision

type GuestDecision struct {
	LinkID   string `json:"link_id"`
	App      string `json:"app"`
	Decision string `json:"decision"`
	Reason   string `json:"reason"`
}

GuestDecision contains the non-secret ledger ID, never the bearer token. Reason must be a stable code rather than request data or a raw error.

type HTTPTraffic added in v0.3.0

type HTTPTraffic struct {
	Requests      int        `json:"requests"`
	Allowed       int        `json:"allowed"`
	Denied        int        `json:"denied"`
	BytesIn       int64      `json:"bytes_in"`
	BytesOut      int64      `json:"bytes_out"`
	LastRequestAt *time.Time `json:"last_request_at"`
	LastAllowedAt *time.Time `json:"last_allowed_at"`
}

type Health

type Health struct {
	Current        bool            `json:"current"`
	MissingHistory []HistoryWindow `json:"missing_history,omitempty"`
	Enabled        bool            `json:"enabled"`
	LastWrite      *time.Time      `json:"last_write"`
	Drops          uint64          `json:"drops"`
	Size           int64           `json:"size_bytes"`
	Error          string          `json:"error,omitempty"`
	UpdatedAt      time.Time       `json:"updated_at"`
}

func ReadHealth

func ReadHealth(configDir string) Health

ReadHealth is strictly read-only. Missing state is reported explicitly; no directory, lock or permission change is made by CLI/MCP queries.

type HistoryWindow

type HistoryWindow struct {
	Start  time.Time  `json:"start"`
	End    *time.Time `json:"end,omitempty"` // absent while history is unavailable
	Reason string     `json:"reason"`
}

type Identity

type Identity struct {
	Login  string   `json:"login"`
	Node   string   `json:"node"`
	Tags   []string `json:"tags"`
	Remote string   `json:"remote,omitempty"`
}

type Lifecycle

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

Lifecycle is the daemon-owned writer handle retained by existing listeners. Initialization and retry I/O run outside its recording lock. Failed starts count drops and retain the exact missing-history window in runtime state, even when the access-log directory cannot be written.

func NewLifecycle

func NewLifecycle(dir string, opts Options, now func() time.Time) *Lifecycle

func (*Lifecycle) Close

func (l *Lifecycle) Close()

func (*Lifecycle) Done

func (l *Lifecycle) Done() <-chan struct{}

func (*Lifecycle) Health

func (l *Lifecycle) Health() Health

func (*Lifecycle) Record

func (l *Lifecycle) Record(e Event) bool

func (*Lifecycle) RecordResolved

func (l *Lifecycle) RecordResolved(e Event, resolve func() Identity) bool

func (*Lifecycle) Retry

func (l *Lifecycle) Retry(at time.Time)

Retry is called on the daemon lifecycle tick, never on a request goroutine.

type MCPAudit

type MCPAudit struct {
	Identity       *MCPIdentity    `json:"identity,omitempty"`
	Role           string          `json:"role,omitempty"`
	ID             string          `json:"id"`
	Principal      string          `json:"principal"` // F6 Principal (legacy Who): login, tag or local OS user
	Scope          string          `json:"scope,omitempty"`
	Capabilities   MCPCapabilities `json:"capabilities"`
	ScopeExpiresAt *time.Time      `json:"scope_expires_at,omitempty"`
	Tool           string          `json:"tool"`
	Apps           []string        `json:"apps"`
	Result         AuditResult     `json:"result"`
	Phase          string          `json:"phase,omitempty"` // intent/completion; started supports the older F6 journal
}

type MCPCapabilities

type MCPCapabilities struct {
	Role        string   `json:"role"`
	Apps        []string `json:"apps,omitempty"`
	Inventory   bool     `json:"inventory,omitempty"`
	MaxDuration string   `json:"max_duration,omitempty"`
}

MCPCapabilities mirrors F6's mcpscope.Scope without importing its authority.

type MCPIdentity

type MCPIdentity struct {
	Login string `json:"login"`
	Node  string `json:"node"`
}

type Options

type Options struct {
	Enabled       *bool  `json:"enabled,omitempty"`
	RecordPath    *bool  `json:"record_path,omitempty"`
	PathMode      string `json:"path_mode,omitempty"`
	RetentionDays int    `json:"retention_days,omitempty"`
	MaxBytes      int64  `json:"max_bytes,omitempty"`
	QueueSize     int    `json:"queue_size,omitempty"`
}

func (Options) Defaults

func (o Options) Defaults() Options

func (Options) IsEnabled

func (o Options) IsEnabled() bool

func (Options) ModeFor

func (o Options) ModeFor(mode string, legacy *bool) string

Legacy true inherits the safe default; false remains a hard opt-out. A service may opt into full unless global recording is explicitly off.

func (Options) PathsEnabled

func (o Options) PathsEnabled(service *bool) bool

func (Options) Validate

func (o Options) Validate() error

type Result

type Result struct {
	Events    []Event `json:"events"`
	Summary   Summary `json:"summary"`
	Truncated bool    `json:"truncated"`
}

func Query

func Query(configDir string, f Filter) (Result, error)

Query opens files read-only and takes a length snapshot per segment. An in-progress final append is ignored, and a complete malformed line is an explicit error, never a silently empty answer. Summaries cover all matching events, independently of the returned-event limit.

type Store

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

func New

func New(configDir string, opts Options, now func() time.Time) (*Store, error)

func (*Store) Close

func (s *Store) Close()

Close begins a drain without waiting for disk. Wait is available to a bounded shutdown caller; the serving path never joins the writer.

func (*Store) Done

func (s *Store) Done() <-chan struct{}

func (*Store) Health

func (s *Store) Health() Health

func (*Store) Record

func (s *Store) Record(e Event) bool

func (*Store) RecordResolved

func (s *Store) RecordResolved(e Event, resolve func() Identity) bool

RecordResolved defers optional WhoIs enrichment to the bounded worker. The callback must be bounded and may capture only address/identity metadata.

type SubjectAppTraffic added in v0.3.0

type SubjectAppTraffic struct {
	SubjectKind string `json:"subject_kind"` // human, tagged, public, unknown
	Login       string `json:"login,omitempty"`
	Subject     string `json:"subject,omitempty"` // non-human bucket, never an inferred login
	App         string `json:"app"`
	HTTPTraffic
}

type Summary

type Summary struct {
	Traffic TrafficSummary `json:"traffic"`
	Reasons []Count        `json:"reasons,omitempty"`
	Count   int            `json:"count"`
	Allowed int            `json:"allowed"`
	Denied  int            `json:"denied"`
	People  []Count        `json:"people"`
	Apps    []Count        `json:"apps"`
}

type TCPTraffic added in v0.3.0

type TCPTraffic struct {
	Connections int   `json:"connections"` // opens, excluding gateway gate drops
	Allowed     int   `json:"allowed"`
	Denied      int   `json:"denied"`
	Closed      int   `json:"closed"`
	BytesIn     int64 `json:"bytes_in"` // close events only
	BytesOut    int64 `json:"bytes_out"`
	GateDrops   int   `json:"gate_drops"` // recorded, rate-limited diagnostics
}

type TrafficSummary added in v0.3.0

type TrafficSummary struct {
	HTTP       HTTPTraffic         `json:"http"`
	PeopleApps []SubjectAppTraffic `json:"people_apps"`
	Apps       []AppTraffic        `json:"apps"`
	TCP        TCPTraffic          `json:"tcp"`
}

TrafficSummary counts retained, matching traffic independently of audit receipts and the returned-event limit. It does not consult current routes.

type Writer

type Writer interface{ Record(Event) bool }

Writer is the shared seam for HTTP/TCP, MCP audit and guest decisions. Record must return immediately; false means the event was dropped.

Jump to

Keyboard shortcuts

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