You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SPA: Audit has no date-range filter, and an audit trail is the screen that most needs one #666
Found while implementing #653, which lists Audit among the screens whose date-range filters move into a bounded toolbar. It has none to move.
$ grep -n 'type="date"\|type="month"' web/src/routes/AuditPage.tsx
(no output)
AuditPage.tsx filters on entity type and action — two <select>s — and nothing else. #653's acceptance criterion "date-range filters sit in a toolbar at a bounded width on every screen that has one" is therefore satisfied there vacuously, which is not the same as satisfied.
Why it matters more here than on the screens that do have one
An audit trail is read to answer "what happened, and when" — almost always about a window. Every other question the screen supports (which entity, which action) narrows a haystack that is still unbounded in time. Feed, Water, Expenses, History and Reports all have a date filter; the one screen whose entire purpose is chronological does not.
It also grows without bound. AuditEvents is deliberately not time-partitioned (#505) because the dominant read filters on AccountId+EntityType+EntityId with no date predicate — a decision worth re-reading before adding a date filter, because a date-filtered audit query is exactly the read that decision says the table is not optimised for. Whether the filter should be added is partly a query-shape question, not only a UI one.
Scope
Whether the API's audit endpoint already accepts a date range, or needs one.
Scope note: the API side is already done, and the index question is answered
Investigated before planning. Recording it here because this issue's body asks two questions that turn out to have answers in the shipped code.
1. Does the audit endpoint accept a date range? Yes, already. AuditEndpoints.cs:29-30 takes DateOnly? from / DateOnly? to, IAuditEventRepository.ListAsync carries them, and listAuditEvents in web/src/api/cluckwork.ts:918-930 already types and serialises them. AuditPage.tsx:132 simply never sends them. So this is SPA-only — no endpoint, handler, validator or repository change.
2. The index question. This issue says a date-filtered audit query is "exactly the read that decision says the table is not optimised for". That rests on a conflation, and it is worth correcting on the record: #505 is about partitioning, not indexing. It argues that range-partitioning by month is the wrong axis, because pruning only helps a query filtering on the partition key while the dominant read (AccountId+EntityId) does not — turning one lookup on IX_AuditEvents_AccountId_EntityId into one per partition. It never says the table has no date index.
It has one.AuditEventConfiguration.cs:24 declares HasIndex(e => new { e.AccountId, e.OccurredAtUtc }), beside (AccountId, EntityId) on line 25. A date-narrowed audit read under a resolved tenant is an index lookup today. So: no migration, no index, no amendment to #505 — not as a deferral to be measured later, but because the schema already supports the read.
One thing this issue did not ask for and is getting. Audit's zero-row state currently says "No audit events yet." Under an active date filter that is a false statement — the log is not empty, the window is. A third message ships with the filter.
Day-boundary semantics, stated so it is not a surprise: audit's from/to are inclusive calendar days over the UTC timestamp (AuditEventRepository.cs:15-25), matching this screen's own "When (UTC)" column header. Expenses' equivalent control filters farm-local business dates. Same-looking controls, different windows, both correct.
Design: docs/designs/666-667-spa-date-range-filters.md. Shipping together with #667 and a Stock fix in one PR.
Activity
mforce commentedon Sep 3, 2026
Scope note: the API side is already done, and the index question is answered
Investigated before planning. Recording it here because this issue's body asks two questions that turn out to have answers in the shipped code.
1. Does the audit endpoint accept a date range? Yes, already.
AuditEndpoints.cs:29-30takesDateOnly? from/DateOnly? to,IAuditEventRepository.ListAsynccarries them, andlistAuditEventsinweb/src/api/cluckwork.ts:918-930already types and serialises them.AuditPage.tsx:132simply never sends them. So this is SPA-only — no endpoint, handler, validator or repository change.2. The index question. This issue says a date-filtered audit query is "exactly the read that decision says the table is not optimised for". That rests on a conflation, and it is worth correcting on the record: #505 is about partitioning, not indexing. It argues that range-partitioning by month is the wrong axis, because pruning only helps a query filtering on the partition key while the dominant read (
AccountId+EntityId) does not — turning one lookup onIX_AuditEvents_AccountId_EntityIdinto one per partition. It never says the table has no date index.It has one.
AuditEventConfiguration.cs:24declaresHasIndex(e => new { e.AccountId, e.OccurredAtUtc }), beside(AccountId, EntityId)on line 25. A date-narrowed audit read under a resolved tenant is an index lookup today. So: no migration, no index, no amendment to #505 — not as a deferral to be measured later, but because the schema already supports the read.One thing this issue did not ask for and is getting. Audit's zero-row state currently says "No audit events yet." Under an active date filter that is a false statement — the log is not empty, the window is. A third message ships with the filter.
Day-boundary semantics, stated so it is not a surprise: audit's
from/toare inclusive calendar days over the UTC timestamp (AuditEventRepository.cs:15-25), matching this screen's own "When (UTC)" column header. Expenses' equivalent control filters farm-local business dates. Same-looking controls, different windows, both correct.Design:
docs/designs/666-667-spa-date-range-filters.md. Shipping together with #667 and a Stock fix in one PR.fix(web): the audit date filter rejects impossible dates, and its his…
fix(web): a scoped audit view filtered to nothing names both the reco…
fix(web): the audit date filter accepts low-numbered years, and its e…
docs: name the scoped filtered-empty key and state the #653 relations…
fix(web): date validation gets one boundary table instead of one case…
test(web): pin whitespace against a lenient future date validator, an…
docs(web): the help text stops describing a cap the filters no longer…
docs(web): the help text claims only what is true of recording, and s…
docs: item 7 names each screen's actual initial filter value (#666)
docs(web): the date-cap help text covers every stocked item, not only…
fix(web): the help text calls the expiry field what the field calls i…
Merge pull request #678 from mforce/feat/666-667-spa-date-range-filters
chore(main): release 0.1.0 (#542)
feat(web): redesign Audit onto Concept C "Focus panels", expandable e…
feat(web): redesign Audit onto Concept C "Focus panels", expandable e…