The node-engine seat whole: every verb's answer, its events' bodies, and ADR 0618's manifest-reads and manifest-reads-changed
The seat's area changes in this milestone, so it moves whole into its contracts (ADR 0613 §3): the eleven verbs it serves get their answers as the engine writes them, asked, done and refused their body, and the seat serves the optional verb manifest-reads (ADR 0618 §3) and says manifest-reads-changed (§4). Each event is published per node, the node's name its last token (by-caller), and kept with the seat's events for seven days. compose-candidate's input is a boolean, as the engine and the checker read it. Fixtures for every event, compose-candidate's input and three answers. Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
@@ -0,0 +1,539 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "node-engine", defined whole (seats/node-engine/seat.json): The node seat every node's engine holds (novox/hq ADR 0563, ADR 0618 §3, §4): its hand acts on the operator's warrant, its read-only judgements, its compositions and what it reads of a manifest. Each verb is answered on this node's subject, mesh.seat.node-engine.tool.<verb>.<node>, and each event is published on mesh.seat.node-engine.event.<event>.<node>, the node's name its last token.
|
||||
|
||||
export const seat = "node-engine";
|
||||
|
||||
export const verbs = {
|
||||
handOver: "hand-over",
|
||||
accessAct: "access-act",
|
||||
judgeDirectories: "judge-directories",
|
||||
setuidSearch: "setuid-search",
|
||||
rootFree: "root-free",
|
||||
acts: "acts",
|
||||
packages: "packages",
|
||||
composition: "composition",
|
||||
compose: "compose",
|
||||
composeCandidate: "compose-candidate",
|
||||
pullWaits: "pull-waits",
|
||||
manifestReads: "manifest-reads",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
asked: "asked",
|
||||
done: "done",
|
||||
refused: "refused",
|
||||
manifestReadsChanged: "manifest-reads-changed",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "node-engine.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export function askedSubject(caller: string): string {
|
||||
return "mesh.seat.node-engine.event.asked." + caller;
|
||||
}
|
||||
|
||||
export function doneSubject(caller: string): string {
|
||||
return "mesh.seat.node-engine.event.done." + caller;
|
||||
}
|
||||
|
||||
export function refusedSubject(caller: string): string {
|
||||
return "mesh.seat.node-engine.event.refused." + caller;
|
||||
}
|
||||
|
||||
export function manifestReadsChangedSubject(caller: string): string {
|
||||
return "mesh.seat.node-engine.event.manifest-reads-changed." + caller;
|
||||
}
|
||||
|
||||
/** one act asked through the seat, as acts reads it (ADR 0563 §9) */
|
||||
export interface Act {
|
||||
/** the act: hand-over, access-act, judge-directories or setuid-search */
|
||||
"act": string;
|
||||
/** the operator's ask of a hand-over or an access act */
|
||||
"ask"?: string;
|
||||
/** when it was asked, RFC 3339 */
|
||||
"at": string;
|
||||
/** the engine asked it itself, on finding a library's root holding data outside its group (ADR 0563 §4) */
|
||||
"auto"?: boolean;
|
||||
/** who answered, as the operator's warrant names them */
|
||||
"by"?: string;
|
||||
/** the caller as the runtime proved it */
|
||||
"caller": string;
|
||||
/** what the engine read on disk when it judged */
|
||||
"disk"?: string;
|
||||
/** when it ended, RFC 3339 */
|
||||
"ended"?: string;
|
||||
/** when the ask ends unanswered, RFC 3339 */
|
||||
"expires"?: string;
|
||||
/** the act's id */
|
||||
"id": string;
|
||||
/** the directory the act changes */
|
||||
"path"?: string;
|
||||
/** the warrant's proofs */
|
||||
"proofs"?: string[];
|
||||
/** what the engine said of it: its outcome or why it was refused */
|
||||
"said"?: string;
|
||||
/** the owner, group and mode it sets, in words */
|
||||
"sets"?: string;
|
||||
/** where it stands */
|
||||
"state": "asked" | "done" | "refused" | "answered";
|
||||
/** the path of a hand-over, or the access of an access act */
|
||||
"subject"?: string;
|
||||
/** the channel the warrant came on */
|
||||
"via"?: string;
|
||||
/** why it was asked, in words */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** what the seat says of an act: the act, the path or access, the caller as the runtime proved it and the ask (ADR 0563 §1) */
|
||||
export interface ActSaid {
|
||||
/** the act */
|
||||
"act": string;
|
||||
/** the operator's ask */
|
||||
"ask"?: string;
|
||||
/** the caller as the runtime proved it */
|
||||
"caller": string;
|
||||
/** the node whose engine says it */
|
||||
"node": string;
|
||||
/** what the engine said of it */
|
||||
"said"?: string;
|
||||
/** where the act stands */
|
||||
"state": "asked" | "done" | "refused";
|
||||
/** the path or the access */
|
||||
"subject"?: string;
|
||||
}
|
||||
|
||||
/** the acts kept */
|
||||
export interface Acts {
|
||||
/** the acts, newest first */
|
||||
"acts": Act[];
|
||||
/** the node */
|
||||
"node": string;
|
||||
}
|
||||
|
||||
/** the answer of an act the operator is asked */
|
||||
export interface Asked {
|
||||
/** the ask's id: acts shows where it stands */
|
||||
"asked": string;
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** what happens next, in words */
|
||||
"says": string;
|
||||
}
|
||||
|
||||
/** what a node-engine says when what it reads changed or its node returned (ADR 0618 §4) */
|
||||
export interface ManifestReadsChanged {
|
||||
/** when it says it, RFC 3339 */
|
||||
"at": string;
|
||||
/** what its engine states it reads now */
|
||||
"manifest-reads"?: string[];
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** the layout's version */
|
||||
"v": number;
|
||||
/** started: the engine started or what it states changed; returned: its node returned after being away */
|
||||
"why": "started" | "returned";
|
||||
}
|
||||
|
||||
/** one module's composition with the candidate */
|
||||
export interface Module {
|
||||
/** the candidate changes it from the one composed without it */
|
||||
"changed"?: boolean;
|
||||
/** the composition's digest when composed */
|
||||
"digest"?: string;
|
||||
/** the fingerprint it was composed at */
|
||||
"fp"?: string;
|
||||
/** the module, node for the node's own composition */
|
||||
"module": string;
|
||||
/** composed (digest set), refused by the candidate, or held without it too (words set) */
|
||||
"state": "composed" | "refused" | "held";
|
||||
/** why, for a refused or held one */
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** one revision of a composition key */
|
||||
export interface Revision {
|
||||
/** its digest */
|
||||
"digest"?: string;
|
||||
/** the composition's key */
|
||||
"key": string;
|
||||
/** the latest revision */
|
||||
"latest"?: boolean;
|
||||
/** why it cannot be read or trusted */
|
||||
"refused"?: string;
|
||||
/** how many resources it names */
|
||||
"resources"?: number;
|
||||
/** its revision */
|
||||
"revision"?: number;
|
||||
}
|
||||
|
||||
/** the engine's root-free verdict (ADR 0563 §6) */
|
||||
export interface RootVerdict {
|
||||
/** the machine is root-free */
|
||||
"free": boolean;
|
||||
/** when the engine judged it, RFC 3339 */
|
||||
"judged": string;
|
||||
/** the machine */
|
||||
"machine": string;
|
||||
/** why, in words */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** the answer of a read-only judgement */
|
||||
export interface Said {
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** the engine's judgement or search, one line per directory or program */
|
||||
"said": string;
|
||||
}
|
||||
|
||||
/** is what hand-over takes. */
|
||||
export interface HandOverInput {
|
||||
/** the directory's absolute path, as the engine states it */
|
||||
"path": string;
|
||||
/** why it is asked, in words the operator reads */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what hand-over answers. */
|
||||
export type HandOverAnswer = Asked;
|
||||
|
||||
/** is what access-act takes. */
|
||||
export interface AccessActInput {
|
||||
/** the access, library:<name> */
|
||||
"access": string;
|
||||
/** the act: take */
|
||||
"act": string;
|
||||
/** why it is asked, in words the operator reads */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what access-act answers. */
|
||||
export type AccessActAnswer = Asked;
|
||||
|
||||
/** is what judge-directories takes. */
|
||||
export interface JudgeDirectoriesInput {
|
||||
}
|
||||
|
||||
/** is what judge-directories answers. */
|
||||
export type JudgeDirectoriesAnswer = Said;
|
||||
|
||||
/** is what setuid-search takes. */
|
||||
export interface SetuidSearchInput {
|
||||
/** why it is asked, in words */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what setuid-search answers. */
|
||||
export type SetuidSearchAnswer = Said;
|
||||
|
||||
/** is what root-free takes. */
|
||||
export interface RootFreeInput {
|
||||
}
|
||||
|
||||
/** is what root-free answers. */
|
||||
export interface RootFreeAnswer {
|
||||
/** this machine's verdict */
|
||||
"machines": RootVerdict[];
|
||||
}
|
||||
|
||||
/** is what acts takes. */
|
||||
export interface ActsInput {
|
||||
/** one act, by its id */
|
||||
"id"?: string;
|
||||
/** at most this many, newest */
|
||||
"limit"?: string;
|
||||
}
|
||||
|
||||
/** is what acts answers. */
|
||||
export type ActsAnswer = Acts;
|
||||
|
||||
/** is what packages takes. */
|
||||
export interface PackagesInput {
|
||||
/** "true": write this machine's key again from what the engine composed */
|
||||
"write"?: "true" | "false";
|
||||
}
|
||||
|
||||
export interface PackagesAnswerKeyPackagesItem {
|
||||
/** declared absent */
|
||||
"absent": boolean;
|
||||
/** the modules that declare it */
|
||||
"modules": string[];
|
||||
/** the package */
|
||||
"package": string;
|
||||
}
|
||||
|
||||
/** the node's key as the bus holds it; absent when the engine wrote none */
|
||||
export interface PackagesAnswerKey {
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** its packages sorted by name, absent after present */
|
||||
"packages": PackagesAnswerKeyPackagesItem[];
|
||||
}
|
||||
|
||||
/** is what packages answers. */
|
||||
export interface PackagesAnswer {
|
||||
/** the node's key as the bus holds it; absent when the engine wrote none */
|
||||
"key"?: PackagesAnswerKey;
|
||||
/** why the key could not be read */
|
||||
"key_error"?: string;
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** a note, such as that no key is written yet */
|
||||
"note"?: string;
|
||||
/** where the key is read: the engine's state packages */
|
||||
"source": string;
|
||||
/** with write: the key was written again (false: it already held what the engine composed) */
|
||||
"wrote"?: boolean;
|
||||
}
|
||||
|
||||
/** is what composition takes. */
|
||||
export interface CompositionInput {
|
||||
/** "true": list the resources that differ from what runs */
|
||||
"diff"?: string;
|
||||
/** a composition's digest (sha256:…), to read that revision rather than the latest */
|
||||
"digest"?: string;
|
||||
/** the module, as placed on this machine; node for the node's own */
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** the module's last apply that did not end running; absent when none */
|
||||
export interface CompositionAnswerAttempt {
|
||||
/** the want's revision the hold took */
|
||||
"answered_revision"?: number;
|
||||
/** the digest tried */
|
||||
"composed"?: string;
|
||||
/** the composition's revision it was tried at */
|
||||
"composition_revision": number;
|
||||
/** the fingerprint tried */
|
||||
"fp": string;
|
||||
/** held for a failed backup */
|
||||
"held"?: boolean;
|
||||
/** it failed because the bus did not answer for a moment */
|
||||
"transient"?: boolean;
|
||||
/** the want's revision it was tried at */
|
||||
"want_revision": number;
|
||||
}
|
||||
|
||||
/** what the module's have key says now; absent when it says nothing */
|
||||
export interface CompositionAnswerHave {
|
||||
/** digest */
|
||||
"composed"?: string;
|
||||
/** detail */
|
||||
"detail"?: string;
|
||||
/** fingerprint */
|
||||
"fp"?: string;
|
||||
/** judgement */
|
||||
"judgement"?: string;
|
||||
/** running, failed, held or waiting-yes */
|
||||
"phase": string;
|
||||
/** the digest that waits for a yes */
|
||||
"waits"?: string;
|
||||
}
|
||||
|
||||
/** the move from what runs to the composition read */
|
||||
export interface CompositionAnswerJudged {
|
||||
/** the judgement */
|
||||
"judgement": string;
|
||||
/** the agent would wait for a person's yes before applying it */
|
||||
"waits_for_yes": boolean;
|
||||
/** its words */
|
||||
"words": string;
|
||||
}
|
||||
|
||||
/** of the node's own composition, its own fields beside what runs names */
|
||||
export interface CompositionAnswerOwn {
|
||||
/** the revision's adoption; absent for a converged node */
|
||||
"adoption"?: Record<string, unknown>;
|
||||
/** groups */
|
||||
"groups"?: number;
|
||||
/** each module the node's composer held in its last pass, with why */
|
||||
"held"?: Record<string, string>;
|
||||
/** identities the revision names */
|
||||
"identities"?: number;
|
||||
/** libraries */
|
||||
"libraries"?: number;
|
||||
/** the account the provisioner's client runs as, as the revision names it */
|
||||
"provisioner_account": string;
|
||||
/** as what runs names it */
|
||||
"runs_provisioner_account"?: string;
|
||||
}
|
||||
|
||||
/** what runs of the module; absent when nothing runs */
|
||||
export interface CompositionAnswerRuns {
|
||||
/** digest */
|
||||
"composed"?: string;
|
||||
/** fingerprint */
|
||||
"fp"?: string;
|
||||
/** applied, have or kept */
|
||||
"from": string;
|
||||
/** phase */
|
||||
"phase"?: string;
|
||||
/** how many resources run */
|
||||
"resources": number;
|
||||
}
|
||||
|
||||
/** the module's want as the agent holds it; absent when it holds none */
|
||||
export interface CompositionAnswerWant {
|
||||
/** the operator's answer to a failed backup, again or skip */
|
||||
"backup"?: string;
|
||||
/** the composition's digest it names */
|
||||
"composed"?: string;
|
||||
/** its build's fingerprint */
|
||||
"fp": string;
|
||||
/** the module is removed */
|
||||
"removed"?: boolean;
|
||||
/** the revision of the want's key read last */
|
||||
"revision": number;
|
||||
/** the node composes the module itself (ADR 0547 §2) */
|
||||
"self"?: boolean;
|
||||
/** its words */
|
||||
"words"?: string;
|
||||
/** the digest a person said yes to */
|
||||
"yes"?: string;
|
||||
}
|
||||
|
||||
/** is what composition answers. */
|
||||
export interface CompositionAnswer {
|
||||
/** the module's last apply that did not end running; absent when none */
|
||||
"attempt"?: CompositionAnswerAttempt;
|
||||
"composition": Revision;
|
||||
/** every resource that differs from what runs, when asked */
|
||||
"diff"?: Record<string, unknown>[];
|
||||
/** what the module's have key says now; absent when it says nothing */
|
||||
"have"?: CompositionAnswerHave;
|
||||
/** the move from what runs to the composition read */
|
||||
"judged": CompositionAnswerJudged;
|
||||
/** the module */
|
||||
"module": string;
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** of the node's own composition, its own fields beside what runs names */
|
||||
"own"?: CompositionAnswerOwn;
|
||||
/** the revisions of its key the bucket keeps, oldest first */
|
||||
"revisions"?: Revision[];
|
||||
/** what runs of the module; absent when nothing runs */
|
||||
"runs"?: CompositionAnswerRuns;
|
||||
/** the agent has looked at the module once since it started */
|
||||
"started": boolean;
|
||||
/** the module's want as the agent holds it; absent when it holds none */
|
||||
"want"?: CompositionAnswerWant;
|
||||
}
|
||||
|
||||
/** is what compose takes. */
|
||||
export interface ComposeInput {
|
||||
/** a module placed on this machine whose apply is also tried again (optional) */
|
||||
"module"?: string;
|
||||
}
|
||||
|
||||
/** how the pass went */
|
||||
export interface ComposeAnswerPass {
|
||||
/** when the node composes again on its own, RFC 3339 */
|
||||
"again"?: string;
|
||||
/** when the pass ended, RFC 3339 */
|
||||
"at": string;
|
||||
/** the answer is the last pass, made moments ago */
|
||||
"earlier"?: boolean;
|
||||
/** how many compositions the pass handed the agent that differ from before */
|
||||
"handed": number;
|
||||
/** each module refused alone, with why */
|
||||
"held"?: Record<string, string>;
|
||||
/** why the node composed none of its modules */
|
||||
"refused"?: string;
|
||||
}
|
||||
|
||||
/** is what compose answers. */
|
||||
export interface ComposeAnswer {
|
||||
/** how the pass went */
|
||||
"pass": ComposeAnswerPass;
|
||||
/** the module whose apply was tried again */
|
||||
"retried"?: string;
|
||||
}
|
||||
|
||||
/** is what compose-candidate takes. */
|
||||
export interface ComposeCandidateInput {
|
||||
/** the key of the indexer's candidate, <group>.<heads hash> */
|
||||
"candidate": string;
|
||||
/** also answer the composition input the candidate was composed from, for the sandbox path */
|
||||
"input"?: boolean;
|
||||
}
|
||||
|
||||
/** is what compose-candidate answers. */
|
||||
export interface ComposeCandidateAnswer {
|
||||
/** the candidate's key */
|
||||
"candidate": string;
|
||||
/** when asked: the composition input it composed from */
|
||||
"input"?: Record<string, unknown>;
|
||||
/** every module placed on the node, sorted by name */
|
||||
"modules": Module[];
|
||||
/** the node */
|
||||
"node": string;
|
||||
"own": Module;
|
||||
/** why the node could not compose with the candidate at all */
|
||||
"refused"?: string;
|
||||
/** how long the engine took, in milliseconds */
|
||||
"took": number;
|
||||
/** the layout's version */
|
||||
"v": number;
|
||||
/** the node's verdict (ADR 0593 §7, §9) */
|
||||
"verdict": "composed" | "refused" | "unready" | "not-judged";
|
||||
}
|
||||
|
||||
/** is what pull-waits takes. */
|
||||
export interface PullWaitsInput {
|
||||
}
|
||||
|
||||
export interface PullWaitsAnswerWaitsItem {
|
||||
/** that seat's holder, whose settled the retry waits on */
|
||||
"holder"?: string;
|
||||
/** the image whose pull failed */
|
||||
"image": string;
|
||||
/** the module whose apply failed */
|
||||
"module": string;
|
||||
/** when the failed pull began, RFC 3339 */
|
||||
"pull-began"?: string;
|
||||
/** when it was last tried again, RFC 3339 */
|
||||
"retry-last"?: string;
|
||||
/** what started that retry: settled, or the engine's start */
|
||||
"retry-trigger"?: string;
|
||||
/** the seat the image came through */
|
||||
"seat"?: string;
|
||||
/** the settled events of the holder heard since the engine started */
|
||||
"settled-count"?: number;
|
||||
/** when the last was heard, RFC 3339 */
|
||||
"settled-last"?: string;
|
||||
}
|
||||
|
||||
/** is what pull-waits answers. */
|
||||
export interface PullWaitsAnswer {
|
||||
/** every failed pull waiting on a holder */
|
||||
"waits": PullWaitsAnswerWaitsItem[];
|
||||
}
|
||||
|
||||
/** is what manifest-reads takes. */
|
||||
export interface ManifestReadsInput {
|
||||
}
|
||||
|
||||
/** is what manifest-reads answers. */
|
||||
export interface ManifestReadsAnswer {
|
||||
/** the reader capabilities its engine states: the manifest words, forms and seat names it reads; empty for an engine built before it said them, read as the baseline */
|
||||
"manifest-reads"?: string[];
|
||||
/** the node */
|
||||
"node": string;
|
||||
/** when the engine last stated them, RFC 3339 */
|
||||
"stated-at": string;
|
||||
/** the layout's version */
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** is the body of the event asked. */
|
||||
export type AskedEvent = ActSaid;
|
||||
|
||||
/** is the body of the event done. */
|
||||
export type DoneEvent = ActSaid;
|
||||
|
||||
/** is the body of the event refused. */
|
||||
export type RefusedEvent = ActSaid;
|
||||
|
||||
/** is the body of the event manifest-reads-changed. */
|
||||
export type ManifestReadsChangedEvent = ManifestReadsChanged;
|
||||
|
||||
Reference in New Issue
Block a user