4690 Commits
Author SHA1 Message Date
binwiederhier 63e25d667e Keep a same-key rate visitor on a poll even if it is stale
A stale one has only its tier from back then to lose, and a publish drops it anyway. Simpler without the check.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 20:31:33 +00:00
binwiederhier 3cae50f18d Keep a stream as the topic's rate visitor when its subscriber polls
Since every request gets its own visitor, a poll from the subscriber of an
open stream replaced the stream's visitor as the topic's rate visitor. Only
the stream's keepalives keep a rate visitor alive, so a day later UnifiedPush
publishes failed with 50701 while the stream was still open. A poll from the
same key now keeps the live rate visitor (and keeps it alive) instead.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 19:46:13 +00:00
binwiederhier d397e9d075 Put security first in the v2.35.0 release notes and merge the bug fix sections
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 16:44:17 +00:00
Philipp C. Heckel b9561e8088 Merge pull request #2118 from binwiederhier/visitor-per-request
Build the visitor per request instead of sharing it
2026-10-29 12:23:48 -04:00
binwiederhier 7aa105bdec Show the day's remaining emails on the account again
emails_remaining was clamped to what the email bucket holds right now, so a fresh
Supporter saw 10 of 50. It is the daily limit minus today's emails again, as in
v2.34.0 and like messages_remaining; the bucket still refuses a burst past it.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 16:10:36 +00:00
binwiederhier b73e4f0402 Add release notes for settled key pruning
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 14:01:50 +00:00
binwiederhier 30d8ba58d7 Forget settled limiter keys after a minute instead of a day
A key whose buckets are full again and whose daily-capped counts are zero
looks exactly like a new one, so forgetting it changes nothing. Prune now
drops such keys once unused for a minute; the idle time stays as the
backstop for keys that never settle.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 14:01:22 +00:00
binwiederhier 1e54713e29 Credit the reporter of the Matrix push key fix 2026-10-29 13:49:36 +00:00
binwiederhier eb9a12d734 Name the visitor's shared environment field env instead of embedding it
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 13:46:56 +00:00
binwiederhier 647698c607 Keep the visitor's subscription methods in visitor.go
Only the gauge lives in visitor_subscriptions.go; the tests follow their code.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 13:24:57 +00:00
binwiederhier 31840bef1a Move the subscription gauge into visitor_subscriptions.go and test it
Covers the limit, release on stream close without leaving keys behind,
concurrent acquires, sharing per key, and the end of the Firebase penalty.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 12:22:41 +00:00
binwiederhier 02be719ce2 Web app: don't add deleted notifications again when a poll replays them
The server replays the whole second of a since=<id> marker, so a poll
returns messages the user deleted. Remember deleted notifications and
skip them (and older versions of their sequence), and don't move the
marker back when a poll only replayed known messages, which made each
poll replay a different part of that second.

Fixes #2098
2026-10-29 11:31:45 +00:00
binwiederhier 89cee1cd11 Keep a topic's rate visitor for as long as its subscriber is, not its key
Stale read the limiter key's last use, which every charged publish refreshes, so a topic kept
a vanished subscriber's limits (and its UnifiedPush subscription) for as long as anyone
published to it. The visitor now carries its own keepalive, set when it is built and by the
subscribe handlers' keepalive loops, like the shared visitor's seen was.

Also from the review: Prune returns and the manager logs the number of forgotten keys, the
unused visitorID wrapper goes, a stale comment and test name are updated, and the release
notes get the #1051 entry.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 03:21:37 +00:00
binwiederhier d61081fe4e Name the shared visitor environment Server.visitors
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 03:04:24 +00:00
binwiederhier e2250f1671 Merge remote-tracking branch 'origin/main' into limit-2118 2026-10-29 02:43:07 +00:00
Philipp C. Heckel 08566a0f0d Merge pull request #2122 from binwiederhier/limit-fixes
Close three gaps in the limit rework and pin its behavior with tests
2026-10-28 22:41:29 -04:00
binwiederhier 90fb310464 Name the hash field correctly in admin API errors, and report unused tokens as never used 2026-10-29 02:37:38 +00:00
binwiederhier 9693d393c8 Merge branch 'limit-fixes' into visitor-per-request
The three fixes apply as they are (the email guard without the visitor mutex, which this
branch no longer has). Of the new tests, the two that pin the shared visitor's SetUser flush
and the expunge of visitor objects have no counterpart here; the rest compare visitor keys
where they compared object identity.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 02:30:47 +00:00
binwiederhier aa9b89ef7b Add release note for terabyte size units 2026-10-29 02:29:50 +00:00
Philipp C. Heckel 3d967b0db0 Merge pull request #2078 from cangen185-sudo/codex/fix-parse-size-terabytes
fix(util): accept terabyte size units without overflow
2026-10-28 22:29:39 -04:00
binwiederhier 62abb9b729 Close three gaps in the limit rework and pin its behavior with tests
A tier with a daily email limit of zero sends no emails (the limit service reads a daily
limit of zero as "no cap"), a tier edited in place flushes the visitor's pending user stats
before resetting its local counts like a tier ID change does, and a bucket refill with a
timestamp older than its last one neither charges tokens nor moves the refill point back.

The tests pin what the rework changed and what it must keep: shared keys count once in the
user stats, an expunged visitor continues its counts, the daily reset keeps the buckets,
zero bursts admit nothing, seeds apply once, prefix keying, tier changes in all directions,
concurrency on a shared key, and the account page's remaining values matching admissions.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 02:28:25 +00:00
binwiederhier 8baa89871f Reset the whole ACL and list all users' tokens only over the admin socket 2026-10-29 02:21:01 +00:00
binwiederhier 64c65311be Inline readAdminTokenUser into the token handlers 2026-10-29 02:08:15 +00:00
binwiederhier a6cd0e4d7e Build the shared visitor config and IP limits once
Visitors are built per request, so what they share (the keying and limit
config, the config-based limits of visitors without a tier, the limiter and
the subscription gauge) is built once in New. Keys are built with string
concatenation instead of fmt.Sprintf.
2026-10-29 02:06:26 +00:00
binwiederhier f90c97f3de Keep new visitors fresh and stop checking the user in the auth and account limits
A visitor's key is touched when the visitor is built, so a subscriber whose
request skipped the limiter (an exempt prefix on an existing topic) is not
dropped as a stale rate visitor. The auth and account limits are per key and
ignore the user, as on main.
2026-10-29 01:55:33 +00:00
Philipp C. Heckel 1e2530e102 Merge pull request #2111 from binwiederhier/dependabot/npm_and_yarn/web/serialize-javascript-7.1.4
Bump serialize-javascript from 7.1.2 to 7.1.4 in /web
2026-10-28 21:54:12 -04:00
dependabot[bot] 6351695d02 Bump i18next-http-backend from 4.0.2 to 4.0.4 in /web
Bumps [i18next-http-backend](https://github.com/i18next/i18next-http-backend) from 4.0.2 to 4.0.4.
- [Changelog](https://github.com/i18next/i18next-http-backend/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-http-backend/compare/v4.0.2...v4.0.4)

---
updated-dependencies:
- dependency-name: i18next-http-backend
  dependency-version: 4.0.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-29 01:51:59 +00:00
Philipp C. Heckel eecfbf645c Merge pull request #2082 from binwiederhier/dependabot/npm_and_yarn/web/vitest-5.0.4
Bump vitest from 5.0.3 to 5.0.4 in /web
2026-10-28 21:49:24 -04:00
dependabot[bot] d6b49bdcb9 Bump github.com/go-jose/go-jose/v4 from 4.1.5 to 4.1.6
Bumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.1.5 to 4.1.6.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Commits](https://github.com/go-jose/go-jose/compare/v4.1.5...v4.1.6)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-version: 4.1.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-29 01:49:16 +00:00
Philipp C. Heckel e6f31170fa Merge pull request #2047 from binwiederhier/dependabot/npm_and_yarn/web/react-i18next-17.0.16
Bump react-i18next from 17.0.15 to 17.0.16 in /web
2026-10-28 21:49:15 -04:00
Philipp C. Heckel 0d2cd0388d Merge pull request #2083 from binwiederhier/dependabot/npm_and_yarn/web/i18next-26.4.4
Bump i18next from 26.4.2 to 26.4.4 in /web
2026-10-28 21:49:05 -04:00
Philipp C. Heckel 078aa9189d Merge pull request #2112 from binwiederhier/dependabot/npm_and_yarn/web/fast-uri-3.1.9
Bump fast-uri from 3.1.8 to 3.1.9 in /web
2026-10-28 21:48:55 -04:00
Philipp C. Heckel 8b54920a2f Merge pull request #2048 from binwiederhier/dependabot/github_actions/all-2f4c4b3894
Bump actions/setup-node from 7.0.0 to 7.1.0 in the all group across 1 directory
2026-10-28 21:48:19 -04:00
Philipp C. Heckel 9e44f3a4c0 Merge pull request #2114 from binwiederhier/dependabot/go_modules/github.com/gabriel-vasile/mimetype-1.4.16
Bump github.com/gabriel-vasile/mimetype from 1.4.15 to 1.4.16
2026-10-28 21:48:15 -04:00
Philipp C. Heckel 88335ea8ec Merge pull request #2115 from binwiederhier/dependabot/go_modules/google.golang.org/api-0.306.0
Bump google.golang.org/api from 0.301.0 to 0.306.0
2026-10-28 21:48:12 -04:00
binwiederhier e0ee4b090f Merge remote-tracking branch 'origin/main' into adminsock-api
# Conflicts:
#	docs/releases.md
#	server/server_admin.go
#	server/server_admin_test.go
2026-10-29 01:46:43 +00:00
binwiederhier 10da6ad425 Merge remote-tracking branch 'origin/main' into visitor-per-request
# Conflicts:
#	server/visitor.go
#	server/visitor_test.go
2026-10-29 01:41:04 +00:00
binwiederhier abd5ac3bb9 Add regression tests for the auth and account limiters under concurrent logins 2026-10-29 01:37:23 +00:00
Philipp C. Heckel f5cea2919a Merge pull request #2119 from binwiederhier/auth-limiter-race
Do not read the shared visitor's user in the auth and account limiters
2026-10-28 21:35:08 -04:00
binwiederhier fefe5e0c19 Do not read the shared visitor's user in the auth and account limiters
The callers only use these for anonymous requests, and the user on an IP-keyed visitor can be
set by another request from the same IP (#1051).

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 01:29:22 +00:00
Philipp C. Heckel b55b6fa8ee Merge pull request #2116 from monarchsofchaos004-gif/docs-integrations-aibot-hostkit
docs: add aibot-hostkit to integrations
2026-10-28 21:28:55 -04:00
binwiederhier ccd4dd9d85 Build the visitor per request instead of sharing it
Requests from one IP (anonymous and untiered users) shared a single visitor
object with a mutable user, so overlapping requests could be authorized as
each other's user. The visitor is now built per request and never changed;
the limit service, keyed by visitor key, still shares the buckets and counts.
The Firebase penalty becomes a limiter kind, open subscriptions move to a
node-local gauge per key, and tier users' stats are enqueued per admitted
unit.

Fixes #1051
2026-10-29 01:28:12 +00:00
binwiederhier 601900cf16 Reject Matrix push keys that do not name a valid topic
The Matrix gateway built its publish request from the push key without the
router's topic path check. Publishing sanitizes the topic after authorization
(it strips NUL bytes and invalid UTF-8), so an anonymous push key like
/sec%00ret was authorized against an unmatched topic and stored under the
protected topic "secret".
2026-10-29 00:36:23 +00:00
Philipp C. Heckel 3798933838 Merge pull request #2105 from binwiederhier/step2-limit
Shared rate limits, step 2: one limiter model in package limit
2026-10-28 19:04:21 -04:00
binwiederhier 1ba8fa2863 Keep spent tokens on a burst change; account shows the emails sendable now
A tier upgrade used to keep the old bucket's tokens, capped at the new\nburst, so a bigger tier did not add its difference. The bucket now shifts\nby the burst difference both ways, down to a debt of one burst.\n\nemails_remaining is now capped by what the email bucket holds, so it no\nlonger shows emails the visitor cannot send (e.g. after the daily reset).\n\nClaude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-28 22:13:53 +00:00
binwiederhier 6463981f8f One field per line in multi-field struct literals
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-28 21:35:06 +00:00
binwiederhier cda6f241f9 Hold the limit shards by pointer
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-28 21:16:08 +00:00
monarchsofchaos004-gif 0d0158220f docs: add aibot-hostkit to integrations 2026-10-28 17:53:56 +00:00
dependabot[bot] 966179316c Bump actions/setup-node
Bumps the all group with 1 update in the / directory: [actions/setup-node](https://github.com/actions/setup-node).


Updates `actions/setup-node` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020...949feb2413d6458794dcd2491c4babbbce0c15c1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-27 21:44:11 +00:00
dependabot[bot] c28dba3f8f Bump google.golang.org/api from 0.301.0 to 0.306.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.301.0 to 0.306.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.301.0...v0.306.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-version: 0.306.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-27 21:42:56 +00:00