Registry seats: remove answers and says kept when a tagged version shares its digest
A store that cannot remove a tag alone (another tag names its digest) kept the tag and the holder said removed, so the builder and every follower believed the tagged version gone while it stayed pullable: work reported done that was not done. The shared registry part gains the outcome kept: in remove's answer (kept, the reason shared-digest, the tags still naming the digest) and as its own event, in all four registry seats. Regenerated with mesh-catalog's seatgen (join-mesh-catalog ccb7eaff); seatgen -check passes; fixtures for the answer and the event in each seat. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -21,6 +21,7 @@ const (
|
|||||||
EventPublished = "published"
|
EventPublished = "published"
|
||||||
EventRefused = "refused"
|
EventRefused = "refused"
|
||||||
EventRemoved = "removed"
|
EventRemoved = "removed"
|
||||||
|
EventKept = "kept"
|
||||||
EventHeld = "held"
|
EventHeld = "held"
|
||||||
EventReleased = "released"
|
EventReleased = "released"
|
||||||
)
|
)
|
||||||
@@ -32,7 +33,7 @@ func Verbs() []string {
|
|||||||
|
|
||||||
// Events is every event published on the seat's subject: a new copy each call.
|
// Events is every event published on the seat's subject: a new copy each call.
|
||||||
func Events() []string {
|
func Events() []string {
|
||||||
return []string{EventPublished, EventRefused, EventRemoved, EventHeld, EventReleased}
|
return []string{EventPublished, EventRefused, EventRemoved, EventKept, EventHeld, EventReleased}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||||
@@ -50,6 +51,9 @@ const SubjectRefused = "mesh.seat.container-image-registry.event.refused"
|
|||||||
// SubjectRemoved is where removed is published.
|
// SubjectRemoved is where removed is published.
|
||||||
const SubjectRemoved = "mesh.seat.container-image-registry.event.removed"
|
const SubjectRemoved = "mesh.seat.container-image-registry.event.removed"
|
||||||
|
|
||||||
|
// SubjectKept is where kept is published.
|
||||||
|
const SubjectKept = "mesh.seat.container-image-registry.event.kept"
|
||||||
|
|
||||||
// SubjectHeld is where held is published.
|
// SubjectHeld is where held is published.
|
||||||
const SubjectHeld = "mesh.seat.container-image-registry.event.held"
|
const SubjectHeld = "mesh.seat.container-image-registry.event.held"
|
||||||
|
|
||||||
@@ -115,12 +119,14 @@ type Outcome struct {
|
|||||||
Module string `json:"module,omitempty"`
|
Module string `json:"module,omitempty"`
|
||||||
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// why: a refusal's cause, or a removal's (retention, tag-gone, by-hand)
|
// why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest)
|
||||||
Reason string `json:"reason,omitempty"`
|
Reason string `json:"reason,omitempty"`
|
||||||
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
||||||
Reference string `json:"reference,omitempty"`
|
Reference string `json:"reference,omitempty"`
|
||||||
// the tag it carries, for a tagged version
|
// the tag it carries, for a tagged version
|
||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
|
// for kept: the other tags still naming its digest
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
// the transfer it ends, when it ended one
|
// the transfer it ends, when it ended one
|
||||||
Transfer string `json:"transfer,omitempty"`
|
Transfer string `json:"transfer,omitempty"`
|
||||||
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
||||||
@@ -250,10 +256,21 @@ const (
|
|||||||
// RemoveAnswer is what remove answers.
|
// RemoveAnswer is what remove answers.
|
||||||
type RemoveAnswer struct {
|
type RemoveAnswer struct {
|
||||||
Artifact *Artifact `json:"artifact,omitempty"`
|
Artifact *Artifact `json:"artifact,omitempty"`
|
||||||
|
// it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)
|
||||||
|
Kept bool `json:"kept,omitempty"`
|
||||||
|
// why it was kept: shared-digest, another tag names its digest
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
// it is gone
|
// it is gone
|
||||||
Removed bool `json:"removed"`
|
Removed bool `json:"removed"`
|
||||||
|
// the other tags still naming its digest, when kept
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The values of RemoveAnswer's reason.
|
||||||
|
const (
|
||||||
|
RemoveAnswerReasonSharedDigest = "shared-digest"
|
||||||
|
)
|
||||||
|
|
||||||
// MirrorInput is what mirror takes.
|
// MirrorInput is what mirror takes.
|
||||||
type MirrorInput struct {
|
type MirrorInput struct {
|
||||||
// its pinned digest, sha256:<hex>
|
// its pinned digest, sha256:<hex>
|
||||||
@@ -337,6 +354,9 @@ type RefusedEvent = Outcome
|
|||||||
// RemovedEvent is the body of the event removed.
|
// RemovedEvent is the body of the event removed.
|
||||||
type RemovedEvent = Outcome
|
type RemovedEvent = Outcome
|
||||||
|
|
||||||
|
// KeptEvent is the body of the event kept.
|
||||||
|
type KeptEvent = Outcome
|
||||||
|
|
||||||
// HeldEvent is the body of the event held.
|
// HeldEvent is the body of the event held.
|
||||||
type HeldEvent = Hold
|
type HeldEvent = Hold
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.refused$")},
|
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.refused$")},
|
||||||
{name: "removed on the seat's subject", subject: "mesh.seat.container-image-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"image\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"image\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "removed on the seat's subject", subject: "mesh.seat.container-image-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"image\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"image\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.removed$")},
|
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.removed$")},
|
||||||
|
{name: "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it", subject: "mesh.seat.container-image-registry.event.kept", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"image\",\"name\":\"mesh-sdk\",\"reason\":\"shared-digest\",\"reference\":\"container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"image\",\"name\":\"mesh-sdk\",\"reason\":\"shared-digest\",\"reference\":\"container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}",
|
||||||
|
decode: func(b []byte) (any, error) { var v KeptEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.kept$")},
|
||||||
{name: "held on the seat's subject", subject: "mesh.seat.container-image-registry.event.held", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
{name: "held on the seat's subject", subject: "mesh.seat.container-image-registry.event.held", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
||||||
decode: func(b []byte) (any, error) { var v HeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.held$")},
|
decode: func(b []byte) (any, error) { var v HeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.container-image-registry\\.event\\.held$")},
|
||||||
{name: "released on the seat's subject", subject: "mesh.seat.container-image-registry.event.released", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
{name: "released on the seat's subject", subject: "mesh.seat.container-image-registry.event.released", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
||||||
@@ -39,6 +41,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
{name: "a release of what is not held answers released false", subject: "", given: "{\"released\":false}", wire: "{\"released\":false}",
|
{name: "a release of what is not held answers released false", subject: "", given: "{\"released\":false}", wire: "{\"released\":false}",
|
||||||
decode: func(b []byte) (any, error) { var v ReleaseAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v ReleaseAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
|
{name: "a tagged version sharing its digest with another tag is kept, not removed", subject: "", given: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}", wire: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}",
|
||||||
|
decode: func(b []byte) (any, error) { var v RemoveAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
v, err := c.decode([]byte(c.given))
|
v, err := c.decode([]byte(c.given))
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const (
|
|||||||
EventPublished = "published"
|
EventPublished = "published"
|
||||||
EventRefused = "refused"
|
EventRefused = "refused"
|
||||||
EventRemoved = "removed"
|
EventRemoved = "removed"
|
||||||
|
EventKept = "kept"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||||
@@ -26,7 +27,7 @@ func Verbs() []string {
|
|||||||
|
|
||||||
// Events is every event published on the seat's subject: a new copy each call.
|
// Events is every event published on the seat's subject: a new copy each call.
|
||||||
func Events() []string {
|
func Events() []string {
|
||||||
return []string{EventPublished, EventRefused, EventRemoved}
|
return []string{EventPublished, EventRefused, EventRemoved, EventKept}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||||
@@ -44,6 +45,9 @@ const SubjectRefused = "mesh.seat.go-package-registry.event.refused"
|
|||||||
// SubjectRemoved is where removed is published.
|
// SubjectRemoved is where removed is published.
|
||||||
const SubjectRemoved = "mesh.seat.go-package-registry.event.removed"
|
const SubjectRemoved = "mesh.seat.go-package-registry.event.removed"
|
||||||
|
|
||||||
|
// SubjectKept is where kept is published.
|
||||||
|
const SubjectKept = "mesh.seat.go-package-registry.event.kept"
|
||||||
|
|
||||||
// Artifact is one published thing, as every registry event and answer names it.
|
// Artifact is one published thing, as every registry event and answer names it.
|
||||||
type Artifact struct {
|
type Artifact struct {
|
||||||
// the source commit it was built from
|
// the source commit it was built from
|
||||||
@@ -87,12 +91,14 @@ type Outcome struct {
|
|||||||
Module string `json:"module,omitempty"`
|
Module string `json:"module,omitempty"`
|
||||||
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// why: a refusal's cause, or a removal's (retention, tag-gone, by-hand)
|
// why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest)
|
||||||
Reason string `json:"reason,omitempty"`
|
Reason string `json:"reason,omitempty"`
|
||||||
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
||||||
Reference string `json:"reference,omitempty"`
|
Reference string `json:"reference,omitempty"`
|
||||||
// the tag it carries, for a tagged version
|
// the tag it carries, for a tagged version
|
||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
|
// for kept: the other tags still naming its digest
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
// the transfer it ends, when it ended one
|
// the transfer it ends, when it ended one
|
||||||
Transfer string `json:"transfer,omitempty"`
|
Transfer string `json:"transfer,omitempty"`
|
||||||
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
||||||
@@ -222,10 +228,21 @@ const (
|
|||||||
// RemoveAnswer is what remove answers.
|
// RemoveAnswer is what remove answers.
|
||||||
type RemoveAnswer struct {
|
type RemoveAnswer struct {
|
||||||
Artifact *Artifact `json:"artifact,omitempty"`
|
Artifact *Artifact `json:"artifact,omitempty"`
|
||||||
|
// it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)
|
||||||
|
Kept bool `json:"kept,omitempty"`
|
||||||
|
// why it was kept: shared-digest, another tag names its digest
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
// it is gone
|
// it is gone
|
||||||
Removed bool `json:"removed"`
|
Removed bool `json:"removed"`
|
||||||
|
// the other tags still naming its digest, when kept
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The values of RemoveAnswer's reason.
|
||||||
|
const (
|
||||||
|
RemoveAnswerReasonSharedDigest = "shared-digest"
|
||||||
|
)
|
||||||
|
|
||||||
// PublishedEvent is the body of the event published.
|
// PublishedEvent is the body of the event published.
|
||||||
type PublishedEvent = Outcome
|
type PublishedEvent = Outcome
|
||||||
|
|
||||||
@@ -235,6 +252,9 @@ type RefusedEvent = Outcome
|
|||||||
// RemovedEvent is the body of the event removed.
|
// RemovedEvent is the body of the event removed.
|
||||||
type RemovedEvent = Outcome
|
type RemovedEvent = Outcome
|
||||||
|
|
||||||
|
// KeptEvent is the body of the event kept.
|
||||||
|
type KeptEvent = Outcome
|
||||||
|
|
||||||
// GoPackageRegistryForm is the form of the provision go-package-registry.
|
// GoPackageRegistryForm is the form of the provision go-package-registry.
|
||||||
type GoPackageRegistryForm struct {
|
type GoPackageRegistryForm struct {
|
||||||
// the read side's address
|
// the read side's address
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.go-package-registry\\.event\\.refused$")},
|
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.go-package-registry\\.event\\.refused$")},
|
||||||
{name: "removed on the seat's subject", subject: "mesh.seat.go-package-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"reason\":\"retention\",\"reference\":\"git.novox.be/novox/mesh-sdk/go@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"reason\":\"retention\",\"reference\":\"git.novox.be/novox/mesh-sdk/go@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "removed on the seat's subject", subject: "mesh.seat.go-package-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"reason\":\"retention\",\"reference\":\"git.novox.be/novox/mesh-sdk/go@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"reason\":\"retention\",\"reference\":\"git.novox.be/novox/mesh-sdk/go@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.go-package-registry\\.event\\.removed$")},
|
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.go-package-registry\\.event\\.removed$")},
|
||||||
|
{name: "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it", subject: "mesh.seat.go-package-registry.event.kept", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"reason\":\"shared-digest\",\"reference\":\"git.novox.be/novox/mesh-sdk/go@0.1.19\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"reason\":\"shared-digest\",\"reference\":\"git.novox.be/novox/mesh-sdk/go@0.1.19\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}",
|
||||||
|
decode: func(b []byte) (any, error) { var v KeptEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.go-package-registry\\.event\\.kept$")},
|
||||||
{name: "publish opens a transfer", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "publish opens a transfer", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
decode: func(b []byte) (any, error) { var v PublishInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v PublishInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
{name: "a field the reader does not know is dropped", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"later\":{\"x\":1},\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "a field the reader does not know is dropped", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"later\":{\"x\":1},\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
@@ -33,6 +35,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v PublishPartInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v PublishPartInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
{name: "the versions held", subject: "", given: "{\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"version\":\"0.1.19\"}]}", wire: "{\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"version\":\"0.1.19\"}]}",
|
{name: "the versions held", subject: "", given: "{\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"version\":\"0.1.19\"}]}", wire: "{\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"git.novox.be/novox/mesh-sdk/go\",\"version\":\"0.1.19\"}]}",
|
||||||
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
|
{name: "a tagged version sharing its digest with another tag is kept, not removed", subject: "", given: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}", wire: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}",
|
||||||
|
decode: func(b []byte) (any, error) { var v RemoveAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
v, err := c.decode([]byte(c.given))
|
v, err := c.decode([]byte(c.given))
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const (
|
|||||||
EventPublished = "published"
|
EventPublished = "published"
|
||||||
EventRefused = "refused"
|
EventRefused = "refused"
|
||||||
EventRemoved = "removed"
|
EventRemoved = "removed"
|
||||||
|
EventKept = "kept"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||||
@@ -26,7 +27,7 @@ func Verbs() []string {
|
|||||||
|
|
||||||
// Events is every event published on the seat's subject: a new copy each call.
|
// Events is every event published on the seat's subject: a new copy each call.
|
||||||
func Events() []string {
|
func Events() []string {
|
||||||
return []string{EventPublished, EventRefused, EventRemoved}
|
return []string{EventPublished, EventRefused, EventRemoved, EventKept}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||||
@@ -44,6 +45,9 @@ const SubjectRefused = "mesh.seat.npm-package-registry.event.refused"
|
|||||||
// SubjectRemoved is where removed is published.
|
// SubjectRemoved is where removed is published.
|
||||||
const SubjectRemoved = "mesh.seat.npm-package-registry.event.removed"
|
const SubjectRemoved = "mesh.seat.npm-package-registry.event.removed"
|
||||||
|
|
||||||
|
// SubjectKept is where kept is published.
|
||||||
|
const SubjectKept = "mesh.seat.npm-package-registry.event.kept"
|
||||||
|
|
||||||
// Artifact is one published thing, as every registry event and answer names it.
|
// Artifact is one published thing, as every registry event and answer names it.
|
||||||
type Artifact struct {
|
type Artifact struct {
|
||||||
// the source commit it was built from
|
// the source commit it was built from
|
||||||
@@ -87,12 +91,14 @@ type Outcome struct {
|
|||||||
Module string `json:"module,omitempty"`
|
Module string `json:"module,omitempty"`
|
||||||
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// why: a refusal's cause, or a removal's (retention, tag-gone, by-hand)
|
// why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest)
|
||||||
Reason string `json:"reason,omitempty"`
|
Reason string `json:"reason,omitempty"`
|
||||||
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
||||||
Reference string `json:"reference,omitempty"`
|
Reference string `json:"reference,omitempty"`
|
||||||
// the tag it carries, for a tagged version
|
// the tag it carries, for a tagged version
|
||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
|
// for kept: the other tags still naming its digest
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
// the transfer it ends, when it ended one
|
// the transfer it ends, when it ended one
|
||||||
Transfer string `json:"transfer,omitempty"`
|
Transfer string `json:"transfer,omitempty"`
|
||||||
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
||||||
@@ -222,10 +228,21 @@ const (
|
|||||||
// RemoveAnswer is what remove answers.
|
// RemoveAnswer is what remove answers.
|
||||||
type RemoveAnswer struct {
|
type RemoveAnswer struct {
|
||||||
Artifact *Artifact `json:"artifact,omitempty"`
|
Artifact *Artifact `json:"artifact,omitempty"`
|
||||||
|
// it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)
|
||||||
|
Kept bool `json:"kept,omitempty"`
|
||||||
|
// why it was kept: shared-digest, another tag names its digest
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
// it is gone
|
// it is gone
|
||||||
Removed bool `json:"removed"`
|
Removed bool `json:"removed"`
|
||||||
|
// the other tags still naming its digest, when kept
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The values of RemoveAnswer's reason.
|
||||||
|
const (
|
||||||
|
RemoveAnswerReasonSharedDigest = "shared-digest"
|
||||||
|
)
|
||||||
|
|
||||||
// PublishedEvent is the body of the event published.
|
// PublishedEvent is the body of the event published.
|
||||||
type PublishedEvent = Outcome
|
type PublishedEvent = Outcome
|
||||||
|
|
||||||
@@ -235,6 +252,9 @@ type RefusedEvent = Outcome
|
|||||||
// RemovedEvent is the body of the event removed.
|
// RemovedEvent is the body of the event removed.
|
||||||
type RemovedEvent = Outcome
|
type RemovedEvent = Outcome
|
||||||
|
|
||||||
|
// KeptEvent is the body of the event kept.
|
||||||
|
type KeptEvent = Outcome
|
||||||
|
|
||||||
// NpmPackageRegistryForm is the form of the provision npm-package-registry.
|
// NpmPackageRegistryForm is the form of the provision npm-package-registry.
|
||||||
type NpmPackageRegistryForm struct {
|
type NpmPackageRegistryForm struct {
|
||||||
// the read side's address
|
// the read side's address
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.npm-package-registry\\.event\\.refused$")},
|
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.npm-package-registry\\.event\\.refused$")},
|
||||||
{name: "removed on the seat's subject", subject: "mesh.seat.npm-package-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"reason\":\"retention\",\"reference\":\"@novox/mesh-sdk@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"reason\":\"retention\",\"reference\":\"@novox/mesh-sdk@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "removed on the seat's subject", subject: "mesh.seat.npm-package-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"reason\":\"retention\",\"reference\":\"@novox/mesh-sdk@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"reason\":\"retention\",\"reference\":\"@novox/mesh-sdk@0.1.19\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.npm-package-registry\\.event\\.removed$")},
|
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.npm-package-registry\\.event\\.removed$")},
|
||||||
|
{name: "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it", subject: "mesh.seat.npm-package-registry.event.kept", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"reason\":\"shared-digest\",\"reference\":\"@novox/mesh-sdk@0.1.19\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"gitea\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"reason\":\"shared-digest\",\"reference\":\"@novox/mesh-sdk@0.1.19\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}",
|
||||||
|
decode: func(b []byte) (any, error) { var v KeptEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.npm-package-registry\\.event\\.kept$")},
|
||||||
{name: "publish opens a transfer", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "publish opens a transfer", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
decode: func(b []byte) (any, error) { var v PublishInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v PublishInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
{name: "a field the reader does not know is dropped", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"later\":{\"x\":1},\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "a field the reader does not know is dropped", subject: "", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"later\":{\"x\":1},\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"parts\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"size\":1048576}],\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
@@ -33,6 +35,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v PublishPartInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v PublishPartInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
{name: "the versions held", subject: "", given: "{\"name\":\"@novox/mesh-sdk\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"version\":\"0.1.19\"}]}", wire: "{\"name\":\"@novox/mesh-sdk\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"version\":\"0.1.19\"}]}",
|
{name: "the versions held", subject: "", given: "{\"name\":\"@novox/mesh-sdk\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"version\":\"0.1.19\"}]}", wire: "{\"name\":\"@novox/mesh-sdk\",\"versions\":[{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"kind\":\"package\",\"name\":\"@novox/mesh-sdk\",\"version\":\"0.1.19\"}]}",
|
||||||
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
|
{name: "a tagged version sharing its digest with another tag is kept, not removed", subject: "", given: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}", wire: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}",
|
||||||
|
decode: func(b []byte) (any, error) { var v RemoveAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
v, err := c.decode([]byte(c.given))
|
v, err := c.decode([]byte(c.given))
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const (
|
|||||||
EventPublished = "published"
|
EventPublished = "published"
|
||||||
EventRefused = "refused"
|
EventRefused = "refused"
|
||||||
EventRemoved = "removed"
|
EventRemoved = "removed"
|
||||||
|
EventKept = "kept"
|
||||||
EventHeld = "held"
|
EventHeld = "held"
|
||||||
EventReleased = "released"
|
EventReleased = "released"
|
||||||
)
|
)
|
||||||
@@ -30,7 +31,7 @@ func Verbs() []string {
|
|||||||
|
|
||||||
// Events is every event published on the seat's subject: a new copy each call.
|
// Events is every event published on the seat's subject: a new copy each call.
|
||||||
func Events() []string {
|
func Events() []string {
|
||||||
return []string{EventPublished, EventRefused, EventRemoved, EventHeld, EventReleased}
|
return []string{EventPublished, EventRefused, EventRemoved, EventKept, EventHeld, EventReleased}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||||
@@ -48,6 +49,9 @@ const SubjectRefused = "mesh.seat.oci-artifact-registry.event.refused"
|
|||||||
// SubjectRemoved is where removed is published.
|
// SubjectRemoved is where removed is published.
|
||||||
const SubjectRemoved = "mesh.seat.oci-artifact-registry.event.removed"
|
const SubjectRemoved = "mesh.seat.oci-artifact-registry.event.removed"
|
||||||
|
|
||||||
|
// SubjectKept is where kept is published.
|
||||||
|
const SubjectKept = "mesh.seat.oci-artifact-registry.event.kept"
|
||||||
|
|
||||||
// SubjectHeld is where held is published.
|
// SubjectHeld is where held is published.
|
||||||
const SubjectHeld = "mesh.seat.oci-artifact-registry.event.held"
|
const SubjectHeld = "mesh.seat.oci-artifact-registry.event.held"
|
||||||
|
|
||||||
@@ -113,12 +117,14 @@ type Outcome struct {
|
|||||||
Module string `json:"module,omitempty"`
|
Module string `json:"module,omitempty"`
|
||||||
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
// the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// why: a refusal's cause, or a removal's (retention, tag-gone, by-hand)
|
// why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest)
|
||||||
Reason string `json:"reason,omitempty"`
|
Reason string `json:"reason,omitempty"`
|
||||||
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
// the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9)
|
||||||
Reference string `json:"reference,omitempty"`
|
Reference string `json:"reference,omitempty"`
|
||||||
// the tag it carries, for a tagged version
|
// the tag it carries, for a tagged version
|
||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
|
// for kept: the other tags still naming its digest
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
// the transfer it ends, when it ended one
|
// the transfer it ends, when it ended one
|
||||||
Transfer string `json:"transfer,omitempty"`
|
Transfer string `json:"transfer,omitempty"`
|
||||||
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
// the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone
|
||||||
@@ -248,10 +254,21 @@ const (
|
|||||||
// RemoveAnswer is what remove answers.
|
// RemoveAnswer is what remove answers.
|
||||||
type RemoveAnswer struct {
|
type RemoveAnswer struct {
|
||||||
Artifact *Artifact `json:"artifact,omitempty"`
|
Artifact *Artifact `json:"artifact,omitempty"`
|
||||||
|
// it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)
|
||||||
|
Kept bool `json:"kept,omitempty"`
|
||||||
|
// why it was kept: shared-digest, another tag names its digest
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
// it is gone
|
// it is gone
|
||||||
Removed bool `json:"removed"`
|
Removed bool `json:"removed"`
|
||||||
|
// the other tags still naming its digest, when kept
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The values of RemoveAnswer's reason.
|
||||||
|
const (
|
||||||
|
RemoveAnswerReasonSharedDigest = "shared-digest"
|
||||||
|
)
|
||||||
|
|
||||||
// HoldInput is what hold takes.
|
// HoldInput is what hold takes.
|
||||||
type HoldInput struct {
|
type HoldInput struct {
|
||||||
// the digest
|
// the digest
|
||||||
@@ -295,6 +312,9 @@ type RefusedEvent = Outcome
|
|||||||
// RemovedEvent is the body of the event removed.
|
// RemovedEvent is the body of the event removed.
|
||||||
type RemovedEvent = Outcome
|
type RemovedEvent = Outcome
|
||||||
|
|
||||||
|
// KeptEvent is the body of the event kept.
|
||||||
|
type KeptEvent = Outcome
|
||||||
|
|
||||||
// HeldEvent is the body of the event held.
|
// HeldEvent is the body of the event held.
|
||||||
type HeldEvent = Hold
|
type HeldEvent = Hold
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.refused$")},
|
decode: func(b []byte) (any, error) { var v RefusedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.refused$")},
|
||||||
{name: "removed on the seat's subject", subject: "mesh.seat.oci-artifact-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"bundle\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"bundle\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
{name: "removed on the seat's subject", subject: "mesh.seat.oci-artifact-registry.event.removed", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"bundle\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"bundle\",\"name\":\"mesh-sdk\",\"reason\":\"retention\",\"reference\":\"oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"transfer\":\"t1\",\"version\":\"0.1.19\"}",
|
||||||
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.removed$")},
|
decode: func(b []byte) (any, error) { var v RemovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.removed$")},
|
||||||
|
{name: "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it", subject: "mesh.seat.oci-artifact-registry.event.kept", given: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"bundle\",\"name\":\"mesh-sdk\",\"reason\":\"shared-digest\",\"reference\":\"oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}", wire: "{\"commit\":\"cccccccccccccccccccccccccccccccccccccccc\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"fingerprint\":\"f1\",\"holder\":\"distribution\",\"kind\":\"bundle\",\"name\":\"mesh-sdk\",\"reason\":\"shared-digest\",\"reference\":\"oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"tag\":\"0.1.19-feat-x.2\",\"tags\":[\"0.1.19\"],\"version\":\"0.1.19-feat-x.2\"}",
|
||||||
|
decode: func(b []byte) (any, error) { var v KeptEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.kept$")},
|
||||||
{name: "held on the seat's subject", subject: "mesh.seat.oci-artifact-registry.event.held", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
{name: "held on the seat's subject", subject: "mesh.seat.oci-artifact-registry.event.held", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
||||||
decode: func(b []byte) (any, error) { var v HeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.held$")},
|
decode: func(b []byte) (any, error) { var v HeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.oci-artifact-registry\\.event\\.held$")},
|
||||||
{name: "released on the seat's subject", subject: "mesh.seat.oci-artifact-registry.event.released", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
{name: "released on the seat's subject", subject: "mesh.seat.oci-artifact-registry.event.released", given: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}", wire: "{\"at\":\"2026-11-04T12:00:00Z\",\"by\":\"mesh-artifact-sweep\",\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"holder\":\"distribution\",\"name\":\"mesh-sdk\",\"reason\":\"kept by the sweep's rule\"}",
|
||||||
@@ -39,6 +41,8 @@ func TestFixtures(t *testing.T) {
|
|||||||
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
{name: "a release of what is not held answers released false", subject: "", given: "{\"released\":false}", wire: "{\"released\":false}",
|
{name: "a release of what is not held answers released false", subject: "", given: "{\"released\":false}", wire: "{\"released\":false}",
|
||||||
decode: func(b []byte) (any, error) { var v ReleaseAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
decode: func(b []byte) (any, error) { var v ReleaseAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
|
{name: "a tagged version sharing its digest with another tag is kept, not removed", subject: "", given: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}", wire: "{\"kept\":true,\"reason\":\"shared-digest\",\"removed\":false,\"tags\":[\"0.1.19\"]}",
|
||||||
|
decode: func(b []byte) (any, error) { var v RemoveAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
v, err := c.decode([]byte(c.given))
|
v, err := c.decode([]byte(c.given))
|
||||||
|
|||||||
+12
-12
@@ -381,7 +381,7 @@ func List() []Seat {
|
|||||||
{Name: "images", Description: "Every container image one machine's want and have name, each with the resources naming it: what the machine keeps when it prunes its images. Reads only.",
|
{Name: "images", Description: "Every container image one machine's want and have name, each with the resources naming it: what the machine keeps when it prunes its images. Reads only.",
|
||||||
Input: map[string]any{"properties": map[string]any{"node": map[string]any{"description": "the machine's name", "type": "string"}}, "required": []string{"node"}, "type": "object"}},
|
Input: map[string]any{"properties": map[string]any{"node": map[string]any{"description": "the machine's name", "type": "string"}}, "required": []string{"node"}, "type": "object"}},
|
||||||
}},
|
}},
|
||||||
{Name: NpmPackageRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0109", Delivers: "npm-package-registry", Emits: []string{"published", "refused", "removed"},
|
{Name: NpmPackageRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0109", Delivers: "npm-package-registry", Emits: []string{"published", "refused", "removed", "kept"},
|
||||||
Serves: []Verb{
|
Serves: []Verb{
|
||||||
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
||||||
@@ -392,11 +392,11 @@ func List() []Seat {
|
|||||||
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
||||||
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.", Optional: true,
|
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}}, "required": []string{"removed"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "kept": map[string]any{"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)", "type": "boolean"}, "reason": map[string]any{"description": "why it was kept: shared-digest, another tag names its digest", "enum": []string{"shared-digest"}, "type": "string"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}, "tags": map[string]any{"description": "the other tags still naming its digest, when kept", "items": map[string]any{"type": "string"}, "type": "array"}}, "required": []string{"removed"}, "type": "object"}},
|
||||||
}},
|
}},
|
||||||
{Name: GoPackageRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0605", Delivers: "go-package-registry", Emits: []string{"published", "refused", "removed"},
|
{Name: GoPackageRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0605", Delivers: "go-package-registry", Emits: []string{"published", "refused", "removed", "kept"},
|
||||||
Serves: []Verb{
|
Serves: []Verb{
|
||||||
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
||||||
@@ -407,11 +407,11 @@ func List() []Seat {
|
|||||||
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
||||||
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.", Optional: true,
|
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}}, "required": []string{"removed"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "kept": map[string]any{"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)", "type": "boolean"}, "reason": map[string]any{"description": "why it was kept: shared-digest, another tag names its digest", "enum": []string{"shared-digest"}, "type": "string"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}, "tags": map[string]any{"description": "the other tags still naming its digest, when kept", "items": map[string]any{"type": "string"}, "type": "array"}}, "required": []string{"removed"}, "type": "object"}},
|
||||||
}},
|
}},
|
||||||
{Name: ContainerImageRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0605", Delivers: "artifact-store", Emits: []string{"published", "refused", "removed", "held", "released"},
|
{Name: ContainerImageRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0605", Delivers: "artifact-store", Emits: []string{"published", "refused", "removed", "kept", "held", "released"},
|
||||||
Serves: []Verb{
|
Serves: []Verb{
|
||||||
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
||||||
@@ -422,9 +422,9 @@ func List() []Seat {
|
|||||||
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
||||||
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.", Optional: true,
|
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}}, "required": []string{"removed"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "kept": map[string]any{"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)", "type": "boolean"}, "reason": map[string]any{"description": "why it was kept: shared-digest, another tag names its digest", "enum": []string{"shared-digest"}, "type": "string"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}, "tags": map[string]any{"description": "the other tags still naming its digest, when kept", "items": map[string]any{"type": "string"}, "type": "array"}}, "required": []string{"removed"}, "type": "object"}},
|
||||||
{Name: "mirror", Description: "Copy an outside image into the store by its pinned digest; emits published or refused.", Optional: true,
|
{Name: "mirror", Description: "Copy an outside image into the store by its pinned digest; emits published or refused.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "its pinned digest, sha256:<hex>", "type": "string"}, "name": map[string]any{"description": "the name it is kept under", "type": "string"}, "source": map[string]any{"description": "the outside image's reference", "type": "string"}}, "required": []string{"source", "digest", "name"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "its pinned digest, sha256:<hex>", "type": "string"}, "name": map[string]any{"description": "the name it is kept under", "type": "string"}, "source": map[string]any{"description": "the outside image's reference", "type": "string"}}, "required": []string{"source", "digest", "name"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest stored", "type": "string"}, "reference": map[string]any{"description": "the reference the seat answers", "type": "string"}}, "required": []string{"reference", "digest"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest stored", "type": "string"}, "reference": map[string]any{"description": "the reference the seat answers", "type": "string"}}, "required": []string{"reference", "digest"}, "type": "object"}},
|
||||||
@@ -438,7 +438,7 @@ func List() []Seat {
|
|||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it is let go", "type": "string"}}, "required": []string{"name", "digest", "reason"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it is let go", "type": "string"}}, "required": []string{"name", "digest", "reason"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"released": map[string]any{"description": "a hold was let go; false when there was none", "type": "boolean"}}, "required": []string{"released"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"released": map[string]any{"description": "a hold was let go; false when there was none", "type": "boolean"}}, "required": []string{"released"}, "type": "object"}},
|
||||||
}},
|
}},
|
||||||
{Name: OciArtifactRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0605", Delivers: "artifact-store", Emits: []string{"published", "refused", "removed", "held", "released"},
|
{Name: OciArtifactRegistry, Scope: "mesh", Grain: "whole", Decision: "novox/hq ADR 0605", Delivers: "artifact-store", Emits: []string{"published", "refused", "removed", "kept", "held", "released"},
|
||||||
Serves: []Verb{
|
Serves: []Verb{
|
||||||
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
{Name: "publish", Description: "Open a transfer, naming the artifact and the digest of every part; answers the digests the holder lacks, which the caller then sends by publish-part. A transfer already open answers the parts held, so a cut transfer goes on from there. With no parts and a version, the held digest is published under that version and nothing is stored (the trunk's claim).", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "parts": map[string]any{"description": "every part's digest and size; none when the digest is already held", "items": map[string]any{"description": "one part of a transfer", "properties": map[string]any{"digest": map[string]any{"description": "the part's digest, sha256:<hex>: an image's layer or config, a package's file, a bundle's blob", "type": "string"}, "size": map[string]any{"description": "its size in bytes", "type": "integer"}}, "required": []string{"digest", "size"}, "type": "object"}, "type": "array"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "transfer": map[string]any{"description": "the transfer's name, the caller's own; the same name opens the same transfer again", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"transfer", "name", "kind", "digest"}, "type": "object"},
|
||||||
@@ -449,9 +449,9 @@ func List() []Seat {
|
|||||||
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
{Name: "versions", Description: "The versions the seat holds of one name, newest first: each one's version, tag, digest, kind and when it was published.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"kind": map[string]any{"description": "narrowed to one kind (optional)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}}, "required": []string{"name"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"name": map[string]any{"description": "the name", "type": "string"}, "versions": map[string]any{"description": "newest first", "items": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "type": "array"}}, "required": []string{"name", "versions"}, "type": "object"}},
|
||||||
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.", Optional: true,
|
{Name: "remove", Description: "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest (for a bundle, archive or copied base)", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "why it goes", "enum": []string{"tag-gone", "retention"}, "type": "string"}, "tag": map[string]any{"description": "the tag (for a tagged version)", "type": "string"}, "version": map[string]any{"description": "the version", "type": "string"}}, "required": []string{"name", "reason"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}}, "required": []string{"removed"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"artifact": map[string]any{"description": "one published thing, as every registry event and answer names it", "properties": map[string]any{"commit": map[string]any{"description": "the source commit it was built from", "type": "string"}, "digest": map[string]any{"description": "its digest, sha256:<hex> (a Go package's h1: hash beside it in the version's record)", "type": "string"}, "fingerprint": map[string]any{"description": "the build's fingerprint", "type": "string"}, "kind": map[string]any{"description": "what it is", "enum": []string{"package", "image", "bundle", "archive", "upstream"}, "type": "string"}, "name": map[string]any{"description": "the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk)", "type": "string"}, "tag": map[string]any{"description": "the tag it carries, for a tagged version", "type": "string"}, "version": map[string]any{"description": "the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone", "type": "string"}}, "required": []string{"name", "kind", "digest"}, "type": "object"}, "kept": map[string]any{"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)", "type": "boolean"}, "reason": map[string]any{"description": "why it was kept: shared-digest, another tag names its digest", "enum": []string{"shared-digest"}, "type": "string"}, "removed": map[string]any{"description": "it is gone", "type": "boolean"}, "tags": map[string]any{"description": "the other tags still naming its digest, when kept", "items": map[string]any{"type": "string"}, "type": "array"}}, "required": []string{"removed"}, "type": "object"}},
|
||||||
{Name: "hold", Description: "Keep one untagged bundle, archive or copied base from removal by retention, as the artifact sweep's rules keep it (ADR 0617 §2); never an image of the holder's own. Emits held.", Optional: true,
|
{Name: "hold", Description: "Keep one untagged bundle, archive or copied base from removal by retention, as the artifact sweep's rules keep it (ADR 0617 §2); never an image of the holder's own. Emits held.", Optional: true,
|
||||||
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "which of the sweep's rules keeps it", "type": "string"}}, "required": []string{"name", "digest", "reason"}, "type": "object"},
|
Input: map[string]any{"properties": map[string]any{"digest": map[string]any{"description": "the digest", "type": "string"}, "name": map[string]any{"description": "the name", "type": "string"}, "reason": map[string]any{"description": "which of the sweep's rules keeps it", "type": "string"}}, "required": []string{"name", "digest", "reason"}, "type": "object"},
|
||||||
Output: map[string]any{"properties": map[string]any{"held": map[string]any{"description": "it is held", "type": "boolean"}, "since": map[string]any{"description": "when the hold began, RFC 3339", "type": "string"}}, "required": []string{"held"}, "type": "object"}},
|
Output: map[string]any{"properties": map[string]any{"held": map[string]any{"description": "it is held", "type": "boolean"}, "since": map[string]any{"description": "when the hold began, RFC 3339", "type": "string"}}, "required": []string{"held"}, "type": "object"}},
|
||||||
|
|||||||
+33
-2
@@ -196,7 +196,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "remove",
|
"name": "remove",
|
||||||
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.",
|
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.",
|
||||||
"callers": "the builder, for a tagged version; the artifact sweep's holder, for retention",
|
"callers": "the builder, for a tagged version; the artifact sweep's holder, for retention",
|
||||||
"input": {
|
"input": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -238,6 +238,24 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "it is gone"
|
"description": "it is gone"
|
||||||
},
|
},
|
||||||
|
"kept": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"shared-digest"
|
||||||
|
],
|
||||||
|
"description": "why it was kept: shared-digest, another tag names its digest"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "the other tags still naming its digest, when kept"
|
||||||
|
},
|
||||||
"artifact": {
|
"artifact": {
|
||||||
"$ref": "#/defs/Artifact"
|
"$ref": "#/defs/Artifact"
|
||||||
}
|
}
|
||||||
@@ -267,6 +285,12 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"$ref": "#/defs/Outcome"
|
"$ref": "#/defs/Outcome"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kept",
|
||||||
|
"body": {
|
||||||
|
"$ref": "#/defs/Outcome"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"defs": {
|
"defs": {
|
||||||
@@ -390,7 +414,14 @@
|
|||||||
},
|
},
|
||||||
"reason": {
|
"reason": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "why: a refusal's cause, or a removal's (retention, tag-gone, by-hand)"
|
"description": "why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest)"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "for kept: the other tags still naming its digest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|||||||
@@ -49,6 +49,26 @@
|
|||||||
"reason": "retention"
|
"reason": "retention"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it",
|
||||||
|
"of": "event:kept",
|
||||||
|
"subject": "mesh.seat.container-image-registry.event.kept",
|
||||||
|
"given": {
|
||||||
|
"name": "mesh-sdk",
|
||||||
|
"version": "0.1.19-feat-x.2",
|
||||||
|
"kind": "image",
|
||||||
|
"digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"fingerprint": "f1",
|
||||||
|
"commit": "cccccccccccccccccccccccccccccccccccccccc",
|
||||||
|
"holder": "distribution",
|
||||||
|
"reference": "container-image-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tag": "0.1.19-feat-x.2",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "held on the seat's subject",
|
"name": "held on the seat's subject",
|
||||||
"of": "event:held",
|
"of": "event:held",
|
||||||
|
|||||||
@@ -101,5 +101,18 @@
|
|||||||
"given": {
|
"given": {
|
||||||
"released": false
|
"released": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "a tagged version sharing its digest with another tag is kept, not removed",
|
||||||
|
"of": "verb:remove.answer",
|
||||||
|
"why": "G-sdk-contracts 3: the store cannot remove the tag alone, so the answer says what holds",
|
||||||
|
"given": {
|
||||||
|
"removed": false,
|
||||||
|
"kept": true,
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -49,5 +49,25 @@
|
|||||||
"reference": "git.novox.be/novox/mesh-sdk/go@0.1.19",
|
"reference": "git.novox.be/novox/mesh-sdk/go@0.1.19",
|
||||||
"reason": "retention"
|
"reason": "retention"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it",
|
||||||
|
"of": "event:kept",
|
||||||
|
"subject": "mesh.seat.go-package-registry.event.kept",
|
||||||
|
"given": {
|
||||||
|
"name": "git.novox.be/novox/mesh-sdk/go",
|
||||||
|
"version": "0.1.19-feat-x.2",
|
||||||
|
"kind": "package",
|
||||||
|
"digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"fingerprint": "f1",
|
||||||
|
"commit": "cccccccccccccccccccccccccccccccccccccccc",
|
||||||
|
"holder": "gitea",
|
||||||
|
"reference": "git.novox.be/novox/mesh-sdk/go@0.1.19",
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tag": "0.1.19-feat-x.2",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -93,5 +93,18 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "a tagged version sharing its digest with another tag is kept, not removed",
|
||||||
|
"of": "verb:remove.answer",
|
||||||
|
"why": "G-sdk-contracts 3: the store cannot remove the tag alone, so the answer says what holds",
|
||||||
|
"given": {
|
||||||
|
"removed": false,
|
||||||
|
"kept": true,
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -48,5 +48,25 @@
|
|||||||
"reference": "@novox/mesh-sdk@0.1.19",
|
"reference": "@novox/mesh-sdk@0.1.19",
|
||||||
"reason": "retention"
|
"reason": "retention"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it",
|
||||||
|
"of": "event:kept",
|
||||||
|
"subject": "mesh.seat.npm-package-registry.event.kept",
|
||||||
|
"given": {
|
||||||
|
"name": "@novox/mesh-sdk",
|
||||||
|
"version": "0.1.19-feat-x.2",
|
||||||
|
"kind": "package",
|
||||||
|
"digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"fingerprint": "f1",
|
||||||
|
"commit": "cccccccccccccccccccccccccccccccccccccccc",
|
||||||
|
"holder": "gitea",
|
||||||
|
"reference": "@novox/mesh-sdk@0.1.19",
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tag": "0.1.19-feat-x.2",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -93,5 +93,18 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "a tagged version sharing its digest with another tag is kept, not removed",
|
||||||
|
"of": "verb:remove.answer",
|
||||||
|
"why": "G-sdk-contracts 3: the store cannot remove the tag alone, so the answer says what holds",
|
||||||
|
"given": {
|
||||||
|
"removed": false,
|
||||||
|
"kept": true,
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -49,6 +49,26 @@
|
|||||||
"reason": "retention"
|
"reason": "retention"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "kept on the seat's subject: a tagged version sharing its digest stays, naming the tags on it",
|
||||||
|
"of": "event:kept",
|
||||||
|
"subject": "mesh.seat.oci-artifact-registry.event.kept",
|
||||||
|
"given": {
|
||||||
|
"name": "mesh-sdk",
|
||||||
|
"version": "0.1.19-feat-x.2",
|
||||||
|
"kind": "bundle",
|
||||||
|
"digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"fingerprint": "f1",
|
||||||
|
"commit": "cccccccccccccccccccccccccccccccccccccccc",
|
||||||
|
"holder": "distribution",
|
||||||
|
"reference": "oci-artifact-registry/mesh-sdk/lib@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tag": "0.1.19-feat-x.2",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "held on the seat's subject",
|
"name": "held on the seat's subject",
|
||||||
"of": "event:held",
|
"of": "event:held",
|
||||||
|
|||||||
@@ -101,5 +101,18 @@
|
|||||||
"given": {
|
"given": {
|
||||||
"released": false
|
"released": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "a tagged version sharing its digest with another tag is kept, not removed",
|
||||||
|
"of": "verb:remove.answer",
|
||||||
|
"why": "G-sdk-contracts 3: the store cannot remove the tag alone, so the answer says what holds",
|
||||||
|
"given": {
|
||||||
|
"removed": false,
|
||||||
|
"kept": true,
|
||||||
|
"reason": "shared-digest",
|
||||||
|
"tags": [
|
||||||
|
"0.1.19"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
held: "held",
|
held: "held",
|
||||||
released: "released",
|
released: "released",
|
||||||
} as const;
|
} as const;
|
||||||
@@ -33,11 +34,14 @@ export const refusedSubject = "mesh.seat.container-image-registry.event.refused"
|
|||||||
|
|
||||||
export const removedSubject = "mesh.seat.container-image-registry.event.removed";
|
export const removedSubject = "mesh.seat.container-image-registry.event.removed";
|
||||||
|
|
||||||
|
export const keptSubject = "mesh.seat.container-image-registry.event.kept";
|
||||||
|
|
||||||
export const heldSubject = "mesh.seat.container-image-registry.event.held";
|
export const heldSubject = "mesh.seat.container-image-registry.event.held";
|
||||||
|
|
||||||
export const releasedSubject = "mesh.seat.container-image-registry.event.released";
|
export const releasedSubject = "mesh.seat.container-image-registry.event.released";
|
||||||
|
|
||||||
export type Artifact = registry.Artifact;
|
export type Artifact = registry.Artifact;
|
||||||
|
export type KeptEvent = registry.KeptEvent;
|
||||||
export type Outcome = registry.Outcome;
|
export type Outcome = registry.Outcome;
|
||||||
export type Part = registry.Part;
|
export type Part = registry.Part;
|
||||||
export type PublishAnswer = registry.PublishAnswer;
|
export type PublishAnswer = registry.PublishAnswer;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/** one published thing, as every registry event and answer names it */
|
/** one published thing, as every registry event and answer names it */
|
||||||
@@ -49,12 +50,14 @@ export interface Outcome {
|
|||||||
"module"?: string;
|
"module"?: string;
|
||||||
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
||||||
"name": string;
|
"name": string;
|
||||||
/** why: a refusal's cause, or a removal's (retention, tag-gone, by-hand) */
|
/** why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest) */
|
||||||
"reason"?: string;
|
"reason"?: string;
|
||||||
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
||||||
"reference"?: string;
|
"reference"?: string;
|
||||||
/** the tag it carries, for a tagged version */
|
/** the tag it carries, for a tagged version */
|
||||||
"tag"?: string;
|
"tag"?: string;
|
||||||
|
/** for kept: the other tags still naming its digest */
|
||||||
|
"tags"?: string[];
|
||||||
/** the transfer it ends, when it ended one */
|
/** the transfer it ends, when it ended one */
|
||||||
"transfer"?: string;
|
"transfer"?: string;
|
||||||
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
||||||
@@ -160,8 +163,14 @@ export interface RemoveInput {
|
|||||||
/** is what remove answers. */
|
/** is what remove answers. */
|
||||||
export interface RemoveAnswer {
|
export interface RemoveAnswer {
|
||||||
"artifact"?: Artifact;
|
"artifact"?: Artifact;
|
||||||
|
/** it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags) */
|
||||||
|
"kept"?: boolean;
|
||||||
|
/** why it was kept: shared-digest, another tag names its digest */
|
||||||
|
"reason"?: "shared-digest";
|
||||||
/** it is gone */
|
/** it is gone */
|
||||||
"removed": boolean;
|
"removed": boolean;
|
||||||
|
/** the other tags still naming its digest, when kept */
|
||||||
|
"tags"?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is the body of the event published. */
|
/** is the body of the event published. */
|
||||||
@@ -173,3 +182,6 @@ export type RefusedEvent = Outcome;
|
|||||||
/** is the body of the event removed. */
|
/** is the body of the event removed. */
|
||||||
export type RemovedEvent = Outcome;
|
export type RemovedEvent = Outcome;
|
||||||
|
|
||||||
|
/** is the body of the event kept. */
|
||||||
|
export type KeptEvent = Outcome;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const family = { name: "go-package-registry.events", maxAgeDays: 7 } as const;
|
export const family = { name: "go-package-registry.events", maxAgeDays: 7 } as const;
|
||||||
@@ -27,7 +28,10 @@ export const refusedSubject = "mesh.seat.go-package-registry.event.refused";
|
|||||||
|
|
||||||
export const removedSubject = "mesh.seat.go-package-registry.event.removed";
|
export const removedSubject = "mesh.seat.go-package-registry.event.removed";
|
||||||
|
|
||||||
|
export const keptSubject = "mesh.seat.go-package-registry.event.kept";
|
||||||
|
|
||||||
export type Artifact = registry.Artifact;
|
export type Artifact = registry.Artifact;
|
||||||
|
export type KeptEvent = registry.KeptEvent;
|
||||||
export type Outcome = registry.Outcome;
|
export type Outcome = registry.Outcome;
|
||||||
export type Part = registry.Part;
|
export type Part = registry.Part;
|
||||||
export type PublishAnswer = registry.PublishAnswer;
|
export type PublishAnswer = registry.PublishAnswer;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/** one published thing, as every registry event and answer names it */
|
/** one published thing, as every registry event and answer names it */
|
||||||
@@ -49,12 +50,14 @@ export interface Outcome {
|
|||||||
"module"?: string;
|
"module"?: string;
|
||||||
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
||||||
"name": string;
|
"name": string;
|
||||||
/** why: a refusal's cause, or a removal's (retention, tag-gone, by-hand) */
|
/** why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest) */
|
||||||
"reason"?: string;
|
"reason"?: string;
|
||||||
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
||||||
"reference"?: string;
|
"reference"?: string;
|
||||||
/** the tag it carries, for a tagged version */
|
/** the tag it carries, for a tagged version */
|
||||||
"tag"?: string;
|
"tag"?: string;
|
||||||
|
/** for kept: the other tags still naming its digest */
|
||||||
|
"tags"?: string[];
|
||||||
/** the transfer it ends, when it ended one */
|
/** the transfer it ends, when it ended one */
|
||||||
"transfer"?: string;
|
"transfer"?: string;
|
||||||
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
||||||
@@ -160,8 +163,14 @@ export interface RemoveInput {
|
|||||||
/** is what remove answers. */
|
/** is what remove answers. */
|
||||||
export interface RemoveAnswer {
|
export interface RemoveAnswer {
|
||||||
"artifact"?: Artifact;
|
"artifact"?: Artifact;
|
||||||
|
/** it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags) */
|
||||||
|
"kept"?: boolean;
|
||||||
|
/** why it was kept: shared-digest, another tag names its digest */
|
||||||
|
"reason"?: "shared-digest";
|
||||||
/** it is gone */
|
/** it is gone */
|
||||||
"removed": boolean;
|
"removed": boolean;
|
||||||
|
/** the other tags still naming its digest, when kept */
|
||||||
|
"tags"?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is the body of the event published. */
|
/** is the body of the event published. */
|
||||||
@@ -173,3 +182,6 @@ export type RefusedEvent = Outcome;
|
|||||||
/** is the body of the event removed. */
|
/** is the body of the event removed. */
|
||||||
export type RemovedEvent = Outcome;
|
export type RemovedEvent = Outcome;
|
||||||
|
|
||||||
|
/** is the body of the event kept. */
|
||||||
|
export type KeptEvent = Outcome;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const family = { name: "npm-package-registry.events", maxAgeDays: 7 } as const;
|
export const family = { name: "npm-package-registry.events", maxAgeDays: 7 } as const;
|
||||||
@@ -27,7 +28,10 @@ export const refusedSubject = "mesh.seat.npm-package-registry.event.refused";
|
|||||||
|
|
||||||
export const removedSubject = "mesh.seat.npm-package-registry.event.removed";
|
export const removedSubject = "mesh.seat.npm-package-registry.event.removed";
|
||||||
|
|
||||||
|
export const keptSubject = "mesh.seat.npm-package-registry.event.kept";
|
||||||
|
|
||||||
export type Artifact = registry.Artifact;
|
export type Artifact = registry.Artifact;
|
||||||
|
export type KeptEvent = registry.KeptEvent;
|
||||||
export type Outcome = registry.Outcome;
|
export type Outcome = registry.Outcome;
|
||||||
export type Part = registry.Part;
|
export type Part = registry.Part;
|
||||||
export type PublishAnswer = registry.PublishAnswer;
|
export type PublishAnswer = registry.PublishAnswer;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/** one published thing, as every registry event and answer names it */
|
/** one published thing, as every registry event and answer names it */
|
||||||
@@ -49,12 +50,14 @@ export interface Outcome {
|
|||||||
"module"?: string;
|
"module"?: string;
|
||||||
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
||||||
"name": string;
|
"name": string;
|
||||||
/** why: a refusal's cause, or a removal's (retention, tag-gone, by-hand) */
|
/** why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest) */
|
||||||
"reason"?: string;
|
"reason"?: string;
|
||||||
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
||||||
"reference"?: string;
|
"reference"?: string;
|
||||||
/** the tag it carries, for a tagged version */
|
/** the tag it carries, for a tagged version */
|
||||||
"tag"?: string;
|
"tag"?: string;
|
||||||
|
/** for kept: the other tags still naming its digest */
|
||||||
|
"tags"?: string[];
|
||||||
/** the transfer it ends, when it ended one */
|
/** the transfer it ends, when it ended one */
|
||||||
"transfer"?: string;
|
"transfer"?: string;
|
||||||
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
||||||
@@ -160,8 +163,14 @@ export interface RemoveInput {
|
|||||||
/** is what remove answers. */
|
/** is what remove answers. */
|
||||||
export interface RemoveAnswer {
|
export interface RemoveAnswer {
|
||||||
"artifact"?: Artifact;
|
"artifact"?: Artifact;
|
||||||
|
/** it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags) */
|
||||||
|
"kept"?: boolean;
|
||||||
|
/** why it was kept: shared-digest, another tag names its digest */
|
||||||
|
"reason"?: "shared-digest";
|
||||||
/** it is gone */
|
/** it is gone */
|
||||||
"removed": boolean;
|
"removed": boolean;
|
||||||
|
/** the other tags still naming its digest, when kept */
|
||||||
|
"tags"?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is the body of the event published. */
|
/** is the body of the event published. */
|
||||||
@@ -173,3 +182,6 @@ export type RefusedEvent = Outcome;
|
|||||||
/** is the body of the event removed. */
|
/** is the body of the event removed. */
|
||||||
export type RemovedEvent = Outcome;
|
export type RemovedEvent = Outcome;
|
||||||
|
|
||||||
|
/** is the body of the event kept. */
|
||||||
|
export type KeptEvent = Outcome;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
held: "held",
|
held: "held",
|
||||||
released: "released",
|
released: "released",
|
||||||
} as const;
|
} as const;
|
||||||
@@ -31,11 +32,14 @@ export const refusedSubject = "mesh.seat.oci-artifact-registry.event.refused";
|
|||||||
|
|
||||||
export const removedSubject = "mesh.seat.oci-artifact-registry.event.removed";
|
export const removedSubject = "mesh.seat.oci-artifact-registry.event.removed";
|
||||||
|
|
||||||
|
export const keptSubject = "mesh.seat.oci-artifact-registry.event.kept";
|
||||||
|
|
||||||
export const heldSubject = "mesh.seat.oci-artifact-registry.event.held";
|
export const heldSubject = "mesh.seat.oci-artifact-registry.event.held";
|
||||||
|
|
||||||
export const releasedSubject = "mesh.seat.oci-artifact-registry.event.released";
|
export const releasedSubject = "mesh.seat.oci-artifact-registry.event.released";
|
||||||
|
|
||||||
export type Artifact = registry.Artifact;
|
export type Artifact = registry.Artifact;
|
||||||
|
export type KeptEvent = registry.KeptEvent;
|
||||||
export type Outcome = registry.Outcome;
|
export type Outcome = registry.Outcome;
|
||||||
export type Part = registry.Part;
|
export type Part = registry.Part;
|
||||||
export type PublishAnswer = registry.PublishAnswer;
|
export type PublishAnswer = registry.PublishAnswer;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const events = {
|
|||||||
published: "published",
|
published: "published",
|
||||||
refused: "refused",
|
refused: "refused",
|
||||||
removed: "removed",
|
removed: "removed",
|
||||||
|
kept: "kept",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/** one published thing, as every registry event and answer names it */
|
/** one published thing, as every registry event and answer names it */
|
||||||
@@ -49,12 +50,14 @@ export interface Outcome {
|
|||||||
"module"?: string;
|
"module"?: string;
|
||||||
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
/** the package's, image's, bundle's or archive's name; a package's is its name in its own language (design 32): a Go package's the go.mod module path (git.novox.be/novox/mesh-sdk/go), an npm package's package.json's name (@novox/mesh-sdk) */
|
||||||
"name": string;
|
"name": string;
|
||||||
/** why: a refusal's cause, or a removal's (retention, tag-gone, by-hand) */
|
/** why: a refusal's cause, a removal's (retention, tag-gone, by-hand), or why a removal was kept (shared-digest) */
|
||||||
"reason"?: string;
|
"reason"?: string;
|
||||||
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
/** the reference the seat answers: <registry>/<module>/<artifact>@sha256:<digest>, or <name>@<version> for a package (ADR 0605 §9) */
|
||||||
"reference"?: string;
|
"reference"?: string;
|
||||||
/** the tag it carries, for a tagged version */
|
/** the tag it carries, for a tagged version */
|
||||||
"tag"?: string;
|
"tag"?: string;
|
||||||
|
/** for kept: the other tags still naming its digest */
|
||||||
|
"tags"?: string[];
|
||||||
/** the transfer it ends, when it ended one */
|
/** the transfer it ends, when it ended one */
|
||||||
"transfer"?: string;
|
"transfer"?: string;
|
||||||
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
/** the version the builder gave it (design 51 *The versions*); empty for a bundle or archive published by its digest alone */
|
||||||
@@ -160,8 +163,14 @@ export interface RemoveInput {
|
|||||||
/** is what remove answers. */
|
/** is what remove answers. */
|
||||||
export interface RemoveAnswer {
|
export interface RemoveAnswer {
|
||||||
"artifact"?: Artifact;
|
"artifact"?: Artifact;
|
||||||
|
/** it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags) */
|
||||||
|
"kept"?: boolean;
|
||||||
|
/** why it was kept: shared-digest, another tag names its digest */
|
||||||
|
"reason"?: "shared-digest";
|
||||||
/** it is gone */
|
/** it is gone */
|
||||||
"removed": boolean;
|
"removed": boolean;
|
||||||
|
/** the other tags still naming its digest, when kept */
|
||||||
|
"tags"?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is the body of the event published. */
|
/** is the body of the event published. */
|
||||||
@@ -173,3 +182,6 @@ export type RefusedEvent = Outcome;
|
|||||||
/** is the body of the event removed. */
|
/** is the body of the event removed. */
|
||||||
export type RemovedEvent = Outcome;
|
export type RemovedEvent = Outcome;
|
||||||
|
|
||||||
|
/** is the body of the event kept. */
|
||||||
|
export type KeptEvent = Outcome;
|
||||||
|
|
||||||
|
|||||||
+82
-6
@@ -3063,7 +3063,8 @@ export const list: readonly Seat[] = [
|
|||||||
"emits": [
|
"emits": [
|
||||||
"published",
|
"published",
|
||||||
"refused",
|
"refused",
|
||||||
"removed"
|
"removed",
|
||||||
|
"kept"
|
||||||
],
|
],
|
||||||
"grain": "whole",
|
"grain": "whole",
|
||||||
"name": "npm-package-registry",
|
"name": "npm-package-registry",
|
||||||
@@ -3316,7 +3317,7 @@ export const list: readonly Seat[] = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.",
|
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.",
|
||||||
"input": {
|
"input": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"digest": {
|
"digest": {
|
||||||
@@ -3400,9 +3401,27 @@ export const list: readonly Seat[] = [
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"kept": {
|
||||||
|
"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"description": "why it was kept: shared-digest, another tag names its digest",
|
||||||
|
"enum": [
|
||||||
|
"shared-digest"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"removed": {
|
"removed": {
|
||||||
"description": "it is gone",
|
"description": "it is gone",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"description": "the other tags still naming its digest, when kept",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -3419,7 +3438,8 @@ export const list: readonly Seat[] = [
|
|||||||
"emits": [
|
"emits": [
|
||||||
"published",
|
"published",
|
||||||
"refused",
|
"refused",
|
||||||
"removed"
|
"removed",
|
||||||
|
"kept"
|
||||||
],
|
],
|
||||||
"grain": "whole",
|
"grain": "whole",
|
||||||
"name": "go-package-registry",
|
"name": "go-package-registry",
|
||||||
@@ -3672,7 +3692,7 @@ export const list: readonly Seat[] = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.",
|
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.",
|
||||||
"input": {
|
"input": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"digest": {
|
"digest": {
|
||||||
@@ -3756,9 +3776,27 @@ export const list: readonly Seat[] = [
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"kept": {
|
||||||
|
"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"description": "why it was kept: shared-digest, another tag names its digest",
|
||||||
|
"enum": [
|
||||||
|
"shared-digest"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"removed": {
|
"removed": {
|
||||||
"description": "it is gone",
|
"description": "it is gone",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"description": "the other tags still naming its digest, when kept",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -3776,6 +3814,7 @@ export const list: readonly Seat[] = [
|
|||||||
"published",
|
"published",
|
||||||
"refused",
|
"refused",
|
||||||
"removed",
|
"removed",
|
||||||
|
"kept",
|
||||||
"held",
|
"held",
|
||||||
"released"
|
"released"
|
||||||
],
|
],
|
||||||
@@ -4030,7 +4069,7 @@ export const list: readonly Seat[] = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.",
|
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.",
|
||||||
"input": {
|
"input": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"digest": {
|
"digest": {
|
||||||
@@ -4114,9 +4153,27 @@ export const list: readonly Seat[] = [
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"kept": {
|
||||||
|
"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"description": "why it was kept: shared-digest, another tag names its digest",
|
||||||
|
"enum": [
|
||||||
|
"shared-digest"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"removed": {
|
"removed": {
|
||||||
"description": "it is gone",
|
"description": "it is gone",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"description": "the other tags still naming its digest, when kept",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -4311,6 +4368,7 @@ export const list: readonly Seat[] = [
|
|||||||
"published",
|
"published",
|
||||||
"refused",
|
"refused",
|
||||||
"removed",
|
"removed",
|
||||||
|
"kept",
|
||||||
"held",
|
"held",
|
||||||
"released"
|
"released"
|
||||||
],
|
],
|
||||||
@@ -4565,7 +4623,7 @@ export const list: readonly Seat[] = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason.",
|
"description": "Remove one tagged version; the holder refuses an untagged one but for the retention removal of a bundle, archive or copied base by the artifact sweep's holder. Every removal emits removed with its reason. A tagged version the store cannot remove alone, because another tag names its digest, stays whole, its tag and bytes kept: the answer says kept with the reason shared-digest and the tags still naming the digest, removed false, and kept is emitted, never removed; the caller ends there without a retry.",
|
||||||
"input": {
|
"input": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"digest": {
|
"digest": {
|
||||||
@@ -4649,9 +4707,27 @@ export const list: readonly Seat[] = [
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"kept": {
|
||||||
|
"description": "it stays whole, its tag and its bytes: the store cannot remove the tag alone while another tag names its digest (reason, tags)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"description": "why it was kept: shared-digest, another tag names its digest",
|
||||||
|
"enum": [
|
||||||
|
"shared-digest"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"removed": {
|
"removed": {
|
||||||
"description": "it is gone",
|
"description": "it is gone",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"description": "the other tags still naming its digest, when kept",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|||||||
Reference in New Issue
Block a user