QueryAudit
One query as an audit trail sees it: who asked (caller; Wow does not own identity), what shape of query on which model version, under which restrictions, and what came back. It never carries a filter value, so no personal data from the query reaches the audit log.
Parameters
computes fingerprint on first read.
Types
Properties
the aggregate type queried.
who ran the query, for the principal and its attributes.
The tenants a cross-tenant query read, the caller's; null for any other. Every such audit is logged at INFO (CROSS_TENANT_LOGGER).
the query's entry, as the caller stated it.
the error code of a failed query (QueryError.errorCode and, when it states one, the rule code of its first binding error); for a state read answered as not found, wow.aggregate.not-found:<reason> (StateNotFoundException.Reason).
A hash of the submitted query's shape (queryShapeOf: operators, fields, value counts, sort, projection, groups, metrics and the paging kind and size), with every value, search text, alias and cursor left out, so equal shapes group together. Computed on first read, so an observer that never reads it (a metrics observer, say) does not pay for it.
the masked fields of the model the response carries, read from the admitted (canonical) projection so an alias cannot hide one; empty for a count, an aggregation or a query rejected before admission.
the queried model, or null when the query was rejected before its schema loaded, and for a state read (QueryType.STATE, QueryType.TRACE), which reads no query model.
the content hash of the model's schema (QueryModelSchema.version).
how the query ended.
the QueryPolicy classes that restricted the query (those that returned anything but match-all).
the fields the caller's scope restricts (tenantId, ownerId, ...), not their values.