Skip to content

Commit d646809

Browse files
committed
chore(rbac): keep the delegated-token invariant, drop the essay
1 parent 79482de commit d646809

2 files changed

Lines changed: 6 additions & 14 deletions

File tree

internal-packages/rbac/src/fallback.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ import type { PrismaClient } from "@trigger.dev/database";
2222
import { buildFallbackAbility, buildJwtAbility, permissiveAbility } from "./ability.js";
2323
import { BearerCredentialResolver } from "./bearerCredentials.js";
2424

25-
// What a user-actor token with no declared cap can do without a plugin. Reads
26-
// only: writes need a role the fallback can't resolve, and denying everything
27-
// would break the token's own JWT exchange (gated on `read:apiKeys`).
25+
// Reads only: a capless token still has to reach its own JWT exchange (gated on `read:apiKeys`).
2826
const CAPLESS_USER_ACTOR_SCOPES = ["read:all"];
2927

3028
export type FallbackPrismaClients = {
@@ -218,9 +216,7 @@ class RoleBaseAccessFallbackController implements RoleBaseAccessController {
218216
organizationId: context.organizationId ?? "",
219217
projectId: context.projectId,
220218
},
221-
// A delegated token is a downgrade of the user, so it never gets the
222-
// blanket ability a PAT gets here: its own cap, or read-only when it
223-
// declares none (a capless token still has to reach the JWT exchange).
219+
// A delegated token is a downgrade of the user: never the blanket ability a PAT gets here.
224220
ability: buildJwtAbility(claims.cap ?? CAPLESS_USER_ACTOR_SCOPES),
225221
};
226222
}

packages/plugins/src/rbac.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ export type RbacSubject =
8888
userId: string;
8989
client?: string;
9090
// The environment the token was signed for, when it carries the claim.
91-
// Carried on the subject so an authorization path can't lose it.
9291
environmentId?: string;
9392
organizationId: string;
9493
projectId?: string;
@@ -399,10 +398,8 @@ export type UserActorAuthResult =
399398
| {
400399
ok: true;
401400
userId: string;
402-
// The verified claims, so the caller gets the token's environment scope
403-
// with the identity instead of re-deriving it. Optional only because a
404-
// plugin built against an older contract can't return it — a host that
405-
// enforces the environment claim must fail closed on its absence.
401+
// Optional only for plugins built against an older contract: a host enforcing the
402+
// environment claim must fail closed when it is absent.
406403
claims?: UserActorClaims;
407404
subject: RbacSubject;
408405
ability: RbacAbility;
@@ -453,9 +450,8 @@ export interface RoleBaseAccessController {
453450
// user: floor = the user's role in the target org (rejects non-members,
454451
// like authenticatePat), cap = the token's optional scope cap.
455452
//
456-
// No plugin installed → the fallback verifies the token and builds the
457-
// ability from the token's own cap (read-only when it declares none). A
458-
// delegated token never gets the blanket ability the fallback gives a PAT.
453+
// No plugin installed → the fallback builds the ability from the token's own cap
454+
// (read-only when it declares none), never the blanket ability it gives a PAT.
459455
authenticateUserActor(
460456
request: Request,
461457
context: { organizationId?: string; projectId?: string }

0 commit comments

Comments
 (0)