Regenerate the domain contracts; hand-acts and conditions clients; operator-channel client moves; the seat-set package ends (ADR 0634, ADR 0635; issue 1966)

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-05 13:19:37 +01:00
parent 23a759c78b
commit 211bdcaa5e
62 changed files with 3808 additions and 8976 deletions
-19
View File
@@ -1,19 +0,0 @@
{
"description": "The mesh's seat set, generated from every seat's definition.",
"devDependencies": {
"typescript": "^5.6.0"
},
"exports": {
".": "./dist/index.js"
},
"files": [
"dist"
],
"name": "@novox/mesh-contracts",
"scripts": {
"build": "tsc",
"prepare": "tsc"
},
"type": "module",
"version": "0.1.0"
}
+41
View File
@@ -32,6 +32,33 @@ export function retiredHolderSubject(holder: string): string {
return "mesh.stream." + holder + ".event.retired";
}
export const states = {
resolved: "resolved",
} as const;
/** The key of one value of the state resolved under the form "<node>.<module>.<key>". */
export function resolvedByNodeModuleKeyKey(node: string, module: string, key: string): string {
return node + "." + module + "." + key;
}
/** The parts of a key of the form "<node>.<module>.<key>", or undefined for a key of another form. */
export function parseResolvedByNodeModuleKeyKey(key: string): { node: string; module: string; key: string } | undefined {
let rest = key;
const at0 = rest.indexOf(".");
if (at0 <= 0) return undefined;
const node = rest.slice(0, at0);
rest = rest.slice(at0 + 1);
const at2 = rest.indexOf(".");
if (at2 <= 0) return undefined;
const module = rest.slice(0, at2);
rest = rest.slice(at2 + 1);
if (rest === "") return undefined;
const key = rest;
rest = "";
if (rest !== "") return undefined;
return { node, module, key };
}
/** is what config takes. */
export interface ConfigInput {
/** list (when not given), set, clear or history */
@@ -117,3 +144,17 @@ export interface RetiredHolderEvent {
"node"?: string;
}
/** is one value of the state resolved under the key <node>.<module>.<key>. */
export interface ResolvedByNodeModuleKeyValue {
"key": string;
"module": string;
"node": string;
/** the predefined key the value falls back to */
"predefined"?: string;
/** an unset value is the operator's own to set */
"required"?: boolean;
"source": string;
"trusted"?: boolean;
"value"?: unknown;
}
+215
View File
@@ -43,6 +43,121 @@ export function manifestReadsChangedSubject(caller: string): string {
return "mesh.seat.node-engine.event.manifest-reads-changed." + caller;
}
export const states = {
have: "have",
composed: "composed",
data: "data",
packages: "packages",
health: "health",
} as const;
/** The key of one value of the state have under the form "<node>.<module>". */
export function haveByNodeModuleKey(node: string, module: string): string {
return node + "." + module;
}
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
export function parseHaveByNodeModuleKey(key: string): { node: string; module: string } | undefined {
let rest = key;
const at0 = rest.indexOf(".");
if (at0 <= 0) return undefined;
const node = rest.slice(0, at0);
rest = rest.slice(at0 + 1);
if (rest === "") return undefined;
const module = rest;
rest = "";
if (rest !== "") return undefined;
return { node, module };
}
/** The key of one value of the state have under the form "<node>.node". */
export function haveByNodeNodeKey(node: string): string {
return node + ".node";
}
/** The parts of a key of the form "<node>.node", or undefined for a key of another form. */
export function parseHaveByNodeNodeKey(key: string): { node: string } | undefined {
let rest = key;
const at0 = rest.indexOf(".node");
if (at0 <= 0) return undefined;
const node = rest.slice(0, at0);
rest = rest.slice(at0 + 5);
if (rest !== "") return undefined;
return { node };
}
/** The key of one value of the state composed under the form "<node>.<module>.<fingerprint>". */
export function composedByNodeModuleFingerprintKey(node: string, module: string, fingerprint: string): string {
return node + "." + module + "." + fingerprint;
}
/** The parts of a key of the form "<node>.<module>.<fingerprint>", or undefined for a key of another form. */
export function parseComposedByNodeModuleFingerprintKey(key: string): { node: string; module: string; fingerprint: string } | undefined {
let rest = key;
const at0 = rest.indexOf(".");
if (at0 <= 0) return undefined;
const node = rest.slice(0, at0);
rest = rest.slice(at0 + 1);
const at2 = rest.indexOf(".");
if (at2 <= 0) return undefined;
const module = rest.slice(0, at2);
rest = rest.slice(at2 + 1);
if (rest === "") return undefined;
const fingerprint = rest;
rest = "";
if (rest !== "") return undefined;
return { node, module, fingerprint };
}
/** The key of one value of the state data under the form "<node>.<module>". */
export function dataByNodeModuleKey(node: string, module: string): string {
return node + "." + module;
}
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
export function parseDataByNodeModuleKey(key: string): { node: string; module: string } | undefined {
let rest = key;
const at0 = rest.indexOf(".");
if (at0 <= 0) return undefined;
const node = rest.slice(0, at0);
rest = rest.slice(at0 + 1);
if (rest === "") return undefined;
const module = rest;
rest = "";
if (rest !== "") return undefined;
return { node, module };
}
/** The key of one value of the state packages under the form "<node>". */
export function packagesByNodeKey(node: string): string {
return node;
}
/** The parts of a key of the form "<node>", or undefined for a key of another form. */
export function parsePackagesByNodeKey(key: string): { node: string } | undefined {
let rest = key;
if (rest === "") return undefined;
const node = rest;
rest = "";
if (rest !== "") return undefined;
return { node };
}
/** The key of one value of the state health under the form "<node>". */
export function healthByNodeKey(node: string): string {
return node;
}
/** The parts of a key of the form "<node>", or undefined for a key of another form. */
export function parseHealthByNodeKey(key: string): { node: string } | undefined {
let rest = key;
if (rest === "") return undefined;
const node = rest;
rest = "";
if (rest !== "") return undefined;
return { node };
}
/** 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 */
@@ -505,3 +620,103 @@ export type RefusedEvent = ActSaid;
/** is the body of the event manifest-reads-changed. */
export type ManifestReadsChangedEvent = ManifestReadsChanged;
/** is one value of the state have under the key <node>.<module>. */
export interface HaveByNodeModuleValue {
"build"?: string;
"build-alone"?: boolean;
/** the composition's digest */
"composed"?: string;
"detail"?: string;
/** the fingerprint held */
"fp"?: string;
/** the accounts handed */
"handed"?: Record<string, unknown>;
/** how it is */
"health": string;
"judgement"?: string;
"kept"?: string[];
/** how far it has come */
"phase": string;
/** a pull the engine waits for */
"pull-wait"?: Record<string, unknown>;
"sealed"?: string[];
"sealed-at"?: Record<string, unknown>;
/** the user list written */
"user-list"?: Record<string, unknown>;
"v": number;
/** what it waits for */
"waits"?: string;
}
/** is one value of the state have under the key <node>.node. */
export interface HaveByNodeNodeValue {
"busy"?: Record<string, unknown>;
"candidates"?: Record<string, Record<string, unknown>>;
"composed"?: string;
/** own, or the controller's */
"composes"?: string;
"composes-why"?: string;
"filters"?: Record<string, unknown>;
"profile"?: Record<string, unknown>;
/** the node's record: its tunnel and certificate */
"record"?: Record<string, unknown>;
"sealed"?: string[];
"sealed-at"?: Record<string, unknown>;
"strays"?: Record<string, unknown>;
"v": number;
"windows"?: Record<string, unknown>;
}
/** is one value of the state composed under the key <node>.<module>.<fingerprint>. */
export interface ComposedByNodeModuleFingerprintValue {
"Data"?: boolean;
"FP": string;
"Filled"?: string[];
"Module": string;
"Node": string;
/** the node's own adoption, identities, groups, libraries and provisioner account */
"Own"?: Record<string, unknown>;
/** the module's plan */
"Plan"?: Record<string, unknown>;
/** why the composition was refused */
"Refused"?: string;
"Resources"?: Record<string, unknown>[];
"V"?: number;
}
/** is one value of the state data under the key <node>.<module>. */
export interface DataByNodeModuleValue {
"digest": string;
"items": Record<string, unknown>[];
"module": string;
"node": string;
"v"?: number;
}
export interface PackagesByNodeValuePackagesItem {
"absent"?: boolean;
"modules"?: string[];
"package"?: string;
}
/** is one value of the state packages under the key <node>. */
export interface PackagesByNodeValue {
"node": string;
"packages": PackagesByNodeValuePackagesItem[];
}
/** is one value of the state health under the key <node>. */
export interface HealthByNodeValue {
"at": string;
"contract"?: number;
"fallback"?: Record<string, unknown>;
"found"?: Record<string, unknown>[];
"network"?: Record<string, unknown>;
"node": string;
"peers"?: Record<string, unknown>[];
"relogin"?: Record<string, unknown>[];
"root"?: Record<string, unknown>[];
"units"?: Record<string, unknown>;
"v": number;
}
-19
View File
@@ -1,19 +0,0 @@
{
"description": "The contract of the seat operator-channel, generated from its definition.",
"devDependencies": {
"typescript": "^5.6.0"
},
"exports": {
".": "./dist/index.js"
},
"files": [
"dist"
],
"name": "@novox/mesh-contracts-operator-channel",
"scripts": {
"build": "tsc",
"prepare": "tsc"
},
"type": "module",
"version": "0.1.0"
}
-282
View File
@@ -1,282 +0,0 @@
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
// The contract of the seat "operator-channel", defined whole (seats/operator-channel/seat.json): Asking a person and answering on a channel (ADR 0259): held by the router, the messenger module, whose manifest declares the seat; written from that seat entry (design 26).
export const seat = "operator-channel";
export const verbs = {
open: "open",
history: "history",
notify: "notify",
tell: "tell",
asks: "asks",
} as const;
export const accepts = {
ask: "ask",
cancel: "cancel",
condition: "condition",
} as const;
export const events = {
decided: "decided",
} as const;
export const family = { name: "operator-channel.decided", maxAgeDays: 7 } as const;
export function decidedSubject(caller: string): string {
return "mesh.seat.operator-channel.event.decided." + caller;
}
export function askSubject(caller: string): string {
return "mesh.seat.operator-channel.accept.ask." + caller;
}
export function cancelSubject(caller: string): string {
return "mesh.seat.operator-channel.accept.cancel." + caller;
}
export function conditionSubject(caller: string): string {
return "mesh.seat.operator-channel.accept.condition." + caller;
}
export const holderEvents = {
refused: "refused",
offered: "offered",
closed: "closed",
} as const;
export function refusedHolderSubject(holder: string): string {
return "mesh.mod." + holder + ".event.refused";
}
export function offeredHolderSubject(holder: string): string {
return "mesh.stream." + holder + ".event.offered";
}
export function closedHolderSubject(holder: string): string {
return "mesh.stream." + holder + ".event.closed";
}
export interface Ask {
/** what it is about: a newer ask about it replaces the older */
"about"?: string;
/** its secondary words */
"details"?: string;
/** when it ends unanswered, RFC 3339 */
"expires": string;
/** what happened and what it means */
"explanation": string;
/** a few plain words */
"headline": string;
/** the asker's own id */
"id": string;
/** what the asker then does */
"on-expiry": string;
/** the answers it offers */
"options": Option[];
/** urgent */
"urgent"?: boolean;
/** who may answer: operator */
"who": string;
/** the explanation with its values whole */
"whole"?: string;
/** the details whole */
"whole-details"?: string;
}
export interface ConditionActionsItem {
"arguments"?: Record<string, string>;
/** label */
"label": string;
/** level */
"level"?: string;
/** machine */
"machine"?: string;
/** verb */
"verb": string;
}
export interface ConditionSubject {
/** id */
"id": string;
/** machine */
"machine"?: string;
/** scope */
"scope": string;
}
export interface Condition {
/** the answers it offers */
"actions"?: ConditionActionsItem[];
/** plain words */
"explanation"?: string;
/** plain words */
"headline"?: string;
/** the condition's key */
"key": string;
/** what it needs */
"needs"?: string;
/** the line said when it is over */
"resolved"?: string;
/** urgent or warning */
"severity"?: string;
/** raised or cleared */
"state": string;
"subject": ConditionSubject;
/** one line */
"summary"?: string;
/** the form's version, 1 */
"v": number;
}
export interface Option {
/** the digest of exactly what the asker performs when it is chosen */
"binds"?: string;
/** what it does, in plain words */
"does": string;
/** the option's id */
"id": string;
/** the button's label */
"label": string;
/** the proof its answer needs */
"level": string;
}
export interface Person {
/** the name shown */
"display"?: string;
/** the account */
"identity": string;
/** the channel kind */
"kind": string;
/** how the router knew */
"verified": string;
/** the role */
"who": string;
}
export interface Warrant {
/** what it was about */
"about"?: string;
/** the ask */
"ask": string;
/** the digest of the ask as the router took it */
"ask-digest"?: string;
/** its asker */
"asker": string;
/** when, RFC 3339 */
"at": string;
"by"?: Person;
/** the module it came through */
"channel"?: string;
/** its label */
"label"?: string;
/** its level */
"level"?: string;
/** the option chosen */
"option"?: string;
"outcome": "chosen" | "expired" | "cancelled" | "replaced" | "refused";
/** the proofs present */
"proofs"?: string[];
/** why it ended without a choice, or what refused it */
"words"?: string;
}
/** is what open takes. */
export interface OpenInput {
}
/** is what open answers. */
export type OpenAnswer = Record<string, unknown>;
/** is what history takes. */
export interface HistoryInput {
/** at most this many of each (default 50) */
"limit"?: number;
}
/** is what history answers. */
export type HistoryAnswer = Record<string, unknown>;
/** is what notify takes. */
export interface NotifyInput {
/** it is over */
"clear"?: boolean;
/** one or two plain sentences */
"explanation"?: string;
/** plain words */
"headline"?: string;
/** the message's key */
"key"?: string;
/** the line said when it is over */
"resolved"?: string;
"severity"?: "urgent" | "warning";
/** what it is about */
"subject"?: string;
/** one line */
"summary"?: string;
}
/** is what notify answers. */
export type NotifyAnswer = Record<string, unknown>;
/** is what tell takes. */
export interface TellInput {
/** plain words */
"headline"?: string;
/** one or two plain lines */
"lines"?: string[];
/** what it is about */
"subject"?: string;
}
/** is what tell answers. */
export type TellAnswer = Record<string, unknown>;
/** is what asks takes. */
export interface AsksInput {
}
/** is what asks answers. */
export type AsksAnswer = Record<string, unknown>;
/** is the body of ask. */
export type AskAccept = Ask;
/** is the body of cancel. */
export interface CancelAccept {
/** the ask's id */
"id": string;
}
/** is the body of condition. */
export type ConditionAccept = Condition;
/** is the body of the event decided. */
export type DecidedEvent = Warrant;
/** is the body of the holder's event offered. */
export interface OfferedHolderEvent {
/** its asker */
"asker": string;
/** the channels it was offered on */
"channels"?: string[];
/** its headline */
"headline"?: string;
/** the ask's id */
"id": string;
}
/** is the body of the holder's event closed. */
export interface ClosedHolderEvent {
/** its asker */
"asker": string;
"how": "answered" | "expired" | "cancelled" | "replaced" | "unlinked";
/** the ask's id */
"id": string;
}
/** is one value of the record asks. */
export type AsksRecord = Record<string, unknown>;
-14
View File
@@ -1,14 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
"outDir": "dist",
"rootDir": "src",
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*.ts"]
}
-3
View File
@@ -1,3 +0,0 @@
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
export * as seats from "./seats.js";
-8185
View File
File diff suppressed because it is too large Load Diff
-14
View File
@@ -1,14 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
"outDir": "dist",
"rootDir": "src",
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*.ts"]
}