notify: a temporary test button on /jobs
The first producer, so the pipe can be exercised from the UI before any real event is wired
to it. Marked TEMPORARY in the source and meant to be deleted when a real producer replaces
it.
POST /_officer/notify now takes the user from the X-Officer-User header the proxy injects
when the body omits it. A producer inside the tailnet says who to notify; a browser reaching
this through /api/notify cannot know its own id, and the platform has already authenticated
whoever sent it. Body still wins where present.
The button sends { type: 'test' }, which fans out to every configured channel — Discord
today, APNs and FCM the moment their credentials exist — and toasts what each one reported,
so "no channels configured" is distinguishable from "sent".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -61,13 +61,16 @@ const server = Bun.serve({
|
||||
if (!body.type || !VALID_TYPES.includes(body.type)) {
|
||||
return Response.json({ error: `type must be one of ${VALID_TYPES.join(', ')}` }, { status: 400 });
|
||||
}
|
||||
// Producers inside the tailnet are trusted, but a userId typo would silently notify nobody, so it
|
||||
// is required rather than defaulted.
|
||||
if (typeof body.userId !== 'number') {
|
||||
return Response.json({ error: 'userId is required' }, { status: 400 });
|
||||
// Producers inside the tailnet POST directly and say who to notify. A browser reaching this
|
||||
// through /api/notify cannot know its own id, so the proxy's injected header stands in — the
|
||||
// platform already authenticated whoever sent it.
|
||||
const headerUser = Number(req.headers.get('X-Officer-User'));
|
||||
const userId = typeof body.userId === 'number' ? body.userId : headerUser;
|
||||
if (!Number.isFinite(userId) || userId <= 0) {
|
||||
return Response.json({ error: 'userId is required (body or X-Officer-User)' }, { status: 400 });
|
||||
}
|
||||
|
||||
const results = await dispatch(body as Notification);
|
||||
const results = await dispatch({ ...body, userId } as Notification);
|
||||
return Response.json({ ok: true, results });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user