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

postgres

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package postgres persists session credentials through Foundry-owned PostgreSQL models and explicit migrations. It borrows an existing pool and never migrates or connects during construction.

Index

Constants

View Source
const (
	MigrationOrigin migrate.Origin  = "foundry.sessions"
	CreateSessions  migrate.ID      = "000001_create_sessions"
	AddSessionState migrate.ID      = "000002_session_device_confirmation"
	AddImpersonator migrate.ID      = "000003_session_impersonation"
	ValidateState   migrate.ID      = "000004_validate_session_state"
	Introduced      migrate.Version = "v0.1.0"
)

Variables

This section is empty.

Functions

func Migrations

func Migrations() []migrate.Definition

Migrations returns owned historical definitions. Run them explicitly in the same schema as Config.Schema using the ordinary migration runner. No existing table/data is dropped or reset, and construction never auto-synchronizes schema.

Types

type Backend

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

Backend persists authoritative sessions in PostgreSQL using a borrowed database pool.

func New

func New(db *database.DB, config Config) (*Backend, error)

New validates configuration and creates an adapter borrowing db.

func (*Backend) Confirm

func (b *Backend) Confirm(ctx context.Context, address session.Address, identity model.Identity, id model.ID[session.Record]) (value.Optional[session.Record], error)

Confirm stamps confirmed_at on one live, fully authenticated session of the subject with a conditional UPDATE, then returns its current record.

func (*Backend) ConfirmedWithin

func (b *Backend) ConfirmedWithin(ctx context.Context, address session.Address, identity model.Identity, id model.ID[session.Record], within time.Duration) (bool, error)

ConfirmedWithin reports whether the live session confirmed its password at or after now-within, using this backend's clock.

func (*Backend) ConsumePendingIn

func (b *Backend) ConsumePendingIn(ctx context.Context, tx *database.Tx, address session.Address, expected session.Record) error

ConsumePendingIn deletes only the exact, still-live pending credential under its subject lock. The caller already holds model/factor locks. Pool ownership and schema restoration follow the shared savepoint boundary. Nothing commits.

func (*Backend) Create

func (b *Backend) Create(ctx context.Context, address session.Address, creation session.Creation) (session.Record, error)

Create atomically creates a session under the subject lock and enforces credential capacity.

func (*Backend) CreateBefore

func (b *Backend) CreateBefore(ctx context.Context, address session.Address, creation session.Creation, deadline temporal.DateTime, check func(context.Context, *database.Tx) error) (session.Record, error)

CreateBefore uses ordinary creation and rechecks the existing credential's deadline after insertion, before the transaction returns to commit. Expiry rolls back the inserted credential and all joined factor/consumption writes.

func (*Backend) CreateChecked

func (b *Backend) CreateChecked(ctx context.Context, address session.Address, creation session.Creation, check func(context.Context, *database.Tx) error) (session.Record, error)

CreateChecked runs check before credential locks and creates the session in the same transaction, without retries.

func (*Backend) List

func (b *Backend) List(ctx context.Context, address session.Address, identity model.Identity, limit int) ([]session.Record, error)

List reads the subject's live sessions in one statement without locking the subject, so listing never blocks issuance or request authentication.

func (*Backend) Lookup

func (b *Backend) Lookup(ctx context.Context, address session.Address, hash session.Digest, touch bool) (value.Optional[session.Record], error)

Lookup is the per-request read path: one schema-qualified statement joins the session and its subject without a transaction or row lock, so parallel requests, listings, pruning and revocation never serialize on the subject. Expiry is checked against the clock sampled after the read. A sliding session records activity only when it is older than TouchInterval, with one conditional UPDATE that cannot revive a removed, rotated or expired row. A revocation committing concurrently with this read applies from the next scope.

func (*Backend) Prune

func (b *Backend) Prune(ctx context.Context, address session.Address, limit int) (uint64, error)

Prune deletes at most limit expired sessions of this address in one set-based, index-backed statement. Rows locked by concurrent work are skipped, and expiry is rechecked on the row actually deleted, so a session touched meanwhile survives. Subject rows remain for serialization.

func (*Backend) ResumeActor

func (b *Backend) ResumeActor(ctx context.Context, address session.Address, expected session.Record, next session.Digest, check func(context.Context, *database.Tx) error) (value.Optional[session.Record], error)

ResumeActor rotates the exact live actor session in place after impersonation. The check runs first in the transaction; the subject and row are then locked in the order shared by every session writer, and the record is revalidated against expected before its secret is replaced.

func (*Backend) Revoke

func (b *Backend) Revoke(ctx context.Context, address session.Address, hash session.Digest) (bool, error)

Revoke atomically deletes the session matching hash and reports whether it existed.

func (*Backend) RevokeAll

func (b *Backend) RevokeAll(ctx context.Context, address session.Address, identity model.Identity) (uint64, error)

RevokeAll atomically removes the subject's sessions and returns the count.

func (*Backend) RevokeAllIn

func (b *Backend) RevokeAllIn(ctx context.Context, tx *database.Tx, address session.Address, identity model.Identity) (uint64, error)

RevokeAllIn returns a provisional count: only the caller's outer transaction can commit. It rejects a transaction from another pool and scopes schema changes inside a savepoint. The original standalone method reuses the same row logic.

func (*Backend) RevokeID

func (b *Backend) RevokeID(ctx context.Context, address session.Address, identity model.Identity, id model.ID[session.Record]) (bool, error)

RevokeID locks the subject and removes the identified session, reporting whether it existed.

func (*Backend) RevokeOthers

func (b *Backend) RevokeOthers(ctx context.Context, address session.Address, identity model.Identity, keep model.ID[session.Record]) (uint64, error)

RevokeOthers removes every session of the subject except keep, under the subject lock. A missing subject has nothing to revoke.

func (*Backend) Rotate

func (b *Backend) Rotate(ctx context.Context, address session.Address, old, next session.Digest) (value.Optional[session.Record], error)

Rotate atomically replaces a live session's digest and records activity, omitting missing or expired sessions.

type Config

type Config struct {
	Schema string
	Clock  clock.Clock
}

Config explicitly selects the schema used by both migrations and runtime. Clock is server-side application time, sampled after taking a subject lock. Instances sharing a store need synchronized clocks. Tests may inject testkit.Clock.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the public schema and system clock.

func (Config) Validate

func (c Config) Validate() error

Validate requires a valid SQL schema and a non-nil clock.

Jump to

Keyboard shortcuts

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