Show users their admin-trail
"What admins did to my account" transparency
For trust, let users see when admins / support agents interacted with their account.
Pattern
In settings:
<section>
<h3>Account activity by support</h3>
{events.length === 0 ? (
<p>No activity</p>
) : (
<table>
{events.map(e => (
<tr>
<td>{e.created_at}</td>
<td>{e.action}</td>
<td>Support agent: {e.actor_name}</td>
<td>{e.reason}</td>
</tr>
))}
</table>
)}
</section>User sees what was done.
Query
SELECT
a.created_at,
a.event_type AS action,
i.traits->>'first_name' AS actor_name,
a.metadata->>'reason' AS reason
FROM security_audit a
JOIN identities i ON a.actor_id = i.id
WHERE a.target_id = $user_id
AND a.actor_type = 'admin'
AND a.actor_id != $user_id -- exclude self-actions
ORDER BY a.created_at DESC
LIMIT 50;What was done to them, by whom.
Visible actions
Show:
- Password reset (by admin).
- MFA disabled (by admin).
- Email changed (by admin).
- Sessions revoked.
- Account locked.
- Account unlocked.
- Role changed.
Don't show:
- Reads (administrative reading of their profile is normal; not noteworthy).
- Audit log views by admin (they don't change the user's account).
const visibleActions = [
"password_reset_by_admin",
"mfa_disabled_by_admin",
"email_changed_by_admin",
"sessions_revoked_by_admin",
"account_locked",
"account_unlocked",
"role_changed",
];Reasons
When admin performs action, require a reason:
// Athena admin tool
<form>
<textarea name="reason" required placeholder="Reason for this action (logged)" />
<Button onClick={revokeSessions}>Revoke all sessions</Button>
</form>INSERT INTO security_audit (event_type, actor_id, target_id, metadata)
VALUES (
'sessions_revoked_by_admin',
$admin_id,
$user_id,
'{"reason": "$reason"}'
);Reason shown to user:
"Reason: Suspected account compromise per ticket #1234"If admin tried to skip reason: forced, UI blocks empty.
Anonymize admin names?
Two views:
Option A: real names
User sees "John Smith reset your password."
Pros: full transparency. Cons: admin's name exposed; could be abused.
Option B: anonymized
User sees "Support agent A reset your password."
Pros: protects admin from harassment. Cons: less specific.
Most B2C: option B. B2B with named CSMs: option A.
When was it done
Time-stamps important:
<time dateTime={e.created_at}>{formatDateAgo(e.created_at)}</time>"2 hours ago"
"May 10, 2026 at 3:30 PM"User context.
Self-actions
Hide admin actions where user did it (admin = self):
WHERE actor_id != target_idOtherwise you'd show "You changed your password", confusing.
Notification on admin action
Beyond passive view, push notifications:
// When admin acts:
await sendEmail(user.email, "Account activity", `
Hi,
A member of our support team [name? or "support"] performed this action
on your account:
Action: ${action}
Reason: ${reason}
Date: ${date}
If you didn't expect this contact, please reply to this email.
`);User informed in real-time.
Trust signaling
Beyond audit, communicate practices:
"Our policy: admins never view your account without a logged reason.
You can see all admin activity in Settings → Account activity."Privacy-respecting framing.
Restrictions
Some actions might not be user-visible (security investigations in progress):
// Filter by visibility flag
WHERE a.metadata->>'visibility' != 'hidden'Use sparingly, fixed-period hiding (30 days). Don't hide indefinitely.
Compare to industry
Various models:
- Google: Recent activity page shows admin actions on your account (rare).
- Apple: less transparent.
- Stripe: account events log includes Stripe's own actions.
Olympus default: transparent. Customer can override.
Disputed actions
User says "I didn't request password reset; admin shouldn't have done it."
Have a dispute flow:
- User clicks "Dispute this action."
- Support reviews ticket reference.
- If admin error: train, fix.
- If user mistaken: explain.
Audit the audit view
When user views admin trail:
INSERT INTO security_audit (event_type, actor_id, target_id, metadata)
VALUES ('admin_trail_viewed', $user_id, $user_id, '{}');Trace who viewed what. Helps detect curious users (potential reconnaissance).