Promise get on the vault's seat, so the Go vault can serve it (issue 674)
mesh/merge-gate head 661918f4e4e0 merged into trunk 71362c196dbc — pass: the change touches no module of the mesh's graph
mesh/repo-check head 661918f4e4e0 merged into trunk 71362c196dbc — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group pkg/57-v1-vault-in-go delivering: 1 of 2 delivered
mesh/merge-gate head 661918f4e4e0 merged into trunk 71362c196dbc — pass: the change touches no module of the mesh's graph
mesh/repo-check head 661918f4e4e0 merged into trunk 71362c196dbc — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group pkg/57-v1-vault-in-go delivering: 1 of 2 delivered
The vault hands a secret only on request and reply, sealed to the asker's key (hq ADR 0349 §11). The seat set is the controller's, so the verb is promised here; optional until the vault that runs serves it (design 33 §7). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -128,7 +128,19 @@ var defaultSeats = append([]Seat{
|
|||||||
// The vault: the controller seals every minted credential with what it provides, which is the
|
// The vault: the controller seals every minted credential with what it provides, which is the
|
||||||
// test for a seat of the mesh's own (novox/hq ADR 0161) — a second provider of `secret` is a
|
// test for a seat of the mesh's own (novox/hq ADR 0161) — a second provider of `secret` is a
|
||||||
// second claimant, refused by name, rather than a candidate for a pin.
|
// second claimant, refused by name, rather than a candidate for a pin.
|
||||||
{Name: "mesh-vault", Scope: ScopeMesh, Delivers: "secret", Decision: "novox/hq ADR 0161"},
|
//
|
||||||
|
// Its one verb, `get`, hands a secret on request and reply, sealed to the key the asker sends and only
|
||||||
|
// to an asker the vault allows (novox/hq ADR 0349 §11, issue 674). Optional until the vault that runs
|
||||||
|
// serves it (design 33 §7).
|
||||||
|
{Name: "mesh-vault", Scope: ScopeMesh, Delivers: "secret", Decision: "novox/hq ADR 0161",
|
||||||
|
Serves: []Verb{
|
||||||
|
{Name: "get", Optional: true, Description: "One secret, sealed to the public key the asker sends (the " +
|
||||||
|
"sealed box of ADR 0206), with its generation; answered only to an asker the vault allows, as the " +
|
||||||
|
"bus proved it. Never the value in the clear, and never to a private key.",
|
||||||
|
Input: schema(map[string]string{"name": "the secret's name",
|
||||||
|
"public_key": "the asker's X25519 public key as SPKI PEM — never a private key"},
|
||||||
|
[]string{"name", "public_key"})},
|
||||||
|
}},
|
||||||
// Named for its scope since 2026-09-30 (novox/hq ADR 0156); `the-artifact-store` resolves to it as
|
// Named for its scope since 2026-09-30 (novox/hq ADR 0156); `the-artifact-store` resolves to it as
|
||||||
// an alias on a mesh that predates the rename. It serves artifacts of every kind a build makes —
|
// an alias on a mesh that predates the rename. It serves artifacts of every kind a build makes —
|
||||||
// images and archives, by digest — which is why the provision is the artifact store and not an
|
// images and archives, by digest — which is why the provision is the artifact store and not an
|
||||||
|
|||||||
@@ -23,3 +23,34 @@ func TestTheVaultsSeatDeliversSecret(t *testing.T) {
|
|||||||
t.Fatal("a provider of secret that does not claim the seat was allowed to hold it")
|
t.Fatal("a provider of secret that does not claim the seat was allowed to hold it")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The vault answers `get` on request and reply (novox/hq ADR 0349 §11, issue 674): the seat promises the
|
||||||
|
// verb, so a holder serving it is accepted — and, optional while the vault that runs is the TypeScript one,
|
||||||
|
// so is a holder that does not yet.
|
||||||
|
func TestTheVaultsSeatPromisesGet(t *testing.T) {
|
||||||
|
seat, _ := SeatNamed("mesh-vault")
|
||||||
|
var get *Verb
|
||||||
|
for i := range seat.Serves {
|
||||||
|
if seat.Serves[i].Name == "get" {
|
||||||
|
get = &seat.Serves[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if get == nil {
|
||||||
|
t.Fatal("the vault's seat does not promise get")
|
||||||
|
}
|
||||||
|
for _, arg := range []string{"name", "public_key"} {
|
||||||
|
if props, _ := get.Input["properties"].(map[string]any); props[arg] == nil {
|
||||||
|
t.Errorf("get takes no %s", arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serving := Manifest{Module: "mesh-vault", Provides: []Offer{{Name: "secret", Scope: ScopeMesh}},
|
||||||
|
Claims: []Claim{{Name: "mesh-vault", Scope: ScopeMesh, Serves: []string{"get"}}}}
|
||||||
|
if err := CanHold(serving, seat); err != nil {
|
||||||
|
t.Fatalf("the vault serving get was refused: %v", err)
|
||||||
|
}
|
||||||
|
notYet := Manifest{Module: "mesh-vault", Provides: []Offer{{Name: "secret", Scope: ScopeMesh}},
|
||||||
|
Claims: []Claim{{Name: "mesh-vault", Scope: ScopeMesh}}}
|
||||||
|
if err := CanHold(notYet, seat); err != nil {
|
||||||
|
t.Fatalf("the vault that does not serve get yet was refused: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user