From 5cd44f0ebe1dd5cd18ddc1349d5f51b455afe7d4 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 11 Nov 2026 10:41:42 +0100 Subject: [PATCH] C9: the seat mesh-grants is defined whole: rule grant, the events wait-held, wait-ended, filling and room, and the read grants-for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewritten from the earlier branch to the final lines: the earlier verbs waits and release go (the part's tools stay its own), grants-for is added, wait events carry clock-from, filling and room carry a store's fill as mesh-wants' do. The generated Go and TypeScript wait on the generator. Builds: design 47 Where it goes (grants part), G §264, §266, §331, §401, §441 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ --- identity-and-access/module.json | 20 ++ identity-and-access/seats/index.json | 1 + .../seats/mesh-grants/fixtures/events.json | 56 +++++ .../seats/mesh-grants/fixtures/verbs.json | 28 +++ .../seats/mesh-grants/seat.json | 222 ++++++++++++++++++ .../seats/mesh-vault/seat.json | 4 +- 6 files changed, 328 insertions(+), 3 deletions(-) create mode 100644 identity-and-access/seats/mesh-grants/fixtures/events.json create mode 100644 identity-and-access/seats/mesh-grants/fixtures/verbs.json create mode 100644 identity-and-access/seats/mesh-grants/seat.json diff --git a/identity-and-access/module.json b/identity-and-access/module.json index 20e2d2c..4f3b3f3 100644 --- a/identity-and-access/module.json +++ b/identity-and-access/module.json @@ -23,6 +23,16 @@ "series": "0.1", "generated-from": "." }, + { + "name": "go-meshgrants", + "kind": "package", + "language": "go", + "paths": [ + "go/seats/meshgrants" + ], + "series": "0.1", + "generated-from": "." + }, { "name": "go-meshvaultclient", "kind": "package", @@ -60,6 +70,16 @@ ], "series": "0.1", "generated-from": "." + }, + { + "name": "ts-meshgrants", + "kind": "package", + "language": "typescript", + "paths": [ + "ts/seats/meshgrants" + ], + "series": "0.1", + "generated-from": "." } ] }, diff --git a/identity-and-access/seats/index.json b/identity-and-access/seats/index.json index 72e28e3..c8222f2 100644 --- a/identity-and-access/seats/index.json +++ b/identity-and-access/seats/index.json @@ -1,6 +1,7 @@ { "format": 1, "seats": [ + "mesh-grants", "mesh-node-enroller", "mesh-vault", "node-secret-service" diff --git a/identity-and-access/seats/mesh-grants/fixtures/events.json b/identity-and-access/seats/mesh-grants/fixtures/events.json new file mode 100644 index 0000000..6e72de6 --- /dev/null +++ b/identity-and-access/seats/mesh-grants/fixtures/events.json @@ -0,0 +1,56 @@ +[ + { + "name": "a granting wait held", + "of": "event:wait-held", + "subject": "mesh.seat.mesh-grants.event.wait-held", + "given": { + "step": "grant", + "part": "mesh-grants", + "version": "src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "module": "mesh-tools", + "fp": "src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "since": "2026-11-09T21:00:00Z", + "bound": "10m", + "clock-from": "2026-11-09T20:55:00Z" + } + }, + { + "name": "a granting wait released", + "of": "event:wait-ended", + "subject": "mesh.seat.mesh-grants.event.wait-ended", + "given": { + "step": "grant", + "part": "mesh-grants", + "version": "src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "module": "mesh-tools", + "fp": "src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "since": "2026-11-09T21:00:00Z", + "bound": "10m", + "how": "released", + "by": "jochen: the new grants part is stuck", + "clock-from": "2026-11-09T20:55:00Z" + } + }, + { + "name": "filling is said past 80 %", + "of": "event:filling", + "subject": "mesh.seat.mesh-grants.event.filling", + "given": { + "store": "SEAT_mesh-pipeline-runner_pipeline-ended", + "bytes": 161061273, + "cap": 201326592, + "at": "2026-11-11T09:00:00Z" + } + }, + { + "name": "room is said below 70 %", + "of": "event:room", + "subject": "mesh.seat.mesh-grants.event.room", + "given": { + "store": "SEAT_mesh-pipeline-runner_pipeline-ended", + "bytes": 100663296, + "cap": 201326592, + "at": "2026-11-11T10:00:00Z" + } + } +] diff --git a/identity-and-access/seats/mesh-grants/fixtures/verbs.json b/identity-and-access/seats/mesh-grants/fixtures/verbs.json new file mode 100644 index 0000000..e2bd9f1 --- /dev/null +++ b/identity-and-access/seats/mesh-grants/fixtures/verbs.json @@ -0,0 +1,28 @@ +[ + { + "name": "grants-for answers the grants a candidate adds", + "of": "verb:grants-for.answer", + "given": { + "modules": [ + { + "module": "mesh-tools", + "added": [ + { + "subject": "mesh.seat.node-engine.verb.manifest-reads", + "verb": "manifest-reads" + } + ], + "removed": [] + } + ] + } + }, + { + "name": "grants-for asks a source revision on a branch", + "of": "verb:grants-for.input", + "given": { + "source": "a1b2c3d4", + "branch": "main" + } + } +] diff --git a/identity-and-access/seats/mesh-grants/seat.json b/identity-and-access/seats/mesh-grants/seat.json new file mode 100644 index 0000000..8fdb2ca --- /dev/null +++ b/identity-and-access/seats/mesh-grants/seat.json @@ -0,0 +1,222 @@ +{ + "format": 1, + "seat": "mesh-grants", + "scope": "mesh", + "grain": "whole", + "domain": "Identity and access", + "decision": "novox/hq ADR 0656, ADR 0547, ADR 0636", + "description": "Who may say what on the bus: the grants part composes each module's membership, its buckets, logs and streams, the bus's user list and grants (design 47 'The grants part'). An acting part of the step grant (ADR 0656 1): an entry whose grant waits for its new version is held on its running build within the bound, said by wait-held and wait-ended; a store passing 80 % of its cap is said by filling, and back below 70 % by room; grants-for answers the grants a candidate would compose (design 47 G 331, 441).", + "acts": [ + { + "step": "grant", + "on": "every" + } + ], + "verbs": [ + { + "name": "grants-for", + "description": "The grants a candidate would compose, per module: the grants it would add and remove against the branch's newest, each named by its subject and verb. The candidate's catalog half is taken by mesh-catalog's revision (design 47 G 441).", + "class": "read", + "input": { + "type": "object", + "properties": { + "source": { + "type": "string", + "description": "the candidate's source revision" + }, + "run": { + "type": "string", + "description": "or the id of a run" + }, + "branch": { + "type": "string", + "description": "its watched branch" + } + }, + "required": [ + "branch" + ], + "additionalProperties": false + }, + "answer": { + "$ref": "#/defs/GrantsFor" + } + } + ], + "events": [ + { + "name": "wait-held", + "body": { + "$ref": "#/defs/Wait" + } + }, + { + "name": "wait-ended", + "body": { + "$ref": "#/defs/Wait" + } + }, + { + "name": "filling", + "body": { + "$ref": "#/defs/Fill" + } + }, + { + "name": "room", + "body": { + "$ref": "#/defs/Fill" + } + } + ], + "family": { + "name": "mesh-grants.events", + "max-age-days": 7 + }, + "defs": { + "Wait": { + "type": "object", + "description": "a granting wait the grants part holds: an entry whose grant waits until the grants part's new version runs (design 47 *Each step's wait is its own part's*)", + "properties": { + "step": { + "type": "string", + "description": "the step, grant", + "enum": [ + "grant" + ] + }, + "part": { + "type": "string", + "description": "the acting part waited for" + }, + "version": { + "type": "string", + "description": "its new version's fingerprint" + }, + "module": { + "type": "string", + "description": "the entry that waits" + }, + "fp": { + "type": "string", + "description": "the entry's fingerprint, whose grant waits" + }, + "since": { + "type": "string", + "format": "date-time" + }, + "bound": { + "type": "string", + "description": "a duration such as 10m" + }, + "how": { + "type": "string", + "description": "on wait-ended: ran or released", + "enum": [ + "ran", + "released" + ] + }, + "by": { + "type": "string", + "description": "on a release, who released it and why" + }, + "clock-from": { + "type": "string", + "format": "date-time", + "description": "when the new version's build was done, as the builder's build.ended says; the bound's clock starts there (design 47 G 266)" + } + }, + "required": [ + "step", + "part", + "version", + "module", + "since", + "bound", + "clock-from" + ] + }, + "Fill": { + "type": "object", + "description": "a store's fill against its cap", + "properties": { + "store": { + "type": "string", + "description": "the store" + }, + "bytes": { + "type": "integer" + }, + "cap": { + "type": "integer", + "description": "bytes" + }, + "at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "store", + "bytes", + "cap" + ] + }, + "Grant": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "description": "the bus subject" + }, + "verb": { + "type": "string", + "description": "the verb or event the grant is for" + } + }, + "required": [ + "subject", + "verb" + ] + }, + "GrantsFor": { + "type": "object", + "description": "the grants a candidate would compose, per module, added and removed against the branch's newest", + "properties": { + "modules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "module": { + "type": "string" + }, + "added": { + "type": "array", + "items": { + "$ref": "#/defs/Grant" + } + }, + "removed": { + "type": "array", + "items": { + "$ref": "#/defs/Grant" + } + } + }, + "required": [ + "module", + "added", + "removed" + ] + } + }, + "error": { + "type": "string", + "description": "why it could not be answered: the catalog half of the candidate is not held" + } + } + } + } +} diff --git a/identity-and-access/seats/mesh-vault/seat.json b/identity-and-access/seats/mesh-vault/seat.json index 749f148..7c93f1b 100644 --- a/identity-and-access/seats/mesh-vault/seat.json +++ b/identity-and-access/seats/mesh-vault/seat.json @@ -597,9 +597,7 @@ "name": "retire", "optional": true, "description": "Retire one module's own secret, by node, module and name, on the operator's warrant bound to exactly those three (design 32 *A value no longer read*). Emits own-retired.", - "callers": [ - "seat:mesh-config" - ], + "callers": "the holder of the seat mesh-config alone", "input": { "type": "object", "properties": {