Let the lease key name its ask and time, and the user-list key say the lease is handed
ADR 0582 clause 3 writes the key holder "with the why, the ask and the time": LeaseHolder gains ask and at, which LeaseHandedAway ignores (it reads handed-to alone). The grants part's user-list key gains lease-handed, so the bus node's engine follows the grants part's list alone once the lease is handed (ADR 0571 clause 8) and never falls back to the controller's; a key written before reads false. Tests: a row in the lease table of TestTheCopiedComposerComposesAsTheControllers; the old key (shaped as EncodeGrantsUserList writes it today) and the flag's round trip added to the existing user-list case in delivery_test.go; no new test function. (issue 774, 774/S3) Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -219,6 +219,10 @@ type LeaseHolder struct {
|
||||
// HandedBy is the credential that wrote it (the operator's), and Why its reason.
|
||||
HandedBy string `json:"handed-by,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
// Ask is the operator's ask whose warrant handed it (novox/hq ADR 0582 clause 3: "with the why, the ask and the
|
||||
// time"), and At when it was written. Neither turns the lease: LeaseHandedAway reads HandedTo alone.
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At time.Time `json:"at,omitzero"`
|
||||
}
|
||||
|
||||
// LeaseHandedAway reads the lease key as a getter answered it (its value, whether it was there, the read's error) and
|
||||
|
||||
@@ -561,6 +561,9 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
||||
}{
|
||||
{"a controller holds it", `{"instance":"novox/1234/2026-10-27T20:00:00Z","epoch":57}`, true, nil, false},
|
||||
{"handed away", `{"handed-to":"the operator's hand-over","handed-by":"person.jochen"}`, true, nil, true},
|
||||
// ADR 0582 clause 3 (774/S3): the write names the ask and the time, which turn nothing.
|
||||
{"handed to mesh-grants with its ask and time", `{"handed-to":"mesh-grants","handed-by":"person.jochen","why":"w",` +
|
||||
`"ask":"lease-write-1","at":"2026-11-02T10:00:00Z"}`, true, nil, true},
|
||||
{"expired or deleted", ``, false, nil, false},
|
||||
{"unreadable", ``, false, errors.New("refused"), false},
|
||||
{"not a holder", `[1]`, true, nil, false},
|
||||
|
||||
@@ -242,9 +242,22 @@ func TestRoundTrip(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
back, err := DecodeGrantsUserList(raw)
|
||||
if err != nil || back.Digest != digest || back.LeftOut == nil || back.Follow != FollowGrants {
|
||||
if err != nil || back.Digest != digest || back.LeftOut == nil || back.Follow != FollowGrants || back.LeaseHanded {
|
||||
t.Fatalf("decoded %+v, %v", back, err)
|
||||
}
|
||||
// ADR 0582 clause 3 (issue 774, 774/S3): a key written before the flag existed reads not handed; one written with
|
||||
// it reads handed.
|
||||
if old, err := DecodeGrantsUserList([]byte(`{"v":1,"follow":"grants","digest":"","object":"","sealed_to":"",` +
|
||||
`"node":"novox","revision":3,"users":40,"left_out":[],"at":"2026-10-30T10:00:00Z"}`)); err != nil || old.LeaseHanded {
|
||||
t.Errorf("a key from before the lease write decodes %+v, %v", old, err)
|
||||
}
|
||||
g.LeaseHanded = true
|
||||
if raw, err := EncodeGrantsUserList(g); err != nil || !bytes.Contains(raw, []byte(`"lease-handed":true`)) {
|
||||
t.Errorf("the handed flag is written as %s, %v", raw, err)
|
||||
} else if back, err := DecodeGrantsUserList(raw); err != nil || !back.LeaseHanded {
|
||||
t.Errorf("the handed flag reads back %+v, %v", back, err)
|
||||
}
|
||||
g.LeaseHanded = false
|
||||
for _, bad := range []GrantsUserList{{Follow: "both", Digest: digest, Object: g.Object},
|
||||
{Follow: FollowGrants, Digest: digest, Object: "other"}, {Follow: FollowGrants, Digest: "md5:x", Object: "md5:x"}} {
|
||||
if _, err := EncodeGrantsUserList(bad); err == nil {
|
||||
|
||||
@@ -65,6 +65,10 @@ type GrantsUserList struct {
|
||||
// LeftOut are the users the list leaves out for want of a hash in the vault.
|
||||
LeftOut []string `json:"left_out"`
|
||||
At time.Time `json:"at"`
|
||||
// LeaseHanded says the controller's lease is handed to the grants part (novox/hq ADR 0582 clause 3, ADR 0571 clause
|
||||
// 8): from then on the bus node follows this list alone and never falls back to the controller's. A key written
|
||||
// before it reads false.
|
||||
LeaseHanded bool `json:"lease-handed,omitempty"`
|
||||
}
|
||||
|
||||
// EncodeGrantsUserList is g as JSON at Version; it refuses a value the bus node could not follow.
|
||||
|
||||
Reference in New Issue
Block a user