1
0
forked from wrenn/wrenn
## What's new

Compliance, audit, and account lifecycle improvements — admin actions are now fully auditable, user data is properly anonymized on deletion, and OAuth signup flow gives users control over their profile.

### Audit

- Added audit logging for all admin actions (user activate/deactivate, team BYOC toggle, team delete, template delete, build create/cancel)
- Added admin audit page with infinite scroll and hierarchical filters
- Fixed audit log team assignment — admin/host actions now correctly land under PlatformTeamID
- Anonymize audit logs on user hard-delete (actor name, IDs, emails stripped)
- Deduplicated audit logger internals (665 → 374 lines, no behavior change)

### Authentication

- Separated GitHub OAuth login/signup flows — login no longer auto-creates accounts
- Added name confirmation dialog for new GitHub signups

### Account Lifecycle

- Email notification sent when account is permanently deleted after grace period
- Audit log anonymization tied to user purge (per-user transactional)

### UX

- Removed accent gradient bars from admin host dialogs (border + shadow only)
- Frontend renders deleted users as styled badge in audit log view

### Others

- Version bump
- Bug fixes

Reviewed-on: wrenn/wrenn#36
This commit is contained in:
2026-04-21 10:11:49 +00:00
parent 23dca7d9ff
commit 52ad21c339
25 changed files with 1200 additions and 443 deletions

View File

@ -11,6 +11,21 @@ import (
"github.com/jackc/pgx/v5/pgtype"
)
const anonymizeAuditLogsByUserID = `-- name: AnonymizeAuditLogsByUserID :exec
UPDATE audit_logs
SET actor_name = CASE WHEN actor_id = $1 THEN 'deleted-user' ELSE actor_name END,
actor_id = CASE WHEN actor_id = $1 THEN NULL ELSE actor_id END,
resource_id = CASE WHEN resource_type = 'member' AND resource_id = $1 THEN NULL ELSE resource_id END,
metadata = CASE WHEN resource_type = 'member' AND resource_id = $1 AND metadata ? 'email' THEN metadata - 'email' ELSE metadata END
WHERE actor_id = $1
OR (resource_type = 'member' AND resource_id = $1)
`
func (q *Queries) AnonymizeAuditLogsByUserID(ctx context.Context, actorID pgtype.Text) error {
_, err := q.db.Exec(ctx, anonymizeAuditLogsByUserID, actorID)
return err
}
const insertAuditLog = `-- name: InsertAuditLog :exec
INSERT INTO audit_logs (id, team_id, actor_type, actor_id, actor_name, resource_type, resource_id, action, scope, status, metadata)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)