diff --git a/supernode/cascade/download.go b/supernode/cascade/download.go index 4b1fed7b..01ca8975 100644 --- a/supernode/cascade/download.go +++ b/supernode/cascade/download.go @@ -71,11 +71,12 @@ func (task *CascadeRegistrationTask) Download(ctx context.Context, req *Download } // Step 2: Validate action state. - if actionDetails.GetAction().State != actiontypes.ActionStateDone { - err = errors.New("action is not in a valid state") - fields[logtrace.FieldError] = "action state is not done yet" - fields[logtrace.FieldActionState] = actionDetails.GetAction().State - return task.wrapErr(ctx, "action not finalized yet", err, fields) + state := actionDetails.GetAction().State + if state != actiontypes.ActionStateDone && state != actiontypes.ActionStateApproved { + err = errors.New("action must be in DONE or APPROVED state to download") + fields[logtrace.FieldError] = err.Error() + fields[logtrace.FieldActionState] = state + return task.wrapErr(ctx, "action not ready for download", err, fields) } logtrace.Info(ctx, "download: action state ok", fields) diff --git a/supernode/cascade/stream_send_error_test.go b/supernode/cascade/stream_send_error_test.go index e1b32e7a..b383351b 100644 --- a/supernode/cascade/stream_send_error_test.go +++ b/supernode/cascade/stream_send_error_test.go @@ -3,6 +3,7 @@ package cascade import ( "context" "errors" + "strings" "testing" actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" @@ -81,3 +82,39 @@ func TestDownload_AbortsOnEventSendError(t *testing.T) { t.Fatalf("expected 1 send call, got %d", sendCalls) } } + +func TestDownload_AllowsApprovedState(t *testing.T) { + service := &CascadeService{ + LumeraClient: &stubLumeraClient{action: &actiontypes.Action{ActionID: "action123", State: actiontypes.ActionStateApproved, Metadata: []byte("bad")}}, + } + task := NewCascadeRegistrationTask(service) + + err := task.Download(context.Background(), &DownloadRequest{ActionID: "action123"}, func(*DownloadResponse) error { + return nil + }) + + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "error decoding cascade metadata") { + t.Fatalf("expected metadata decode error, got %v", err) + } +} + +func TestDownload_RejectsInvalidState(t *testing.T) { + service := &CascadeService{ + LumeraClient: &stubLumeraClient{action: &actiontypes.Action{ActionID: "action123", State: actiontypes.ActionStatePending}}, + } + task := NewCascadeRegistrationTask(service) + + err := task.Download(context.Background(), &DownloadRequest{ActionID: "action123"}, func(*DownloadResponse) error { + return nil + }) + + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "action not ready for download") { + t.Fatalf("expected action state error, got %v", err) + } +}