Documentation
¶
Index ¶
- Constants
- Variables
- func KeyFingerprint(key []byte) string
- type Event
- type Store
- func (a *Store) Append(scheme, namespace string, event *Event, encKey []byte) error
- func (a *Store) Init() error
- func (a *Store) LastChecksum(scheme, namespace string) string
- func (a *Store) LoadChain(scheme, namespace string, decKey []byte) ([]*Event, error)
- func (a *Store) Prune(scheme, namespace string, olderThan time.Duration, keepLastN int) error
- func (a *Store) SetSigningKey(key []byte)
- func (a *Store) VerifyIntegrity(scheme, namespace string) error
Constants ¶
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 ¶
var ErrChainBroken = errors.New("audit chain integrity check failed")
ErrChainBroken is returned when audit chain integrity verification fails.
Functions ¶
func KeyFingerprint ¶
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 ¶
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 ¶
ComputeHMAC returns HMAC-SHA256 over all event fields using key. Returns "" when key is empty.
func (*Event) VerifyChecksum ¶
VerifyChecksum returns true when e.Checksum matches the computed value.
func (*Event) VerifyHMAC ¶
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 ¶
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 ¶
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) LastChecksum ¶
LastChecksum returns the checksum of the most recently appended event, or "" if no events exist for this scheme/namespace.
func (*Store) LoadChain ¶
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 ¶
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
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 ¶
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.