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

database

package
v0.0.0-...-40c6b5d Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 55 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ProbeOutcomeStatusSuccess = "success"
	ProbeOutcomeStatusFailure = "failure"
)

Outcome enum stored in connection_probe_outcomes.outcome.

View Source
const (
	// NotificationKeyAuthRequired is the condition key suffix used when a
	// connection requires the actor to re-authenticate, e.g.
	// "connection:cxn_...:auth_required".
	NotificationKeyAuthRequired = "auth_required"

	// NotificationKeySetupRequired is the condition key suffix used when a
	// connection requires additional setup, e.g.
	// "connection:cxn_...:setup_required".
	NotificationKeySetupRequired = "setup_required"
)
View Source
const (
	NotificationsTable     = "notifications"
	NotificationViewsTable = "notification_views"
)
View Source
const ActorTable = "actors"
View Source
const ConnectionCredentialsTable = "connection_credentials"
View Source
const ConnectionProbeOutcomesTable = "connection_probe_outcomes"
View Source
const ConnectionsTable = "connections"
View Source
const ConnectorGenerationsTable = "connector_generations"
View Source
const ConnectorsTable = "connectors"
View Source
const DataEncryptionKeysTable = "data_encryption_keys"
View Source
const KeysTable = "keys"
View Source
const MaxToolCandidateLimit = 100

MaxToolCandidateLimit bounds one internal scan, independently of a public discovery page. Authorization may discard any or all candidates in a scan.

View Source
const MaxToolListLimit = MaxToolCandidateLimit

MaxToolListLimit bounds one management list page. Management pages read full identity rows, so the cap matches the internal candidate scan.

View Source
const MaxToolSetBindingListLimit = 100

MaxToolSetBindingListLimit bounds one page of a connection's ToolSet bindings.

View Source
const MaxToolSetListLimit = 100

MaxToolSetListLimit bounds one management page of logical ToolSets or of one ToolSet's generations.

View Source
const MigrateMutexKeyName = "db-migrate-lock"

MigrateMutexKeyName is the key that can be used when locking to perform a migration in redis.

View Source
const NamespaceLabelToken = "ns"

NamespaceLabelToken is the <rt> token used in apxy/ keys that reference a namespace. Namespaces are path-keyed (not apid-keyed) so the token is hard-coded rather than derived from an apid prefix.

View Source
const NamespacesTable = "namespaces"
View Source
const OAuth2AccessTokenExpiryBuffer = 30 * time.Second
View Source
const OAuth2TokensTable = "oauth2_tokens"
View Source
const RateLimitsTable = "rate_limits"
View Source
const ToolRevisionsTable = "tool_revisions"

ToolRevisionsTable retains immutable executable definitions for each Tool.

View Source
const ToolSetBindingsTable = "tool_set_bindings"

ToolSetBindingsTable stores the lifetime of a ToolSet-to-connection assignment.

View Source
const ToolSetGenerationsTable = "tool_set_generations"

ToolSetGenerationsTable stores generation-owned definitions and release state.

View Source
const ToolSetsTable = "tool_sets"

ToolSetsTable stores logical ToolSet identity and connection membership policy.

View Source
const ToolsTable = "tools"

ToolsTable holds Tool identities and their current definition pointers.

View Source
const UsedNoncesTable = "used_nonces"

Variables

View Source
var (
	// ErrToolSetBindingEpochConflict means a worker's captured binding is stale.
	ErrToolSetBindingEpochConflict = errors.New("toolset binding epoch changed")

	// ErrToolSetBindingMembershipConflict means current namespace/label matching
	// contradicts the requested creation or removal. Recompute desired membership.
	ErrToolSetBindingMembershipConflict = errors.New("toolset binding membership changed")
)
View Source
var (
	// ErrToolSetBindingInventoryConflict prevents first installation from being
	// used to replace an installed inventory or reuse retained identities, and
	// rejects installed inventory counters that cannot advance.
	ErrToolSetBindingInventoryConflict = errors.New("toolset binding inventory state conflicts")

	// ErrToolSetInventoryGenerationConflict means the target is no longer
	// eligible: first installation requires primary, replacement primary/active.
	ErrToolSetInventoryGenerationConflict = errors.New("toolset inventory generation is no longer eligible")

	// ErrToolSetInventoryConnectionNotReady preserves the prior inventory while
	// the connection is unconfigured or disconnected.
	ErrToolSetInventoryConnectionNotReady = errors.New("toolset inventory connection is not configured")
)
View Source
var ErrDuplicate = errors.New("duplicate record")

ErrDuplicate is returned when a database operation that is expected to be unique fails because a duplicate record already exists.

View Source
var ErrInvalidListQuery = errors.New("invalid list query")

ErrInvalidListQuery is returned when a Tool, ToolSet, or binding listing runs with an invalid filter, so callers can tell bad input from a database failure.

View Source
var ErrInvalidReference = errors.New("invalid object reference")

ErrInvalidReference is returned when an object reference cannot identify a supported resource because its GVK, identity, or generation is invalid.

View Source
var ErrNamespaceDoesNotExist = errors.New("namespace does not exist")

ErrNamespaceDoesNotExist is returned when a namespace does not exist for a resource that is attempting to be created in the specified namespace.

View Source
var ErrNotFound = errors.New("record not found")

ErrNotFound is returned when a database operation that is expected to find a record does not find the record.

View Source
var ErrProtected = errors.New("resource is protected")

ErrProtected is returned when an operation is attempted on a protected resource that cannot be modified in the requested way.

View Source
var ErrToolManaged = errors.New("tool is managed by a toolset")

ErrToolManaged means a standalone write attempted to create, change, or remove controller-owned state. Generated Tools must be changed through their ToolSet.

View Source
var ErrToolRevisionConflict = errors.New("tool revision changed")

ErrToolRevisionConflict means a replacement or deletion used a stale revision. Callers must reload and validate their candidate before retrying.

View Source
var ErrToolSetBindingGenerationConflict = errors.New("toolset binding applied generation changed")

ErrToolSetBindingGenerationConflict means replacement did not observe the installed generation captured during preparation, including a pending binding.

View Source
var ErrToolSetGenerationRevisionConflict = errors.New("toolset generation is no longer the expected draft revision")

ErrToolSetGenerationRevisionConflict means the requested draft was edited or published since it was read. Callers must reload and validate before retrying.

View Source
var ErrToolSetSelectorRevisionConflict = errors.New("toolset selector revision changed")

ErrToolSetSelectorRevisionConflict means a selector replacement lost its compare-and-increment check. The caller must read current state before retrying.

View Source
var ErrViolation = errors.New("database constraint violation")

ErrViolation is returned when a constraint in the database is violated (e.g. multiple rows with the same ID) after an operation that should have been unique.

View Source
var GlobalKeyID = apid.ID("key_global")

GlobalKeyID is the ID of the global key created by migration. It is the root of the key hierarchy and must not be deleted.

Functions

func ApidPrefixToLabelToken

func ApidPrefixToLabelToken(p apid.Prefix) string

ApidPrefixToLabelToken returns the label-key token associated with an apid prefix. It strips the trailing underscore so e.g. "cxr_" becomes "cxr" and "cxn_" becomes "cxn". Used to build apxy/ keys whose <rt> segment matches the resource's id prefix.

func BuildLabelSelectorFromMap

func BuildLabelSelectorFromMap(labels map[string]string) string

BuildLabelSelectorFromMap creates a label selector string from key-value pairs. Keys are sorted for deterministic output. Example: {"type": "salesforce", "env": "prod"} -> "env=prod,type=salesforce"

func IsValidActorOrderByField

func IsValidActorOrderByField[T string | ActorOrderByField](field T) bool

IsValidActorOrderByField checks if the given value is a valid ActorOrderByField.

func IsValidConnectionHealthState

func IsValidConnectionHealthState[T string | ConnectionHealthState](state T) bool

func IsValidConnectionOrderByField

func IsValidConnectionOrderByField[T string | ConnectionOrderByField](field T) bool

func IsValidConnectionState

func IsValidConnectionState[T string | ConnectionState](state T) bool

func IsValidConnectorGenerationOrderByField

func IsValidConnectorGenerationOrderByField[T string | ConnectorGenerationOrderByField](field T) bool

func IsValidConnectorGenerationState

func IsValidConnectorGenerationState[T string | ConnectorGenerationState](state T) bool

func IsValidConnectorOrderByField

func IsValidConnectorOrderByField[T string | ConnectorOrderByField](field T) bool

func IsValidKeyMaterialType

func IsValidKeyMaterialType[T string | KeyMaterialType](materialType T) bool

func IsValidKeyOrderByField

func IsValidKeyOrderByField[T string | KeyOrderByField](field T) bool

func IsValidKeyState

func IsValidKeyState[T string | KeyState](state T) bool

func IsValidKeyUsage

func IsValidKeyUsage[T string | KeyUsage](usage T) bool

func IsValidNamespaceOrderByField

func IsValidNamespaceOrderByField[T string | NamespaceOrderByField](field T) bool

func IsValidNamespaceState

func IsValidNamespaceState[T string | NamespaceState](state T) bool

func IsValidNotificationLevel

func IsValidNotificationLevel[T string | NotificationLevel](level T) bool

func IsValidNotificationState

func IsValidNotificationState[T string | NotificationState](state T) bool

func IsValidRateLimitOrderByField

func IsValidRateLimitOrderByField[T string | RateLimitOrderByField](field T) bool

func IsValidSearchResourceType

func IsValidSearchResourceType(t SearchResourceType) bool

func IsValidToolOrderByField

func IsValidToolOrderByField[T string | ToolOrderByField](field T) bool

IsValidToolOrderByField reports whether field is a supported sort column. Listings interpolate the field into SQL, so only these values may reach it.

func IsValidToolSetGenerationOrderByField

func IsValidToolSetGenerationOrderByField[T string | ToolSetGenerationOrderByField](field T) bool

IsValidToolSetGenerationOrderByField reports whether field is a supported sort column. Listings interpolate the field into SQL, so only these may reach it.

func IsValidToolSetOrderByField

func IsValidToolSetOrderByField[T string | ToolSetOrderByField](field T) bool

IsValidToolSetOrderByField reports whether field is a supported sort column. Listings interpolate the field into SQL, so only these values may reach it.

func MigrationStatus

func MigrationStatus(
	ctx context.Context,
	cfg *config.Database,
) migration.Status

MigrationStatus returns the status of the database migrations for the main application database.

func RegisterEncryptedField

func RegisterEncryptedField(reg EncryptedFieldRegistration)

RegisterEncryptedField adds an encrypted field registration to the global registry. Panics if the registration is invalid. Must be called during init().

func RunMigrations

func RunMigrations(
	ctx context.Context,
	cfg *config.Database,
	logger *slog.Logger,
	direction migration.Direction,
	version *uint,
) (resultErr error)

RunMigrations runs database migrations for the main application database.

Types

type Actor

type Actor struct {
	Id           apid.ID
	Namespace    string
	Name         scommon.ResourceName
	ExternalId   string
	Permissions  Permissions
	Labels       Labels
	Annotations  Annotations
	EncryptedKey *encfield.EncryptedField
	CreatedAt    time.Time
	UpdatedAt    time.Time
	EncryptedAt  *time.Time
	DeletedAt    *time.Time
}

Actor is some entity taking action within the system.

func (*Actor) CanSelfSign

func (a *Actor) CanSelfSign() bool

CanSelfSign returns true if this actor has an encrypted key and can self-sign requests

func (*Actor) GetAnnotations

func (a *Actor) GetAnnotations() map[string]string

func (*Actor) GetEncryptedKey

func (a *Actor) GetEncryptedKey() *encfield.EncryptedField

func (*Actor) GetExternalId

func (a *Actor) GetExternalId() string

func (*Actor) GetId

func (a *Actor) GetId() apid.ID

func (*Actor) GetLabels

func (a *Actor) GetLabels() map[string]string

func (*Actor) GetName

func (a *Actor) GetName() scommon.ResourceName

func (*Actor) GetNamespace

func (a *Actor) GetNamespace() string

func (*Actor) GetPermissions

func (a *Actor) GetPermissions() []aschema.Permission

type ActorOrderByField

type ActorOrderByField string
const (
	ActorOrderByCreatedAt  ActorOrderByField = "created_at"
	ActorOrderByUpdatedAt  ActorOrderByField = "updated_at"
	ActorOrderByNamespace  ActorOrderByField = "namespace"
	ActorOrderByExternalId ActorOrderByField = "external_id"
	ActorOrderByDeletedAt  ActorOrderByField = "deleted_at"
)

type Annotations

type Annotations map[string]string

Annotations is a map of key-value pairs similar to Kubernetes annotations. Keys follow the same format as label keys ([prefix/]name). Values have no format restriction — any string is allowed. Total size of all annotations (keys + values) must not exceed 256KB.

func (Annotations) Copy

func (a Annotations) Copy() Annotations

Copy returns a deep copy of the annotations.

func (Annotations) Get

func (a Annotations) Get(key string) (string, bool)

Get returns the value for an annotation key, and whether the key exists.

func (Annotations) Has

func (a Annotations) Has(key string) bool

Has returns true if the annotation key exists.

func (*Annotations) Scan

func (a *Annotations) Scan(value interface{}) error

Scan implements the sql.Scanner interface for Annotations

func (Annotations) Validate

func (a Annotations) Validate() error

Validate validates all annotations.

func (Annotations) Value

func (a Annotations) Value() (driver.Value, error)

Value implements the driver.Valuer interface for Annotations

type ApiKeyCredential

type ApiKeyCredential struct {
	Id                   apid.ID
	ConnectionId         apid.ID                  // FK to Connection; not enforced by DB
	EncryptedCredentials encfield.EncryptedField  // Opaque encrypted credential blob
	PlacementSnapshot    *cschema.ApiKeyPlacement // API-key placement config at submission time
	CreatedByActorId     *apid.ID                 // Actor who submitted (or rotated to) this credential
	LastValidatedAt      *time.Time               // Most recent successful probe against this credential
	CreatedAt            time.Time
	EncryptedAt          *time.Time
	DeletedAt            *time.Time
}

ApiKeyCredential is one row in the connection_credentials table — an encrypted credential blob submitted by a user for a connection. API-key connections store api key material here; OAuth2 client_credentials connections store client id / secret material here. The encrypted_credentials column stores a single opaque encrypted blob; the substructure inside is decided by the encrypt/decrypt layer that owns the plaintext shape — the database is agnostic to it.

Rotation produces a new row and soft-deletes the prior, so the history of credentials is preserved. At most one row per connection has deleted_at IS NULL at any given moment.

func (*ApiKeyCredential) Validate

func (c *ApiKeyCredential) Validate() error

type ApiKeyCredentialPlaintext

type ApiKeyCredentialPlaintext struct {
	ApiKey   string `json:"apiKey"`
	Username string `json:"username,omitempty"`
}

ApiKeyCredentialPlaintext is the canonical plaintext shape stored, encrypted, inside ApiKeyCredential.EncryptedCredentials. Defined here so callers that encrypt (the connection-initiate submit handler) and callers that decrypt (the api-key proxy) share one contract. The database itself never inspects the plaintext — it only stores the encrypted blob.

type Connection

type Connection struct {
	Id                     apid.ID
	Namespace              string
	Name                   scommon.ResourceName
	State                  ConnectionState
	HealthState            ConnectionHealthState
	ConnectorId            apid.ID
	ConnectorGeneration    uint64
	Labels                 Labels
	Annotations            Annotations
	EncryptedConfiguration *encfield.EncryptedField
	EncryptedAt            *time.Time
	SetupStep              *cschema.SetupStep
	SetupError             *string
	CreatedAt              time.Time
	UpdatedAt              time.Time
	DeletedAt              *time.Time
}

func (*Connection) GetAnnotations

func (c *Connection) GetAnnotations() map[string]string

func (*Connection) GetConnectorGeneration

func (c *Connection) GetConnectorGeneration() uint64

func (*Connection) GetConnectorId

func (c *Connection) GetConnectorId() apid.ID

func (*Connection) GetId

func (c *Connection) GetId() apid.ID

func (*Connection) GetLabels

func (c *Connection) GetLabels() map[string]string

func (*Connection) GetNamespace

func (c *Connection) GetNamespace() string

func (*Connection) Validate

func (c *Connection) Validate() error

type ConnectionGenerationMigrationUpdate

type ConnectionGenerationMigrationUpdate struct {
	Id                     apid.ID
	ConnectorId            apid.ID
	ConnectorGeneration    uint64
	EncryptedConfiguration *encfield.EncryptedField
	UserLabels             map[string]string
	Annotations            map[string]string
	SetupStep              *cschema.SetupStep
	SetupError             *string
	HealthState            *ConnectionHealthState
}

ConnectionGenerationMigrationUpdate is the complete connection row replacement produced by a connector-generation migration. The database layer applies it in a single transaction so the target generation, encrypted configuration, labels, annotations, setup state, and health state cannot be partially persisted.

type ConnectionHealthState

type ConnectionHealthState string

ConnectionHealthState is the operational health signal for a connection, distinct from its lifecycle state. A connection can be Configured and unhealthy simultaneously — for example, an OAuth2 connection whose refresh token has been revoked stays in ConnectionStateConfigured but flips to unhealthy until the user re-authenticates. Probe-driven and refresh-driven signals both write to this field; UI surfaces it to drive the unified reauth action.

const (
	ConnectionHealthStateHealthy   ConnectionHealthState = "healthy"
	ConnectionHealthStateUnhealthy ConnectionHealthState = "unhealthy"
)

type ConnectionOrderByField

type ConnectionOrderByField string
const (
	ConnectionOrderById        ConnectionOrderByField = "id"
	ConnectionOrderByNamespace ConnectionOrderByField = "namespace"
	ConnectionOrderByState     ConnectionOrderByField = "state"
	ConnectionOrderByCreatedAt ConnectionOrderByField = "created_at"
	ConnectionOrderByUpdatedAt ConnectionOrderByField = "updated_at"
)

type ConnectionProbeOutcome

type ConnectionProbeOutcome struct {
	Id           apid.ID
	ConnectionId apid.ID
	ProbeId      string
	Outcome      string
	ErrorMessage *string
	OccurredAt   time.Time
	CreatedAt    time.Time
}

ConnectionProbeOutcome is one append-only event in the probe-outcome log. Each probe invocation produces a row; the runtime walks the most recent rows for a (connection_id, probe_id) pair to compute consecutive-success or -failure counts that drive the connection's health_state transitions.

Storage is event-shaped rather than counter-shaped so that:

  • writes never race on a shared counter row;
  • the log naturally carries probe history for operators (when did the last failure happen? what error did it report?);
  • threshold semantics can change without a schema migration.

A daily cleanup task (DeleteOldProbeOutcomes) caps growth — see internal/core/task_probe_outcome_cleanup.go.

type ConnectionState

type ConnectionState string
const (
	// ConnectionStateSetup is the initial state — a connection in setup
	// has been persisted and has one or more setup steps in progress.
	ConnectionStateSetup ConnectionState = "setup"
	// ConnectionStateConfigured means setup is complete. The connection
	// may or may not be currently usable; whether the credentials still
	// work is the orthogonal ConnectionHealthState axis (e.g. an OAuth2
	// connection with a revoked refresh token stays Configured but flips
	// unhealthy until reauth).
	ConnectionStateConfigured    ConnectionState = "configured"
	ConnectionStateDisabled      ConnectionState = "disabled"
	ConnectionStateDisconnecting ConnectionState = "disconnecting"
	ConnectionStateDisconnected  ConnectionState = "disconnected"
)

type Connector

type Connector struct {
	Id          apid.ID
	Namespace   string
	Name        scommon.ResourceName
	Labels      Labels
	Annotations Annotations
	CreatedAt   time.Time
	UpdatedAt   time.Time
	DeletedAt   *time.Time
}

Connector is the database representation of a logical connector. Definition generations are stored separately in connector_generations.

func (*Connector) Validate

func (c *Connector) Validate() error

type ConnectorGeneration

type ConnectorGeneration struct {
	Id                  apid.ID
	ConnectorId         apid.ID
	Generation          uint64
	State               ConnectorGenerationState
	EncryptedDefinition encfield.EncryptedField
	CreatedAt           time.Time
	UpdatedAt           time.Time
	EncryptedAt         *time.Time
	DeletedAt           *time.Time
}

ConnectorGeneration is the database representation of a single row in connector_generations.

func (*ConnectorGeneration) Validate

func (cv *ConnectorGeneration) Validate() error

type ConnectorGenerationId

type ConnectorGenerationId struct {
	Id         apid.ID
	Generation uint64
}

type ConnectorGenerationOrderByField

type ConnectorGenerationOrderByField string
const (
	ConnectorGenerationOrderById         ConnectorGenerationOrderByField = "id"
	ConnectorGenerationOrderByGeneration ConnectorGenerationOrderByField = "generation"
	ConnectorGenerationOrderByState      ConnectorGenerationOrderByField = "state"
	ConnectorGenerationOrderByCreatedAt  ConnectorGenerationOrderByField = "created_at"
	ConnectorGenerationOrderByUpdatedAt  ConnectorGenerationOrderByField = "updated_at"
)

type ConnectorGenerationState

type ConnectorGenerationState string
const (
	// ConnectorGenerationStateDraft means the connector definition is being worked on and new users should not connect to
	// this generation and existing users should not be upgraded to this generation
	ConnectorGenerationStateDraft ConnectorGenerationState = "draft"

	// ConnectorGenerationStatePrimary means that the generation has been published and this should be the generation used for
	// new connections. Existing connections of this connector will be upgraded to this generation if possible, or
	// transitioned to a state where action is required to complete the upgrade.
	ConnectorGenerationStatePrimary ConnectorGenerationState = "primary"

	// ConnectorGenerationStateActive means that a newer generation of the connector has been published, but connections
	// still exist on this generation that have not been upgraded.
	ConnectorGenerationStateActive ConnectorGenerationState = "active"

	// ConnectorGenerationStateArchived means that this is an old generation of the connect that does not have any active
	// connections running on the generation.
	ConnectorGenerationStateArchived ConnectorGenerationState = "archived"
)

func (*ConnectorGenerationState) Scan

func (s *ConnectorGenerationState) Scan(value interface{}) error

Scan implements the sql.Scanner interface for ConnectorGenerationState

func (ConnectorGenerationState) Value

Value implements the driver.Valuer interface for ConnectorGenerationState

type ConnectorOrderByField

type ConnectorOrderByField string
const (
	ConnectorOrderById         ConnectorOrderByField = "id"
	ConnectorOrderByGeneration ConnectorOrderByField = "generation"
	ConnectorOrderByNamespace  ConnectorOrderByField = "namespace"
	ConnectorOrderByState      ConnectorOrderByField = "state"
	ConnectorOrderByCreatedAt  ConnectorOrderByField = "created_at"
	ConnectorOrderByUpdatedAt  ConnectorOrderByField = "updated_at"
	ConnectorOrderByType       ConnectorOrderByField = "type"
)

type ConnectorWithDefinition

type ConnectorWithDefinition struct {
	Id                     apid.ID
	Namespace              string
	Name                   scommon.ResourceName
	DefinitionGenerationId apid.ID
	Generation             uint64
	State                  ConnectorGenerationState
	EncryptedDefinition    encfield.EncryptedField
	Labels                 Labels
	Annotations            Annotations
	CreatedAt              time.Time
	UpdatedAt              time.Time
	DefinitionCreatedAt    time.Time
	DefinitionUpdatedAt    time.Time
	EncryptedAt            *time.Time
	DeletedAt              *time.Time
}

ConnectorWithDefinition combines fields from connectors and connector_generations.

func (*ConnectorWithDefinition) GetGeneration

func (cv *ConnectorWithDefinition) GetGeneration() uint64

func (*ConnectorWithDefinition) GetId

func (cv *ConnectorWithDefinition) GetId() apid.ID

func (*ConnectorWithDefinition) GetNamespace

func (cv *ConnectorWithDefinition) GetNamespace() string

func (*ConnectorWithDefinition) Validate

func (cv *ConnectorWithDefinition) Validate() error

type DB

type DB interface {
	SetCursorEncryptor(e pagination.CursorEncryptor)
	Ping(ctx context.Context) bool
	SearchResources(ctx context.Context, params SearchResourcesParams) (SearchResourcesResult, error)

	ResolveActorReference(ctx context.Context, reference meta.ObjectReference) (*Actor, error)
	ResolveConnectionReference(ctx context.Context, reference meta.ObjectReference) (*Connection, error)
	ResolveConnectorReference(ctx context.Context, reference meta.ObjectReference) (*Connector, error)
	ResolveKeyReference(ctx context.Context, reference meta.ObjectReference) (*Key, error)
	ResolveNamespaceReference(ctx context.Context, reference meta.ObjectReference) (*Namespace, error)
	ResolveRateLimitReference(ctx context.Context, reference meta.ObjectReference) (*RateLimit, error)

	GetNamespace(ctx context.Context, path string) (*Namespace, error)
	CreateNamespace(ctx context.Context, ns *Namespace) error
	EnsureNamespaceByPath(ctx context.Context, path string) error
	DeleteNamespace(ctx context.Context, path string) error
	SetNamespaceState(ctx context.Context, path string, state NamespaceState) error
	SetNamespaceKeyId(ctx context.Context, path string, ekId *apid.ID) (*Namespace, error)
	UpdateNamespaceLabels(ctx context.Context, path string, labels map[string]string) (*Namespace, error)
	PutNamespaceLabels(ctx context.Context, path string, labels map[string]string) (*Namespace, error)
	DeleteNamespaceLabels(ctx context.Context, path string, keys []string) (*Namespace, error)
	UpdateNamespaceAnnotations(ctx context.Context, path string, annotations map[string]string) (*Namespace, error)
	PutNamespaceAnnotations(ctx context.Context, path string, annotations map[string]string) (*Namespace, error)
	DeleteNamespaceAnnotations(ctx context.Context, path string, keys []string) (*Namespace, error)
	ListNamespacesBuilder() ListNamespacesBuilder
	ListNamespacesFromCursor(ctx context.Context, cursor string) (ListNamespacesExecutor, error)
	EnumerateNamespaceEncryptionTargets(
		ctx context.Context,
		callback func(targets []NamespaceEncryptionTarget, lastPage bool) (updates []NamespaceTargetDataEncryptionKeyUpdate, keepGoing pagination.KeepGoing, err error),
	) error

	GetActor(ctx context.Context, id apid.ID) (*Actor, error)
	GetActorByExternalId(ctx context.Context, namespace, externalId string) (*Actor, error)
	CreateActor(ctx context.Context, actor *Actor) error
	UpsertActor(ctx context.Context, actor IActorData) (*Actor, error)
	UpdateActorName(ctx context.Context, id apid.ID, name scommon.ResourceName) (*Actor, error)
	DeleteActor(ctx context.Context, id apid.ID) error
	PutActorLabels(ctx context.Context, id apid.ID, labels map[string]string) (*Actor, error)
	DeleteActorLabels(ctx context.Context, id apid.ID, keys []string) (*Actor, error)
	UpdateActorAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*Actor, error)
	PutActorAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*Actor, error)
	DeleteActorAnnotations(ctx context.Context, id apid.ID, keys []string) (*Actor, error)
	ListActorsBuilder() ListActorsBuilder
	ListActorsFromCursor(ctx context.Context, cursor string) (ListActorsExecutor, error)

	GetConnectorGeneration(ctx context.Context, id apid.ID, generation uint64) (*ConnectorWithDefinition, error)
	GetConnectorGenerations(ctx context.Context, requested []ConnectorGenerationId) (map[ConnectorGenerationId]*ConnectorWithDefinition, error)
	GetConnectorGenerationForState(ctx context.Context, id apid.ID, state ConnectorGenerationState) (*ConnectorWithDefinition, error)
	NewestConnectorGenerationForId(ctx context.Context, id apid.ID) (*ConnectorWithDefinition, error)
	NewestPublishedConnectorGenerationForId(ctx context.Context, id apid.ID) (*ConnectorWithDefinition, error)
	UpsertConnectorGeneration(ctx context.Context, cv *ConnectorWithDefinition) error
	SetConnectorGenerationState(ctx context.Context, id apid.ID, generation uint64, state ConnectorGenerationState) error
	UpdateConnectorName(ctx context.Context, id apid.ID, name scommon.ResourceName) error
	UpdateConnectorLabels(
		ctx context.Context,
		id apid.ID,
		labels map[string]string,
	) (*Connector, error)
	UpdateConnectorAnnotations(
		ctx context.Context,
		id apid.ID,
		annotations map[string]string,
	) (*Connector, error)
	DeleteConnector(ctx context.Context, id apid.ID) error
	ListConnectorGenerationsBuilder() ListConnectorGenerationsBuilder
	ListConnectorGenerationsFromCursor(ctx context.Context, cursor string) (ListConnectorGenerationsExecutor, error)
	ListConnectorsBuilder() ListConnectorsBuilder
	ListConnectorsFromCursor(ctx context.Context, cursor string) (ListConnectorsExecutor, error)

	CreateToolSet(ctx context.Context, toolSet *ToolSet) error
	GetToolSet(ctx context.Context, id apid.ID) (*ToolSet, error)
	GetToolSetByName(ctx context.Context, namespace string, name scommon.ResourceName) (*ToolSet, error)
	UpdateToolSetConnectionSelector(ctx context.Context, id apid.ID, expectedRevision uint64, selector toolsetschema.ConnectionSelector) (*ToolSet, error)
	DeleteToolSet(ctx context.Context, id apid.ID) error

	// UpdateToolSetMetadata replaces the logical name, user labels, and
	// annotations without touching the selector or any generation.
	UpdateToolSetMetadata(ctx context.Context, id apid.ID, name scommon.ResourceName, userLabels map[string]string, annotations map[string]string) (*ToolSet, error)

	// ListToolSetsBuilder pages through live logical ToolSets within a namespace scope.
	ListToolSetsBuilder() ListToolSetsBuilder
	ListToolSetsFromCursor(ctx context.Context, cursor string) (ListToolSetsExecutor, error)

	// ListToolSetGenerationsBuilder pages through one live ToolSet's generations, newest first.
	ListToolSetGenerationsBuilder() ListToolSetGenerationsBuilder
	ListToolSetGenerationsFromCursor(ctx context.Context, cursor string) (ListToolSetGenerationsExecutor, error)

	// CreateToolSetGeneration allocates a new draft under a live parent. Only one
	// live draft may exist, and historical generation numbers are never reused.
	CreateToolSetGeneration(ctx context.Context, id apid.ID, definition encfield.EncryptedField) (*ToolSetGeneration, error)

	// GetToolSetGeneration returns one generation if it and its parent are live.
	GetToolSetGeneration(ctx context.Context, id apid.ID, generation uint64) (*ToolSetGeneration, error)

	// GetToolSetGenerationByState finds the sole draft or primary generation.
	GetToolSetGenerationByState(ctx context.Context, id apid.ID, state toolsetschema.ToolSetReleaseState) (*ToolSetGeneration, error)

	// UpdateToolSetGenerationDraft replaces only the expected editable revision
	// and advances its revision. Published plaintext cannot be changed here.
	UpdateToolSetGenerationDraft(ctx context.Context, id apid.ID, generation uint64, expectedRevision uint64, definition encfield.EncryptedField) (*ToolSetGeneration, error)

	// PublishToolSetGeneration atomically promotes the expected draft revision and
	// demotes the former primary. The caller must validate the definition and any
	// imported source snapshot before publishing; bindings are not migrated here.
	PublishToolSetGeneration(ctx context.Context, id apid.ID, generation uint64, expectedRevision uint64) (*ToolSetGeneration, error)

	// CreateToolSetBinding creates a pending assignment from the current matched
	// selector snapshot. It does not install a generation or inventory.
	CreateToolSetBinding(ctx context.Context, toolSetId apid.ID, connectionId apid.ID, expectedSelectorRevision uint64) (*ToolSetBinding, error)

	// GetToolSetBinding returns a live assignment whose two parents are live.
	GetToolSetBinding(ctx context.Context, id apid.ID) (*ToolSetBinding, error)

	// GetToolSetBindingForConnection finds the current assignment for a parent pair.
	GetToolSetBindingForConnection(ctx context.Context, toolSetId apid.ID, connectionId apid.ID) (*ToolSetBinding, error)

	// ListToolSetBindingsBuilder starts a listing of one connection's live assignments.
	ListToolSetBindingsBuilder() ListToolSetBindingsBuilder

	// ListToolSetBindingsFromCursor continues a binding listing with its saved filters.
	ListToolSetBindingsFromCursor(ctx context.Context, cursor string) (ListToolSetBindingsExecutor, error)

	// InstallExplicitToolSetInventory atomically pins a pending binding to its
	// prepared primary generation and installs its complete first Tool inventory.
	InstallExplicitToolSetInventory(ctx context.Context, install ToolSetInventoryInstall) (*ToolSetBinding, error)

	// ReplaceExplicitToolSetInventory replaces an installed inventory at its
	// captured epoch/generation, preserving identities for retained source keys.
	ReplaceExplicitToolSetInventory(ctx context.Context, install ToolSetInventoryInstall, expectedGeneration uint64) (*ToolSetBinding, error)

	// DeleteToolSetBinding retires a no-longer-matching assignment using its epoch
	// and current selector snapshot. Deleted-parent cleanup ignores selector revision.
	DeleteToolSetBinding(ctx context.Context, id apid.ID, expectedEpoch uint64, expectedSelectorRevision uint64) error

	// CreateStandaloneTool atomically stores an identity and its first active definition.
	CreateStandaloneTool(ctx context.Context, tool *Tool, definition encfield.EncryptedField, digest string) (*ToolRevision, error)

	// GetTool reads a live identity, including those whose connection was deleted.
	GetTool(ctx context.Context, id apid.ID) (*Tool, error)

	// ListToolCandidates scans bounded current metadata for later authorization;
	// its internal pages and cursors must not be exposed as discovery results.
	ListToolCandidates(ctx context.Context, query ToolCandidateQuery) (ToolCandidatePage, error)

	// ListToolCandidatesFromCursor resumes a candidate scan with its saved filters
	// and limit. Callers must still authorize each returned candidate.
	ListToolCandidatesFromCursor(ctx context.Context, cursor string) (ToolCandidatePage, error)

	// ListToolsBuilder pages live Tool identities for management, independent of
	// connection liveness. Callers must still check per-resource permissions.
	ListToolsBuilder() ListToolsBuilder

	// ListToolsFromCursor resumes a management listing with its saved filters.
	ListToolsFromCursor(ctx context.Context, cursor string) (ListToolsExecutor, error)

	// UpdateStandaloneTool appends a revision and switches the pointer only if the observed revision is current.
	UpdateStandaloneTool(ctx context.Context, tool *Tool, expectedRevision uint64, definition encfield.EncryptedField, digest string) (*ToolRevision, error)

	// DeleteStandaloneTool removes the observed identity while retaining its revision history.
	DeleteStandaloneTool(ctx context.Context, id apid.ID, expectedRevision uint64) error

	// GetCurrentToolRevision reads the active definition and its connection identity in one SQL snapshot.
	GetCurrentToolRevision(ctx context.Context, id apid.ID) (*ToolRevision, error)

	// GetToolExecutionSnapshot captures the active definition, connection configuration,
	// pinned connector definition, and ToolSet provenance together for invocation admission.
	// Callers still authorize the revision and check expected revision and readiness.
	GetToolExecutionSnapshot(ctx context.Context, id apid.ID) (*ToolExecutionSnapshot, error)

	// GetToolRevision inspects retained history; it does not select a definition for invocation.
	GetToolRevision(ctx context.Context, id apid.ID, revision uint64) (*ToolRevision, error)

	GetConnection(ctx context.Context, id apid.ID) (*Connection, error)
	CreateConnection(ctx context.Context, c *Connection) error
	UpdateConnectionName(ctx context.Context, id apid.ID, name scommon.ResourceName) (*Connection, error)
	DeleteConnection(ctx context.Context, id apid.ID) error
	SetConnectionState(ctx context.Context, id apid.ID, state ConnectionState) error
	SetConnectionHealthState(ctx context.Context, id apid.ID, state ConnectionHealthState) error
	SetConnectionSetupStep(ctx context.Context, id apid.ID, setupStep *cschema.SetupStep) error
	SetConnectionSetupError(ctx context.Context, id apid.ID, setupError *string) error
	SetConnectionEncryptedConfiguration(ctx context.Context, id apid.ID, encryptedConfig *encfield.EncryptedField) error
	UpdateConnectionLabels(ctx context.Context, id apid.ID, labels map[string]string) (*Connection, error)
	PutConnectionLabels(ctx context.Context, id apid.ID, labels map[string]string) (*Connection, error)
	DeleteConnectionLabels(ctx context.Context, id apid.ID, keys []string) (*Connection, error)
	UpdateConnectionAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*Connection, error)
	PutConnectionAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*Connection, error)
	DeleteConnectionAnnotations(ctx context.Context, id apid.ID, keys []string) (*Connection, error)
	UpdateConnectionForGenerationMigration(ctx context.Context, update ConnectionGenerationMigrationUpdate) (*Connection, error)
	ListConnectionsBuilder() ListConnectionsBuilder
	ListConnectionsFromCursor(ctx context.Context, cursor string) (ListConnectionsExecutor, error)

	/*
	 * Notifications
	 */
	UpsertNotification(ctx context.Context, upsert NotificationUpsert) (*Notification, error)
	GetNotification(ctx context.Context, id apid.ID) (*Notification, error)
	ListNotifications(ctx context.Context, opts ListNotificationsOptions) ([]Notification, error)
	MarkNotificationViewed(ctx context.Context, notificationID apid.ID, actorID apid.ID) error
	MarkNotificationsViewed(ctx context.Context, notificationIDs []apid.ID, actorID apid.ID) error
	NotificationViewedMap(ctx context.Context, actorID apid.ID, ids []apid.ID) (map[apid.ID]time.Time, error)
	ResolveNotificationsForResourceKeys(ctx context.Context, resourceType string, resourceID apid.ID, keys []string) error

	/*
	 * OAuth2 tokens
	 */
	GetOAuth2Token(ctx context.Context, connectionId apid.ID) (*OAuth2Token, error)
	InsertOAuth2Token(
		ctx context.Context,
		connectionId apid.ID,
		refreshedFrom *apid.ID,
		encryptedRefreshToken encfield.EncryptedField,
		encryptedAccessToken encfield.EncryptedField,
		accessTokenExpiresAt *time.Time,
		refreshTokenExpiry OAuth2RefreshTokenExpiry,
		scopes string,
		requestedScopes string,
		createdByActorId *apid.ID,
	) (*OAuth2Token, error)
	DeleteOAuth2Token(ctx context.Context, tokenId apid.ID) error
	DeleteAllOAuth2TokensForConnection(ctx context.Context, connectionId apid.ID) error

	// EnumerateOAuth2TokensExpiringWithin enumerates OAuth2 tokens that are expiring within a specified time interval
	// of now. This includes tokens that are already expired. It also includes tokens whose refresh token is due for
	// a proactive refresh (refresh_token_refresh_at has passed) regardless of access-token expiry. Deleted tokens are
	// not considered, nor are tokens tied to a deleted connection.
	EnumerateOAuth2TokensExpiringWithin(
		ctx context.Context,
		duration time.Duration,
		callback func(tokens []*OAuth2TokenWithConnection, lastPage bool) (keepGoing pagination.KeepGoing, err error),
	) error

	/*
	 * API Key credentials
	 */
	GetActiveApiKeyCredential(ctx context.Context, connectionId apid.ID) (*ApiKeyCredential, error)
	InsertApiKeyCredential(
		ctx context.Context,
		connectionId apid.ID,
		encryptedCredentials encfield.EncryptedField,
		placement *cschema.ApiKeyPlacement,
		createdByActorId *apid.ID,
	) (*ApiKeyCredential, error)
	UpdateApiKeyCredentialLastValidated(ctx context.Context, credentialId apid.ID, at time.Time) error
	DeleteAllApiKeyCredentialsForConnection(ctx context.Context, connectionId apid.ID) error

	/*
	 * Connection probe outcomes — append-only event log that drives the
	 * probe-driven health-check signal. The runtime walks the most-recent
	 * rows for each (connection_id, probe_id) to compute consecutive-success
	 * or -failure counts. A daily cleanup task caps growth (see
	 * internal/core/task_probe_outcome_cleanup.go).
	 */
	InsertProbeOutcome(ctx context.Context, connectionId apid.ID, probeId string, outcome string, errorMessage string) (*ConnectionProbeOutcome, error)
	GetRecentProbeOutcomes(ctx context.Context, connectionId apid.ID, probeId string, limit int) ([]*ConnectionProbeOutcome, error)
	DeleteOldProbeOutcomes(ctx context.Context, connectionId apid.ID, probeId string, keepMinimum int, olderThan time.Time) (int64, error)
	DistinctProbeIdsForConnection(ctx context.Context, connectionId apid.ID) ([]string, error)
	CountProbeOutcomes(ctx context.Context, connectionId apid.ID, probeId string) (int, error)

	GetKey(ctx context.Context, id apid.ID) (*Key, error)
	CreateKey(ctx context.Context, ek *Key) error
	UpdateKeyName(ctx context.Context, id apid.ID, name scommon.ResourceName) (*Key, error)
	UpdateKey(ctx context.Context, id apid.ID, updates map[string]interface{}) (*Key, error)
	DeleteKey(ctx context.Context, id apid.ID) error
	// DeleteUnusedKey refuses keys with namespace references or any DEK history.
	DeleteUnusedKey(ctx context.Context, id apid.ID) error
	SetKeyState(ctx context.Context, id apid.ID, state KeyState) error
	UpdateKeyLabels(ctx context.Context, id apid.ID, labels map[string]string) (*Key, error)
	PutKeyLabels(ctx context.Context, id apid.ID, labels map[string]string) (*Key, error)
	DeleteKeyLabels(ctx context.Context, id apid.ID, keys []string) (*Key, error)
	UpdateKeyAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*Key, error)
	PutKeyAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*Key, error)
	DeleteKeyAnnotations(ctx context.Context, id apid.ID, keys []string) (*Key, error)
	ListKeysBuilder() ListKeysBuilder
	ListKeysFromCursor(ctx context.Context, cursor string) (ListKeysExecutor, error)

	// EnumerateKeysInDependencyOrder loads all non-deleted keys and walks them
	// in breadth-first order starting from the root key (the one with nil EncryptedKeyData).
	// The callback receives one depth-level of keys at a time, with depth 0 being the root.
	// Returns a slice of orphaned keys whose parent key could not be resolved.
	EnumerateKeysInDependencyOrder(
		ctx context.Context,
		callback func(keys []*Key, depth int) (keepGoing pagination.KeepGoing, err error),
	) ([]*Key, error)

	CreateDataEncryptionKey(ctx context.Context, dek *DataEncryptionKey) error
	GetDataEncryptionKey(ctx context.Context, id apid.ID) (*DataEncryptionKey, error)
	GetCurrentDataEncryptionKeyForKey(ctx context.Context, keyId apid.ID) (*DataEncryptionKey, error)
	UpdateDataEncryptionKeyWrapping(ctx context.Context, dek *DataEncryptionKey) error
	ClearCurrentDataEncryptionKeyFlagForKey(ctx context.Context, keyId apid.ID) error
	SetDataEncryptionKeyCurrentFlag(ctx context.Context, id apid.ID, isCurrent bool) error
	ListDataEncryptionKeysForKey(ctx context.Context, keyId apid.ID) ([]*DataEncryptionKey, error)
	EnumerateDataEncryptionKeysForKey(
		ctx context.Context,
		keyId apid.ID,
		callback func(deks []*DataEncryptionKey, lastPage bool) (keepGoing pagination.KeepGoing, err error),
	) error

	GetRateLimit(ctx context.Context, id apid.ID) (*RateLimit, error)
	CreateRateLimit(ctx context.Context, rl *RateLimit) error
	UpdateRateLimitName(ctx context.Context, id apid.ID, name scommon.ResourceName) (*RateLimit, error)
	UpdateRateLimitDefinition(ctx context.Context, id apid.ID, def rlschema.RateLimitSpec) (*RateLimit, error)
	DeleteRateLimit(ctx context.Context, id apid.ID) error
	UpdateRateLimitLabels(ctx context.Context, id apid.ID, labels map[string]string) (*RateLimit, error)
	PutRateLimitLabels(ctx context.Context, id apid.ID, labels map[string]string) (*RateLimit, error)
	DeleteRateLimitLabels(ctx context.Context, id apid.ID, keys []string) (*RateLimit, error)
	UpdateRateLimitAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*RateLimit, error)
	PutRateLimitAnnotations(ctx context.Context, id apid.ID, annotations map[string]string) (*RateLimit, error)
	DeleteRateLimitAnnotations(ctx context.Context, id apid.ID, keys []string) (*RateLimit, error)
	ListRateLimitsBuilder() ListRateLimitsBuilder
	ListRateLimitsFromCursor(ctx context.Context, cursor string) (ListRateLimitsExecutor, error)

	// EnumerateFieldsRequiringReEncryption walks all registered encrypted fields across all tables,
	// finding rows whose encrypted field EKV ID does not match the namespace's target EKV ID.
	EnumerateFieldsRequiringReEncryption(
		ctx context.Context,
		callback func(targets []ReEncryptionTarget, lastPage bool) (keepGoing pagination.KeepGoing, err error),
	) error

	// BatchUpdateReEncryptedFields sets the new value and encrypted_at only on live
	// rows whose encrypted field still matches ExpectedValue. Stale updates are
	// skipped without error; earlier updates may be applied if a later one fails.
	BatchUpdateReEncryptedFields(ctx context.Context, updates []ReEncryptedFieldUpdate) error

	// PurgeSoftDeletedRecords hard-deletes all soft-deleted records where deleted_at is before olderThan.
	// Returns the total number of records deleted across all tables.
	PurgeSoftDeletedRecords(ctx context.Context, olderThan time.Time) (int64, error)

	// RefreshNamespaceLabelsCarryForward re-derives the materialized apxy/
	// portion of every resource that inherits from nsPath, then walks each
	// direct child namespace, recomputes its labels, and recurses. Each
	// row's update runs in its own short transaction. Intended to be
	// invoked from a background asynq task — a label change on a deeply
	// nested namespace can fan out to many descendants.
	RefreshNamespaceLabelsCarryForward(ctx context.Context, nsPath string) error

	// RefreshConnectionsForConnector re-derives the materialized
	// apxy/ portion of every connection pointing at the given logical
	// connector. Each connection's update runs in its own short
	// transaction. Intended to be invoked from a background asynq task
	// after a connector's user labels change.
	RefreshConnectionsForConnector(ctx context.Context, id apid.ID) error

	// ReconcileCarryForwardLabels walks every labelled resource in batches
	// of `batchSize` and re-derives the materialized apxy/ portion of
	// each row. The optional `limiter` is consulted before each row is
	// processed, providing a per-row records/sec rate limit; nil means
	// unlimited. Drift is rare under normal operation, but this method
	// is the safety net for any propagation task that misfired or any
	// data path that bypassed the carry-forward triggers. Intended to be
	// invoked from a daily asynq cron task. Returns the total number of
	// rows whose labels were corrected.
	ReconcileCarryForwardLabels(ctx context.Context, batchSize int32, limiter *rate.Limiter) (corrected int64, err error)

	HasNonceBeenUsed(ctx context.Context, nonce apid.ID) (hasBeenUsed bool, err error)
	CheckNonceValidAndMarkUsed(ctx context.Context, nonce apid.ID, retainRecordUntil time.Time) (wasValid bool, err error)
	DeleteExpiredNonces(ctx context.Context) (err error)
}

func MustApplyBlankTestDbConfig

func MustApplyBlankTestDbConfig(t testing.TB, cfg config.C) (config.C, DB)

MustApplyBlankTestDbConfig applies a test database configuration to the specified config root. The database is guaranteed to be blank and migrated. This method uses a temp file so that the database will be eventually cleaned up after the process exits. Note that the configuration in the root will be modified for the database and populated for the GlobalAESKey if it is not already populated.

To support debugging tests by inspecting the SQLite database, if the SQLITE_TEST_DATABASE_PATH env var is set this method will use the database at that path. It will delete the existing file at that path to recreate unless the SQLITE_TEST_DATABASE_PATH_CLEAR env var is set to false.

To run tests against Postgres, set AUTH_PROXY_TEST_DATABASE_PROVIDER=postgres and configure the connection with POSTGRES_TEST_HOST, POSTGRES_TEST_PORT, POSTGRES_TEST_USER, POSTGRES_TEST_PASSWORD, POSTGRES_TEST_DATABASE, and POSTGRES_TEST_OPTIONS. You can also tune POSTGRES_TEST_MAX_PARALLEL and POSTGRES_TEST_MAX_CONNS to reduce connection pressure.

Parameters: - t: the test instance used for naming and cleanup - cfg: the config to apply the database config to. This may be nil, in which case a new config is created. This method will overwrite the existing config.

Returns: - the config with information populated for the database. If a config was passed in, the same value is returned with data populated. - a database instance configured with the specified root. This database can be used directly, or if the root used again, it will connect to the same database instance.

func MustApplyBlankTestDbConfigRaw

func MustApplyBlankTestDbConfigRaw(t testing.TB, cfg config.C) (config.C, DB, *sql.DB)

func NewService

func NewService(db *sql.DB, dbConfig config.DatabaseImpl, logger *slog.Logger) (DB, error)

NewService creates the AuthProxy database service using an already-open and fully configured database/sql handle. The caller owns the SQL handle and is responsible for closing it.

type DataEncryptionKey

type DataEncryptionKey struct {
	Id               apid.ID
	KeyId            apid.ID
	Provider         string
	ProviderID       string
	ProviderVersion  string
	ProviderMetadata DataEncryptionKeyProviderMetadata
	ProtectedData    *sconfig.KeyVersionProtectedData
	IsCurrent        bool
	CreatedAt        time.Time
	UpdatedAt        time.Time
	DeletedAt        *time.Time
}

func (*DataEncryptionKey) Validate

func (d *DataEncryptionKey) Validate() error

type DataEncryptionKeyProviderMetadata

type DataEncryptionKeyProviderMetadata map[string]string

func (*DataEncryptionKeyProviderMetadata) Scan

func (m *DataEncryptionKeyProviderMetadata) Scan(value interface{}) error

func (DataEncryptionKeyProviderMetadata) Value

type DeletedHandling

type DeletedHandling bool
const (
	// DeletedHandlingExclude will exclude deleted records from the result set
	DeletedHandlingExclude DeletedHandling = false

	// DeletedHandlingInclude will include deleted records in the result set
	DeletedHandlingInclude DeletedHandling = true
)

type EncryptedFieldRegistration

type EncryptedFieldRegistration struct {
	Table          string
	PrimaryKeyCols []string // e.g. ["id"] or ["id", "generation"]
	EncryptedCols  []string // e.g. ["encrypted_access_token", "encrypted_refresh_token"]

	// Direct namespace resolution (most tables)
	NamespaceCol string // e.g. "namespace" — column on this table

	// Indirect namespace resolution via JOIN (e.g. oauth2_tokens → connections)
	JoinTable        string // e.g. "connections"
	JoinLocalCol     string // e.g. "connection_id" — FK column on this table
	JoinRemoteCol    string // e.g. "id" — PK column on join table
	JoinNamespaceCol string // e.g. "namespace" — namespace column on join table

}

EncryptedFieldRegistration declares which columns on a table contain encrypted fields and how the table resolves to a namespace.

func GetEncryptedFieldRegistrations

func GetEncryptedFieldRegistrations() []EncryptedFieldRegistration

GetEncryptedFieldRegistrations returns a copy of all registered encrypted field registrations.

type IActorData

type IActorData interface {
	GetId() apid.ID
	GetExternalId() string
	GetPermissions() []aschema.Permission
	GetNamespace() string
	GetLabels() map[string]string
	// GetAnnotations returns the annotations to apply on upsert. A nil return means
	// annotations should be left unchanged on existing actors (PATCH semantics);
	// a non-nil map (including empty) is treated as a full replacement.
	GetAnnotations() map[string]string
}

type IActorDataExtended

type IActorDataExtended interface {
	IActorData
	GetEncryptedKey() *encfield.EncryptedField
}

IActorDataExtended extends IActorData with additional fields for labels and encrypted key. This interface is used when creating or updating actors with extended data such as labels for tracking the source of admin syncs, or encrypted keys for admin authentication.

type Key

type Key struct {
	Id           apid.ID
	Namespace    string
	Name         scommon.ResourceName
	Usage        KeyUsage
	MaterialType KeyMaterialType
	// Key provider configuration is encrypted at rest, but it is not registered
	// with namespace re-encryption. It defines the key hierarchy, so rewrapping
	// it based on namespace targets can make a key depend on its own DEK.
	EncryptedKeyData *encfield.EncryptedField
	State            KeyState
	Labels           Labels
	Annotations      Annotations
	CreatedAt        time.Time
	UpdatedAt        time.Time
	EncryptedAt      *time.Time
	DeletedAt        *time.Time
}

Key represents a user-managed key configuration.

func (*Key) GetNamespace

func (ek *Key) GetNamespace() string

func (*Key) Validate

func (ek *Key) Validate() error

type KeyMaterialType

type KeyMaterialType string
const (
	KeyMaterialTypeSymmetric KeyMaterialType = "symmetric"
	KeyMaterialTypePublic    KeyMaterialType = "public"
	KeyMaterialTypePrivate   KeyMaterialType = "private"
	KeyMaterialTypeExternal  KeyMaterialType = "external"
)

type KeyOrderByField

type KeyOrderByField string
const (
	KeyOrderByState     KeyOrderByField = "state"
	KeyOrderByCreatedAt KeyOrderByField = "created_at"
	KeyOrderByUpdatedAt KeyOrderByField = "updated_at"
)

type KeyState

type KeyState string
const (
	KeyStateActive   KeyState = "active"
	KeyStateDisabled KeyState = "disabled"
)

type KeyUsage

type KeyUsage string
const (
	KeyUsageDataEncryption KeyUsage = "data_encryption"
)

type LabelOperator

type LabelOperator string
const (
	LabelOperatorEqual     LabelOperator = "="
	LabelOperatorNotEqual  LabelOperator = "!="
	LabelOperatorExists    LabelOperator = "exists"
	LabelOperatorNotExists LabelOperator = "!exists"
)

type LabelRequirement

type LabelRequirement struct {
	Key      string
	Operator LabelOperator
	Value    string
}

type LabelSelector

type LabelSelector []LabelRequirement

func ParseLabelSelector

func ParseLabelSelector(selector string) (LabelSelector, error)

ParseLabelSelector parses a Kubernetes-style label selector string. Supported syntax: - key=value, key==value - key!=value - key (exists) - !key (does not exist)

func (LabelSelector) ApplyToSqlBuilderWithProvider

func (s LabelSelector) ApplyToSqlBuilderWithProvider(q sq.SelectBuilder, labelsColumn string, provider config.DatabaseProvider) sq.SelectBuilder

func (LabelSelector) Matches

func (s LabelSelector) Matches(labels map[string]string) bool

Matches reports whether the supplied label map satisfies every requirement in the selector. An empty / nil selector matches any input — same convention the SQL-side uses (no requirements means no filter).

This is the in-memory counterpart to ApplyToSqlBuilderWithProvider used by the rate-limit evaluator (and any future runtime path that needs to match label selectors against per-request snapshots).

func (LabelSelector) String

func (s LabelSelector) String() string

type Labels

type Labels map[string]string

Labels is a map of key-value pairs following Kubernetes label restrictions. Keys follow the format [prefix/]name where: - prefix (optional): valid DNS subdomain, max 253 characters - name (required): 1-63 characters, alphanumeric start/end, may contain '-', '_', '.' Values: 0-63 characters, if non-empty must start/end with alphanumeric

func ApplyParentCarryForward

func ApplyParentCarryForward(userLabels Labels, parents ...ParentCarryForward) Labels

ApplyParentCarryForward composes a child resource's labels from the parents listed and the user-supplied labels. For each parent it calls BuildCarriedLabels(parent.Rt, parent.Labels) and merges the result; the user's own labels are merged last among non-self entries (they cannot collide with apxy/ keys because user input cannot reference the apxy/ namespace). Parents are applied in order, so a later parent's apxy/ pass-through overrides an earlier parent's — list parents from most distant to most direct so the most direct ancestor wins on conflicts (deeper-overrides-shallower).

Callers should follow with InjectSelfImplicitLabels (or InjectNamespaceSelfImplicitLabels for path-keyed namespaces) so the child's own self-implicit labels override any same-keyed pass-through from a parent.

func BuildCarriedLabels

func BuildCarriedLabels(parentRt string, parentLabels Labels) Labels

BuildCarriedLabels takes a parent's labels and returns the carry-forward labels for a child of the parent.

  • User labels on the parent (any key NOT starting with apxy/) are re-keyed under apxy/<parentRt>/<key>.
  • apxy/-prefixed labels on the parent are forwarded as-is so that ancestors further up the chain remain visible. The child is expected to merge its own self-implicit labels on top of this map (deeper overrides shallower).

parentRt is the resource-type token of the parent (e.g. "cxr", "cxn", "ns") — typically obtained via ApidPrefixToLabelToken.

func BuildImplicitResourceLabels

func BuildImplicitResourceLabels(id apid.ID, name scommon.ResourceName, namespacePath string) Labels

BuildImplicitResourceLabels returns the three implicit identity labels for an apid-keyed resource: apxy/<rt>/-/id, apxy/<rt>/-/name, and apxy/<rt>/-/ns, where <rt> is derived from the resource's id prefix.

func BuildImplicitResourceLabelsForToken

func BuildImplicitResourceLabelsForToken(rt, id string, name scommon.ResourceName, namespacePath string) Labels

BuildImplicitResourceLabelsForToken builds the apxy/<rt>/-/id, apxy/<rt>/-/name, and apxy/<rt>/-/ns implicit identity labels for any resource type, keyed by the supplied <rt> token and identifier string. This is the underlying builder used by both apid-keyed and path-keyed resources.

func BuildNamespaceImplicitResourceLabels

func BuildNamespaceImplicitResourceLabels(path string) Labels

BuildNamespaceImplicitResourceLabels builds a namespace's self-implicit identity labels. Both -/id and -/ns carry the namespace path, while -/name carries the final path segment.

func InjectNamespaceSelfImplicitLabels

func InjectNamespaceSelfImplicitLabels(path string, existing Labels) Labels

InjectNamespaceSelfImplicitLabels returns a copy of existing with a namespace's own apxy/ns/-/id, apxy/ns/-/name, and apxy/ns/-/ns labels added. Mirrors InjectSelfImplicitLabels but for path-keyed namespace resources.

func InjectSelfImplicitLabels

func InjectSelfImplicitLabels(id apid.ID, name scommon.ResourceName, namespacePath string, existing Labels) Labels

InjectSelfImplicitLabels returns a copy of existing with the resource's own apxy/<rt>/-/id, apxy/<rt>/-/name, and apxy/<rt>/-/ns labels added. The self-implicit labels override any same-keyed entries already in existing (deeper-overrides- shallower across the carry-forward chain). Callers pass this to the create path so the row is persisted with the implicit identity labels in place.

func MergeApxyAndUserLabels

func MergeApxyAndUserLabels(user, apxy Labels) Labels

MergeApxyAndUserLabels returns a single map containing both the user and apxy portions. Because the two inputs are partitioned by key prefix, no collisions are possible.

func MergeUpsertLabels

func MergeUpsertLabels(callerLabels, existingLabels Labels) Labels

MergeUpsertLabels composes the labels to persist on an upsert by combining caller-supplied labels with the row's existing apxy/ labels.

User-portion labels come from the caller — fully replacing what was stored (write-API endpoints that PATCH user labels go through a different helper). apxy/-prefixed labels merge: stored values are preserved by default, and any apxy/-prefixed entries the caller passes in override the stored values for those specific keys. This lets system code update its own provenance markers (e.g. apxy/cxr/source) on an upsert without requiring a separate label-mutation call, while still preserving apxy/ labels owned by other subsystems (e.g. carry-forward materializations).

func SplitUserAndApxyLabels

func SplitUserAndApxyLabels(labels Labels) (user, apxy Labels)

SplitUserAndApxyLabels partitions a labels map into the user-provided portion (no apxy/ prefix) and the system-managed portion (apxy/ prefix). The two returned maps are disjoint and together reconstitute the input. Either map may be nil if its half is empty.

func (Labels) Copy

func (l Labels) Copy() Labels

Copy returns a deep copy of the labels.

func (Labels) Get

func (l Labels) Get(key string) (string, bool)

Get returns the value for a label key, and whether the key exists.

func (Labels) Has

func (l Labels) Has(key string) bool

Has returns true if the label key exists.

func (*Labels) Scan

func (l *Labels) Scan(value interface{}) error

Scan implements the sql.Scanner interface for Labels

func (Labels) Validate

func (l Labels) Validate() error

Validate validates all labels (system mode — apxy/ keys allowed, with the longer SystemLabelValueMaxLength value cap for those keys).

func (Labels) Value

func (l Labels) Value() (driver.Value, error)

Value implements the driver.Valuer interface for Labels

type ListActorsBuilder

type ListActorsBuilder interface {
	ListActorsExecutor
	ForExternalId(externalId string) ListActorsBuilder
	ForName(name scommon.ResourceName) ListActorsBuilder
	ForNamespaceMatcher(matcher string) ListActorsBuilder
	ForNamespaceMatchers(matchers []string) ListActorsBuilder
	Limit(int32) ListActorsBuilder
	OrderBy(ActorOrderByField, pagination.OrderBy) ListActorsBuilder
	IncludeDeleted() ListActorsBuilder
	ForLabelSelector(selector string) ListActorsBuilder
}

type ListActorsExecutor

type ListActorsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[*Actor]
	Enumerate(context.Context, pagination.EnumerateCallback[*Actor]) error
}

type ListConnectionsBuilder

type ListConnectionsBuilder interface {
	ListConnectionsExecutor
	Limit(int32) ListConnectionsBuilder
	ForState(ConnectionState) ListConnectionsBuilder
	ForStates([]ConnectionState) ListConnectionsBuilder
	ForConnectorId(id apid.ID) ListConnectionsBuilder
	ForNamespaceMatcher(matcher string) ListConnectionsBuilder
	ForNamespaceMatchers(matchers []string) ListConnectionsBuilder
	ForName(name scommon.ResourceName) ListConnectionsBuilder
	OrderBy(ConnectionOrderByField, pagination.OrderBy) ListConnectionsBuilder
	IncludeDeleted() ListConnectionsBuilder
	WithDeletedHandling(DeletedHandling) ListConnectionsBuilder
	ForLabelSelector(selector string) ListConnectionsBuilder
	WithSetupStepNotNull() ListConnectionsBuilder
	UpdatedBefore(t time.Time) ListConnectionsBuilder
}

type ListConnectionsExecutor

type ListConnectionsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[Connection]
	Enumerate(context.Context, pagination.EnumerateCallback[Connection]) error
}

type ListKeysBuilder

type ListKeysBuilder interface {
	ListKeysExecutor
	Limit(int32) ListKeysBuilder
	ForNamespaceMatcher(matcher string) ListKeysBuilder
	ForNamespaceMatchers(matchers []string) ListKeysBuilder
	ForName(name scommon.ResourceName) ListKeysBuilder
	ForState(KeyState) ListKeysBuilder
	OrderBy(KeyOrderByField, pagination.OrderBy) ListKeysBuilder
	IncludeDeleted() ListKeysBuilder
	ForLabelSelector(selector string) ListKeysBuilder
}

type ListKeysExecutor

type ListKeysExecutor interface {
	FetchPage(context.Context) pagination.PageResult[Key]
	Enumerate(context.Context, pagination.EnumerateCallback[Key]) error
}

type ListNamespacesBuilder

type ListNamespacesBuilder interface {
	ListNamespacesExecutor
	Limit(int32) ListNamespacesBuilder
	ForPathPrefix(path string) ListNamespacesBuilder
	ForDepth(depth uint64) ListNamespacesBuilder
	ForChildrenOf(path string) ListNamespacesBuilder
	ForNamespaceMatcher(matcher string) ListNamespacesBuilder
	ForNamespaceMatchers(matchers []string) ListNamespacesBuilder
	ForName(name scommon.ResourceName) ListNamespacesBuilder
	ForState(NamespaceState) ListNamespacesBuilder
	OrderBy(NamespaceOrderByField, pagination.OrderBy) ListNamespacesBuilder
	IncludeDeleted() ListNamespacesBuilder
	ForLabelSelector(selector string) ListNamespacesBuilder
}

type ListNamespacesExecutor

type ListNamespacesExecutor interface {
	FetchPage(context.Context) pagination.PageResult[Namespace]
	Enumerate(context.Context, pagination.EnumerateCallback[Namespace]) error
}

type ListNotificationsOptions

type ListNotificationsOptions struct {
	States            []NotificationState
	ResourceType      string
	ResourceId        apid.ID
	NamespaceMatchers []string
	LabelSelector     *string
	Limit             uint64
	IncludeViewed     bool
	ActorId           apid.ID
}

type ListRateLimitsBuilder

type ListRateLimitsBuilder interface {
	ListRateLimitsExecutor
	Limit(int32) ListRateLimitsBuilder
	ForNamespaceMatcher(matcher string) ListRateLimitsBuilder
	ForNamespaceMatchers(matchers []string) ListRateLimitsBuilder
	ForName(name scommon.ResourceName) ListRateLimitsBuilder
	OrderBy(RateLimitOrderByField, pagination.OrderBy) ListRateLimitsBuilder
	IncludeDeleted() ListRateLimitsBuilder
	ForLabelSelector(selector string) ListRateLimitsBuilder
}

type ListRateLimitsExecutor

type ListRateLimitsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[RateLimit]
	Enumerate(context.Context, pagination.EnumerateCallback[RateLimit]) error
}

type ListToolSetBindingsBuilder

type ListToolSetBindingsBuilder interface {
	ListToolSetBindingsExecutor

	// Limit sets the page size. Non-positive values select the default and values
	// above MaxToolSetBindingListLimit are capped.
	Limit(int32) ListToolSetBindingsBuilder

	// ForConnectionId selects the connection whose assignments are listed.
	ForConnectionId(apid.ID) ListToolSetBindingsBuilder

	// ForToolSetNamespaceMatchers replaces the scope of visible parent ToolSets.
	// This scopes the ToolSet's namespace, which can be an ancestor of the
	// connection's. Replacing means a later call can never widen an earlier scope.
	ForToolSetNamespaceMatchers([]string) ListToolSetBindingsBuilder
}

ListToolSetBindingsBuilder pages one connection's live assignments whose two parents are live, ordered by ToolSet ID. ForConnectionId is required.

ToolSet namespace scope is required too: with no matchers the listing is empty, so a caller with no ToolSet access never learns what is bound. Invalid filters are reported as ErrInvalidListQuery when the listing runs. Callers must still apply per-resource permission checks.

type ListToolSetBindingsExecutor

type ListToolSetBindingsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[ToolSetBindingListing]
	Enumerate(context.Context, pagination.EnumerateCallback[ToolSetBindingListing]) error
}

ListToolSetBindingsExecutor runs a binding listing one page at a time or across every remaining page. Each FetchPage advances the listing, and Enumerate stops at the first error.

type ListToolSetGenerationsBuilder

type ListToolSetGenerationsBuilder interface {
	ListToolSetGenerationsExecutor

	// Limit sets the page size. Non-positive values select the default and values
	// above MaxToolSetListLimit are capped.
	Limit(int32) ListToolSetGenerationsBuilder

	// ForToolSetId selects the parent ToolSet.
	ForToolSetId(apid.ID) ListToolSetGenerationsBuilder

	// OrderBy selects the sort column and direction. Generation number always
	// breaks ties, newest first, so pages stay deterministic.
	OrderBy(ToolSetGenerationOrderByField, pagination.OrderBy) ListToolSetGenerationsBuilder
}

ListToolSetGenerationsBuilder selects the live generations of one live ToolSet, newest first unless OrderBy is set. ForToolSetId is required. A missing or deleted parent returns ErrNotFound rather than an empty page, so callers can distinguish an unknown ToolSet from one with no live generations.

type ListToolSetGenerationsExecutor

type ListToolSetGenerationsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[ToolSetGeneration]
	Enumerate(context.Context, pagination.EnumerateCallback[ToolSetGeneration]) error
}

ListToolSetGenerationsExecutor runs a generation listing one page at a time or across every remaining page. Each FetchPage advances the listing, and Enumerate stops at the first error.

type ListToolSetsBuilder

type ListToolSetsBuilder interface {
	ListToolSetsExecutor

	// Limit sets the page size. Non-positive values select the default and values
	// above MaxToolSetListLimit are capped.
	Limit(int32) ListToolSetsBuilder

	// ForNamespaceMatcher replaces the namespace scope with one matcher.
	ForNamespaceMatcher(string) ListToolSetsBuilder

	// ForNamespaceMatchers replaces the namespace scope. Replacing, rather than
	// adding to it, means a later call can never widen an earlier scope.
	ForNamespaceMatchers([]string) ListToolSetsBuilder

	// ForName selects one exact resource name.
	ForName(common.ResourceName) ListToolSetsBuilder

	// ForLabelSelector matches the logical ToolSet's labels, including inherited
	// namespace labels and self-implicit identity labels.
	ForLabelSelector(string) ListToolSetsBuilder

	// OrderBy selects the sort column and direction. Results always fall back to
	// ID so pages stay deterministic when sort values tie; the default sorts by ID.
	OrderBy(ToolSetOrderByField, pagination.OrderBy) ListToolSetsBuilder
}

ListToolSetsBuilder narrows a management listing of live logical ToolSets in live namespaces. All supplied filters intersect; generations are not consulted.

Namespace scope is required: with no matchers the listing is empty, so a missing permission scope never lists every ToolSet. Invalid filters are reported as ErrInvalidListQuery when the listing runs. Callers must still apply per-resource permission checks.

type ListToolSetsExecutor

type ListToolSetsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[ToolSet]
	Enumerate(context.Context, pagination.EnumerateCallback[ToolSet]) error
}

ListToolSetsExecutor runs a logical ToolSet listing one page at a time or across every remaining page. Each FetchPage advances the listing, and Enumerate stops at the first error.

type ListToolsBuilder

type ListToolsBuilder interface {
	ListToolsExecutor

	// Limit sets the page size. Non-positive values select the default and values
	// above MaxToolListLimit are capped.
	Limit(int32) ListToolsBuilder

	// ForNamespaceMatcher replaces the namespace scope with one matcher.
	ForNamespaceMatcher(string) ListToolsBuilder

	// ForNamespaceMatchers replaces the namespace scope. Replacing, rather than
	// adding to it, means a later call can never widen an earlier scope.
	ForNamespaceMatchers([]string) ListToolsBuilder

	// ForName selects one exact resource name.
	ForName(common.ResourceName) ListToolsBuilder

	// ForConnectionId selects Tools currently bound to one connection.
	ForConnectionId(apid.ID) ListToolsBuilder

	// ForLabelSelector matches Tool labels, including inherited connection identity.
	ForLabelSelector(string) ListToolsBuilder

	// OrderBy selects the sort column and direction. Results always fall back to
	// ID so pages stay deterministic when sort values tie; the default sorts by ID.
	OrderBy(ToolOrderByField, pagination.OrderBy) ListToolsBuilder
}

ListToolsBuilder narrows a management listing of live Tool identities. Unlike ToolCandidateQuery it does not require a live connection, active definition projections, or an installed binding, so administrators can inspect and clean up every Tool that GetTool would return. All supplied filters intersect.

Namespace scope is required: with no matchers the listing is empty, so a missing permission scope never lists every Tool. Invalid filters are reported as ErrInvalidListQuery when the listing runs. Results include standalone and generated Tools in live namespaces, whether or not their connection is still live; callers must still apply per-resource permission checks.

type ListToolsExecutor

type ListToolsExecutor interface {
	FetchPage(context.Context) pagination.PageResult[Tool]
	Enumerate(context.Context, pagination.EnumerateCallback[Tool]) error
}

ListToolsExecutor runs a management Tool listing one page at a time or across every remaining page. Each FetchPage advances the listing, and Enumerate stops at the first error.

type Namespace

type Namespace struct {
	Path string

	State                     NamespaceState
	KeyId                     *apid.ID
	TargetDataEncryptionKeyId *apid.ID
	Labels                    Labels
	Annotations               Annotations
	CreatedAt                 time.Time
	UpdatedAt                 time.Time
	DeletedAt                 *time.Time
	// contains filtered or unexported fields
}

Namespace is the grouping of resources within AuthProxy.

func (*Namespace) GetNamespace

func (ns *Namespace) GetNamespace() string

func (*Namespace) Validate

func (ns *Namespace) Validate() error

type NamespaceEncryptionTarget

type NamespaceEncryptionTarget struct {
	Path                      string
	Depth                     uint64
	KeyId                     *apid.ID
	TargetDataEncryptionKeyId *apid.ID
}

NamespaceEncryptionTarget holds the fields needed by the background job that computes and caches the target data encryption key for each namespace.

type NamespaceOrderByField

type NamespaceOrderByField string
const (
	NamespaceOrderByPath      NamespaceOrderByField = "path"
	NamespaceOrderByState     NamespaceOrderByField = "state"
	NamespaceOrderByCreatedAt NamespaceOrderByField = "created_at"
	NamespaceOrderByUpdatedAt NamespaceOrderByField = "updated_at"
)

type NamespaceState

type NamespaceState string
const (
	NamespaceStateActive     NamespaceState = "active"
	NamespaceStateDestroying NamespaceState = "destroying"
	NamespaceStateDestroyed  NamespaceState = "destroyed"
)

type NamespaceTargetDataEncryptionKeyUpdate

type NamespaceTargetDataEncryptionKeyUpdate struct {
	Path                      string
	TargetDataEncryptionKeyId apid.ID
}

NamespaceTargetDataEncryptionKeyUpdate carries an update to set the target data encryption key for a specific namespace.

type Notification

type Notification struct {
	// Id is the stable notification id, e.g. "ntf_...".
	Id apid.ID

	// Key is the deterministic dedupe key for the notification condition.
	// Reusing the same key upserts the active row instead of creating another
	// notification; for example:
	// "connection:cxn_...:auth_required".
	Key string

	// Level describes severity for presentation, such as "info" or "warning".
	Level NotificationLevel

	// State is "active" while the notification is visible and "resolved" once
	// the underlying condition no longer applies.
	State NotificationState

	// ResourceType names the resource that owns this notification, e.g.
	// "connection".
	ResourceType string

	// ResourceId is the owning resource id, e.g. a "cxn_..." connection id.
	ResourceId apid.ID

	// Namespace is the owning resource namespace used for list filtering and
	// permission checks, e.g. "root.acme".
	Namespace string

	// Labels is a denormalized snapshot of the owning resource labels so
	// notification lists can use label selectors such as "env=prod".
	Labels Labels

	// Title is the short user-facing summary shown in notification lists.
	Title string

	// Message is the longer user-facing explanation shown in detail surfaces.
	Message string

	// ActionUrl is the relative route for the suggested action, e.g.
	// "/connections/cxn_...?action=reauth"; it is only returned to actors that
	// satisfy ActionPermissions.
	ActionUrl *string

	// ViewPermissions are the stored permissions an actor must satisfy before
	// seeing the notification, usually a resource "get" permission.
	ViewPermissions NotificationPermissions

	// ActionPermissions are the stored permissions an actor must satisfy before
	// receiving ActionUrl/can_action=true, usually a resource "update"
	// permission.
	ActionPermissions NotificationPermissions

	// Metadata is producer-specific structured context for debugging or UI
	// hints, e.g. {"target_generation": 3, "requires_reauth": true}.
	Metadata NotificationMetadata

	// ResolvedAt is set when State transitions to resolved.
	ResolvedAt *time.Time

	// CreatedAt is when the notification row was first inserted.
	CreatedAt time.Time

	// UpdatedAt is when the notification was last changed or reactivated.
	UpdatedAt time.Time

	// DeletedAt is reserved for soft deletion; non-nil rows are excluded.
	DeletedAt *time.Time
}

func (*Notification) GetId

func (n *Notification) GetId() apid.ID

func (*Notification) GetNamespace

func (n *Notification) GetNamespace() string

func (*Notification) Validate

func (n *Notification) Validate() error

type NotificationLevel

type NotificationLevel string
const (
	NotificationLevelInfo    NotificationLevel = "info"
	NotificationLevelWarning NotificationLevel = "warning"
	NotificationLevelError   NotificationLevel = "error"
)

type NotificationMetadata

type NotificationMetadata map[string]any

func (*NotificationMetadata) Scan

func (m *NotificationMetadata) Scan(value interface{}) error

func (NotificationMetadata) Value

func (m NotificationMetadata) Value() (driver.Value, error)

type NotificationPermissions

type NotificationPermissions []aschema.Permission

func (*NotificationPermissions) Scan

func (p *NotificationPermissions) Scan(value interface{}) error

func (NotificationPermissions) Value

type NotificationState

type NotificationState string
const (
	NotificationStateActive   NotificationState = "active"
	NotificationStateResolved NotificationState = "resolved"
)

type NotificationUpsert

type NotificationUpsert struct {
	Key               string
	Level             NotificationLevel
	ResourceType      string
	ResourceId        apid.ID
	Namespace         string
	Labels            map[string]string
	Title             string
	Message           string
	ActionUrl         *string
	ViewPermissions   []aschema.Permission
	ActionPermissions []aschema.Permission
	Metadata          map[string]any
}

type OAuth2ClientCredentialsPlaintext

type OAuth2ClientCredentialsPlaintext struct {
	ClientId     string `json:"clientId"`
	ClientSecret string `json:"clientSecret,omitempty"`
}

type OAuth2RefreshTokenExpiry

type OAuth2RefreshTokenExpiry struct {
	// ExpiresAt is when the refresh token stops working.
	ExpiresAt *time.Time
	// RefreshAt is when to proactively refresh to keep the connection alive.
	RefreshAt *time.Time
}

OAuth2RefreshTokenExpiry carries what is known about a refresh token's lifetime when inserting a token row. The zero value means "unknown".

type OAuth2Token

type OAuth2Token struct {
	Id                    apid.ID
	ConnectionId          apid.ID // Foreign key to Connection; not enforced by database
	RefreshedFromId       *apid.ID
	EncryptedRefreshToken encfield.EncryptedField
	EncryptedAccessToken  encfield.EncryptedField
	AccessTokenExpiresAt  *time.Time
	// RefreshTokenExpiresAt is when the provider says the refresh token
	// stops working, derived from refresh_token_expires_in and related
	// token-response fields. Nil when the provider did not say.
	RefreshTokenExpiresAt *time.Time
	// RefreshTokenRefreshAt is when the background refresh task should
	// proactively refresh this token so that a new (or renewed) refresh
	// token is obtained before RefreshTokenExpiresAt. Nil when refreshing
	// cannot extend the refresh token's life or background refresh is off.
	RefreshTokenRefreshAt *time.Time
	Scopes                string
	RequestedScopes       string
	CreatedByActorId      *apid.ID // Actor who initiated this token (carried forward on refresh)
	CreatedAt             time.Time
	EncryptedAt           *time.Time
	DeletedAt             *time.Time
}

func (*OAuth2Token) IsAccessTokenExpired

func (t *OAuth2Token) IsAccessTokenExpired(ctx context.Context) bool

func (*OAuth2Token) Validate

func (t *OAuth2Token) Validate() error

type OAuth2TokenWithConnection

type OAuth2TokenWithConnection struct {
	Token      OAuth2Token
	Connection Connection
}

type ParentCarryForward

type ParentCarryForward struct {
	Rt     string
	Labels Labels
}

ParentCarryForward bundles a parent's resource-type token with the parent's stored labels for use with ApplyParentCarryForward.

type Permissions

type Permissions []aschema.Permission

Permissions is a custom type for a slice of permissions. The values are serlized to json.

func (*Permissions) Scan

func (p *Permissions) Scan(value interface{}) error

Scan implements the sql.Scanner interface for Permissions

func (Permissions) Value

func (p Permissions) Value() (driver.Value, error)

Value implements the driver.Valuer interface for Permissions

type PreparedToolSetTool

type PreparedToolSetTool struct {
	Tool                Tool
	EncryptedDefinition encfield.EncryptedField
	DefinitionDigest    string
}

PreparedToolSetTool pairs a generated identity and its discovery metadata with a compiled, encrypted explicit-template definition. The trusted caller supplies a provisional fresh ID, exact source key, name, namespace, connection, and binding identity. Replacement resolves retained IDs by source key; an omitted name retains the existing name. This layer derives parent labels, revision numbers, timestamps, and provenance. Compilation and encryption must finish before calling the database; definitions must retain symbolic configuration references, not resolved connection values.

type RateLimit

type RateLimit struct {
	Id          apid.ID
	Namespace   string
	Name        scommon.ResourceName
	Definition  rlschema.RateLimitSpec
	Labels      Labels
	Annotations Annotations
	CreatedAt   time.Time
	UpdatedAt   time.Time
	DeletedAt   *time.Time
}

RateLimit is the flat persistence model for a canonical RateLimit resource. Definition stores only RateLimitSpec in the existing JSON column; core owns conversion to and from apiVersion/kind/metadata/spec/status.

func (*RateLimit) GetNamespace

func (rl *RateLimit) GetNamespace() string

func (*RateLimit) Validate

func (rl *RateLimit) Validate() error

type RateLimitOrderByField

type RateLimitOrderByField string
const (
	RateLimitOrderByCreatedAt RateLimitOrderByField = "created_at"
	RateLimitOrderByUpdatedAt RateLimitOrderByField = "updated_at"
	RateLimitOrderByNamespace RateLimitOrderByField = "namespace"
)

type ReEncryptedFieldUpdate

type ReEncryptedFieldUpdate struct {
	Table            string
	PrimaryKeyCols   []string
	PrimaryKeyValues []any
	FieldColumn      string

	// ExpectedValue is the nonzero encrypted value read before re-encryption.
	// Both its key ID and ciphertext must still match when NewValue is written.
	ExpectedValue encfield.EncryptedField
	NewValue      encfield.EncryptedField
}

ReEncryptedFieldUpdate carries a re-encrypted value and the captured value it replaces. The update is skipped if the stored value changed in the meantime.

type ReEncryptionTarget

type ReEncryptionTarget struct {
	Table                     string
	PrimaryKeyCols            []string                // column names in PK order (from registration)
	PrimaryKeyValues          []any                   // values in PK column order
	FieldColumn               string                  // which encrypted column
	EncryptedFieldValue       encfield.EncryptedField // current value (contains the active DEK ID)
	TargetDataEncryptionKeyId apid.ID                 // target DEK for the namespace
}

ReEncryptionTarget represents one encrypted field on one row that needs re-encryption.

type ResourceSearcher

type ResourceSearcher interface {
	SearchResources(ctx context.Context, params SearchResourcesParams) (SearchResourcesResult, error)
}

ResourceSearcher is the replaceable database-facing search contract. The live database service implements it with bounded provider-specific queries; callers can substitute a projection-backed implementation later without changing the Admin API contract.

type SearchLabelMatch

type SearchLabelMatch struct {
	Key   string
	Value string
}

type SearchResource

type SearchResource struct {
	ResourceType  SearchResourceType
	ResourceID    string
	Name          string
	Namespace     string
	Labels        Labels
	MatchedLabels []SearchLabelMatch
	UpdatedAt     time.Time
	MatchRank     int
}

type SearchResourceType

type SearchResourceType string

SearchResourceType identifies a durable resource supported by the Admin UI command palette. Request events and task/workflow monitoring records are intentionally excluded because they are not stored in the primary database.

const (
	SearchResourceTypeActor      SearchResourceType = "actor"
	SearchResourceTypeConnection SearchResourceType = "connection"
	SearchResourceTypeConnector  SearchResourceType = "connector"
	SearchResourceTypeNamespace  SearchResourceType = "namespace"
	SearchResourceTypeKey        SearchResourceType = "key"
	SearchResourceTypeRateLimit  SearchResourceType = "rate_limit"
)

func SearchResourceTypes

func SearchResourceTypes() []SearchResourceType

type SearchResourcesParams

type SearchResourcesParams struct {
	ResourceType      SearchResourceType
	Query             string
	LabelSelector     string
	NamespaceMatchers []string
	Limit             int
}

type SearchResourcesResult

type SearchResourcesResult struct {
	Items     []SearchResource
	Truncated bool
}

type Tool

type Tool struct {
	Id             apid.ID
	Namespace      string
	Name           common.ResourceName
	ConnectionId   apid.ID
	ActiveRevision uint64
	CreatedAt      time.Time
	UpdatedAt      time.Time
	DeletedAt      *time.Time

	// Labels contains user labels plus derived apxy/ labels. Standalone writes
	// regenerate the system portion instead of trusting supplied projections.
	Labels Labels
	// Annotations belong to the Tool; parent annotations are never inherited.
	Annotations Annotations

	// Description is the active definition's public descriptive text. The trusted
	// preparer supplies it from the same plaintext it encrypts; this layer cannot
	// verify that correspondence. Never put resolved configuration or credentials
	// into this projection. Legacy rows may be empty until a definition update.
	Description string
	// Verbs are exact permission aliases, stored in sorted order. They support
	// candidate filtering, not authorization by themselves. Legacy nil values
	// mean unprepared, never unrestricted access. Historical aliases remain in
	// the encrypted revision; this list always describes ActiveRevision.
	Verbs []string

	// BindingId identifies the controller assignment that owns this Tool; nil
	// means standalone. A binding's removal/recreation creates a new identity.
	BindingId apid.ID
	// SourceKey is the exact source identity within a binding, independent of
	// display name. It is empty only for standalone Tools. The pair stays unique
	// across tombstones so a later inventory can restore the original Tool ID.
	SourceKey string
}

Tool is an operation identity bound to one connection in its namespace. A replacement changes its active revision atomically, while prior definitions remain immutable and inspectable. Labels include authored values and derived parent/self projections. Description and Verbs project the active definition. Generated inventories are installed atomically through their binding; current-definition and candidate reads check that installed ownership.

func (*Tool) Validate

func (t *Tool) Validate() error

Validate checks identity, metadata, definition projections, and the active revision. Legacy rows with missing projections remain readable but must have them supplied before a definition write. Parent liveness and connection namespace equality require transactional checks.

type ToolCandidate

type ToolCandidate struct {
	Id             apid.ID
	Namespace      string
	Name           common.ResourceName
	ConnectionId   apid.ID
	ConnectionName common.ResourceName
	ActiveRevision uint64
	Description    string
	Verbs          []string
	Labels         Labels
	// ConnectionLabels is the current connection row's own label snapshot,
	// rather than the Tool's potentially lagging inherited label projection.
	ConnectionLabels Labels
}

ToolCandidate contains current metadata needed for later authorization and discovery preparation. No executable source, schemas, annotations, resolved configuration, or credentials are read. It is not a public descriptor.

type ToolCandidatePage

type ToolCandidatePage struct {
	Items []ToolCandidate
	// Cursor resumes through ListToolCandidatesFromCursor with the same filters
	// and limit. It is empty at the end. The opaque cursor preserves a position
	// in the producing database's ID order; it does not confer authorization.
	Cursor string
}

ToolCandidatePage is a bounded internal batch, not an authorized result page. Callers must keep scanning after rejected candidates, filter permissions before visible ranking/counts/pagination, and bind public cursors to principal, JWT scope, and query. Calls do not share a snapshot: inserts before the scan position are not revisited, and invocation must recheck the current Tool and parents.

type ToolCandidateQuery

type ToolCandidateQuery struct {
	// NamespaceMatchers is an explicit scan scope. Nil or empty matches nothing.
	NamespaceMatchers []string `json:"namespaceMatchers"`

	// LabelSelector matches Tool labels, including inherited connection identity.
	LabelSelector string `json:"labelSelector"`

	// AnyVerbs matches exact literal aliases, never permission wildcard patterns.
	// Nil omits this prefilter; a nonnil empty slice matches nothing. The caller
	// must still check actor/JWT permission intersection for the same Tool alias.
	// Preserve nil versus empty when serializing a continuation cursor.
	AnyVerbs []string `json:"anyVerbs"`

	// Limit must be between one and MaxToolCandidateLimit; there is no default.
	Limit int `json:"limit"`
}

ToolCandidateQuery narrows an internal traversal of current Tool projections. It is not a public search request or permission check. All filters intersect, except that namespace matchers and verb aliases each match any member.

type ToolExecutionSnapshot

type ToolExecutionSnapshot struct {
	// Revision is the active Tool definition, including its schemas, aliases,
	// and captured source generation. It belongs to Connection.Id.
	Revision ToolRevision

	// Connection captures configuration ciphertext, effective stored labels,
	// annotations, lifecycle/setup/health state, and the pinned connector
	// identity. For example, a tenant configuration changed after this read does
	// not replace the tenant used by this invocation's templates.
	Connection Connection

	// Connector is the exact generation referenced by Connection, with its
	// logical metadata and encrypted definition. Hydration can build the
	// connection client from these rows without rereading its generation pin.
	Connector ConnectorWithDefinition

	// ToolSetId identifies the live installed binding's owner for a generated
	// Tool. It is apid.Nil for a standalone Tool; Revision.SourceGeneration
	// supplies the corresponding ToolSet generation.
	ToolSetId apid.ID
}

ToolExecutionSnapshot captures the stored inputs for one Tool invocation in a single SQL read. It is internal storage data, not an authorized invocation or an API response. The caller must authorize the captured revision's aliases, check any expected revision and execution readiness, and decrypt/compile the captured definitions before using them. Credentials are resolved separately through the connection's authentication method and may still refresh.

Each read owns its maps, pointers, and ciphertext. Later database updates do not change a returned snapshot. Consumers must likewise avoid rereading the active Tool or connection and mixing those new values with this revision.

type ToolOrderByField

type ToolOrderByField string

ToolOrderByField names a column management Tool listings can sort by.

const (
	ToolOrderById        ToolOrderByField = "id"
	ToolOrderByNamespace ToolOrderByField = "namespace"
	ToolOrderByName      ToolOrderByField = "name"
	ToolOrderByCreatedAt ToolOrderByField = "created_at"
	ToolOrderByUpdatedAt ToolOrderByField = "updated_at"
)

type ToolRevision

type ToolRevision struct {
	ToolId              apid.ID
	Revision            uint64
	ConnectionId        apid.ID
	EncryptedDefinition encfield.EncryptedField

	// DefinitionDigest is lowercase SHA-256 of the caller's canonical plaintext
	// definition, independent of randomized encryption and later key rotation.
	DefinitionDigest string
	CreatedAt        time.Time
	EncryptedAt      *time.Time
	DeletedAt        *time.Time

	// SourceGeneration is nil for standalone Tools and identifies the published
	// generation used to prepare a generated revision. The Tool's immutable
	// binding supplies its source ToolSet; later installations do not rewrite it.
	SourceGeneration *uint64
}

ToolRevision captures a prepared definition and its connection at publication. EncryptedDefinition contains the complete executable definition, including its schemas and aliases; callers own compilation, serialization, and encryption. ConnectionId is historical identity, so purging a former connection after a retarget must not delete this revision. Revisions are never updated in place, except that key rotation may replace ciphertext without changing the digest. Generated revisions also capture their source generation; catalog provenance and retention policies will be added with imported Tools.

func (*ToolRevision) Validate

func (r *ToolRevision) Validate() error

Validate checks identities, SQL counter bounds, ciphertext presence, and digest shape. The database cannot verify plaintext or its digest without decryption.

type ToolSet

type ToolSet struct {
	Id                 apid.ID
	Namespace          string
	Name               common.ResourceName
	Labels             Labels
	Annotations        Annotations
	ConnectionSelector toolsetschema.ConnectionSelector

	// SelectorRevision starts at one and advances with each accepted selector
	// replacement. It fences membership work independently of generation numbers.
	SelectorRevision uint64
	CreatedAt        time.Time
	UpdatedAt        time.Time
	DeletedAt        *time.Time
}

ToolSet is the logical, namespace-owned record shared by all generations. Definitions and publication state belong to separate generation records; neither publishing nor migrating a generation rewrites this selection policy.

func (*ToolSet) Validate

func (t *ToolSet) Validate() error

Validate checks the stored identity, metadata, selection scope, and positive revision. SQL counters use the signed 64-bit range shared by both providers.

type ToolSetBinding

type ToolSetBinding struct {
	Id           apid.ID
	ToolSetId    apid.ID
	ConnectionId apid.ID

	// Epoch starts at one and advances on inventory installation and removal.
	// Future inventory and context changes must advance it too.
	// It protects one assignment's lifetime, not the lifetime of the parent pair.
	Epoch     uint64
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt *time.Time

	// AppliedGeneration is nil until the first complete inventory is installed.
	// Removed bindings retain their last installed generation for inspection.
	AppliedGeneration *uint64
	// InventoryRevision is zero while pending and advances with complete
	// inventories. It differs from Epoch, which also advances on removal.
	InventoryRevision uint64
}

ToolSetBinding is an internal assignment identity, initially pending inventory installation. It is not a public resource or an execution grant. Removing and recreating the same pair allocates a new ID; a removed ID is never revived. Applied generation and inventory revision change together with the complete generated inventory, never independently through membership operations.

func (*ToolSetBinding) Validate

func (b *ToolSetBinding) Validate() error

Validate checks typed identities, counters in the shared SQL range, and the paired pending/installed state of the applied generation and inventory. Current parent liveness and membership require transactional database checks.

type ToolSetBindingListing

type ToolSetBindingListing struct {
	ToolSetBinding
	ConnectionNamespace string
	ToolSetNamespace    string
	ToolSetName         common.ResourceName
}

ToolSetBindingListing is one live assignment with the parent identity a management projection needs. The namespaces are read with the binding, so a caller can authorize both parents without loading either one.

type ToolSetGeneration

type ToolSetGeneration struct {
	ToolSetId           apid.ID
	Generation          uint64
	State               toolsetschema.ToolSetReleaseState
	EncryptedDefinition encfield.EncryptedField

	// Revision starts at one and advances on every accepted draft replacement.
	// Publication compares the revision the caller validated. It is independent
	// of the logical ToolSet's selector revision and of encryption-key rotation.
	Revision    uint64
	CreatedAt   time.Time
	UpdatedAt   time.Time
	EncryptedAt *time.Time
	DeletedAt   *time.Time
}

ToolSetGeneration is an encrypted definition owned by a logical ToolSet. Its composite identity is retained after soft deletion, so generation numbers cannot be reused. Published plaintext is immutable; key rotation may replace its ciphertext without changing the definition revision or release state.

func (*ToolSetGeneration) Validate

func (g *ToolSetGeneration) Validate() error

Validate checks storage identity, counters, release state, and the presence of encrypted content. Decryption and definition/compiler validation belong to the calling service, including source readiness checks before publication.

type ToolSetGenerationOrderByField

type ToolSetGenerationOrderByField string

ToolSetGenerationOrderByField names a column generation listings can sort by.

const (
	ToolSetGenerationOrderByGeneration ToolSetGenerationOrderByField = "generation"
	ToolSetGenerationOrderByState      ToolSetGenerationOrderByField = "state"
	ToolSetGenerationOrderByCreatedAt  ToolSetGenerationOrderByField = "created_at"
	ToolSetGenerationOrderByUpdatedAt  ToolSetGenerationOrderByField = "updated_at"
)

type ToolSetInventoryInstall

type ToolSetInventoryInstall struct {
	BindingId                apid.ID
	ExpectedEpoch            uint64
	ExpectedSelectorRevision uint64
	Generation               uint64
	Tools                    []PreparedToolSetTool
}

ToolSetInventoryInstall captures a complete inventory prepared from a published explicit ToolSet generation, for first installation or replacement. Both nil and empty Tools install an empty inventory. Remote catalogs require connection-context fencing and are not supported by these explicit operations.

type ToolSetOrderByField

type ToolSetOrderByField string

ToolSetOrderByField names a column logical ToolSet listings can sort by.

const (
	ToolSetOrderById        ToolSetOrderByField = "id"
	ToolSetOrderByNamespace ToolSetOrderByField = "namespace"
	ToolSetOrderByName      ToolSetOrderByField = "name"
	ToolSetOrderByCreatedAt ToolSetOrderByField = "created_at"
	ToolSetOrderByUpdatedAt ToolSetOrderByField = "updated_at"
)

type UsedNonce

type UsedNonce struct {
	Id          apid.ID
	RetainUntil time.Time
	CreatedAt   time.Time
}

UsedNonce represents a onetime use value (UUID) that has already been used in the system and cannot be used again. When used outside the system, nonces should also use some sort of expiry mechanism such that when they are used there is a known time that they must be retained until so that the list of used nonces doesn't grow infinitely.

Directories

Path Synopsis
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.

Jump to

Keyboard shortcuts

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