• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Unleash / unleash / 34333860587
87%
master: 91%

Build:
Build:
LAST BUILD BRANCH: main
DEFAULT BRANCH: master
Ran 09 Sep 2026 09:22AM UTC
Jobs 1
Files 1219
Run time 3min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

09 Sep 2026 09:16AM UTC coverage: 87.356% (-0.03%) from 87.385%
34333860587

push

github

web-flow
feat(audit): adds user-agent to audit events for user-initiated events only - EG-4693

Closes [EG-4693](https://linear.app/unleash/issue/EG-4693)

## Issue

Customer's CSOC needs `user-agent` on the audit logs we replicate to S3
(Samely it's done for login/logout events). Access logs already carry
it, audit-events didn't.


### What we did

In this PR we add `user-agent` to audit events, but only for
user-initiated ones. This is behind a `"auditEventUserAgent"` flag (off
by default).

By tech decision, we track only reqs that create audit-events not all of
them.

Rest of scheduled change requests, automated actions, bg jobs, anything
under the system-audit-user do NOT get the 'user-agent' info. As there's
no HTTP req behind those, there's nothing to record => these rows store
`null` intentionally, so we can tell "NO user agent" from "empty user
agent".

### How it works

`extractAuditInfo(req)` builds the audit-context for a req, and it's the
only place a user-agent can get in. So that's where we read the header,
check the flag and clean the value:

```ts
userAgent: captureUserAgent ? sanitizeUserAgent(extractUserAgent(req)) : undefined
```

### Where it shows up

- new db column `user_agent` on `events` (nullable)
- the S3 audit export, as `userAgent`
- **not** the event search API or the UI 
- `auditEventFields(auditUser)` - 15 events were hand-writing
`createdBy` / `createdByUserId` / `ip` as object literals. One helper
now, so the next audit column is a one-line change instead of a 15-file
sweep.
- import-toggles was rebuilding its audit context with
`extractAuditInfoFromUser`, which throws the request away. It passes
`auditUser` straight through now.

### Tests

- unit: sanitizing, flag on/off, and a check of every entry point that
is *not* user-initiated
- e2e via real HTTP stack: one req that produces both a user-attributed
and a system-attributed event, proving only the first gets a
'user-agent' field

How we tested it:

- Run the app with the... (continued)

3961 of 5167 branches covered (76.66%)

20 of 20 new or added lines in 6 files covered. (100.0%)

7 existing lines in 1 file now uncovered.

16188 of 18531 relevant lines covered (87.36%)

854.87 hits per line

Coverage Regressions

Lines Coverage ∆ File
7
77.12
-5.93% src/lib/features/playground/feature-evaluator/constraint.ts
Jobs
ID Job ID Ran Files Coverage
1 34333860587.1 09 Sep 2026 09:22AM UTC 1219
87.36
GitHub Action Run
Source Files on build 34333860587
  • Tree
  • List 1219
  • Changed 13
  • Source Changed 12
  • Coverage Changed 12
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #34333860587
  • 623785b7 on github
  • Prev Build on main (#34333804628)
  • Next Build on main (#34337989841)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc