Cross-LV helpers shared by the staff admin LiveViews.
log_operation_error/3 — failure-side audit rows
Staff's documented architectural choice is that PhoenixKitStaff.Activity
is success-only at the call site (see CLAUDE.md "Activity logging").
The post-Apr pipeline expects every user-driven mutation to leave an
audit row on BOTH :ok AND :error branches so a DB outage / FK
violation / constraint failure can't silently erase admin clicks
from the activity feed.
The catalogue module's Batch 4 (canonical reference at
phoenix_kit_catalogue/lib/phoenix_kit_catalogue/web/helpers.ex)
resolves the tension by writing the failure-side row at the
LiveView layer, not in the context. Same intent here:
- One edit point in this helper instead of ~10 LV mutation sites
- Same action atom the success path would have used
(e.g.
staff.person_deleted) metadata.db_pending: trueso audit-feed readers can distinguish attempted-but-failed from completed actions- PII-safe metadata: changeset reasons land error-key field names
only (no values), atom reasons land the atom string, other shapes
get
error_kind: "other"
Helper only fires from handle_event {:error, _} branches —
validate cycles never reach it (they're handled by the form's
assign_form/2 cycle, no audit row needed for keystrokes).
Summary
Functions
Writes a failure-side activity row for a destructive/mutating operation.
Functions
@spec log_operation_error(String.t(), Phoenix.LiveView.Socket.t(), keyword()) :: :ok | :activity_unavailable | {:ok, struct()} | {:error, any()}
Writes a failure-side activity row for a destructive/mutating operation.
Required opts
:resource_type— string, e.g."staff_person"/"department":reason— the{:error, reason}value from the context call
Optional opts
:resource_uuid— uuid of the record the operation targeted. Optional because failed CREATE submissions have no uuid yet — in that case the audit row records intent without a target.:target_uuid— second-party uuid for membership operations (the user being added/removed, etc.):metadata— extra metadata (must be PII-safe). Merged UNDER the helper's owndb_pending/error_kind/error_keys/error_atomkeys — caller-supplied collisions on those keys are ignored so the audit-feed contract stays stable.
Returns the underlying Activity.log/2 return value (:ok,
{:ok, _entry}, {:error, _}, :activity_unavailable); never
raises.