From 4629b544e69e528d7fbe16edc6f0ca88f133484d Mon Sep 17 00:00:00 2001 From: Juan Castro Date: Tue, 6 Oct 2026 11:35:20 -0400 Subject: [PATCH] docs: say why AppDriver.select lists apps it does not own Reads as the same enumeration surface `/query/app` refuses to be, so write down that it is not: `/query/app` answers for apps the caller names, which is why it must not confirm one it may not see. `select` is the listing a launcher reads, and a listing that hid every app but your own would not be one. Protected apps are still filtered by the permission check, and `user-can-edit` narrows it to the caller's own. A test already pins the behaviour by name; this is the reason behind it. --- src/backend/drivers/apps/AppDriver.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/backend/drivers/apps/AppDriver.js b/src/backend/drivers/apps/AppDriver.js index 4b09fa607..0837f130d 100644 --- a/src/backend/drivers/apps/AppDriver.js +++ b/src/backend/drivers/apps/AppDriver.js @@ -337,6 +337,13 @@ export class AppDriver extends PuterDriver { return this.#toClient(app, actor, { ...params, stats }); } + /** + * Paged app listing. Unlike `/query/app`, which answers only for apps named + * by the caller and so must not confirm ones it may not see, this is the + * listing surface a launcher reads: `protected` apps are filtered by the + * permission check below, and everything else is listable by design. Narrow + * it with `predicate: ['user-can-edit']` to the caller's own. + */ async select(args = {}) { const { predicate, params = {} } = args; const actor = this.#requireActor();