fix(push): "der kommer ikke nogen" kunne ikke besvares
Release / Build and publish image (push) Failing after 10m0s

Alt om det var usynligt. Indstillingssiden sagde "til for denne enhed", så snart
der fandtes et abonnement — også når hver eneste push blev afvist. Og en afvist
push gik i en logline på **Debug**, som ikke skrives på en instans, der kører på
standardniveau. Så en levering, der fejler lydløst, og en levering, der aldrig
sker, så ens ud, og forskellen er hele diagnosen.

Tre forskellige problemer havde ét udseende: browseren tilmeldte sig aldrig,
tjenesten afviste den, eller der var ikke noget forfaldent endnu.

**En prøveknap** under Indstillinger → Notifikationer sender én notifikation
gennem den rigtige rute — ikke en genvej, så det, den beviser, er det, der
faktisk skal virke — og siger hvad hver enhed gjorde ved den. Kom den ikke frem,
og afviste ingen den, står der, at det så er browseren eller styresystemet, der
holder den tilbage. Nu peger svaret på ét af de tre steder.

Loglinjen er hævet fra Debug til Warn. Det var den ene linje, der ville have sagt
hvorfor.

Teksten kommer fra klienten, fordi ordbøgerne gør. En server, der bærer sin egen
kopi af "det her er en prøve", bærer den på ét sprog.

**Og en lækage, prøven fandt.** Go pakker en transportfejl som `*url.Error`, og
dens tekst er `Post "https://fcm.googleapis.com/fcm/send/dQw4…": dial tcp: …` —
hele endepunktet, som er den legitimation, push-tjenesten udstedte til den enhed.
Den var på vej ud i svaret, i loglinjen og i ethvert skærmbillede af nogen af dem.
Prøven var skrevet for at bevise, at kun værten blev nævnt, og det var sådan den
blev fundet. Fejlen pakkes ud, og adressen skrubbes bagefter alligevel: den næste
fejltype, der bærer den med, kommer ikke med en advarsel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-20 20:41:33 +02:00
co-authored by Claude Opus 5
parent ae673086bc
commit fcd6dca852
8 changed files with 299 additions and 4 deletions
+47
View File
@@ -2079,6 +2079,53 @@ paths:
"404": { $ref: "#/components/responses/NotFound" }
"422": { $ref: "#/components/responses/Validation" }
/api/v1/push/test:
post:
tags: [notifications]
summary: Send one notification to your own devices, and say what happened.
description: |
The answer to "no notifications arrive". A push that a service refuses is
the ordinary failure — a stale subscription, a browser that revoked
permission without telling the server — and every one of them looks
exactly like silence from the outside.
It goes through the same path a real notification takes, so what it proves
is the thing that has to work. The title and body come from the caller
because the dictionaries live in the interface.
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
title: { type: string, maxLength: 200 }
body: { type: string, maxLength: 500 }
responses:
"200":
description: What each device did with it.
content:
application/json:
schema:
type: object
properties:
subscriptions:
type: integer
description: Devices registered for this account.
sent:
type: integer
failed:
type: array
items:
type: object
properties:
service:
type: string
description: The push service's host — never the endpoint, which is a credential.
reason:
type: string
description: What the service said.
/api/v1/sections/{sectionID}:
parameters:
- { name: sectionID, in: path, required: true, schema: { type: string } }