feat: add browser auth shell
This commit is contained in:
@@ -220,6 +220,7 @@ function createModuleRealtimeClient(
|
||||
function createModuleApiClient(
|
||||
config: EkklesiaHostConfig,
|
||||
descriptor: HostModuleUiDescriptor,
|
||||
onAuthorizationResponse?: (status: 401 | 403) => void,
|
||||
): ModuleUiApiClient {
|
||||
const performRequest = config.fetch ?? fetch;
|
||||
const moduleRoot = new URL(resolveApiUrl(config, descriptor.apiBaseUrl));
|
||||
@@ -244,7 +245,13 @@ function createModuleApiClient(
|
||||
// The module's own `init` is forwarded whole — method, headers, body, signal — and only
|
||||
// `credentials` is imposed, because session handling is the host's job and a module UI never
|
||||
// sees or supplies a token (ADR 0022). A module cannot opt out of it.
|
||||
return performRequest(target.href, { ...init, credentials: "include" });
|
||||
const response = await performRequest(target.href, { ...init, credentials: "include" });
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
// This callback stays entirely on the host side. The module still receives its original
|
||||
// response, and the public ModuleUiContext gains no authentication control or event.
|
||||
onAuthorizationResponse?.(response.status);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -253,6 +260,9 @@ export interface CreateModuleUiContextOptions {
|
||||
readonly config: EkklesiaHostConfig;
|
||||
readonly descriptor: HostModuleUiDescriptor;
|
||||
readonly principal: ModuleUiPrincipal;
|
||||
/** Host-only signal used by the Dashboard to revalidate an apparently expired session. It is not
|
||||
* included in the returned ModuleUiHostContext and is intentionally absent from the UI SDK. */
|
||||
readonly onAuthorizationResponse?: (status: 401 | 403) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,7 +281,7 @@ export interface CreateModuleUiContextOptions {
|
||||
export function createModuleUiContext(options: CreateModuleUiContextOptions): ModuleUiHostContext {
|
||||
const granted = new Set(options.descriptor.permissions);
|
||||
return Object.freeze({
|
||||
api: createModuleApiClient(options.config, options.descriptor),
|
||||
api: createModuleApiClient(options.config, options.descriptor, options.onAuthorizationResponse),
|
||||
moduleId: options.descriptor.id,
|
||||
permissions: Object.freeze({ has: (permissionId: string) => granted.has(permissionId) }),
|
||||
principal: options.principal,
|
||||
|
||||
Reference in New Issue
Block a user