Skip to content

fix(audit): stop logging read endpoints as mutations + name task-item events - #3508

Merged
Marfuen merged 4 commits into
mainfrom
mariano/fix-audit-read-post-noise
Jul 27, 2026
Merged

fix(audit): stop logging read endpoints as mutations + name task-item events#3508
Marfuen merged 4 commits into
mainfrom
mariano/fix-audit-read-post-noise

Conversation

@Marfuen

@Marfuen Marfuen commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Why

The org activity feed was full of misleading audit entries. Two causes, both fixed here.

1. Read endpoints logged as "Created X"

The global AuditLogInterceptor decides "is this a mutation?" from the HTTP method and derives the verb from it (POST → "Created") — ignoring the declared permission. Read endpoints that use POST to carry a filter body (e.g. POST /v1/trust-portal/{documents,compliance-resources}/list, POST /v1/integrations/sync/{provider}/status) are correctly gated with @RequirePermission(..., 'read'), but every call was logged as "Created trust" / "Created integration" — on every page load. (~370 bogus "trust" + ~1,000 bogus "integration" rows and counting.)

Fix: skip audit logging when the endpoint's declared permission action is read-only (['read']). A required permission of only read is definitionally not a mutation, regardless of HTTP verb. @AuditRead still opts a read endpoint back in.

2. "created this task" reads ambiguously in the global feed

Task-item events were logged as "created this task" / "deleted this task" — wording written for a single task's own activity timeline, where "this task" has a referent. In the org-wide feed it's ambiguous and inconsistent with every other entry.

Fix: name the task — Created task "<title>" / Deleted task "<title>" — in the task-item audit service and the vendor risk-assessment flow that emits the same events. (The task title was already in the log's data; it just wasn't in the description.)

Tests

  • audit-log.interceptor.spec — new case: a POST with a read-only permission is not logged (42/42).
  • task-item-audit.service.spec — new: create/delete descriptions include the task title, incl. the (via API key) variant (3/3).
  • Typecheck clean on all changed files.

Not in scope (filed separately)

  • Onboarding auto-assigns vendors to the oldest admin/owner in an un-audited background job (the "vendors assigned to someone who didn't do it" issue).
  • Member/sync audit-logging redesign (the sync is nearly invisible; per-member churn from the people endpoints is what floods the feed).

🤖 Generated with Claude Code


Summary by cubic

Stop logging read-only POST endpoints as mutations and add task titles to task-item audit entries to reduce noise and clarify the org activity feed.

  • Bug Fixes
    • Audit: Skip logging only when all declared permissions are read (regardless of HTTP verb); endpoints with mixed actions (e.g., ['read','create']) still log; @AuditRead can opt a read endpoint back in.
    • Task items: Use Created task "<title>" and Deleted task "<title>" (incl. via API key) across the audit service and vendor risk-assessment flow.

Written for commit 353b1d4. Summary will update on new commits.

Review in cubic

… events

Two audit-trail hygiene fixes:

- The global AuditLogInterceptor derived the verb purely from the HTTP method,
  so read endpoints that use POST to carry a body (e.g. `POST .../list`,
  `POST .../status`) were logged as "Created X" on every page load — spamming
  the trail with false "Created trust"/"Created integration" entries. Skip
  logging when the endpoint's declared permission is read-only (`['read']`);
  `@AuditRead` still opts a read endpoint back in.

- Task-item audit descriptions said "created this task" / "deleted this task" —
  wording written for a single task's own timeline that reads ambiguously in the
  org-wide feed. Name the task instead: `Created task "<title>"` /
  `Deleted task "<title>"`, across the audit service and the vendor
  risk-assessment flow that emits the same events.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jul 27, 2026 4:26pm
comp-framework-editor Ready Ready Preview, Comment Jul 27, 2026 4:26pm
portal Ready Ready Preview, Comment Jul 27, 2026 4:26pm

Request Review

@linear

linear Bot commented Jul 27, 2026

Copy link
Copy Markdown

ENG-260

ENG-259

@cubic-dev-ai cubic-dev-ai 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.

1 issue found and verified against the latest diff

Confidence score: 3/5

  • In apps/api/src/audit/audit-log.interceptor.ts, POST routes with mixed RBAC requirements can incorrectly skip mutation auditing when the first permission is read, which risks missing create/update/delete audit records and weakens traceability/compliance—change the skip logic to bypass logging only when all declared permissions are read-only.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/api/src/audit/audit-log.interceptor.ts">

<violation number="1" location="apps/api/src/audit/audit-log.interceptor.ts:85">
P2: POST endpoints with multiple RBAC requirements can lose their mutation audit entry when the first requirement is read-only. Skip only when every declared permission is exclusively `read`; otherwise a later create/update/delete requirement still represents a mutation.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/api/src/audit/audit-log.interceptor.ts Outdated
Addresses cubic review: the read-only skip checked only the first
@RequirePermission, so a POST declaring multiple requirements (e.g.
[read, create]) would drop its mutation audit entry. Skip only when every
declared permission is exclusively `read`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Marfuen
Marfuen merged commit 3f9e1cf into main Jul 27, 2026
8 of 10 checks passed
@Marfuen
Marfuen deleted the mariano/fix-audit-read-post-noise branch July 27, 2026 16:25
claudfuen pushed a commit that referenced this pull request Jul 27, 2026
# [3.110.0](v3.109.0...v3.110.0) (2026-07-27)

### Bug Fixes

* **app:** make invite modal manual rows scrollable so action buttons stay visible ([#3510](#3510)) ([9926408](9926408))
* **audit:** stop logging read endpoints as mutations + name task-item events ([#3508](#3508)) ([3f9e1cf](3f9e1cf))
* **audit:** stop plaintext secrets leaking into the audit log ([#3512](#3512)) ([55a48fb](55a48fb))

### Features

* **api:** email org owners/admins when a portal access request is submitted (CS-522) ([#3494](#3494)) ([258ce45](258ce45))
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.110.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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