4690 Commits
Author SHA1 Message Date
binwiederhier c30365bc7b Test --wait-pid on processes owned by other users, add release note 2026-10-30 23:39:46 +00:00
binwiederhier 64d2819039 Merge branch 'fix/wait-pid-eperm-and-pidof-docs' of github.com:bekoeppel/ntfy into pr-1710 2026-10-30 23:36:04 +00:00
Philipp C. Heckel 4ef0154431 Merge pull request #2120 from binwiederhier/dependabot/npm_and_yarn/web/i18next-http-backend-4.0.4
Bump i18next-http-backend from 4.0.2 to 4.0.4 in /web
2026-10-30 19:35:47 -04:00
Philipp C. Heckel cb993278a8 Merge pull request #2121 from binwiederhier/dependabot/go_modules/github.com/go-jose/go-jose/v4-4.1.6
Bump github.com/go-jose/go-jose/v4 from 4.1.5 to 4.1.6
2026-10-30 19:35:43 -04:00
binwiederhier 89cd122952 Start the admin socket listener like the unix listener, without a server field 2026-10-30 23:35:33 +00:00
binwiederhier 0e0b2e4c7c Mention the deprecated database fallback in the admin socket startup warning 2026-10-30 23:27:00 +00:00
binwiederhier 0f49391494 Drop the deprecation of starting without the admin socket, just warn 2026-10-30 23:22:08 +00:00
Philipp C. Heckel 8dc17de284 Merge pull request #1969 from mikejgray/fix/serve-config-validation-chain
Fix serve config validation being skipped when base-url is set
2026-10-30 18:03:25 -04:00
binwiederhier e67d24b36a Merge remote-tracking branch 'origin/main' into pr-1969
# Conflicts:
#	docs/releases.md
2026-10-30 21:29:48 +00:00
Philipp C. Heckel b5b0b3bf0c Merge pull request #2125 from binwiederhier/replay-tombstones
Web app: keep deleted and read notifications when the server replays them
2026-10-30 17:28:10 -04:00
binwiederhier fd3a48436b Keep the serve config checks running after base-url and message-size-limit
Move the base-url check out of the else-if chain instead of into a
helper, and test both cases with an invalid auth-default-access, which
fails right after the checks, instead of starting a server.
2026-10-30 21:27:59 +00:00
binwiederhier 1ca0e5a766 Merge remote-tracking branch 'origin/main' into pr-1969
# Conflicts:
#	cmd/serve.go
#	cmd/serve_test.go
2026-10-30 21:27:43 +00:00
binwiederhier 5737b0bd8c Start the admin socket in Run like the other listeners, and deprecate starting without it 2026-10-30 21:26:40 +00:00
binwiederhier 2cbf4abd95 Say that counts converge in about two sync intervals, and what promotion and the email cap leave out 2026-10-30 21:25:44 +00:00
binwiederhier ce476d676d Restore the utils tests next to the reset_at ones 2026-10-30 21:25:17 +00:00
binwiederhier 02446d985a Do not crash the account page when the server sends no reset_at 2026-10-30 21:25:01 +00:00
binwiederhier 05d7ae22cc Report the in-memory counts of the kinds without a daily counter again 2026-10-30 21:24:21 +00:00
binwiederhier 6a573ab5c1 Round the Postgres clock down to the second, like SQLite 2026-10-30 21:23:03 +00:00
binwiederhier 6674f3b5bd Cancel a stuck usage load or sync on Close instead of waiting for it 2026-10-30 21:22:38 +00:00
binwiederhier 3fef91d342 Read the period end of a daily denial under the counter lock 2026-10-30 21:21:59 +00:00
binwiederhier 2b46b90df9 Check the row's age in the outer prune delete, so a row refreshed meanwhile survives 2026-10-30 21:21:40 +00:00
binwiederhier 614242e10f Make the admin socket visitor IP a var 2026-10-30 21:20:28 +00:00
binwiederhier e6a6049d23 Web app: notify for a message only a poll stored, and test replays end to end
A message the poll stored before its live delivery has no unread marker
yet, so the WebSocket delivery that follows marks it unread and notifies
again, while a replayed message that came in live keeps its state.

The e2e tests publish within one second and reload, so the reconnect
and the startup poll replay the earlier messages: deleted ones stay
gone, and read ones stay read without a new browser notification.
2026-10-30 21:14:26 +00:00
binwiederhier df332a9942 Disable the admin socket with "-", like listen-http 2026-10-30 21:14:06 +00:00
binwiederhier fd6e83134a Drop the admin socket peer credentials from the audit log 2026-10-30 21:03:16 +00:00
binwiederhier c43c475be3 Web app: mark deleted notifications instead of keeping a separate store
Like the Android app, a deleted notification stays in the notifications
table with a deleted flag, so the existing duplicate checks skip it when
the server replays it, and a deleted newer version keeps an older one
out. The lists leave deleted notifications out, and they are pruned with
the others. The service worker does not store a deleted message again.
2026-10-30 20:54:03 +00:00
binwiederhier 59775edc72 Rename admin-socket to listen-admin-unix 2026-10-30 20:52:50 +00:00
binwiederhier 851d98c475 Merge remote-tracking branch 'origin/main' into replay-tombstones
# Conflicts:
#	docs/releases.md
2026-10-30 20:47:27 +00:00
binwiederhier a96b35e242 Web app: keep read state of a replayed WebSocket message
The WebSocket handler deleted every version of a message's sequence
before adding it, so a replayed message that was already stored came
back as unread and notified again, and a replayed older version
replaced a newer one. addNotification now replaces older versions of
the sequence itself, and skips a message if a newer version is stored.

Fixes #2090
2026-10-30 20:45:30 +00:00
binwiederhier c3ecea55c4 Show the reset time and the sync delay on the account page, document shared daily limits
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:42:27 +00:00
binwiederhier c113e20677 Share daily limits through the usage table, drop the midnight reset and the stats queue
The server builds the usage store on the user database (the shared pool on
Postgres, the auth-file on SQLite) and starts the limiter before serving. A
visitor without a user writes its message count from a tenth of the cap on,
everyone else from the first message; anonymous emails get the daily cap the
replenish interval implies. The account API reports reset_at. The user stats
columns are no longer read or written.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:41:36 +00:00
Philipp C. Heckel 1a85857a99 Merge pull request #2087 from binwiederhier/adminsock-api
Admin API: tokens, tiers, password reset links, role changes
2026-10-30 16:41:14 -04:00
binwiederhier e73282539a Merge branch 'adminsock-api' into adminsock-socket
# Conflicts:
#	docs/releases.md
2026-10-30 20:40:54 +00:00
binwiederhier ceb0666d36 Shorter release notes for the internal admin API 2026-10-30 20:40:41 +00:00
binwiederhier f8f0d87253 Merge branch 'adminsock-api' into adminsock-socket
# Conflicts:
#	docs/releases.md
#	server/server.go
#	server/server_admin_socket.go
#	server/server_admin_test.go
2026-10-30 20:40:33 +00:00
binwiederhier 862bc5e14f Merge remote-tracking branch 'origin/main' into adminsock-api
# Conflicts:
#	docs/releases.md
2026-10-30 20:37:09 +00:00
binwiederhier dad9cfa03b Sync daily counts with the usage table in a background worker
Every 5 s a node writes the unflushed counts of its promoted keys and reads back
the rows changed since the last round; at startup it loads the current rows
(waiting up to 30 s, then serving from memory while it keeps loading). A key is
promoted once it reaches its rule's threshold, or when another node's row for it
shows up. Rows not written for 25 h are pruned hourly.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:33:09 +00:00
binwiederhier e074eaffa3 Add the usage store on SQLite and Postgres
One row per key: same period adds, a newer period replaces, and a leftover of an
older period is added to the stored one rather than taking the row back. Writes
are sorted by key and chunked; reads stream rows changed since a database time.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:28:56 +00:00
binwiederhier b4669de064 Add the usage table in user schema migration 9 -> 10, zero the stats_* columns
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:27:29 +00:00
binwiederhier 59cee8430a Split daily counters from token buckets, roll each key over on its own 24h period
Daily counts (messages, emails, calls) now live in per-key counters that start
over lazily when the key's period ends; buckets keep their tokens. ResetAt
reports the end of the key's period. Seed, ResetUsage and Config.ResetTime are
gone, and an idle key is forgotten only once its buckets are full again.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:23:47 +00:00
binwiederhier 9280bc1e14 Add per-key 24h periods from a hashed reset offset
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 20:15:19 +00:00
binwiederhier 5c2a1ddeef Release notes and install docs, prep v2.35.0
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
v2.35.0
2026-10-30 13:24:49 +00:00
Philipp C. Heckel 3aa1b46bc1 Merge pull request #2129 from binwiederhier/email-cap
Do not cap emails without a tier, keep UnifiedPush rate visitors alive while a stream is open
2026-10-30 09:11:11 -04:00
binwiederhier e7cc914087 Keep a topic's rate visitor alive while any stream is open on it
Liveness no longer comes from keepalives: a topic keeps its rate visitor
while it has an open stream, and for a day after the last one closed or
the last subscribe. This removes the keepalive matching, taking a stale
topic back and its write re-check.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-30 03:35:14 +00:00
binwiederhier f666779ee8 Check that a stream may still write before it takes a topic back
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 23:39:13 +00:00
binwiederhier 1883645c1a Keep a topic's rate visitor alive by the topic, for any stream with its key
A stream's keepalives refreshed only its own visitor, so a topic that held
the visitor of a newer stream or a poll from the same key lost it after a
day although a stream was still open. The topic now keeps when a
subscriber with its rate visitor's key was last seen, and a stream takes a
stale topic back.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 22:54:19 +00:00
binwiederhier 1185578dc5 Do not turn off email without a tier when the refill is slower than a day
Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 22:45:43 +00:00
binwiederhier be440b62ae Make the v2.35.0 release notes briefer and accurate
Tier to tier changes keep spend (no tier to a tier never did), only a tier's daily email limit is a cap, only the read over the size limit is refunded, and the #2119 bullet describes the fix.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 21:10:24 +00:00
binwiederhier 4ed82ddd69 Do not cap the emails of visitors without a tier at a day's refill
Without a tier, the daily email limit is only derived from the refill, for
display. Enforcing it as a cap cut what the email bucket allowed: with a burst
of 5 and a refill every 288 minutes, 5 emails a day instead of about 10. Only
a tier's daily email limit is a cap now, as before.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
2026-10-29 21:10:24 +00:00
Philipp C. Heckel 8256b410c3 Merge pull request #2128 from binwiederhier/limit-release
Keep a stream as the topic's rate visitor when its subscriber polls
2026-10-29 16:44:30 -04:00