chio_kernel/receipt_query.rs
1use crate::receipt_store::StoredToolReceipt;
2
3/// Maximum number of receipts returnable in a single query page.
4pub const MAX_QUERY_LIMIT: usize = 200;
5
6/// Query parameters for filtering and paginating tool receipts.
7#[derive(Debug, Default, Clone)]
8pub struct ReceiptQuery {
9 /// Filter by capability ID (exact match).
10 pub capability_id: Option<String>,
11 /// Filter by tool server name (exact match).
12 pub tool_server: Option<String>,
13 /// Filter by tool name (exact match).
14 pub tool_name: Option<String>,
15 /// Filter by decision outcome (maps to decision_kind column:
16 /// "allow", "deny", "cancelled", "incomplete").
17 pub outcome: Option<String>,
18 /// Include only receipts with timestamp >= since (Unix seconds, inclusive).
19 pub since: Option<u64>,
20 /// Include only receipts with timestamp <= until (Unix seconds, inclusive).
21 pub until: Option<u64>,
22 /// Include only receipts with financial cost_charged >= min_cost (minor units).
23 /// Receipts without financial metadata are excluded when this filter is set.
24 pub min_cost: Option<u64>,
25 /// Include only receipts with financial cost_charged <= max_cost (minor units).
26 /// Receipts without financial metadata are excluded when this filter is set.
27 pub max_cost: Option<u64>,
28 /// Cursor for forward pagination: return only receipts with seq > cursor (exclusive).
29 pub cursor: Option<u64>,
30 /// Maximum number of receipts to return per page (capped at MAX_QUERY_LIMIT).
31 pub limit: usize,
32 /// Filter by agent subject public key (hex-encoded Ed25519). Resolved through
33 /// capability_lineage JOIN -- does not replay issuance logs.
34 pub agent_subject: Option<String>,
35 /// Phase 1.5 multi-tenant receipt isolation: restrict results to a
36 /// tenant. When `Some(id)`, the store returns receipts whose
37 /// `tenant_id = id` OR whose `tenant_id IS NULL` (the pre-
38 /// multi-tenant "public" set) so legacy receipts remain visible
39 /// during the transition. When `None`, no filter is applied --
40 /// intended for admin / compat query paths only.
41 ///
42 /// For strict isolation that excludes the NULL fallback set, the
43 /// caller must also flip the store's strict-tenant-isolation mode
44 /// via `SqliteReceiptStore::with_strict_tenant_isolation(true)`.
45 ///
46 /// MUST be derived from the caller's authentication context at the
47 /// HTTP edge, not from a query parameter. See
48 /// `docs/protocols/STRUCTURAL-SECURITY-FIXES.md` section 6.
49 pub tenant_filter: Option<String>,
50}
51
52/// Result of a receipt query, including pagination state.
53#[derive(Debug)]
54pub struct ReceiptQueryResult {
55 /// Receipts matching the query filters, ordered by seq ASC.
56 pub receipts: Vec<StoredToolReceipt>,
57 /// Total number of receipts matching the filters (independent of limit/cursor).
58 pub total_count: u64,
59 /// Cursor for the next page: Some(last_seq) when more results exist, None on last page.
60 pub next_cursor: Option<u64>,
61}