audit

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const EventTypeKeyRotationCheckpoint = "key_rotation_checkpoint"

EventTypeKeyRotationCheckpoint marks a key-rotation boundary in the chain. Events before the checkpoint are verified with the old signing key; events after are verified with the new signing key. History is never rewritten — the checkpoint is the trust bridge.

Variables

View Source
var ErrChainBroken = errors.New("audit chain integrity check failed")

ErrChainBroken is returned when audit chain integrity verification fails.

Functions

func KeyFingerprint

func KeyFingerprint(key []byte) string

KeyFingerprint returns a short proof-of-possession token for key. Used in checkpoint events to prove the old and new keys without revealing them.

Types

type Event

type Event struct {
	ID           string    `json:"id"`
	BucketID     string    `json:"bucket_id"`
	Scheme       string    `json:"scheme"`    // always plaintext
	Namespace    string    `json:"namespace"` // always plaintext
	Seq          int64     `json:"seq"`
	EventType    string    `json:"event_type"`
	Details      []byte    `json:"details,omitempty"` // plaintext JSON; nil when Encrypted=true
	Timestamp    time.Time `json:"timestamp"`
	PrevChecksum string    `json:"prev_checksum"`
	Checksum     string    `json:"checksum"`
	HMAC         string    `json:"hmac,omitempty"`
	Encrypted    bool      `json:"encrypted"`               // true = Enc* fields are populated
	EncScheme    []byte    `json:"enc_scheme,omitempty"`    // ciphertext of Scheme
	EncNamespace []byte    `json:"enc_namespace,omitempty"` // ciphertext of Namespace
	EncDetails   []byte    `json:"enc_details,omitempty"`   // ciphertext of Details
}

Event is an append-only audit record with chain integrity.

Scheme and Namespace are always plaintext strings — they identify the bucket and are used for routing, display, and chain verification without a key.

When Encrypted is true, EncScheme, EncNamespace, and EncDetails hold the ciphertext of those fields; Details is cleared. When Encrypted is false all three Enc* fields are nil and Details holds plaintext JSON.

The chain is secured at two levels:

Checksum — SHA256 over prevChecksum, ID, BucketID, the stored form of Scheme/Namespace/Details (ciphertext when Encrypted=true), EventType, and Timestamp. Detects content modification and cross-bucket transplantation. Seq is excluded — it is assigned inside the write transaction.

HMAC — HMAC-SHA256 over all fields including Seq. Only a holder of the signing key can produce a valid HMAC.

func (*Event) ComputeChecksum

func (e *Event) ComputeChecksum(prevChecksum string) string

ComputeChecksum returns SHA256 over the stored bytes of each field. When Encrypted=true the Enc* fields are hashed, so verification works for public-tier auditors who hold no decryption key.

func (*Event) ComputeHMAC

func (e *Event) ComputeHMAC(key []byte) string

ComputeHMAC returns HMAC-SHA256 over all event fields using key. Returns "" when key is empty.

func (*Event) VerifyChecksum

func (e *Event) VerifyChecksum() bool

VerifyChecksum returns true when e.Checksum matches the computed value.

func (*Event) VerifyHMAC

func (e *Event) VerifyHMAC(key []byte) bool

VerifyHMAC returns true when the event's HMAC is valid for key. Returns true unconditionally when key or e.HMAC is empty.

type Store

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

Store handles audit event persistence.

func New

func New(db store.Store, signingKey []byte) *Store

New creates an audit Store. Pass a non-nil signingKey to enable HMAC signing of every appended event and HMAC verification in VerifyIntegrity. Pass nil to disable signing.

func (*Store) Append

func (a *Store) Append(scheme, namespace string, event *Event, encKey []byte) error

Append writes event to the chain for scheme/namespace. When encKey is non-nil, Scheme, Namespace, and Details are encrypted into the Enc* fields; the plaintext string fields are preserved for routing and the Details field is cleared. Encrypted is set to true. Checksum and HMAC are computed over the stored (Enc*) bytes so VerifyIntegrity never needs to decrypt. Seq is assigned atomically inside the write transaction.

func (*Store) Init

func (a *Store) Init() error

Init creates the root audit bucket if it does not exist.

func (*Store) LastChecksum

func (a *Store) LastChecksum(scheme, namespace string) string

LastChecksum returns the checksum of the most recently appended event, or "" if no events exist for this scheme/namespace.

func (*Store) LoadChain

func (a *Store) LoadChain(scheme, namespace string, decKey []byte) ([]*Event, error)

LoadChain returns all events for scheme/namespace ordered by Seq ascending. When decKey is non-nil and event.Encrypted is true, Scheme, Namespace, and Details are decrypted before returning. When decKey is nil, encrypted fields are returned as opaque blobs (public-tier: checksum verification only).

func (*Store) Prune

func (a *Store) Prune(scheme, namespace string, olderThan time.Duration, keepLastN int) error

Prune removes events from the chain, always trimming the oldest end so the surviving events form a contiguous tail. The chain index is rewritten after deletion so LastChecksum remains consistent with stored data.

olderThan: events with Timestamp older than time.Now()-olderThan are candidates for deletion. Pass 0 to make all events candidates. keepLastN: always preserve the most recent keepLastN events by Seq.

func (*Store) SetSigningKey added in v0.0.2

func (a *Store) SetSigningKey(key []byte)

SetSigningKey replaces the active HMAC signing key. Pass nil to disable signing. This is used by the keeper after key rotation to activate the new epoch key without constructing a new Store. Tests use it to drive rotation scenarios without going through the full keeper lifecycle.

func (*Store) VerifyIntegrity

func (a *Store) VerifyIntegrity(scheme, namespace string) error

VerifyIntegrity checks the entire chain for scheme/namespace. Operates over the stored bytes — no decryption needed. Checksums and HMACs are computed over ciphertext blobs when events are encrypted, so verification works for the public tier (no key) as well as authenticated tiers.

Jump to

Keyboard shortcuts

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