feat(server): name the event in a push and offer a booking as a Google Wallet pass

The push payload carries the event it reports, so the Android app can file a
notification under a channel of its own (chat, trip updates, invitations).
A browser and the iOS extension ignore the field.

GET /api/trips/:tripId/reservations/:id/wallet-pass/google sends the same
request the Apple Wallet signer takes to the TREK services' Google route and
answers with the signed save-to-wallet link the Android app opens. Off with the
other TREK services, and a clear 404 while liketrek has no Wallet issuer yet.
This commit is contained in:
Maurice
2026-11-07 14:11:22 +01:00
parent 41c713fd9a
commit d41a4f0827
9 changed files with 151 additions and 2 deletions
@@ -199,5 +199,7 @@ describe('pushPayloadSchema', () => {
expect(pushPayloadSchema.safeParse({ title: 'T' }).success).toBe(false);
expect(pushPayloadSchema.safeParse({ body: 'B' }).success).toBe(false);
expect(pushPayloadSchema.safeParse({ title: 'T', body: 'B', tag: 5 }).success).toBe(false);
expect(pushPayloadSchema.safeParse({ title: 'T', body: 'B', event: 'trip_invite' }).success).toBe(true);
expect(pushPayloadSchema.safeParse({ title: 'T', body: 'B', event: 1 }).success).toBe(false);
});
});
@@ -125,5 +125,10 @@ export const pushPayloadSchema = z.object({
body: z.string(),
url: z.string().optional(),
tag: z.string().optional(),
/**
* The event it reports (trip_invite, collab_message, ...). The Android app
* sorts notifications into its channels by it; a browser ignores it.
*/
event: z.string().optional(),
});
export type PushPayload = z.infer<typeof pushPayloadSchema>;