feat: centralize application framework primitives
Quality / quality (ubuntu-latest) (push) Failing after 14m38s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-22 23:07:46 +05:30
parent 96e082b943
commit a3ddd39b7b
73 changed files with 1429 additions and 84 deletions
+52 -10
View File
@@ -10,6 +10,27 @@ import type { AuthzScope } from "./types.ts";
*/
export const AUTHZ_LOCALS_KEY = "_authz";
export interface AuthorizationResponses {
forbidden(decision?: AuthorizationDecision, options?: { exposeReason?: boolean }): Response;
notFoundOrForbidden(options?: {
mayDiscover?: boolean;
decision?: AuthorizationDecision;
exposeReason?: boolean;
}): Response;
}
export interface RequestAuthorization extends AuthorizationResponses {
can(permission: string, resource?: unknown): Promise<boolean>;
decide(permission: string, resource?: unknown): Promise<AuthorizationDecision>;
}
declare module "@wrnexus/core" {
interface Context {
/** Installed by authzMiddleware for handlers that prefer context-local authorization. */
authz?: RequestAuthorization;
}
}
interface RequestAuthz {
resolver: AuthzResolver;
/**
@@ -49,10 +70,39 @@ export function authzMiddleware(options: AuthzResolverOptions): Middleware {
byValue: new Map(),
};
ctx.locals[AUTHZ_LOCALS_KEY] = request;
ctx.authz = {
can: (permission, resource) => can(ctx, permission, resource),
decide: (permission, resource) => decideFor(ctx, permission, resource),
forbidden: (decision, responseOptions) =>
forbiddenResponse(decision, responseOptions?.exposeReason),
notFoundOrForbidden: (responseOptions = {}) =>
responseOptions.mayDiscover
? Response.json(
{ ok: false, error: "Not Found" },
{ status: 404, headers: NO_STORE_HEADERS },
)
: forbiddenResponse(responseOptions.decision, responseOptions.exposeReason),
};
return next();
};
}
function forbiddenResponse(decision?: AuthorizationDecision, exposeReason = false): Response {
return Response.json(
exposeReason
? { ok: false, error: "Forbidden", reason: decision?.reason, policy: decision?.policy }
: { ok: false, error: "Forbidden" },
{ status: 403, headers: NO_STORE_HEADERS },
);
}
export function getRequestAuthorization(ctx: Context): RequestAuthorization {
if (!ctx.authz) {
throw new Error("WRN-AUTHZ-SETUP: authzMiddleware() is not registered for this request.");
}
return ctx.authz;
}
/**
* Read the tenant from the context at decision time, not at middleware time:
* a request that switches tenant mid-flight must not keep the old scope.
@@ -236,10 +286,7 @@ export function guardPermission(permission: string, options: GuardOptions = {}):
reason: "Resource unavailable",
at: Date.now(),
});
return Response.json(
{ ok: false, error: "Forbidden" },
{ status: 403, headers: NO_STORE_HEADERS },
);
return forbiddenResponse();
}
}
@@ -264,12 +311,7 @@ export function guardPermission(permission: string, options: GuardOptions = {}):
);
}
return Response.json(
options.exposeReason
? { ok: false, error: "Forbidden", reason: result.reason, policy: result.policy }
: { ok: false, error: "Forbidden" },
{ status: 403, headers: NO_STORE_HEADERS },
);
return forbiddenResponse(result, options.exposeReason);
};
}