fix(provision): clamp negative max in ListRecords instead of panicking
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 files changed,
+26
−0
internal/provision/provision.go+10 −0internal/provision/provision_test.go+16 −0
diff --git a/internal/provision/provision.go b/internal/provision/provision.go| index 788d3333f..bb24da438 100644 |
| --- a/internal/provision/provision.go |
| +++ b/internal/provision/provision.go |
| @@ -243,7 +243,17 @@ func GetRecord(ctx context.Context, s release.Store, acct, app, host string) (*R |
| // extra keys past the cap to compensate, and truncated must not depend on |
| // which records happen to be malformed today. A malformed or |
| // path-disagreeing body (GetRecord's own checks) is skipped, not fatal. |
| +// |
| +// A negative max is clamped to 0 rather than treated as "no cap" (a caller |
| +// passing an unvalidated int — a console handler's query param, most |
| +// likely — must degrade safely, not panic on the slice below or list |
| +// everything by accident). max=0 lists nothing but still reports |
| +// truncated when any keys exist, the same "cap decided on key count" rule |
| +// applied at its floor. |
| func ListRecords(ctx context.Context, s release.Store, acct, app string, max int) (recs []Record, truncated bool, err error) { |
| + if max < 0 { |
| + max = 0 |
| + } |
| prefix := RecordsPrefix(acct, app) |
| keys, err := s.List(ctx, prefix) |
| if err != nil { |
diff --git a/internal/provision/provision_test.go b/internal/provision/provision_test.go| index 32b62167e..902b1abd9 100644 |
| --- a/internal/provision/provision_test.go |
| +++ b/internal/provision/provision_test.go |
| @@ -252,6 +252,22 @@ func TestListRecords(t *testing.T) { |
| if len(recs) != 3 { |
| t.Fatalf("ListRecords with a malformed body: got %d records, want 3 (malformed skipped)", len(recs)) |
| } |
| + |
| + // max=0 and a negative max must both degrade to "list nothing", never |
| + // panic on the slice bound — a console handler hands this an |
| + // unvalidated int. |
| + for _, max := range []int{0, -1} { |
| + recs, truncated, err := ListRecords(ctx, s, "bad", "tito", max) |
| + if err != nil { |
| + t.Fatalf("ListRecords with max=%d: %v", max, err) |
| + } |
| + if len(recs) != 0 { |
| + t.Errorf("ListRecords with max=%d: got %d records, want 0", max, len(recs)) |
| + } |
| + if !truncated { |
| + t.Errorf("ListRecords with max=%d: truncated = false, want true (keys exist)", max) |
| + } |
| + } |
| } |
| func TestGetRecord(t *testing.T) { |