Ctrl K
ComunidadGuías…

CHANGELOG.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Changes

## 2.6.3 (6 November 2026)

### Security

Replace the C Brotli decoder with Rust-based `brotli-rs` to reduce security risks. See #566.
Brotli decoding can now be disabled with `FEATURE_BROTLI=False` (`FEATURE_BROTLI=false` in Docker). See #568.

### Installation messages

Superusers can now receive and dismiss messages from Bugsink, such as upgrade notices, through the existing
phonehome connection. See #177.

### Smaller fixes

* Speed up minidump processing by unwinding stacks only once, using `symalot`. See #576.
* Keep debug files and source bundles that are still being used for minidumps from expiring. See #571.
* Report source-map upload status and assembly failures to `sentry-cli`. See #563.
* Allow upload chunks to use object storage instead of the database. See #575.
* Reduce file cleanup batches to shorten database write transactions. See #574.
* Reject incomplete gzip and deflate request bodies. See #567.

## 2.6.2 (22 October 2026)

### Security

#### Artifact assembly loads chunks before checking their combined size

Fix: reject oversized artifact uploads before loading their chunks into memory.

An API token with `debug-files:upload` access could previously cause excessive memory use during source-map uploads.
The assembled-file size check ran after loading the chunks. This fix also applies when experimental minidump support is
disabled.

See [the security advisory](https://github.com/bugsink/bugsink/security/advisories/GHSA-f8c4-h8vr-rh5v).

#### Artifact bundle ZIP parsing can exhaust memory

Fix: limit decompressed artifact-bundle manifests to 50 MiB (or `MAX_FILE_SIZE`, if lower).

Manifests previously used the much larger general file-size limit, allowing an authorized uploader to cause excessive
memory use with a highly compressed manifest.

Artifact-bundle ZIP entries must now use Stored or DEFLATE compression. Rejecting BZIP2 and LZMA avoids decompressor
memory-exhaustion bugs on affected Python versions, even when Bugsink limits how many decompressed bytes it reads.

See [the security advisory](https://github.com/bugsink/bugsink/security/advisories/GHSA-mcpx-frgv-p228).

#### Docker certificate trust stores affected by the eMudhra CA incident

Fix: update certificate trust stores following the eMudhra/emSign CA incident.

Bugsink now requires `certifi>=2026.10.19`. Docker builds also install pip 26.2.2 from a hash-verified wheel before
downloading packages and refresh the system CA bundle. Recreate running containers from the updated image to apply
these changes. See #559 and the [Python Packaging incident guidance](https://discuss.python.org/t/109576).

See [the security advisory](https://github.com/bugsink/bugsink/security/advisories/GHSA-2r4m-8qhq-j364).

### Backwards incompatible changes

Python 3.10 is no longer supported. Bugsink now requires Python 3.11 or newer. Docker users do not need to change their
host's Python installation. See #199.

### Canonical API

* Search issues and events using the same query syntax as the UI, and filter issues by state. See #558.
* List issues across accessible projects in one request, and look up an event by its SDK event ID and project. See #558.
* Retrieve issue history, including state changes, comments and author names, with cursor pagination. See #554.
* Retrieve an issue's tag counts and grouping keys, and hourly event counts for issues and projects. See #558.
* Include release information and mute conditions in issue responses and custom webhook payloads. See #558.
* Document search syntax and friendly issue IDs in the API schema. See #558.

### Experimental minidumps

Minidump support remains experimental and requires `FEATURE_MINIDUMPS`.
It got the following improvements in this release:

* Apply `MAX_ATTACHMENT_SIZE` to direct minidump uploads, whether compressed or uncompressed, and reject oversized
  requests with HTTP 413. The limit covers the whole decompressed multipart request, including fields and overhead.
  `MAX_ATTACHMENT_SIZE` is now also configurable through the Docker environment.
* Check installation and project quotas before accepting direct minidump uploads.
* Limit decompressed source-context files to 10 MiB by default, configurable with `MAX_SOURCE_CONTEXT_FILE_SIZE`.
  Omit source context when a file exceeds the limit. See #555.
* Avoid unnecessary source-bundle manifest parsing by Symbolic, and only read Stored or DEFLATE ZIP entries when
  extracting source context.
* Parse minidumps before entering the database write transaction. Reuse debug files across matching stack frames and
  release their contents after use, reducing repeated reads, parsing and memory use.
* Assemble debug files in background tasks, with upload status available to `sentry-cli` while it polls for completion.
* Fix direct minidump ingestion and avoid processing minidump-only envelopes twice. See #532.

### Smaller fixes

* Support source context in sectioned source maps, and match source-map debug images using a frame's `abs_path` before
  falling back to `filename`. This fixes matching for Cloudflare Workers events. See #550 and #553.
* Keep uploaded chunks available for other files that share them, instead of deleting them after the first assembly.
  Chunks are removed by age-based cleanup. See #546.
* Shed already-queued, over-quota events before entering the database write transaction, and move event schema
  validation outside that transaction. See #494 and #557.
* Handle multipart uploads with Chunked Transfer-Encoding under Gunicorn, rather than treating their files as absent.
* Enforce the 1,000,000-byte body-size limit for uncompressed multipart requests when `API_LOG_UNIMPLEMENTED_CALLS` is
  enabled. Oversized requests now receive HTTP 413. This debug logging option is disabled by default.
* Make tag values clickable filters that narrow the current search, and add clear buttons to search fields. See #527
  and #538.
* Show whether events are arriving on SDK setup pages. See #531.
* Add copy buttons next to auth tokens. See #525.
* Ask for confirmation before leaving a team, and prevent its last accepted admin from leaving. See #534.
* Refuse email delivery to `@bugsink.com` recipients, avoiding accidental notifications to the Bugsink maintainers.
  See #536.
* Reject conflicting reuse of event IDs without raising an unhandled exception, and tolerate malformed stacktrace
  frame containers. See #537 and #533.
* Keep Tailwind's development watcher output consistent with production builds and update development-only npm
  dependencies. See #539, #541, #547 and #556.

## 2.6.1 (25 September 2026)

### Smaller fixes

* Fix Snappea memory growth after source-map uploads by counting database queries without retaining their contents, and
  avoid loading duplicate uploaded files into memory. See #523.
* Allow project-bound API tokens with `projects:read` to list and retrieve their bound project. See #520.
* Fix server errors on the canonical API root and on `OPTIONS` requests made with valid API tokens. See #516.

## 2.6.0 (15 September 2026)

### Scoped API tokens

Users can now create personal API tokens that follow their current permissions, optionally limited to one project.
Each token has an explicit set of capabilities, such as reading issues, triaging them or uploading debug files.
Superusers can also create service tokens for integrations that should operate independently of a user account.
These limits are enforced in both the canonical and Sentry-compatible APIs, and endpoint requirements are included
in the OpenAPI documentation. See #216.

Existing tokens keep their full installation-wide access after upgrading. Tokens can be revoked from the token list.

### Request-URL search

Issue and event searches can now filter by request URL, for example `url:"https://example.org/checkout"`. URLs are stored
as tags for newly ingested events, with query strings and fragments removed so equivalent pages share a value.
See #269.

### Alert destinations

Alerts can now be sent to Google Chat spaces using incoming webhooks. See #326.

### Smaller fixes

* Show newest events first in an issue's event list, including filtered results, see #485.
* Show friendly issue IDs in project issue lists, see #509.
* Apply Docker SMTP environment settings when `EMAIL_BACKEND` is explicitly configured, and allow `EMAIL_LOGGING`
  independently of SMTP configuration. Selecting SMTP without `EMAIL_HOST` now uses localhost with port 587 and TLS
  by default. See #502.
* Tell SDKs to stop sending unsupported transaction and span data, reducing unnecessary ingestion traffic, see #500.
* Parse quoted search terms consistently, including colons in values and escaped quotes, see #501.
* Prevent project updates through the canonical API from moving a project to another team, see #216.
* Update Gunicorn to 26.2, Django REST Framework to 3.18 and Pygments to 2.21, see #498, #486 and #489.

## 2.5.1 (31 August 2026)

### Backwards incompatible changes

Some _very ancient_ migration files, long since squashed and replaced, have been removed. In the unlikely event that
you are running a pre-1.2.0 release and have not yet run migrations, you will need to upgrade to any release from 1.2.0
to 2.5.0 and run migrations before upgrading to 2.5.1 or later. See #470.

### Security

Fix: enforce the configured lifetime for email verification, password-reset and new-user setup links.

The lifetime setting is expressed in seconds but was interpreted as days, so unused links remained valid far beyond
their configured expiry. Bugsink now expires them after the configured number of seconds. See:

https://github.com/bugsink/bugsink/security/advisories/GHSA-4f45-qmjf-82cv

Fix: reject webhook targets with non-global IPv4 addresses embedded in IPv6 destinations.

On installations with NAT64 routing, a project admin could use a globally classified IPv6 address that translated to
a private, loopback or link-local IPv4 destination. Bugsink now applies the global-address requirement to IPv4
addresses embedded in standard IPv6 transition formats. See:

https://github.com/bugsink/bugsink/security/advisories/GHSA-qxqr-25p3-664q

### Alert destinations

Alerts can now be sent to Telegram, Microsoft Teams and custom webhook endpoints. Telegram supports channels, groups
and topics, Microsoft Teams uses Power Automate Workflows, and custom webhooks receive a payload based on the canonical
issue API. See #368, #433 and #461.

### Stacktraces and log messages

Log-message issues now use the actual message as their title instead of the generic "Log Message" label, including the
formatted message when an SDK provides one. See #111 and #364.

Stacktrace views now render thread-based stacktraces from message and log events, show multiple threads alongside
exceptions, and support the deprecated top-level event stacktrace. See #471 and #482.

### Smaller fixes

* Accept events that do not specify a platform, see #474.
* Remove the broken, Python-specific plain-text event view; the Markdown view remains available, see #473.
* Only accepted team members can join team projects, and send issue alerts only to accepted, active members, see #481.
* Hide raw exception details from production error responses when `MINIMIZE_INFORMATION_EXPOSURE` is enabled, see
  #481.
* Parse `USE_ADMIN` as a boolean in Docker settings, so values such as `False` no longer enable it, see #481.
* Clean up minidump files from minidump-only envelopes, see 5b09ae57.
* Correct the artifact-upload authentication error message to name the expected Bearer scheme, see #488.
* Update `fastjsonschema` to 2.22, see #476.
* Simplify development by keeping events in the database instead of an event filestore, see 14f24309.
* Update development-only Tailwind dependencies and keep pre-commit builds in sync with the lockfile, see 03e33bec and
  f50c0dd8.

## 2.5.0 (21 July 2026)

### Improved issue grouping

New projects now use a grouping mechanism that ignores variable values such as IDs and IP addresses in exception and
log messages. This keeps repeated occurrences together more reliably. Grouping mechanisms are now versioned: existing
projects stay on the previous mechanism until a project-admin opts in, with a 30-day transition period to avoid
splitting existing issues. See #255, #440, #441, #448 and #451.

If you wish to convert an existing project to the new grouping mechanism, you can do so from the project settings page.

### Issues across projects

The new global issue list lets users triage issues across all projects they can access, including the usual state
filters and bulk actions. Project and global issue lists can also be sorted by lifetime event count, making the
highest-impact issues easy to find. The canonical API supports the same event-count ordering. See #190, #260, #457 and
#469.

### Self-hosted administration

Installations without email delivery can now show invite links for manual sharing. Admins can generate set-password
links from the command line, users can change their own passwords, and DSNs have copy buttons. Docker deployments can
also configure `EMAIL_BACKEND` directly, including Django's dummy backend to disable email deliberately. See #78, #247,
#333, #365, #453 and #456.

### Smaller fixes

* Add Go SDK setup instructions, see #450.
* Show "many issues" instead of looking empty when an exact project issue count would be too expensive, see #455.
* Clarify ingest-directory vacuum output and clean up stale minidump ingest files, see #454.
* Fix Snappea statistics with Django 5.2's UTC handling, link issue tag summaries to filtered events, and shorten long
  "seen in releases" lists, see #459.
* Show column numbers in stacktraces, see #414 and #466.
* Add cleanup of issues whose stored events have all been removed, see #138 and #468.
* Use consistent page headings across project, team and settings pages, see #467.
* Update development-only Tailwind dependencies, see c0c8e752.
* Email delivery now has a configurable hourly limit, defaulting to 60, so repeated alerts cannot quietly monopolize task
  workers. Recent email failures are surfaced as a system warning. See #458.
* Users with unaccepted invitations no longer have project, issue or event access. See #437
* Auth tokens are masked in the list view until explicitly revealed. See #457 and #460.
* Project names now only need to be unique within a team, so different teams can use natural names such as "Backend" or
  "API" independently. See #464.

## 2.4.0 (10 July 2026)

### Backwards incompatible changes

Fail to start when `PID_FILE` is configured to be in a directory not owned by the process running gunicorn/snappea
(typically: the `bugsink` user). The reason for this is: extra defense in depth, as per #174.

Ensure that `PID_FILE` is either `None` (recommended in systemd setups, i.e. recommended in the recommended case) or, if
you must, in file in a directory "one level deep" (e.g. `/tmp/snappea/snappea.pid` or `{base_path}/snappea/snappea.pid`)

Otherwise you'll get a B108SecurityError ("Target path owned by uid other than me: ...")

See #195, #196

### Security

Fix: prevent DNS rebinding bypasses in outbound webhook protection.

A project admin who controlled webhook DNS responses could make the policy check see an allowed public IP while the
actual HTTP request connected to a blocked internal destination. Bugsink now pins each webhook send to the validated DNS
result while preserving normal Host/SNI behavior. See:

https://github.com/bugsink/bugsink/security/advisories/GHSA-w589-2ffr-2prv

### Sparklines / Trends

Project and issue lists now show compact 24h event-volume trends. Sparkline bucket boundaries respect the installation
timezone, and y-axis labels now use nicer count-oriented steps with a floor of 10 for low-volume charts. See #444,
#445 and #447.

### Issue resolution

Resolved issues can be reopened manually. The Resolve controls also support a plain "Resolve" flow and resolve-by-current
release when observations already exist. See #431 and #436.

### Smaller fixes

* Fix AuthToken description edits applying to the wrong token, see #424.
* Use the ready endpoint in the sample Compose healthcheck, see #426.
* Reduce Docker image size, see #430.
* Improve invalid payload handling in envelope and deprecated `/store/` ingest paths, see #435.

## 2.3.1 (30 June 2026)

* Decode percent-encoded components from `DATABASE_URL` after parsing (See #423)
* Return 404 for malformed API lookups (in markdown view)

## 2.3.0 (23 June 2026)

### CSP reports

Add native support for CSP violation reports via a new `/api/<project_pk>/security/` endpoint, compatible with the
`report-uri` directive browsers emit. Reports are translated into events and pushed through the existing envelope
pipeline, grouped by `(effective-directive, blocked-uri)`, see #371.

### Sparklines

Issue event pages now show a 28-day event-volume sparkline. The sparkline is backed by hourly event-count buckets, so
regular page views do not need to rescan the event table. Bars can be clicked to jump to an event in that time bucket,
see #417 and #420.

### Smaller fixes

* Show full exception values on stacktrace pages, see #412.
* Include Bugsink's Sentry-compatible API surface in the OpenAPI schema, see #413.
* Return `{"id": ...}` from the `/envelope/` endpoint, see #396.
* Update the Docker run command in the README, see #415.

## 2.2.2 (4 June 2026)

### Security

Fix: cap the number of tags stored per event.

Events with very many tags could keep the single write transaction busy for longer than intended during digestion.
Bugsink now stores at most `MAX_EVENT_TAGS` tags per event, defaulting to 100.

https://github.com/bugsink/bugsink/security/advisories/GHSA-5x67-j5xg-c5gj

### Smaller fixes

* Show project slugs as read-only on project settings pages, see #402.

## 2.2.1 (22 May 2026)

### API

* Add issue actions to the canonical API, see #214 and #401.
* Add canonical API issue comment creation, see #352 and #401.
* Accept issue friendly IDs in the canonical API, see #389 and #401.
* Improve OpenAPI endpoint docs, see #390 and #401.
* Use Bugsink's version as the OpenAPI spec version, see #307.

### Smaller fixes

* Fix long module names overlapping version values on event detail pages, see #377 and #382.
* Validate `CREATE_SUPERUSER` email addresses and use the email as username in Docker server-start setup, see #394.
* Development server: do not send email by default, see d6d5190441b3.
* Docker: disable Gunicorn's unused control socket, see #405.
* Sourcemap uploads without a project slug now log server-side context before returning `400`, see #404 and #408.

## 2.2.0 (21 May 2026)

### Security

Fix: scope issue actions and event lookups to the authorized project/issue.

A project member who knew UUIDs from another project could use some issue-list
bulk actions and issue event views through a project or issue they were allowed
to access. These views now require the selected issues/events to belong to the
authorized parent. See:

https://github.com/bugsink/bugsink/security/advisories/GHSA-g5vc-q7qc-v939
https://github.com/bugsink/bugsink/security/advisories/GHSA-vx2f-6m6h-9frf

Fix: scope sourcemap and minidump debug-file metadata to projects.

Sourcemap and debug-file IDs are client-provided and were previously resolved
globally. That could let events in one project use uploaded debug metadata from
another project. Newly uploaded files now store project information and lookup
prefers project-scoped metadata. Already-uploaded legacy sourcemaps/debug files
keep working through a fallback. See:

https://github.com/bugsink/bugsink/security/advisories/GHSA-5389-f7vh-wxj8

### Smaller fixes

* Fix health-check `ALLOWED_HOSTS`-ignore, see #140, #397
* Generate an `event_id` on `/store/` when the SDK does not send one, see #383.
* Refresh issue title fields on every event digest, see #378.
* Include ingest-dir cleanup in the `vacuum` command and warn about stale ingest-dir files, see 772fb1a9bff6 and
  1ee34c574b7d.
* Add more verbose output to file vacuuming, see #372.
* Broaden phonehome triggers and avoid unnecessary queueing, see 2f76eacfbf68.
* Fix API catch-all logging for non-JSON bodies, see d13e5eff132b.
* Ensure `release` is a string before ingesting, see 374914c96f62.
* Fix direct minidump endpoint calls, see 5324d802cc50.

### Upgrading

Sourcemap uploads should include a meaningful project slug. Existing unscoped
sourcemaps keep working, but installations that prefer to remove that fallback
can run `delete_legacy_sourcemaps` and re-upload sourcemaps with project slugs.

## 2.1.3 (2 May 2026)

### Security

Fix: harden webhook URL validation parsing and reject non-RFC characters.

In some malformed URLs, Python’s standard URL parser (urllib) and the HTTP
client stack (requests / urllib3) do not agree on which host is actually being
targeted. That could allow a webhook URL to pass Bugsink’s outbound-host checks
while the actual HTTP request is sent somewhere else. See:

https://github.com/bugsink/bugsink/security/advisories/GHSA-fp53-qcf8-2xx2

### Smaller fixes

* Add issue-level markdown, see #334.
* Fix installation quota counting across projects, see #359.
* When vacuuming files, don't load them in memory, and allow long-running totals queries, see #363, #373 and #372.
* Refuse to send email as something@bugsink.com for self-hosters, see 3ff3a6fbeb6d.
* Fix `MultipleObjectsReturned` when user has unaccepted project memberships, see 653be6968f6e.
* Cleanup lingering files for `MAX_EVENT_SIZE` overshoots, see #370.
* Fix some `.get(context, {})` usages and an exception-path double-exception, see #369.
* Upgrade `gunicorn` requirement from `==25.1.*` to `==25.3.*`, see 2d5e0071cf66.
* Upgrade monofy, see #367.

## 2.1.2 (11 April 2026)

* Add stored file count and byte caps, see #355
* Error message readability in dark mode, see #362

## 2.1.1 (9 April 2026)

### Security

Fix: avoid using upload checksums as temporary filenames.

The recent temp-file assembly change made checksum values part of path
construction before they had been validated. An authenticated caller could
thereby reach a write-before-checksum-mismatch path during file assembly.

### Smaller fixes

* AuthToken deletion is now idempotent, so mashing the delete button no longer results in a spurious 500.
* Disable phonehome in development, see #357.
* Allow enabling `USE_ADMIN` via environment variable, see #361.
* Fix sourcemap application when `sourcesContent` contains `null`, see #360.

## 2.1.0 (4 April 2026)

* Show open issue counts on project list (skipping very large projects), see #228

* Add outbound webhook destination policy: destinations can be filtered by hostname/IP/CIDR allow/deny lists and
  non-global IPs are blocked by default. See #339 and [the docs](https://www.bugsink.com/docs/webhook-outbound-policy/).

* Add object storage for uploaded files via `OBJECT_STORAGES`, including `migrate_to_current_objectstorage` and
  `cleanup_objectstorage`, see #354.

* File uploads and artifact bundle assembly now enforce server-side limits more strictly: chunk uploads are checked
  server-side, `MAX_FILE_SIZE` applies to assembled files too, and artifact bundles no longer need to be loaded fully
  into memory during extraction, see #356.

* Add a synchronous `vacuum` command as a single entry point for cleanup tasks, and add `MAX_EVENT_AGE_DAYS` /
  `delete_old_events` for age-based event cleanup, see #350 and #48.

* Docker config: add `USE_X_FORWARDED_HOST` and `USE_X_FORWARDED_FOR`, see #336 and d3e743d.

* Sourcemaps: handle unmappable frames per-frame, so mixed mapped/unmapped stacktraces keep rendering, see #330.

* Reject events at ingest when retention is configured as zero, see #341.

## 2.0.14 (3 March 2026)

* sourcemaps upload now works for sentry-cli >= 3.0.0, See #290
* Add `chunk_max_days` and `file_max_days parameters` to `vacuum_files` command and task

* Update whitenoise requirement from ==6.11.* to ==6.12.*
* Fix `FEATURE_MINIDUMPS` env-parsing in docker template
* mobile menu: somewhat workable, See #120
* Add index on `(digested_at, digest_order)` Fix #322
* Move `mark_safe` closer to actual escaping

## 2.0.13 (21 February 20206)

### Security

Fix: escape output for pygments fallback.

An unauthenticated attacker could store arbitrary JavaScript in a bugsink
project by sending a crafted Sentry event. Any admin who views the stacktrace
will execute the payload.

### Other

* annotate with meta: when meta-keys are not actually in the var
* Reduce Slack title length from 200 to 150 characters (See #318)
* fix dbrouter `allow_migrate` for more than 2 databases
* Distinguish installation-quota warning message from the project-level ones
* fix unsupported operand type(s) for +: 'NoneType' and 'str' in request.url display
* Add a `description` field to authtoken (See #312)
* 400 template should say 'bad request' not 'server error'
* Max retention: default per-project of 20% per project to avoid out-of-room on project 2
* Allow editing of project when global `max_rention` settings have recently been decreased

## 2.0.12 (26 January 2026)

### Fixes:

* Quota checks: don't get confused (so much) by eviction, see c157827a3050
* `cleanup_eventstorage` command: don't fail when no storage initialized, see 45dc85a38288
* `EventStorage.list` must return UUIDs for usage in .delete, see c8457ed9bd45
* Don't rely on SDK-provided `event_id` for ingest-digest handover, see 6ab3fa56200e, and 9e8f59ebc1b1
* `cleanup_events` (after delete): push out of transaction, see 4130cd240205 and 7f726cad8fc9
* Add simple command to delete the oldest events until under retention max, see 941490605355
* `FileEventStorage` config forward-compatible, see 5099d697493f
* `migrate_to_current_eventstorage` command: don't crash when there are 'very many' events, see 34cf7dc868f5

### Upgrading

The optional management command `fix_project_digest_order` can be run in
addition to migrations; this will make rate-limiting quota work more
correctly immediately.

(if you don't care, this will become eventually correct as the old data
fades away).

## 2.0.11 (20 January 2026)

* Add brotli and gzip filestorages, see 5b345e0535c9
* Apply max retention from settings even if stored project value is higher, see 1f1b06b74dd0
* Max retention event count: guard the API, see d3beed517217
* Max event retention: don't mention a negative budget, see 0a39ce16f487
* New project: suggest no more than the legal retention, see 0cdb6c0afdab

## 2.0.10 (14 January 2026)

* FileStorage: basepath configurable using `get_basepath` (callable), 2561f5602a7b

## 2.0.9 (13 January 2026)

* Add event URL for the "external" (SDK-provided) ID, see #291
* Add OpenAPI link to navigation bar, see #302 / #301
* Adding info to contributing guidelines, see #303

## 2.0.8 (10 January 2026)

* Improve default Sentry SDK settings for Python, Fix #298
* Fix background of event search inputs in dark mode, see #300
* Add missing tailwindcss dependencies (for development)
* `MAX_RETENTION[_PER_PROJECT]` as a setting
* More fully disable the admin when `USE_ADMIN=False`, See #131
* quota exceeded: show a message
* Project quota: pick up on settings-changes
* Setting & check for site-wide per-month event ingestion maximum
* Add modelcounts command; useful in the context of housekeeping when servers are down
* Fix exception for unsupported envelope items / when minidump feature is off. See #293

## 2.0.7 (6 January 2026)

### New & Improved Alert backends

* Adds the Mattermost Alert Backend, see #278, #253, #277
* Adds the Discord Alert Backend, see #279, #121

### Minidump API Endpoint: _Experimental_

This release contains _code_ that supports Minidumps, and which can be turned on with the
feature-flag (setting) `FEATURE_MINIDUMPS`.

However, as it stands, this code should be seen as development-only: it has not
passed security-review yet, which means it opens your Bugsink-installation to DOS-like
attacks.

See #270, #82.

### Other changes

* Fix `never_evict` for the "conditional ummute" case, see #292
* ingest ParseError: don't raise a 500; make this the SDK's problem (400), see 4fe8bd3fad44
* Upgrade Verbose CSRF Middleware to match Django 5.2, see e3f1c92fd17f
* Fix for pygements mishandling a weird case w/ ruby, see 4564131ff532
* Raise 413 for the 'content too large' case
* Slack alerts: issue title in message title, fix #283
* Channel support for Mattermost message backend, see #281
* Discord alert backend: send 'valid' URLs only, fix #280
* yesno filter: just don't return None ever, see 9b2acddf206b
* tailwind update, see bddc2e8f640e
* Link to 'all tags' in the 'tags' RHS box, see eeac2e750c05
* 'files' is a bugsink module too; reflect in `eat_your_own_dogfood`, see 74a04f6ea1dc
* Don't log emails to 0 recepients, see #86
* Fix member counts on project/team list, they were at most 1, see a93f369ad749
* Support request.body when doing Chuncked Transfer Encoding, see #9
* Fix inefficient bytes concatenation when `KEEP_ENVELOPES` != 0, see 0432451e8e8b
* Compression decoding errors: return 400 rather than 500, see 53bea102d911
* Support Python 3.14, see #267

## 2.0.6 (8 November 2025)

### Security

Add a mitigation for another DOS attack using adverserial brotli payloads.
Similar to, but distinct from, the fix in 2.0.5.

## 2.0.5 (8 November 2025)

### Security

Add a mitigation for certain DOS attacks using adverserial brotli payloads, see #266

### Backwards incompatible changes

Fail to start when using non-sqlite for snappea, See #252

Since this was always recommended against, and probably broken anyway, this is not
expected to be backwards incompatible _in practice_, but it is at least in prinicple.


### Other changes

* Markdown stacktrace: render with all frames, See 9cb89ecf46a7
* Add database vendor, version and machine arch to phonehome message, see d8fef759cabc
* Fix redirect on single-click actions when hosting at subdomain, Fix #250
* 'poor mans's DB lock: lock the right DB; See e55c0eb417e2, and #252 for context
* Add more warnings about using non-sqlite for snappea in the conf templates, See #252
* `parse_timestamp`: _actually_ parse as UTC when timezone not provided, see 8ad7f9738085
* Add debug setting for email-sending, Fix #86
* docker-compose-sample.yaml: more clearly email:password, See #261
* create snappea database on Docker start rather than image build, See #244

## 2.0.4 (9 October 2025)

* `convert_mariadb_uuids` command to fix UUID column problems on MariaDB

If you upgrade (or have upgraded) from Bugsink < 2.0 to any 2.0.x version you
need to run this command (and you need 2.0.4 to be able to run it).

See #226

## 2.0.3 (5 October 2025)

* Simplify login template (f8be55da89dd)
* Better hints for malformed Token headers (d0e7b75dbba1)
* API: datetime objects always in UTC (afd31d226352)
* API: remove `is_deleted` as a field (0ca3e33e1f81)
* Fix null constraint failure when `remote_addr` is `None` and user is '{{auto}}' (See #229)

## 2.0.2 (22 September 2025)

* Fix broken checkbox in issue list (See #225)

## 2.0.1 (16 September 2025)

2 docker-related fixes (e346f8d5c22a and aa799e9c940f)

## 2.0.0 (16 September 2025)

### Backwards incompatible changes

* Python 3.9 is no longer supported

[Unless you're running Debian Bullseye this will not affect you](12af5302efdd).

The minimum supported version for the database backends has been raised to:

* SQLite ≥ 3.31.0
* MySQL ≥ 8.0.11
* PostgreSQL ≥ 14
* MariaDB ≥ 10.5

[Overview of typical versions in various
OSes](https://github.com/bugsink/bugsink/pull/89#issuecomment-3253843464)

#### Non-root Docker

The provided Docker container no longer runs the Bugsink process as the root
user. This improves security (defense in depth), but may require changes to
your setup (i.e. volume permissions).

Setups that mount the `/data` dir as a volume must ensure that the directory is
owned by UID 14237 (the user the process runs as inside the container).
[Further migration
instructions](https://github.com/bugsink/bugsink/issues/176#issuecomment-3139184180)

If you have not mounted any volumes, you will not be visibly affected by this change.

#### Hardening of Temporary-Directory

Bugsink now requires ownership of the `INGEST_STORE_BASE_DIR` directory to avoid
certain classes of local privilege escalation attacks. (see #174)

If you manually configured this directory to be something that the process
running Bugsink _cannot_ own (e.g. to `/tmp/` without a further subdir), you
must change it to something it can own (e.g. the default of `/tmp/bugsink/ingestion`)

The Docker image is not affected by this (manual configuration wasn't possible to
begin with).

### Various Improvements & Fixes

* When selecting text in the stacktrace frameHeader, don't toggle the frame (d62d016be3aa)
* i18n support and Chinese translation (See #192, #161)
* minor changes to `send_json` util (f0d3667121ab, c38ca8c58a4c)
* Docker: bugsink-show-version on-start (42ba5a71facc)
* Implement `vacuum_ingest_dir` management command (See #163)
* add dark-mode default for border color (833776c646f5)
* API: first version (see #211, #146)
* docker compose sample: use alpine postgres (#208)
* docker compose sample: fix major version (#207)
* Improve Slack alerts to work with Mattermost (#203)
* Fix #97: implement /api/0/ endpoint
* Move conf utils to separate module
* transaction: use connection.vendor instead of settings.DATABASES engine check (see #117)
* support hosting at subpath (#201, #93)

### Dependency updates

* Replace `python-sourcemap` with `ecma426` (see 0764024389fc)
* django 4.2 => django 5.2
* Tailwind 3 => Tailwind 4
* django-tailwind 3.6 => 4.2
* `inotify_simple` => 2.0

## 1.7.6 (1 August 2025)

* envelope-headers `sent_at` check should allow 00+00 (See #179)
* evenlope-header validation failure should not lead to envelope-rejection (See #179)

## 1.7.5 (31 July 2025)

### General Improvements

* Add failure visibility for alert backends (See #169)
* Add per-month quota for email-sending (Fix #34)
* Store `remote_addr` on the event (Fix #165)
* Use `remote_addr` for `'{{auto}}'` `ip_addr` tags (See #165)
* `PID_FILE` check: make optional (See #99)
* `PID_FILE` check: don't use in docker/systemd (Fix #99)
* Breadcrumb timestamps: display harmonized w/ rest of application (ceca12940bd5)

### Sourcemaps: better debugging

* sourcemaps: Uploaded, but ignored, files: warn (See #158)
* Sourcemaps: Warn (in the logs) on multiple-debug-ids source uploads (See #157, #158)
* Debug IDs for missing sourcemaps: show them right in the stacktrace (See #158)
* Sourcemap Images IDs: show those in event details (See #158)

### Configuration / Settings

* `SINGLE_USER` implies `SINGLE_TEAM` and more (Fix #162)
* Docker config: `BEHIND_PLAIN_HTTP_PROXY` (Fix #164)
* Development setting: keep artifact bundles (1aef4a45c2dc)

### Security Hardening

* CI pipeline security checks with Bandit (See #175)
* Envelope parsing validates headers strictly (See #173)
* Use `django.utils._os.safe_join` to construct paths (see #173)

### Internal Tooling

* Remove the Django Debug Toolbar entirely (Fix #168)
* semaphore-for-db-write-lock: sqlite only (See #117)
* `send_json` utility: make envelope API the default (13226603ec7a)

## 1.7.4, 1.6.4, 1.5.5, 1.4.3 (29 July 2025)

Security release. Upgrading is highly recommended. See [this
notice](https://github.com/bugsink/bugsink/security/advisories/GHSA-q78p-g86f-jg6q)

## 1.7.3 (17 July 2025)

Migration fix: delete TurningPoints w/ project=None (Fix #155)

## 1.7.2 (17 July 2025)

Various fixes:

* Dark mode: use monokai style from pygments (Fix #152)
* add `vacuum_files` command (Fix #129)
* Artifact Bundle upload: clean up after extract (See #129)
* Add API catch-all endpoint for logging (Fix #153)
* File-upload: chunk-size of 2MiB (Fix #147)
* Sourcemaps upload: max file size 2GiB (See #147)
* Auto-clean binlogs on docker compose (sample) for mysql (See #149)
* Remove platform 'choices' from Event.model (See 403e28adb410)
* Better `ALLOWED_HOSTS` misconfig error-message (Fix #148)
* As per the "little red box on" #120
* Fix wasted space at certain width in stacktrace UI (See #120)
* Fixed command's 'running in background' output (See 770ccb16225e)
* Project-edit: redirect to list on-save (See 2b46bfe9a114)
* `cleanup_eventstorage` command: be more clear when no `event_storage` is actually configured (See b2769d7202b6)
* Don't crash on illegal values for platform (See #143, #145)
* Support 'crystal' platform (Fix #145)
* Support 'powershell' platform (Fix #143)

## 1.7.1 (10 July 2025)

Fix: user-related forms broken by unclosed link

## 1.7.0 (9 July 2025)

Bugsink 1.7.0 introduces Dark Mode (See #40, #125)

### Housekeeping

A number of options to clean up unwanted or unneeded data have been added:

* Project Deletion (See #50, #137)
* Issue Deletion (See #50)
* Vacuum Tags command (See #135)
* `vacuum_eventless_issuetags` command (see #134, #142)

How these commands/tools relate to each other and may be used is [documented on
the website](https://www.bugsink.com/docs/housekeeping/)

### Various small fixes

* Skip `ALLOWED_HOSTS` validation for /health/ endpoints (see #140)
* `get_system_warnings` as a callable (see c2bc2e417475)
* `store_tags`: support 'very many' (~500) tags (see d62e53fdf8e7)
* Snappea: refuse to start in `TASK_ALWAYS_EAGER` mode (see aa255978b776)
* Sentry-SDK requirement, unpin minor version (see a91fdcd65673)

## 1.6.3 (27 June 2025)

* fix `make_consistent` on mysql (Fix #132)
* Tags in `event_data` can be lists; deal with that (Fix #130)

## 1.6.2 (19 June 2025)

* Too many quotes in local-vars display (Fix #119)

## 1.6.1 (11 June 2025)

Remove hard-coded slack `webhook_url` from the "test this connector" loop.

## 1.6.0 (10 June 2025)

### Slack Alerts

Bugsink 1.6.0 introduces Slack Alerts (through webhooks); see #3.

### Backwards-incompatible changes

* The default number of web processes (gunicorn server workers) in the
  dockerized setup is now equal to `min(cpu_count, 4)`; (it used to be 10).

  set `GUNICORN_CMD_ARGS="--workers=10"` to restore the previous behavior or
  choose a custom number.

### Various Features & Fixes

* Display formatted log message when available (see #111)
* Add 2 env variables to compose-sample.yaml (See #110)
* Add delete functionality for users (See #108)
* Multi-file sourcemaps (See #87)
* Lookup by `debug_id` in dicts: use UUID (See #105)
* Add robots.txt that disallows crawling
* Add HEALTHCHECK command to Dockerfiles (See #98)
* Fingerprint: convert to string before concatenating (See #102)
* Add /health/ready endpoint (See #98)

## 1.5.4 (12 May 2025)

* Add bugsink-util script to allow settings-independent commands to be run
* UX of the `stress_test` command (param cleanup)
* checks on `settings.BASE_URL`
* Show _all_ Request Headers in `CSRF_DEBUG` view (see #100)
* Fix obj not found when visiting project as a non-member superuser

## 1.5.3 (7 May 2025)

* Performance fixes of the issue-list when there are many (millions) of _issues_ (rather than just events) in the
  database; see aad0f624f904 & 0dfd01db9b38.

* Fix: `different_runtime_limit` applying to the wrong DB alias, see 699f6e587d28

* `CREATE_SUPERUSER` shortcut: robust for ':' in password, see 9b0f0e04f4e4

## 1.5.2 (6 May 2025)

Various performance fixes when there are many (millions) of _issues_
(rather than just events) in the database:

* Add index for `Grouping.grouping_key` (and project), see 392f5a30be18, 49e6700d4a81
* Digest: check Grouping.exists only once (save a query)
* Remove `open_issue_count` from homepage; it's too expensive
* Issue Paginator: don't attempt to count the Issues, see 378366105496
* Stress test command: more fat-tailed randomness (d5a449020d03)

Compatibility fix:

* `format_exception` in `capture_or_log_exception`: python 3.9 compatible

## 1.5.1 (24 April 2025)

Various fixes and improvements:

* 2 new tools to get a handle on performance of systems under load:
    * A [snappea-stats] subcommand to gain insight in
    * A page was added at `http://YOURINSTALL/counts/` that shows, for each type of object, the number of objects in the
      DB. (superuser only)

* Fix `different_runtime_limit` race conditions, see 53d4be818334
* `immediate_semaphore`: implement alias "using", see 67f769d3e5be
* `immediate atomic` 'get-write-lock' performance logging: fix it, see f8db5edf82ed

* Various improvements in the yellow warning bar for "backlogged snappea":
    * Better 'yellow bar' for snappea warnings (using Stat info)
    * Oldest task age warning: display as int
    * snappea task warning should itself never slow down the site (max runtime)

* Add some examples to the "conf templates"
    * `EVENT_STORAGES`: add (commented-out) example configuration to `conf_templates`
    * Clarify options for `EMAIL_BACKEND` in the `conf_templates`

* When is the `email_system_warning` shown? change & document
* Snappea foreman: on catastrophic errors, wait for workers, see 9b6fbe523f3c
* Explain tailwind usage during development & vendoring step, see 5c0e45a16db2
* Fix Header/Grouper for Log Messages using deprecated SDKs (See #85)

* `EMAIL_USE_TLS`: false by default (as was documented). See 7c3c19b6c8f2
* `EMAIL_USE_SSL`: `not EMAIL_USE_TLS` by default (avoids crashing on "both
  true" when only `EMAIL_USE_TLS` is explicitly configured

## 1.5.0 (14 April 2025)

Bugsink 1.5.0 introduces preliminary support for sourcemaps.

_preliminary_ because only the following combination (all must apply) of features works:

* Uploading "manually", using `sentry-cli`
* sourcemaps & sources are related using `debug-id`, which must be injected by `sentry-cli`

Tested with the followin `sentry-cli` invocation:

```
uglifyjs captureException.js   -o captureException.min.js   --source-map url=captureException.min.js.map,includeSources
sentry-cli sourcemaps inject captureException.min.js captureException.min.js.map
SENTRY_AUTH_TOKEN=a sentry-cli --url https://YOURBUGSINK/ sourcemaps --org bugsinkhasnoorgs --project=ignoredalso upload .
```

Implemented with 3 endpoints Bugsink-side:

* upload-chunks GET tells the CLI what our capabilities are
* upload-chunks POST allows the CLI to upload the files (the CLI bundles everything first, and adds a manifest)
* assemble-artifact: unpack that thing and put it in the right location.

[This comment contains a longer overview of the current state](https://github.com/bugsink/bugsink/issues/19#issuecomment-2796304379)

### Further Features & Fixes

* Add `EMAIL_USE_SSL` to settings/templates.

* Print full stacktraces when _not_ dogfooding (i.e. when sentry-sdk is not configured).

* Various Dockerfile improvements (See #68 and the top of the Dockerfile for details)

* Allow users to join their own team's projects Fix #56
* Don't crash on non-str tag-values: Fixes #76

* Add `user.id`, `user.username`, `user.email` and `user.ip_address` tags in `deduce_tags`
  allows for direct matching on one of those rather than just "whatever is avaialble"
  (which goes into the not further qualified `user` tag)

## 1.4.2 (1 April 2025)

* `deduce_allowed_hosts`: allow for localhost, see #46
* `retention_max_event_count`: in project settings form
* `issue.stored_event_count`: fix (it was incorrectly calculated). Running the migrations will
    automatically fix the existing values too.
* Fix user tag deduction (user tags were not correctly calculated from the event data)

## 1.4.1 (17 March 2025)

* Bugfixes on the experimental postgres support, see #21, #61
* sqlite: per-query timeout configurable
* Make `EMAIL_TIMEOUT` configurable on Docker, fixes #60

## 1.4.0 (13 March 2025)

### Introducing (Tag-based) Search

Bugsink 1.4.0 [introduces tag-based search](https://www.bugsink.com/blog/introducing-search/).

* Support for searching both **Issues** and individual **Events**.
* Search is built entirely on **tags** (both user-supplied and deduced from event properties).
* **Simple query language**: `key:value` pairs for structured filtering.
* Search is **implemented directly in the database**, ensuring a simple and efficient architecture.

Because tags take such a key role in the implementation of search, the introduction of search is coupled with per-issue
tag overviews, see #36 & #12. i.e. per issue pages show a breakdown-by-tag; and a special page (showing up to 25 values)
for tags is introduced.

NOTE: when upgrading to 1.4.0 tags for already-seen events are not automatically calculated (for large databases, this
could make migrating very annoying). You can either wait a while (the tags for as of yet unseen events will be added)
or run the `init_tags` command to determine the tags for the already-existing issues and events.

### Further Features & Fixes

* Postgres: experimental support: our testsuite now runs against postgres, and configuring the Docker image to run with
  a postgres backend is possible. No further testing has been done, but this at least makes such experiments possible.
  See #21

* Createsuperuser pre-start: don't do that when _any_ users exist in the DB (Fixes #54)

* Show remaining (in db, AKA 'available') number of events in the issue-list (when some events have been evicted from
  the DB, the issue list shows the _actually availale_ number of events in a smaller font next to the total seen number.

* Details page: be robust for top-level message-as-string (Fixes #55)

* Add 'level' to logentry event details

* Issue.calculated_* fields: fix lengths (fixes an issue on MySQL)

## 1.3.0 (20 February 2025)

### Introduce FileEventStorage

An (optional) way to store the `event_data` (full event as JSON)
outside the DB. This is expected to be useful for larger setups,
because it gives you:

* A more portable database (e.g. backups); (depeding on event size
  the impact on your DB is ~50x.
* Less worries about hitting "physical" limits (e.g. disk size, max
  file size) for your DB.

Presumably (more testing will happen going forwards) it will:

* Speed up migrations (especially on sqlite, which does full table copies)

However: Ingestion speed does not seem to notacibly changed (either
way) with this change.

Related utilities:

* `migrate_to_current_eventstorage` command: a command to move data over.
* `cleanup_eventstorage` command: a "vacuum" of sorts.

### Further Features

* Pagination on the Issues list
* Event-detail UI for Logentries: show `logentry.message` and `logentry.params`
* UI: thousand-separators for counts
* Support for top-level `message` in events (See #43)
* `nuke_events` command improvements: more consistent behavior, better confirmation.
* `make_consistent` command improvements: more affected cases, run in transaction
* `migrate` command: always shows timings
* `showstat` command: `digestion_speed`
* Send welcome email: as a command
* Support for CORS

### Fixes

* transaction semaphore: ensure release for exceptions while _entering_ the transaction

### Cleanup / refactoring

* Move MoreLoudlyFailingTransport out of the default 'eat_your_own_dogfood' conf
* allow long-running queries on long-running commands (`nuke_events`, `make_consistent`)
* DB indexes for the issue-lists (including filters)
* Don't 'eat your own dogfood' (send errors to backend) while running tests
* `delete_with_limit` was removed; this removes one tie-in to MySQL/Sqlite (See #21)
* Print task's name in Snappea log when "Done"

## 1.2.0 (11 February 2025)

### Features

* Docker: The SQLite database now defaults to being stored in `/data/`, with a warning if the directory needs to be created.
* Show 'event grouping', 'handled' and 'mechanism' in the event details
* Ingestion performance fixes (most notable when >1M events are stored). See 615d2da4c8b5
* UI performance fixes (most notable in the UI, when >1M events are stored). See 86e8c4318bc2

### Bug Fixes

* Transaction semaphore fixes prevent deadlocks
* Various fields are cut off at max length to avoid (1406, "Data too long for column ...")` errors in MySQL.
* Ensured `digested_at` time is set correctly.
* Added indexes on fields used for ordering
* UI: 'This might mean' refers to 'No open issues'; make this show in the interface

### Cleanup / refactoring

* Remove 2 fields that were "temporary [..] to get a sense of the shape of the data
* Set up dependabot
* Update dependencies (as per dependabot)
* Datamodel: `Event.grouping`, which ensures every event has a consistent Grouping associated with it.
* Move 'DESIGN*' docs out of repo
* Mention Security Policiy in CONTRIBUTING.md
* squashmigrations (faster startup for fresh installations)