From 9bf49b75744e8066f45c751d3e809fa3b379554c Mon Sep 17 00:00:00 2001 From: Juan Castro Date: Fri, 21 Aug 2026 10:20:05 -0400 Subject: [PATCH 1/2] docs(perms): drop the app-root-dir raw string, wire the perms playground `app-root-dir:` was listed among the raw permission strings, but it reads as nothing during a permission check - the rewriter yields the sentinel outside a grant, so `check()` reports it ungranted even once it is and `request()` prompts every call. Both contradict what the same page promises. The `'appRootDir'` resource is the supported path and asks the server instead; the list now says so rather than implying the string behaves like its neighbours. The playground listed no perms examples at all: six files existed but nothing referenced them in examples.js, so a freshly-reshaped API shipped with nothing runnable. Adds a Perms group after UI, matching the sidebar's order, and two examples for the features that had none - one prompt covering several resources, and check() deciding whether to prompt. --- src/docs/src/Perms/request.md | 3 +- src/docs/src/examples.js | 53 +++++++++++++++++++ .../src/playground/examples/perms-check.html | 23 ++++++++ .../examples/perms-request-batch.html | 20 +++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/docs/src/playground/examples/perms-check.html create mode 100644 src/docs/src/playground/examples/perms-request-batch.html diff --git a/src/docs/src/Perms/request.md b/src/docs/src/Perms/request.md index 776d7e982..4bbe4c0b6 100644 --- a/src/docs/src/Perms/request.md +++ b/src/docs/src/Perms/request.md @@ -62,10 +62,11 @@ The array form resolves to an array of those values, in the order asked. - File system: `fs:{path}:{read|write}` - Apps: `apps-of-user:{uuid}:{read|write}` - Subdomains: `subdomains-of-user:{uuid}:{read|write}` -- An app's root directory: `app-root-dir:{app_uid}:{read|write}` Some permission strings are not supported and are denied silently. +An app's root directory has no raw form: `app-root-dir:` reads as nothing during a permission check, so asking for it this way would prompt on every call and [`check()`](/Perms/check/) would report it as not granted even once it is. Use the `'appRootDir'` resource, which asks the server directly. + A lone string that names no resource is treated as a permission string, so `puter.perms.request('fs:/user/Documents:read')` keeps working. ## Batching diff --git a/src/docs/src/examples.js b/src/docs/src/examples.js index f71e041a1..60a2c1328 100644 --- a/src/docs/src/examples.js +++ b/src/docs/src/examples.js @@ -715,6 +715,59 @@ const examples = [ }, ], }, + { + title: 'Perms', + children: [ + { + title: "Request the user's email", + description: "Request access to the user's email address with Puter.js permissions API. Run and experiment with this example directly in the playground.", + slug: 'perms-request-email', + source: '/playground/examples/perms-request-email.html', + }, + { + title: 'Request folder access', + description: 'Request write access to a special folder with Puter.js permissions API. Run and modify this example instantly in your browser.', + slug: 'perms-request-folder', + source: '/playground/examples/perms-request-folder.html', + }, + { + title: 'Request several at once', + description: 'Request everything your app needs under a single prompt with Puter.js permissions API. Run and experiment with this batch example in the playground.', + slug: 'perms-request-batch', + source: '/playground/examples/perms-request-batch.html', + }, + { + title: 'Check without prompting', + description: 'Check whether access is already granted before asking for it with Puter.js permissions API. Run and modify this example in the playground.', + slug: 'perms-check', + source: '/playground/examples/perms-check.html', + }, + { + title: "Request access to the user's apps", + description: "Request read access to the user's apps with Puter.js permissions API. Run and experiment with this example directly in the playground.", + slug: 'perms-request-apps', + source: '/playground/examples/perms-request-apps.html', + }, + { + title: "Request access to the user's subdomains", + description: "Request write access to the user's subdomains with Puter.js permissions API. Run and modify this example instantly in your browser.", + slug: 'perms-request-subdomains', + source: '/playground/examples/perms-request-subdomains.html', + }, + { + title: "Use another app's data", + description: "Request permission to use another app's key-value data with Puter.js permissions API. Run and experiment with this example in the playground.", + slug: 'perms-request-app-data', + source: '/playground/examples/perms-request-app-data.html', + }, + { + title: 'Request a raw permission string', + description: 'Request a specific permission string with Puter.js permissions API. Run and modify this example directly in your browser.', + slug: 'perms-request-permission', + source: '/playground/examples/perms-request-permission.html', + }, + ], + }, { title: 'Workers', children: [ diff --git a/src/docs/src/playground/examples/perms-check.html b/src/docs/src/playground/examples/perms-check.html new file mode 100644 index 000000000..ad1d6adee --- /dev/null +++ b/src/docs/src/playground/examples/perms-check.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/src/docs/src/playground/examples/perms-request-batch.html b/src/docs/src/playground/examples/perms-request-batch.html new file mode 100644 index 000000000..0adc5e811 --- /dev/null +++ b/src/docs/src/playground/examples/perms-request-batch.html @@ -0,0 +1,20 @@ + + + + + + + From e7be457a56b09c850ae6613482b5fbd896280be7 Mon Sep 17 00:00:00 2001 From: Juan Castro Date: Fri, 21 Aug 2026 11:26:32 -0400 Subject: [PATCH 2/2] docs: redirect the retired perms pages, add the missing playground examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both were left as follow-ups on the previous commit. Thirteen `puter.perms` method pages went when the surface collapsed onto `request(resource, details)`, and `requestAppData` moved to `/Perms/appData`. All fourteen had shipped, so an external link or a bookmark landed on nothing. The build already generates meta-refresh redirects from a map; they are entries in it now. Pages that only ever existed on the branch that removed them are deliberately absent — nobody can hold a link to a URL that was never published. Six documented APIs annotated a code block with a playground id but had no example file behind it, so the build warned on every one and the Try-it link resolved to nothing: `fs.share`, `fs.unshare`, `fs.listShared`, `fs.getShares`, `ai.txt2speech` with Speechify, and `ui.showFeedbackDialog`. The files are the documented blocks themselves, extracted rather than rewritten, so the example and the page it appears on cannot drift. Each is indexed in `examples.js` beside its siblings. The build now runs clean: 12 warnings to none. --- src/docs/src/examples.js | 36 +++++++++++++++++++ .../examples/ai-txt2speech-speechify.html | 19 ++++++++++ .../src/playground/examples/fs-getShares.html | 16 +++++++++ .../playground/examples/fs-listShared.html | 14 ++++++++ .../src/playground/examples/fs-share.html | 15 ++++++++ .../src/playground/examples/fs-unshare.html | 14 ++++++++ .../examples/ui-show-feedback-dialog.html | 14 ++++++++ src/docs/src/redirects.js | 20 +++++++++++ 8 files changed, 148 insertions(+) create mode 100644 src/docs/src/playground/examples/ai-txt2speech-speechify.html create mode 100644 src/docs/src/playground/examples/fs-getShares.html create mode 100644 src/docs/src/playground/examples/fs-listShared.html create mode 100644 src/docs/src/playground/examples/fs-share.html create mode 100644 src/docs/src/playground/examples/fs-unshare.html create mode 100644 src/docs/src/playground/examples/ui-show-feedback-dialog.html diff --git a/src/docs/src/examples.js b/src/docs/src/examples.js index 60a2c1328..7a86913ae 100644 --- a/src/docs/src/examples.js +++ b/src/docs/src/examples.js @@ -193,6 +193,12 @@ const examples = [ slug: 'ai-txt2speech-elevenlabs', source: '/playground/examples/ai-txt2speech-elevenlabs.html', }, + { + title: 'Text to Speech with Speechify', + description: 'Generate speech with Speechify voices using Puter.js AI API. Run and experiment with this TTS example in the playground.', + slug: 'ai-txt2speech-speechify', + source: '/playground/examples/ai-txt2speech-speechify.html', + }, { title: 'Text to Speech with Gemini', description: 'Generate speech with Gemini voices using Puter.js AI API. Run and experiment with this TTS example in the playground.', @@ -378,6 +384,30 @@ const examples = [ slug: 'fs-delete-directory', source: '/playground/examples/fs-delete-directory.html', }, + { + title: 'Share a file', + description: 'Share a file with another user using Puter.js filesystem API. Run and experiment with this sharing example in the playground.', + slug: 'fs-share', + source: '/playground/examples/fs-share.html', + }, + { + title: 'Stop sharing a file', + description: 'Revoke a share with Puter.js filesystem API. Run and modify this example instantly in your browser.', + slug: 'fs-unshare', + source: '/playground/examples/fs-unshare.html', + }, + { + title: 'List what is shared with you', + description: 'List items other people have shared with you using Puter.js filesystem API. Run and experiment with this example in the playground.', + slug: 'fs-listShared', + source: '/playground/examples/fs-listShared.html', + }, + { + title: 'See who a file is shared with', + description: 'List the shares on one of your own files with Puter.js filesystem API. Run and modify this example in your browser.', + slug: 'fs-getShares', + source: '/playground/examples/fs-getShares.html', + }, ], }, { @@ -713,6 +743,12 @@ const examples = [ slug: 'ui-set-menubar', source: '/playground/examples/ui-set-menubar.html', }, + { + title: 'Feedback dialog', + description: 'Collect feedback with the built-in dialog from the Puter.js UI API. Run and experiment with this example directly in the playground.', + slug: 'ui-show-feedback-dialog', + source: '/playground/examples/ui-show-feedback-dialog.html', + }, ], }, { diff --git a/src/docs/src/playground/examples/ai-txt2speech-speechify.html b/src/docs/src/playground/examples/ai-txt2speech-speechify.html new file mode 100644 index 000000000..1f17accce --- /dev/null +++ b/src/docs/src/playground/examples/ai-txt2speech-speechify.html @@ -0,0 +1,19 @@ + + + + + + + diff --git a/src/docs/src/playground/examples/fs-getShares.html b/src/docs/src/playground/examples/fs-getShares.html new file mode 100644 index 000000000..43c71f4b8 --- /dev/null +++ b/src/docs/src/playground/examples/fs-getShares.html @@ -0,0 +1,16 @@ + + + + + + diff --git a/src/docs/src/playground/examples/fs-listShared.html b/src/docs/src/playground/examples/fs-listShared.html new file mode 100644 index 000000000..371f1428a --- /dev/null +++ b/src/docs/src/playground/examples/fs-listShared.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/docs/src/playground/examples/fs-share.html b/src/docs/src/playground/examples/fs-share.html new file mode 100644 index 000000000..2de299a13 --- /dev/null +++ b/src/docs/src/playground/examples/fs-share.html @@ -0,0 +1,15 @@ + + + + + + diff --git a/src/docs/src/playground/examples/fs-unshare.html b/src/docs/src/playground/examples/fs-unshare.html new file mode 100644 index 000000000..511681983 --- /dev/null +++ b/src/docs/src/playground/examples/fs-unshare.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/docs/src/playground/examples/ui-show-feedback-dialog.html b/src/docs/src/playground/examples/ui-show-feedback-dialog.html new file mode 100644 index 000000000..82c60807b --- /dev/null +++ b/src/docs/src/playground/examples/ui-show-feedback-dialog.html @@ -0,0 +1,14 @@ + + + + + + + diff --git a/src/docs/src/redirects.js b/src/docs/src/redirects.js index 19d2aa289..f25a26d13 100644 --- a/src/docs/src/redirects.js +++ b/src/docs/src/redirects.js @@ -1,5 +1,25 @@ const redirects = { '/Introduction': '/', + + // `puter.perms` collapsed one-method-per-task into `request(resource, + // details)`, so these pages went. Every one of them shipped, which is the + // reason for the redirect: an external link or a bookmark would otherwise + // land on nothing. Pages that only ever existed on the branch that removed + // them are deliberately absent — nobody could have a link to those. + '/Perms/requestAppData': '/Perms/appData', + '/Perms/requestEmail': '/Perms/request', + '/Perms/requestManageApps': '/Perms/request', + '/Perms/requestManageSubdomains': '/Perms/request', + '/Perms/requestReadApps': '/Perms/request', + '/Perms/requestReadDesktop': '/Perms/request', + '/Perms/requestReadDocuments': '/Perms/request', + '/Perms/requestReadPictures': '/Perms/request', + '/Perms/requestReadSubdomains': '/Perms/request', + '/Perms/requestReadVideos': '/Perms/request', + '/Perms/requestWriteDesktop': '/Perms/request', + '/Perms/requestWriteDocuments': '/Perms/request', + '/Perms/requestWritePictures': '/Perms/request', + '/Perms/requestWriteVideos': '/Perms/request', }; module.exports = redirects;