perf(permission): resolve default grants through full-access issuers (#4361)

This commit is contained in:
Daniel Salazar authored and GitHub committed 2026-10-26 22:03:45 -07:00
1 parent b7a0276337
commit cf5d2c60a5
3 files changed
+42 -8

No files matched your search

@@ -195,7 +195,13 @@ describe('check on default grants', () => {
it('answers a default grant without reading the scan cache', async () => {
const getScanCache = vi.spyOn(server.stores.permission, 'getScanCache');
try {
for (const actor of [actors.user, actors.looseUser, actors.app]) {
// A full-access token holds its issuer's defaults.
for (const actor of [
actors.user,
actors.looseUser,
actors.app,
actors.fullToken,
]) {
expect(
await permService.check(
actor,
@@ -211,10 +217,7 @@ describe('check on default grants', () => {
actors.scopedToken,
'service:puter-chat-completion:ii:puter-chat-completion',
],
[
actors.fullToken,
'service:puter-chat-completion:ii:puter-chat-completion',
],
[actors.fullToken, `fs:${fileUid}:read`],
[actors.app, 'feature:something'],
[actors.user, `fs:${fileUid}:read`],
] as const) {
@@ -2113,6 +2113,31 @@ describe('PermissionService — scan paths', () => {
).toBe(false);
});
it('answers default grants for full-access tokens without reading the scan cache', async () => {
const { actor } = await makeGroupedUser();
const token: Actor = {
user: actor.user,
accessToken: {
uid: `tok-${uuidv4()}`,
issuer: actor,
authorized: null,
fullAccess: true,
},
};
const get = vi.spyOn(server.clients.redis, 'get');
try {
expect(
await permService.check(
token,
'service:puter-kvstore:ii:puter-kvstore',
),
).toBe(true);
expect(get).not.toHaveBeenCalled();
} finally {
get.mockRestore();
}
});
it('a full-access token resolves anything its issuer holds, and nothing more', async () => {
const { row, actor } = await makeGroupedUser();
const held = `zztest:full-${uuidv4()}:ii:read`;
@@ -239,7 +239,10 @@ export class PermissionService extends PuterService {
permissionOptions: string | string[],
scanOptions?: ScanOptions,
): Promise<boolean> {
if (this.#heldByDefault(actor, permissionOptions)) return true;
const defaultActor = actor.accessToken?.fullAccess
? actor.accessToken.issuer
: actor;
if (this.#heldByDefault(defaultActor, permissionOptions)) return true;
const reading = await this.scan(
actor,
permissionOptions,
@@ -626,8 +629,11 @@ export class PermissionService extends PuterService {
// Account-management endpoints stay closed because they gate on actor
// type (requireUserActor / session cookie), not permissions.
if (actor.accessToken.fullAccess) {
for (const permission of options) {
const issuerReading = await this.scan(issuerActor, permission);
const issuerReadings = await Promise.all(
options.map((permission) => this.scan(issuerActor, permission)),
);
for (const [index, permission] of options.entries()) {
const issuerReading = issuerReadings[index];
reading.push({
$: 'path',
via: 'access-token',