Commit b81a25efa5

b81a25efa5dd60e3379bb1f0efaf6548f244e26c

parent: b58fd61f44

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-20 10:48 UTC

docs: push notifications

Closes #89
.gitbay/wiki/Admin.org +32
@@ -118,6 +118,38 @@ default, is right when gitbayd terminates TLS itself.
118118 registration and self-service =email add=; in closed mode you may omit
119119 it entirely and assert addresses by hand (below).
120120
121** [push]
122Push notifications to Apple devices, delivered by gitbayd talking to
123APNs directly over HTTP/2, authenticated by an ES256 JWT signed with an
124operator-supplied provider key. Off unless configured.
125
126- =enabled= (false).
127- =key_file= — path to the =.p8= provider key from Apple's developer
128 portal (Certificates, Identifiers & Profiles → Keys). It belongs at
129 =/etc/gitbay/apns.p8=, mode 0600, owned by the account gitbayd runs
130 as. Read and validated at startup: it must parse as a PEM-wrapped
131 PKCS#8 EC (P-256) private key, or the daemon refuses to start rather
132 than fill a queue nobody is watching.
133- =key_id=, =team_id= — the key's id and your Apple developer team id,
134 both from the same portal page.
135- =topic= — the app's bundle identifier. *An APNs key belongs to a
136 bundle ID.* gitbay.org pushes to the App Store build under its own
137 bundle id; a self-hoster who wants push ships their own iOS build
138 under their own bundle id, with its own =.p8= key from their own
139 developer account, and points =topic= at that id. There is no way to
140 push to someone else's build, by design — this is Apple's model, not
141 gitbay's.
142- =environment==production= or =sandbox=, naming the APNs host
143 rather than taking a URL, so a typo cannot aim the key at a host that
144 is not Apple's.
145
146All five of =key_file=, =key_id=, =team_id=, =topic= and =environment=
147are required when =enabled= is true; validation runs at config load,
148so a misconfigured =[push]= is caught before the daemon serves
149anything. The delivery queue (a device's undelivered and attempted
150pushes) is capped the same way the mail queue is, by =[retention]
151push=.
152
121153** [api]
122154- =enabled= (false) — the JSON API surface; see [[API]]. Off
123155 means no credential-bearing HTTP endpoint exists at all.
.gitbay/wiki/Parity.org +11
@@ -331,6 +331,10 @@ client has no use for one (krz/gitbay#57).
331331| notification inbox | yes | yes | yes |
332332| activity mail on, off | yes | yes | yes |
333333| watch writable repos | yes | yes | yes |
334| push device add | yes | yes | no |
335| push device list | yes | yes | no |
336| push device remove | yes | yes | no |
337| activity push on, off | yes | yes | no |
334338| web colour scheme | yes | yes | n/a |
335339| API token mint | yes | no | no |
336340| account export bundle | yes | yes | n/a |
@@ -351,6 +355,13 @@ to every repository you can write to, without a row per repository. A
351355mute wins over owning the repository, having written the thread, or the
352356preference.
353357
358Push is the third leg beside inbox and mail, delivered to Apple devices
359an account has registered. =notifications device add= runs on every
360surface like every other command, but no web page offers a form for
361it, because only the iOS app can produce an APNs device token — a
362browser has no way to ask Apple for one. =device list= and =device
363remove= have no such limit and are yes on the web like the rest.
364
354365A login link is requested from the login page by username or verified
355366address, and arrives by mail: it works once and expires in fifteen
356367minutes. The row is =n/a= for the CLI because a terminal with a
.gitbay/wiki/Users.org +21 −3
@@ -680,9 +680,10 @@ control under Appearance.
680680When the instance has SMTP configured, activity mails you as well as
681681filing the inbox row: someone opens an issue or MR on your repository,
682682comments where you are a participant (author, commenter, reviewer, or
683mentioned), reviews, closes, or merges. =notifications settings mail
684off= keeps the inbox and stops that mail (login links are not activity
685and still arrive); the account page has the same switch.
683mentioned), reviews, closes, merges, or assigns you.
684=notifications settings mail off= keeps the inbox and stops that mail
685(login links are not activity and still arrive); the account page has
686the same switch.
686687=notifications settings watch on= makes you a recipient of every issue
687688and merge request on the repositories you can write to, as if you had
688689run =repo watch= on each: it is consulted when a notice is delivered,
@@ -696,6 +697,23 @@ someone else.
696697You are never mailed about your own actions, and only verified primary
697698addresses receive anything. Delivery retries on relay failure.
698699
700Push is the same activity again, delivered to a phone: the iOS app
701registers a device, and =notifications settings push off= silences it
702the way =mail off= silences mail, without deregistering anything.
703=notifications device list= shows what is registered (token shown
704truncated); =notifications device remove <id>= drops one by hand, from
705the CLI or the account page. A device is also dropped on its own the
706moment Apple reports the token dead, so an app deleted from a phone
707stops costing anything without you having to notice. Push only works
708when the instance operator has configured it — a self-hosted instance
709with no APNs key configured never sends any.
710
711Push notifications carry the notice in full: a private repository's
712name and the issue or merge request number reach Apple and can appear
713on a lock screen, the same as any other text a phone shows in a
714notification. This is deliberate, not an oversight — weigh it against
715what you keep in a private repository before registering a device.
716
699717* Web vocabulary
700718
701719Sign in / Log out, Search, sentence-case headings and buttons, product
CHANGELOG.org +30
@@ -4,6 +4,36 @@ Versioning follows semver from v0.1.0. Database migrations run
44automatically on daemon start; upgrade notes appear per release when
55anything beyond "replace the binary and restart" is needed.
66
7* v1.32.0 — unreleased
8
9Push notifications to iOS devices (#89): activity reaches a registered
10phone the way it already reaches the inbox and mail.
11
12- gitbayd talks to APNs directly over HTTP/2, authenticated by an
13 ES256 JWT signed with an operator-supplied =.p8= provider key. New
14 config section =[push]=: =enabled=, =key_file=, =key_id=, =team_id=,
15 =topic= (the app's bundle identifier) and =environment=
16 (=production= | =sandbox=), all validated at load when enabled — a
17 misconfigured =[push]= refuses to start rather than filling a queue
18 nobody is watching. An APNs key belongs to a bundle id: a self-hoster
19 ships their own build under their own =topic= to use this; the App
20 Store build talks to gitbay.org.
21- Migration 0059: =push_devices= and =push_queue=, and
22 =users.notify_push= (default on).
23- =notifications device add= (token on stdin), =device list= (token
24 shown truncated), =device remove <id>=, and =notifications settings
25 push on|off=. A device is dropped automatically when Apple reports
26 the token dead (410 Unregistered or BadDeviceToken).
27- =[retention] push= caps the delivery queue, beside =mail=.
28- =issue assign= now files a notice, so assignment reaches the inbox,
29 mail and push.
30- Notification text is sent in full, private repositories included: a
31 repository's name and item number reach Apple and can appear on a
32 lock screen.
33- Web: the notification settings page carries the push toggle and the
34 device list, with removal behind confirmation. No web page offers a
35 device-add form — only the app can mint an APNs token.
36
737* v1.31.1 — 2026-09-20
838
939The stylesheet URL carries the build's hash (#239).