audit-trail
Specifies an append-only audit events model and the rules for writing, reading, retaining and exporting it.
looks for
- admin actions, role or permission changes
- money, pricing or inventory edits
- sign-in, password, key and token lifecycle events
- deletes of user data
- who changed this and when?
outputs
- → an audit_events schema
- → a list of audited actions with naming convention
- → write path, access rules, retention and export plan
SKILL.md
Audit trail
An audit log answers who did what, to what, when, from where, and what changed, and it cannot be quietly edited afterwards.
Schema (relational example)
create table audit_events (
id uuid primary key default gen_random_uuid(),
occurred_at timestamptz not null default now(),
tenant_id uuid not null, -- org / workspace scope
actor_type text not null, -- user | api_key | system | support
actor_id text, -- null for system
actor_label text, -- display name at the time
action text not null, -- e.g. 'member.role.changed'
target_type text not null, -- e.g. 'member'
target_id text,
ip inet,
user_agent text,
request_id text, -- correlate with app logs
before jsonb, -- changed fields only, redacted
after jsonb,
metadata jsonb not null default '{}'
);
create index on audit_events (tenant_id, occurred_at desc);
create index on audit_events (tenant_id, target_type, target_id, occurred_at desc);
What to audit
- Auth: sign-in success/failure, sign-out, MFA changes, password reset, session revoke.
- Access: invite, join, remove, role change, API key create/rotate/revoke.
- Money and data: price/total edits, refunds, exports, bulk deletes, imports.
- Settings: anything in an admin console.
- Support/impersonation: always, with the real operator as actor.
Name actions resource.verb or resource.field.verb in past tense
(invoice.voided, member.role.changed). Keep the list in code as an enum.
Write rules
- Append-only. No updates or deletes from the app. Enforce in the database:
revoke
update/delete, or a trigger that raises. - Write in the same transaction as the change when the change must not happen unaudited; for best-effort events (reads, sign-in failures), write outside it so a rollback doesn't erase the attempt.
- Server decides actor, tenant, IP and time. Never trust the client for them.
- Diff, not dump: store only changed fields in before/after.
- Redact: never store passwords, tokens, secrets, full card numbers or unnecessary personal data. Hash or mask where an identifier is needed.
- Optional tamper evidence: a hash chain (
hash = sha256(prev_hash || row)) or periodic export to write-once storage.
Read rules
- Tenant-scoped; only admins (and the actor, for their own events) can read.
- Reading exports of the audit log is itself audited.
- UI: a filterable timeline per tenant and per object ("History" tab).
Retention and export
- Retention by policy (
{{RETENTION}}, e.g. 1 year hot, 7 years archived). - Purge by partition/date, by a privileged job, which logs its own run.
- Export as CSV/JSON with the same filters as the UI.
- Personal-data erasure: pseudonymize
actor_label/IP rather than deleting events.
Checklist
- Every action in the list writes an event (test per action)
- App role cannot update/delete audit rows (test it)
- No secrets in before/after (test with a password change)
- Tenant isolation on reads (test cross-tenant)
- Retention job documented
Customize for your project
Database ({{DATABASE}}), tenant model, {{RETENTION}}, compliance regime
(SOC 2, HIPAA, GDPR), and where the History UI lives.
pairs with
- skilltrueorfalse
api-contract
Locks request/response shapes and change rules so clients and servers can ship independently without breaking.
- a new or changed endpoint
- a field rename, removal or type change
- plain-text error responses
Claude · Codex · ChatGPT - agenttrueorfalse
privacy-check
Blocks or clears content for publishing by scanning for secrets, real identities, internal hosts and raw data.
- staged changes to docs, screenshots, fixtures or sample data
- strings shaped like keys, tokens or JWTs
- IP addresses and non-allowed hostnames
Claude · Codex · ChatGPT - skilltrueorfalse
adr
Captures one decision with its context, rejected options and consequences in a numbered, immutable record.
- a technology or vendor choice
- a change that is hard to reverse
- a decision made in chat that nobody wrote down
Claude · Codex · ChatGPT