postgres

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 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
}

func New

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

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)

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)

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)

func (*Backend) RevokeAll

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

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)

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)

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

func (Config) Validate

func (c Config) Validate() error

Jump to

Keyboard shortcuts

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