fix(snapshot): address recovery review findings
- commit
- 697053d9d5cdde5e055961e764df81e6fa20ab9c
- author
- brice · · 2026-07-27 14:36 UTC
- parent
- 6bbbdf6
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +10 -2
M internal/usecase/daemon/snapshot_capture.go +1 -1
| @@ -2,7 +2,7 @@ package daemon | |||
| 2 | 2 | ||
| 3 | 3 | import snapcodec "github.com/bnema/vev/internal/usecase/snapshot" | |
| 4 | 4 | ||
| 5 | - | // captureSession copies history tails and recovery transcripts while holding | |
| 5 | + | // captureSnapshotState copies history tails and recovery transcripts while holding | |
| 6 | 6 | // each pane lock. The returned capture contains only immutable state; encoding | |
| 7 | 7 | // and persistence are deliberately deferred to snapshotEncodeWorker. | |
| 8 | 8 | func (d *Daemon) captureSnapshotState(sess *session, generation uint64) (*snapshotCapture, bool) { | |
| @@ -2,7 +2,7 @@ package daemon | |||||
| 2 | 2 | ||||
| 3 | import snapcodec "github.com/bnema/vev/internal/usecase/snapshot" | 3 | import snapcodec "github.com/bnema/vev/internal/usecase/snapshot" | ||
| 4 | 4 | ||||
| 5 | - | // captureSession copies history tails and recovery transcripts while holding | 5 | + | // captureSnapshotState copies history tails and recovery transcripts while holding |
| 6 | // each pane lock. The returned capture contains only immutable state; encoding | 6 | // each pane lock. The returned capture contains only immutable state; encoding | ||
| 7 | // and persistence are deliberately deferred to snapshotEncodeWorker. | 7 | // and persistence are deliberately deferred to snapshotEncodeWorker. | ||
| 8 | func (d *Daemon) captureSnapshotState(sess *session, generation uint64) (*snapshotCapture, bool) { | 8 | func (d *Daemon) captureSnapshotState(sess *session, generation uint64) (*snapshotCapture, bool) { | ||
M internal/usecase/snapshot/manifest_test.go +4 -0
| @@ -88,6 +88,10 @@ func TestManifestCodecUsesGenerationAndOrderedTypedReferences(t *testing.T) { | |||
| 88 | 88 | if got.Generation != manifest.Generation || got.Tabs[0].Panes[0].Tail != manifest.Tabs[0].Panes[0].Tail { | |
| 89 | 89 | t.Fatalf("round trip = %#v", got) | |
| 90 | 90 | } | |
| 91 | + | gotTranscript := got.Tabs[0].Panes[0].Transcript | |
| 92 | + | if gotTranscript.Kind != RecoveryTranscript || gotTranscript.Digest != transcript.Digest || gotTranscript.Size != uint32(len(transcript.Data)) { | |
| 93 | + | t.Fatalf("transcript round trip = %#v", gotTranscript) | |
| 94 | + | } | |
| 91 | 95 | for n := range len(encoded) { | |
| 92 | 96 | if _, err := UnmarshalManifest(encoded[:n]); err == nil { | |
| 93 | 97 | t.Fatalf("prefix %d accepted", n) | |
| @@ -88,6 +88,10 @@ func TestManifestCodecUsesGenerationAndOrderedTypedReferences(t *testing.T) { | |||||
| 88 | if got.Generation != manifest.Generation || got.Tabs[0].Panes[0].Tail != manifest.Tabs[0].Panes[0].Tail { | 88 | if got.Generation != manifest.Generation || got.Tabs[0].Panes[0].Tail != manifest.Tabs[0].Panes[0].Tail { | ||
| 89 | t.Fatalf("round trip = %#v", got) | 89 | t.Fatalf("round trip = %#v", got) | ||
| 90 | } | 90 | } | ||
| 91 | + | gotTranscript := got.Tabs[0].Panes[0].Transcript | |||
| 92 | + | if gotTranscript.Kind != RecoveryTranscript || gotTranscript.Digest != transcript.Digest || gotTranscript.Size != uint32(len(transcript.Data)) { | |||
| 93 | + | t.Fatalf("transcript round trip = %#v", gotTranscript) | |||
| 94 | + | } | |||
| 91 | for n := range len(encoded) { | 95 | for n := range len(encoded) { | ||
| 92 | if _, err := UnmarshalManifest(encoded[:n]); err == nil { | 96 | if _, err := UnmarshalManifest(encoded[:n]); err == nil { | ||
| 93 | t.Fatalf("prefix %d accepted", n) | 97 | t.Fatalf("prefix %d accepted", n) | ||
M internal/usecase/snapshot/preflight.go +5 -1
| @@ -220,9 +220,13 @@ func preflightPaneStructure(r *payloadReader, totals *vt.DecodeStats, blobs *uin | |||
| 220 | 220 | if tail.Chunks > 1 { | |
| 221 | 221 | return fmt.Errorf("%w: tail blob role", ErrInvalidData) | |
| 222 | 222 | } | |
| 223 | - | if _, err := preflightBlob(r, totals, blobs, budget); err != nil { | |
| 223 | + | transcript, err := preflightBlob(r, totals, blobs, budget) | |
| 224 | + | if err != nil { | |
| 224 | 225 | return err | |
| 225 | 226 | } | |
| 227 | + | // Transcripts are canonical history; they may contain multiple chunks or be | |
| 228 | + | // empty, so no blob-role assertion applies. | |
| 229 | + | _ = transcript | |
| 226 | 230 | return preflightProcess(r) | |
| 227 | 231 | } | |
| 228 | 232 | ||
| @@ -220,9 +220,13 @@ func preflightPaneStructure(r *payloadReader, totals *vt.DecodeStats, blobs *uin | |||||
| 220 | if tail.Chunks > 1 { | 220 | if tail.Chunks > 1 { | ||
| 221 | return fmt.Errorf("%w: tail blob role", ErrInvalidData) | 221 | return fmt.Errorf("%w: tail blob role", ErrInvalidData) | ||
| 222 | } | 222 | } | ||
| 223 | - | if _, err := preflightBlob(r, totals, blobs, budget); err != nil { | 223 | + | transcript, err := preflightBlob(r, totals, blobs, budget) |
| 224 | + | if err != nil { | |||
| 224 | return err | 225 | return err | ||
| 225 | } | 226 | } | ||
| 227 | + | // Transcripts are canonical history; they may contain multiple chunks or be | |||
| 228 | + | // empty, so no blob-role assertion applies. | |||
| 229 | + | _ = transcript | |||
| 226 | return preflightProcess(r) | 230 | return preflightProcess(r) | ||
| 227 | } | 231 | } | ||
| 228 | 232 | ||||