From 1ddc26087d46cd5248ef14e2e7bb2d2a75187781 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 11 Nov 2026 20:35:40 +0100 Subject: [PATCH] CT16 (approval carried, pins stated): the seat mesh-delivery says approval-carried and pins-stated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit approval-carried.. is kept 90 days; pins-stated has the keep of pinned, which is the seat's family. Builds: design 47 G §542, §579, §652 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ --- contracts/go/seats/meshdelivery/contract.go | 60 ++++++++++++++---- .../go/seats/meshdelivery/contract_test.go | 4 ++ .../seats/mesh-delivery/fixtures/events.json | 20 ++++++ contracts/seats/mesh-delivery/seat.json | 61 ++++++++++++++++++- contracts/ts/seats/meshdelivery/index.d.ts | 30 +++++++++ contracts/ts/seats/meshdelivery/index.js | 12 ++++ 6 files changed, 174 insertions(+), 13 deletions(-) diff --git a/contracts/go/seats/meshdelivery/contract.go b/contracts/go/seats/meshdelivery/contract.go index 52e6cfb0..8f065371 100644 --- a/contracts/go/seats/meshdelivery/contract.go +++ b/contracts/go/seats/meshdelivery/contract.go @@ -24,17 +24,19 @@ const ( ) const ( - EventOwed = "owed" - EventPinned = "pinned" - EventFreed = "freed" - EventHeadsReplaced = "heads-replaced" - EventRecordOpened = "record-opened" - EventRecordEnded = "record-ended" - EventFilling = "filling" - EventFull = "full" - EventRoom = "room" - EventSourceMoved = "source-moved" - EventRecoveryMerged = "recovery-merged" + EventOwed = "owed" + EventPinned = "pinned" + EventFreed = "freed" + EventHeadsReplaced = "heads-replaced" + EventRecordOpened = "record-opened" + EventRecordEnded = "record-ended" + EventFilling = "filling" + EventFull = "full" + EventRoom = "room" + EventSourceMoved = "source-moved" + EventRecoveryMerged = "recovery-merged" + EventApprovalCarried = "approval-carried" + EventPinsStated = "pins-stated" ) // Verbs is every verb the seat serves, in its definition's order: a new copy each call. @@ -44,7 +46,7 @@ func Verbs() []string { // Events is every event published on the seat's subject: a new copy each call. func Events() []string { - return []string{EventOwed, EventPinned, EventFreed, EventHeadsReplaced, EventRecordOpened, EventRecordEnded, EventFilling, EventFull, EventRoom, EventSourceMoved, EventRecoveryMerged} + return []string{EventOwed, EventPinned, EventFreed, EventHeadsReplaced, EventRecordOpened, EventRecordEnded, EventFilling, EventFull, EventRoom, EventSourceMoved, EventRecoveryMerged, EventApprovalCarried, EventPinsStated} } // Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects. @@ -99,6 +101,20 @@ const SubjectSourceMovedAll = "mesh.seat.mesh-delivery.event.source-moved.*" // SubjectRecoveryMerged is where recovery-merged is published. const SubjectRecoveryMerged = "mesh.seat.mesh-delivery.event.recovery-merged" +// StreamApprovalCarried is the stream approval-carried is kept in. +const StreamApprovalCarried = "SEAT_mesh-delivery_approval-carried" + +// SubjectApprovalCarried is where approval-carried is published, on mesh.seat.mesh-delivery.event.approval-carried... +func SubjectApprovalCarried(repository, pull string) string { + return "mesh.seat.mesh-delivery.event.approval-carried." + repository + "." + pull +} + +// SubjectApprovalCarriedAll hears every approval-carried. +const SubjectApprovalCarriedAll = "mesh.seat.mesh-delivery.event.approval-carried.*.*" + +// SubjectPinsStated is where pins-stated is published. +const SubjectPinsStated = "mesh.seat.mesh-delivery.event.pins-stated" + const ( StateSource = "source" StateMerges = "merges" @@ -635,6 +651,26 @@ type RecoveryMergedEvent struct { Why string `json:"why"` } +// ApprovalCarriedEvent is the body of the event approval-carried. +type ApprovalCarriedEvent struct { + // who approved: the operator + Approver string `json:"approver"` + // when it was said, RFC 3339 + At time.Time `json:"at"` + // the head the Approve named + Commit string `json:"commit"` + // the pull request's number + Pull int64 `json:"pull"` + // the repository + Repository string `json:"repository"` +} + +// PinsStatedEvent is the body of the event pins-stated. +type PinsStatedEvent struct { + // when it was said, RFC 3339 + At time.Time `json:"at"` +} + // SourceByBranchValue is one value of the state source under the key . type SourceByBranchValue struct { // the group that moved it diff --git a/contracts/go/seats/meshdelivery/contract_test.go b/contracts/go/seats/meshdelivery/contract_test.go index 0dab3001..b636e28e 100644 --- a/contracts/go/seats/meshdelivery/contract_test.go +++ b/contracts/go/seats/meshdelivery/contract_test.go @@ -43,6 +43,10 @@ func TestFixtures(t *testing.T) { decode: func(b []byte) (any, error) { var v SourceMovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.source-moved\\.[^.*> ]+$")}, {name: "a recovery merged", subject: "mesh.seat.mesh-delivery.event.recovery-merged", given: "{\"at\":\"2026-11-11T10:00:00Z\",\"by\":\"jochen\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"v\":1,\"why\":\"the live delivery was broken\"}", wire: "{\"at\":\"2026-11-11T10:00:00Z\",\"by\":\"jochen\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"v\":1,\"why\":\"the live delivery was broken\"}", decode: func(b []byte) (any, error) { var v RecoveryMergedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.recovery-merged$")}, + {name: "approval-carried is said for a pull request approved before G", subject: "mesh.seat.mesh-delivery.event.approval-carried.mesh-tools.35", given: "{\"approver\":\"operator\",\"at\":\"2026-11-11T10:00:00Z\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"pull\":35,\"repository\":\"mesh-tools\"}", wire: "{\"approver\":\"operator\",\"at\":\"2026-11-11T10:00:00Z\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"pull\":35,\"repository\":\"mesh-tools\"}", + decode: func(b []byte) (any, error) { var v ApprovalCarriedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.approval-carried\\.[^.*> ]+\\.[^.*> ]+$")}, + {name: "pins-stated is said once the pins are", subject: "mesh.seat.mesh-delivery.event.pins-stated", given: "{\"at\":\"2026-11-11T10:00:00Z\"}", wire: "{\"at\":\"2026-11-11T10:00:00Z\"}", + decode: func(b []byte) (any, error) { var v PinsStatedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.pins-stated$")}, {name: "the source revision", subject: "", given: "{\"group\":\"feat/registry\",\"heads\":{\"novox/mesh-sdk\":\"cccccccccccccccccccccccccccccccccccccccc\"},\"v\":1}", wire: "{\"group\":\"feat/registry\",\"heads\":{\"novox/mesh-sdk\":\"cccccccccccccccccccccccccccccccccccccccc\"},\"v\":1}", decode: func(b []byte) (any, error) { var v SourceByBranchValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "a merge", subject: "", given: "{\"ask\":\"merge.feat=registry.0123456789ab\",\"group\":\"feat/registry\",\"pulls\":[{\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":1,\"repository\":\"novox/mesh-sdk\",\"state\":\"merging\"}],\"v\":1}", wire: "{\"ask\":\"merge.feat=registry.0123456789ab\",\"group\":\"feat/registry\",\"pulls\":[{\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":1,\"repository\":\"novox/mesh-sdk\",\"state\":\"merging\"}],\"v\":1}", diff --git a/contracts/seats/mesh-delivery/fixtures/events.json b/contracts/seats/mesh-delivery/fixtures/events.json index da3dc7ce..52b3fcbe 100644 --- a/contracts/seats/mesh-delivery/fixtures/events.json +++ b/contracts/seats/mesh-delivery/fixtures/events.json @@ -166,5 +166,25 @@ "by": "jochen", "at": "2026-11-11T10:00:00Z" } + }, + { + "name": "approval-carried is said for a pull request approved before G", + "of": "event:approval-carried", + "subject": "mesh.seat.mesh-delivery.event.approval-carried.mesh-tools.35", + "given": { + "repository": "mesh-tools", + "pull": 35, + "commit": "0123456789abcdef0123456789abcdef01234567", + "approver": "operator", + "at": "2026-11-11T10:00:00Z" + } + }, + { + "name": "pins-stated is said once the pins are", + "of": "event:pins-stated", + "subject": "mesh.seat.mesh-delivery.event.pins-stated", + "given": { + "at": "2026-11-11T10:00:00Z" + } } ] diff --git a/contracts/seats/mesh-delivery/seat.json b/contracts/seats/mesh-delivery/seat.json index 4f4bf39f..f39b1399 100644 --- a/contracts/seats/mesh-delivery/seat.json +++ b/contracts/seats/mesh-delivery/seat.json @@ -453,6 +453,65 @@ "why" ] } + }, + { + "name": "approval-carried", + "subject": "approval-carried..", + "keep": { + "max-age-days": 90 + }, + "body": { + "type": "object", + "description": "an Approve given before G, carried as that pull request's approval step: said at G's switch for each merges key the old bridge had not performed (design 47 G 542)", + "properties": { + "repository": { + "type": "string", + "description": "the repository" + }, + "pull": { + "type": "integer", + "description": "the pull request's number", + "minimum": 1 + }, + "commit": { + "type": "string", + "description": "the head the Approve named" + }, + "approver": { + "type": "string", + "description": "who approved: the operator" + }, + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "repository", + "pull", + "commit", + "approver", + "at" + ] + } + }, + { + "name": "pins-stated", + "body": { + "type": "object", + "description": "the gate states every pin it holds once its pinned events are said, so an indexer whose state pins was made later hears them all; kept as pinned is, on the seat's family (design 47 G 579, 652)", + "properties": { + "at": { + "type": "string", + "description": "when it was said, RFC 3339", + "format": "date-time" + } + }, + "required": [ + "at" + ] + } } ], "states": [ @@ -1015,7 +1074,7 @@ }, "Ask": { "type": "object", - "description": "the one Approve ask of a milestone (ADR 0493 \u00a79), said apart from each delivery's transition", + "description": "the one Approve ask of a milestone (ADR 0493 §9), said apart from each delivery's transition", "properties": { "milestone": { "type": "string", diff --git a/contracts/ts/seats/meshdelivery/index.d.ts b/contracts/ts/seats/meshdelivery/index.d.ts index c00f97c5..98ffe486 100644 --- a/contracts/ts/seats/meshdelivery/index.d.ts +++ b/contracts/ts/seats/meshdelivery/index.d.ts @@ -25,6 +25,8 @@ export declare const events: { readonly room: "room"; readonly sourceMoved: "source-moved"; readonly recoveryMerged: "recovery-merged"; + readonly approvalCarried: "approval-carried"; + readonly pinsStated: "pins-stated"; }; export declare const family: { readonly name: "mesh-delivery.events"; readonly maxAgeDays: 7 }; @@ -57,6 +59,14 @@ export declare const sourceMovedSubjectAll: "mesh.seat.mesh-delivery.event.sourc export declare const recoveryMergedSubject: "mesh.seat.mesh-delivery.event.recovery-merged"; +export declare const approvalCarriedStream: "SEAT_mesh-delivery_approval-carried"; + +export declare function approvalCarriedSubject(repository: string, pull: string): string; + +export declare const approvalCarriedSubjectAll: "mesh.seat.mesh-delivery.event.approval-carried.*.*"; + +export declare const pinsStatedSubject: "mesh.seat.mesh-delivery.event.pins-stated"; + export declare const states: { readonly source: "source"; readonly merges: "merges"; @@ -411,6 +421,26 @@ export interface RecoveryMergedEvent { "why": string; } +/** is the body of the event approval-carried. */ +export interface ApprovalCarriedEvent { + /** who approved: the operator */ + "approver": string; + /** when it was said, RFC 3339 */ + "at": string; + /** the head the Approve named */ + "commit": string; + /** the pull request's number */ + "pull": number; + /** the repository */ + "repository": string; +} + +/** is the body of the event pins-stated. */ +export interface PinsStatedEvent { + /** when it was said, RFC 3339 */ + "at": string; +} + /** is one value of the state source under the key . */ export interface SourceByBranchValue { /** the group that moved it */ diff --git a/contracts/ts/seats/meshdelivery/index.js b/contracts/ts/seats/meshdelivery/index.js index b3eed1fb..5416d647 100644 --- a/contracts/ts/seats/meshdelivery/index.js +++ b/contracts/ts/seats/meshdelivery/index.js @@ -25,6 +25,8 @@ export const events = { room: "room", sourceMoved: "source-moved", recoveryMerged: "recovery-merged", + approvalCarried: "approval-carried", + pinsStated: "pins-stated", }; export const family = { name: "mesh-delivery.events", maxAgeDays: 7 }; @@ -61,6 +63,16 @@ export const sourceMovedSubjectAll = "mesh.seat.mesh-delivery.event.source-moved export const recoveryMergedSubject = "mesh.seat.mesh-delivery.event.recovery-merged"; +export const approvalCarriedStream = "SEAT_mesh-delivery_approval-carried"; + +export function approvalCarriedSubject(repository, pull) { + return "mesh.seat.mesh-delivery.event.approval-carried." + repository + "." + pull; +} + +export const approvalCarriedSubjectAll = "mesh.seat.mesh-delivery.event.approval-carried.*.*"; + +export const pinsStatedSubject = "mesh.seat.mesh-delivery.event.pins-stated"; + export const states = { source: "source", merges: "merges",