Skip to content

SPA: Audit has no date-range filter, and an audit trail is the screen that most needs one #666

Description

@mforce

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

Related: #653 (which established the toolbar pattern), #505 (audit partitioning decision).

Activity

  1. mforce commented on Sep 3, 2026

    @mforce
    OwnerAuthor

    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.

  2. added a commit that references this issue on Sep 4, 2026
  3. added a commit that references this issue on Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions