store

package
v2.10.1 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package store defines the two ports the engine is built against (ManifestStore and OperationalStore) and the record shapes they persist. The SQLite adapter (package sqlite) and the in-memory adapter (package memory) both satisfy these interfaces and are proven equivalent by the conformance suite in package conformance.

Index

Constants

View Source
const (
	ItemSave   = ""
	ItemDelete = "delete"
	ItemState  = "state"
)

What an item does to its record.

View Source
const (
	ChangeSetOpen     = "open"
	ChangeSetProposed = "proposed"
	// ChangeSetMerging is held while its items are committed, so two
	// acceptances never both commit them.
	ChangeSetMerging = "merging"
	ChangeSetMerged  = "merged"
	ChangeSetClosed  = "closed"
)

Where a change set stands.

View Source
const (
	ProposeSave   = "save"
	ProposeAppend = "append"
	ProposeState  = "state"
)

What a proposal does.

View Source
const (
	ProposalOpen     = "open"
	ProposalAccepted = "accepted"
	ProposalDeclined = "declined"
)

Where a proposal stands.

View Source
const EnrolledByDirectory = "directory"

EnrolledByDirectory is the AddedBy of a person a sign-in listed.

Variables

View Source
var (
	// ErrNoChangeSet is a change set that does not exist.
	ErrNoChangeSet = errors.New("no such change set")
	// ErrChangeSetMoved is a change set no longer where a move expected
	// it: accepted or closed by someone else meanwhile.
	ErrChangeSetMoved = errors.New("the change set has moved on since")
)
View Source
var (
	// ErrNoProposal is a proposal that does not exist.
	ErrNoProposal = errors.New("no such proposal")
	// ErrProposalDecided is a proposal decided already.
	ErrProposalDecided = errors.New("this proposal has been decided already")
)
View Source
var ErrNoAgentGrant = errors.New("no such agent grant")

ErrNoAgentGrant is a grant that does not exist.

View Source
var ErrNoDocument = errors.New("no such document")

ErrNoDocument is returned for a document id or a manifest that has no shared document.

View Source
var ErrNoPerson = errors.New("not on the access list")

ErrNoPerson is returned for an address that is not on the access list.

Functions

This section is empty.

Types

type AccessStore added in v2.2.0

type AccessStore interface {
	// ListPeople returns everyone on the list, by address.
	ListPeople(ctx context.Context) ([]Person, error)
	// GetPerson returns one person, or ErrNoPerson.
	GetPerson(ctx context.Context, email string) (Person, error)
	// GrantPerson lists a person if they are not listed, with AddedBy and
	// AddedOn from p, and sets the roles, teams and AgentsOff an
	// administrator grants. It leaves everything a sign-in records as it
	// is.
	GrantPerson(ctx context.Context, p Person) (Person, error)
	// RecordSignIn sets the name, subject, directory roles and teams and
	// the time of a sign-in, listing the person first when s.Enrol says
	// so. It leaves what an administrator granted as it is.
	RecordSignIn(ctx context.Context, s SignIn) (Person, error)
	// DeletePerson removes a person from the list, or returns ErrNoPerson.
	DeletePerson(ctx context.Context, email string) error

	// Agent grants (docs/adr/0016): a person's consent to one agent
	// acting for them, kept so it can be listed and revoked. Whatever
	// token carries a grant is the authorization server's, never stored.
	PutAgentGrant(ctx context.Context, g AgentGrant) error
	// GetAgentGrant returns one, or ErrNoAgentGrant.
	GetAgentGrant(ctx context.Context, id string) (AgentGrant, error)
	// ListAgentGrants returns a person's grants, or everyone's for "",
	// newest first.
	ListAgentGrants(ctx context.Context, email string) ([]AgentGrant, error)
	// RevokeAgentGrant marks a grant revoked at at; ErrNoAgentGrant when
	// there is none. Revoking twice keeps the first time.
	RevokeAgentGrant(ctx context.Context, id string, at time.Time) error
	// TouchAgentGrant records when a grant was last used.
	TouchAgentGrant(ctx context.Context, id string, at time.Time) error
	// RotateAgentGrant moves a grant's generation from from to from+1,
	// atomically: false when it was not at from (a code or refresh token
	// used twice), or there is no such grant.
	RotateAgentGrant(ctx context.Context, id string, from int) (bool, error)
}

AccessStore keeps the access list. Every method is atomic for one person: two replicas recording the same person's sign-in, or a sign-in racing an administrator's change, both leave every field either writer set.

type AgentGrant added in v2.5.0

type AgentGrant struct {
	ID        string
	Email     string
	Label     string
	CreatedAt time.Time
	ExpiresAt time.Time
	LastUsed  time.Time
	RevokedAt time.Time
	// Generation counts the codes and refresh tokens exchanged for the
	// grant: each carries the generation it was issued at, so one used
	// twice is told from the latest.
	Generation int
}

AgentGrant is one agent a person let act for them: its label, when it was granted, when it expires, when it was last used, and whether it was revoked.

type ApplyFile

type ApplyFile struct {
	Path    string // Path relative to vault root (e.g., "vault.yaml" or "Goal/some-goal.yaml")
	SHA256  string // SHA-256 hash of content (hex, 64 chars)
	Content []byte // File content
}

ApplyFile is one file write within an ApplyUnit: path relative to vault root, sha256 hash of content (for idempotence during replay), and the content itself.

type ApplyJournal

type ApplyJournal interface {
	// PutUnit writes a new unit with applied=false.
	PutUnit(ctx context.Context, unit ApplyUnit) error

	// MarkApplied marks a unit as applied and updates the index. Called in the
	// same transaction as index updates (rebuild, rehydration, reference indexing).
	MarkApplied(ctx context.Context, unitID string) error

	// ListUnapplied returns every unit with applied=false, oldest first.
	ListUnapplied(ctx context.Context) ([]ApplyUnit, error)

	// PruneOld removes applied units older than the given count (keeps the most
	// recent `keepCount` applied units). A keepCount of 0 or less means unlimited.
	PruneOld(ctx context.Context, keepCount int) error

	// WithinTransaction runs fn against the journal in a transaction (adapters
	// that support transactions). Idempotent with database adapters.
	WithinTransaction(ctx context.Context, fn func(ctx context.Context, tx ApplyJournal) error) error
}

ApplyJournal records every mutation (apply, exclude, recover, etc.) with a two-phase commit: write the unit (applied=false), commit files to disk, then mark applied and update the index in one transaction.

type ApplyUnit

type ApplyUnit struct {
	ID       string      // Unique identifier for this unit (uuid)
	On       time.Time   // When the mutation happened
	Operator string      // Who performed it (actor, "local" for file operations)
	Reason   string      // Why (for exclusion, recovery, or user-supplied reason)
	Files    []ApplyFile // Files to write: {path, sha256, content}
	Applied  bool        // Whether this unit was applied (committed to files and index)
}

ApplyUnit is one mutation: a set of file writes recorded first with applied=false, then files written (temp file and rename, vault.yaml last), then marked applied and the index updated in one transaction. On open, replay every unit not applied.

type Bundle

type Bundle struct {
	Location string
	Paths    map[string]string
}

Bundle is where a handoff's files went. Location is what the state history records: a path relative to the vault root for the vault adapter, an opaque name for others. Paths maps each file name to where a person can find it, for the command line to print.

type BundleStore

type BundleStore interface {
	// PutBundle stores files (name to content) for one project at one
	// version, all or nothing, and returns where they went.
	PutBundle(ctx context.Context, projectID string, version int, files map[string][]byte) (Bundle, error)
}

BundleStore keeps the files a handoff produces (the rendered charter in its formats) beside the version they were rendered from. The vault adapter writes them under .cartograph/handoff; the memory adapter keeps them in memory, which is what tests need.

type ChangeItem added in v2.7.0

type ChangeItem struct {
	Set, Kind, ID string
	Text          []byte
	// Base is the manifest's latest version when the change set first
	// touched it; 0 for a manifest the change set creates.
	Base int
	// Included is false for an item trimmed from the next acceptance: it
	// stays in the change set, as a draft, for later.
	Included bool
	By       string
	At       time.Time
	// Op is what the item does to its record when the change set is
	// rolled in (docs/adr/0024): "" saves Text as its next version,
	// ItemDelete deletes the record, ItemState moves a project to State.
	Op    string
	State string
}

ChangeItem is one manifest's draft in a change set.

type ChangeSet added in v2.7.0

type ChangeSet struct {
	ID          string
	Title       string
	Description string
	// Owner is who works in it: an agent's grant, so two agents never
	// share one, or a person who opened it.
	Owner string
	// Agent is the agent working in it, if one is; For is the person it
	// acts for, who alone accepts it ("" for an anonymous operator).
	Agent string
	For   string
	// Status is ChangeSetOpen, ChangeSetProposed, ChangeSetMerging,
	// ChangeSetMerged or ChangeSetClosed.
	Status string
	// Reason and Waivers are what proposing it said: why, and the checks
	// left open with why each.
	Reason  string
	Waivers []Waiver
	At      time.Time
	Updated time.Time
	// DecidedBy, DecidedAt and DecisionReason record the last time it
	// was accepted or closed.
	DecidedBy      string
	DecidedAt      time.Time
	DecisionReason string
}

ChangeSet is a piece of work kept apart from the record and from every other piece of work until it is accepted, as a pull request is (docs/adr/0022): its own drafts of every manifest it touches, each with the version it started from, reviewed in one place and accepted whole.

type ChangeSetFilter added in v2.7.0

type ChangeSetFilter struct {
	For, Owner, Status string
}

ChangeSetFilter narrows a list. An empty field matches anything.

type ChangeSetStore added in v2.7.0

type ChangeSetStore interface {
	// PutChangeSet keeps a change set, replacing one with its id.
	PutChangeSet(ctx context.Context, cs ChangeSet) error
	// GetChangeSet returns one, or ErrNoChangeSet.
	GetChangeSet(ctx context.Context, id string) (ChangeSet, error)
	// ListChangeSets returns those the filter matches, newest first.
	ListChangeSets(ctx context.Context, f ChangeSetFilter) ([]ChangeSet, error)
	// MoveChangeSet moves a change set from one status to another,
	// recording who, when and why; ErrChangeSetMoved when it is not in
	// from, ErrNoChangeSet when there is none.
	MoveChangeSet(ctx context.Context, id, from, to, by, reason string, at time.Time) (ChangeSet, error)
	// PutChangeItem keeps an item, replacing the one for its manifest.
	PutChangeItem(ctx context.Context, it ChangeItem) error
	// GetChangeItem returns a change set's item for a manifest; found is
	// false when it has none.
	GetChangeItem(ctx context.Context, set, kind, id string) (it ChangeItem, found bool, err error)
	// ListChangeItems returns a change set's items, oldest first.
	ListChangeItems(ctx context.Context, set string) ([]ChangeItem, error)
	// DeleteChangeItem drops an item; none is no error.
	DeleteChangeItem(ctx context.Context, set, kind, id string) error
}

ChangeSetStore keeps change sets and their items. Moving one is atomic: of two moves from the same status at once, one wins and the other is ErrChangeSetMoved.

type Chunk

type Chunk struct {
	Seq  int64
	Data []byte
}

Chunk is one saved piece of a shared document: incremental changes, appended in the order the store received them.

type ConflictError

type ConflictError struct {
	Kind   string
	ID     string
	Ours   []byte
	Theirs []byte
}

ConflictError is returned by PutVersion when a manifest's file on disk has changed since it was last read, indicating concurrent edits that need reconciliation. Both Ours (the version being written) and Theirs (the current file on disk) carry the full YAML text.

func (*ConflictError) Error

func (e *ConflictError) Error() string

type DocRepairer added in v2.3.0

type DocRepairer interface {
	// StaleDocs returns up to limit versions and working copies stored
	// without a document. A working copy has Number 0.
	StaleDocs(ctx context.Context, limit int) ([]Version, error)

	// PutDocs stores the document of each version or working copy given,
	// matched by Kind, ID and Number. It changes nothing else.
	PutDocs(ctx context.Context, docs []Version) error
}

DocRepairer is a ManifestStore whose documents can be missing: rows a writer stored as text alone, such as a replica of an earlier release during a rolling upgrade. The engine decodes them and puts the documents back.

type DocStore

type DocStore interface {
	// Create records a new document for a manifest with its first
	// snapshot, unless the manifest already has one. created is false,
	// and docID the existing document's, when another writer got there
	// first; the caller then loads that one and discards its own.
	Create(ctx context.Context, kind, id, docID string, snapshot []byte) (existing string, created bool, err error)
	// DocumentFor returns the document id of a manifest's draft, or
	// ErrNoDocument.
	DocumentFor(ctx context.Context, kind, id string) (string, error)
	// ManifestFor returns the manifest a document belongs to, or
	// ErrNoDocument.
	ManifestFor(ctx context.Context, docID string) (kind, id string, err error)
	// Append stores a chunk and returns its sequence number, which is
	// greater than every earlier one for the document.
	Append(ctx context.Context, docID string, data []byte) (int64, error)
	// Load returns the snapshot and every chunk since, oldest first.
	Load(ctx context.Context, docID string) (snapshot []byte, chunks []Chunk, err error)
	// Since returns the chunks after seq, oldest first; always non-nil.
	Since(ctx context.Context, docID string, after int64) ([]Chunk, error)
	// Compact replaces the snapshot with one that includes every chunk
	// up to and including upTo, and drops those chunks. Chunks appended
	// after upTo, even while compacting, are kept.
	Compact(ctx context.Context, docID string, snapshot []byte, upTo int64) error
}

DocStore keeps the shared draft of each manifest as a CRDT document (docs/adr/0007): a compacted snapshot plus the chunks appended since. Loading the snapshot and every chunk, in any order, reproduces the document, so concurrent appends from different replicas never need arbitration. It holds bytes only; what they mean is the crdt port's business.

The document is not the record of truth; versions are. It is the draft between them, and it carries on across versions.

type DocWorkingStore added in v2.3.0

type DocWorkingStore interface {
	PutWorkingDoc(ctx context.Context, kind, id string, text, doc []byte) error
}

DocWorkingStore is a ManifestStore that keeps a working copy's document beside its text, as it keeps a version's (Version.Doc).

type Event added in v2.3.0

type Event struct {
	Seq    int64
	At     time.Time
	Type   string // "version", "state" or "series"
	Kind   string
	ID     string
	Number int    // the version, for "version"
	Detail string // the new state, or the series item's key
	Actor  string
}

Event is one thing that happened to the record: a version saved, a project's state changed, a series item recorded. Seq orders them and is a consumer's cursor.

type EventLog added in v2.3.0

type EventLog interface {
	// Events returns up to limit events after seq after, oldest first.
	Events(ctx context.Context, after int64, limit int) ([]Event, error)
}

EventLog reads the events a store wrote as it saved. Every adapter writes them in the transaction of the change itself, so an event is never lost and never early.

type Exclusion

type Exclusion struct {
	Kind     string    // Manifest kind
	ID       string    // Manifest id
	Name     string    // Manifest name at time of exclusion
	On       time.Time // When excluded
	Reason   string    // Why excluded
	Operator string    // Who excluded it
}

Exclusion is one manifest that has been excluded from the live state.

type ManifestDraft

type ManifestDraft struct {
	Kind string
	ID   string
	YAML []byte
	On   time.Time
}

ManifestDraft is a manifest's working copy: the YAML as last saved with the draft header, never validated beyond its basic shape, never versioned. Keyed by Kind and ID (generalised from the Project-only project_draft table).

type ManifestStore

type ManifestStore interface {
	// PutVersion appends a new version. The caller is responsible for
	// computing Number as one more than the current version (or 1 for a
	// new manifest); an adapter rejects a Number that is not exactly that,
	// which is what guards immutability under concurrent writers.
	PutVersion(ctx context.Context, v Version) error

	// GetCurrent returns the highest-numbered version of a manifest.
	GetCurrent(ctx context.Context, kind, id string) (Version, bool, error)

	// GetVersion returns one specific historical version.
	GetVersion(ctx context.Context, kind, id string, number int) (Version, bool, error)

	// ListVersions returns every version of a manifest, oldest first.
	ListVersions(ctx context.Context, kind, id string) ([]Version, error)

	// ListAllVersions returns every version of every manifest across all
	// kinds, newest first, with optional pagination (limit defaults to 20,
	// cursor is opaque and returned by the preceding call). Used by the
	// snapshots list endpoint.
	ListAllVersions(ctx context.Context, limit int, cursor string) (versions []Version, nextCursor string, err error)

	// ListSummaries returns the current version of every manifest of a
	// kind, optionally filtered by a case-insensitive substring match over
	// id and name (query, ignored when empty) and by zero or more
	// reference filters (refs; a manifest must have a current outgoing
	// reference matching every one of them - logical AND, ignored when
	// empty). Always returns a non-nil, possibly empty, slice.
	ListSummaries(ctx context.Context, kind, query string, refs []RefFilter) ([]Summary, error)

	// ListIDs returns the id of every manifest of a kind that has a
	// current version.
	ListIDs(ctx context.Context, kind string) ([]string, error)

	// Counts returns the number of manifests (by id, not by version) for
	// every kind that has at least one.
	Counts(ctx context.Context) (map[string]int, error)

	// IndexReferences replaces the recorded outgoing references for one
	// manifest's current version. The engine calls this once per commit,
	// right after PutVersion, inside the same transaction, with every
	// x-cartograph-ref value found by walking that kind's schema.
	IndexReferences(ctx context.Context, fromKind, fromID string, refs []Ref) error

	// ListReferencedBy returns every outgoing reference recorded for one
	// manifest's current version.
	ListReferencedBy(ctx context.Context, fromKind, fromID string) ([]Ref, error)

	// ListReferencing returns the current summary of every manifest that
	// has an outgoing reference to toKind/toID.
	ListReferencing(ctx context.Context, toKind, toID string) ([]Summary, error)

	// PutWorking writes a manifest's YAML as the working copy without creating
	// a version. Used for autosave writes that don't create an explicit
	// snapshot. The working copy is updated, but no version entry is created.
	PutWorking(ctx context.Context, kind, id string, yamlBytes []byte) error

	// GetWorking returns a manifest's working copy (the file on disk that may
	// not yet be versioned). Returns found=false when no working copy exists.
	GetWorking(ctx context.Context, kind, id string) ([]byte, bool, error)

	// WithinTransaction runs fn against a ManifestStore that commits all of
	// its writes together, or none of them if fn returns an error.
	WithinTransaction(ctx context.Context, fn func(ctx context.Context, tx ManifestStore) error) error

	// Exclude removes a manifest from vault.yaml and records the exclusion.
	// The file remains on disk. Returns an error if the manifest does not exist
	// (use GetCurrent to check first). Refused if the manifest is referenced by
	// a live manifest (call ListReferencing first).
	Exclude(ctx context.Context, kind, id, name, reason, operator string) error

	// ListExcluded returns every excluded manifest, newest first.
	ListExcluded(ctx context.Context) ([]Exclusion, error)

	// Recover re-adds an excluded manifest to vault.yaml and removes the
	// exclusion record. Returns an error if the file is missing from disk.
	Recover(ctx context.Context, kind, id, reason, operator string) error
}

ManifestStore holds every manifest version ever committed. Rows are immutable: once written, a version is never updated or deleted.

type NotFoundError

type NotFoundError struct {
	Kind string
	ID   string
}

ErrNotFound is returned by Get-style methods is expressed with the bool "found" return instead of a sentinel error, to keep call sites simple; this type exists only for adapters that need a concrete not-found error internally (for example inside a transaction helper).

func (*NotFoundError) Error

func (e *NotFoundError) Error() string

type OperationalStore

type OperationalStore interface {
	// PutProjectStateTransition appends one row to a project's state
	// history (the table is append-only; the current state is the most
	// recent row). A project with no rows is implicitly "draft".
	PutProjectStateTransition(ctx context.Context, e ProjectStateEntry) error

	// ListProjectStateHistory returns every state transition for a
	// project, oldest first. Empty (never nil) when the project has never
	// moved out of the implicit "draft" state.
	ListProjectStateHistory(ctx context.Context, projectID string) ([]ProjectStateEntry, error)
}

OperationalStore holds facts about manifests: project state history and project drafts. Later increments add readings and data-quality check results.

type Person added in v2.2.0

type Person struct {
	// Email is the key: the organisation address, lower-case.
	Email string
	// Name is the display name the directory gave at the last sign-in,
	// empty until the first.
	Name string
	// Subject is the identity provider's stable identifier, from the
	// last sign-in.
	Subject string
	// Roles and Teams are what an administrator granted.
	Roles []string
	Teams []string
	// DirectoryRoles and DirectoryTeams are what the directory's groups
	// gave at the last sign-in.
	DirectoryRoles []string
	DirectoryTeams []string
	// AddedBy is the actor who listed the person: an administrator, or
	// the directory when a sign-in enrolled them.
	AddedBy string
	AddedOn time.Time
	// LastSignedIn is zero until the first sign-in.
	LastSignedIn time.Time
	// AgentsOff is an administrator turning this person's agents off,
	// whatever their roles allow (docs/adr/0016).
	AgentsOff bool
}

Person is one entry on the access list (docs/adr/0011, TAXONOMY.md D27): someone who may sign in, and what they hold. It is operational state about a principal, never a manifest.

What an administrator grants and what the directory grants are kept apart, so a sign-in refreshing the one never undoes the other.

type ProjectStateEntry

type ProjectStateEntry struct {
	ProjectID string
	State     string
	Actor     string
	Reason    string
	On        time.Time
	Snapshot  int
	Bundle    string
}

ProjectStateEntry is one row of a project's state history: at On, Actor moved the project to State, giving Reason (required only for a move to cancelled; empty otherwise). Snapshot and Bundle are set when state is handed off: Snapshot is the version number, Bundle is the directory path where the charter bundle was written (relative to vault root).

type Proposal added in v2.5.0

type Proposal struct {
	ID         string
	Kind       string
	ManifestID string
	// Op is ProposeSave, ProposeAppend or ProposeState.
	Op string
	// Text is the manifest to commit, for ProposeSave.
	Text []byte
	// Series and Item are the series and the item to record, as JSON,
	// for ProposeAppend.
	Series string
	Item   []byte
	// State is where to move the project, for ProposeState.
	State string
	// Base is the manifest's latest version when it was proposed.
	Base   int
	Reason string
	// Waivers are the checks the agent left open, each with its reason,
	// for its person to see before deciding.
	Waivers []Waiver
	// Set groups proposals that stand or fall together (manifests that
	// reference each other, such as a KPI, the gap it measures and the
	// outcome that closes it); SetIndex is the order they are saved in.
	// "" for a proposal on its own.
	Set      string
	SetIndex int
	// Agent is the agent that proposed it; For is the person it acts for,
	// who alone may decide it (their address, or "" for an anonymous
	// operator).
	Agent string
	For   string
	At    time.Time
	// Status is ProposalOpen, ProposalAccepted or ProposalDeclined.
	Status         string
	DecidedBy      string
	DecidedAt      time.Time
	DecisionReason string
	// Version is the version accepting it made, when it made one.
	Version int
}

Proposal is something an agent proposed for its person to confirm (docs/adr/0016): what would make the record, kept exactly as proposed, with the version it was proposed against.

type ProposalFilter added in v2.5.0

type ProposalFilter struct {
	For, Kind, ManifestID, Status, Set string
}

ProposalFilter narrows a list. An empty field matches anything; Status "" is every status.

type ProposalStore added in v2.5.0

type ProposalStore interface {
	PutProposal(ctx context.Context, p Proposal) error
	// GetProposal returns one, or ErrNoProposal.
	GetProposal(ctx context.Context, id string) (Proposal, error)
	// ListProposals returns those the filter matches, newest first.
	ListProposals(ctx context.Context, f ProposalFilter) ([]Proposal, error)
	// DecideProposal moves an open proposal to status, recording who,
	// when, why and the version made; ErrProposalDecided when it is not
	// open, ErrNoProposal when there is none.
	DecideProposal(ctx context.Context, id, status, by, reason string, at time.Time, version int) (Proposal, error)
	// DecideProposalSet decides every proposal of a set at once, or none:
	// ErrProposalDecided when any is not open, ErrNoProposal when the set
	// has none. versions gives the version each made, by proposal id.
	DecideProposalSet(ctx context.Context, set, status, by, reason string, at time.Time, versions map[string]int) ([]Proposal, error)
}

ProposalStore keeps proposals. Deciding one is atomic: of two decisions at once, one wins and the other is ErrProposalDecided.

type Ref

type Ref struct {
	Path   string
	ToKind string
	ToID   string
}

Ref is one outgoing reference recorded for a manifest: at Path (a JSON pointer within it) it names ToKind/ToID.

type RefFilter

type RefFilter struct {
	Kind string
	ID   string
}

RefFilter narrows ListSummaries to manifests with an outgoing reference to Kind/ID.

type SeriesItem added in v2.3.0

type SeriesItem struct {
	Kind, ID string
	// Series is the array's JSON pointer, "/spec/readings".
	Series string
	// Key is the value of the element's key field, its period.
	Key string
	// Item is the element as JSON; nil records that it was removed.
	Item       []byte
	RecordedAt time.Time
	RecordedBy string
	Reason     string
}

SeriesItem is one element of a series: an array a kind's schema marks x-cartograph-series, such as a KPI's readings. Besides living in the manifest, every item is kept as an append-only row of what was recorded, when and by whom, so a series can be read as it stood at any time and reported on without reading every version (docs/adr/0013).

type SeriesStore added in v2.3.0

type SeriesStore interface {
	RecordSeries(ctx context.Context, items []SeriesItem) error

	// SeriesAsOf returns each manifest's series as it stood at at (the
	// zero time for now): for every key the item recorded last, leaving
	// out removed ones, in key order, by manifest id. ids limits it to
	// those manifests; nil is every manifest of the kind.
	SeriesAsOf(ctx context.Context, kind, series string, ids []string, at time.Time) (map[string][]SeriesItem, error)
}

SeriesStore keeps series items. The engine records them in the transaction of the save that changed them.

type SetReader added in v2.3.0

type SetReader interface {
	// CurrentOfKind returns what GetCurrent returns for every manifest of
	// a kind (the working copy where there is one, else the highest
	// version), ordered by id.
	CurrentOfKind(ctx context.Context, kind string) ([]Version, error)

	// ReferencingKind returns, for every manifest of toKind that something
	// references, what ListReferencing returns for it, keyed by its id.
	ReferencingKind(ctx context.Context, toKind string) (map[string][]Summary, error)

	// CurrentMany returns what GetCurrent returns for each of ids that
	// exists, ordered by id: a page of a list, read in one call.
	CurrentMany(ctx context.Context, kind string, ids []string) ([]Version, error)
}

SetReader is a ManifestStore that answers for many manifests in one call. The engine asks for sets wherever it would otherwise loop over GetCurrent or ListReferencing, which in a database across a network is a round trip per manifest (docs/adr/0012). An adapter implements it when it can answer each in one query; the engine falls back to the loop when it does not.

type SignIn added in v2.2.0

type SignIn struct {
	Email, Name, Subject string
	// Roles and Teams are what the person's directory groups give now.
	Roles, Teams []string
	At           time.Time
	// Enrol lists the person when they are not listed yet, added by
	// EnrolledByDirectory at At; otherwise an unlisted person's sign-in
	// is ErrNoPerson.
	Enrol bool
}

SignIn is what a sign-in reports about a person.

type StateSetReader added in v2.3.0

type StateSetReader interface {
	// CurrentStates returns the latest state of each project given that
	// has any history; a project without one is in the implicit "draft".
	CurrentStates(ctx context.Context, projectIDs []string) (map[string]string, error)
}

StateSetReader is an OperationalStore that answers the current state of many projects in one call, for a list of projects.

type StateStore

type StateStore interface {
	// Name is the state manifest's own id (metadata.id).
	Name() string

	// Included returns every ref ("Kind/id") the state manifest includes,
	// in the order it lists them.
	Included(ctx context.Context) ([]string, error)

	// ListUnapplied returns every manifest the adapter can see that is
	// neither included nor excluded: what a person could apply next.
	ListUnapplied(ctx context.Context) ([]UnappliedRef, error)

	// Apply includes the given refs. Applying a ref that is already
	// included is quiet; a ref the adapter cannot find is refused with
	// an error that names it. Returns how many refs were newly included.
	Apply(ctx context.Context, refs []string) (added int, err error)

	// StateYAML returns the state manifest's own bytes, or found=false
	// when the adapter has not written one yet.
	StateYAML(ctx context.Context) (yaml []byte, found bool, err error)

	// Rehydrate reloads the live state from the adapter's source of
	// truth. Called after Apply or Recover changed what is included.
	Rehydrate(ctx context.Context) error
}

StateStore is the apply gate: an adapter keeps a state manifest (an include list) over manifests that can exist before they are included. The vault adapter implements it over vault.yaml. A database adapter where every row is live has no need for it.

type Summary

type Summary struct {
	Kind      string
	ID        string
	Name      string
	Version   int
	UpdatedOn time.Time

	// Labels is metadata.labels, carried on the summary so a list can be
	// grouped and filtered by them. Nil where the manifest sets none.
	Labels map[string]string

	// Draft is true only for a synthetic Summary standing in for a
	// project that has only ever been saved as a draft, never committed
	// (includeDrafts=true): Version is then 0 and UpdatedOn is the
	// draft's own save time. False (the zero value) for every ordinary,
	// committed Summary a store adapter's own ListSummaries builds.
	Draft bool

	// Proposed is "new" or "changed" when a list is read as if a change
	// set were accepted (docs/adr/0024) and this summary is its draft;
	// empty otherwise. Set by the engine, never by an adapter.
	Proposed string
}

Summary is the list-view projection of a manifest's current version.

type SummaryPager added in v2.3.0

type SummaryPager interface {
	// ListSummariesAfter is ListSummaries limited to ids after afterID
	// ("" for the first page), at most limit of them, in id order.
	ListSummariesAfter(ctx context.Context, kind, query string, refs []RefFilter, afterID string, limit int) ([]Summary, error)
}

SummaryPager is a ManifestStore that lists one page of a kind at a time, so a page costs its own size and not the kind's.

type UnappliedRef

type UnappliedRef struct {
	Kind string
	ID   string
	Name string
}

UnappliedRef is one manifest that could be applied.

type VaultIndex

type VaultIndex interface {
	ManifestStore                  // versions, summaries, references, working copies, exclusions
	Journal() ApplyJournal         // the two-phase apply journal
	Operational() OperationalStore // project state history (same database)
	Docs() DocStore                // the shared drafts' CRDT documents (same database)
	Access() AccessStore           // the access list (same database)

	// File hashes: what the vault compares a file against on open and on a watcher event.
	GetFileHash(ctx context.Context, kind, id string) (sha256 string, found bool, err error)
	PutFileHash(ctx context.Context, kind, id, sha256, mtime string) error
	DeleteFileHash(ctx context.Context, kind, id string) error

	// Meta: small key/value facts about the index itself (the recorded vault.yaml hash, rebuild time).
	GetMeta(ctx context.Context, key string) (value string, found bool, err error)
	PutMeta(ctx context.Context, key, value string) error

	Close() error
}

VaultIndex is everything the vault adapter keeps beside its files: the rebuildable cache a database holds for it. SQLite implements it today; any adapter that passes conformance.RunVaultIndex may.

type Version

type Version struct {
	Kind   string
	ID     string
	Number int
	YAML   []byte
	Actor  string
	Reason string
	On     time.Time

	// Doc is the same manifest as a JSON document, decoded by the engine
	// at every save. YAML stays what the person wrote; Doc is what an
	// adapter that keeps documents stores, indexes and queries. An
	// adapter may ignore it, and need not return it.
	Doc []byte
}

Version is one immutable, committed version of a manifest.

type VersionCounter added in v2.3.0

type VersionCounter interface {
	// LatestNumber returns the highest version number recorded, 0 when
	// there is none.
	LatestNumber(ctx context.Context, kind, id string) (int, error)
}

VersionCounter is a ManifestStore that knows a manifest's highest version number without reading its history. The engine asks it for the next number at every save; without it, it lists every version.

type Waiver added in v2.6.0

type Waiver struct {
	// On is the manifest it is on, as Kind/id, in a change set; empty on
	// a proposal, which is on one manifest.
	On      string `json:"on,omitempty"`
	Check   string `json:"check"`
	Message string `json:"message"`
	Reason  string `json:"reason"`
}

Waiver is a check an agent proposed without meeting: the check, what it said, and why the agent left it.

Directories

Path Synopsis
Package conformance is the one test suite every store adapter must pass, proving the SQLite, in-memory and Postgres adapters are interchangeable behind the store ports.
Package conformance is the one test suite every store adapter must pass, proving the SQLite, in-memory and Postgres adapters are interchangeable behind the store ports.
Package manifestmeta reads metadata.name and metadata.labels out of a manifest's text, for the store adapters that index both beside each version.
Package manifestmeta reads metadata.name and metadata.labels out of a manifest's text, for the store adapters that index both beside each version.
Package memory is the in-memory ManifestStore and OperationalStore adapter used by tests and by the conformance suite.
Package memory is the in-memory ManifestStore and OperationalStore adapter used by tests and by the conformance suite.
Package postgres is the Postgres adapter for the ports a stateless deployment needs (docs/adr/0008): store.ManifestStore, store.OperationalStore, store.BundleStore and store.DocStore, over one database through pgx, a pure-Go driver, so the binary stays CGO_ENABLED=0.
Package postgres is the Postgres adapter for the ports a stateless deployment needs (docs/adr/0008): store.ManifestStore, store.OperationalStore, store.BundleStore and store.DocStore, over one database through pgx, a pure-Go driver, so the binary stays CGO_ENABLED=0.
Package sqlite is the SQLite adapter for both store.ManifestStore and store.OperationalStore, backed by modernc.org/sqlite (a pure-Go driver, no cgo).
Package sqlite is the SQLite adapter for both store.ManifestStore and store.OperationalStore, backed by modernc.org/sqlite (a pure-Go driver, no cgo).
Package vault implements store.ManifestStore over a directory tree: files are the source of truth.
Package vault implements store.ManifestStore over a directory tree: files are the source of truth.

Jump to

Keyboard shortcuts

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