configplan

package
v0.1.13 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package configplan turns a plan, a scope of scanned tables and rules to apply to them, into a proposal: the configuration changes and a report of what they cover, what changes, the exceptions to look at, and when the changes take effect. It is deterministic and reads no database: the console, saved templates and the configuration MCP endpoint all evaluate plans here, against the scanned catalog and a base configuration.

Index

Constants

View Source
const (
	ChangeImport     = "import"
	ChangeCreateRole = "createRole"
	ChangeGrant      = "grant"
	ChangeExclude    = "exclude"
	ChangeMask       = "mask"
	ChangeSyncAdd    = "syncAdd"
	ChangeSyncRemove = "syncRemove"
)

Change kinds.

View Source
const (
	// ExceptionRenamed: the entity name differs from the table, which another
	// entity of the schema uses.
	ExceptionRenamed = "renamed"
	// ExceptionNoKey: no key identifies a row; updates and deletes are not
	// granted.
	ExceptionNoKey = "noKey"
	// ExceptionSideEffects: triggers or rules may write other tables.
	ExceptionSideEffects = "sideEffects"
	// ExceptionRelationshipDropped: a foreign key references a table that has
	// no entity.
	ExceptionRelationshipDropped = "relationshipDropped"
	// ExceptionQualified: an existing reference would name several entities
	// once the plan adds its own; it is rewritten to the ID of the one it
	// named.
	ExceptionQualified = "qualified"
	// ExceptionUnknownUser: a grant names a user that does not exist.
	ExceptionUnknownUser = "unknownUser"
	// ExceptionNoFields: a grant's field patterns match no field.
	ExceptionNoFields = "noFields"
	// ExceptionReferenced: a field to remove is still referenced.
	ExceptionReferenced = "referenced"
	// ExceptionDenied: the connection lacks the privilege for an action.
	ExceptionDenied = "denied"
	// ExceptionReview: a new table enters an existing grant.
	ExceptionReview = "review"
)

Exception kinds.

View Source
const (
	// LevelBlock exceptions keep the proposal from being taken. No rule of
	// the engine raises one today; an outcome that does not validate blocks
	// the same way.
	LevelBlock = "block"
	// LevelConfirm exceptions change what is granted or fail to apply: taking
	// the proposal needs them acknowledged.
	LevelConfirm = "confirm"
	// LevelInfo exceptions only inform.
	LevelInfo = "info"
)

Exception levels: what a reviewer has to do about an exception.

Variables

This section is empty.

Functions

func ConfiguredTables

func ConfiguredTables(datasource string, cat introspect.Catalog, cfg *config.Config) map[string]config.EntityConfig

ConfiguredTables maps each catalog table (by TableKey) to the configured entity of datasource that reads it, resolved by the catalog like the runtime does.

func IdentityUniqueKeys

func IdentityUniqueKeys(d entity.Entity) [][]string

IdentityUniqueKeys lists the unique keys of d that identify a row.

func Ref

func Ref(datasource, schema, table string) string

Ref names a table: datasource.schema.table, or datasource.table in a datasource without schemas, like an entity ID.

func TableKey

func TableKey(schema, table string) string

TableKey identifies a table within a datasource: tables of different schemas may share a name.

func Unscanned

func Unscanned(sources []Source, scope Scope) map[string][]string

Unscanned lists, per datasource in scope, the listed schemas the scope covers that were never scanned: the plan cannot see their tables.

Types

type Candidate

type Candidate struct {
	Table entity.Entity
	// Configured is the entity of the configuration that reads the table.
	Configured *config.EntityConfig
	// Entity is an entity proposed for the table, named like the
	// configured one if any.
	Entity config.EntityConfig
	// ID identifies the entity: the configured one's when configured.
	ID string
}

Candidate is a scanned table with the entity that reads it, if any, and a zero-permission entity proposed for it.

func Candidates

func Candidates(
	datasource string, cat introspect.Catalog, cfg *config.Config, names map[string]string, only map[string]bool,
) []Candidate

Candidates proposes an entity for the tables of cat (those of only, by TableKey, when only is not nil), sorted by schema and table: names follow the tables, numbered when another entity of the datasource and schema uses one; names (by TableKey) are preferred where given. Names are worked out over every table, so a candidate is named the same whichever are asked for. Foreign keys become relationships between candidates and to configured entities, in both directions.

type Change

type Change struct {
	Kind      string
	Principal string
	Actions   []string
	Mask      string
	// Fields counts the fields a field change touches.
	Fields   int
	Entities []string
}

Change summarizes one kind of change over the entities it applies to.

type Exception

type Exception struct {
	Kind string
	// Level is block, confirm or info (see levelOf).
	Level string
	// Warning marks exceptions that are not only informative.
	Warning bool
	// Ref is the table, when excluding it is a way out.
	Ref    string
	Entity string
	// Detail names what the exception is about: a name, an action, a field.
	Detail string
}

Exception is something a reviewer should look at.

type FieldRule

type FieldRule struct {
	// Columns are glob patterns on column names.
	Columns []string `json:"columns"`
	// Types are glob patterns on column types; empty: any type.
	Types   []string `json:"types,omitempty"`
	Exclude bool     `json:"exclude,omitempty"`
	Mask    string   `json:"mask,omitempty"`
}

FieldRule hides or masks the fields of matching columns.

type GrantRule

type GrantRule struct {
	// Principal is role:<name> or user:<name>; a role is created if needed.
	Principal string   `json:"principal"`
	Actions   []string `json:"actions"`
	// Fields are glob patterns of the fields granted; empty: every field.
	Fields []string `json:"fields,omitempty"`
	// Rows filters the rows granted, as in a grant.
	Rows config.FilterConfig `json:"rows,omitempty"`
}

GrantRule grants actions to a role or a user.

type Index

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

Index is every scanned table with where it stands, worked out once for a set of scans and a configuration: many scopes (catalog pages, counts of conditions, several administrators) filter it instead of each resolving the configured entities of every table again.

func NewIndex

func NewIndex(sources []Source, base, published *config.Config) *Index

NewIndex indexes the tables of sources against base and published (nil: none).

func (*Index) At

func (x *Index) At(i int32) Row

At is the row at a position Match listed.

func (*Index) Len

func (x *Index) Len() int

Len is how many tables are indexed.

func (*Index) Match

func (x *Index) Match(scope Scope) []int32

Match lists the positions of the rows in scope, in order: a few bytes a row, to keep for paging through them with At.

func (*Index) Referenced

func (x *Index) Referenced(ref string) int

Referenced counts the foreign keys of scanned tables referencing a table.

func (*Index) Rows

func (x *Index) Rows(scope Scope) []Row

Rows lists the rows in scope, as Rows does.

type Input

type Input struct {
	// Base is the configuration the plan changes: the console's workspace,
	// or the published configuration.
	Base *config.Config
	// Published tells published tables from those only in Base; nil: none.
	Published *config.Config
	Sources   []Source
	// Denied reports an entity action the serving connections cannot run,
	// with why; nil reports none.
	Denied func(entity, action string) (reason string, denied bool)
	// Review reports every new table a grant covers, as a recurring
	// template's proposal needs.
	Review bool
}

Input is what a plan is evaluated against.

type Objects

type Objects struct {
	Datasource string
	Schema     string
	Tables     int
	Imported   int
	Changed    int
}

Objects counts what the plan covers in one schema.

type Plan

type Plan struct {
	Scope Scope `json:"scope"`
	// Import adds an entity for each table in scope no entity reads.
	Import bool `json:"import,omitempty"`
	// Grants grant actions on the entities of the tables in scope.
	Grants []GrantRule `json:"grants,omitempty"`
	// Fields hide or mask the fields of those entities by column.
	Fields []FieldRule `json:"fields,omitempty"`
	// Sync brings their fields in line with the scanned columns.
	Sync *SyncRule `json:"sync,omitempty"`
	// Exclude leaves tables out of the plan, by Ref.
	Exclude []string `json:"exclude,omitempty"`
	// Names names the entities imported for tables, by Ref.
	Names map[string]string `json:"names,omitempty"`
}

Plan selects tables and says what to do with them. Its JSON form is what templates store and the MCP tools take.

func Decode

func Decode(data []byte) (Plan, error)

Decode reads a plan, rejecting unknown keys, and checks it.

func (*Plan) Check

func (p *Plan) Check() error

Check reports a plan that cannot be evaluated.

type Proposal

type Proposal struct {
	// Config is Base with the changes applied.
	Config *config.Config
	// Entities are the entities added or changed, in configuration order.
	Entities []config.EntityConfig
	// Added are the IDs of the entities added.
	Added []string
	// Roles and Users are the principals added or changed.
	Roles  map[string]config.RoleDefinition
	Users  map[string]config.UserConfig
	Report Report
}

Proposal is the outcome of a plan.

func Evaluate

func Evaluate(in Input, p Plan) (Proposal, error)

Evaluate applies p to in.Base. It does not validate the result: the caller runs it through the configuration chain.

func (Proposal) Edit

func (p Proposal) Edit() configedit.Edit

Edit is the proposal as an edit of the configuration it was evaluated against: the sections it changes, whole, as what they say (config.SpecOf: a default is left unset, as before it applied).

func (Proposal) Empty

func (p Proposal) Empty() bool

Empty reports a proposal that changes nothing.

type Report

type Report struct {
	// Matched counts the tables in scope; Excluded those left out of them.
	Matched  int
	Excluded int
	Objects  []Objects
	Changes  []Change
	// Exceptions need a look: they may be excluded or changed.
	Exceptions []Exception
	// Unscanned are the schemas in scope never scanned, by datasource.
	Unscanned map[string][]string
	// ScannedFrom and ScannedTo bound when the tables in scope were scanned;
	// zero when unknown.
	ScannedFrom, ScannedTo time.Time
}

Report is what a reviewer reads before taking a proposal.

type Row

type Row struct {
	Ref        string
	Datasource string
	Table      entity.Entity
	Status     Status
	// Entity is the entity of the base configuration that reads the table.
	Entity *config.EntityConfig
	// Added are columns without a field, Missing fields without a column.
	Added, Missing []string
	// ScannedAt is when the table's schema was scanned; zero when unknown.
	ScannedAt time.Time
}

Row is a scanned table with where it stands against the configuration.

func Rows

func Rows(sources []Source, base, published *config.Config, scope Scope) []Row

Rows lists the tables of sources in scope, sorted by datasource, schema and table, with their status against base and published (nil: none). The scope is compiled once; conditions on the table alone are checked before its status is worked out.

func (Row) Drift

func (r Row) Drift() bool

Drift reports whether the entity's fields differ from the columns.

type Scope

type Scope struct {
	// Datasources limits the scope to these datasources; empty: all.
	Datasources []string `json:"datasources,omitempty"`
	// Schemas are glob patterns (* and ?) on schema names; empty: all.
	Schemas []string `json:"schemas,omitempty"`
	// Tables are glob patterns on table names; empty: all.
	Tables []string `json:"tables,omitempty"`
	// Search matches a part of the table name or its comment.
	Search string `json:"search,omitempty"`
	// Status limits the scope to tables in these states; empty: all.
	Status []Status `json:"status,omitempty"`
	// Drift limits the scope to configured tables whose columns and fields
	// differ.
	Drift bool `json:"drift,omitempty"`
	// Refs limits the scope to these tables.
	Refs []string `json:"refs,omitempty"`
}

Scope selects scanned tables; every condition set must hold.

type Source

type Source struct {
	Datasource string
	// Catalog holds every scanned schema of the datasource.
	Catalog introspect.Catalog
	// Listed are the schemas the datasource lists; nil when unknown.
	Listed []string
	// Scanned are the schemas scanned.
	Scanned []string
	// ScannedAt is when each scanned schema was scanned.
	ScannedAt map[string]time.Time
}

Source is what was scanned of one datasource.

type Status

type Status string

Status is where a table stands against the configuration.

const (
	// StatusNew tables are read by no entity.
	StatusNew Status = "new"
	// StatusWorkspace tables are read by an entity not yet published.
	StatusWorkspace Status = "workspace"
	// StatusPublished tables are read by a published entity.
	StatusPublished Status = "published"
)

Table states.

type SyncRule

type SyncRule struct {
	Add    bool `json:"add,omitempty"`
	Remove bool `json:"remove,omitempty"`
	// HideNew excludes the fields it adds until they are reviewed.
	HideNew bool `json:"hideNew,omitempty"`
}

SyncRule adds fields for new columns and removes those of dropped ones.

Jump to

Keyboard shortcuts

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