Read the vault's structured move-in refusal and take a value it holds another of as superseded, so the move is not asked again for ever (issue 774)
mesh-vault (mesh-catalog f3b13de2) answers a move it refuses with `refused: {reason, held}` and `why`, and
no read-back. The engine read only the read-back, so every such row failed "answered with no read-back"
and the controller asked it again on every pass.
Quick fix: treat any answer without a read-back as done. Thorough fix (chosen): read `refused`. For
holds-another-value the vault's value is the live one: the move answers done, superseded, at the held
generation with the held record in its words, so the controller records the row and stops asking; the
journal says it once per secret. Any other reason fails in the vault's own words.
This commit is contained in:
@@ -54,6 +54,9 @@ type MoveSecretAnswer struct {
|
||||
Secret string `json:"secret,omitempty"`
|
||||
Generation int `json:"generation,omitempty"`
|
||||
Unchanged bool `json:"unchanged,omitempty"`
|
||||
// Superseded is set when the vault holds another value for the name, which is the live one: the row is done and
|
||||
// is not asked again; Generation is the held value's, and Said its record in words.
|
||||
Superseded bool `json:"superseded,omitempty"`
|
||||
}
|
||||
|
||||
// MoveSecret is one move asked and believed, as the handler is given it: the row, this machine, and who asked.
|
||||
@@ -70,6 +73,9 @@ type MovedSecret struct {
|
||||
Secret string
|
||||
Generation int
|
||||
Unchanged bool
|
||||
// Superseded says, in words, that the vault holds another value for the name, which is the live one: nothing was
|
||||
// moved, and the move is done (the vault's record of the held value, its generation in Generation).
|
||||
Superseded string
|
||||
}
|
||||
|
||||
// MoveSecretFunc moves one value into the vault: what it kept, or why not.
|
||||
@@ -133,7 +139,11 @@ func AnswerMoveSecret(check HandOverCheck, handle MoveSecretFunc, body []byte) M
|
||||
if moved.Unchanged {
|
||||
said = fmt.Sprintf("the vault held %s already, the same value (generation %d)", moved.Secret, moved.Generation)
|
||||
}
|
||||
return MoveSecretAnswer{Said: said, Secret: moved.Secret, Generation: moved.Generation, Unchanged: moved.Unchanged}
|
||||
if moved.Superseded != "" {
|
||||
said = moved.Superseded
|
||||
}
|
||||
return MoveSecretAnswer{Said: said, Secret: moved.Secret, Generation: moved.Generation, Unchanged: moved.Unchanged,
|
||||
Superseded: moved.Superseded != ""}
|
||||
}
|
||||
|
||||
// MoveSecretReply is what a move request is answered with, and whether to answer, as HandOverReply.
|
||||
|
||||
@@ -28,8 +28,9 @@ func TestTheMovesAskKeepsItsFieldNamesAndContext(t *testing.T) {
|
||||
if MoveSecretContext != "novox-mesh move-secret v1\n" {
|
||||
t.Fatalf("the signing context is %q", MoveSecretContext)
|
||||
}
|
||||
answer, _ := json.Marshal(MoveSecretAnswer{Said: "s", Refused: "r", Secret: "own/a/b/c", Generation: 1, Unchanged: true})
|
||||
if got := keysOf(t, answer); got != "generation refused said secret unchanged" {
|
||||
answer, _ := json.Marshal(MoveSecretAnswer{Said: "s", Refused: "r", Secret: "own/a/b/c", Generation: 1, Unchanged: true,
|
||||
Superseded: true})
|
||||
if got := keysOf(t, answer); got != "generation refused said secret superseded unchanged" {
|
||||
t.Fatalf("the answer's fields are %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user