Skip to content

[codex] Add actor attribution to audit logs#2462

Merged
riderx merged 17 commits into
mainfrom
codex/audit-log-actor-attribution
Jul 10, 2026
Merged

[codex] Add actor attribution to audit logs#2462
riderx merged 17 commits into
mainfrom
codex/audit-log-actor-attribution

Conversation

@riderx

@riderx riderx commented Jun 8, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Added audit log actor snapshot fields for user, API key, and automated/system actions.
  • Removed audit log foreign keys to users and orgs so retained audit rows survive deleted resources.
  • Updated the audit log trigger, webhook payloads, API schema, generated types, UI display, and tests.

Motivation (AI generated)

Audit logs previously only stored a user id, which made it hard to distinguish direct user actions from API key actions or automated backend actions. The old foreign keys could also erase or mutate attribution when dependent resources were deleted.

Business Impact (AI generated)

This improves incident investigation and customer support by making audit trails clearer and more durable. Teams can identify whether an action came from a user, an API key id/name, or automation without exposing API key secrets.

Test Plan (AI generated)

  • bun lint
  • bun typecheck
  • bun run supabase:with-env -- bunx vitest run tests/audit-logs.test.ts
  • bun run supabase:with-env -- bunx vitest run tests/audit-logs.test.ts tests/webhook-delivery-security.unit.test.ts tests/webhook-delivery-redirect.unit.test.ts tests/webhook-queue-processing.test.ts
  • bun run supabase:with-env -- bunx vitest run tests/organization-api.test.ts
  • bun run supabase:with-env -- bunx vitest run tests/chart-refresh-rpc.test.ts
  • bun run supabase:with-env -- bunx vitest run tests/webhook-signature.test.ts
  • bun run supabase:with-env -- bunx vitest run tests/bundle.test.ts
  • bun test:all was run twice locally; each run had one unrelated parallel-suite failure, and each failed file passed when rerun alone.

Generated with AI

Summary by CodeRabbit

  • New Features

    • Audit logs now identify the source of each action, including users, API keys, and automated system activity.
    • Audit log details display relevant user email, user ID, API key ID, and API key name information.
    • Webhook audit events now include actor attribution metadata.
  • Bug Fixes

    • Audit records retain actor identity snapshots even when related users or organizations are deleted.
    • Deleted organization IDs are prevented from being reused.

Note

High Risk
Touches audit triggers, org lifecycle, webhook dispatch, and account deletion—security-sensitive paths with broad behavioral changes; migration alters constraints and production audit semantics.

Overview
Audit logs now record who performed an action via snapshot fields (actor_type, user email/id, API key id/name) instead of relying only on user_id. The audit log UI replaces the email column with an Actor column and expands the details modal with source, API key, and user email.

A large migration drops audit_logs foreign keys to users and orgs so retained rows keep attribution after deletes, adds org_id_tombstones and triggers to block org UUID reuse, and rewrites audit_log_trigger to classify JWT users vs write-capable API keys vs system, suppress noisy stats/counter updates, and skip orphaned webhooks during org deletion. Webhook payloads and the organization audit API expose the new actor fields; generated Supabase types are updated.

Tests and CI: integration tests assert actor attribution and tombstone behavior; test:cli and Vitest hook timeouts are raised for CI stability; workflow checkout uses full history for path filters on long-lived branches.

Reviewed by Cursor Bugbot for commit d968f8b. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c760c8a1-9058-4b91-9277-b3aeb673b3f7

📥 Commits

Reviewing files that changed from the base of the PR and between f3ab6ea and d968f8b.

📒 Files selected for processing (1)
  • .github/workflows/tests.yml
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

📝 Walkthrough

Walkthrough

Adds actor attribution fields across audit-log types, parsing, webhooks, tests, and frontend display. It also adds organization tombstone type coverage, seed reset handling, audit snapshot assertions, localized actor labels, and a workflow checkout-depth update.

Changes

Audit Log Actor Attribution

Layer / File(s) Summary
Schema and integration contracts
src/types/supabase.types.ts, supabase/functions/_backend/utils/supabase.types.ts, supabase/functions/_backend/public/organization/audit.ts, supabase/functions/_backend/utils/webhook.ts
Audit-log types, parsing schemas, webhook interfaces, and payload construction now carry actor type, user, and API key metadata; organization tombstone table types are added.
Tombstone lifecycle and audit retention
supabase/seed.sql, supabase/tests/29_test_delete_accounts_marked_for_deletion.sql, supabase/tests/40_test_audit_log_apikey.sql
Seed resets clear tombstones, while SQL tests verify actor snapshots, tombstone creation, audit retention, organization ID reuse prevention, and function privileges.
Frontend actor display and localization
src/components/tables/AuditLogTable.vue, messages/en.json
The audit table and details modal display localized user, API key, system, and unknown actor information, resolving members from actor user IDs when available.
Application audit attribution tests
tests/audit-logs.test.ts
Application tests validate actor schemas, system and API key attribution, user email loading, and audit-log snapshot behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: RobinWitch, WcaleNieWolny, Dalanir

Sequence Diagram(s)

sequenceDiagram
  participant AuditLog as Audit log
  participant Webhook as buildWebhookPayload
  participant Table as AuditLogTable.vue
  participant Modal as Details modal

  AuditLog->>Webhook: Provide actor metadata
  Webhook->>Webhook: Build actor-attributed payload
  AuditLog->>Table: Provide actor fields
  Table->>Table: Resolve and format actor
  Table->>Modal: Render source details
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding actor attribution to audit logs.
Description check ✅ Passed The description covers Summary and Test Plan well, and the missing Screenshots/Checklist sections are acceptable for this backend-focused change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@codspeed-hq

codspeed-hq Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will improve performance by 61.92%

⚡ 1 improved benchmark
✅ 42 untouched benchmarks
⏩ 2 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
/updates manifest response with metadata 141.6 µs 87.4 µs +61.92%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing codex/audit-log-actor-attribution (d968f8b) with main (0ff1119)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@riderx riderx marked this pull request as ready for review June 8, 2026 17:04
@riderx

riderx commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c26343e090

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/migrations/20260710192458_audit_log_actor_attribution.sql

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 478246fcda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/migrations/20260710192458_audit_log_actor_attribution.sql

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f2effed3d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/migrations/20260710182708_audit_log_actor_attribution.sql Outdated
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/tables/AuditLogTable.vue`:
- Around line 253-255: The getActorUserEmail helper currently returns
actor_user_email or user?.email unconditionally; change
getActorUserEmail(ExtendedAuditLog) so it only returns those values when the
audit item represents a user actor (e.g., item.actor_type === 'user'), otherwise
return null; likewise update places that fallback to actor_user_id / user_id
(calls/usages of getActorUserEmail and any inline fallbacks) to only use those
user-specific fields when actor_type === 'user' to prevent showing user
emails/IDs for non-user actors (API key/system).

In `@supabase/migrations/20260608160711_audit_log_actor_attribution.sql`:
- Around line 358-500: The SECURITY DEFINER function
public.delete_accounts_marked_for_deletion() is currently executable by any
role; revoke public execute and explicitly grant EXECUTE only to trusted
roles/groups (e.g., your admin role(s)) to prevent privilege escalation. Add
statements after the function definition that REVOKE EXECUTE ON FUNCTION
public.delete_accounts_marked_for_deletion() FROM PUBLIC; and then GRANT EXECUTE
ON FUNCTION public.delete_accounts_marked_for_deletion() TO <trusted_role1>[,
<trusted_role2>] (replace with your actual admin/trusted role names), ensuring
the function remains owned by postgres.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 68f48908-b20b-4600-ad4e-1b872de3c325

📥 Commits

Reviewing files that changed from the base of the PR and between 1d9a54c and 8f2effe.

📒 Files selected for processing (11)
  • messages/en.json
  • src/components/tables/AuditLogTable.vue
  • src/types/supabase.types.ts
  • supabase/functions/_backend/public/organization/audit.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/functions/_backend/utils/webhook.ts
  • supabase/migrations/20260608160711_audit_log_actor_attribution.sql
  • supabase/seed.sql
  • supabase/tests/29_test_delete_accounts_marked_for_deletion.sql
  • supabase/tests/40_test_audit_log_apikey.sql
  • tests/audit-logs.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread src/components/tables/AuditLogTable.vue
Comment thread supabase/migrations/20260710192458_audit_log_actor_attribution.sql

@RobinWitch RobinWitch left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

audit_log_trigger() now resolves the actor by looking at get_apikey_header() before checking auth.uid(). That changes live JWT requests whenever the client also sends capgkey: the existing 31_test_get_apikey_header.sql case documents that get_apikey_header() returns the capgkey even when Authorization: Bearer ... is present, so lines 215-228 classify the mutation as actor_type = 'apikey' and skip the user branch at lines 231-236.

That means a normal Supabase/PostgREST write that succeeds under the JWT/RLS identity on orgs, apps, channels, app_versions, or org_users can be audited as if it was performed by whichever unexpired API key happened to be in the headers. In particular, a read-only or otherwise unrelated key can appear to have performed the write even though authorization came from the JWT user. The old get_identity('{read,upload,write,all}') path returned auth.uid() first, so actor attribution should preserve that precedence or otherwise only treat the key as the actor when it is the credential that authorized the operation.

@riderx

riderx commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

Addressed the outstanding review feedback in 6eefb7b: legacy actor rows are now marked unknown, authenticated users take precedence over a co-present API key, actor emails are limited to user actors, and the account-deletion function is service-role-only with a privilege regression test.

Comment thread supabase/migrations/20260710192458_audit_log_actor_attribution.sql
@cursor cursor Bot requested review from RobinWitch and WcaleNieWolny July 10, 2026 16:24

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: medium. Cursor Bugbot skipped on this sync and left one unresolved medium-severity finding (org delete webhooks). Human review is needed before merge; assigned WcaleNieWolny and RobinWitch.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: high. Not approving: Cursor Bugbot skipped on this sync and reported one unresolved issue (org delete webhooks), and this migration/auth/audit change exceeds the low-risk approval threshold. RobinWitch and WcaleNieWolny are already assigned for human review.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@riderx

riderx commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

Addressed the org-delete webhook finding in f3ab6ea. The audit row is retained, but the trigger now intentionally skips enqueueing the undeliverable org DELETE event because that transaction has already cascaded the organization webhooks away.

cursor[bot]
cursor Bot approved these changes Jul 10, 2026
@riderx

riderx commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

Fixed the Cloudflare shard failure in babadfe: the stale-org retry fixture now makes its unique (name, created_by) key dynamic as well as its UUID and email. Local typecheck passes; restarting the full CI/review loop.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: high. Not approving: Cursor Bugbot skipped on this sync (usage limit reached), so the latest commit lacks a clean automated review, and this migration/auth/audit change exceeds the low-risk approval threshold. RobinWitch and WcaleNieWolny are already assigned for human review.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: medium. Not approving: Cursor Bugbot skipped on this sync (usage limit reached), so the latest commit lacks a clean automated review. RobinWitch and WcaleNieWolny are already assigned for human review.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@riderx riderx force-pushed the codex/audit-log-actor-attribution branch from babadfe to d968f8b Compare July 10, 2026 20:01
@cursor

cursor Bot commented Jul 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_3535ca7f-5aba-4eab-9883-d1541568a6e7)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: high. Not approving: Cursor Bugbot skipped on this sync (usage limit reached), so the latest commit lacks a clean automated review, and this migration/auth/audit change exceeds the low-risk approval threshold. RobinWitch and WcaleNieWolny are already assigned for human review.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: medium. Not approving: Cursor Bugbot skipped on this sync (usage limit reached), so the latest commit lacks a clean automated review. RobinWitch and WcaleNieWolny are already assigned for human review.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@sonarqubecloud

Copy link
Copy Markdown

@riderx

riderx commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

@codspeedbot explain the regression on /updates manifest response with metadata

@codspeed-hq

codspeed-hq Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

@codspeedbot explain the regression on /updates manifest response with metadata

Looked into the CodSpeed data for /updates manifest response with metadata on this PR. Short version: CodSpeed did not flag a regression here — it's environment noise, not a code change.

What the data shows

Comparing the PR head (d968f8b) against its rebase base on main (5ebf11b):

  • All 43 benchmarks are reported as ✅ Unchanged (2 skipped). Overall impact is ≈ -0.26%, i.e. within noise.
  • For /updates manifest response with metadata specifically, the CPU-cycle estimate moved from ~141.3 µs → ~147.6 µs (about +4%), but it did not cross CodSpeed's significance threshold, so it stays "Unchanged".

Why the small shift appears

The base and head runs executed on different CI hardware:

  • CPU: AMD EPYC 7763Intel Xeon Platinum 8370C
  • Vendor: AuthenticAMD → GenuineIntel (different cache/AVX-512 flags)

This benchmark runs in Simulation mode, which estimates CPU cycles against a simulated cache model derived from the physical CPU. When the underlying CPU/toolchain changes, the estimate can drift on identical source code. The drift here is concentrated in the instruction-execution component (~54.3 µs → ~58.0 µs), which is exactly the pattern you'd expect from a runner change rather than a real code difference. More on this: https://codspeed.io/docs/instruments/cpu/regression-causes#ci-runner-variability

Is this PR responsible?

Very unlikely. This PR changes audit-log actor attribution (SQL triggers/migration, webhook payload fields, Supabase types, and the audit-log UI). None of that is on the /updates manifest response-shaping path exercised by this benchmark, and no code change explains a systematic slowdown there.

Bottom line: no action needed for this benchmark — the difference is attributable to the base/head runs landing on different CPUs, and CodSpeed correctly classifies it as unchanged. If you'd like a clean apples-to-apples confirmation, re-running the base and head on the same runner type would remove the environment difference entirely.

Summary
  • Warming up the performance wizard...
  • Handling comment — Comment handling finished successfully

Was this response helpful? React with 👍 or 👎 to help us improve CodSpeedBot.

@riderx riderx merged commit a5c6518 into main Jul 10, 2026
72 of 90 checks passed
@riderx riderx deleted the codex/audit-log-actor-attribution branch July 10, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants