Plan 002: Make collection analytics event completeness explicit
Executor: follow every step and verification gate. Modify only listed files. Stop and report if a STOP condition occurs.
Status
- Priority: P1
- Effort: M
- Risk: MED
- Depends on: none
- Category: correctness
- Planned at: commit
c16bc4f, 2026-07-16
Why this matters
The analytics query requests at most MAX_MARKET_EVENTS rows and only supplies an upper timestamp bound. For busy collections, bounded ranges can exceed the cap, yet the result is normalized and rendered without a general completeness signal. This can make charts and totals appear complete when they are truncated.
Current state
app/composables/useCollectionAnalytics.ts:71-77 defines a 5,000-row cap and a result flag.
:310-331 calls collectionAnalyticsMarketEvents with limit and timestampLte, then marks allRangeCapped only when range === 'all' and the returned row count reaches the cap.
- The TODO at
:311-312 explicitly identifies missing timestampGte and limit+1 truncation detection.
Commands and expected results
| Purpose |
Command |
Expected result |
| Tests |
pnpm run test -- app/composables/useCollectionAnalytics.spec.ts |
Boundary and truncation tests pass |
| Typecheck |
pnpm run typecheck |
exit 0 |
| Lint |
pnpm run lint -- app/composables/useCollectionAnalytics.ts |
exit 0 |
Scope
In scope:
app/composables/useCollectionAnalytics.ts
- Related analytics query/types/UI test files needed to expose completeness accurately
Out of scope:
- Redesigning all analytics charts
- Changing historical event semantics outside the selected range
Steps
Step 1: Bound the query to the selected range
Compute and send both lower and upper timestamps for every bounded range. Preserve the existing all-time behavior intentionally and document it in the query result contract.
Verify: Unit-test each supported range's lower/upper timestamp variables.
Step 2: Detect truncation without false negatives
Request one extra row (MAX_MARKET_EVENTS + 1) or use the API's supported page metadata, then trim to the display cap and set an explicit completeness flag whenever more rows exist.
Verify: Test zero, exactly-cap, and cap-plus-one rows.
Step 3: Expose the limitation to consumers
Use the existing allRangeCapped result or rename it to a range-agnostic field, then add a clear UI indication wherever analytics present capped results. Do not silently alter numeric totals.
Verify: Component test or existing composable consumer test asserts the warning state.
Test plan
- 1-hour, 1-day, 7-day, 30-day, and 1-year lower bounds are correct.
- Exactly-cap rows are complete; cap-plus-one is truncated.
- All-time results preserve intentional cap signaling.
- Empty responses remain valid.
Done criteria
STOP conditions
- GraphQL schema does not support the proposed lower-bound field; inspect schema/query types and choose the supported equivalent.
- Existing consumers rely on the old flag name in ways requiring broader redesign.
Maintenance notes
If pagination is feasible in the backend, prefer paginated retrieval for exports and retain the capped path only for interactive charts.
Issue body
Bug Description
Collection analytics caps market events at 5,000 but only signals capping for the all range. Bounded ranges can silently undercount busy collections.
Evidence
app/composables/useCollectionAnalytics.ts:310-331
- Existing TODO explicitly calls for
timestampGte and limit+1 truncation detection.
Expected Behavior
Each selected range is bounded by both timestamps, and any cap is surfaced to the user or handled through pagination.
Acceptance Criteria
- Add lower-bound variables for bounded ranges.
- Detect cap-plus-one for all ranges.
- Add regression tests for boundary and truncation cases.
- Preserve explicit user-facing semantics for incomplete results.
- Verification commands pass.
Plan 002: Make collection analytics event completeness explicit
Status
c16bc4f, 2026-07-16Why this matters
The analytics query requests at most
MAX_MARKET_EVENTSrows and only supplies an upper timestamp bound. For busy collections, bounded ranges can exceed the cap, yet the result is normalized and rendered without a general completeness signal. This can make charts and totals appear complete when they are truncated.Current state
app/composables/useCollectionAnalytics.ts:71-77defines a 5,000-row cap and a result flag.:310-331callscollectionAnalyticsMarketEventswithlimitandtimestampLte, then marksallRangeCappedonly whenrange === 'all'and the returned row count reaches the cap.:311-312explicitly identifies missingtimestampGteandlimit+1truncation detection.Commands and expected results
pnpm run test -- app/composables/useCollectionAnalytics.spec.tspnpm run typecheckpnpm run lint -- app/composables/useCollectionAnalytics.tsScope
In scope:
app/composables/useCollectionAnalytics.tsOut of scope:
Steps
Step 1: Bound the query to the selected range
Compute and send both lower and upper timestamps for every bounded range. Preserve the existing all-time behavior intentionally and document it in the query result contract.
Verify: Unit-test each supported range's lower/upper timestamp variables.
Step 2: Detect truncation without false negatives
Request one extra row (
MAX_MARKET_EVENTS + 1) or use the API's supported page metadata, then trim to the display cap and set an explicit completeness flag whenever more rows exist.Verify: Test zero, exactly-cap, and cap-plus-one rows.
Step 3: Expose the limitation to consumers
Use the existing
allRangeCappedresult or rename it to a range-agnostic field, then add a clear UI indication wherever analytics present capped results. Do not silently alter numeric totals.Verify: Component test or existing composable consumer test asserts the warning state.
Test plan
Done criteria
STOP conditions
Maintenance notes
If pagination is feasible in the backend, prefer paginated retrieval for exports and retain the capped path only for interactive charts.
Issue body
Bug Description
Collection analytics caps market events at 5,000 but only signals capping for the
allrange. Bounded ranges can silently undercount busy collections.Evidence
app/composables/useCollectionAnalytics.ts:310-331timestampGteandlimit+1truncation detection.Expected Behavior
Each selected range is bounded by both timestamps, and any cap is surfaced to the user or handled through pagination.
Acceptance Criteria