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

store

package
v0.1.0-alpha.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, AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package store is Headmesh's Postgres access layer: tenant-scoped transactions, migrations, the tamper-evident audit log and the loader that turns database state into a policy.Snapshot.

Index

Constants

This section is empty.

Variables

View Source
var ErrChainBroken = errors.New("audit chain broken")

ErrChainBroken reports an audit chain whose stored hashes do not match the recomputed ones.

View Source
var ErrNoScope = errors.New("store: transaction needs a tenant scope or the system scope")

ErrNoScope is returned when a transaction is started without a tenant scope.

Functions

func AppendAudit

func AppendAudit(ctx context.Context, q *dbq.Queries, ev AuditEvent) (int64, error)

AppendAudit adds ev to its org's chain inside the caller's transaction. The chain head row is locked for the rest of the transaction, so concurrent appends to the same org serialise and the chain never forks.

func LoadSnapshot

func LoadSnapshot(ctx context.Context, q *dbq.Queries, cell dbq.Cell, now time.Time, horizon time.Duration) (policy.Snapshot, error)

LoadSnapshot reads one cell's tenancy state as policy input. It must run in a System-scoped transaction. Grants are limited to those active at now or starting before now+horizon, which is everything a policy timeline over that horizon can need.

func Migrate

func Migrate(ctx context.Context, pool *pgxpool.Pool) error

Migrate applies all pending migrations. It must run as the schema owner, not as the application role.

func UUID

func UUID(s string) (pgtype.UUID, error)

UUID parses a canonical UUID string into the pgx type.

func VerifyAuditChain

func VerifyAuditChain(ctx context.Context, q *dbq.Queries, org pgtype.UUID) (int, error)

VerifyAuditChain recomputes org's chain from genesis and checks it ends at the stored head. It returns the number of events checked, or ErrChainBroken naming the first event that does not verify.

Types

type AuditEvent

type AuditEvent struct {
	OrgID      pgtype.UUID // zero (invalid) for events that belong to no tenant
	OccurredAt time.Time
	ActorType  string // user | api_key | system | cell | platform
	ActorID    string
	Action     string // dotted, e.g. "grant.revoked"
	TargetType string
	TargetID   string
	RequestID  string
	IP         *netip.Addr
	UserAgent  string
	Data       map[string]any
}

AuditEvent is one entry in the tamper-evident audit log.

type CellStore

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

CellStore implements cellserver.Store on Postgres. Every call runs in the system scope: the hub works on whole cells, never on behalf of a tenant.

func NewCellStore

func NewCellStore(s *Store) *CellStore

NewCellStore returns a CellStore.

func (*CellStore) NextRevision

func (c *CellStore) NextRevision(ctx context.Context, name string) (uint64, error)

NextRevision implements cellserver.Store.

func (*CellStore) RecordApplied

func (c *CellStore) RecordApplied(ctx context.Context, name string, a *cellv1.PolicyApplied) error

RecordApplied implements cellserver.Store. A guardrail refusal is also written to the audit log, because it means the control server asked a cell for something the cell considered unsafe.

func (*CellStore) RecordHello

func (c *CellStore) RecordHello(ctx context.Context, name string, hello *cellv1.Hello) error

RecordHello implements cellserver.Store.

func (*CellStore) RecordObserved

func (c *CellStore) RecordObserved(ctx context.Context, name string, obs *cellv1.Observed) error

RecordObserved implements cellserver.Store: it syncs addresses and liveness onto known devices.

func (*CellStore) RecordTimeline

func (c *CellStore) RecordTimeline(ctx context.Context, name string, tl []*cellv1.PolicyRevision) error

RecordTimeline implements cellserver.Store.

func (*CellStore) Snapshot

func (c *CellStore) Snapshot(ctx context.Context, name string, now time.Time, horizon time.Duration) (policy.Snapshot, error)

Snapshot implements cellserver.Store.

type OrgSettings

type OrgSettings struct {
	SSHEnabled        bool `json:"ssh_enabled,omitempty"`
	AllowSubnetRoutes bool `json:"allow_subnet_routes,omitempty"`
	AllowExitNodes    bool `json:"allow_exit_nodes,omitempty"`
	MaxGrantTTLHours  int  `json:"max_grant_ttl_hours,omitempty"`
}

OrgSettings is the typed view of orgs.settings.

type PlatformSelectorJSON

type PlatformSelectorJSON struct {
	Scope string `json:"scope"` // platform | children
	Role  string `json:"role,omitempty"`
}

PlatformSelectorJSON is the stored form of a platform rule side.

type Scope

type Scope struct {
	OrgIDs []pgtype.UUID
	// System grants a whole-cell view. Only background workers (policy compiler, reconciler, recovery sweep)
	// use it; request handlers never do.
	System bool
}

Scope says which tenants a transaction may see. Exactly one of OrgIDs or System must be set.

type SelectorJSON

type SelectorJSON struct {
	Kind   string `json:"kind"` // all | users | role | device
	Role   string `json:"role,omitempty"`
	Device string `json:"device,omitempty"`
}

SelectorJSON is how rule and grant selectors are stored in jsonb columns. Device selectors reference the device by UUID so renames and re-enrolments never break them.

type Store

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

Store wraps a connection pool. The pool's role must not be a superuser and must not have BYPASSRLS, otherwise row-level security (the database half of tenant isolation) silently stops applying.

func New

func New(pool *pgxpool.Pool) *Store

New returns a Store over pool.

func (*Store) Pool

func (s *Store) Pool() *pgxpool.Pool

Pool exposes the underlying pool (for River and health checks).

func (*Store) Tx

func (s *Store) Tx(ctx context.Context, scope Scope, fn func(q *dbq.Queries, tx pgx.Tx) error) error

Tx runs fn in a transaction whose row-level-security context is set to scope. The context is transaction-local (SET LOCAL semantics), so it can never leak to another request through the pool.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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