db

package
v0.1.0-rc.2 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: MIT Imports: 9 Imported by: 0

README

internal/db

internal/db is Cypra's tenant-isolation boundary. Application code that reads or writes tenant-owned rows must use TenantScopedDB, not raw *gorm.DB.

Contract

  • Every public TenantScopedDB method requires an explicit non-zero uuid.UUID tenant id or a typed context value from ContextWithTenant.
  • Missing tenant context returns ErrTenantContextMissing.
  • Each operation runs inside a transaction, sets cypra.tenant_id with SET LOCAL, executes the statement, then resets the GUC with SELECT set_config('cypra.tenant_id', '', false) before the connection returns to the pool.
  • Raw SQL is allowed only through Raw / RawScan, and still requires a tenant id.

Postgres RLS is the second line of defense. It should make a tenant-missing or tenant-mismatched query return zero rows even if a caller accidentally bypasses the higher-level API.

Documentation

Overview

Package db contains Cypra's tenant-scoped database boundary.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInstanceAdminContextRequired = errors.New("instance admin context required")
	ErrInstanceAdminReasonRequired  = errors.New("instance admin reason required")
	ErrInstanceAdminActionDenied    = errors.New("instance admin action denied")
)
View Source
var ErrTenantContextMissing = errors.New("tenant context missing")

ErrTenantContextMissing is returned when a tenant-owned operation lacks a non-zero tenant id.

Functions

func ContextAsInstanceAdmin

func ContextAsInstanceAdmin(ctx context.Context) context.Context

func ContextWithTenant

func ContextWithTenant(ctx context.Context, tenantID uuid.UUID) context.Context

ContextWithTenant returns a child context carrying the tenant identifier used by TenantFromContext-aware database calls.

func IsInstanceAdminContext

func IsInstanceAdminContext(ctx context.Context) bool

func TenantFromContext

func TenantFromContext(ctx context.Context) (uuid.UUID, bool)

TenantFromContext extracts the typed tenant identifier from ctx.

Types

type InstanceAdminDB

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

func (*InstanceAdminDB) Exec

func (adb *InstanceAdminDB) Exec(ctx context.Context, action string, stmt string, args ...any) error

func (*InstanceAdminDB) RawScan

func (adb *InstanceAdminDB) RawScan(ctx context.Context, action string, stmt string, dest any, args ...any) error

type TenantPlugin

type TenantPlugin struct{}

TenantPlugin wires GORM callbacks so direct GORM use can still honor a typed tenant context. TenantScopedDB remains the required application boundary.

func (TenantPlugin) Initialize

func (TenantPlugin) Initialize(db *gorm.DB) error

func (TenantPlugin) Name

func (TenantPlugin) Name() string

type TenantScopedDB

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

TenantScopedDB is the only application-facing DB boundary for tenant-owned data. Every operation runs in a transaction with cypra.tenant_id set before the statement and reset before the connection returns to the pool.

func NewTenantScopedDB

func NewTenantScopedDB(db *gorm.DB) *TenantScopedDB

func (*TenantScopedDB) AsInstanceAdmin

func (tdb *TenantScopedDB) AsInstanceAdmin(ctx context.Context, reason string) (*InstanceAdminDB, error)

func (*TenantScopedDB) Create

func (tdb *TenantScopedDB) Create(ctx context.Context, tenantID uuid.UUID, value any) error

func (*TenantScopedDB) Delete

func (tdb *TenantScopedDB) Delete(ctx context.Context, tenantID uuid.UUID, value any, conds ...any) error

func (*TenantScopedDB) Find

func (tdb *TenantScopedDB) Find(ctx context.Context, tenantID uuid.UUID, dest any, conds ...any) error

func (*TenantScopedDB) FindWithContext

func (tdb *TenantScopedDB) FindWithContext(ctx context.Context, dest any, conds ...any) error

func (*TenantScopedDB) Raw

func (tdb *TenantScopedDB) Raw(ctx context.Context, stmt string, tenantID uuid.UUID, args ...any) *gorm.DB

func (*TenantScopedDB) RawScan

func (tdb *TenantScopedDB) RawScan(ctx context.Context, stmt string, tenantID uuid.UUID, dest any, args ...any) error

func (*TenantScopedDB) Transaction

func (tdb *TenantScopedDB) Transaction(ctx context.Context, tenantID uuid.UUID, fn func(tx *gorm.DB) error) error

func (*TenantScopedDB) Update

func (tdb *TenantScopedDB) Update(ctx context.Context, tenantID uuid.UUID, model any, updates any) error

Directories

Path Synopsis
Package fuzz contains the reusable tenant-isolation fuzzer harness that later phases use to enroll HTTP handlers.
Package fuzz contains the reusable tenant-isolation fuzzer harness that later phases use to enroll HTTP handlers.

Jump to

Keyboard shortcuts

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