Change AuthorizationAttributer.AuthorizationAttributes to take a slice
of resource ids and return policy.AttributesByID, so a single SQL
round-trip can load condition attributes for a whole batch. All
coredata implementations are migrated to a single
`WHERE id = ANY(@resource_ids::text[])` query that returns only the
rows it finds.
Authorizer gains:
- AuthorizeBatch — all-or-nothing across a homogeneous (same entity
type, same organization) resource set; rejects mixed entity types,
mixed organizations, and empty batches with structured errors.
- AuthorizeMulti — heterogeneous evaluation that returns one error
per item and writes audit log entries in a single bulk insert.
The single-resource Authorize is rewired to delegate to AuthorizeBatch
so all paths share the same condition evaluation and audit logging.
recordAuditLog is split into buildAuditLogEntry plus a batch insert.
Tests cover the new batch and multi paths, mixed/empty/unsupported
resource cases, audit log batching, and dry-run behaviour.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Subsequent fetches of the same source re-upsert every access entry.
Without a guard, a reviewer's (or an agent's) decision, its note, and
the flags that drove it would be silently replaced on every poll.
The ON CONFLICT DO UPDATE SET clause now refreshes only the columns
that track live source state (email, full_name, role, is_admin, MFA,
etc.) and deliberately omits the verdict bundle -- flags, flag_reasons,
decision, decision_note, decided_by, decided_at -- so the audit trail
stays consistent with whatever the reviewer or agent last recorded.
Tighten the signature from pg.Querier to pg.Tx to match the rest of
the coredata package -- every caller already runs inside WithTx.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>