core

package
v0.21.2 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 13 Imported by: 0

README

core

import "github.com/kitsunium/sdk/framework/model/internal/core"

Package core is the Product Graph under the names the role rule asks for: every struct carries its role (NodeEntity, GraphMessage, EndpointSpec, …). framework/model is its public face — an alias per type under the graph's own names (Node, Graph, EndpointInfo, …), its constants and its functions — and the one package a caller imports.

Index

Constants

const AccessAnyUser = "any-user"

AccessAnyUser is kit.AnyUser(): any signed-in user may run it — the operation asks for one.

const AccessAnyone = "anyone"

AccessAnyone is kit.Anyone(): whoever reaches the route may run the operation.

const AuthOptional = "optional"

AuthOptional endpoints run the auth handler when credentials are present, and serve anonymous callers too.

const AuthRequired = "required"

AuthRequired endpoints run only for an authenticated caller; the others are answered 401 before the handler runs.

const BinaryScope = "binary:"

BinaryScope prefixes the ID of a binary and of its roles.

const BlockCase = "case"

The kinds of CodeBlockMessage.

const BlockDefer = "defer"

The kinds of CodeBlockMessage.

const BlockElse = "else"

The kinds of CodeBlockMessage.

const BlockElseIf = "else-if"

The kinds of CodeBlockMessage.

const BlockFunc = "func"

The kinds of CodeBlockMessage.

const BlockGo = "go"

The kinds of CodeBlockMessage.

const BlockIf = "if"

The kinds of CodeBlockMessage.

const BlockLoop = "loop"

The kinds of CodeBlockMessage.

const BlockTransaction = "transaction"

BlockTransaction is the function a kit.Transact runs: its steps run in one transaction, and the effects they make leave at its commit.

const BootComponents = "components"

Boot steps, in the order kit takes them.

const BootConfig = "config"

Boot steps, in the order kit takes them.

const BootData = "data"

Boot steps, in the order kit takes them.

const BootDeclarations = "declarations"

Boot steps, in the order kit takes them.

const BootHandler = "handler"

Boot steps, in the order kit takes them.

const BootMount = "mount"

Boot steps, in the order kit takes them.

const BootRoutes = "routes"

Boot steps, in the order kit takes them.

const BootServing = "serving"

Boot steps, in the order kit takes them.

const ClassPersonal = "personal"

ClassPersonal holds data about an identifiable person: a name, an address, a message a person wrote.

const ClassPublic = "public"

ClassPublic holds nothing personal and nothing secret: the question was asked.

const ClassSecret = "secret"

ClassSecret holds a credential: a password's hash, a token's digest.

const ClassSpecial = "special"

ClassSpecial holds the special categories of GDPR art. 9(1), or criminal convictions (art. 10).

const CodeInvalidID errs.Code = 262401

CodeInvalidID identifies an ID the grammar of IDPattern does not match.

Code 0.4.1.1

const ComponentDown = "down"

Component states.

const ComponentFailed = "failed"

Component states.

const ComponentPending = "pending"

Component states.

const ComponentStarting = "starting"

Component states.

const ComponentStopping = "stopping"

Component states.

const ComponentUp = "up"

Component states.

const ConnectorData ConnectorKind = "data"

ConnectorData is where it keeps its data: stores, databases.

const ConnectorDatabase = "database"

ConnectorDatabase is brought by a store a database keeps (ADR 0004): kit.Database declares the database, an engine module reaches it.

const ConnectorHTTP = "http"

The connectors kit ships.

const ConnectorMail = "mail"

The connectors kit ships.

const ConnectorMessaging ConnectorKind = "messaging"

ConnectorMessaging is what it sends and receives: mail, queues.

const ConnectorQueue = "queue"

The connectors kit ships.

const ConnectorStore = "store"

The connectors kit ships.

const ConnectorTransport ConnectorKind = "transport"

ConnectorTransport is how the product is reached: HTTP.

const ContainerDatabase = "database"

ContainerDatabase is a database the app declares (kit.Database): "container:database:<name>", drawn as a cylinder.

const ContainerMemory = "memory"

Container kinds.

const ContainerProcess = "process"

Container kinds.

const ContainerSPA = "spa"

Container kinds.

const ContainerVolume = "volume"

Container kinds.

const ContractPattern = "[a-z][a-z0-9-]{0,62}/v[1-9][0-9]{0,3}"

ContractPattern is the versioned contract an EdgeContracts edge carries: "render/v1".

const DatabaseClosed = "closed"

DatabaseClosed: not opened yet, or closed by the stop.

const DatabaseFailed = "failed"

DatabaseFailed: the start could not open it, migrate it or reach it.

const DatabaseMemory = "memory"

DatabaseMemory: the app keeps its data in memory (kit.InMemory): nothing is opened, no URL is read.

const DatabaseOpen = "open"

DatabaseOpen: the pool is open, its migrations ran, it answered its check at start.

const DatabaseUnset = "unset"

DatabaseUnset: no URL, in dev. Its stores stay in the data directory and nothing is opened.

const EdgeAsks EdgeKind = "asks"

EdgeAsks targets a query: the source asks it. From an endpoint that exposes the query, or from a port bound to it, it is declared.

const EdgeCalls EdgeKind = "calls"

EdgeCalls targets an endpoint or a port. From a port, it is the port's binding — what the port calls — and it is declared.

const EdgeContracts EdgeKind = "contracts"

EdgeContracts goes from one process role to another it talks to — through a socket, a pipe, a command line —, and names the versioned contract they share in [EdgeMessage.Contract]. It is the only edge between two roles (D22). Declared.

const EdgeDelivers EdgeKind = "delivers"

EdgeDelivers goes from a topic to each of its subscriptions, and from a store to each watch it feeds (ADR 0008). Declared.

const EdgeDispatches EdgeKind = "dispatches"

EdgeDispatches targets a command: the source dispatches it. From an endpoint that exposes the command, or from a port bound to it, it is declared.

const EdgeImports EdgeKind = "imports"

EdgeImports goes from a component to a library it may import (D19). Declared.

const EdgePersists EdgeKind = "persists"

EdgePersists goes from a workflow to the store it lives in. Declared.

const EdgePublishes EdgeKind = "publishes"

EdgePublishes targets a topic.

const EdgeReads EdgeKind = "reads"

EdgeReads targets a store the source reads from.

const EdgeRenders EdgeKind = "renders"

EdgeRenders goes from a presentation to what it renders. Declared.

const EdgeRuns EdgeKind = "runs"

EdgeRuns goes from a role to what it runs: a CLI command, a listener, an endpoint's server, a loop. Declared.

const EdgeSends EdgeKind = "sends"

EdgeSends targets a mailer: the source puts a message in its outbox.

const EdgeTransitions EdgeKind = "transitions"

EdgeTransitions targets a workflow; Label carries the event.

const EdgeUses EdgeKind = "uses"

EdgeUses targets a secret whose value or keys the source uses.

const EdgeWakes EdgeKind = "wakes"

EdgeWakes goes from a topic to a declared loop it wakes. Declared.

const EdgeWrites EdgeKind = "writes"

EdgeWrites targets a store the source writes to.

const EngineMySQL = "mysql"

The engines a database runs on (ADR 0004): one module each in kit's repository, the only code that imports its driver.

const EnginePostgres = "postgres"

The engines a database runs on (ADR 0004): one module each in kit's repository, the only code that imports its driver.

const EngineSQLite = "sqlite"

The engines a database runs on (ADR 0004): one module each in kit's repository, the only code that imports its driver.

const EventCensus EventType = "census"

EventCensus reports a workflow's population per state.

const EventGraph EventType = "graph"

EventGraph reports that the graph structure changed.

const EventHello EventType = "hello"

EventHello opens every stream and carries the graph revision.

const EventLifecycle EventType = "lifecycle"

EventLifecycle reports a lifecycle component moving, or the process changing phase.

const EventLog EventType = "log"

EventLog reports a log record written by product code, in dev.

const EventLoop EventType = "loop"

EventLoop reports a loop run.

const EventMail EventType = "mail"

EventMail reports a mail entering the outbox or changing status.

const EventSpan EventType = "span"

EventSpan reports one unit of work that finished on a node.

const EventTransition EventType = "transition"

EventTransition reports a workflow instance changing state.

const ExposePrivate = "private"

ExposePrivate endpoints have no route: the implementation of a port (Service.Implement), reached in process through its port. A graph kit made before its operations were internal by default also marks so an endpoint it kept off the listener.

const ExposePublic = "public"

ExposePublic endpoints are routed on the product's HTTP listener.

const ExternalID = "external"

ExternalID is the id of the node standing for the outside world.

const GapPurpose = "purpose"

The gaps a register lists for a store that keeps personal data.

const GapRetention = "retention"

The gaps a register lists for a store that keeps personal data.

const GapSubject = "subject"

The gaps a register lists for a store that keeps personal data.

const JournalDelete = "delete"

The operations of the privacy journal.

const JournalErase = "erase"

The operations of the privacy journal.

const JournalEraseFields = "erase-fields"

The operations of the privacy journal.

const JournalExport = "export"

The operations of the privacy journal.

const JournalHold = "hold"

The operations of the privacy journal.

const JournalRead = "read"

The operations of the privacy journal.

const JournalRelease = "release"

The operations of the privacy journal.

const JournalShred = "shred"

The operations of the privacy journal.

const KindAuth NodeKind = "auth"

KindAuth is the app's authentication handler: it turns a request's credentials into a user, in front of every endpoint that asks for one.

const KindBinary NodeKind = "binary"

KindBinary is one executable the product ships. It holds process roles; its ID is "binary:<name>".

const KindCLI NodeKind = "cli"

KindCLI is a short command-line command: it parses its arguments, runs once and exits with a typed status.

const KindCommand NodeKind = "command"

KindCommand is an operation that changes something: a typed input, a typed result, one handler, the pipeline of its kind. It is dispatched, on its caller's goroutine or through its own queue.

const KindEndpoint NodeKind = "endpoint"

KindEndpoint is an HTTP endpoint with typed request and response.

const KindExternal NodeKind = "external"

KindExternal stands for everything outside the product.

const KindFrontend NodeKind = "frontend"

KindFrontend is static assets served by the product.

const KindJob NodeKind = "job"

KindJob is scheduled work: a fixed interval or a cron expression.

const KindLibrary NodeKind = "library"

KindLibrary is a package shared between components, declared so the components that use it are allowed to import it. Its ID is "library:<name>".

const KindListener NodeKind = "listener"

KindListener accepts connections that are not HTTP: a private Unix socket, a named pipe. It is an inbound port like an endpoint.

const KindLoop NodeKind = "loop"

KindLoop is a long-running loop of the daemon: declared (kit owns the wait, the product the work) or hand-written (a goroutine kit supervises).

const KindMailer NodeKind = "mailer"

KindMailer is outbound mail: a durable outbox, and the transport that empties it — SMTP, or the capture of dev and tests.

const KindPort NodeKind = "port"

KindPort is an operation a service needs and does not implement: a typed request, a typed response, a name. What it calls — another service's endpoint, the app's binding, its own fallback — is decided when the app starts, and drawn as a declared edge from the port.

const KindPresentation NodeKind = "presentation"

KindPresentation turns a service's results into what a reader sees: a rendered line, a page, a report.

const KindQuery NodeKind = "query"

KindQuery is an operation that reads and changes nothing: a typed input, a typed result, one handler. It is asked.

const KindRole NodeKind = "role"

KindRole is one process role of a binary — "statusline" and "statusline daemon" are two roles of one binary. Its root package is generated wiring; two roles talk through their contract only. Its ID is "binary:<binary>/role/<name>".

const KindSecret NodeKind = "secret"

KindSecret is a secret the product declares: provided by the operator, or generated by kit and rotated on a schedule. Its value is never in a graph.

const KindService NodeKind = "service"

KindService groups the nodes of one bounded context.

const KindStore NodeKind = "store"

KindStore is a typed, keyed collection of entities.

const KindSubscription NodeKind = "subscription"

KindSubscription consumes one topic.

const KindTopic NodeKind = "topic"

KindTopic is an asynchronous, at-least-once message channel.

const KindWorkflow NodeKind = "workflow"

KindWorkflow is a state machine over the entities of one store.

const LibraryScope = "library:"

LibraryScope prefixes the ID of a library.

const LoopConsumer = "consumer"

Loop kinds.

const LoopDeclared = "declared"

LoopDeclared is Service.Loop: kit owns the wait — the wake sources are data, so the diagram draws them — and the product owns the work.

const LoopGoroutine = "goroutine"

LoopGoroutine is Service.Go: the product wrote the whole loop; kit starts it, stops it, restarts it after a failure, and reads its select statements to draw what it waits on.

const LoopHTTP = "http"

Loop kinds.

const LoopJob = "job"

Loop kinds.

const LoopRestarting = "restarting"

Loop states.

const LoopRetention = "retention"

Loop kinds.

const LoopRotation = "rotation"

Loop kinds.

const LoopRoutine = "goroutine"

Loop kinds.

const LoopRunning = "running"

Loop states.

const LoopScheduler = "scheduler"

Loop kinds.

const LoopStopped = "stopped"

Loop states.

const LoopTimer = "timer"

Loop kinds.

const LoopWaiting = "waiting"

Loop states.

const LoopWake = "wake"

Loop kinds.

const MailDead = "dead"

Mail statuses.

const MailQueued = "queued"

Mail statuses.

const MailRetrying = "retrying"

Mail statuses.

const MailSent = "sent"

Mail statuses.

const MaxTableLen int = 58

MaxTableLen is the longest table name a store on a database takes, in bytes: the SDK's document store over SQL keeps its index rows in the table named after it with "___ix", within PostgreSQL's 63.

const MeasureHolds = "legal-holds"

MeasureHolds: a legal hold stops erasure and deletion.

const MeasureJournal = "journal"

MeasureJournal: every export, erasure, deletion and hold is journaled, each entry chained to the previous one by SHA-256.

const MeasureNotSealed = "not-sealed"

MeasureNotSealed: the store's classified members are in clear: it is kept in memory, where nothing is at rest, or its members are plain.

const MeasureRedacted = "redacted"

MeasureRedacted: the Studio, the spans and the logs never show a personal, special or secret value.

const MeasureSealed = "sealed"

MeasureSealed: its classified members are sealed at rest, AES-256-GCM under per-subject data keys a person's erasure destroys (ADR 0006 §4).

const MockReplace = "replace"

MockReplace is the one mode a MockMessage has: a test's kit.Replace, a typed function run in place of an operation's handler — or of what a port calls — while the rest of its pipeline still runs. The Studio sets none (D13): it shows the application, it does not act on it, so the respond, fail and delay modes of the platform's kit have no representation here.

const ModeQueued = "queued"

ModeQueued is sent to the background (kit.Queued): Dispatch returns once the command's own queue accepted it, and a consumer handles it, retried and dead-lettered.

const ModeSync = "sync"

ModeSync is handled on its caller's goroutine: Dispatch returns the handler's result.

const NamePattern = "[A-Za-z][A-Za-z0-9_.-]{0,62}"

NamePattern is a node's name within its service and kind.

const NetworkLocal = "local"

NetworkLocal is NetworkUnix where there is one, NetworkPipe on Windows: what a product declares when it does not care which.

const NetworkPipe = "pipe"

NetworkPipe is a Windows named pipe, its DACL granting its owner only.

const NetworkUnix = "unix"

NetworkUnix is a Unix-domain socket, private to its owner.

const OpAsk = "ask"

Span operations.

const OpAuth = "auth"

Span operations.

const OpCLI = "cli"

Span operations.

const OpCall = "call"

Span operations.

const OpConnect = "connect"

Span operations.

const OpDeliver = "deliver"

Span operations.

const OpDeliverMail = "deliver-mail"

Span operations.

const OpDispatch = "dispatch"

Span operations.

const OpHandle = "handle"

Span operations.

const OpPublish = "publish"

Span operations.

const OpRead = "read"

Span operations.

const OpRequest = "request"

Span operations.

const OpRun = "run"

Span operations.

const OpSecret = "secret"

Span operations.

const OpSend = "send"

Span operations.

const OpTransaction = "transaction"

OpTransaction is a unit of work (kit.Transact, a command's, a workflow's transition): its attrs say the database it belongs to — "database", and "backend" as a store says it —, its "outcome", the effects it held ("effects"), and "savepoint" for one nested in another.

const OpTransition = "transition"

Span operations.

const OpWrite = "write"

Span operations.

const OutcomeCommit = "commit"

OutcomeCommit is a transaction that committed: its effects left.

const OutcomeRollback = "rollback"

OutcomeRollback is a transaction whose writes were undone: its effects were dropped.

const PhaseDraining = "draining"

Process phases, in the order a process goes through them.

const PhaseFailed = "failed"

Process phases, in the order a process goes through them.

const PhaseServing = "serving"

Process phases, in the order a process goes through them.

const PhaseStarting = "starting"

Process phases, in the order a process goes through them.

const PhaseStopped = "stopped"

Process phases, in the order a process goes through them.

const PortOwnerKit = "kit"

PortOwnerKit is kit's own listener: the health probes, the Studio in dev, and the product's HTTP when it declares any.

const ProfileCLI = "cli"

ProfileCLI parses its arguments, runs once and exits with a typed status. It starts no listener and no loop outlives it.

const ProfileCPU = "cpu"

Profile kinds.

const ProfileDaemon = "daemon"

ProfileDaemon runs until it is stopped, or until it has been idle for its declared time, and serves no HTTP: it answers on its listeners — a private socket, a pipe — and runs its loops.

const ProfileHeap = "heap"

Profile kinds.

const ProfileServer = "server"

ProfileServer serves HTTP until it is stopped: the platform's kit product, and the only profile that opens a TCP listener.

const ProvenanceKit = "kit"

ProvenanceKit loops are written by kit for a declaration: a workflow's sweep, a declared loop's wake cycle.

const ProvenanceLibrary = "library"

ProvenanceLibrary loops are written by a library: net/http's accept loop, the SDK scheduler, the SDK queue consumer.

const ProvenanceProduct = "product"

ProvenanceProduct loops are written by hand in the product: Service.Go.

const RetentionDryRun = "dry-run"

RetentionDryRun journals what the retention would do and changes nothing: how a new retention is deployed over old data.

const RetentionOff = "off"

RetentionOff runs no retention, warned of at every start outside dev.

const RetentionOn = "on"

RetentionOn erases and deletes what is due: the default.

const RoleInbound = "inbound"

The roles of a connector, against the process boundary.

const RoleOutbound = "outbound"

The roles of a connector, against the process boundary.

const RoleStorage = "storage"

The roles of a connector, against the process boundary.

const RoutePattern = "[A-Z]+ /[^\\s]*"

RoutePattern is the name of an endpoint declared without one: its route, "GET /tasks/{id}".

const SealedPlaceholder = "[sealed]"

SealedPlaceholder is what the Studio receives in place of a value kit keeps sealed at rest — a record's member in the data browser, a former value —: never the value, nor its box (ADR 0006 §9). A value it opens and may not show is "[redacted]".

const SecretFromEnv = "env"

SecretFromEnv is the environment: the variable, or the file its _FILE form names.

const SecretFromFile = "file"

SecretFromFile is kit's encrypted file store: KIT_SECRETS=file:<dir>, or .kit/secrets/dev in dev.

const SecretFromMemory = "memory"

SecretFromMemory is a store in the process's memory: a test, or KIT_SECRETS=memory. A generated secret is made again at every start.

const SecretFromStore = "store"

SecretFromStore is a store the product's code gave kit.

const SecretGenerated = "generated"

SecretGenerated is made by kit and rotated on a schedule: a signing or sealing key.

const SecretProvided = "provided"

SecretProvided is given by the operator: an SMTP URL, an API token.

const SegmentPattern = "[a-z][a-z0-9-]{0,62}"

SegmentPattern is a service, module, binary, role or library name.

const SelectDefault = "default"

Select case kinds.

const SelectDone = "done"

Select case kinds.

const SelectReceive = "receive"

Select case kinds.

const SelectSend = "send"

Select case kinds.

const SelectTimer = "timer"

Select case kinds.

const ServesHTTP = "http"

What a port serves.

const ServesHealth = "health"

What a port serves.

const ServesStudio = "studio"

What a port serves.

const SettingDefault = "default"

Where a setting's value comes from.

const SettingEnv = "env"

Where a setting's value comes from.

const SettingFile = "file"

Where a setting's value comes from.

const SettingKitDev = "kitdev"

Where a setting's value comes from.

const SettingOption = "option"

Where a setting's value comes from.

const SettingStore = "store"

Where a setting's value comes from.

const StatusError = "error"

Span statuses.

const StatusOK = "ok"

Span statuses.

const TransportCapture = "capture"

TransportCapture keeps every message for the Studio's mailbox and delivers nothing: the transport of dev and tests.

const TransportSMTP = "smtp"

TransportSMTP delivers to an SMTP relay.

const TriggerCreate = "create"

TriggerCreate is the entry of a new instance into the initial state.

const TriggerEvent = "event"

TriggerEvent is a transition fired by code, naming an event.

const TriggerGuard = "guard"

TriggerGuard is a transition fired when a condition on the entity holds, checked each time the entity is written.

const TriggerTimer = "timer"

TriggerTimer is a transition fired after a duration in a state, or at an instant the entity carries.

const VarAddr = "KIT_ADDR"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarAllowedHosts = "KIT_ALLOWED_HOSTS"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarAnalyze = "KIT_ANALYZE"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarDataDir = "KIT_DATA_DIR"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarDevForced = "KIT_DEV_FORCED"

VarDevForced is how kit dev tells the product which of the variables above it set itself for this launch: their origin is kit dev.

const VarEnv = "KIT_ENV"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarLogLevel = "KIT_LOG_LEVEL"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarRetention = "KIT_RETENTION"

VarRetention sets what the stores' retention loops do: on, dry-run or off (ADR 0006).

const VarSMTPURL = "KIT_SMTP_URL"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarStudio = "KIT_STUDIO"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarStudioRemote = "KIT_STUDIO_REMOTE"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const VarTrustProxy = "KIT_TRUST_PROXY"

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

const Version int = 5

Version is the schema version of every document in this package.

Version 2 adds the auth, mailer and loop kinds, the sends and wakes edges, the code level of every node (CodeResult), the C4 context and containers (ArchitectureMessage) and the daemon's own machinery (RuntimeMessage).

Version 3 adds the secret kind (SecretSpec), the uses edge, the secret span operation, the rotation loop and the store origin of a setting.

Version 4 is the one bump the decisions of issue #17 share. It adds the port kind (PortSpec) and its binding, a declared edge from the port to what it calls; the endpoint that implements a port ([EndpointSpec.Implements]), which has no method and no path; and the replace mock mode (MockReplace). ADR 0004 adds the databases: the store's database ([StoreSpec.Database]), the database container, the database connector and its adapters, [RuntimeMessage.Databases] and [SettingMessage.Database]. ADR 0008 adds the modules the app mounts ([GraphMessage.Modules]), the module of a node ([NodeEntity.Module]) and the Go module of a position outside the product's ([SourceMessage.GoModule]); and the watch, a subscription fed by stores: its mark and the stores that feed it ([SubscriptionSpec.Mark], [SubscriptionSpec.Stores]), each drawing a declared delivers edge to it. ADR 0005 adds the command and query kinds (CommandSpec, QuerySpec), the dispatches and asks edges, the endpoint that exposes one ([EndpointSpec.Exposes]), the read model ([StoreSpec.ReadModel]), the dispatch, ask and handle span operations and the dispatch and ask controls.

Version 5 is the first the SDK's framework publishes (ADR 0147). It adds what a product is made of beyond its services: the binary (KindBinary) and its process roles (KindRole), the short CLI command (KindCLI), the listener that is not HTTP (KindListener), the library shared between components (KindLibrary) and the presentation (KindPresentation); the edge between two roles of a product, which carries a versioned contract (EdgeContracts, [EdgeMessage.Contract]); and the grammar every ID follows, written once (IDValue, ParseID). It removes what the Studio no longer does (D13): the respond, fail and delay mock modes, the control event and its payload — a MockMessage is a test's replacement only.

const ViaBind = "bind"

ViaBind is the app's kit.Bind.

const ViaFallback = "fallback"

ViaFallback is the port's own kit.Fallback.

const ViaImplement = "implement"

ViaImplement is the one Service.Implement among the mounted services.

const ViaReplace = "replace"

ViaReplace is a test's kit.Replace: a function answers in place of whatever the port would call, and nothing is bound.

const WakeChange = "change"

Wake source kinds of a declared loop, and why a loop of kit's ran.

const WakeDeadline = "deadline"

Wake source kinds of a declared loop, and why a loop of kit's ran.

const WakeInterval = "interval"

Wake source kinds of a declared loop, and why a loop of kit's ran.

const WakeManual = "manual"

Wake source kinds of a declared loop, and why a loop of kit's ran.

const WakeStart = "start"

Wake source kinds of a declared loop, and why a loop of kit's ran.

const WakeTopic = "topic"

Wake source kinds of a declared loop, and why a loop of kit's ran.

Variables

var IDPattern string

IDPattern is the whole grammar as one regular expression, anchored — the one the design files' JSON Schema publishes for an ID. Only an endpoint may be named by its route.

var InvalidID *errs.Error

InvalidID is returned by ParseID for a string the ID grammar does not match. Its "part" field names what failed — the kind, the service name, the node name —, never the input.

Code 0.4.1.1 · reason INVALID_ID · public "The node identifier is not valid"

func BinaryID

func BinaryID(binary string) string

BinaryID is the ID of a binary.

func CompareSource

func CompareSource(a SourceMessage, b SourceMessage) int

CompareSource orders sources by root, file, then line.

func ConnectorCatalog

func ConnectorCatalog() []ConnectorSpec

ConnectorCatalog is every connector kit ships, sorted by ID: what a product may plug into.

func ConnectorsOf

func ConnectorsOf(nodes []NodeEntity) []ConnectorMessage

ConnectorsOf derives the connectors a product uses from its nodes: an endpoint, a frontend or an auth handler means HTTP, a mailer mail, a store stores — and a database when one keeps it —, a topic, a subscription or a queued command queues. Sorted by ID.

func EdgeID

func EdgeID(from string, kind EdgeKind, to string, label string) string

EdgeID builds the ID of an edge. The label is part of the identity: two transitions of one workflow fired from one endpoint are two edges.

func IsEngine

func IsEngine(backend string) bool

IsEngine reports whether backend names an engine a database runs on.

func LibraryID

func LibraryID(library string) string

LibraryID is the ID of a library.

func Merge

func Merge(base *GraphMessage, extra *GraphMessage) *GraphMessage

Merge enriches a graph with what another description of the same product knows. base is authoritative on which nodes exist — a runtime graph describes what the process actually serves —, on the modules it mounts, on what each of its ports calls and on which stores feed each of its watches: the app chose them when it started, where the analysis only reads the same rules over the whole module. extra, typically the static analysis, contributes documentation, handler ranges — an authorization function's too —, transition callers and the edges it found. Nodes only extra knows about are dropped: code that is compiled but not mounted in this app is not part of this product — save a node of a module's service the base mounts, which a package the binary does not link declares: a warning says so.

func Mermaid

func Mermaid(g *GraphMessage) string

Mermaid renders the architecture of a graph as a Mermaid flowchart: one subgraph per service — a module's inside the module's own, ADR 0008 —, one arrow per edge. GitHub renders it in Markdown, which makes a product's README carry its own, always regenerable, diagram.

Each kind has its shape: an endpoint a box (marked "auth" when it asks for a user; an implementation of a port by its name), a store a cylinder, a topic a flag, a subscription a parallelogram (a watch, ADR 0008, marked with the mark it watches — its stores' arrows say where from), a workflow a hexagon, a job a stadium, the auth handler a trapezoid — a gate —, a mailer a subroutine box, a declared loop a circle, a hand-written loop a double circle, a port an inverted trapezoid — a socket, UML's required interface —, a command a parallelogram leaning back — a subscription's leans forward —, marked "queued" when it waits in its queue, and a query a rhombus, a question. An arrow is solid when it exists by construction or was observed, dotted when only the code says so — or when it is a port's binding to its own fallback, the default the app may replace, as the Studio draws it.

func ModulePrefix

func ModulePrefix(name string) string

ModulePrefix is a module's default mount prefix: "/<name>/".

func NodeID

func NodeID(service string, kind NodeKind, name string) string

NodeID builds the ID of a node declared in a service. A service's own ID is its name.

func ParseID

func ParseID(s string) (IDValue, error)

ParseID reads an ID. It refuses anything IDPattern does not match, with InvalidID; the refusal never quotes the input, which may be anything a caller sent.

func QualifiedService

func QualifiedService(module string, service string) string

QualifiedService is the name a module gives a service it lists: the module's own name for the service named like it, "<module>.<service>" otherwise. The runtime and the analyzer both qualify with it.

func RoleID

func RoleID(binary string, role string) string

RoleID is the ID of one process role of a binary.

func ServiceOf

func ServiceOf(id string) string

ServiceOf returns the service part of a node ID.

func SplitDoc

func SplitDoc(text string) (string, map[string]string)

SplitDoc splits a description into its default text and its translations.

A product documents a building block once, in Go, in its default language; a paragraph that starts with a language tag and a colon — "fr: Le cycle de vie d'un compte…" — is the same description in that language, until the next tag or the end:

// AccountLifecycle is the life of an account…
//
// fr: AccountLifecycle est la vie d'un compte…

It keeps Go's convention (the comment still starts with the name) and go doc prints both. Each text is joined into one line. A description whose only tagged paragraph is "en" uses it as the default.

func TableName

func TableName(service string, node string, suffix string) string

TableName is the table a database keeps a kit table in (ADR 0004): the service's name — qualified, for a module's —, two underscores and the node's name, then suffix, '-' and '.' written '_', lower case — "moderation.intake"'s store "cases" is moderation_intake__cases. A name the rule cannot keep as it is — upper case, longer than MaxTableLen, three underscores in a row, SQLite's own prefix — is cut and ends with a digest of the whole, so it stays one table's. The runtime and the analyzer name tables with it.

func UnderPrefix

func UnderPrefix(prefix string, path string) string

UnderPrefix is a route declared at path, served under a module's mount prefix: "/reports" under "/moderation/" is "/moderation/reports", and under "/" it stays "/reports".

func ValidContract

func ValidContract(s string) bool

ValidContract reports whether s names a versioned contract: "render/v1".

func ValidName

func ValidName(s string) bool

ValidName reports whether s is a legal node name. An endpoint named by its route is legal as an ID but is not a name a declaration may give.

func ValidSegment

func ValidSegment(s string) bool

ValidSegment reports whether s is a legal service, module, binary, role or library name.

type AdapterMessage

AdapterMessage is a module a connector plugs a product in through: an engine, imported by the product's main to reach a database, and the only code of the product that imports its driver.

type AdapterMessage struct {
	// ID names it as the graph does: "postgres".
	ID     string `json:"id"`
	// Name is what a reader calls what it reaches: "PostgreSQL".
	Name   string `json:"name"`
	// Import is the package the product's main imports:
	// "github.com/kitsunium/sdk/framework/connectors/postgres".
	Import string `json:"import"`
	// Driver is the Go driver it links: "github.com/jackc/pgx/v5".
	Driver string `json:"driver,omitempty"`
}

type AnalysisResult

AnalysisResult reports the status of static analysis. It says whether the analyzer ran, how long it took, and the error that stopped it.

type AnalysisResult struct {
	// Status is "pending", "running", "ok", "failed" or "unavailable".
	Status   string     `json:"status"`
	// Error explains a failed or unavailable analysis.
	Error    string     `json:"error,omitempty"`
	// At is when the analysis finished.
	At       *time.Time `json:"at,omitempty"`
	// Packages is how many packages were analyzed.
	Packages int        `json:"packages,omitempty"`
	// TookMs is how long it took.
	TookMs   float64    `json:"tookMs,omitempty"`
}

type AppMessage

AppMessage identifies the product and the machine that described it. It names the module, the environment and the build the graph was taken from.

type AppMessage struct {
	// Name is the product name given to kit.NewApp.
	Name      string        `json:"name"`
	// Module is the Go module path of the product.
	Module    string        `json:"module,omitempty"`
	// Root is the absolute module root on the machine that produced the
	// graph. Present in dev only: it is what an editor link needs, and what a
	// production graph must not leak.
	Root      string        `json:"root,omitempty"`
	// Env is "dev" or "production".
	Env       string        `json:"env,omitempty"`
	// Kit is the kit version that produced the graph.
	Kit       string        `json:"kit,omitempty"`
	// Go is the Go version the product was built with.
	Go        string        `json:"go,omitempty"`
	// StartedAt is when the process started, for a runtime graph.
	StartedAt *time.Time    `json:"startedAt,omitempty"`
	// Build says what the binary was built from: the product, kit and the
	// SDK kit depends on.
	Build     *BuildMessage `json:"build,omitempty"`
}

type ArchitectureMessage

ArchitectureMessage is the product at the two outer levels of the C4 model.

Context (level 1) is the product as one box, the people who use it and the systems it depends on. Containers (level 2) is what the product is deployed as: the process, the frontend its browser runs, the volume its data lives on. Components (level 3) are the nodes, grouped by service; code (level 4) is each node's CodeResult.

kit derives all of it from the declarations — a frontend implies a person with a browser, a mailer an SMTP relay, a data directory a volume, a database its own container — so it is exactly as true as the rest of the graph.

type ArchitectureMessage struct {
	// People are the humans the product serves.
	People     []PersonMessage    `json:"people"`
	// Systems are the software systems outside the product it talks to, or
	// that talk to it.
	Systems    []SystemMessage    `json:"systems"`
	// Containers are the product's runnable and storage units.
	Containers []ContainerMessage `json:"containers"`
	// Links are the relationships between people, systems and containers.
	Links      []LinkMessage      `json:"links"`
}

type AuthSpec

AuthSpec describes the app's authentication handler. Credentials says what it reads from a request; Endpoints are the ones behind it.

type AuthSpec struct {
	// Credentials is the type the handler reads: its fields are tagged
	// cookie:"…" or header:"…".
	Credentials *SchemaMessage `json:"credentials,omitempty"`
	// Data is the type of what the handler says about the caller, which
	// endpoints read with kit.AuthData.
	Data        *SchemaMessage `json:"data,omitempty"`
	// Endpoints counts the endpoints that ask for authentication.
	Endpoints   int            `json:"endpoints"`
}

type BinarySpec

BinarySpec is one executable the product ships: the [NodeEntity.Binary] of a KindBinary node, naming its roles.

type BinarySpec struct {
	// Package is the Go package of its main.
	Package string   `json:"package,omitempty"`
	// Roles are the IDs of its process roles, in declaration order; the
	// first is the one it runs with no role argument.
	Roles   []string `json:"roles"`
}

type BootStepMessage

BootStepMessage is one step of the start, as it ran. It carries when it began, how long it took and, when it failed, its error.

type BootStepMessage struct {
	// Name is one of the Boot constants.
	Name   string    `json:"name"`
	// Count is how many it went through: settings, warnings, services,
	// routes, components.
	Count  int       `json:"count,omitempty"`
	// Value is what it used: the data directory, in dev.
	Value  string    `json:"value,omitempty"`
	// Begun is when it began.
	Begun  time.Time `json:"begun"`
	// TookMs is how long it took.
	TookMs float64   `json:"tookMs"`
	// Error is the public message of a failure.
	Error  string    `json:"error,omitempty"`
}

type BuildMessage

BuildMessage is what a binary was built from, at its three levels. Its three levels are the Go toolchain, the main module and the modules it depends on.

type BuildMessage struct {
	// Product is the product's own module.
	Product ModuleVersionMessage `json:"product"`
	// Kit is the framework: since ADR 0162 the SDK module,
	// github.com/kitsunium/sdk, which holds it.
	Kit     ModuleVersionMessage `json:"kit"`
	// SDK is the SDK the framework is built on — the same module as Kit
	// since ADR 0162, so the two say the same version.
	SDK     ModuleVersionMessage `json:"sdk"`
}

type CLISpec

CLISpec is a short command-line command: the [NodeEntity.CLI] of a KindCLI node, the words that run it.

type CLISpec struct {
	// Path is the command's words after the binary's name: ["status"],
	// ["daemon", "stop"].
	Path []string `json:"path"`
	// Role is the ID of the role that runs it.
	Role string   `json:"role,omitempty"`
}

type CensusMessage

CensusMessage is a workflow's population per state. It counts the instances in each state when the census was taken.

type CensusMessage struct {
	// Workflow is the workflow node ID.
	Workflow string         `json:"workflow"`
	// Counts maps each state to its number of instances.
	Counts   map[string]int `json:"counts"`
}

type CodeBlockMessage

CodeBlockMessage is a block of a function that decides whether, or how many times, the steps under it run.

type CodeBlockMessage struct {
	// Kind is one of the Block constants.
	Kind   string `json:"kind"`
	// Label is the condition or the clause, as written: "err != nil",
	// `case "done"`, "range ids"; bounded.
	Label  string `json:"label,omitempty"`
	// Line is the 1-based line where the block starts.
	Line   int    `json:"line"`
	// Group is the line of the statement the block is a branch of: an
	// if/else chain, a switch, a select. Blocks with one group are its
	// alternatives.
	Group  int    `json:"group,omitempty"`
	// Parent is the enclosing block: its index in Blocks, plus one; 0 for
	// the function's body.
	Parent int    `json:"parent,omitempty"`
}

type CodeEffectMessage

CodeEffectMessage is one call on a building block, inside a function. It names the node it reaches and the edge kind that call draws.

type CodeEffectMessage struct {
	// Kind is the edge the call makes: reads, writes, publishes…
	Kind   EdgeKind `json:"kind"`
	// Target is the node the call reaches.
	Target string   `json:"target"`
	// Label refines Kind like an edge's label: the event of a transition.
	Label  string   `json:"label,omitempty"`
	// Op is the method called: "Get", "Insert", "Fire", "Send".
	Op     string   `json:"op"`
	// Line is the 1-based line of the call, in the function's file.
	Line   int      `json:"line"`
}

type CodeFuncMessage

CodeFuncMessage is one function of the module a node's code reaches. Its steps are listed in the order they run, under the blocks that guard them.

type CodeFuncMessage struct {
	// Func is the qualified name: "github.com/kitsunium/todo/tasks.Create".
	Func    string              `json:"func"`
	// Name is the short name a developer reads: "Create", "(*Store).visible".
	Name    string              `json:"name"`
	// Source is the function's range.
	Source  *SourceMessage      `json:"source,omitempty"`
	// Calls are the qualified names of the module functions it calls, in
	// source order, deduplicated.
	Calls   []string            `json:"calls,omitempty"`
	// Effects are its calls on building blocks, in source order.
	Effects []CodeEffectMessage `json:"effects,omitempty"`
	// Steps are what it does, in the order it does it: its calls to module
	// functions, on building blocks and into the SDK, arguments before the
	// call they are passed to. A sequence diagram is drawn from them.
	Steps   []CodeStepMessage   `json:"steps,omitempty"`
	// Blocks are its blocks that decide whether, or how many times, the
	// steps under them run: an if's branches, a switch's cases, a loop.
	Blocks  []CodeBlockMessage  `json:"blocks,omitempty"`
}

type CodeResult

CodeResult is the code a node runs, as the static analysis read it: the fourth and innermost level of the C4 model. The entry is the function the node runs — an endpoint's handler, a subscription's, a loop's — and Funcs are the functions of the module it reaches, each with what it calls and what it does to other nodes.

type CodeResult struct {
	// Entry is the qualified name of the function the node runs first.
	Entry     string            `json:"entry,omitempty"`
	// Funcs are the module's functions reachable from the entry, entry
	// first, then in the order the walk met them.
	Funcs     []CodeFuncMessage `json:"funcs,omitempty"`
	// Uses are the SDK functions the code calls: the mechanics it composes
	// rather than implements.
	Uses      []CodeUseMessage  `json:"uses,omitempty"`
	// Truncated is set when the walk stopped at its depth or size bound.
	Truncated bool              `json:"truncated,omitempty"`
}

type CodeStepMessage

CodeStepMessage is one thing a function does: a call to another function of the module, a call on a building block, or a call into the SDK — under the innermost block that guards it.

type CodeStepMessage struct {
	// Line is the 1-based line of the call, in the function's file.
	Line   int    `json:"line"`
	// Call is the qualified name of the module function it calls.
	Call   string `json:"call,omitempty"`
	// Effect is its call on a building block: the index in Effects, plus one.
	Effect int    `json:"effect,omitempty"`
	// Use is the SDK function it calls, from the SDK's version directory:
	// "crypto/password.Hash".
	Use    string `json:"use,omitempty"`
	// Block is the innermost block guarding it: the index in Blocks, plus
	// one; 0 for the function's body.
	Block  int    `json:"block,omitempty"`
}

type CodeUseMessage

CodeUseMessage is one SDK function a node's code calls. Sites are where the node's code calls it, so a reader sees what it leans on.

type CodeUseMessage struct {
	// Package is the SDK package: "github.com/kitsunium/sdk/pkg/v1/crypto/password".
	Package string          `json:"package"`
	// Func is the function or method: "Hash", "(*Composer).Compose".
	Func    string          `json:"func"`
	// Sites are the call sites, sorted.
	Sites   []SourceMessage `json:"sites,omitempty"`
}

type CommandSpec

CommandSpec describes a command: an operation that changes something. It carries its input and result schemas, its handler, its queue and who may dispatch it.

type CommandSpec struct {
	// Input is the type it is dispatched with.
	Input         *SchemaMessage      `json:"input,omitempty"`
	// Result is the type it answers; Empty for a queued command.
	Result        *SchemaMessage      `json:"result,omitempty"`
	// Mode is [ModeSync] or [ModeQueued].
	Mode          string              `json:"mode"`
	// Auth is [AuthRequired] — implied by a permission —, [AuthOptional],
	// or empty when the command ignores authentication.
	Auth          string              `json:"auth,omitempty"`
	// Pipeline lists the mechanics a dispatch goes through before the
	// handler, in the order they run.
	Pipeline      []MechanicMessage   `json:"pipeline,omitempty"`
	// Permissions are the permissions a caller needs (Allow).
	Permissions   []PermissionMessage `json:"permissions,omitempty"`
	// Authorize locates the function of its Authorize: a rule that needs
	// the data.
	Authorize     *SourceMessage      `json:"authorize,omitempty"`
	// Key is set when the command names the entity it is about (Key): two
	// runs with one key never overlap.
	Key           bool                `json:"key,omitempty"`
	// MaxDeliveries is how many attempts a queued command gets before it is
	// dead-lettered.
	MaxDeliveries int                 `json:"maxDeliveries,omitempty"`
	// Parallelism is how many dispatches of a queued command are handled at
	// once.
	Parallelism   int                 `json:"parallelism,omitempty"`
	// Queue is "memory" or "file": where a queued command waits.
	Queue         string              `json:"queue,omitempty"`
	// DeadLetters is how many dispatches of a queued command were
	// abandoned, on a runtime graph.
	DeadLetters   *int                `json:"deadLetters,omitempty"`
}

type ComponentMessage

ComponentMessage is one lifecycle component: brought up in order, taken down in reverse.

type ComponentMessage struct {
	// Name is the lifecycle name: "store:todos/store/todos", "http"…
	Name   string     `json:"name"`
	// Node is the node the component belongs to, when there is one.
	Node   string     `json:"node,omitempty"`
	// State is one of the Component constants.
	State  string     `json:"state"`
	// Begun is when the last start or stop call began.
	Begun  *time.Time `json:"begun,omitempty"`
	// TookMs is how long that call took.
	TookMs float64    `json:"tookMs,omitempty"`
	// Error is the public message of a failure.
	Error  string     `json:"error,omitempty"`
}

type ConnectorKind

ConnectorKind groups connectors by what they are for.

type ConnectorKind string

type ConnectorMessage

ConnectorMessage is something a product plugs into, as the product declares it: how it is reached, what it reaches out to, where it keeps its data. The Studio shows a connector's pages and widgets only when the product has one: a command-line tool has no requests to list, a service without a mailer no mailbox.

A connector says what the code declares, never what an environment supplies. The relay a mailer delivers through, the directory a store writes to, the address kit listens on are facts of the running environment — MailerSpec, StoreSpec, the ArchitectureMessage and RuntimeMessage carry those. So a connector is a pure function of the nodes (ConnectorsOf), and never moves a graph's revision.

type ConnectorMessage struct {
	// ID names the connector: [ConnectorHTTP], [ConnectorMail],
	// [ConnectorStore], [ConnectorQueue], [ConnectorDatabase].
	ID       string        `json:"id"`
	// Kind groups connectors by what they are for; kept for older readers,
	// Roles says more.
	Kind     ConnectorKind `json:"kind"`
	// Roles place it against the process boundary: [RoleInbound] (the
	// product is reached through it), [RoleOutbound] (the product reaches out
	// through it), [RoleStorage] (the product keeps data in it). kit's
	// built-in queues run inside the process: storage only.
	Roles    []string      `json:"roles,omitempty"`
	// Protocol is the wire protocol the code fixes, when it does: "http".
	Protocol string        `json:"protocol,omitempty"`
	// Detail is what the product uses, in kit's words: the stores'
	// backends, the mail transport, the queues' brokers.
	Detail   string        `json:"detail,omitempty"`
	// Settings are the settings the connector owns — the ones its page shows
	// with their value. A setting of a resource it uses (the data directory,
	// kit's port) belongs to that resource: [ContainerMessage].
	Settings []string      `json:"settings,omitempty"`
	// Nodes are the nodes the connector brings to the graph, sorted.
	Nodes    []string      `json:"nodes"`
}

type ConnectorSpec

ConnectorSpec is a connector kit can plug a product into, whether the product uses it or not: what it is, and the building blocks that bring it.

type ConnectorSpec struct {
	// ID is the connector's: [ConnectorHTTP]…
	ID       string           `json:"id"`
	// Kind groups it, as [ConnectorMessage.Kind].
	Kind     ConnectorKind    `json:"kind"`
	// Roles place it against the process boundary.
	Roles    []string         `json:"roles"`
	// Protocol is the wire protocol the code fixes, when it does.
	Protocol string           `json:"protocol,omitempty"`
	// Settings are the settings it owns.
	Settings []string         `json:"settings,omitempty"`
	// Declares are the building blocks whose declaration brings it: a
	// command brings the queue connector only when it is queued.
	Declares []NodeKind       `json:"declares"`
	// Adapters are the modules a product imports to plug it into what it
	// reaches: the engines of the database connector.
	Adapters []AdapterMessage `json:"adapters,omitempty"`
}

type ContainerMessage

ContainerMessage is one runnable or storage unit of the product. Its ID starts with "container:"; Nodes are the nodes that live in it.

type ContainerMessage struct {
	// ID is unique in the architecture: "container:process".
	ID         string         `json:"id"`
	// Name is what the diagram prints.
	Name       string         `json:"name"`
	// Kind is one of the Container constants.
	Kind       string         `json:"kind"`
	// Technology names what it is built with: "Go 1.27 · kit · net/http".
	Technology string         `json:"technology,omitempty"`
	// Doc says what it does.
	Doc        string         `json:"doc,omitempty"`
	// Location is where it runs or lives: the listen address, the data
	// directory. Present in dev only.
	Location   string         `json:"location,omitempty"`
	// Nodes are the nodes it hosts: services for the process, stores and
	// subscriptions for the volume, frontends for an SPA.
	Nodes      []string       `json:"nodes,omitempty"`
	// Ports are what the process listens on, and whose each port is.
	Ports      []PortMessage  `json:"ports,omitempty"`
	// Settings are the settings that configure it: KIT_DATA_DIR for the
	// data directory; a database's URL and tuning variables for a database.
	Settings   []string       `json:"settings,omitempty"`
	// Engine is a database's engine: "postgres", "mysql", "sqlite".
	Engine     string         `json:"engine,omitempty"`
	// Source is where the code declares the container, when it does: the
	// app for the process, a frontend for its SPA, kit.Database for a
	// database. [GraphMessage.Files] allows it.
	Source     *SourceMessage `json:"source,omitempty"`
}

type DatabaseMessage

DatabaseMessage is one database the app declares (kit.Database), as the running process found it. Its URL is never shown: where it was found, the engine, the address and the TLS mode are.

type DatabaseMessage struct {
	// Name is the database's, as the app declares it.
	Name       string                `json:"name"`
	// Engine is the engine it runs on: "postgres", "mysql", "sqlite".
	Engine     string                `json:"engine"`
	// State is one of the Database constants.
	State      string                `json:"state"`
	// Ready says whether it answered its last check; CheckedAt says when.
	Ready      bool                  `json:"ready"`
	CheckedAt  *time.Time            `json:"checkedAt,omitempty"`
	// Problem is the public text of its last failure: a start that failed,
	// a check it did not answer.
	Problem    string                `json:"problem,omitempty"`
	// URLFrom is where its URL was found — a Setting constant: env, store,
	// or default for a SQLite file beside the data —, empty when it is set
	// nowhere.
	URLFrom    string                `json:"urlFrom,omitempty"`
	// TLS is the TLS mode its URL writes: "verify-full"; "none" when it is
	// written off; empty when the URL leaves it to the driver, or when the
	// database is a file.
	TLS        string                `json:"tls,omitempty"`
	// Pool is database/sql's own count of its connections, sampled when the
	// graph was built.
	Pool       *Pool                 `json:"pool,omitempty"`
	// Migrations are its sets of migrations, kit's first, as the start —
	// or the last sample — found them.
	Migrations []MigrationSetMessage `json:"migrations,omitempty"`
}

type DevBuildMessage

DevBuildMessage is one build of `kit dev`: when, how long, and why. It lets the Studio say what changed and how long the reload took.

type DevBuildMessage struct {
	// BuiltAt is when the build finished.
	BuiltAt  *time.Time `json:"builtAt,omitempty"`
	// BuildMs is how long it took.
	BuildMs  float64    `json:"buildMs,omitempty"`
	// Rebuilds counts the builds of this kit dev session, this one
	// included: 1 is the first start.
	Rebuilds int        `json:"rebuilds,omitempty"`
	// Changed are the files whose change triggered this build, relative to
	// the module root, at most 20.
	Changed  []string   `json:"changed,omitempty"`
	// More counts the changed files beyond Changed.
	More     int        `json:"more,omitempty"`
}

type DiagnosticMessage

DiagnosticMessage is a problem found while building the graph. It names the node or the file it is about, and how serious it is.

type DiagnosticMessage struct {
	// Severity is "error" or "warning". An error refuses to start the app.
	Severity string            `json:"severity"`
	// Message says what is wrong and how to fix it, in English.
	Message  string            `json:"message"`
	// Texts is the message in each language kit speaks, by language: "en",
	// "fr". The Studio shows its reader's.
	Texts    map[string]string `json:"texts,omitempty"`
	// Node is the node concerned, when there is one.
	Node     string            `json:"node,omitempty"`
	// Source is where the problem is.
	Source   *SourceMessage    `json:"source,omitempty"`
}

type EdgeKind

EdgeKind says how two nodes relate. It is a wire format — the graph's JSON and the Studio's TypeScript unions carry these names —, so it stays a string.

type EdgeKind string

type EdgeMessage

EdgeMessage is one relation, with the evidence for it. Declared, Static and Observed say whether construction, the code or the runtime knows it.

type EdgeMessage struct {
	// ID is "<from>|<kind>|<to>" or "<from>|<kind>|<to>|<label>".
	ID       string          `json:"id"`
	// From is the source node ID.
	From     string          `json:"from"`
	// To is the target node ID.
	To       string          `json:"to"`
	// Kind says how the two relate.
	Kind     EdgeKind        `json:"kind"`
	// Label refines the kind: the event of a transition ("create" for a new
	// instance), or "direct" for a call that bypasses an endpoint.
	Label    string          `json:"label,omitempty"`
	// Contract names the versioned contract of an [EdgeContracts] edge:
	// "<name>/v<major>", "render/v1".
	Contract string          `json:"contract,omitempty"`
	// Declared is set when the edge exists by construction.
	Declared bool            `json:"declared,omitempty"`
	// Static lists the call sites the analyzer found, sorted.
	Static   []SourceMessage `json:"static,omitempty"`
	// Observed is present once the edge was seen at runtime.
	Observed *StatsMessage   `json:"observed,omitempty"`
}

type EditMessage

EditMessage is one change between two versions of a record, in RFC 6902's words: Op is add, remove or replace, Path the RFC 6901 JSON pointer of the member it changes, From its value before and To its value after, as JSON. A member whose value is not given — a secret's, or in the Studio a personal or special one — says it changed, never what: From and To are absent.

type EditMessage struct {
	Op   string          `json:"op"`
	Path string          `json:"path"`
	From json.RawMessage `json:"from,omitempty" kit:"personal"`
	To   json.RawMessage `json:"to,omitempty" kit:"personal"`
}

type EndpointSpec

EndpointSpec describes an HTTP endpoint, or the implementation of a port. It carries the method and path, the request and response schemas, and its auth.

type EndpointSpec struct {
	// Method is the HTTP method, upper case; empty for an implementation.
	Method     string            `json:"method"`
	// Path is the route pattern, with {wildcards}; empty for an
	// implementation.
	Path       string            `json:"path"`
	// Expose is [ExposePublic] or [ExposePrivate].
	Expose     string            `json:"expose"`
	// Auth is [AuthRequired], [AuthOptional], or empty when the endpoint
	// ignores authentication.
	Auth       string            `json:"auth,omitempty"`
	// Request is the input type.
	Request    *SchemaMessage    `json:"request,omitempty"`
	// Response is the output type.
	Response   *SchemaMessage    `json:"response,omitempty"`
	// Pipeline lists the mechanics a request goes through before the
	// handler, in order.
	Pipeline   []MechanicMessage `json:"pipeline,omitempty"`
	// Implements is the node ID of the port this endpoint implements
	// (Service.Implement): an endpoint with no route, reached through the
	// port.
	Implements string            `json:"implements,omitempty"`
	// Exposes is the node ID of the command this endpoint dispatches, or of
	// the query it asks (Command.Expose, Query.Expose): its authentication
	// is the operation's, and the rest of its pipeline — validation, key,
	// authorization — the operation's own.
	Exposes    string            `json:"exposes,omitempty"`
	// Access is how an exposure says its operation is open on purpose —
	// [AccessAnyone] or [AccessAnyUser] —; empty when the operation says who
	// may run it (a permission, a rule), and on any other endpoint.
	Access     string            `json:"access,omitempty"`
}

type ErasureMessage

ErasureMessage is what kit.Erase did, store by store. Stores lists, store by store, what the erasure did there.

type ErasureMessage struct {
	// Stores are the stores that kept records about the person.
	Stores []StoreErasureMessage `json:"stores"`
}

type Event

Event is one live event. Exactly one of the payload fields matching Type is set.

type Event struct {
	// Seq increases strictly on one stream; a reader drops what it has seen.
	Seq        uint64              `json:"seq"`
	// Type selects the payload.
	Type       EventType           `json:"type"`
	// Time is when it happened.
	Time       time.Time           `json:"time"`
	// Revision is the graph revision, on hello and graph events.
	Revision   string              `json:"revision,omitempty"`
	// StartedAt is when the process's current run started, on hello: a new
	// value means the process restarted, and what the reader knew of the
	// previous run is stale.
	StartedAt  *time.Time          `json:"startedAt,omitempty"`
	// Phase is the process phase, on hello and lifecycle events.
	Phase      string              `json:"phase,omitempty"`
	Span       *SpanMessage        `json:"span,omitempty"`
	Transition *TransitionEvent    `json:"transition,omitempty"`
	Lifecycle  *ComponentMessage   `json:"lifecycle,omitempty"`
	Loop       *LoopMessage        `json:"loop,omitempty"`
	Census     *CensusMessage      `json:"census,omitempty"`
	Log        *LogRecordMessage   `json:"log,omitempty"`
	Mail       *MailSummaryMessage `json:"mail,omitempty"`
}

type EventType

EventType names the kind of a live event. It is a wire format — the graph's JSON and the Studio's TypeScript unions carry these names —, so it stays a string.

type EventType string

type ExportedVersionsMessage

ExportedVersionsMessage are the versions of one exported record, as a StoreDataMessage carries them beside its records.

type ExportedVersionsMessage struct {
	// Record is the record's position in its StoreData's Records.
	Record   int                    `json:"record"`
	// Versions are its versions, newest first — the record as it is now
	// first —, each without its secret members.
	Versions []RecordVersionMessage `json:"versions"`
}

type FieldMessage

FieldMessage is one member of an object schema. It carries the JSON name, the schema of its value and the classes of its data.

type FieldMessage struct {
	// Name is the wire name.
	Name      string         `json:"name"`
	// In is where a request field is read from: "body", "path", "query",
	// "header" or "cookie". Empty outside requests.
	In        string         `json:"in,omitempty"`
	// Type is the member's schema.
	Type      *SchemaMessage `json:"type"`
	// Optional is set when the member may be absent.
	Optional  bool           `json:"optional,omitempty"`
	// Rules are the validation rules, as written in the validate tag.
	Rules     string         `json:"rules,omitempty"`
	// Doc is the field's comment, when the analyzer found one.
	Doc       string         `json:"doc,omitempty"`
	// Class is what the field holds, as its kit tag says (ADR 0006): one of
	// the Class constants, or empty when the field is unclassified. A
	// subject field is personal unless it is special.
	Class     string         `json:"class,omitempty"`
	// Subject marks the field that says whom a record is about.
	Subject   bool           `json:"subject,omitempty"`
	// Moderated marks content others see and a moderator may act on.
	Moderated bool           `json:"moderated,omitempty"`
	// Sealed is set when kit keeps the field sealed at rest (ADR 0006 §4):
	// a personal, special or secret field, or the subject, not plain, of
	// what kit keeps on disk — a store's entity, a topic's message, a queued
	// command's input. A store in memory seals nothing.
	Sealed    bool           `json:"sealed,omitempty"`
	// Erased marks the time kit stamps when it erases the record.
	Erased    bool           `json:"erased,omitempty"`
	// History is how many former values kit keeps of the field (ADR 0007).
	History   int            `json:"history,omitempty"`
}

type FileMessage

FileMessage is one file a graph points at: its path, relative to its root — the product's module, or the Go module [SourceMessage.GoModule] names.

type FileMessage struct {
	// GoModule is empty for a file of the product's own module.
	GoModule string `json:"goModule,omitempty"`
	File     string `json:"file"`
}

type FlameNodeMessage

FlameNodeMessage is one frame of a flame graph. Its children are the frames it called; its value is the samples under it.

type FlameNodeMessage struct {
	// Name is the function.
	Name     string              `json:"name"`
	// Value is its cumulative cost.
	Value    float64             `json:"value"`
	// Node is the node the frame belongs to, when it is a node's code.
	Node     string              `json:"node,omitempty"`
	// Children are its callees, highest first.
	Children []*FlameNodeMessage `json:"children,omitempty"`
}

type FormerMessage

FormerMessage is one former value of a field that keeps its history: what it was, until when, and who replaced it.

type FormerMessage struct {
	// Value is the field's value then, as JSON; absent for a secret field,
	// whose former values are never given.
	Value json.RawMessage `json:"value,omitempty" kit:"personal"`
	// Until is when it was replaced, on the app's clock.
	Until time.Time       `json:"until"`
	// By is the user who replaced it — kit.UserID —, empty for a write
	// with no user: a job's, a loop's, kit's own.
	By    string          `json:"by,omitempty"`
}

type FrontendSpec

FrontendSpec describes static assets served by the product. It carries the path the assets are served under and where they are read from.

type FrontendSpec struct {
	// Prefix is the URL path the assets are served under.
	Prefix string `json:"prefix"`
	// Files is how many files are served.
	Files  int    `json:"files,omitempty"`
}

type FuncCostMessage

FuncCostMessage is what one function cost. It carries the flat and cumulative samples of the function and where it lives.

type FuncCostMessage struct {
	// Func is the qualified function name.
	Func   string         `json:"func"`
	// Source locates it, when it is in the product's module.
	Source *SourceMessage `json:"source,omitempty"`
	// Flat is the cost of the function's own code; Cum includes its callees.
	Flat   float64        `json:"flat"`
	Cum    float64        `json:"cum"`
	// Node is the node it was attributed to, when one.
	Node   string         `json:"node,omitempty"`
}

type GoroutineGroup

GoroutineGroup is goroutines doing the same thing. They share one stack; Count says how many run it.

type GoroutineGroup struct {
	// Node is the node they run for, from their pprof label, when any.
	Node  string   `json:"node,omitempty"`
	// Loop is the loop they are, when kit knows: "http accept", a consumer.
	Loop  string   `json:"loop,omitempty"`
	// State is the runtime's word for what they wait on: "running",
	// "select", "chan receive", "IO wait", "sleep", "semacquire"…
	State string   `json:"state"`
	// Count is how many goroutines are in the group.
	Count int      `json:"count"`
	// Top is the innermost frame that is not the runtime's.
	Top   string   `json:"top"`
	// Stack is the group's stack, innermost first, capped.
	Stack []string `json:"stack,omitempty"`
}

type GoroutinesResult

GoroutinesResult is every goroutine of the process, grouped by what it runs. Each group names the node its stack runs in, when one does.

type GoroutinesResult struct {
	// At is when they were counted.
	At     time.Time        `json:"at"`
	// Total is how many goroutines exist.
	Total  int              `json:"total"`
	// Groups are goroutines sharing a node or loop, a state and a top frame,
	// largest first.
	Groups []GoroutineGroup `json:"groups"`
}

type GraphMessage

GraphMessage is the whole product. It is the JSON document the runtime serves and the analyzer writes; Version names its shape.

type GraphMessage struct {
	// Version is always [Version] for a document this package produced.
	Version          int                  `json:"version"`
	// Revision changes whenever the structure changes (nodes, edges, sources),
	// never when only observed statistics move. A reader caches layout on it.
	Revision         string               `json:"revision"`
	// App identifies the product.
	App              AppMessage           `json:"app"`
	// Nodes are sorted by ID.
	Nodes            []NodeEntity         `json:"nodes"`
	// Edges are sorted by ID.
	Edges            []EdgeMessage        `json:"edges"`
	// Catalog lists the generic mechanics this kit version offers.
	Catalog          []MechanicMessage    `json:"catalog,omitempty"`
	// Diagnostics are problems found while building the graph.
	Diagnostics      []DiagnosticMessage  `json:"diagnostics,omitempty"`
	// Runtime is present when a running process describes itself.
	Runtime          *RuntimeMessage      `json:"runtime,omitempty"`
	// Analysis reports the static analysis that enriched this graph.
	Analysis         *AnalysisResult      `json:"analysis,omitempty"`
	// Architecture is the product at C4's two outer levels: who uses it and
	// what it depends on, and what it is deployed as.
	Architecture     *ArchitectureMessage `json:"architecture,omitempty"`
	// Connectors are what the product plugs into, derived from its nodes by
	// [GraphMessage.Normalize]: the Studio shows their pages and widgets only.
	Connectors       []ConnectorMessage   `json:"connectors,omitempty"`
	// ConnectorCatalog is every connector this kit version ships, used or
	// not: what the product may plug into, and what brings each.
	ConnectorCatalog []ConnectorSpec      `json:"connectorCatalog,omitempty"`
	// Modules are the modules the app mounts (ADR 0008), sorted by name.
	Modules          []ModuleMessage      `json:"modules,omitempty"`
}

func (GraphMessage) Edge
func (*GraphMessage) Edge(id string) *EdgeMessage

Edge returns the edge with the given ID, or nil.

func (GraphMessage) Files
func (*GraphMessage) Files() []FileMessage

Files returns every file the graph points at, each with its root — the product's module, or another Go module: a module's (ADR 0008), a library's —, sorted and deduplicated. It is the complete list of files a reader of this graph may legitimately ask to see, and the source endpoint serves nothing else.

func (GraphMessage) ModuleOf
func (*GraphMessage) ModuleOf(name string) *ModuleMessage

ModuleOf returns the module named name, or nil.

func (GraphMessage) Node
func (*GraphMessage) Node(id string) *NodeEntity

Node returns the node with the given ID, or nil.

func (GraphMessage) Normalize
func (*GraphMessage) Normalize()

Normalize sorts nodes, edges and call sites into their canonical order, fills each workflow transition's callers from the edges, derives the connectors from the nodes, and recomputes Revision. Two graphs describing the same structure normalize to the same bytes, whatever order they were built in.

type HTTPServer

HTTPServer is the product's HTTP server, and whose loop serves it. Its address is the one it listens on; its loop is the node that runs it.

type HTTPServer struct {
	// Library is the implementation: "sdk/v1/net/server" — the SDK's engine
	// accepting and draining the connections, net/http speaking the protocol.
	Library    string            `json:"library"`
	// Loop says how it serves: one accept loop, one goroutine per
	// connection, written by the library rather than the product.
	Loop       string            `json:"loop"`
	// Addr is the listening address.
	Addr       string            `json:"addr,omitempty"`
	// Middleware is the chain every request goes through before its route,
	// outermost first.
	Middleware []MechanicMessage `json:"middleware,omitempty"`
	// Timeouts are the server's timeouts, as Go durations: "readHeader",
	// "read", "write", "idle".
	Timeouts   map[string]string `json:"timeouts,omitempty"`
	// Conns counts connections: "active" now, "total" ever accepted,
	// "rejected" by the listener's ceiling. Older graphs carry "new", "idle"
	// and "hijacked" too.
	Conns      map[string]int64  `json:"conns,omitempty"`
	// InFlight is how many requests are being served.
	InFlight   int64             `json:"inFlight"`
	// Served counts the requests served since start.
	Served     int64             `json:"served"`
}

type HeldUntilSpec

HeldUntilSpec is the hold a store declares on each of its records, until an instant the record carries.

type HeldUntilSpec struct {
	// At locates the function that gives the instant.
	At     *SourceMessage `json:"at,omitempty"`
	// Reason is the legal ground the declaration gives: "commercial code:
	// 10 years".
	Reason string         `json:"reason,omitempty"`
}

type HoldEvent

HoldEvent is one record a legal hold keeps. It carries references only: never the record's key, its subject's identity, or the hold's reason, which kit keeps apart.

type HoldEvent struct {
	// Store is the store's node ID.
	Store   string    `json:"store"`
	// Record is the record's reference.
	Record  string    `json:"record"`
	// Subject is the reference of the person the record is about, when it
	// has one.
	Subject string    `json:"subject,omitempty"`
	// By is who placed it: a user's ID, "cli" or "studio".
	By      string    `json:"by"`
	// At is when.
	At      time.Time `json:"at"`
}

type IDValue

IDValue is a node's identity, parsed: the one grammar of IDPattern. Its String is the ID it was parsed from.

type IDValue struct {
	// Module qualifies Service when a module lists it; empty for the
	// product's own services, and for a module's service named like it.
	Module  string
	// Service is the service's own name, unqualified; empty for a binary, a
	// role, a library and [ExternalID].
	Service string
	// Scope is the name of the binary of a binary or a role, or of the
	// library of a library; empty otherwise.
	Scope   string
	// Kind is the node's kind.
	Kind    NodeKind
	// Name is the node's name: the service's for a service, the binary's for
	// a binary.
	Name    string
}

func (IDValue) QualifiedServiceName
func (*IDValue) QualifiedServiceName() string

QualifiedServiceName is the service's ID segment: the qualification QualifiedService applies.

func (IDValue) String
func (*IDValue) String() string

String renders the ID; ParseID(id.String()) is id for every ID ParseID returned.

type IndexSpec

IndexSpec is one secondary index of a store. Its name is unique in the store; Unique says whether two records may share a key.

type IndexSpec struct {
	// Name is how code asks for the index: Store.Lookup(ctx, name, key).
	Name   string `json:"name"`
	// Unique is set when two entities may not share a key: a write that
	// would is refused with a conflict.
	Unique bool   `json:"unique,omitempty"`
}

type InstanceMessage

InstanceMessage is one entity's journey through a workflow. It carries the entity's key, its current state and the steps that brought it there.

type InstanceMessage struct {
	// ID is the entity key.
	ID        string      `json:"id"`
	// State is the current state.
	State     string      `json:"state"`
	// EnteredAt is when the instance entered its current state.
	EnteredAt time.Time   `json:"enteredAt"`
	// History lists the transitions, oldest first, capped.
	History   []StepEvent `json:"history,omitempty"`
}

type JobSpec

JobSpec describes a scheduled job. It carries the fixed interval or the cron expression that schedules it.

type JobSpec struct {
	// Schedule is "every 10s" or a five-field cron expression.
	Schedule string `json:"schedule"`
	// Kind is "interval" or "cron".
	Kind     string `json:"kind"`
}

type JournalCheckMessage

JournalCheckMessage is what verifying the journal's chain found. A broken chain names the first entry whose hash does not follow.

type JournalCheckMessage struct {
	// Entries is how many entries the journal holds.
	Entries  int   `json:"entries"`
	// BrokenAt is the sequence number where the chain breaks: an entry
	// changed, or one removed before it. Zero when the chain holds.
	BrokenAt int64 `json:"brokenAt,omitempty"`
}

type JournalEntryEvent

JournalEntryEvent is one operation of the privacy journal: what was done, where, by whom and when, with references only — never an identity, a value or a key. Each entry is chained to the previous one by SHA-256.

type JournalEntryEvent struct {
	// Seq numbers the entries from 1, with no gap.
	Seq     int64     `json:"seq"`
	// At is when, on the app's clock.
	At      time.Time `json:"at"`
	// Op is one of the Journal constants.
	Op      string    `json:"op"`
	// DryRun marks what the retention would have done under
	// KIT_RETENTION=dry-run: nothing changed.
	DryRun  bool      `json:"dryRun,omitempty"`
	// Store is the store's node ID.
	Store   string    `json:"store,omitempty"`
	// Record is the record's reference; Subject its subject's.
	Record  string    `json:"record,omitempty"`
	Subject string    `json:"subject,omitempty"`
	// By is who: a user's ID, the node that called, "retention", "cli" or
	// "studio".
	By      string    `json:"by"`
	// Hash is the entry's link in the chain: SHA-256 of the previous
	// entry's hash and this entry.
	Hash    string    `json:"hash"`
}

type LibrarySpec

LibrarySpec is a package shared between components (D19): the [NodeEntity.Library] of a KindLibrary node.

type LibrarySpec struct {
	// Package is its Go import path.
	Package string `json:"package"`
}

type LinkMessage

LinkMessage is a relationship between two elements of the architecture. The process's link to a database, "Reads and writes", carries the database connector, and the store connector once stores live on it.

type LinkMessage struct {
	// From is the ID of a person, system or container.
	From       string   `json:"from"`
	// To is the ID of a person, system or container.
	To         string   `json:"to"`
	// Label says what the relationship is: "Reads and writes".
	Label      string   `json:"label"`
	// Technology says how: "JSON over HTTP", "SMTP", "file I/O".
	Technology string   `json:"technology,omitempty"`
	// Nodes are the nodes whose edges make the link true.
	Nodes      []string `json:"nodes,omitempty"`
	// Connectors are the connectors the link is made of: one link from the
	// process to the data directory carries the stores, the queues and the
	// mail outbox.
	Connectors []string `json:"connectors,omitempty"`
}

type ListenerSpec

ListenerSpec is a listener that is not HTTP: the [NodeEntity.Listener] of a KindListener node — its network, its contract, who may connect.

type ListenerSpec struct {
	// Network is one of the Network constants.
	Network  string `json:"network"`
	// Contract is the versioned contract spoken on it: "render/v1".
	Contract string `json:"contract"`
	// Peer says who may connect: "owner" (the process's own user), or the
	// declared list, never "anyone".
	Peer     string `json:"peer"`
	// Role is the ID of the role that runs it.
	Role     string `json:"role,omitempty"`
}

type LogRecordMessage

LogRecordMessage is one log record written by product code through kit.Log, kept in dev so the Studio can show a request's logs beside its spans.

type LogRecordMessage struct {
	// Seq orders records; it only increases.
	Seq     uint64            `json:"seq"`
	// Time is when it was written.
	Time    time.Time         `json:"time"`
	// Level is "debug", "info", "warn" or "error".
	Level   string            `json:"level"`
	// Message is the record's message.
	Message string            `json:"message"`
	// Node is the node whose code wrote it.
	Node    string            `json:"node,omitempty"`
	// TraceID and SpanID correlate it with a span.
	TraceID string            `json:"traceId,omitempty"`
	SpanID  string            `json:"spanId,omitempty"`
	// Attrs are the record's attributes, as text, secrets redacted.
	Attrs   map[string]string `json:"attrs,omitempty"`
}

type LoopMessage

LoopMessage is one recurring piece of the daemon's internal loop: a job, a workflow's timer sweep, a subscription's consumer, the HTTP accept loop, a declared or hand-written loop.

type LoopMessage struct {
	// Name identifies the loop.
	Name       string     `json:"name"`
	// Node is the node the loop drives.
	Node       string     `json:"node,omitempty"`
	// Kind is one of the Loop constants.
	Kind       string     `json:"kind"`
	// Provenance is one of the Provenance constants.
	Provenance string     `json:"provenance,omitempty"`
	// Library names the code that loops, for a library or kit loop:
	// "net/http", "sdk/v1/app/scheduler", "sdk/v1/data/queue",
	// "sdk/v1/app/mail/spool", "sdk/v1/app/statemachine", "kit".
	Library    string     `json:"library,omitempty"`
	// State is one of the Loop state constants.
	State      string     `json:"state,omitempty"`
	// LastWake is why the last run started: "interval", "topic",
	// "deadline", "manual", "start".
	LastWake   string     `json:"lastWake,omitempty"`
	// Restarts counts supervised restarts, for a hand-written loop.
	Restarts   int64      `json:"restarts,omitempty"`
	// Schedule is human text: "every 10s", "*/5 * * * *", "on publish · poll 5s".
	Schedule   string     `json:"schedule"`
	// Runs counts completed runs.
	Runs       int64      `json:"runs"`
	// Errors counts failed runs.
	Errors     int64      `json:"errors"`
	// Missed counts due instants dropped because they had already passed.
	Missed     int64      `json:"missed"`
	// Skipped counts fires skipped because the previous run was still going.
	Skipped    int64      `json:"skipped"`
	// LastRun is when the last run started.
	LastRun    *time.Time `json:"lastRun,omitempty"`
	// LastMs is how long the last run took.
	LastMs     float64    `json:"lastMs,omitempty"`
	// NextRun is when the next run is due, when it is known.
	NextRun    *time.Time `json:"nextRun,omitempty"`
	// LastError is the public message of the last failure.
	LastError  string     `json:"lastError,omitempty"`
}

type LoopSpec

LoopSpec describes a loop node. Style says whether it is declared (kit owns the wait) or hand-written.

type LoopSpec struct {
	// Style is [LoopDeclared] or [LoopGoroutine].
	Style   string              `json:"style"`
	// Wakes are what wakes a declared loop.
	Wakes   []WakeSourceMessage `json:"wakes,omitempty"`
	// Selects are the cases of the select statements a hand-written loop
	// waits in, as the static analysis read them.
	Selects []SelectCaseMessage `json:"selects,omitempty"`
	// Restart is the supervision policy, as text.
	Restart string              `json:"restart,omitempty"`
}

type MailMessage

MailMessage is a whole captured mail, for the Studio's mailbox. It is kept by the capture transport of dev and tests only, never in production.

type MailMessage struct {
	MailSummary
	// Text is the plain text body.
	Text    string            `json:"text,omitempty"`
	// HTML is the HTML body. The Studio renders it in a sandboxed frame
	// that runs no script.
	HTML    string            `json:"html,omitempty"`
	// Headers are the extra headers, rendered.
	Headers map[string]string `json:"headers,omitempty"`
	// Raw is the composed message, as the transport received it.
	Raw     string            `json:"raw,omitempty"`
}

type MailSummary

MailSummary is the name MailMessage embeds its summary under: the field a caller sets and reads is MailMessage.MailSummary, its JSON members promoted beside the body's.

type MailSummary = MailSummaryMessage

MailSummary is an alias of github.com/kitsunium/sdk/framework/model/internal/core.MailSummaryMessage, declared as:

type MailSummary struct {
	// ID identifies the mail in the outbox.
	ID       string     `json:"id"`
	// Mailer is the mailer node.
	Mailer   string     `json:"mailer"`
	// From and To are addresses, rendered.
	From     string     `json:"from"`
	To       []string   `json:"to"`
	// Subject is the subject.
	Subject  string     `json:"subject"`
	// Status is one of the Mail constants.
	Status   string     `json:"status"`
	// Attempts counts delivery attempts.
	Attempts int        `json:"attempts"`
	// Error is the public message of the last failure.
	Error    string     `json:"error,omitempty"`
	// QueuedAt is when it entered the outbox; SentAt when it left.
	QueuedAt time.Time  `json:"queuedAt"`
	SentAt   *time.Time `json:"sentAt,omitempty"`
	// TraceID is the trace that queued it.
	TraceID  string     `json:"traceId,omitempty"`
	// Node is the node that queued it.
	Node     string     `json:"node,omitempty"`
}

type MailSummaryMessage

MailSummaryMessage is one mail as the outbox sees it. It carries no body: the Studio lists summaries and reads a whole mail on demand.

type MailSummaryMessage struct {
	// ID identifies the mail in the outbox.
	ID       string     `json:"id"`
	// Mailer is the mailer node.
	Mailer   string     `json:"mailer"`
	// From and To are addresses, rendered.
	From     string     `json:"from"`
	To       []string   `json:"to"`
	// Subject is the subject.
	Subject  string     `json:"subject"`
	// Status is one of the Mail constants.
	Status   string     `json:"status"`
	// Attempts counts delivery attempts.
	Attempts int        `json:"attempts"`
	// Error is the public message of the last failure.
	Error    string     `json:"error,omitempty"`
	// QueuedAt is when it entered the outbox; SentAt when it left.
	QueuedAt time.Time  `json:"queuedAt"`
	SentAt   *time.Time `json:"sentAt,omitempty"`
	// TraceID is the trace that queued it.
	TraceID  string     `json:"traceId,omitempty"`
	// Node is the node that queued it.
	Node     string     `json:"node,omitempty"`
}

type MailerSpec

MailerSpec describes outbound mail. It carries the transport that empties the outbox and the outbox's counters.

type MailerSpec struct {
	// Transport is [TransportSMTP] or [TransportCapture].
	Transport   string `json:"transport"`
	// Server is the relay's host:port. Credentials never appear.
	Server      string `json:"server,omitempty"`
	// TLS is "starttls", "implicit" or "none", for SMTP.
	TLS         string `json:"tls,omitempty"`
	// From is the default sender.
	From        string `json:"from,omitempty"`
	// MaxAttempts is how many deliveries a message gets before it is
	// dead-lettered.
	MaxAttempts int    `json:"maxAttempts"`
	// Outbox is "memory" or "file": where queued messages wait.
	Outbox      string `json:"outbox,omitempty"`
	// Queued is how many messages wait in the outbox, on a runtime graph.
	Queued      *int   `json:"queued,omitempty"`
	// Sent is how many messages the transport accepted, on a runtime graph.
	Sent        *int   `json:"sent,omitempty"`
	// DeadLetters is how many messages were abandoned, on a runtime graph.
	DeadLetters *int   `json:"deadLetters,omitempty"`
}

type MechanicMessage

MechanicMessage is a generic building block, backed by an SDK package, that a node composes. The catalog lists every mechanic kit offers; an endpoint's pipeline lists the ones it uses.

type MechanicMessage struct {
	// Kind is the stable identifier: "validate", "ratelimit", "timeout"…
	Kind    string            `json:"kind"`
	// Label is a short human rendering of the configuration: "5/s".
	Label   string            `json:"label"`
	// Package is the SDK package that implements it.
	Package string            `json:"package,omitempty"`
	// Doc says what it does, for a catalog.
	Doc     string            `json:"doc,omitempty"`
	// Snippet is the Go code that adds it, for a catalog.
	Snippet string            `json:"snippet,omitempty"`
	// Config is the configuration, as text.
	Config  map[string]string `json:"config,omitempty"`
}

type MigrationMessage

MigrationMessage is one versioned migration. Its Version orders it among the others; Name says what it does.

type MigrationMessage struct {
	// Version orders it: a UTC timestamp by convention, 20260910143000.
	Version uint64 `json:"version"`
	// Name says what it does; empty for a version this build does not carry.
	Name    string `json:"name,omitempty"`
}

type MigrationSetMessage

MigrationSetMessage is one set of migrations on a database — kit's own, the product's (kit.Migrations), a module's — with its own version table, and so its own lock.

type MigrationSetMessage struct {
	// Name is the set's origin: "kit", "product", or a module's name.
	Name    string             `json:"name"`
	// Table is its version table: "kit_migrations", "schema_migrations".
	Table   string             `json:"table"`
	// Applied are the migrations the database records, and Pending those
	// this build carries that it does not, oldest first.
	Applied []MigrationMessage `json:"applied,omitempty"`
	Pending []MigrationMessage `json:"pending,omitempty"`
	// Problem is why the set could not be read or applied.
	Problem string             `json:"problem,omitempty"`
}

type MockMessage

MockMessage is the replacement a test gave the app (MockReplace). It is set by a test only; the Studio shows it and never sets one (D13).

type MockMessage struct {
	// Node is the node it applies to: a port, a command or a query.
	Node string `json:"node"`
	// Mode is [MockReplace].
	Mode string `json:"mode"`
	// Hits counts the runs it changed.
	Hits int64  `json:"hits"`
}

type ModuleMessage

ModuleMessage is a module the app mounts: a Go module's services, released and mounted together like a bundle (ADR 0008). Everything a module declares is qualified with its name: its services are "<module>.<service>" — the one named like the module is "<module>" —, so its nodes are "<module>.<service>/<kind>/<name>" and carry [NodeEntity.Module].

type ModuleMessage struct {
	// Name is the name kit.NewModule gives it.
	Name       string                `json:"name"`
	// Doc is its description in the product's default language; Docs the
	// same in other languages, by tag, as a node's.
	Doc        string                `json:"doc,omitempty"`
	Docs       map[string]string     `json:"docs,omitempty"`
	// Package is the Go package that declares it: the one a product imports.
	Package    string                `json:"package,omitempty"`
	// Build is the Go module it comes from, and its version.
	Build      *ModuleVersionMessage `json:"build,omitempty"`
	// Services are its services' IDs, in the order it lists them.
	Services   []string              `json:"services"`
	// Requires are the modules it requires (kit.Requires), by name.
	Requires   []string              `json:"requires,omitempty"`
	// RequiredBy are the mounted modules that require it, by name, sorted.
	RequiredBy []string              `json:"requiredBy,omitempty"`
	// Prefix is where its routes are served: "/<name>/" unless the mount
	// says otherwise (kit.Prefix); "/" shares the product's route space.
	Prefix     string                `json:"prefix"`
	// Source is where kit.NewModule declares it.
	Source     *SourceMessage        `json:"source,omitempty"`
	// Mount is where the app mounts it — App.With or kit.Mount —; absent
	// when only another module's kit.Requires mounted it, at its defaults.
	Mount      *SourceMessage        `json:"mount,omitempty"`
}

type ModuleVersionMessage

ModuleVersionMessage identifies one module of a build. Local and Modified say when the code that ran is not the published version.

type ModuleVersionMessage struct {
	// Module is the module path.
	Module   string     `json:"module"`
	// Version is the published module version, "v0.4.6"; empty for a local
	// directory or a build without module version.
	Version  string     `json:"version,omitempty"`
	// Revision is the VCS commit the module was built from, when known.
	Revision string     `json:"revision,omitempty"`
	// Time is that commit's time.
	Time     *time.Time `json:"time,omitempty"`
	// Modified is set when the build included uncommitted changes.
	Modified bool       `json:"modified,omitempty"`
	// Local is set when the module came from a local directory (a replace
	// or a workspace) rather than a published version.
	Local    bool       `json:"local,omitempty"`
}

type NodeCostMessage

NodeCostMessage is what one node cost. It is the share of the profile's samples spent in the node's code.

type NodeCostMessage struct {
	// Node is the node ID.
	Node  string            `json:"node"`
	// Value is the cost, in the profile's unit.
	Value float64           `json:"value"`
	// Share is Value over Total, from 0 to 1.
	Share float64           `json:"share"`
	// Top are the node's costliest functions.
	Top   []FuncCostMessage `json:"top,omitempty"`
}

type NodeEntity

NodeEntity is one building block. Its ID is its identity; exactly one of the kind-specific fields matching Kind is set.

type NodeEntity struct {
	// ID is "<service>/<kind>/<name>", "<service>" for a service,
	// "binary:<name>" for a binary, "binary:<binary>/role/<name>" for a
	// role, "library:<name>" for a library, or [ExternalID]: the grammar of
	// [IDValue].
	ID           string            `json:"id"`
	// Kind says which building block this is.
	Kind         NodeKind          `json:"kind"`
	// Name is unique among the nodes of one kind in one service.
	Name         string            `json:"name"`
	// Service is the owning service ID. Empty for services and external.
	Service      string            `json:"service,omitempty"`
	// Module is the module the node belongs to — a module's service and
	// every node of it —; empty for the product's own.
	Module       string            `json:"module,omitempty"`
	// Doc is the Go doc comment of the declaration or of its handler, in
	// the product's default language.
	Doc          string            `json:"doc,omitempty"`
	// Docs are the same description in other languages, by tag ("fr"),
	// from the comment's tagged paragraphs: see [SplitDoc].
	Docs         map[string]string `json:"docs,omitempty"`
	// Source is where the node is declared.
	Source       *SourceMessage    `json:"source,omitempty"`
	// Handler is the body of the function the node runs, when it has one.
	Handler      *SourceMessage    `json:"handler,omitempty"`
	Endpoint     *EndpointSpec     `json:"endpoint,omitempty"`
	Store        *StoreSpec        `json:"store,omitempty"`
	Topic        *TopicSpec        `json:"topic,omitempty"`
	Subscription *SubscriptionSpec `json:"subscription,omitempty"`
	Workflow     *WorkflowSpec     `json:"workflow,omitempty"`
	Job          *JobSpec          `json:"job,omitempty"`
	Frontend     *FrontendSpec     `json:"frontend,omitempty"`
	Auth         *AuthSpec         `json:"auth,omitempty"`
	Mailer       *MailerSpec       `json:"mailer,omitempty"`
	Loop         *LoopSpec         `json:"loop,omitempty"`
	Secret       *SecretSpec       `json:"secret,omitempty"`
	Port         *PortSpec         `json:"port,omitempty"`
	Command      *CommandSpec      `json:"command,omitempty"`
	Query        *QuerySpec        `json:"query,omitempty"`
	Binary       *BinarySpec       `json:"binary,omitempty"`
	Role         *RoleSpec         `json:"role,omitempty"`
	CLI          *CLISpec          `json:"cli,omitempty"`
	Listener     *ListenerSpec     `json:"listener,omitempty"`
	Library      *LibrarySpec      `json:"library,omitempty"`
	Presentation *PresentationSpec `json:"presentation,omitempty"`
	// Code is the code the node runs, as the static analysis read it: C4's
	// code level.
	Code         *CodeResult       `json:"code,omitempty"`
	// Stats are runtime counters, present on a runtime graph.
	Stats        *StatsMessage     `json:"stats,omitempty"`
}

type NodeKind

NodeKind is the closed set of building blocks a kit product is made of. It is a wire format — the graph's JSON and the Studio's TypeScript unions carry these names —, so it stays a string.

type NodeKind string

type PasswordPolicyMessage

PasswordPolicyMessage is the policy of one secret field that holds a password's hash (Store.Passwords).

type PasswordPolicyMessage struct {
	// Field is the field's JSON pointer: "/password".
	Field     string         `json:"field"`
	// MinLength is the fewest characters a password may have.
	MinLength int            `json:"minLength"`
	// NotReused is how many former passwords it refuses; zero when it
	// refuses none.
	NotReused int            `json:"notReused,omitempty"`
	// NotCommon says it refuses the most common passwords (kit.NotCommon),
	// as every policy does.
	NotCommon bool           `json:"notCommon,omitempty"`
	// Source is where the policy is declared.
	Source    *SourceMessage `json:"source,omitempty"`
}

type Payload

Payload is the request and the response of a span, as JSON, in dev only. Every member whose name says it is a secret — password, token, secret, authorization, cookie… — or whose Go field is tagged kit:"secret" is replaced by "[redacted]", and each side is cut at 8 KiB.

type Payload struct {
	// Request is the decoded request, or the message delivered.
	Request   json.RawMessage `json:"request,omitempty"`
	// Response is the response.
	Response  json.RawMessage `json:"response,omitempty"`
	// Truncated is set when a side was cut.
	Truncated bool            `json:"truncated,omitempty"`
}

type PermissionMessage

PermissionMessage is what a caller needs to dispatch a command or to ask a query: that the app's policy lets it do Action to Resource (Allow).

type PermissionMessage struct {
	// Action is what the caller does: "place".
	Action   string `json:"action"`
	// Resource is the kind of thing it does it to: "order".
	Resource string `json:"resource"`
}

type PersonMessage

PersonMessage is a human user of the product. It is drawn at the edge of the C4 context view, outside every container.

type PersonMessage struct {
	// ID is unique in the architecture: "person:user".
	ID   string `json:"id"`
	// Name is what the diagram prints: "User".
	Name string `json:"name"`
	// Doc says who they are and what they do with the product.
	Doc  string `json:"doc,omitempty"`
}

type PersonalDataMessage

PersonalDataMessage is a person's data as kit.Export gives it (GDPR art. 15 and 20): their records, store by store, with what art. 15(1) asks beside them.

type PersonalDataMessage struct {
	// Stores are the stores that keep records about the person.
	Stores []StoreDataMessage `json:"stores"`
}

type PhaseChangeEvent

PhaseChangeEvent is one step of the daemon's life. It carries the phase entered, when it was entered, and why.

type PhaseChangeEvent struct {
	// Phase is the phase entered: one of the Phase constants.
	Phase  string    `json:"phase"`
	// At is when.
	At     time.Time `json:"at"`
	// Reason says why, when it is not the natural next step: "SIGTERM",
	// "a component failed".
	Reason string    `json:"reason,omitempty"`
}

type Pool

Pool is a database's connection pool, as database/sql counts it. It is sampled when the runtime state is read; its counters never move a revision.

type Pool struct {
	// MaxOpen is its ceiling.
	MaxOpen int     `json:"maxOpen"`
	// Open is how many connections are open: InUse and Idle.
	Open    int     `json:"open"`
	InUse   int     `json:"inUse"`
	Idle    int     `json:"idle"`
	// Waits counts the calls that waited for a connection, and WaitMs how
	// long they waited in all.
	Waits   int64   `json:"waits"`
	WaitMs  float64 `json:"waitMs"`
	// Closed counts the connections closed for being idle too many, idle
	// too long, or too old.
	Closed  int64   `json:"closed,omitempty"`
}

type PortMessage

PortMessage is an address a process listens on. Owner is the container that listens on it; Serves names what is reached through it.

type PortMessage struct {
	// Address is the listen address: "127.0.0.1:4000", ":4000". Present in
	// dev only, like every location.
	Address  string   `json:"address,omitempty"`
	// Owner is [PortOwnerKit], or the ID of the connector that opened it.
	Owner    string   `json:"owner"`
	// Serves says what it answers: the Serves constants.
	Serves   []string `json:"serves"`
	// Settings are the settings that configure it.
	Settings []string `json:"settings,omitempty"`
}

type PortSpec

PortSpec describes a port: an operation a service needs and another implements.

type PortSpec struct {
	// Request is the type the port is called with.
	Request  *SchemaMessage `json:"request,omitempty"`
	// Response is the type it answers.
	Response *SchemaMessage `json:"response,omitempty"`
	// Fallback is the node ID of the operation the port declares for when
	// the app binds nothing else (kit.Fallback).
	Fallback string         `json:"fallback,omitempty"`
	// Bound is the node ID of the operation the port calls, as the start
	// chose it — on a static graph, as the analysis reads the same rule;
	// empty when nothing is bound or a test replaced the port. The graph
	// draws it as a declared edge from the port.
	Bound    string         `json:"bound,omitempty"`
	// Via is how it was chosen: one of the Via constants.
	Via      string         `json:"via,omitempty"`
}

type PresentationSpec

PresentationSpec is what turns results into what a reader sees: the [NodeEntity.Presentation] of a KindPresentation node.

type PresentationSpec struct {
	// Media is what it renders: "text", "ansi", "html", "json".
	Media string `json:"media"`
}

type PrivacyMessage

PrivacyMessage is what a running app says of the personal data it keeps. It is the Privacy page's data: the register, the holds and the journal's state.

type PrivacyMessage struct {
	// Retention is KIT_RETENTION: one of the Retention constants.
	Retention string              `json:"retention"`
	// Register is the record of processing, as far as the code knows it.
	Register  RegisterMessage     `json:"register"`
	// Holds are the records a legal hold keeps, newest first.
	Holds     []HoldEvent         `json:"holds,omitempty"`
	// Journal is the privacy journal's latest entries, newest first.
	Journal   []JournalEntryEvent `json:"journal,omitempty"`
	// Chain says whether the journal's chain holds.
	Chain     JournalCheckMessage `json:"chain"`
}

type ProcessSpec

ProcessSpec is the Go process a product runs in. It carries the runtime's figures — goroutines, heap, GC, CPU — taken at At.

type ProcessSpec struct {
	// PID is the process ID.
	PID               int        `json:"pid"`
	// Go is the Go version the binary was built with.
	Go                string     `json:"go"`
	// OS and Arch are GOOS and GOARCH.
	OS                string     `json:"os"`
	Arch              string     `json:"arch"`
	// MaxProcs is GOMAXPROCS; CPUs the logical CPUs the process sees.
	MaxProcs          int        `json:"maxProcs"`
	CPUs              int        `json:"cpus"`
	// Goroutines is how many goroutines exist.
	Goroutines        int        `json:"goroutines"`
	// HeapBytes is the live heap; HeapObjects its object count.
	HeapBytes         uint64     `json:"heapBytes"`
	HeapObjects       uint64     `json:"heapObjects"`
	// HeapGoalBytes is the heap size at which the next collection starts.
	HeapGoalBytes     uint64     `json:"heapGoalBytes,omitempty"`
	// MemoryBytes is all the memory the Go runtime holds from the system:
	// the heap, the stacks, the runtime's own structures.
	MemoryBytes       uint64     `json:"memoryBytes,omitempty"`
	// TotalAllocBytes is every byte ever allocated on the heap.
	TotalAllocBytes   uint64     `json:"totalAllocBytes"`
	// GCCycles counts completed garbage collections.
	GCCycles          uint64     `json:"gcCycles"`
	// LastGC is when the last collection ended; absent before the first.
	LastGC            *time.Time `json:"lastGC,omitempty"`
	// GCPauseP99Ms is the 99th percentile stop-the-world pause.
	GCPauseP99Ms      float64    `json:"gcPauseP99Ms"`
	// SchedLatencyP99Ms is the 99th percentile time a goroutine waited to run.
	SchedLatencyP99Ms float64    `json:"schedLatencyP99Ms"`
	// CPUSeconds is the CPU time the process consumed, user and system.
	CPUSeconds        float64    `json:"cpuSeconds"`
	// UptimeMs is how long the process has run.
	UptimeMs          float64    `json:"uptimeMs"`
	// At is when the sample was taken.
	At                time.Time  `json:"at"`
}

type ProductRetentionSpec

ProductRetentionSpec is a retention the product keeps itself, as it says it.

type ProductRetentionSpec struct {
	// Limits says, in the product's words, how long the records keep their
	// personal data and how they go — the register's time limits, GDPR
	// art. 30(1)(f); empty when it gave none.
	Limits string `json:"limits,omitempty"`
}

type ProfileResult

ProfileResult is a pprof profile of the running product, folded onto its graph: every sample is attributed to the node whose code was running — through the pprof label kit puts on every handler, subscription, job and loop run, or, for the heap, which carries no label, through the node's code functions on the sample's stack.

type ProfileResult struct {
	// Kind is one of the Profile constants.
	Kind         string            `json:"kind"`
	// At is when the profile ended.
	At           time.Time         `json:"at"`
	// DurationMs is how long a CPU profile sampled.
	DurationMs   float64           `json:"durationMs,omitempty"`
	// Unit is what the values count: "ms" of CPU, "bytes" of heap.
	Unit         string            `json:"unit"`
	// Total is the sum of every sample.
	Total        float64           `json:"total"`
	// Nodes are the costs attributed to nodes, highest first.
	Nodes        []NodeCostMessage `json:"nodes"`
	// Unattributed is the cost outside any node's code: the runtime, the
	// garbage collector, kit itself, idle loops.
	Unattributed float64           `json:"unattributed"`
	// Top are the costliest functions, by flat cost.
	Top          []FuncCostMessage `json:"top"`
	// Flame is the call tree, root first, pruned below 0.5% of Total.
	Flame        *FlameNodeMessage `json:"flame,omitempty"`
}

type QuerySpec

QuerySpec describes a query: an operation that reads and changes nothing.

type QuerySpec struct {
	// Input is the type it is asked with.
	Input       *SchemaMessage      `json:"input,omitempty"`
	// Result is the type it answers.
	Result      *SchemaMessage      `json:"result,omitempty"`
	// Auth is [AuthRequired] — implied by a permission —, [AuthOptional],
	// or empty when the query ignores authentication.
	Auth        string              `json:"auth,omitempty"`
	// Pipeline lists the mechanics a question goes through before the
	// handler, in the order they run.
	Pipeline    []MechanicMessage   `json:"pipeline,omitempty"`
	// Permissions are the permissions a caller needs (Allow).
	Permissions []PermissionMessage `json:"permissions,omitempty"`
	// Authorize locates the function of its Authorize: a rule that needs
	// the data.
	Authorize   *SourceMessage      `json:"authorize,omitempty"`
}

type RecordFormerMessage

RecordFormerMessage is the former values of one exported record's fields. A personal or special field's former values are redacted, never exported in clear.

type RecordFormerMessage struct {
	// Record is the record's position in its StoreData's Records.
	Record int                        `json:"record"`
	// Fields are each field's former values, newest first, by the field's
	// JSON pointer. A secret field's are left out.
	Fields map[string][]FormerMessage `json:"fields"`
}

type RecordHistoryMessage

RecordHistoryMessage is what kit remembers of one record, as the Studio's data view shows it (GET /_kit/api/former): each field's former values, newest first, by the field's JSON pointer — a secret field's without their values, a personal or special one's redacted.

type RecordHistoryMessage struct {
	Fields map[string][]FormerMessage `json:"fields"`
}

type RecordVersionMessage

RecordVersionMessage is one version of a record whose store keeps revisions (ADR 0007 §3): its number — from 1, never given twice while the record exists —, when the write that made it ran — zero for a record stored before its store kept revisions —, who made it and which command, and the record as it was.

type RecordVersionMessage struct {
	Number  uint64          `json:"number"`
	// At is when the write that made it ran, on the app's clock.
	At      time.Time       `json:"at,omitzero"`
	// By is the user who made it — kit.UserID —, empty for a write with no
	// user.
	By      string          `json:"by,omitempty"`
	// Command is the node ID of the command that made it, empty outside
	// one.
	Command string          `json:"command,omitempty"`
	// Value is the record as it was: in an export, its secret members left
	// out; in the Studio, as the data browser shows a record.
	Value   json.RawMessage `json:"value,omitempty" kit:"personal"`
}

type RecordVersionsMessage

RecordVersionsMessage is a record's versions as the Studio's data view shows them (GET /_kit/api/revisions): newest first, each as the data browser shows a record — a member sealed at rest sealed, a personal, special or secret one redacted —, and, when two were asked for, what changed from one to the other, a value given only where the data browser would show it.

type RecordVersionsMessage struct {
	Versions []RecordVersionMessage `json:"versions"`
	// From and To are the two versions compared, when asked for; Edits what
	// changed between them.
	From     uint64                 `json:"from,omitempty"`
	To       uint64                 `json:"to,omitempty"`
	Edits    []EditMessage          `json:"edits,omitempty"`
}

type RegisterMessage

RegisterMessage is the record of processing of GDPR art. 30(1), as far as the code knows it.

type RegisterMessage struct {
	// App is the product.
	App        string                 `json:"app"`
	// ToComplete are the points the code cannot know, for a person to
	// write: "a" (the controller and its representatives), "e" (the
	// transfers).
	ToComplete []string               `json:"toComplete,omitempty"`
	// Stores are the stores that keep personal data, by node ID.
	Stores     []RegisterStoreMessage `json:"stores,omitempty"`
}

type RegisterStoreMessage

RegisterStoreMessage is one store's line in the register. It names the classes the store keeps, their purposes and their retention.

type RegisterStoreMessage struct {
	// Store is the store's node ID.
	Store      string                `json:"store"`
	// Purpose is point (b): why the store keeps its records.
	Purpose    string                `json:"purpose,omitempty"`
	// Subject is point (c)'s category of data subjects: the pointer of the
	// field that says whom each record is about.
	Subject    string                `json:"subject,omitempty"`
	// SubjectDoc is that field's comment, when the analyzer read it.
	SubjectDoc string                `json:"subjectDoc,omitempty"`
	// Personal, Special and Secret are point (c)'s categories of personal
	// data: the fields of each class, as JSON pointers. Special fields are
	// art. 9 data; secret ones are credentials.
	Personal   []string              `json:"personal,omitempty"`
	Special    []string              `json:"special,omitempty"`
	Secret     []string              `json:"secret,omitempty"`
	// Recipients are point (d) inside the product: the nodes the graph
	// shows reading the store, and the connectors that carry its data out.
	Recipients []string              `json:"recipients,omitempty"`
	// Erase, Delete and HeldUntil are point (f), the time limits, in words.
	Erase      string                `json:"erase,omitempty"`
	Delete     string                `json:"delete,omitempty"`
	HeldUntil  string                `json:"heldUntil,omitempty"`
	// ByProduct is point (f) when the product keeps the store's retention
	// itself (kit.RetentionByProduct), in its own words: no retention gap,
	// and no subject gap either.
	ByProduct  *ProductRetentionSpec `json:"byProduct,omitempty"`
	// Security is point (g): the measures kit takes.
	Security   []string              `json:"security,omitempty"`
	// Gaps are the Gap constants the store lacks.
	Gaps       []string              `json:"gaps,omitempty"`
}

type RetentionSpec

RetentionSpec is when kit erases or deletes a record: after a delay counted from an instant the record carries (After or Setting, and Since), or at an instant a function gives (At).

type RetentionSpec struct {
	// After is the delay, as a Go duration: the declared one, or the
	// setting's value when the graph describes a running app.
	After   string         `json:"after,omitempty"`
	// Setting names the setting of the store's service the delay is read
	// from, when the environment gives it.
	Setting string         `json:"setting,omitempty"`
	// Since locates the function that gives the instant the delay counts
	// from: a record's closing, say.
	Since   *SourceMessage `json:"since,omitempty"`
	// At locates the function that gives the instant itself.
	At      *SourceMessage `json:"at,omitempty"`
}

type RoleSpec

RoleSpec is one process role of a binary: the [NodeEntity.Role] of a KindRole node — its profile, arguments, singleton and idle stop.

type RoleSpec struct {
	// Binary is the ID of the binary that holds it.
	Binary    string   `json:"binary"`
	// Profile is one of the Profile constants.
	Profile   string   `json:"profile"`
	// Args are the leading arguments that select it — ["daemon"] for
	// "statusline daemon" —; empty for the binary's default role.
	Args      []string `json:"args,omitempty"`
	// Singleton, when set, is the scope of the lock that keeps one process of
	// this role alive at a time: what the lock's name is derived from.
	Singleton string   `json:"singleton,omitempty"`
	// IdleMs is how long a daemon waits without a client before it stops
	// itself; zero means it runs until stopped.
	IdleMs    int64    `json:"idleMs,omitempty"`
}

type RuntimeMessage

RuntimeMessage is what a running process says about itself: the daemon's own state and its internal loop.

type RuntimeMessage struct {
	// Phase is one of the Phase constants.
	Phase      string             `json:"phase"`
	// StartedAt is when the process started.
	StartedAt  time.Time          `json:"startedAt"`
	// Components are the lifecycle components, in start order.
	Components []ComponentMessage `json:"components"`
	// Loops are the recurring pieces of the internal loop.
	Loops      []LoopMessage      `json:"loops"`
	// History lists the phases the process went through, oldest first: the
	// daemon's own state machine, as it ran.
	History    []PhaseChangeEvent `json:"history,omitempty"`
	// Process is the Go process, sampled when the graph was built; nil when
	// the product imports no framework/kit/server, which plugs the sampler
	// in (ADR 0172).
	Process    *ProcessSpec       `json:"process,omitempty"`
	// HTTP is the product's HTTP server.
	HTTP       *HTTPServer        `json:"http,omitempty"`
	// Mocks are the replacements a test gave the app (kit.Replace).
	Mocks      []MockMessage      `json:"mocks,omitempty"`
	// Dev describes the build `kit dev` made of this process, when it did.
	Dev        *DevBuildMessage   `json:"dev,omitempty"`
	// Config is how the product was configured when it started: every
	// setting kit read, the value it uses — never a secret's — and where
	// that value came from.
	Config     []SettingMessage   `json:"config,omitempty"`
	// Boot is what kit did to start the product, step by step, as it ran;
	// the lifecycle components it then started are Components.
	Boot       []BootStepMessage  `json:"boot,omitempty"`
	// Databases are the databases the app declares, as this run found them:
	// each one's state, readiness, pool and migrations.
	Databases  []DatabaseMessage  `json:"databases,omitempty"`
}

type SchemaMessage

SchemaMessage describes a Go type as it appears on the wire. It is a JSON-Schema-like shape: a kind, its fields or elements, and its Go type.

type SchemaMessage struct {
	// Type is "object", "array", "map", "string", "integer", "number",
	// "boolean" or "any".
	Type     string         `json:"type"`
	// Name is the qualified Go type name, for named types.
	Name     string         `json:"name,omitempty"`
	// Format refines a scalar: "date-time", "duration", "int64"…
	Format   string         `json:"format,omitempty"`
	// Fields are the members of an object.
	Fields   []FieldMessage `json:"fields,omitempty"`
	// Items is the element type of an array.
	Items    *SchemaMessage `json:"items,omitempty"`
	// Values is the value type of a map.
	Values   *SchemaMessage `json:"values,omitempty"`
	// Enum lists the allowed values, when they are known.
	Enum     []string       `json:"enum,omitempty"`
	// Ref names a type already described higher up, to break a cycle.
	Ref      string         `json:"ref,omitempty"`
	// Nullable says a nil value is written null: a pointer, a slice, a map,
	// an interface — unless its member leaves it out (omitempty, omitzero).
	Nullable bool           `json:"nullable,omitempty"`
}

type SecretSpec

SecretSpec describes a declared secret: how it is made, where it lives, its versions — never its value.

type SecretSpec struct {
	// Origin is [SecretProvided] or [SecretGenerated].
	Origin       string     `json:"origin"`
	// Variable is the environment variable that provides it, or — for a
	// generated secret — pins it: TODO_SMTP_URL, or TODO_SMTP_URL_FILE naming
	// a file.
	Variable     string     `json:"variable"`
	// Bytes is the size of each version of a generated secret.
	Bytes        int        `json:"bytes,omitempty"`
	// RotateEvery is how often kit makes a new version of a generated
	// secret, as a Go duration.
	RotateEvery  string     `json:"rotateEvery,omitempty"`
	// Keep is how many versions a rotation leaves, the new one included.
	Keep         int        `json:"keep,omitempty"`
	// Optional: a provided secret the product can do without
	// (kit.Optional) — found nowhere, it is absent, and the start goes on.
	Optional     bool       `json:"optional,omitempty"`
	// From is where the running app found it: one of the SecretFrom
	// constants, on a runtime graph. Empty when it is found nowhere — for an
	// optional secret, absent.
	From         string     `json:"from,omitempty"`
	// Version is the number of its current version, from 1.
	Version      int        `json:"version,omitempty"`
	// Created is when the current version was made; the environment does
	// not say when a variable was set.
	Created      *time.Time `json:"created,omitempty"`
	// Versions is how many versions are kept.
	Versions     int        `json:"versions,omitempty"`
	// NextRotation is when kit rotates it next. Absent when kit does not
	// rotate it: provided, pinned by the environment, or in a store kit
	// cannot write.
	NextRotation *time.Time `json:"nextRotation,omitempty"`
	// Pinned: a generated secret the environment provides — kit uses it and
	// does not rotate it.
	Pinned       bool       `json:"pinned,omitempty"`
	// Rotations counts the rotations this process made.
	Rotations    int        `json:"rotations,omitempty"`
	// Problem says why it cannot be used, on a runtime graph.
	Problem      string     `json:"problem,omitempty"`
}

type SelectCaseMessage

SelectCaseMessage is one case of a select statement in a hand-written loop. The analyzer reads it from the loop's body; Kind says what the case waits on.

type SelectCaseMessage struct {
	// Text is the case as written: "<-ticker.C", "job := <-jobs".
	Text   string         `json:"text"`
	// Kind is one of the Select constants.
	Kind   string         `json:"kind"`
	// Source is where the case is.
	Source *SourceMessage `json:"source,omitempty"`
}

type SettingMessage

SettingMessage is one configuration value kit read when the product started: kit's own, or one a service of the product declares.

type SettingMessage struct {
	// Name is the environment variable that sets it: "KIT_ADDR",
	// "TODO_BASE_URL".
	Name     string `json:"name"`
	// Value is what kit uses. A secret's is left out: Secret says so.
	Value    string `json:"value,omitempty"`
	// From is one of the Setting constants.
	From     string `json:"from"`
	// Service declared it; empty for kit's own.
	Service  string `json:"service,omitempty"`
	// Key is a declared setting's name, its key in a configuration file:
	// "base-url". A module's is qualified with the module's name,
	// "moderation.tdb-url": kit.Set's key, and in a file "tdb-url" under
	// "moderation:" (ADR 0008).
	Key      string `json:"key,omitempty"`
	// Type is what a declared setting holds: text, bool, int, number,
	// duration or list.
	Type     string `json:"type,omitempty"`
	// Detail is the configuration file that gave the value, when From is
	// SettingFile: "config/production.yaml".
	Detail   string `json:"detail,omitempty"`
	// Secret: the value is withheld.
	Secret   bool   `json:"secret,omitempty"`
	// Option is the AppOption that sets it in code, when there is one:
	// "kit.Listen". Code wins over the environment.
	Option   string `json:"option,omitempty"`
	// Flag is the kit dev flag that sets it in dev, when there is one:
	// "-addr".
	Flag     string `json:"flag,omitempty"`
	// Database is the database the setting configures, when kit declares it
	// for one (kit.Database): its URL, its pool, its timeouts.
	Database string `json:"database,omitempty"`
}

type SnippetMessage

SnippetMessage is source code served to a reader of the graph. Focus and FocusEnd mark the lines a reader asked for, inside the lines served.

type SnippetMessage struct {
	// File is relative to App.Root.
	File      string   `json:"file"`
	// StartLine is the 1-based line of Lines[0].
	StartLine int      `json:"startLine"`
	// Focus is the first line of the range asked for.
	Focus     int      `json:"focus"`
	// FocusEnd is the last line of the range asked for.
	FocusEnd  int      `json:"focusEnd,omitempty"`
	// Lines are the file's lines around the focus, without terminators.
	Lines     []string `json:"lines"`
	// Language is the highlighter language: "go", "javascript"…
	Language  string   `json:"language"`
}

type SourceMessage

SourceMessage locates code. File is relative to its module's root; Line and EndLine bound the declaration.

type SourceMessage struct {
	// File is relative to App.Root, slash-separated — or, when GoModule is
	// set, to the root of that Go module.
	File     string `json:"file"`
	// Line is 1-based.
	Line     int    `json:"line"`
	// EndLine, when set, closes the range [Line, EndLine].
	EndLine  int    `json:"endLine,omitempty"`
	// Func is the qualified Go function, when the range is a function.
	Func     string `json:"func,omitempty"`
	// GoModule is set on a position outside the product's Go module — a
	// module's (ADR 0008), a library's —: that Go module, "path@version", or
	// its path alone when it is built from a local directory.
	GoModule string `json:"goModule,omitempty"`
}

type SpanMessage

SpanMessage is a finished unit of work, attributed to a node. Only allow-listed, wire-safe fields travel: no URL, no query string, no private error text.

type SpanMessage struct {
	// TraceID groups the spans of one causal chain (W3C, hex).
	TraceID  string            `json:"traceId"`
	// SpanID identifies the span (W3C, hex).
	SpanID   string            `json:"spanId"`
	// ParentID is the parent span, absent on a root.
	ParentID string            `json:"parentId,omitempty"`
	// Node is where the work happened.
	Node     string            `json:"node"`
	// From is the node that caused it: the edge this span travelled.
	From     string            `json:"from,omitempty"`
	// Edge is the kind of the edge From → Node.
	Edge     EdgeKind          `json:"edge,omitempty"`
	// Label refines Edge, like the edge's own label.
	Label    string            `json:"label,omitempty"`
	// Op is one of the Op constants.
	Op       string            `json:"op"`
	// Name is a low-cardinality operation name: a route pattern, "Get".
	Name     string            `json:"name"`
	// Start is when the work began.
	Start    time.Time         `json:"start"`
	// Ms is how long it took.
	Ms       float64           `json:"ms"`
	// Status is StatusError when the product failed — what kit answers with
	// a 5xx — and StatusOK otherwise, a refusal the caller has to fix (not
	// found, invalid, conflict, rate limited…) included.
	Status   string            `json:"status"`
	// Code is the error code, when the work ended in one: a failure's, or a
	// refusal's ("not_found").
	Code     string            `json:"code,omitempty"`
	// Error is the wire-safe public message of a failure; a refusal has none.
	Error    string            `json:"error,omitempty"`
	// Attrs are allow-listed attributes: "http.status", "instance"…
	Attrs    map[string]string `json:"attrs,omitempty"`
	// User is the authenticated caller's ID, when there is one.
	User     string            `json:"user,omitempty"`
	// Payload is what went in and out, in dev only, with secrets redacted.
	Payload  *Payload          `json:"payload,omitempty"`
}

type StateSpec

StateSpec is one state of a workflow. Terminal marks a state an instance stays in; Count is how many instances are in it.

type StateSpec struct {
	// Name is the state value, as text.
	Name     string          `json:"name"`
	// Terminal is set when no transition leaves the state.
	Terminal bool            `json:"terminal,omitempty"`
	// Count is how many instances are in the state, on a runtime graph.
	Count    *int            `json:"count,omitempty"`
	// OnEnter lists the hooks run when an instance enters the state.
	OnEnter  []SourceMessage `json:"onEnter,omitempty"`
}

type StatsMessage

StatsMessage are observed counters for a node or an edge. They are counters: they never move a graph's revision.

type StatsMessage struct {
	// Count is how many times it ran.
	Count  int64      `json:"count"`
	// Errors is how many of those failed.
	Errors int64      `json:"errors"`
	// LastAt is when it last ran.
	LastAt *time.Time `json:"lastAt,omitempty"`
	// AvgMs is the mean duration in milliseconds.
	AvgMs  float64    `json:"avgMs"`
	// MaxMs is the longest duration in milliseconds.
	MaxMs  float64    `json:"maxMs"`
}

type StepEvent

StepEvent is one transition in an instance's history. It carries the event, the states it went from and to, and when it fired.

type StepEvent struct {
	// Event is the transition's event name.
	Event   string    `json:"event"`
	// From is the state left.
	From    string    `json:"from"`
	// To is the state entered.
	To      string    `json:"to"`
	// At is when it happened.
	At      time.Time `json:"at"`
	// Trigger is one of the Trigger constants.
	Trigger string    `json:"trigger"`
	// Caller is the node that fired it, when code did.
	Caller  string    `json:"caller,omitempty"`
}

type StoreDataMessage

StoreDataMessage is one store's records about a person. It is one part of what kit.Export gives a person about themselves.

type StoreDataMessage struct {
	// Store is the store's node ID.
	Store      string                    `json:"store"`
	// Purpose is why the store keeps them.
	Purpose    string                    `json:"purpose,omitempty"`
	// Retention says, in words, how long they keep their personal data.
	Retention  string                    `json:"retention,omitempty"`
	// Recipients are who inside the product reads them, as far as the
	// running app knows.
	Recipients []string                  `json:"recipients,omitempty"`
	// Records are the records, their secret members left out. They hold the
	// person's data, which the Studio and the logs never show.
	Records    []json.RawMessage         `json:"records" kit:"personal"`
	// Former are the former values of the records' fields that keep them
	// (ADR 0007), record by record; a secret field's are left out.
	Former     []RecordFormerMessage     `json:"former,omitempty" kit:"personal"`
	// Versions are the versions of the records a store with revisions keeps
	// (ADR 0007 §3), record by record, their secret members left out.
	Versions   []ExportedVersionsMessage `json:"versions,omitempty" kit:"personal"`
}

type StoreErasureMessage

StoreErasureMessage is one store's part of an erasure: the keys of the records erased, deleted, and held — left in place, as a legal hold asks. A key may be personal data, which the Studio and the logs never show.

type StoreErasureMessage struct {
	// Store is the store's node ID.
	Store   string   `json:"store"`
	// Erased are the records whose personal data was cleared.
	Erased  []string `json:"erased,omitempty" kit:"personal"`
	// Deleted are the records removed.
	Deleted []string `json:"deleted,omitempty" kit:"personal"`
	// Held are the records a hold keeps, untouched.
	Held    []string `json:"held,omitempty" kit:"personal"`
}

type StoreHistoryMessage

StoreHistoryMessage is what a store remembers of its records. Fields names the fields it keeps former values of; Kept and Bytes weigh them.

type StoreHistoryMessage struct {
	// Revisions is how many former versions each record keeps
	// (kit.Revisions, ADR 0007 §3); zero when it keeps none.
	Revisions int                     `json:"revisions,omitempty"`
	// Fields are the JSON pointers of the fields that keep their former
	// values: tagged history=N — the schema's Field.History says how many —
	// or read by a password policy that refuses former passwords.
	Fields    []string                `json:"fields,omitempty"`
	// Passwords are the store's password policies.
	Passwords []PasswordPolicyMessage `json:"passwords,omitempty"`
	// Kept is how many former values the store keeps, and Bytes what its
	// histories weigh, on a runtime graph.
	Kept      *int                    `json:"kept,omitempty"`
	Bytes     *int64                  `json:"bytes,omitempty"`
}

type StorePrivacyMessage

StorePrivacyMessage is what a store keeps of people: whom each record is about, why, for how long, and — on a runtime graph — what is held and due.

type StorePrivacyMessage struct {
	// Subject is the JSON pointer of the field that says whom each record is
	// about: "/email". Empty when the entity has no subject field.
	Subject         string                `json:"subject,omitempty"`
	// Purpose is why the store keeps its records, as kit.Purpose says it.
	Purpose         string                `json:"purpose,omitempty"`
	// Erase says when kit clears a record's personal data; Delete when it
	// removes the record.
	Erase           *RetentionSpec        `json:"erase,omitempty"`
	Delete          *RetentionSpec        `json:"delete,omitempty"`
	// ByProduct is set when the product keeps the store's retention itself
	// (kit.RetentionByProduct): kit runs none — Erase and Delete are then
	// absent — and asks for neither a retention nor a subject.
	ByProduct       *ProductRetentionSpec `json:"byProduct,omitempty"`
	// HeldUntil holds each record until an instant it carries: the law's
	// own retention (kit.HeldUntil).
	HeldUntil       *HeldUntilSpec        `json:"heldUntil,omitempty"`
	// Anonymise locates the function that says what an erased record keeps,
	// generalised (kit.Anonymise).
	Anonymise       *SourceMessage        `json:"anonymise,omitempty"`
	// DeleteOnErasure: a person's erasure deletes the record instead of
	// clearing it (kit.DeleteOnErasure).
	DeleteOnErasure bool                  `json:"deleteOnErasure,omitempty"`
	// Held is how many records a hold keeps, on a runtime graph.
	Held            *int                  `json:"held,omitempty"`
	// Due is when the next record is due to be erased or deleted, on a
	// runtime graph; absent when none is.
	Due             *time.Time            `json:"due,omitempty"`
	// Erased and Deleted count what this run erased and deleted, on a
	// runtime graph.
	Erased          *int                  `json:"erased,omitempty"`
	Deleted         *int                  `json:"deleted,omitempty"`
}

type StoreSpec

StoreSpec describes a store. It carries the entity's schema, its backend, its indexes, its privacy and its history.

type StoreSpec struct {
	// Entity is the stored type.
	Entity    *SchemaMessage       `json:"entity,omitempty"`
	// Backend is where the store's data is: "memory", "file", or the engine
	// of the database that keeps it (ADR 0004): "postgres", "mysql",
	// "sqlite".
	Backend   string               `json:"backend"`
	// Location is where a file backend keeps its data, relative to the data
	// directory.
	Location  string               `json:"location,omitempty"`
	// Database names the database that keeps the store, as the app declares
	// it (kit.Database, kit.Keeps) — present even while the store's data
	// stays in the data directory, in dev without the database's URL. Its
	// container is "container:database:<name>".
	Database  string               `json:"database,omitempty"`
	// Table is the table the database keeps the store's entities in —
	// "<service>__<store>", '-' and '.' written '_', a digest past the
	// engine's limit —, beside its index rows in "<table>___ix". Present
	// with Database.
	Table     string               `json:"table,omitempty"`
	// Count is how many entities the store holds, on a runtime graph.
	Count     *int                 `json:"count,omitempty"`
	// Indexes are the secondary indexes the store maintains, in declaration
	// order.
	Indexes   []IndexSpec          `json:"indexes,omitempty"`
	// Privacy says what the store does with personal data (ADR 0006): whom
	// its records are about, why it keeps them and for how long. Absent when
	// its entity holds nothing personal and it declares no retention.
	Privacy   *StorePrivacyMessage `json:"privacy,omitempty"`
	// History says what the store remembers of its records (ADR 0007): the
	// fields that keep their former values, its password policies. Absent
	// when it remembers nothing and has no policy.
	History   *StoreHistoryMessage `json:"history,omitempty"`
	// ReadModel is set on a store derived from others (kit.ReadModel):
	// written by projections — subscriptions —, read by queries.
	ReadModel bool                 `json:"readModel,omitempty"`
}

type SubscriptionSpec

SubscriptionSpec describes a subscription — or a watch (ADR 0008), a subscription whose deliveries come from stores instead of a topic.

type SubscriptionSpec struct {
	// Topic is the node ID of the consumed topic; empty for a watch.
	Topic         string   `json:"topic"`
	// Mark is what a watch hears the writes of: "personal", "special" or
	// "moderated", ADR 0006's marks. Empty for a subscription.
	Mark          string   `json:"mark,omitempty"`
	// OwnStores: the watch hears its own module's stores too — the
	// product's own, for a watch of the product's (kit.OwnStores) —, never
	// the writes its own handler makes.
	OwnStores     bool     `json:"ownStores,omitempty"`
	// Stores are the node IDs of the stores that feed a watch, sorted: those
	// whose entity holds a field with its mark, but its own module's — the
	// product's own, for a watch of the product's — unless OwnStores. Each
	// draws a declared delivers edge to it.
	Stores        []string `json:"stores,omitempty"`
	// MaxDeliveries is how many attempts a message gets before it is
	// dead-lettered.
	MaxDeliveries int      `json:"maxDeliveries,omitempty"`
	// Parallelism is how many messages are handled concurrently.
	Parallelism   int      `json:"parallelism,omitempty"`
	// DeadLetters is how many messages were abandoned, on a runtime graph.
	DeadLetters   *int     `json:"deadLetters,omitempty"`
}

type SystemMessage

SystemMessage is a software system outside the product. Nodes are the product's nodes that talk to it; Technology says what it runs on.

type SystemMessage struct {
	// ID is unique in the architecture: "system:smtp".
	ID         string   `json:"id"`
	// Name is what the diagram prints: "SMTP relay".
	Name       string   `json:"name"`
	// Doc says what it is to the product.
	Doc        string   `json:"doc,omitempty"`
	// Technology names how it is reached: "SMTP · STARTTLS".
	Technology string   `json:"technology,omitempty"`
	// Location says where, when it is known and not secret: "smtp.example.com:587".
	Location   string   `json:"location,omitempty"`
	// Nodes are the nodes of the product that talk to it.
	Nodes      []string `json:"nodes,omitempty"`
}

type TopicSpec

TopicSpec describes a topic. It carries the message's schema; its subscriptions are the nodes it delivers to.

type TopicSpec struct {
	// Message is the published type.
	Message  *SchemaMessage `json:"message,omitempty"`
	// Delivery is the guarantee: "at-least-once".
	Delivery string         `json:"delivery"`
	// Broker is "memory" or "file".
	Broker   string         `json:"broker,omitempty"`
}

type TraceMessage

TraceMessage is the spans sharing one trace ID, root first. The root span is the one with no parent in the trace; the others follow it.

type TraceMessage struct {
	// TraceID identifies the trace.
	TraceID string        `json:"traceId"`
	// Root is the node of the root span.
	Root    string        `json:"root"`
	// Name is the root span's name.
	Name    string        `json:"name"`
	// Start is when the root began.
	Start   time.Time     `json:"start"`
	// Ms spans from the first start to the last end.
	Ms      float64       `json:"ms"`
	// Status is StatusError when any span failed.
	Status  string        `json:"status"`
	// Spans are in start order.
	Spans   []SpanMessage `json:"spans"`
}

type TransitionEvent

TransitionEvent is one workflow instance moving between states. It names the workflow, the entity, the event and the states it went from and to.

type TransitionEvent struct {
	// Workflow is the workflow node ID.
	Workflow string `json:"workflow"`
	// Instance is the entity key.
	Instance string `json:"instance"`
	// Event is the transition's event name.
	Event    string `json:"event"`
	// From is the state left; empty on creation.
	From     string `json:"from"`
	// To is the state entered.
	To       string `json:"to"`
	// Trigger is one of the Trigger constants.
	Trigger  string `json:"trigger"`
	// Caller is the node that fired it, when code did.
	Caller   string `json:"caller,omitempty"`
}

type TransitionSpec

TransitionSpec is one arrow of a workflow. It names the event that fires it and the states it goes from and to.

type TransitionSpec struct {
	// Event names the transition. Timer and guard transitions have one too.
	Event   string         `json:"event"`
	// From is the source state.
	From    string         `json:"from"`
	// To is the target state.
	To      string         `json:"to"`
	// Trigger is [TriggerEvent], [TriggerTimer] or [TriggerGuard].
	Trigger string         `json:"trigger"`
	// After is the delay of a timer transition, as a Go duration string.
	After   string         `json:"after,omitempty"`
	// Setting names the setting of the service the delay is read from, when
	// the environment gives it: "archive-after".
	Setting string         `json:"setting,omitempty"`
	// At locates the function that says when a timer transition declared at
	// an instant is due — a due date, a deadline the entity carries.
	At      *SourceMessage `json:"at,omitempty"`
	// Guard locates the condition of a guard transition.
	Guard   *SourceMessage `json:"guard,omitempty"`
	// Source is where the transition is declared.
	Source  *SourceMessage `json:"source,omitempty"`
	// Callers are the node IDs found to fire this event.
	Callers []string       `json:"callers,omitempty"`
}

type WakeSourceMessage

WakeSourceMessage is one thing that wakes a declared loop. Kind says whether a topic, a period (Every) or a function wakes the loop.

type WakeSourceMessage struct {
	// Kind is one of the Wake constants.
	Kind  string         `json:"kind"`
	// Every is the period of an interval wake, as a Go duration.
	Every string         `json:"every,omitempty"`
	// Topic is the node ID of a topic wake.
	Topic string         `json:"topic,omitempty"`
	// Func locates the function computing a deadline wake.
	Func  *SourceMessage `json:"func,omitempty"`
}

type WorkflowSpec

WorkflowSpec describes a state machine bound to a store. It carries the states and the transitions between them, and the store it lives in.

type WorkflowSpec struct {
	// Store is the node ID of the store holding the instances.
	Store       string           `json:"store"`
	// Field is the wire name of the entity field holding the state, when the
	// state function points at a field of the entity.
	Field       string           `json:"field,omitempty"`
	// Initial is the state a new instance enters.
	Initial     string           `json:"initial"`
	// States are in declaration order.
	States      []StateSpec      `json:"states"`
	// Transitions are in declaration order.
	Transitions []TransitionSpec `json:"transitions"`
}

Generated from docs/api by tools/genindex.

Documentation

Overview

Package core is the Product Graph under the names the role rule asks for: every struct carries its role (NodeEntity, GraphMessage, EndpointSpec, …). framework/model is its public face — an alias per type under the graph's own names (Node, Graph, EndpointInfo, …), its constants and its functions — and the one package a caller imports.

Index

Constants

View Source
const (
	ContainerProcess = "process" // the Go binary: every service, one process
	ContainerSPA     = "spa"     // a frontend: served by the process, run by a browser
	ContainerVolume  = "volume"  // the data directory: store files, queue files
	ContainerMemory  = "memory"  // data kept in the process's memory only
	// ContainerDatabase is a database the app declares (kit.Database):
	// "container:database:<name>", drawn as a cylinder.
	ContainerDatabase = "database"
)

Container kinds.

View Source
const (
	ServesHealth = "health" // the liveness and readiness probes
	ServesStudio = "studio" // the Studio and its API, in dev
	ServesHTTP   = "http"   // the product's own HTTP entry points
)

What a port serves.

View Source
const (
	BlockIf     = "if"      // an if's first branch
	BlockElseIf = "else-if" // an if's else-if branch
	BlockElse   = "else"    // an if's last branch
	BlockCase   = "case"    // a switch's or a select's case
	BlockLoop   = "loop"    // a for or range loop's body
	BlockGo     = "go"      // a go statement: runs beside the caller
	BlockDefer  = "defer"   // a defer statement: runs when the function returns
	BlockFunc   = "func"    // a function literal: runs when it is called
	// BlockTransaction is the function a kit.Transact runs: its steps run in
	// one transaction, and the effects they make leave at its commit.
	BlockTransaction = "transaction"
)

The kinds of CodeBlockMessage.

View Source
const (
	RoleInbound  = "inbound"
	RoleOutbound = "outbound"
	RoleStorage  = "storage"
)

The roles of a connector, against the process boundary.

View Source
const (
	ConnectorHTTP  = "http"
	ConnectorMail  = "mail"
	ConnectorStore = "store"
	ConnectorQueue = "queue"
	// ConnectorDatabase is brought by a store a database keeps (ADR 0004):
	// kit.Database declares the database, an engine module reaches it.
	ConnectorDatabase = "database"
)

The connectors kit ships.

View Source
const (
	EnginePostgres = "postgres"
	EngineMySQL    = "mysql"
	EngineSQLite   = "sqlite"
)

The engines a database runs on (ADR 0004): one module each in kit's repository, the only code that imports its driver.

View Source
const (
	MailQueued   = "queued"   // in the outbox, not yet handed to the transport
	MailSent     = "sent"     // the transport accepted it (capture: kept for the mailbox)
	MailRetrying = "retrying" // the last attempt failed; another is scheduled
	MailDead     = "dead"     // abandoned after its last attempt
)

Mail statuses.

View Source
const (
	// SegmentPattern is a service, module, binary, role or library name.
	SegmentPattern = `[a-z][a-z0-9-]{0,62}`
	// NamePattern is a node's name within its service and kind.
	NamePattern = `[A-Za-z][A-Za-z0-9_.-]{0,62}`
	// RoutePattern is the name of an endpoint declared without one: its
	// route, "GET /tasks/{id}".
	RoutePattern = `[A-Z]+ /[^\s]*`
	// ContractPattern is the versioned contract an [EdgeContracts] edge
	// carries: "render/v1".
	ContractPattern = `[a-z][a-z0-9-]{0,62}/v[1-9][0-9]{0,3}`

	// BinaryScope prefixes the ID of a binary and of its roles.
	BinaryScope = "binary:"
	// LibraryScope prefixes the ID of a library.
	LibraryScope = "library:"
)

The grammar of every ID a graph carries, written once. The runtime, the analyzer, the design files' JSON Schema and the Studio all read it from here: a second copy is how two sides come to derive different names for the same declaration (invariant 1 of the platform's kit).

id       = "external"
         | service
         | service "/" kind "/" name
         | "binary:" segment
         | "binary:" segment "/role/" segment
         | "library:" segment
service  = [ segment "." ] segment        ; "<module>.<service>"
segment  = [a-z][a-z0-9-]{0,62}
name     = [A-Za-z][A-Za-z0-9_.-]{0,62}
         | method " " path                 ; an endpoint named by its route

A module's service named like the module is the module's name alone (QualifiedService); every other service of a module is qualified.

View Source
const (
	// ExposePublic endpoints are routed on the product's HTTP listener.
	ExposePublic = "public"
	// ExposePrivate endpoints have no route: the implementation of a port
	// (Service.Implement), reached in process through its port. A graph kit
	// made before its operations were internal by default also marks so an
	// endpoint it kept off the listener.
	ExposePrivate = "private"
)

Exposure says who may reach an endpoint.

View Source
const (
	// AccessAnyone is kit.Anyone(): whoever reaches the route may run the
	// operation.
	AccessAnyone = "anyone"
	// AccessAnyUser is kit.AnyUser(): any signed-in user may run it — the
	// operation asks for one.
	AccessAnyUser = "any-user"
)

How an exposure says it is open on purpose, when its operation declares no permission and no rule (EndpointInfo.Access).

View Source
const (
	// AuthRequired endpoints run only for an authenticated caller; the others
	// are answered 401 before the handler runs.
	AuthRequired = "required"
	// AuthOptional endpoints run the auth handler when credentials are
	// present, and serve anonymous callers too.
	AuthOptional = "optional"
)

Authentication an endpoint asks for.

View Source
const (
	// TriggerEvent is a transition fired by code, naming an event.
	TriggerEvent = "event"
	// TriggerTimer is a transition fired after a duration in a state, or at
	// an instant the entity carries.
	TriggerTimer = "timer"
	// TriggerGuard is a transition fired when a condition on the entity
	// holds, checked each time the entity is written.
	TriggerGuard = "guard"
	// TriggerCreate is the entry of a new instance into the initial state.
	TriggerCreate = "create"
)

Transition triggers.

View Source
const (
	// ViaBind is the app's kit.Bind.
	ViaBind = "bind"
	// ViaImplement is the one Service.Implement among the mounted services.
	ViaImplement = "implement"
	// ViaFallback is the port's own kit.Fallback.
	ViaFallback = "fallback"
	// ViaReplace is a test's kit.Replace: a function answers in place of
	// whatever the port would call, and nothing is bound.
	ViaReplace = "replace"
)

How the start chose what a port calls: kit.Bind, else the one Service.Implement among the services the app mounts, else the port's fallback — or a test replaced the port.

View Source
const (
	// ModeSync is handled on its caller's goroutine: Dispatch returns the
	// handler's result.
	ModeSync = "sync"
	// ModeQueued is sent to the background (kit.Queued): Dispatch returns
	// once the command's own queue accepted it, and a consumer handles it,
	// retried and dead-lettered.
	ModeQueued = "queued"
)

How a command is handled.

View Source
const (
	// TransportSMTP delivers to an SMTP relay.
	TransportSMTP = "smtp"
	// TransportCapture keeps every message for the Studio's mailbox and
	// delivers nothing: the transport of dev and tests.
	TransportCapture = "capture"
)

Mail transports.

View Source
const (
	// SecretProvided is given by the operator: an SMTP URL, an API token.
	SecretProvided = "provided"
	// SecretGenerated is made by kit and rotated on a schedule: a signing or
	// sealing key.
	SecretGenerated = "generated"
)

How a secret is made.

View Source
const (
	// SecretFromEnv is the environment: the variable, or the file its _FILE
	// form names.
	SecretFromEnv = "env"
	// SecretFromFile is kit's encrypted file store: KIT_SECRETS=file:<dir>,
	// or .kit/secrets/dev in dev.
	SecretFromFile = "file"
	// SecretFromMemory is a store in the process's memory: a test, or
	// KIT_SECRETS=memory. A generated secret is made again at every start.
	SecretFromMemory = "memory"
	// SecretFromStore is a store the product's code gave kit.
	SecretFromStore = "store"
)

Where a running app found a secret.

View Source
const (
	// LoopDeclared is Service.Loop: kit owns the wait — the wake sources are
	// data, so the diagram draws them — and the product owns the work.
	LoopDeclared = "declared"
	// LoopGoroutine is Service.Go: the product wrote the whole loop; kit
	// starts it, stops it, restarts it after a failure, and reads its select
	// statements to draw what it waits on.
	LoopGoroutine = "goroutine"
)

Loop styles.

View Source
const (
	WakeInterval = "interval" // a fixed period
	WakeDeadline = "deadline" // a time the product computes after every run
	WakeTopic    = "topic"    // any publish on a topic
	WakeStart    = "start"    // once, when the app starts
	WakeManual   = "manual"   // Loop.Nudge, or the Studio
	WakeChange   = "change"   // a write of the store a workflow runs over, or of one a watch hears
)

Wake source kinds of a declared loop, and why a loop of kit's ran.

View Source
const (
	SelectTimer   = "timer"   // a timer, ticker or time.After channel
	SelectDone    = "done"    // ctx.Done(): the loop's way out
	SelectReceive = "receive" // any other receive
	SelectSend    = "send"    // a send
	SelectDefault = "default" // the default case: the select never blocks
)

Select case kinds.

View Source
const (
	// ClassPublic holds nothing personal and nothing secret: the question
	// was asked.
	ClassPublic = "public"
	// ClassPersonal holds data about an identifiable person: a name, an
	// address, a message a person wrote.
	ClassPersonal = "personal"
	// ClassSpecial holds the special categories of GDPR art. 9(1), or
	// criminal convictions (art. 10).
	ClassSpecial = "special"
	// ClassSecret holds a credential: a password's hash, a token's digest.
	ClassSecret = "secret"
)

What a field holds: the classes of a kit tag (ADR 0006).

View Source
const (
	// ProfileServer serves HTTP until it is stopped: the platform's kit
	// product, and the only profile that opens a TCP listener.
	ProfileServer = "server"
	// ProfileCLI parses its arguments, runs once and exits with a typed
	// status. It starts no listener and no loop outlives it.
	ProfileCLI = "cli"
	// ProfileDaemon runs until it is stopped, or until it has been idle for
	// its declared time, and serves no HTTP: it answers on its listeners —
	// a private socket, a pipe — and runs its loops.
	ProfileDaemon = "daemon"
)

Process profiles: what a role does with its process.

View Source
const (
	// NetworkUnix is a Unix-domain socket, private to its owner.
	NetworkUnix = "unix"
	// NetworkPipe is a Windows named pipe, its DACL granting its owner only.
	NetworkPipe = "pipe"
	// NetworkLocal is NetworkUnix where there is one, NetworkPipe on
	// Windows: what a product declares when it does not care which.
	NetworkLocal = "local"
)

Listener networks.

View Source
const (
	// RetentionOn erases and deletes what is due: the default.
	RetentionOn = "on"
	// RetentionDryRun journals what the retention would do and changes
	// nothing: how a new retention is deployed over old data.
	RetentionDryRun = "dry-run"
	// RetentionOff runs no retention, warned of at every start outside dev.
	RetentionOff = "off"
)

The modes of KIT_RETENTION.

View Source
const (
	GapPurpose   = "purpose"   // no kit.Purpose
	GapRetention = "retention" // no retention, kit's or the product's: its personal data is kept forever
	GapSubject   = "subject"   // no subject field: no person can have their records
)

The gaps a register lists for a store that keeps personal data.

View Source
const (
	// MeasureRedacted: the Studio, the spans and the logs never show a
	// personal, special or secret value.
	MeasureRedacted = "redacted"
	// MeasureHolds: a legal hold stops erasure and deletion.
	MeasureHolds = "legal-holds"
	// MeasureJournal: every export, erasure, deletion and hold is journaled,
	// each entry chained to the previous one by SHA-256.
	MeasureJournal = "journal"
	// MeasureNotSealed: the store's classified members are in clear: it is
	// kept in memory, where nothing is at rest, or its members are plain.
	MeasureNotSealed = "not-sealed"
	// MeasureSealed: its classified members are sealed at rest, AES-256-GCM
	// under per-subject data keys a person's erasure destroys (ADR 0006 §4).
	MeasureSealed = "sealed"
)

The security measures a register lists (point g).

View Source
const (
	JournalExport      = "export"       // a person's records exported
	JournalRead        = "read"         // a record read by a module, through kit.Records
	JournalErase       = "erase"        // a record's personal data cleared
	JournalDelete      = "delete"       // a record removed
	JournalEraseFields = "erase-fields" // some fields of a record cleared, by a module
	JournalHold        = "hold"         // a hold placed on a record
	JournalRelease     = "release"      // a hold lifted
	JournalShred       = "shred"        // a subject's data key destroyed (ADR 0006, step 3)
)

The operations of the privacy journal.

View Source
const (
	ProfileCPU  = "cpu"  // where CPU time went, sampled for a duration
	ProfileHeap = "heap" // where the live heap was allocated
)

Profile kinds.

View Source
const (
	PhaseStarting = "starting"
	PhaseServing  = "serving"
	PhaseDraining = "draining"
	PhaseStopped  = "stopped"
	PhaseFailed   = "failed"
)

Process phases, in the order a process goes through them.

View Source
const (
	// DatabaseUnset: no URL, in dev. Its stores stay in the data directory
	// and nothing is opened.
	DatabaseUnset = "unset"
	// DatabaseMemory: the app keeps its data in memory (kit.InMemory):
	// nothing is opened, no URL is read.
	DatabaseMemory = "memory"
	// DatabaseOpen: the pool is open, its migrations ran, it answered its
	// check at start.
	DatabaseOpen = "open"
	// DatabaseFailed: the start could not open it, migrate it or reach it.
	DatabaseFailed = "failed"
	// DatabaseClosed: not opened yet, or closed by the stop.
	DatabaseClosed = "closed"
)

Database states.

View Source
const (
	SettingEnv     = "env"     // an environment variable
	SettingOption  = "option"  // the product's code: an AppOption
	SettingDefault = "default" // kit's default for the environment
	SettingStore   = "store"   // the environment's secret store (a secret)
	SettingKitDev  = "kitdev"  // kit dev set the variable, for this launch
	SettingFile    = "file"    // a configuration file of the product (Detail)
)

Where a setting's value comes from.

View Source
const (
	VarEnv          = "KIT_ENV"
	VarAddr         = "KIT_ADDR"
	VarDataDir      = "KIT_DATA_DIR"
	VarStudio       = "KIT_STUDIO"
	VarStudioRemote = "KIT_STUDIO_REMOTE"
	VarAnalyze      = "KIT_ANALYZE"
	VarTrustProxy   = "KIT_TRUST_PROXY"
	VarAllowedHosts = "KIT_ALLOWED_HOSTS"
	VarLogLevel     = "KIT_LOG_LEVEL"
	VarSMTPURL      = "KIT_SMTP_URL"
	// VarRetention sets what the stores' retention loops do: on, dry-run
	// or off (ADR 0006).
	VarRetention = "KIT_RETENTION"
	// VarDevForced is how kit dev tells the product which of the variables
	// above it set itself for this launch: their origin is kit dev.
	VarDevForced = "KIT_DEV_FORCED"
)

The settings kit reads, by the environment variable that sets each: kit's configuration reads them, the connectors and the architecture name them.

View Source
const (
	BootConfig       = "config"       // the environment and the options, read
	BootDeclarations = "declarations" // what the services declare, checked
	BootMount        = "mount"        // the services bound to the app
	BootRoutes       = "routes"       // the routes of endpoints and frontends
	BootData         = "data"         // the data directory, opened
	BootHandler      = "handler"      // health, the Studio, protection, observation
	BootComponents   = "components"   // the lifecycle components, started in order
	BootServing      = "serving"      // ready: the phase is serving
)

Boot steps, in the order kit takes them.

View Source
const (
	ComponentPending  = "pending"
	ComponentStarting = "starting"
	ComponentUp       = "up"
	ComponentStopping = "stopping"
	ComponentDown     = "down"
	ComponentFailed   = "failed"
)

Component states.

View Source
const (
	LoopJob       = "job"       // a job, fired by the scheduler
	LoopTimer     = "timer"     // a workflow's own loop: its timers and guards, when due
	LoopConsumer  = "consumer"  // a subscription's consumer, a queued command's, or a mailer's outbox
	LoopHTTP      = "http"      // the HTTP server's accept loop
	LoopScheduler = "scheduler" // the scheduler's own loop, which fires the jobs
	LoopWake      = "wake"      // a declared loop's wake cycle (Service.Loop)
	LoopRoutine   = "goroutine" // a hand-written loop (Service.Go)
	LoopRotation  = "rotation"  // a generated secret's rotation, on its schedule
	LoopRetention = "retention" // a store's retention: erases and deletes what is due (ADR 0006)
)

Loop kinds.

View Source
const (
	// ProvenanceLibrary loops are written by a library: net/http's accept
	// loop, the SDK scheduler, the SDK queue consumer.
	ProvenanceLibrary = "library"
	// ProvenanceKit loops are written by kit for a declaration: a workflow's
	// sweep, a declared loop's wake cycle.
	ProvenanceKit = "kit"
	// ProvenanceProduct loops are written by hand in the product: Service.Go.
	ProvenanceProduct = "product"
)

Loop provenances: who wrote the code that loops.

View Source
const (
	LoopWaiting    = "waiting"    // blocked until its next wake
	LoopRunning    = "running"    // doing a run
	LoopRestarting = "restarting" // failed, waiting out its backoff
	LoopStopped    = "stopped"
)

Loop states.

View Source
const (
	OpRequest     = "request"      // an HTTP request served by an endpoint
	OpCall        = "call"         // an in-process call of an endpoint, or of a port
	OpRead        = "read"         // a store read
	OpWrite       = "write"        // a store write
	OpPublish     = "publish"      // a topic publish
	OpDeliver     = "deliver"      // a subscription handling one message
	OpTransition  = "transition"   // a workflow transition
	OpRun         = "run"          // a job run, a loop run
	OpAuth        = "auth"         // the auth handler, in front of an endpoint
	OpSend        = "send"         // a mail put in the outbox
	OpDeliverMail = "deliver-mail" // the outbox handing one mail to the transport
	OpSecret      = "secret"       // a secret's value or keys used: Value, Seal, Open, Sign, Verify
	OpDispatch    = "dispatch"     // a command dispatched: its run, or its queuing for a queued one
	OpAsk         = "ask"          // a query asked
	OpHandle      = "handle"       // a queued command handled by its consumer, in the dispatcher's trace
	OpConnect     = "connect"      // a connection a listener accepted, handled until it closes
	OpCLI         = "cli"          // a short command-line command, run once
	// OpTransaction is a unit of work (kit.Transact, a command's, a
	// workflow's transition): its attrs say the database it belongs to —
	// "database", and "backend" as a store says it —, its "outcome", the
	// effects it held ("effects"), and "savepoint" for one nested in
	// another.
	OpTransaction = "transaction"
)

Span operations.

View Source
const (
	// OutcomeCommit is a transaction that committed: its effects left.
	OutcomeCommit = "commit"
	// OutcomeRollback is a transaction whose writes were undone: its effects
	// were dropped.
	OutcomeRollback = "rollback"
)

The outcomes of a transaction, as its span's "outcome" attribute says them.

View Source
const (
	StatusOK    = "ok"
	StatusError = "error"
)

Span statuses.

View Source
const CodeInvalidID errs.Code = 0x00_04_01_01 // 0.4.1.1

CodeInvalidID identifies an ID the grammar of IDPattern does not match.

View Source
const ExternalID = "external"

ExternalID is the id of the node standing for the outside world.

View Source
const MaxTableLen int = 58

MaxTableLen is the longest table name a store on a database takes, in bytes: the SDK's document store over SQL keeps its index rows in the table named after it with "___ix", within PostgreSQL's 63.

View Source
const MockReplace = "replace"

MockReplace is the one mode a MockMessage has: a test's kit.Replace, a typed function run in place of an operation's handler — or of what a port calls — while the rest of its pipeline still runs. The Studio sets none (D13): it shows the application, it does not act on it, so the respond, fail and delay modes of the platform's kit have no representation here.

View Source
const (
	// PortOwnerKit is kit's own listener: the health probes, the Studio in
	// dev, and the product's HTTP when it declares any.
	PortOwnerKit = "kit"
)

Whose a port is.

View Source
const SealedPlaceholder = "[sealed]"

SealedPlaceholder is what the Studio receives in place of a value kit keeps sealed at rest — a record's member in the data browser, a former value —: never the value, nor its box (ADR 0006 §9). A value it opens and may not show is "[redacted]".

View Source
const Version int = 5

Version is the schema version of every document in this package.

Version 2 adds the auth, mailer and loop kinds, the sends and wakes edges, the code level of every node (CodeResult), the C4 context and containers (ArchitectureMessage) and the daemon's own machinery (RuntimeMessage).

Version 3 adds the secret kind (SecretSpec), the uses edge, the secret span operation, the rotation loop and the store origin of a setting.

Version 4 is the one bump the decisions of issue #17 share. It adds the port kind (PortSpec) and its binding, a declared edge from the port to what it calls; the endpoint that implements a port (EndpointSpec.Implements), which has no method and no path; and the replace mock mode (MockReplace). ADR 0004 adds the databases: the store's database (StoreSpec.Database), the database container, the database connector and its adapters, RuntimeMessage.Databases and SettingMessage.Database. ADR 0008 adds the modules the app mounts (GraphMessage.Modules), the module of a node (NodeEntity.Module) and the Go module of a position outside the product's (SourceMessage.GoModule); and the watch, a subscription fed by stores: its mark and the stores that feed it (SubscriptionSpec.Mark, SubscriptionSpec.Stores), each drawing a declared delivers edge to it. ADR 0005 adds the command and query kinds (CommandSpec, QuerySpec), the dispatches and asks edges, the endpoint that exposes one (EndpointSpec.Exposes), the read model (StoreSpec.ReadModel), the dispatch, ask and handle span operations and the dispatch and ask controls.

Version 5 is the first the SDK's framework publishes (ADR 0147). It adds what a product is made of beyond its services: the binary (KindBinary) and its process roles (KindRole), the short CLI command (KindCLI), the listener that is not HTTP (KindListener), the library shared between components (KindLibrary) and the presentation (KindPresentation); the edge between two roles of a product, which carries a versioned contract (EdgeContracts, EdgeMessage.Contract); and the grammar every ID follows, written once (IDValue, ParseID). It removes what the Studio no longer does (D13): the respond, fail and delay mock modes, the control event and its payload — a MockMessage is a test's replacement only.

Variables

View Source
var (
	// IDPattern is the whole grammar as one regular expression, anchored —
	// the one the design files' JSON Schema publishes for an ID. Only an
	// endpoint may be named by its route.
	IDPattern string = `^(?:external` +
		`|(?:` + SegmentPattern + `\.)?` + SegmentPattern +
		`(?:/(?:` + kindAlternatives() + `)/` + NamePattern + `|/endpoint/` + RoutePattern + `)?` +
		`|binary:` + SegmentPattern + `(?:/role/` + SegmentPattern + `)?` +
		`|library:` + SegmentPattern + `)$`
)
View Source
var InvalidID = errs.Define(CodeInvalidID, "INVALID_ID",
	"The node identifier is not valid",
	"framework/model.ParseID: the input does not match IDPattern; the part field names the failing component",
	errs.WithHTTPStatus(http.StatusBadRequest))

InvalidID is returned by ParseID for a string the ID grammar does not match. Its "part" field names what failed — the kind, the service name, the node name —, never the input.

Functions

func BinaryID

func BinaryID(binary string) string

BinaryID is the ID of a binary.

func CompareSource

func CompareSource(a, b SourceMessage) int

CompareSource orders sources by root, file, then line.

func EdgeID

func EdgeID(from string, kind EdgeKind, to, label string) string

EdgeID builds the ID of an edge. The label is part of the identity: two transitions of one workflow fired from one endpoint are two edges.

func IsEngine

func IsEngine(backend string) bool

IsEngine reports whether backend names an engine a database runs on.

func LibraryID

func LibraryID(library string) string

LibraryID is the ID of a library.

func Mermaid

func Mermaid(g *GraphMessage) string

Mermaid renders the architecture of a graph as a Mermaid flowchart: one subgraph per service — a module's inside the module's own, ADR 0008 —, one arrow per edge. GitHub renders it in Markdown, which makes a product's README carry its own, always regenerable, diagram.

Each kind has its shape: an endpoint a box (marked "auth" when it asks for a user; an implementation of a port by its name), a store a cylinder, a topic a flag, a subscription a parallelogram (a watch, ADR 0008, marked with the mark it watches — its stores' arrows say where from), a workflow a hexagon, a job a stadium, the auth handler a trapezoid — a gate —, a mailer a subroutine box, a declared loop a circle, a hand-written loop a double circle, a port an inverted trapezoid — a socket, UML's required interface —, a command a parallelogram leaning back — a subscription's leans forward —, marked "queued" when it waits in its queue, and a query a rhombus, a question. An arrow is solid when it exists by construction or was observed, dotted when only the code says so — or when it is a port's binding to its own fallback, the default the app may replace, as the Studio draws it.

func ModulePrefix

func ModulePrefix(name string) string

ModulePrefix is a module's default mount prefix: "/<name>/".

func NodeID

func NodeID(service string, kind NodeKind, name string) string

NodeID builds the ID of a node declared in a service. A service's own ID is its name.

func QualifiedService

func QualifiedService(module, service string) string

QualifiedService is the name a module gives a service it lists: the module's own name for the service named like it, "<module>.<service>" otherwise. The runtime and the analyzer both qualify with it.

func RoleID

func RoleID(binary, role string) string

RoleID is the ID of one process role of a binary.

func ServiceOf

func ServiceOf(id string) string

ServiceOf returns the service part of a node ID.

func SplitDoc

func SplitDoc(text string) (string, map[string]string)

SplitDoc splits a description into its default text and its translations.

A product documents a building block once, in Go, in its default language; a paragraph that starts with a language tag and a colon — "fr: Le cycle de vie d'un compte…" — is the same description in that language, until the next tag or the end:

// AccountLifecycle is the life of an account…
//
// fr: AccountLifecycle est la vie d'un compte…

It keeps Go's convention (the comment still starts with the name) and go doc prints both. Each text is joined into one line. A description whose only tagged paragraph is "en" uses it as the default.

func TableName

func TableName(service, node, suffix string) string

TableName is the table a database keeps a kit table in (ADR 0004): the service's name — qualified, for a module's —, two underscores and the node's name, then suffix, '-' and '.' written '_', lower case — "moderation.intake"'s store "cases" is moderation_intake__cases. A name the rule cannot keep as it is — upper case, longer than MaxTableLen, three underscores in a row, SQLite's own prefix — is cut and ends with a digest of the whole, so it stays one table's. The runtime and the analyzer name tables with it.

func UnderPrefix

func UnderPrefix(prefix, path string) string

UnderPrefix is a route declared at path, served under a module's mount prefix: "/reports" under "/moderation/" is "/moderation/reports", and under "/" it stays "/reports".

func ValidContract

func ValidContract(s string) bool

ValidContract reports whether s names a versioned contract: "render/v1".

func ValidName

func ValidName(s string) bool

ValidName reports whether s is a legal node name. An endpoint named by its route is legal as an ID but is not a name a declaration may give.

func ValidSegment

func ValidSegment(s string) bool

ValidSegment reports whether s is a legal service, module, binary, role or library name.

Types

type AdapterMessage

type AdapterMessage struct {
	// ID names it as the graph does: "postgres".
	ID string `json:"id"`
	// Name is what a reader calls what it reaches: "PostgreSQL".
	Name string `json:"name"`
	// Import is the package the product's main imports:
	// "github.com/kitsunium/sdk/framework/connectors/postgres".
	Import string `json:"import"`
	// Driver is the Go driver it links: "github.com/jackc/pgx/v5".
	Driver string `json:"driver,omitempty"`
}

AdapterMessage is a module a connector plugs a product in through: an engine, imported by the product's main to reach a database, and the only code of the product that imports its driver.

type AnalysisResult

type AnalysisResult struct {
	// Status is "pending", "running", "ok", "failed" or "unavailable".
	Status string `json:"status"`
	// Error explains a failed or unavailable analysis.
	Error string `json:"error,omitempty"`
	// At is when the analysis finished.
	At *time.Time `json:"at,omitempty"`
	// Packages is how many packages were analyzed.
	Packages int `json:"packages,omitempty"`
	// TookMs is how long it took.
	TookMs float64 `json:"tookMs,omitempty"`
}

AnalysisResult reports the status of static analysis. It says whether the analyzer ran, how long it took, and the error that stopped it.

type AppMessage

type AppMessage struct {
	// Name is the product name given to kit.NewApp.
	Name string `json:"name"`
	// Module is the Go module path of the product.
	Module string `json:"module,omitempty"`
	// Root is the absolute module root on the machine that produced the
	// graph. Present in dev only: it is what an editor link needs, and what a
	// production graph must not leak.
	Root string `json:"root,omitempty"`
	// Env is "dev" or "production".
	Env string `json:"env,omitempty"`
	// Kit is the kit version that produced the graph.
	Kit string `json:"kit,omitempty"`
	// Go is the Go version the product was built with.
	Go string `json:"go,omitempty"`
	// StartedAt is when the process started, for a runtime graph.
	StartedAt *time.Time `json:"startedAt,omitempty"`
	// Build says what the binary was built from: the product, kit and the
	// SDK kit depends on.
	Build *BuildMessage `json:"build,omitempty"`
}

AppMessage identifies the product and the machine that described it. It names the module, the environment and the build the graph was taken from.

type ArchitectureMessage

type ArchitectureMessage struct {
	// People are the humans the product serves.
	People []PersonMessage `json:"people"`
	// Systems are the software systems outside the product it talks to, or
	// that talk to it.
	Systems []SystemMessage `json:"systems"`
	// Containers are the product's runnable and storage units.
	Containers []ContainerMessage `json:"containers"`
	// Links are the relationships between people, systems and containers.
	Links []LinkMessage `json:"links"`
}

ArchitectureMessage is the product at the two outer levels of the C4 model.

Context (level 1) is the product as one box, the people who use it and the systems it depends on. Containers (level 2) is what the product is deployed as: the process, the frontend its browser runs, the volume its data lives on. Components (level 3) are the nodes, grouped by service; code (level 4) is each node's CodeResult.

kit derives all of it from the declarations — a frontend implies a person with a browser, a mailer an SMTP relay, a data directory a volume, a database its own container — so it is exactly as true as the rest of the graph.

type AuthSpec

type AuthSpec struct {
	// Credentials is the type the handler reads: its fields are tagged
	// cookie:"…" or header:"…".
	Credentials *SchemaMessage `json:"credentials,omitempty"`
	// Data is the type of what the handler says about the caller, which
	// endpoints read with kit.AuthData.
	Data *SchemaMessage `json:"data,omitempty"`
	// Endpoints counts the endpoints that ask for authentication.
	Endpoints int `json:"endpoints"`
}

AuthSpec describes the app's authentication handler. Credentials says what it reads from a request; Endpoints are the ones behind it.

type BinarySpec

type BinarySpec struct {
	// Package is the Go package of its main.
	Package string `json:"package,omitempty"`
	// Roles are the IDs of its process roles, in declaration order; the
	// first is the one it runs with no role argument.
	Roles []string `json:"roles"`
}

BinarySpec is one executable the product ships: the NodeEntity.Binary of a KindBinary node, naming its roles.

type BootStepMessage

type BootStepMessage struct {
	// Name is one of the Boot constants.
	Name string `json:"name"`
	// Count is how many it went through: settings, warnings, services,
	// routes, components.
	Count int `json:"count,omitempty"`
	// Value is what it used: the data directory, in dev.
	Value string `json:"value,omitempty"`
	// Begun is when it began.
	Begun time.Time `json:"begun"`
	// TookMs is how long it took.
	TookMs float64 `json:"tookMs"`
	// Error is the public message of a failure.
	Error string `json:"error,omitempty"`
}

BootStepMessage is one step of the start, as it ran. It carries when it began, how long it took and, when it failed, its error.

type BuildMessage

type BuildMessage struct {
	// Product is the product's own module.
	Product ModuleVersionMessage `json:"product"`
	// Kit is the framework: since ADR 0162 the SDK module,
	// github.com/kitsunium/sdk, which holds it.
	Kit ModuleVersionMessage `json:"kit"`
	// SDK is the SDK the framework is built on — the same module as Kit
	// since ADR 0162, so the two say the same version.
	SDK ModuleVersionMessage `json:"sdk"`
}

BuildMessage is what a binary was built from, at its three levels. Its three levels are the Go toolchain, the main module and the modules it depends on.

type CLISpec

type CLISpec struct {
	// Path is the command's words after the binary's name: ["status"],
	// ["daemon", "stop"].
	Path []string `json:"path"`
	// Role is the ID of the role that runs it.
	Role string `json:"role,omitempty"`
}

CLISpec is a short command-line command: the NodeEntity.CLI of a KindCLI node, the words that run it.

type CensusMessage

type CensusMessage struct {
	// Workflow is the workflow node ID.
	Workflow string `json:"workflow"`
	// Counts maps each state to its number of instances.
	Counts map[string]int `json:"counts"`
}

CensusMessage is a workflow's population per state. It counts the instances in each state when the census was taken.

type CodeBlockMessage

type CodeBlockMessage struct {
	// Kind is one of the Block constants.
	Kind string `json:"kind"`
	// Label is the condition or the clause, as written: "err != nil",
	// `case "done"`, "range ids"; bounded.
	Label string `json:"label,omitempty"`
	// Line is the 1-based line where the block starts.
	Line int `json:"line"`
	// Group is the line of the statement the block is a branch of: an
	// if/else chain, a switch, a select. Blocks with one group are its
	// alternatives.
	Group int `json:"group,omitempty"`
	// Parent is the enclosing block: its index in Blocks, plus one; 0 for
	// the function's body.
	Parent int `json:"parent,omitempty"`
}

CodeBlockMessage is a block of a function that decides whether, or how many times, the steps under it run.

type CodeEffectMessage

type CodeEffectMessage struct {
	// Kind is the edge the call makes: reads, writes, publishes…
	Kind EdgeKind `json:"kind"`
	// Target is the node the call reaches.
	Target string `json:"target"`
	// Label refines Kind like an edge's label: the event of a transition.
	Label string `json:"label,omitempty"`
	// Op is the method called: "Get", "Insert", "Fire", "Send".
	Op string `json:"op"`
	// Line is the 1-based line of the call, in the function's file.
	Line int `json:"line"`
}

CodeEffectMessage is one call on a building block, inside a function. It names the node it reaches and the edge kind that call draws.

type CodeFuncMessage

type CodeFuncMessage struct {
	// Func is the qualified name: "github.com/kitsunium/todo/tasks.Create".
	Func string `json:"func"`
	// Name is the short name a developer reads: "Create", "(*Store).visible".
	Name string `json:"name"`
	// Source is the function's range.
	Source *SourceMessage `json:"source,omitempty"`
	// Calls are the qualified names of the module functions it calls, in
	// source order, deduplicated.
	Calls []string `json:"calls,omitempty"`
	// Effects are its calls on building blocks, in source order.
	Effects []CodeEffectMessage `json:"effects,omitempty"`
	// Steps are what it does, in the order it does it: its calls to module
	// functions, on building blocks and into the SDK, arguments before the
	// call they are passed to. A sequence diagram is drawn from them.
	Steps []CodeStepMessage `json:"steps,omitempty"`
	// Blocks are its blocks that decide whether, or how many times, the
	// steps under them run: an if's branches, a switch's cases, a loop.
	Blocks []CodeBlockMessage `json:"blocks,omitempty"`
}

CodeFuncMessage is one function of the module a node's code reaches. Its steps are listed in the order they run, under the blocks that guard them.

type CodeResult

type CodeResult struct {
	// Entry is the qualified name of the function the node runs first.
	Entry string `json:"entry,omitempty"`
	// Funcs are the module's functions reachable from the entry, entry
	// first, then in the order the walk met them.
	Funcs []CodeFuncMessage `json:"funcs,omitempty"`
	// Uses are the SDK functions the code calls: the mechanics it composes
	// rather than implements.
	Uses []CodeUseMessage `json:"uses,omitempty"`
	// Truncated is set when the walk stopped at its depth or size bound.
	Truncated bool `json:"truncated,omitempty"`
}

CodeResult is the code a node runs, as the static analysis read it: the fourth and innermost level of the C4 model. The entry is the function the node runs — an endpoint's handler, a subscription's, a loop's — and Funcs are the functions of the module it reaches, each with what it calls and what it does to other nodes.

type CodeStepMessage

type CodeStepMessage struct {
	// Line is the 1-based line of the call, in the function's file.
	Line int `json:"line"`
	// Call is the qualified name of the module function it calls.
	Call string `json:"call,omitempty"`
	// Effect is its call on a building block: the index in Effects, plus one.
	Effect int `json:"effect,omitempty"`
	// Use is the SDK function it calls, from the SDK's version directory:
	// "crypto/password.Hash".
	Use string `json:"use,omitempty"`
	// Block is the innermost block guarding it: the index in Blocks, plus
	// one; 0 for the function's body.
	Block int `json:"block,omitempty"`
}

CodeStepMessage is one thing a function does: a call to another function of the module, a call on a building block, or a call into the SDK — under the innermost block that guards it.

type CodeUseMessage

type CodeUseMessage struct {
	// Package is the SDK package: "github.com/kitsunium/sdk/pkg/v1/crypto/password".
	Package string `json:"package"`
	// Func is the function or method: "Hash", "(*Composer).Compose".
	Func string `json:"func"`
	// Sites are the call sites, sorted.
	Sites []SourceMessage `json:"sites,omitempty"`
}

CodeUseMessage is one SDK function a node's code calls. Sites are where the node's code calls it, so a reader sees what it leans on.

type CommandSpec

type CommandSpec struct {
	// Input is the type it is dispatched with.
	Input *SchemaMessage `json:"input,omitempty"`
	// Result is the type it answers; Empty for a queued command.
	Result *SchemaMessage `json:"result,omitempty"`
	// Mode is [ModeSync] or [ModeQueued].
	Mode string `json:"mode"`
	// Auth is [AuthRequired] — implied by a permission —, [AuthOptional],
	// or empty when the command ignores authentication.
	Auth string `json:"auth,omitempty"`
	// Pipeline lists the mechanics a dispatch goes through before the
	// handler, in the order they run.
	Pipeline []MechanicMessage `json:"pipeline,omitempty"`
	// Permissions are the permissions a caller needs (Allow).
	Permissions []PermissionMessage `json:"permissions,omitempty"`
	// Authorize locates the function of its Authorize: a rule that needs
	// the data.
	Authorize *SourceMessage `json:"authorize,omitempty"`
	// Key is set when the command names the entity it is about (Key): two
	// runs with one key never overlap.
	Key bool `json:"key,omitempty"`
	// MaxDeliveries is how many attempts a queued command gets before it is
	// dead-lettered.
	MaxDeliveries int `json:"maxDeliveries,omitempty"`
	// Parallelism is how many dispatches of a queued command are handled at
	// once.
	Parallelism int `json:"parallelism,omitempty"`
	// Queue is "memory" or "file": where a queued command waits.
	Queue string `json:"queue,omitempty"`
	// DeadLetters is how many dispatches of a queued command were
	// abandoned, on a runtime graph.
	DeadLetters *int `json:"deadLetters,omitempty"`
}

CommandSpec describes a command: an operation that changes something. It carries its input and result schemas, its handler, its queue and who may dispatch it.

type ComponentMessage

type ComponentMessage struct {
	// Name is the lifecycle name: "store:todos/store/todos", "http"…
	Name string `json:"name"`
	// Node is the node the component belongs to, when there is one.
	Node string `json:"node,omitempty"`
	// State is one of the Component constants.
	State string `json:"state"`
	// Begun is when the last start or stop call began.
	Begun *time.Time `json:"begun,omitempty"`
	// TookMs is how long that call took.
	TookMs float64 `json:"tookMs,omitempty"`
	// Error is the public message of a failure.
	Error string `json:"error,omitempty"`
}

ComponentMessage is one lifecycle component: brought up in order, taken down in reverse.

type ConnectorKind

type ConnectorKind string

ConnectorKind groups connectors by what they are for.

const (
	// ConnectorTransport is how the product is reached: HTTP.
	ConnectorTransport ConnectorKind = "transport"
	// ConnectorMessaging is what it sends and receives: mail, queues.
	ConnectorMessaging ConnectorKind = "messaging"
	// ConnectorData is where it keeps its data: stores, databases.
	ConnectorData ConnectorKind = "data"
)

The kinds of connectors.

type ConnectorMessage

type ConnectorMessage struct {
	// ID names the connector: [ConnectorHTTP], [ConnectorMail],
	// [ConnectorStore], [ConnectorQueue], [ConnectorDatabase].
	ID string `json:"id"`
	// Kind groups connectors by what they are for; kept for older readers,
	// Roles says more.
	Kind ConnectorKind `json:"kind"`
	// Roles place it against the process boundary: [RoleInbound] (the
	// product is reached through it), [RoleOutbound] (the product reaches out
	// through it), [RoleStorage] (the product keeps data in it). kit's
	// built-in queues run inside the process: storage only.
	Roles []string `json:"roles,omitempty"`
	// Protocol is the wire protocol the code fixes, when it does: "http".
	Protocol string `json:"protocol,omitempty"`
	// Detail is what the product uses, in kit's words: the stores'
	// backends, the mail transport, the queues' brokers.
	Detail string `json:"detail,omitempty"`
	// Settings are the settings the connector owns — the ones its page shows
	// with their value. A setting of a resource it uses (the data directory,
	// kit's port) belongs to that resource: [ContainerMessage].
	Settings []string `json:"settings,omitempty"`
	// Nodes are the nodes the connector brings to the graph, sorted.
	Nodes []string `json:"nodes"`
}

ConnectorMessage is something a product plugs into, as the product declares it: how it is reached, what it reaches out to, where it keeps its data. The Studio shows a connector's pages and widgets only when the product has one: a command-line tool has no requests to list, a service without a mailer no mailbox.

A connector says what the code declares, never what an environment supplies. The relay a mailer delivers through, the directory a store writes to, the address kit listens on are facts of the running environment — MailerSpec, StoreSpec, the ArchitectureMessage and RuntimeMessage carry those. So a connector is a pure function of the nodes (ConnectorsOf), and never moves a graph's revision.

func ConnectorsOf

func ConnectorsOf(nodes []NodeEntity) []ConnectorMessage

ConnectorsOf derives the connectors a product uses from its nodes: an endpoint, a frontend or an auth handler means HTTP, a mailer mail, a store stores — and a database when one keeps it —, a topic, a subscription or a queued command queues. Sorted by ID.

type ConnectorSpec

type ConnectorSpec struct {
	// ID is the connector's: [ConnectorHTTP]…
	ID string `json:"id"`
	// Kind groups it, as [ConnectorMessage.Kind].
	Kind ConnectorKind `json:"kind"`
	// Roles place it against the process boundary.
	Roles []string `json:"roles"`
	// Protocol is the wire protocol the code fixes, when it does.
	Protocol string `json:"protocol,omitempty"`
	// Settings are the settings it owns.
	Settings []string `json:"settings,omitempty"`
	// Declares are the building blocks whose declaration brings it: a
	// command brings the queue connector only when it is queued.
	Declares []NodeKind `json:"declares"`
	// Adapters are the modules a product imports to plug it into what it
	// reaches: the engines of the database connector.
	Adapters []AdapterMessage `json:"adapters,omitempty"`
	// contains filtered or unexported fields
}

ConnectorSpec is a connector kit can plug a product into, whether the product uses it or not: what it is, and the building blocks that bring it.

func ConnectorCatalog

func ConnectorCatalog() []ConnectorSpec

ConnectorCatalog is every connector kit ships, sorted by ID: what a product may plug into.

type ContainerMessage

type ContainerMessage struct {
	// ID is unique in the architecture: "container:process".
	ID string `json:"id"`
	// Name is what the diagram prints.
	Name string `json:"name"`
	// Kind is one of the Container constants.
	Kind string `json:"kind"`
	// Technology names what it is built with: "Go 1.27 · kit · net/http".
	Technology string `json:"technology,omitempty"`
	// Doc says what it does.
	Doc string `json:"doc,omitempty"`
	// Location is where it runs or lives: the listen address, the data
	// directory. Present in dev only.
	Location string `json:"location,omitempty"`
	// Nodes are the nodes it hosts: services for the process, stores and
	// subscriptions for the volume, frontends for an SPA.
	Nodes []string `json:"nodes,omitempty"`
	// Ports are what the process listens on, and whose each port is.
	Ports []PortMessage `json:"ports,omitempty"`
	// Settings are the settings that configure it: KIT_DATA_DIR for the
	// data directory; a database's URL and tuning variables for a database.
	Settings []string `json:"settings,omitempty"`
	// Engine is a database's engine: "postgres", "mysql", "sqlite".
	Engine string `json:"engine,omitempty"`
	// Source is where the code declares the container, when it does: the
	// app for the process, a frontend for its SPA, kit.Database for a
	// database. [GraphMessage.Files] allows it.
	Source *SourceMessage `json:"source,omitempty"`
}

ContainerMessage is one runnable or storage unit of the product. Its ID starts with "container:"; Nodes are the nodes that live in it.

type DatabaseMessage

type DatabaseMessage struct {
	// Name is the database's, as the app declares it.
	Name string `json:"name"`
	// Engine is the engine it runs on: "postgres", "mysql", "sqlite".
	Engine string `json:"engine"`
	// State is one of the Database constants.
	State string `json:"state"`
	// Ready says whether it answered its last check; CheckedAt says when.
	Ready     bool       `json:"ready"`
	CheckedAt *time.Time `json:"checkedAt,omitempty"`
	// Problem is the public text of its last failure: a start that failed,
	// a check it did not answer.
	Problem string `json:"problem,omitempty"`
	// URLFrom is where its URL was found — a Setting constant: env, store,
	// or default for a SQLite file beside the data —, empty when it is set
	// nowhere.
	URLFrom string `json:"urlFrom,omitempty"`
	// TLS is the TLS mode its URL writes: "verify-full"; "none" when it is
	// written off; empty when the URL leaves it to the driver, or when the
	// database is a file.
	TLS string `json:"tls,omitempty"`
	// Pool is database/sql's own count of its connections, sampled when the
	// graph was built.
	Pool *Pool `json:"pool,omitempty"`
	// Migrations are its sets of migrations, kit's first, as the start —
	// or the last sample — found them.
	Migrations []MigrationSetMessage `json:"migrations,omitempty"`
}

DatabaseMessage is one database the app declares (kit.Database), as the running process found it. Its URL is never shown: where it was found, the engine, the address and the TLS mode are.

type DevBuildMessage

type DevBuildMessage struct {
	// BuiltAt is when the build finished.
	BuiltAt *time.Time `json:"builtAt,omitempty"`
	// BuildMs is how long it took.
	BuildMs float64 `json:"buildMs,omitempty"`
	// Rebuilds counts the builds of this kit dev session, this one
	// included: 1 is the first start.
	Rebuilds int `json:"rebuilds,omitempty"`
	// Changed are the files whose change triggered this build, relative to
	// the module root, at most 20.
	Changed []string `json:"changed,omitempty"`
	// More counts the changed files beyond Changed.
	More int `json:"more,omitempty"`
}

DevBuildMessage is one build of `kit dev`: when, how long, and why. It lets the Studio say what changed and how long the reload took.

type DiagnosticMessage

type DiagnosticMessage struct {
	// Severity is "error" or "warning". An error refuses to start the app.
	Severity string `json:"severity"`
	// Message says what is wrong and how to fix it, in English.
	Message string `json:"message"`
	// Texts is the message in each language kit speaks, by language: "en",
	// "fr". The Studio shows its reader's.
	Texts map[string]string `json:"texts,omitempty"`
	// Node is the node concerned, when there is one.
	Node string `json:"node,omitempty"`
	// Source is where the problem is.
	Source *SourceMessage `json:"source,omitempty"`
}

DiagnosticMessage is a problem found while building the graph. It names the node or the file it is about, and how serious it is.

type EdgeKind

type EdgeKind string

EdgeKind says how two nodes relate. It is a wire format — the graph's JSON and the Studio's TypeScript unions carry these names —, so it stays a string.

const (
	// EdgeCalls targets an endpoint or a port. From a port, it is the port's
	// binding — what the port calls — and it is declared.
	EdgeCalls EdgeKind = "calls"
	// EdgeReads targets a store the source reads from.
	EdgeReads EdgeKind = "reads"
	// EdgeWrites targets a store the source writes to.
	EdgeWrites EdgeKind = "writes"
	// EdgePublishes targets a topic.
	EdgePublishes EdgeKind = "publishes"
	// EdgeDelivers goes from a topic to each of its subscriptions, and from a
	// store to each watch it feeds (ADR 0008). Declared.
	EdgeDelivers EdgeKind = "delivers"
	// EdgeTransitions targets a workflow; Label carries the event.
	EdgeTransitions EdgeKind = "transitions"
	// EdgePersists goes from a workflow to the store it lives in. Declared.
	EdgePersists EdgeKind = "persists"
	// EdgeSends targets a mailer: the source puts a message in its outbox.
	EdgeSends EdgeKind = "sends"
	// EdgeWakes goes from a topic to a declared loop it wakes. Declared.
	EdgeWakes EdgeKind = "wakes"
	// EdgeUses targets a secret whose value or keys the source uses.
	EdgeUses EdgeKind = "uses"
	// EdgeDispatches targets a command: the source dispatches it. From an
	// endpoint that exposes the command, or from a port bound to it, it is
	// declared.
	EdgeDispatches EdgeKind = "dispatches"
	// EdgeAsks targets a query: the source asks it. From an endpoint that
	// exposes the query, or from a port bound to it, it is declared.
	EdgeAsks EdgeKind = "asks"
	// EdgeContracts goes from one process role to another it talks to —
	// through a socket, a pipe, a command line —, and names the versioned
	// contract they share in [EdgeMessage.Contract]. It is the only edge between two
	// roles (D22). Declared.
	EdgeContracts EdgeKind = "contracts"
	// EdgeRuns goes from a role to what it runs: a CLI command, a listener,
	// an endpoint's server, a loop. Declared.
	EdgeRuns EdgeKind = "runs"
	// EdgeImports goes from a component to a library it may import (D19).
	// Declared.
	EdgeImports EdgeKind = "imports"
	// EdgeRenders goes from a presentation to what it renders. Declared.
	EdgeRenders EdgeKind = "renders"
)

The edge kinds.

type EdgeMessage

type EdgeMessage struct {
	// ID is "<from>|<kind>|<to>" or "<from>|<kind>|<to>|<label>".
	ID string `json:"id"`
	// From is the source node ID.
	From string `json:"from"`
	// To is the target node ID.
	To string `json:"to"`
	// Kind says how the two relate.
	Kind EdgeKind `json:"kind"`
	// Label refines the kind: the event of a transition ("create" for a new
	// instance), or "direct" for a call that bypasses an endpoint.
	Label string `json:"label,omitempty"`
	// Contract names the versioned contract of an [EdgeContracts] edge:
	// "<name>/v<major>", "render/v1".
	Contract string `json:"contract,omitempty"`
	// Declared is set when the edge exists by construction.
	Declared bool `json:"declared,omitempty"`
	// Static lists the call sites the analyzer found, sorted.
	Static []SourceMessage `json:"static,omitempty"`
	// Observed is present once the edge was seen at runtime.
	Observed *StatsMessage `json:"observed,omitempty"`
}

EdgeMessage is one relation, with the evidence for it. Declared, Static and Observed say whether construction, the code or the runtime knows it.

type EditMessage

type EditMessage struct {
	Op   string          `json:"op"`
	Path string          `json:"path"`
	From json.RawMessage `json:"from,omitempty" kit:"personal"`
	To   json.RawMessage `json:"to,omitempty" kit:"personal"`
}

EditMessage is one change between two versions of a record, in RFC 6902's words: Op is add, remove or replace, Path the RFC 6901 JSON pointer of the member it changes, From its value before and To its value after, as JSON. A member whose value is not given — a secret's, or in the Studio a personal or special one — says it changed, never what: From and To are absent.

type EndpointSpec

type EndpointSpec struct {
	// Method is the HTTP method, upper case; empty for an implementation.
	Method string `json:"method"`
	// Path is the route pattern, with {wildcards}; empty for an
	// implementation.
	Path string `json:"path"`
	// Expose is [ExposePublic] or [ExposePrivate].
	Expose string `json:"expose"`
	// Auth is [AuthRequired], [AuthOptional], or empty when the endpoint
	// ignores authentication.
	Auth string `json:"auth,omitempty"`
	// Request is the input type.
	Request *SchemaMessage `json:"request,omitempty"`
	// Response is the output type.
	Response *SchemaMessage `json:"response,omitempty"`
	// Pipeline lists the mechanics a request goes through before the
	// handler, in order.
	Pipeline []MechanicMessage `json:"pipeline,omitempty"`
	// Implements is the node ID of the port this endpoint implements
	// (Service.Implement): an endpoint with no route, reached through the
	// port.
	Implements string `json:"implements,omitempty"`
	// Exposes is the node ID of the command this endpoint dispatches, or of
	// the query it asks (Command.Expose, Query.Expose): its authentication
	// is the operation's, and the rest of its pipeline — validation, key,
	// authorization — the operation's own.
	Exposes string `json:"exposes,omitempty"`
	// Access is how an exposure says its operation is open on purpose —
	// [AccessAnyone] or [AccessAnyUser] —; empty when the operation says who
	// may run it (a permission, a rule), and on any other endpoint.
	Access string `json:"access,omitempty"`
}

EndpointSpec describes an HTTP endpoint, or the implementation of a port. It carries the method and path, the request and response schemas, and its auth.

type ErasureMessage

type ErasureMessage struct {
	// Stores are the stores that kept records about the person.
	Stores []StoreErasureMessage `json:"stores"`
}

ErasureMessage is what kit.Erase did, store by store. Stores lists, store by store, what the erasure did there.

type Event

type Event struct {
	// Seq increases strictly on one stream; a reader drops what it has seen.
	Seq uint64 `json:"seq"`
	// Type selects the payload.
	Type EventType `json:"type"`
	// Time is when it happened.
	Time time.Time `json:"time"`
	// Revision is the graph revision, on hello and graph events.
	Revision string `json:"revision,omitempty"`
	// StartedAt is when the process's current run started, on hello: a new
	// value means the process restarted, and what the reader knew of the
	// previous run is stale.
	StartedAt *time.Time `json:"startedAt,omitempty"`
	// Phase is the process phase, on hello and lifecycle events.
	Phase string `json:"phase,omitempty"`

	Span       *SpanMessage        `json:"span,omitempty"`
	Transition *TransitionEvent    `json:"transition,omitempty"`
	Lifecycle  *ComponentMessage   `json:"lifecycle,omitempty"`
	Loop       *LoopMessage        `json:"loop,omitempty"`
	Census     *CensusMessage      `json:"census,omitempty"`
	Log        *LogRecordMessage   `json:"log,omitempty"`
	Mail       *MailSummaryMessage `json:"mail,omitempty"`
}

Event is one live event. Exactly one of the payload fields matching Type is set.

type EventType

type EventType string

EventType names the kind of a live event. It is a wire format — the graph's JSON and the Studio's TypeScript unions carry these names —, so it stays a string.

const (
	// EventHello opens every stream and carries the graph revision.
	EventHello EventType = "hello"
	// EventSpan reports one unit of work that finished on a node.
	EventSpan EventType = "span"
	// EventTransition reports a workflow instance changing state.
	EventTransition EventType = "transition"
	// EventLifecycle reports a lifecycle component moving, or the process
	// changing phase.
	EventLifecycle EventType = "lifecycle"
	// EventLoop reports a loop run.
	EventLoop EventType = "loop"
	// EventCensus reports a workflow's population per state.
	EventCensus EventType = "census"
	// EventGraph reports that the graph structure changed.
	EventGraph EventType = "graph"
	// EventLog reports a log record written by product code, in dev.
	EventLog EventType = "log"
	// EventMail reports a mail entering the outbox or changing status.
	EventMail EventType = "mail"
)

The live event types.

type ExportedVersionsMessage

type ExportedVersionsMessage struct {
	// Record is the record's position in its StoreData's Records.
	Record int `json:"record"`
	// Versions are its versions, newest first — the record as it is now
	// first —, each without its secret members.
	Versions []RecordVersionMessage `json:"versions"`
}

ExportedVersionsMessage are the versions of one exported record, as a StoreDataMessage carries them beside its records.

type FieldMessage

type FieldMessage struct {
	// Name is the wire name.
	Name string `json:"name"`
	// In is where a request field is read from: "body", "path", "query",
	// "header" or "cookie". Empty outside requests.
	In string `json:"in,omitempty"`
	// Type is the member's schema.
	Type *SchemaMessage `json:"type"`
	// Optional is set when the member may be absent.
	Optional bool `json:"optional,omitempty"`
	// Rules are the validation rules, as written in the validate tag.
	Rules string `json:"rules,omitempty"`
	// Doc is the field's comment, when the analyzer found one.
	Doc string `json:"doc,omitempty"`

	// Class is what the field holds, as its kit tag says (ADR 0006): one of
	// the Class constants, or empty when the field is unclassified. A
	// subject field is personal unless it is special.
	Class string `json:"class,omitempty"`
	// Subject marks the field that says whom a record is about.
	Subject bool `json:"subject,omitempty"`
	// Moderated marks content others see and a moderator may act on.
	Moderated bool `json:"moderated,omitempty"`
	// Sealed is set when kit keeps the field sealed at rest (ADR 0006 §4):
	// a personal, special or secret field, or the subject, not plain, of
	// what kit keeps on disk — a store's entity, a topic's message, a queued
	// command's input. A store in memory seals nothing.
	Sealed bool `json:"sealed,omitempty"`
	// Erased marks the time kit stamps when it erases the record.
	Erased bool `json:"erased,omitempty"`
	// History is how many former values kit keeps of the field (ADR 0007).
	History int `json:"history,omitempty"`
}

FieldMessage is one member of an object schema. It carries the JSON name, the schema of its value and the classes of its data.

type FileMessage

type FileMessage struct {
	// GoModule is empty for a file of the product's own module.
	GoModule string `json:"goModule,omitempty"`
	File     string `json:"file"`
}

FileMessage is one file a graph points at: its path, relative to its root — the product's module, or the Go module SourceMessage.GoModule names.

type FlameNodeMessage

type FlameNodeMessage struct {
	// Name is the function.
	Name string `json:"name"`
	// Value is its cumulative cost.
	Value float64 `json:"value"`
	// Node is the node the frame belongs to, when it is a node's code.
	Node string `json:"node,omitempty"`
	// Children are its callees, highest first.
	Children []*FlameNodeMessage `json:"children,omitempty"`
}

FlameNodeMessage is one frame of a flame graph. Its children are the frames it called; its value is the samples under it.

type FormerMessage

type FormerMessage struct {
	// Value is the field's value then, as JSON; absent for a secret field,
	// whose former values are never given.
	Value json.RawMessage `json:"value,omitempty" kit:"personal"`
	// Until is when it was replaced, on the app's clock.
	Until time.Time `json:"until"`
	// By is the user who replaced it — kit.UserID —, empty for a write
	// with no user: a job's, a loop's, kit's own.
	By string `json:"by,omitempty"`
}

FormerMessage is one former value of a field that keeps its history: what it was, until when, and who replaced it.

type FrontendSpec

type FrontendSpec struct {
	// Prefix is the URL path the assets are served under.
	Prefix string `json:"prefix"`
	// Files is how many files are served.
	Files int `json:"files,omitempty"`
}

FrontendSpec describes static assets served by the product. It carries the path the assets are served under and where they are read from.

type FuncCostMessage

type FuncCostMessage struct {
	// Func is the qualified function name.
	Func string `json:"func"`
	// Source locates it, when it is in the product's module.
	Source *SourceMessage `json:"source,omitempty"`
	// Flat is the cost of the function's own code; Cum includes its callees.
	Flat float64 `json:"flat"`
	Cum  float64 `json:"cum"`
	// Node is the node it was attributed to, when one.
	Node string `json:"node,omitempty"`
}

FuncCostMessage is what one function cost. It carries the flat and cumulative samples of the function and where it lives.

type GoroutineGroup

type GoroutineGroup struct {
	// Node is the node they run for, from their pprof label, when any.
	Node string `json:"node,omitempty"`
	// Loop is the loop they are, when kit knows: "http accept", a consumer.
	Loop string `json:"loop,omitempty"`
	// State is the runtime's word for what they wait on: "running",
	// "select", "chan receive", "IO wait", "sleep", "semacquire"…
	State string `json:"state"`
	// Count is how many goroutines are in the group.
	Count int `json:"count"`
	// Top is the innermost frame that is not the runtime's.
	Top string `json:"top"`
	// Stack is the group's stack, innermost first, capped.
	Stack []string `json:"stack,omitempty"`
}

GoroutineGroup is goroutines doing the same thing. They share one stack; Count says how many run it.

type GoroutinesResult

type GoroutinesResult struct {
	// At is when they were counted.
	At time.Time `json:"at"`
	// Total is how many goroutines exist.
	Total int `json:"total"`
	// Groups are goroutines sharing a node or loop, a state and a top frame,
	// largest first.
	Groups []GoroutineGroup `json:"groups"`
}

GoroutinesResult is every goroutine of the process, grouped by what it runs. Each group names the node its stack runs in, when one does.

type GraphMessage

type GraphMessage struct {
	// Version is always [Version] for a document this package produced.
	Version int `json:"version"`
	// Revision changes whenever the structure changes (nodes, edges, sources),
	// never when only observed statistics move. A reader caches layout on it.
	Revision string `json:"revision"`
	// App identifies the product.
	App AppMessage `json:"app"`
	// Nodes are sorted by ID.
	Nodes []NodeEntity `json:"nodes"`
	// Edges are sorted by ID.
	Edges []EdgeMessage `json:"edges"`
	// Catalog lists the generic mechanics this kit version offers.
	Catalog []MechanicMessage `json:"catalog,omitempty"`
	// Diagnostics are problems found while building the graph.
	Diagnostics []DiagnosticMessage `json:"diagnostics,omitempty"`
	// Runtime is present when a running process describes itself.
	Runtime *RuntimeMessage `json:"runtime,omitempty"`
	// Analysis reports the static analysis that enriched this graph.
	Analysis *AnalysisResult `json:"analysis,omitempty"`
	// Architecture is the product at C4's two outer levels: who uses it and
	// what it depends on, and what it is deployed as.
	Architecture *ArchitectureMessage `json:"architecture,omitempty"`
	// Connectors are what the product plugs into, derived from its nodes by
	// [GraphMessage.Normalize]: the Studio shows their pages and widgets only.
	Connectors []ConnectorMessage `json:"connectors,omitempty"`
	// ConnectorCatalog is every connector this kit version ships, used or
	// not: what the product may plug into, and what brings each.
	ConnectorCatalog []ConnectorSpec `json:"connectorCatalog,omitempty"`
	// Modules are the modules the app mounts (ADR 0008), sorted by name.
	Modules []ModuleMessage `json:"modules,omitempty"`
}

GraphMessage is the whole product. It is the JSON document the runtime serves and the analyzer writes; Version names its shape.

func Merge

func Merge(base, extra *GraphMessage) *GraphMessage

Merge enriches a graph with what another description of the same product knows. base is authoritative on which nodes exist — a runtime graph describes what the process actually serves —, on the modules it mounts, on what each of its ports calls and on which stores feed each of its watches: the app chose them when it started, where the analysis only reads the same rules over the whole module. extra, typically the static analysis, contributes documentation, handler ranges — an authorization function's too —, transition callers and the edges it found. Nodes only extra knows about are dropped: code that is compiled but not mounted in this app is not part of this product — save a node of a module's service the base mounts, which a package the binary does not link declares: a warning says so.

func (*GraphMessage) Edge

func (g *GraphMessage) Edge(id string) *EdgeMessage

Edge returns the edge with the given ID, or nil.

func (*GraphMessage) Files

func (g *GraphMessage) Files() []FileMessage

Files returns every file the graph points at, each with its root — the product's module, or another Go module: a module's (ADR 0008), a library's —, sorted and deduplicated. It is the complete list of files a reader of this graph may legitimately ask to see, and the source endpoint serves nothing else.

func (*GraphMessage) ModuleOf

func (g *GraphMessage) ModuleOf(name string) *ModuleMessage

ModuleOf returns the module named name, or nil.

func (*GraphMessage) Node

func (g *GraphMessage) Node(id string) *NodeEntity

Node returns the node with the given ID, or nil.

func (*GraphMessage) Normalize

func (g *GraphMessage) Normalize()

Normalize sorts nodes, edges and call sites into their canonical order, fills each workflow transition's callers from the edges, derives the connectors from the nodes, and recomputes Revision. Two graphs describing the same structure normalize to the same bytes, whatever order they were built in.

type HTTPServer

type HTTPServer struct {
	// Library is the implementation: "sdk/v1/net/server" — the SDK's engine
	// accepting and draining the connections, net/http speaking the protocol.
	Library string `json:"library"`
	// Loop says how it serves: one accept loop, one goroutine per
	// connection, written by the library rather than the product.
	Loop string `json:"loop"`
	// Addr is the listening address.
	Addr string `json:"addr,omitempty"`
	// Middleware is the chain every request goes through before its route,
	// outermost first.
	Middleware []MechanicMessage `json:"middleware,omitempty"`
	// Timeouts are the server's timeouts, as Go durations: "readHeader",
	// "read", "write", "idle".
	Timeouts map[string]string `json:"timeouts,omitempty"`
	// Conns counts connections: "active" now, "total" ever accepted,
	// "rejected" by the listener's ceiling. Older graphs carry "new", "idle"
	// and "hijacked" too.
	Conns map[string]int64 `json:"conns,omitempty"`
	// InFlight is how many requests are being served.
	InFlight int64 `json:"inFlight"`
	// Served counts the requests served since start.
	Served int64 `json:"served"`
}

HTTPServer is the product's HTTP server, and whose loop serves it. Its address is the one it listens on; its loop is the node that runs it.

type HeldUntilSpec

type HeldUntilSpec struct {
	// At locates the function that gives the instant.
	At *SourceMessage `json:"at,omitempty"`
	// Reason is the legal ground the declaration gives: "commercial code:
	// 10 years".
	Reason string `json:"reason,omitempty"`
}

HeldUntilSpec is the hold a store declares on each of its records, until an instant the record carries.

type HoldEvent

type HoldEvent struct {
	// Store is the store's node ID.
	Store string `json:"store"`
	// Record is the record's reference.
	Record string `json:"record"`
	// Subject is the reference of the person the record is about, when it
	// has one.
	Subject string `json:"subject,omitempty"`
	// By is who placed it: a user's ID, "cli" or "studio".
	By string `json:"by"`
	// At is when.
	At time.Time `json:"at"`
}

HoldEvent is one record a legal hold keeps. It carries references only: never the record's key, its subject's identity, or the hold's reason, which kit keeps apart.

type IDValue

type IDValue struct {
	// Module qualifies Service when a module lists it; empty for the
	// product's own services, and for a module's service named like it.
	Module string
	// Service is the service's own name, unqualified; empty for a binary, a
	// role, a library and [ExternalID].
	Service string
	// Scope is the name of the binary of a binary or a role, or of the
	// library of a library; empty otherwise.
	Scope string
	// Kind is the node's kind.
	Kind NodeKind
	// Name is the node's name: the service's for a service, the binary's for
	// a binary.
	Name string
}

IDValue is a node's identity, parsed: the one grammar of IDPattern. Its String is the ID it was parsed from.

func ParseID

func ParseID(s string) (IDValue, error)

ParseID reads an ID. It refuses anything IDPattern does not match, with InvalidID; the refusal never quotes the input, which may be anything a caller sent.

func (*IDValue) QualifiedServiceName

func (id *IDValue) QualifiedServiceName() string

QualifiedServiceName is the service's ID segment: the qualification QualifiedService applies.

func (*IDValue) String

func (id *IDValue) String() string

String renders the ID; ParseID(id.String()) is id for every ID ParseID returned.

type IndexSpec

type IndexSpec struct {
	// Name is how code asks for the index: Store.Lookup(ctx, name, key).
	Name string `json:"name"`
	// Unique is set when two entities may not share a key: a write that
	// would is refused with a conflict.
	Unique bool `json:"unique,omitempty"`
}

IndexSpec is one secondary index of a store. Its name is unique in the store; Unique says whether two records may share a key.

type InstanceMessage

type InstanceMessage struct {
	// ID is the entity key.
	ID string `json:"id"`
	// State is the current state.
	State string `json:"state"`
	// EnteredAt is when the instance entered its current state.
	EnteredAt time.Time `json:"enteredAt"`
	// History lists the transitions, oldest first, capped.
	History []StepEvent `json:"history,omitempty"`
}

InstanceMessage is one entity's journey through a workflow. It carries the entity's key, its current state and the steps that brought it there.

type JobSpec

type JobSpec struct {
	// Schedule is "every 10s" or a five-field cron expression.
	Schedule string `json:"schedule"`
	// Kind is "interval" or "cron".
	Kind string `json:"kind"`
}

JobSpec describes a scheduled job. It carries the fixed interval or the cron expression that schedules it.

type JournalCheckMessage

type JournalCheckMessage struct {
	// Entries is how many entries the journal holds.
	Entries int `json:"entries"`
	// BrokenAt is the sequence number where the chain breaks: an entry
	// changed, or one removed before it. Zero when the chain holds.
	BrokenAt int64 `json:"brokenAt,omitempty"`
}

JournalCheckMessage is what verifying the journal's chain found. A broken chain names the first entry whose hash does not follow.

type JournalEntryEvent

type JournalEntryEvent struct {
	// Seq numbers the entries from 1, with no gap.
	Seq int64 `json:"seq"`
	// At is when, on the app's clock.
	At time.Time `json:"at"`
	// Op is one of the Journal constants.
	Op string `json:"op"`
	// DryRun marks what the retention would have done under
	// KIT_RETENTION=dry-run: nothing changed.
	DryRun bool `json:"dryRun,omitempty"`
	// Store is the store's node ID.
	Store string `json:"store,omitempty"`
	// Record is the record's reference; Subject its subject's.
	Record  string `json:"record,omitempty"`
	Subject string `json:"subject,omitempty"`
	// By is who: a user's ID, the node that called, "retention", "cli" or
	// "studio".
	By string `json:"by"`
	// Hash is the entry's link in the chain: SHA-256 of the previous
	// entry's hash and this entry.
	Hash string `json:"hash"`
}

JournalEntryEvent is one operation of the privacy journal: what was done, where, by whom and when, with references only — never an identity, a value or a key. Each entry is chained to the previous one by SHA-256.

type LibrarySpec

type LibrarySpec struct {
	// Package is its Go import path.
	Package string `json:"package"`
}

LibrarySpec is a package shared between components (D19): the NodeEntity.Library of a KindLibrary node.

type LinkMessage

type LinkMessage struct {
	// From is the ID of a person, system or container.
	From string `json:"from"`
	// To is the ID of a person, system or container.
	To string `json:"to"`
	// Label says what the relationship is: "Reads and writes".
	Label string `json:"label"`
	// Technology says how: "JSON over HTTP", "SMTP", "file I/O".
	Technology string `json:"technology,omitempty"`
	// Nodes are the nodes whose edges make the link true.
	Nodes []string `json:"nodes,omitempty"`
	// Connectors are the connectors the link is made of: one link from the
	// process to the data directory carries the stores, the queues and the
	// mail outbox.
	Connectors []string `json:"connectors,omitempty"`
}

LinkMessage is a relationship between two elements of the architecture. The process's link to a database, "Reads and writes", carries the database connector, and the store connector once stores live on it.

type ListenerSpec

type ListenerSpec struct {
	// Network is one of the Network constants.
	Network string `json:"network"`
	// Contract is the versioned contract spoken on it: "render/v1".
	Contract string `json:"contract"`
	// Peer says who may connect: "owner" (the process's own user), or the
	// declared list, never "anyone".
	Peer string `json:"peer"`
	// Role is the ID of the role that runs it.
	Role string `json:"role,omitempty"`
}

ListenerSpec is a listener that is not HTTP: the NodeEntity.Listener of a KindListener node — its network, its contract, who may connect.

type LogRecordMessage

type LogRecordMessage struct {
	// Seq orders records; it only increases.
	Seq uint64 `json:"seq"`
	// Time is when it was written.
	Time time.Time `json:"time"`
	// Level is "debug", "info", "warn" or "error".
	Level string `json:"level"`
	// Message is the record's message.
	Message string `json:"message"`
	// Node is the node whose code wrote it.
	Node string `json:"node,omitempty"`
	// TraceID and SpanID correlate it with a span.
	TraceID string `json:"traceId,omitempty"`
	SpanID  string `json:"spanId,omitempty"`
	// Attrs are the record's attributes, as text, secrets redacted.
	Attrs map[string]string `json:"attrs,omitempty"`
}

LogRecordMessage is one log record written by product code through kit.Log, kept in dev so the Studio can show a request's logs beside its spans.

type LoopMessage

type LoopMessage struct {
	// Name identifies the loop.
	Name string `json:"name"`
	// Node is the node the loop drives.
	Node string `json:"node,omitempty"`
	// Kind is one of the Loop constants.
	Kind string `json:"kind"`
	// Provenance is one of the Provenance constants.
	Provenance string `json:"provenance,omitempty"`
	// Library names the code that loops, for a library or kit loop:
	// "net/http", "sdk/v1/app/scheduler", "sdk/v1/data/queue",
	// "sdk/v1/app/mail/spool", "sdk/v1/app/statemachine", "kit".
	Library string `json:"library,omitempty"`
	// State is one of the Loop state constants.
	State string `json:"state,omitempty"`
	// LastWake is why the last run started: "interval", "topic",
	// "deadline", "manual", "start".
	LastWake string `json:"lastWake,omitempty"`
	// Restarts counts supervised restarts, for a hand-written loop.
	Restarts int64 `json:"restarts,omitempty"`
	// Schedule is human text: "every 10s", "*/5 * * * *", "on publish · poll 5s".
	Schedule string `json:"schedule"`
	// Runs counts completed runs.
	Runs int64 `json:"runs"`
	// Errors counts failed runs.
	Errors int64 `json:"errors"`
	// Missed counts due instants dropped because they had already passed.
	Missed int64 `json:"missed"`
	// Skipped counts fires skipped because the previous run was still going.
	Skipped int64 `json:"skipped"`
	// LastRun is when the last run started.
	LastRun *time.Time `json:"lastRun,omitempty"`
	// LastMs is how long the last run took.
	LastMs float64 `json:"lastMs,omitempty"`
	// NextRun is when the next run is due, when it is known.
	NextRun *time.Time `json:"nextRun,omitempty"`
	// LastError is the public message of the last failure.
	LastError string `json:"lastError,omitempty"`
}

LoopMessage is one recurring piece of the daemon's internal loop: a job, a workflow's timer sweep, a subscription's consumer, the HTTP accept loop, a declared or hand-written loop.

type LoopSpec

type LoopSpec struct {
	// Style is [LoopDeclared] or [LoopGoroutine].
	Style string `json:"style"`
	// Wakes are what wakes a declared loop.
	Wakes []WakeSourceMessage `json:"wakes,omitempty"`
	// Selects are the cases of the select statements a hand-written loop
	// waits in, as the static analysis read them.
	Selects []SelectCaseMessage `json:"selects,omitempty"`
	// Restart is the supervision policy, as text.
	Restart string `json:"restart,omitempty"`
}

LoopSpec describes a loop node. Style says whether it is declared (kit owns the wait) or hand-written.

type MailMessage

type MailMessage struct {
	MailSummary
	// Text is the plain text body.
	Text string `json:"text,omitempty"`
	// HTML is the HTML body. The Studio renders it in a sandboxed frame
	// that runs no script.
	HTML string `json:"html,omitempty"`
	// Headers are the extra headers, rendered.
	Headers map[string]string `json:"headers,omitempty"`
	// Raw is the composed message, as the transport received it.
	Raw string `json:"raw,omitempty"`
}

MailMessage is a whole captured mail, for the Studio's mailbox. It is kept by the capture transport of dev and tests only, never in production.

type MailSummary

type MailSummary = MailSummaryMessage

MailSummary is the name MailMessage embeds its summary under: the field a caller sets and reads is MailMessage.MailSummary, its JSON members promoted beside the body's.

type MailSummaryMessage

type MailSummaryMessage struct {
	// ID identifies the mail in the outbox.
	ID string `json:"id"`
	// Mailer is the mailer node.
	Mailer string `json:"mailer"`
	// From and To are addresses, rendered.
	From string   `json:"from"`
	To   []string `json:"to"`
	// Subject is the subject.
	Subject string `json:"subject"`
	// Status is one of the Mail constants.
	Status string `json:"status"`
	// Attempts counts delivery attempts.
	Attempts int `json:"attempts"`
	// Error is the public message of the last failure.
	Error string `json:"error,omitempty"`
	// QueuedAt is when it entered the outbox; SentAt when it left.
	QueuedAt time.Time  `json:"queuedAt"`
	SentAt   *time.Time `json:"sentAt,omitempty"`
	// TraceID is the trace that queued it.
	TraceID string `json:"traceId,omitempty"`
	// Node is the node that queued it.
	Node string `json:"node,omitempty"`
}

MailSummaryMessage is one mail as the outbox sees it. It carries no body: the Studio lists summaries and reads a whole mail on demand.

type MailerSpec

type MailerSpec struct {
	// Transport is [TransportSMTP] or [TransportCapture].
	Transport string `json:"transport"`
	// Server is the relay's host:port. Credentials never appear.
	Server string `json:"server,omitempty"`
	// TLS is "starttls", "implicit" or "none", for SMTP.
	TLS string `json:"tls,omitempty"`
	// From is the default sender.
	From string `json:"from,omitempty"`
	// MaxAttempts is how many deliveries a message gets before it is
	// dead-lettered.
	MaxAttempts int `json:"maxAttempts"`
	// Outbox is "memory" or "file": where queued messages wait.
	Outbox string `json:"outbox,omitempty"`
	// Queued is how many messages wait in the outbox, on a runtime graph.
	Queued *int `json:"queued,omitempty"`
	// Sent is how many messages the transport accepted, on a runtime graph.
	Sent *int `json:"sent,omitempty"`
	// DeadLetters is how many messages were abandoned, on a runtime graph.
	DeadLetters *int `json:"deadLetters,omitempty"`
}

MailerSpec describes outbound mail. It carries the transport that empties the outbox and the outbox's counters.

type MechanicMessage

type MechanicMessage struct {
	// Kind is the stable identifier: "validate", "ratelimit", "timeout"…
	Kind string `json:"kind"`
	// Label is a short human rendering of the configuration: "5/s".
	Label string `json:"label"`
	// Package is the SDK package that implements it.
	Package string `json:"package,omitempty"`
	// Doc says what it does, for a catalog.
	Doc string `json:"doc,omitempty"`
	// Snippet is the Go code that adds it, for a catalog.
	Snippet string `json:"snippet,omitempty"`
	// Config is the configuration, as text.
	Config map[string]string `json:"config,omitempty"`
}

MechanicMessage is a generic building block, backed by an SDK package, that a node composes. The catalog lists every mechanic kit offers; an endpoint's pipeline lists the ones it uses.

type MigrationMessage

type MigrationMessage struct {
	// Version orders it: a UTC timestamp by convention, 20260910143000.
	Version uint64 `json:"version"`
	// Name says what it does; empty for a version this build does not carry.
	Name string `json:"name,omitempty"`
}

MigrationMessage is one versioned migration. Its Version orders it among the others; Name says what it does.

type MigrationSetMessage

type MigrationSetMessage struct {
	// Name is the set's origin: "kit", "product", or a module's name.
	Name string `json:"name"`
	// Table is its version table: "kit_migrations", "schema_migrations".
	Table string `json:"table"`
	// Applied are the migrations the database records, and Pending those
	// this build carries that it does not, oldest first.
	Applied []MigrationMessage `json:"applied,omitempty"`
	Pending []MigrationMessage `json:"pending,omitempty"`
	// Problem is why the set could not be read or applied.
	Problem string `json:"problem,omitempty"`
}

MigrationSetMessage is one set of migrations on a database — kit's own, the product's (kit.Migrations), a module's — with its own version table, and so its own lock.

type MockMessage

type MockMessage struct {
	// Node is the node it applies to: a port, a command or a query.
	Node string `json:"node"`
	// Mode is [MockReplace].
	Mode string `json:"mode"`
	// Hits counts the runs it changed.
	Hits int64 `json:"hits"`
}

MockMessage is the replacement a test gave the app (MockReplace). It is set by a test only; the Studio shows it and never sets one (D13).

type ModuleMessage

type ModuleMessage struct {
	// Name is the name kit.NewModule gives it.
	Name string `json:"name"`
	// Doc is its description in the product's default language; Docs the
	// same in other languages, by tag, as a node's.
	Doc  string            `json:"doc,omitempty"`
	Docs map[string]string `json:"docs,omitempty"`
	// Package is the Go package that declares it: the one a product imports.
	Package string `json:"package,omitempty"`
	// Build is the Go module it comes from, and its version.
	Build *ModuleVersionMessage `json:"build,omitempty"`
	// Services are its services' IDs, in the order it lists them.
	Services []string `json:"services"`
	// Requires are the modules it requires (kit.Requires), by name.
	Requires []string `json:"requires,omitempty"`
	// RequiredBy are the mounted modules that require it, by name, sorted.
	RequiredBy []string `json:"requiredBy,omitempty"`
	// Prefix is where its routes are served: "/<name>/" unless the mount
	// says otherwise (kit.Prefix); "/" shares the product's route space.
	Prefix string `json:"prefix"`
	// Source is where kit.NewModule declares it.
	Source *SourceMessage `json:"source,omitempty"`
	// Mount is where the app mounts it — App.With or kit.Mount —; absent
	// when only another module's kit.Requires mounted it, at its defaults.
	Mount *SourceMessage `json:"mount,omitempty"`
}

ModuleMessage is a module the app mounts: a Go module's services, released and mounted together like a bundle (ADR 0008). Everything a module declares is qualified with its name: its services are "<module>.<service>" — the one named like the module is "<module>" —, so its nodes are "<module>.<service>/<kind>/<name>" and carry NodeEntity.Module.

type ModuleVersionMessage

type ModuleVersionMessage struct {
	// Module is the module path.
	Module string `json:"module"`
	// Version is the published module version, "v0.4.6"; empty for a local
	// directory or a build without module version.
	Version string `json:"version,omitempty"`
	// Revision is the VCS commit the module was built from, when known.
	Revision string `json:"revision,omitempty"`
	// Time is that commit's time.
	Time *time.Time `json:"time,omitempty"`
	// Modified is set when the build included uncommitted changes.
	Modified bool `json:"modified,omitempty"`
	// Local is set when the module came from a local directory (a replace
	// or a workspace) rather than a published version.
	Local bool `json:"local,omitempty"`
}

ModuleVersionMessage identifies one module of a build. Local and Modified say when the code that ran is not the published version.

type NodeCostMessage

type NodeCostMessage struct {
	// Node is the node ID.
	Node string `json:"node"`
	// Value is the cost, in the profile's unit.
	Value float64 `json:"value"`
	// Share is Value over Total, from 0 to 1.
	Share float64 `json:"share"`
	// Top are the node's costliest functions.
	Top []FuncCostMessage `json:"top,omitempty"`
}

NodeCostMessage is what one node cost. It is the share of the profile's samples spent in the node's code.

type NodeEntity

type NodeEntity struct {
	// ID is "<service>/<kind>/<name>", "<service>" for a service,
	// "binary:<name>" for a binary, "binary:<binary>/role/<name>" for a
	// role, "library:<name>" for a library, or [ExternalID]: the grammar of
	// [IDValue].
	ID string `json:"id"`
	// Kind says which building block this is.
	Kind NodeKind `json:"kind"`
	// Name is unique among the nodes of one kind in one service.
	Name string `json:"name"`
	// Service is the owning service ID. Empty for services and external.
	Service string `json:"service,omitempty"`
	// Module is the module the node belongs to — a module's service and
	// every node of it —; empty for the product's own.
	Module string `json:"module,omitempty"`
	// Doc is the Go doc comment of the declaration or of its handler, in
	// the product's default language.
	Doc string `json:"doc,omitempty"`
	// Docs are the same description in other languages, by tag ("fr"),
	// from the comment's tagged paragraphs: see [SplitDoc].
	Docs map[string]string `json:"docs,omitempty"`
	// Source is where the node is declared.
	Source *SourceMessage `json:"source,omitempty"`
	// Handler is the body of the function the node runs, when it has one.
	Handler *SourceMessage `json:"handler,omitempty"`

	Endpoint     *EndpointSpec     `json:"endpoint,omitempty"`
	Store        *StoreSpec        `json:"store,omitempty"`
	Topic        *TopicSpec        `json:"topic,omitempty"`
	Subscription *SubscriptionSpec `json:"subscription,omitempty"`
	Workflow     *WorkflowSpec     `json:"workflow,omitempty"`
	Job          *JobSpec          `json:"job,omitempty"`
	Frontend     *FrontendSpec     `json:"frontend,omitempty"`
	Auth         *AuthSpec         `json:"auth,omitempty"`
	Mailer       *MailerSpec       `json:"mailer,omitempty"`
	Loop         *LoopSpec         `json:"loop,omitempty"`
	Secret       *SecretSpec       `json:"secret,omitempty"`
	Port         *PortSpec         `json:"port,omitempty"`
	Command      *CommandSpec      `json:"command,omitempty"`
	Query        *QuerySpec        `json:"query,omitempty"`
	Binary       *BinarySpec       `json:"binary,omitempty"`
	Role         *RoleSpec         `json:"role,omitempty"`
	CLI          *CLISpec          `json:"cli,omitempty"`
	Listener     *ListenerSpec     `json:"listener,omitempty"`
	Library      *LibrarySpec      `json:"library,omitempty"`
	Presentation *PresentationSpec `json:"presentation,omitempty"`

	// Code is the code the node runs, as the static analysis read it: C4's
	// code level.
	Code *CodeResult `json:"code,omitempty"`

	// Stats are runtime counters, present on a runtime graph.
	Stats *StatsMessage `json:"stats,omitempty"`
}

NodeEntity is one building block. Its ID is its identity; exactly one of the kind-specific fields matching Kind is set.

type NodeKind

type NodeKind string

NodeKind is the closed set of building blocks a kit product is made of. It is a wire format — the graph's JSON and the Studio's TypeScript unions carry these names —, so it stays a string.

const (
	// KindService groups the nodes of one bounded context.
	KindService NodeKind = "service"
	// KindEndpoint is an HTTP endpoint with typed request and response.
	KindEndpoint NodeKind = "endpoint"
	// KindStore is a typed, keyed collection of entities.
	KindStore NodeKind = "store"
	// KindTopic is an asynchronous, at-least-once message channel.
	KindTopic NodeKind = "topic"
	// KindSubscription consumes one topic.
	KindSubscription NodeKind = "subscription"
	// KindWorkflow is a state machine over the entities of one store.
	KindWorkflow NodeKind = "workflow"
	// KindJob is scheduled work: a fixed interval or a cron expression.
	KindJob NodeKind = "job"
	// KindFrontend is static assets served by the product.
	KindFrontend NodeKind = "frontend"
	// KindExternal stands for everything outside the product.
	KindExternal NodeKind = "external"
	// KindAuth is the app's authentication handler: it turns a request's
	// credentials into a user, in front of every endpoint that asks for one.
	KindAuth NodeKind = "auth"
	// KindMailer is outbound mail: a durable outbox, and the transport that
	// empties it — SMTP, or the capture of dev and tests.
	KindMailer NodeKind = "mailer"
	// KindLoop is a long-running loop of the daemon: declared (kit owns the
	// wait, the product the work) or hand-written (a goroutine kit supervises).
	KindLoop NodeKind = "loop"
	// KindSecret is a secret the product declares: provided by the operator,
	// or generated by kit and rotated on a schedule. Its value is never in a
	// graph.
	KindSecret NodeKind = "secret"
	// KindPort is an operation a service needs and does not implement: a
	// typed request, a typed response, a name. What it calls — another
	// service's endpoint, the app's binding, its own fallback — is decided
	// when the app starts, and drawn as a declared edge from the port.
	KindPort NodeKind = "port"
	// KindCommand is an operation that changes something: a typed input, a
	// typed result, one handler, the pipeline of its kind. It is dispatched,
	// on its caller's goroutine or through its own queue.
	KindCommand NodeKind = "command"
	// KindQuery is an operation that reads and changes nothing: a typed
	// input, a typed result, one handler. It is asked.
	KindQuery NodeKind = "query"
	// KindBinary is one executable the product ships. It holds process
	// roles; its ID is "binary:<name>".
	KindBinary NodeKind = "binary"
	// KindRole is one process role of a binary — "statusline" and
	// "statusline daemon" are two roles of one binary. Its root package is
	// generated wiring; two roles talk through their contract only. Its ID
	// is "binary:<binary>/role/<name>".
	KindRole NodeKind = "role"
	// KindCLI is a short command-line command: it parses its arguments,
	// runs once and exits with a typed status.
	KindCLI NodeKind = "cli"
	// KindListener accepts connections that are not HTTP: a private Unix
	// socket, a named pipe. It is an inbound port like an endpoint.
	KindListener NodeKind = "listener"
	// KindLibrary is a package shared between components, declared so the
	// components that use it are allowed to import it. Its ID is
	// "library:<name>".
	KindLibrary NodeKind = "library"
	// KindPresentation turns a service's results into what a reader sees:
	// a rendered line, a page, a report.
	KindPresentation NodeKind = "presentation"
)

The node kinds.

type PasswordPolicyMessage

type PasswordPolicyMessage struct {
	// Field is the field's JSON pointer: "/password".
	Field string `json:"field"`
	// MinLength is the fewest characters a password may have.
	MinLength int `json:"minLength"`
	// NotReused is how many former passwords it refuses; zero when it
	// refuses none.
	NotReused int `json:"notReused,omitempty"`
	// NotCommon says it refuses the most common passwords (kit.NotCommon),
	// as every policy does.
	NotCommon bool `json:"notCommon,omitempty"`
	// Source is where the policy is declared.
	Source *SourceMessage `json:"source,omitempty"`
}

PasswordPolicyMessage is the policy of one secret field that holds a password's hash (Store.Passwords).

type Payload

type Payload struct {
	// Request is the decoded request, or the message delivered.
	Request json.RawMessage `json:"request,omitempty"`
	// Response is the response.
	Response json.RawMessage `json:"response,omitempty"`
	// Truncated is set when a side was cut.
	Truncated bool `json:"truncated,omitempty"`
}

Payload is the request and the response of a span, as JSON, in dev only. Every member whose name says it is a secret — password, token, secret, authorization, cookie… — or whose Go field is tagged kit:"secret" is replaced by "[redacted]", and each side is cut at 8 KiB.

type PermissionMessage

type PermissionMessage struct {
	// Action is what the caller does: "place".
	Action string `json:"action"`
	// Resource is the kind of thing it does it to: "order".
	Resource string `json:"resource"`
}

PermissionMessage is what a caller needs to dispatch a command or to ask a query: that the app's policy lets it do Action to Resource (Allow).

type PersonMessage

type PersonMessage struct {
	// ID is unique in the architecture: "person:user".
	ID string `json:"id"`
	// Name is what the diagram prints: "User".
	Name string `json:"name"`
	// Doc says who they are and what they do with the product.
	Doc string `json:"doc,omitempty"`
}

PersonMessage is a human user of the product. It is drawn at the edge of the C4 context view, outside every container.

type PersonalDataMessage

type PersonalDataMessage struct {
	// Stores are the stores that keep records about the person.
	Stores []StoreDataMessage `json:"stores"`
}

PersonalDataMessage is a person's data as kit.Export gives it (GDPR art. 15 and 20): their records, store by store, with what art. 15(1) asks beside them.

type PhaseChangeEvent

type PhaseChangeEvent struct {
	// Phase is the phase entered: one of the Phase constants.
	Phase string `json:"phase"`
	// At is when.
	At time.Time `json:"at"`
	// Reason says why, when it is not the natural next step: "SIGTERM",
	// "a component failed".
	Reason string `json:"reason,omitempty"`
}

PhaseChangeEvent is one step of the daemon's life. It carries the phase entered, when it was entered, and why.

type Pool

type Pool struct {
	// MaxOpen is its ceiling.
	MaxOpen int `json:"maxOpen"`
	// Open is how many connections are open: InUse and Idle.
	Open  int `json:"open"`
	InUse int `json:"inUse"`
	Idle  int `json:"idle"`
	// Waits counts the calls that waited for a connection, and WaitMs how
	// long they waited in all.
	Waits  int64   `json:"waits"`
	WaitMs float64 `json:"waitMs"`
	// Closed counts the connections closed for being idle too many, idle
	// too long, or too old.
	Closed int64 `json:"closed,omitempty"`
}

Pool is a database's connection pool, as database/sql counts it. It is sampled when the runtime state is read; its counters never move a revision.

type PortMessage

type PortMessage struct {
	// Address is the listen address: "127.0.0.1:4000", ":4000". Present in
	// dev only, like every location.
	Address string `json:"address,omitempty"`
	// Owner is [PortOwnerKit], or the ID of the connector that opened it.
	Owner string `json:"owner"`
	// Serves says what it answers: the Serves constants.
	Serves []string `json:"serves"`
	// Settings are the settings that configure it.
	Settings []string `json:"settings,omitempty"`
}

PortMessage is an address a process listens on. Owner is the container that listens on it; Serves names what is reached through it.

type PortSpec

type PortSpec struct {
	// Request is the type the port is called with.
	Request *SchemaMessage `json:"request,omitempty"`
	// Response is the type it answers.
	Response *SchemaMessage `json:"response,omitempty"`
	// Fallback is the node ID of the operation the port declares for when
	// the app binds nothing else (kit.Fallback).
	Fallback string `json:"fallback,omitempty"`
	// Bound is the node ID of the operation the port calls, as the start
	// chose it — on a static graph, as the analysis reads the same rule;
	// empty when nothing is bound or a test replaced the port. The graph
	// draws it as a declared edge from the port.
	Bound string `json:"bound,omitempty"`
	// Via is how it was chosen: one of the Via constants.
	Via string `json:"via,omitempty"`
}

PortSpec describes a port: an operation a service needs and another implements.

type PresentationSpec

type PresentationSpec struct {
	// Media is what it renders: "text", "ansi", "html", "json".
	Media string `json:"media"`
}

PresentationSpec is what turns results into what a reader sees: the NodeEntity.Presentation of a KindPresentation node.

type PrivacyMessage

type PrivacyMessage struct {
	// Retention is KIT_RETENTION: one of the Retention constants.
	Retention string `json:"retention"`
	// Register is the record of processing, as far as the code knows it.
	Register RegisterMessage `json:"register"`
	// Holds are the records a legal hold keeps, newest first.
	Holds []HoldEvent `json:"holds,omitempty"`
	// Journal is the privacy journal's latest entries, newest first.
	Journal []JournalEntryEvent `json:"journal,omitempty"`
	// Chain says whether the journal's chain holds.
	Chain JournalCheckMessage `json:"chain"`
}

PrivacyMessage is what a running app says of the personal data it keeps. It is the Privacy page's data: the register, the holds and the journal's state.

type ProcessSpec

type ProcessSpec struct {
	// PID is the process ID.
	PID int `json:"pid"`
	// Go is the Go version the binary was built with.
	Go string `json:"go"`
	// OS and Arch are GOOS and GOARCH.
	OS   string `json:"os"`
	Arch string `json:"arch"`
	// MaxProcs is GOMAXPROCS; CPUs the logical CPUs the process sees.
	MaxProcs int `json:"maxProcs"`
	CPUs     int `json:"cpus"`
	// Goroutines is how many goroutines exist.
	Goroutines int `json:"goroutines"`
	// HeapBytes is the live heap; HeapObjects its object count.
	HeapBytes   uint64 `json:"heapBytes"`
	HeapObjects uint64 `json:"heapObjects"`
	// HeapGoalBytes is the heap size at which the next collection starts.
	HeapGoalBytes uint64 `json:"heapGoalBytes,omitempty"`
	// MemoryBytes is all the memory the Go runtime holds from the system:
	// the heap, the stacks, the runtime's own structures.
	MemoryBytes uint64 `json:"memoryBytes,omitempty"`
	// TotalAllocBytes is every byte ever allocated on the heap.
	TotalAllocBytes uint64 `json:"totalAllocBytes"`
	// GCCycles counts completed garbage collections.
	GCCycles uint64 `json:"gcCycles"`
	// LastGC is when the last collection ended; absent before the first.
	LastGC *time.Time `json:"lastGC,omitempty"`
	// GCPauseP99Ms is the 99th percentile stop-the-world pause.
	GCPauseP99Ms float64 `json:"gcPauseP99Ms"`
	// SchedLatencyP99Ms is the 99th percentile time a goroutine waited to run.
	SchedLatencyP99Ms float64 `json:"schedLatencyP99Ms"`
	// CPUSeconds is the CPU time the process consumed, user and system.
	CPUSeconds float64 `json:"cpuSeconds"`
	// UptimeMs is how long the process has run.
	UptimeMs float64 `json:"uptimeMs"`
	// At is when the sample was taken.
	At time.Time `json:"at"`
}

ProcessSpec is the Go process a product runs in. It carries the runtime's figures — goroutines, heap, GC, CPU — taken at At.

type ProductRetentionSpec

type ProductRetentionSpec struct {
	// Limits says, in the product's words, how long the records keep their
	// personal data and how they go — the register's time limits, GDPR
	// art. 30(1)(f); empty when it gave none.
	Limits string `json:"limits,omitempty"`
}

ProductRetentionSpec is a retention the product keeps itself, as it says it.

type ProfileResult

type ProfileResult struct {
	// Kind is one of the Profile constants.
	Kind string `json:"kind"`
	// At is when the profile ended.
	At time.Time `json:"at"`
	// DurationMs is how long a CPU profile sampled.
	DurationMs float64 `json:"durationMs,omitempty"`
	// Unit is what the values count: "ms" of CPU, "bytes" of heap.
	Unit string `json:"unit"`
	// Total is the sum of every sample.
	Total float64 `json:"total"`
	// Nodes are the costs attributed to nodes, highest first.
	Nodes []NodeCostMessage `json:"nodes"`
	// Unattributed is the cost outside any node's code: the runtime, the
	// garbage collector, kit itself, idle loops.
	Unattributed float64 `json:"unattributed"`
	// Top are the costliest functions, by flat cost.
	Top []FuncCostMessage `json:"top"`
	// Flame is the call tree, root first, pruned below 0.5% of Total.
	Flame *FlameNodeMessage `json:"flame,omitempty"`
}

ProfileResult is a pprof profile of the running product, folded onto its graph: every sample is attributed to the node whose code was running — through the pprof label kit puts on every handler, subscription, job and loop run, or, for the heap, which carries no label, through the node's code functions on the sample's stack.

type QuerySpec

type QuerySpec struct {
	// Input is the type it is asked with.
	Input *SchemaMessage `json:"input,omitempty"`
	// Result is the type it answers.
	Result *SchemaMessage `json:"result,omitempty"`
	// Auth is [AuthRequired] — implied by a permission —, [AuthOptional],
	// or empty when the query ignores authentication.
	Auth string `json:"auth,omitempty"`
	// Pipeline lists the mechanics a question goes through before the
	// handler, in the order they run.
	Pipeline []MechanicMessage `json:"pipeline,omitempty"`
	// Permissions are the permissions a caller needs (Allow).
	Permissions []PermissionMessage `json:"permissions,omitempty"`
	// Authorize locates the function of its Authorize: a rule that needs
	// the data.
	Authorize *SourceMessage `json:"authorize,omitempty"`
}

QuerySpec describes a query: an operation that reads and changes nothing.

type RecordFormerMessage

type RecordFormerMessage struct {
	// Record is the record's position in its StoreData's Records.
	Record int `json:"record"`
	// Fields are each field's former values, newest first, by the field's
	// JSON pointer. A secret field's are left out.
	Fields map[string][]FormerMessage `json:"fields"`
}

RecordFormerMessage is the former values of one exported record's fields. A personal or special field's former values are redacted, never exported in clear.

type RecordHistoryMessage

type RecordHistoryMessage struct {
	Fields map[string][]FormerMessage `json:"fields"`
}

RecordHistoryMessage is what kit remembers of one record, as the Studio's data view shows it (GET /_kit/api/former): each field's former values, newest first, by the field's JSON pointer — a secret field's without their values, a personal or special one's redacted.

type RecordVersionMessage

type RecordVersionMessage struct {
	Number uint64 `json:"number"`
	// At is when the write that made it ran, on the app's clock.
	At time.Time `json:"at,omitzero"`
	// By is the user who made it — kit.UserID —, empty for a write with no
	// user.
	By string `json:"by,omitempty"`
	// Command is the node ID of the command that made it, empty outside
	// one.
	Command string `json:"command,omitempty"`
	// Value is the record as it was: in an export, its secret members left
	// out; in the Studio, as the data browser shows a record.
	Value json.RawMessage `json:"value,omitempty" kit:"personal"`
}

RecordVersionMessage is one version of a record whose store keeps revisions (ADR 0007 §3): its number — from 1, never given twice while the record exists —, when the write that made it ran — zero for a record stored before its store kept revisions —, who made it and which command, and the record as it was.

type RecordVersionsMessage

type RecordVersionsMessage struct {
	Versions []RecordVersionMessage `json:"versions"`
	// From and To are the two versions compared, when asked for; Edits what
	// changed between them.
	From  uint64        `json:"from,omitempty"`
	To    uint64        `json:"to,omitempty"`
	Edits []EditMessage `json:"edits,omitempty"`
}

RecordVersionsMessage is a record's versions as the Studio's data view shows them (GET /_kit/api/revisions): newest first, each as the data browser shows a record — a member sealed at rest sealed, a personal, special or secret one redacted —, and, when two were asked for, what changed from one to the other, a value given only where the data browser would show it.

type RegisterMessage

type RegisterMessage struct {
	// App is the product.
	App string `json:"app"`
	// ToComplete are the points the code cannot know, for a person to
	// write: "a" (the controller and its representatives), "e" (the
	// transfers).
	ToComplete []string `json:"toComplete,omitempty"`
	// Stores are the stores that keep personal data, by node ID.
	Stores []RegisterStoreMessage `json:"stores,omitempty"`
}

RegisterMessage is the record of processing of GDPR art. 30(1), as far as the code knows it.

type RegisterStoreMessage

type RegisterStoreMessage struct {
	// Store is the store's node ID.
	Store string `json:"store"`
	// Purpose is point (b): why the store keeps its records.
	Purpose string `json:"purpose,omitempty"`
	// Subject is point (c)'s category of data subjects: the pointer of the
	// field that says whom each record is about.
	Subject string `json:"subject,omitempty"`
	// SubjectDoc is that field's comment, when the analyzer read it.
	SubjectDoc string `json:"subjectDoc,omitempty"`
	// Personal, Special and Secret are point (c)'s categories of personal
	// data: the fields of each class, as JSON pointers. Special fields are
	// art. 9 data; secret ones are credentials.
	Personal []string `json:"personal,omitempty"`
	Special  []string `json:"special,omitempty"`
	Secret   []string `json:"secret,omitempty"`
	// Recipients are point (d) inside the product: the nodes the graph
	// shows reading the store, and the connectors that carry its data out.
	Recipients []string `json:"recipients,omitempty"`
	// Erase, Delete and HeldUntil are point (f), the time limits, in words.
	Erase     string `json:"erase,omitempty"`
	Delete    string `json:"delete,omitempty"`
	HeldUntil string `json:"heldUntil,omitempty"`
	// ByProduct is point (f) when the product keeps the store's retention
	// itself (kit.RetentionByProduct), in its own words: no retention gap,
	// and no subject gap either.
	ByProduct *ProductRetentionSpec `json:"byProduct,omitempty"`
	// Security is point (g): the measures kit takes.
	Security []string `json:"security,omitempty"`
	// Gaps are the Gap constants the store lacks.
	Gaps []string `json:"gaps,omitempty"`
}

RegisterStoreMessage is one store's line in the register. It names the classes the store keeps, their purposes and their retention.

type RetentionSpec

type RetentionSpec struct {
	// After is the delay, as a Go duration: the declared one, or the
	// setting's value when the graph describes a running app.
	After string `json:"after,omitempty"`
	// Setting names the setting of the store's service the delay is read
	// from, when the environment gives it.
	Setting string `json:"setting,omitempty"`
	// Since locates the function that gives the instant the delay counts
	// from: a record's closing, say.
	Since *SourceMessage `json:"since,omitempty"`
	// At locates the function that gives the instant itself.
	At *SourceMessage `json:"at,omitempty"`
}

RetentionSpec is when kit erases or deletes a record: after a delay counted from an instant the record carries (After or Setting, and Since), or at an instant a function gives (At).

type RoleSpec

type RoleSpec struct {
	// Binary is the ID of the binary that holds it.
	Binary string `json:"binary"`
	// Profile is one of the Profile constants.
	Profile string `json:"profile"`
	// Args are the leading arguments that select it — ["daemon"] for
	// "statusline daemon" —; empty for the binary's default role.
	Args []string `json:"args,omitempty"`
	// Singleton, when set, is the scope of the lock that keeps one process of
	// this role alive at a time: what the lock's name is derived from.
	Singleton string `json:"singleton,omitempty"`
	// IdleMs is how long a daemon waits without a client before it stops
	// itself; zero means it runs until stopped.
	IdleMs int64 `json:"idleMs,omitempty"`
}

RoleSpec is one process role of a binary: the NodeEntity.Role of a KindRole node — its profile, arguments, singleton and idle stop.

type RuntimeMessage

type RuntimeMessage struct {
	// Phase is one of the Phase constants.
	Phase string `json:"phase"`
	// StartedAt is when the process started.
	StartedAt time.Time `json:"startedAt"`
	// Components are the lifecycle components, in start order.
	Components []ComponentMessage `json:"components"`
	// Loops are the recurring pieces of the internal loop.
	Loops []LoopMessage `json:"loops"`
	// History lists the phases the process went through, oldest first: the
	// daemon's own state machine, as it ran.
	History []PhaseChangeEvent `json:"history,omitempty"`
	// Process is the Go process, sampled when the graph was built; nil when
	// the product imports no framework/kit/server, which plugs the sampler
	// in (ADR 0172).
	Process *ProcessSpec `json:"process,omitempty"`
	// HTTP is the product's HTTP server.
	HTTP *HTTPServer `json:"http,omitempty"`
	// Mocks are the replacements a test gave the app (kit.Replace).
	Mocks []MockMessage `json:"mocks,omitempty"`
	// Dev describes the build `kit dev` made of this process, when it did.
	Dev *DevBuildMessage `json:"dev,omitempty"`
	// Config is how the product was configured when it started: every
	// setting kit read, the value it uses — never a secret's — and where
	// that value came from.
	Config []SettingMessage `json:"config,omitempty"`
	// Boot is what kit did to start the product, step by step, as it ran;
	// the lifecycle components it then started are Components.
	Boot []BootStepMessage `json:"boot,omitempty"`
	// Databases are the databases the app declares, as this run found them:
	// each one's state, readiness, pool and migrations.
	Databases []DatabaseMessage `json:"databases,omitempty"`
}

RuntimeMessage is what a running process says about itself: the daemon's own state and its internal loop.

type SchemaMessage

type SchemaMessage struct {
	// Type is "object", "array", "map", "string", "integer", "number",
	// "boolean" or "any".
	Type string `json:"type"`
	// Name is the qualified Go type name, for named types.
	Name string `json:"name,omitempty"`
	// Format refines a scalar: "date-time", "duration", "int64"…
	Format string `json:"format,omitempty"`
	// Fields are the members of an object.
	Fields []FieldMessage `json:"fields,omitempty"`
	// Items is the element type of an array.
	Items *SchemaMessage `json:"items,omitempty"`
	// Values is the value type of a map.
	Values *SchemaMessage `json:"values,omitempty"`
	// Enum lists the allowed values, when they are known.
	Enum []string `json:"enum,omitempty"`
	// Ref names a type already described higher up, to break a cycle.
	Ref string `json:"ref,omitempty"`
	// Nullable says a nil value is written null: a pointer, a slice, a map,
	// an interface — unless its member leaves it out (omitempty, omitzero).
	Nullable bool `json:"nullable,omitempty"`
}

SchemaMessage describes a Go type as it appears on the wire. It is a JSON-Schema-like shape: a kind, its fields or elements, and its Go type.

type SecretSpec

type SecretSpec struct {
	// Origin is [SecretProvided] or [SecretGenerated].
	Origin string `json:"origin"`
	// Variable is the environment variable that provides it, or — for a
	// generated secret — pins it: TODO_SMTP_URL, or TODO_SMTP_URL_FILE naming
	// a file.
	Variable string `json:"variable"`
	// Bytes is the size of each version of a generated secret.
	Bytes int `json:"bytes,omitempty"`
	// RotateEvery is how often kit makes a new version of a generated
	// secret, as a Go duration.
	RotateEvery string `json:"rotateEvery,omitempty"`
	// Keep is how many versions a rotation leaves, the new one included.
	Keep int `json:"keep,omitempty"`
	// Optional: a provided secret the product can do without
	// (kit.Optional) — found nowhere, it is absent, and the start goes on.
	Optional bool `json:"optional,omitempty"`

	// From is where the running app found it: one of the SecretFrom
	// constants, on a runtime graph. Empty when it is found nowhere — for an
	// optional secret, absent.
	From string `json:"from,omitempty"`
	// Version is the number of its current version, from 1.
	Version int `json:"version,omitempty"`
	// Created is when the current version was made; the environment does
	// not say when a variable was set.
	Created *time.Time `json:"created,omitempty"`
	// Versions is how many versions are kept.
	Versions int `json:"versions,omitempty"`
	// NextRotation is when kit rotates it next. Absent when kit does not
	// rotate it: provided, pinned by the environment, or in a store kit
	// cannot write.
	NextRotation *time.Time `json:"nextRotation,omitempty"`
	// Pinned: a generated secret the environment provides — kit uses it and
	// does not rotate it.
	Pinned bool `json:"pinned,omitempty"`
	// Rotations counts the rotations this process made.
	Rotations int `json:"rotations,omitempty"`
	// Problem says why it cannot be used, on a runtime graph.
	Problem string `json:"problem,omitempty"`
}

SecretSpec describes a declared secret: how it is made, where it lives, its versions — never its value.

type SelectCaseMessage

type SelectCaseMessage struct {
	// Text is the case as written: "<-ticker.C", "job := <-jobs".
	Text string `json:"text"`
	// Kind is one of the Select constants.
	Kind string `json:"kind"`
	// Source is where the case is.
	Source *SourceMessage `json:"source,omitempty"`
}

SelectCaseMessage is one case of a select statement in a hand-written loop. The analyzer reads it from the loop's body; Kind says what the case waits on.

type SettingMessage

type SettingMessage struct {
	// Name is the environment variable that sets it: "KIT_ADDR",
	// "TODO_BASE_URL".
	Name string `json:"name"`
	// Value is what kit uses. A secret's is left out: Secret says so.
	Value string `json:"value,omitempty"`
	// From is one of the Setting constants.
	From string `json:"from"`
	// Service declared it; empty for kit's own.
	Service string `json:"service,omitempty"`
	// Key is a declared setting's name, its key in a configuration file:
	// "base-url". A module's is qualified with the module's name,
	// "moderation.tdb-url": kit.Set's key, and in a file "tdb-url" under
	// "moderation:" (ADR 0008).
	Key string `json:"key,omitempty"`
	// Type is what a declared setting holds: text, bool, int, number,
	// duration or list.
	Type string `json:"type,omitempty"`
	// Detail is the configuration file that gave the value, when From is
	// SettingFile: "config/production.yaml".
	Detail string `json:"detail,omitempty"`
	// Secret: the value is withheld.
	Secret bool `json:"secret,omitempty"`
	// Option is the AppOption that sets it in code, when there is one:
	// "kit.Listen". Code wins over the environment.
	Option string `json:"option,omitempty"`
	// Flag is the kit dev flag that sets it in dev, when there is one:
	// "-addr".
	Flag string `json:"flag,omitempty"`
	// Database is the database the setting configures, when kit declares it
	// for one (kit.Database): its URL, its pool, its timeouts.
	Database string `json:"database,omitempty"`
}

SettingMessage is one configuration value kit read when the product started: kit's own, or one a service of the product declares.

type SnippetMessage

type SnippetMessage struct {
	// File is relative to App.Root.
	File string `json:"file"`
	// StartLine is the 1-based line of Lines[0].
	StartLine int `json:"startLine"`
	// Focus is the first line of the range asked for.
	Focus int `json:"focus"`
	// FocusEnd is the last line of the range asked for.
	FocusEnd int `json:"focusEnd,omitempty"`
	// Lines are the file's lines around the focus, without terminators.
	Lines []string `json:"lines"`
	// Language is the highlighter language: "go", "javascript"…
	Language string `json:"language"`
}

SnippetMessage is source code served to a reader of the graph. Focus and FocusEnd mark the lines a reader asked for, inside the lines served.

type SourceMessage

type SourceMessage struct {
	// File is relative to App.Root, slash-separated — or, when GoModule is
	// set, to the root of that Go module.
	File string `json:"file"`
	// Line is 1-based.
	Line int `json:"line"`
	// EndLine, when set, closes the range [Line, EndLine].
	EndLine int `json:"endLine,omitempty"`
	// Func is the qualified Go function, when the range is a function.
	Func string `json:"func,omitempty"`
	// GoModule is set on a position outside the product's Go module — a
	// module's (ADR 0008), a library's —: that Go module, "path@version", or
	// its path alone when it is built from a local directory.
	GoModule string `json:"goModule,omitempty"`
}

SourceMessage locates code. File is relative to its module's root; Line and EndLine bound the declaration.

type SpanMessage

type SpanMessage struct {
	// TraceID groups the spans of one causal chain (W3C, hex).
	TraceID string `json:"traceId"`
	// SpanID identifies the span (W3C, hex).
	SpanID string `json:"spanId"`
	// ParentID is the parent span, absent on a root.
	ParentID string `json:"parentId,omitempty"`
	// Node is where the work happened.
	Node string `json:"node"`
	// From is the node that caused it: the edge this span travelled.
	From string `json:"from,omitempty"`
	// Edge is the kind of the edge From → Node.
	Edge EdgeKind `json:"edge,omitempty"`
	// Label refines Edge, like the edge's own label.
	Label string `json:"label,omitempty"`
	// Op is one of the Op constants.
	Op string `json:"op"`
	// Name is a low-cardinality operation name: a route pattern, "Get".
	Name string `json:"name"`
	// Start is when the work began.
	Start time.Time `json:"start"`
	// Ms is how long it took.
	Ms float64 `json:"ms"`
	// Status is StatusError when the product failed — what kit answers with
	// a 5xx — and StatusOK otherwise, a refusal the caller has to fix (not
	// found, invalid, conflict, rate limited…) included.
	Status string `json:"status"`
	// Code is the error code, when the work ended in one: a failure's, or a
	// refusal's ("not_found").
	Code string `json:"code,omitempty"`
	// Error is the wire-safe public message of a failure; a refusal has none.
	Error string `json:"error,omitempty"`
	// Attrs are allow-listed attributes: "http.status", "instance"…
	Attrs map[string]string `json:"attrs,omitempty"`
	// User is the authenticated caller's ID, when there is one.
	User string `json:"user,omitempty"`
	// Payload is what went in and out, in dev only, with secrets redacted.
	Payload *Payload `json:"payload,omitempty"`
}

SpanMessage is a finished unit of work, attributed to a node. Only allow-listed, wire-safe fields travel: no URL, no query string, no private error text.

type StateSpec

type StateSpec struct {
	// Name is the state value, as text.
	Name string `json:"name"`
	// Terminal is set when no transition leaves the state.
	Terminal bool `json:"terminal,omitempty"`
	// Count is how many instances are in the state, on a runtime graph.
	Count *int `json:"count,omitempty"`
	// OnEnter lists the hooks run when an instance enters the state.
	OnEnter []SourceMessage `json:"onEnter,omitempty"`
}

StateSpec is one state of a workflow. Terminal marks a state an instance stays in; Count is how many instances are in it.

type StatsMessage

type StatsMessage struct {
	// Count is how many times it ran.
	Count int64 `json:"count"`
	// Errors is how many of those failed.
	Errors int64 `json:"errors"`
	// LastAt is when it last ran.
	LastAt *time.Time `json:"lastAt,omitempty"`
	// AvgMs is the mean duration in milliseconds.
	AvgMs float64 `json:"avgMs"`
	// MaxMs is the longest duration in milliseconds.
	MaxMs float64 `json:"maxMs"`
}

StatsMessage are observed counters for a node or an edge. They are counters: they never move a graph's revision.

type StepEvent

type StepEvent struct {
	// Event is the transition's event name.
	Event string `json:"event"`
	// From is the state left.
	From string `json:"from"`
	// To is the state entered.
	To string `json:"to"`
	// At is when it happened.
	At time.Time `json:"at"`
	// Trigger is one of the Trigger constants.
	Trigger string `json:"trigger"`
	// Caller is the node that fired it, when code did.
	Caller string `json:"caller,omitempty"`
}

StepEvent is one transition in an instance's history. It carries the event, the states it went from and to, and when it fired.

type StoreDataMessage

type StoreDataMessage struct {
	// Store is the store's node ID.
	Store string `json:"store"`
	// Purpose is why the store keeps them.
	Purpose string `json:"purpose,omitempty"`
	// Retention says, in words, how long they keep their personal data.
	Retention string `json:"retention,omitempty"`
	// Recipients are who inside the product reads them, as far as the
	// running app knows.
	Recipients []string `json:"recipients,omitempty"`
	// Records are the records, their secret members left out. They hold the
	// person's data, which the Studio and the logs never show.
	Records []json.RawMessage `json:"records" kit:"personal"`
	// Former are the former values of the records' fields that keep them
	// (ADR 0007), record by record; a secret field's are left out.
	Former []RecordFormerMessage `json:"former,omitempty" kit:"personal"`
	// Versions are the versions of the records a store with revisions keeps
	// (ADR 0007 §3), record by record, their secret members left out.
	Versions []ExportedVersionsMessage `json:"versions,omitempty" kit:"personal"`
}

StoreDataMessage is one store's records about a person. It is one part of what kit.Export gives a person about themselves.

type StoreErasureMessage

type StoreErasureMessage struct {
	// Store is the store's node ID.
	Store string `json:"store"`
	// Erased are the records whose personal data was cleared.
	Erased []string `json:"erased,omitempty" kit:"personal"`
	// Deleted are the records removed.
	Deleted []string `json:"deleted,omitempty" kit:"personal"`
	// Held are the records a hold keeps, untouched.
	Held []string `json:"held,omitempty" kit:"personal"`
}

StoreErasureMessage is one store's part of an erasure: the keys of the records erased, deleted, and held — left in place, as a legal hold asks. A key may be personal data, which the Studio and the logs never show.

type StoreHistoryMessage

type StoreHistoryMessage struct {
	// Revisions is how many former versions each record keeps
	// (kit.Revisions, ADR 0007 §3); zero when it keeps none.
	Revisions int `json:"revisions,omitempty"`
	// Fields are the JSON pointers of the fields that keep their former
	// values: tagged history=N — the schema's Field.History says how many —
	// or read by a password policy that refuses former passwords.
	Fields []string `json:"fields,omitempty"`
	// Passwords are the store's password policies.
	Passwords []PasswordPolicyMessage `json:"passwords,omitempty"`
	// Kept is how many former values the store keeps, and Bytes what its
	// histories weigh, on a runtime graph.
	Kept  *int   `json:"kept,omitempty"`
	Bytes *int64 `json:"bytes,omitempty"`
}

StoreHistoryMessage is what a store remembers of its records. Fields names the fields it keeps former values of; Kept and Bytes weigh them.

type StorePrivacyMessage

type StorePrivacyMessage struct {
	// Subject is the JSON pointer of the field that says whom each record is
	// about: "/email". Empty when the entity has no subject field.
	Subject string `json:"subject,omitempty"`
	// Purpose is why the store keeps its records, as kit.Purpose says it.
	Purpose string `json:"purpose,omitempty"`
	// Erase says when kit clears a record's personal data; Delete when it
	// removes the record.
	Erase  *RetentionSpec `json:"erase,omitempty"`
	Delete *RetentionSpec `json:"delete,omitempty"`
	// ByProduct is set when the product keeps the store's retention itself
	// (kit.RetentionByProduct): kit runs none — Erase and Delete are then
	// absent — and asks for neither a retention nor a subject.
	ByProduct *ProductRetentionSpec `json:"byProduct,omitempty"`
	// HeldUntil holds each record until an instant it carries: the law's
	// own retention (kit.HeldUntil).
	HeldUntil *HeldUntilSpec `json:"heldUntil,omitempty"`
	// Anonymise locates the function that says what an erased record keeps,
	// generalised (kit.Anonymise).
	Anonymise *SourceMessage `json:"anonymise,omitempty"`
	// DeleteOnErasure: a person's erasure deletes the record instead of
	// clearing it (kit.DeleteOnErasure).
	DeleteOnErasure bool `json:"deleteOnErasure,omitempty"`

	// Held is how many records a hold keeps, on a runtime graph.
	Held *int `json:"held,omitempty"`
	// Due is when the next record is due to be erased or deleted, on a
	// runtime graph; absent when none is.
	Due *time.Time `json:"due,omitempty"`
	// Erased and Deleted count what this run erased and deleted, on a
	// runtime graph.
	Erased  *int `json:"erased,omitempty"`
	Deleted *int `json:"deleted,omitempty"`
}

StorePrivacyMessage is what a store keeps of people: whom each record is about, why, for how long, and — on a runtime graph — what is held and due.

type StoreSpec

type StoreSpec struct {
	// Entity is the stored type.
	Entity *SchemaMessage `json:"entity,omitempty"`
	// Backend is where the store's data is: "memory", "file", or the engine
	// of the database that keeps it (ADR 0004): "postgres", "mysql",
	// "sqlite".
	Backend string `json:"backend"`
	// Location is where a file backend keeps its data, relative to the data
	// directory.
	Location string `json:"location,omitempty"`
	// Database names the database that keeps the store, as the app declares
	// it (kit.Database, kit.Keeps) — present even while the store's data
	// stays in the data directory, in dev without the database's URL. Its
	// container is "container:database:<name>".
	Database string `json:"database,omitempty"`
	// Table is the table the database keeps the store's entities in —
	// "<service>__<store>", '-' and '.' written '_', a digest past the
	// engine's limit —, beside its index rows in "<table>___ix". Present
	// with Database.
	Table string `json:"table,omitempty"`
	// Count is how many entities the store holds, on a runtime graph.
	Count *int `json:"count,omitempty"`
	// Indexes are the secondary indexes the store maintains, in declaration
	// order.
	Indexes []IndexSpec `json:"indexes,omitempty"`
	// Privacy says what the store does with personal data (ADR 0006): whom
	// its records are about, why it keeps them and for how long. Absent when
	// its entity holds nothing personal and it declares no retention.
	Privacy *StorePrivacyMessage `json:"privacy,omitempty"`
	// History says what the store remembers of its records (ADR 0007): the
	// fields that keep their former values, its password policies. Absent
	// when it remembers nothing and has no policy.
	History *StoreHistoryMessage `json:"history,omitempty"`
	// ReadModel is set on a store derived from others (kit.ReadModel):
	// written by projections — subscriptions —, read by queries.
	ReadModel bool `json:"readModel,omitempty"`
}

StoreSpec describes a store. It carries the entity's schema, its backend, its indexes, its privacy and its history.

type SubscriptionSpec

type SubscriptionSpec struct {
	// Topic is the node ID of the consumed topic; empty for a watch.
	Topic string `json:"topic"`
	// Mark is what a watch hears the writes of: "personal", "special" or
	// "moderated", ADR 0006's marks. Empty for a subscription.
	Mark string `json:"mark,omitempty"`
	// OwnStores: the watch hears its own module's stores too — the
	// product's own, for a watch of the product's (kit.OwnStores) —, never
	// the writes its own handler makes.
	OwnStores bool `json:"ownStores,omitempty"`
	// Stores are the node IDs of the stores that feed a watch, sorted: those
	// whose entity holds a field with its mark, but its own module's — the
	// product's own, for a watch of the product's — unless OwnStores. Each
	// draws a declared delivers edge to it.
	Stores []string `json:"stores,omitempty"`
	// MaxDeliveries is how many attempts a message gets before it is
	// dead-lettered.
	MaxDeliveries int `json:"maxDeliveries,omitempty"`
	// Parallelism is how many messages are handled concurrently.
	Parallelism int `json:"parallelism,omitempty"`
	// DeadLetters is how many messages were abandoned, on a runtime graph.
	DeadLetters *int `json:"deadLetters,omitempty"`
}

SubscriptionSpec describes a subscription — or a watch (ADR 0008), a subscription whose deliveries come from stores instead of a topic.

type SystemMessage

type SystemMessage struct {
	// ID is unique in the architecture: "system:smtp".
	ID string `json:"id"`
	// Name is what the diagram prints: "SMTP relay".
	Name string `json:"name"`
	// Doc says what it is to the product.
	Doc string `json:"doc,omitempty"`
	// Technology names how it is reached: "SMTP · STARTTLS".
	Technology string `json:"technology,omitempty"`
	// Location says where, when it is known and not secret: "smtp.example.com:587".
	Location string `json:"location,omitempty"`
	// Nodes are the nodes of the product that talk to it.
	Nodes []string `json:"nodes,omitempty"`
}

SystemMessage is a software system outside the product. Nodes are the product's nodes that talk to it; Technology says what it runs on.

type TopicSpec

type TopicSpec struct {
	// Message is the published type.
	Message *SchemaMessage `json:"message,omitempty"`
	// Delivery is the guarantee: "at-least-once".
	Delivery string `json:"delivery"`
	// Broker is "memory" or "file".
	Broker string `json:"broker,omitempty"`
}

TopicSpec describes a topic. It carries the message's schema; its subscriptions are the nodes it delivers to.

type TraceMessage

type TraceMessage struct {
	// TraceID identifies the trace.
	TraceID string `json:"traceId"`
	// Root is the node of the root span.
	Root string `json:"root"`
	// Name is the root span's name.
	Name string `json:"name"`
	// Start is when the root began.
	Start time.Time `json:"start"`
	// Ms spans from the first start to the last end.
	Ms float64 `json:"ms"`
	// Status is StatusError when any span failed.
	Status string `json:"status"`
	// Spans are in start order.
	Spans []SpanMessage `json:"spans"`
}

TraceMessage is the spans sharing one trace ID, root first. The root span is the one with no parent in the trace; the others follow it.

type TransitionEvent

type TransitionEvent struct {
	// Workflow is the workflow node ID.
	Workflow string `json:"workflow"`
	// Instance is the entity key.
	Instance string `json:"instance"`
	// Event is the transition's event name.
	Event string `json:"event"`
	// From is the state left; empty on creation.
	From string `json:"from"`
	// To is the state entered.
	To string `json:"to"`
	// Trigger is one of the Trigger constants.
	Trigger string `json:"trigger"`
	// Caller is the node that fired it, when code did.
	Caller string `json:"caller,omitempty"`
}

TransitionEvent is one workflow instance moving between states. It names the workflow, the entity, the event and the states it went from and to.

type TransitionSpec

type TransitionSpec struct {
	// Event names the transition. Timer and guard transitions have one too.
	Event string `json:"event"`
	// From is the source state.
	From string `json:"from"`
	// To is the target state.
	To string `json:"to"`
	// Trigger is [TriggerEvent], [TriggerTimer] or [TriggerGuard].
	Trigger string `json:"trigger"`
	// After is the delay of a timer transition, as a Go duration string.
	After string `json:"after,omitempty"`
	// Setting names the setting of the service the delay is read from, when
	// the environment gives it: "archive-after".
	Setting string `json:"setting,omitempty"`
	// At locates the function that says when a timer transition declared at
	// an instant is due — a due date, a deadline the entity carries.
	At *SourceMessage `json:"at,omitempty"`
	// Guard locates the condition of a guard transition.
	Guard *SourceMessage `json:"guard,omitempty"`
	// Source is where the transition is declared.
	Source *SourceMessage `json:"source,omitempty"`
	// Callers are the node IDs found to fire this event.
	Callers []string `json:"callers,omitempty"`
}

TransitionSpec is one arrow of a workflow. It names the event that fires it and the states it goes from and to.

type WakeSourceMessage

type WakeSourceMessage struct {
	// Kind is one of the Wake constants.
	Kind string `json:"kind"`
	// Every is the period of an interval wake, as a Go duration.
	Every string `json:"every,omitempty"`
	// Topic is the node ID of a topic wake.
	Topic string `json:"topic,omitempty"`
	// Func locates the function computing a deadline wake.
	Func *SourceMessage `json:"func,omitempty"`
}

WakeSourceMessage is one thing that wakes a declared loop. Kind says whether a topic, a period (Every) or a function wakes the loop.

type WorkflowSpec

type WorkflowSpec struct {
	// Store is the node ID of the store holding the instances.
	Store string `json:"store"`
	// Field is the wire name of the entity field holding the state, when the
	// state function points at a field of the entity.
	Field string `json:"field,omitempty"`
	// Initial is the state a new instance enters.
	Initial string `json:"initial"`
	// States are in declaration order.
	States []StateSpec `json:"states"`
	// Transitions are in declaration order.
	Transitions []TransitionSpec `json:"transitions"`
}

WorkflowSpec describes a state machine bound to a store. It carries the states and the transitions between them, and the store it lives in.

Jump to

Keyboard shortcuts

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