every proxied request carries who is asking
Officer's session is the only place the acting user is known, and fofos writes it into its own change history. An email in X-Actor, because that database has no users to point at. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,14 @@ type RequestOptions = {
|
||||
/** Already-serialised. Forwarded as given so what fofos receives is what the caller sent. */
|
||||
body?: string | FormData | null;
|
||||
contentType?: string | null;
|
||||
/**
|
||||
* Who is asking, as an email — sent as `X-Actor`, and written into fofos's own change history.
|
||||
*
|
||||
* fofos has no users, so it cannot work this out and cannot check it: the header is as trustworthy
|
||||
* as the token that carried it. That is enough for what it is for, which is telling two colleagues
|
||||
* apart rather than proving anything.
|
||||
*/
|
||||
actor?: string | null;
|
||||
};
|
||||
|
||||
export type FofosResponse = { status: number; body: string; contentType: string | null };
|
||||
@@ -70,6 +78,7 @@ export async function fofosRequest(
|
||||
// Left unset for FormData: fetch has to write its own, including the multipart boundary, and a
|
||||
// hand-set Content-Type here produces a body the other end cannot parse.
|
||||
if (options.contentType) headers['Content-Type'] = options.contentType;
|
||||
if (options.actor) headers['X-Actor'] = options.actor;
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
|
||||
@@ -762,6 +762,9 @@ router.all('/*', async (ctx) => {
|
||||
search: url.search,
|
||||
body,
|
||||
contentType: body ? 'application/json' : null,
|
||||
// Officer's session is the only place the acting user is known. fofos writes it into its own
|
||||
// history — see its record.ts, and the note on `actor` in fofos-client.
|
||||
actor: ctx.get('user')?.email ?? null,
|
||||
});
|
||||
return passThrough(response);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user