fix(viewer): scope template routes under /w/<wsid>/ (close open global GET/DELETE)#180
Merged
Conversation
…l GET/DELETE) Code review of #179 found the template library's read/delete routes were ORIGIN-rooted and ungated: they sat above the /w/<wsid> dispatch with no wsid and no token. Because GET /templates returned every template id+name, any anonymous caller (the public demo shares the deployment's origin) could enumerate the whole global library and DELETE /template/<id> to wipe it — the "unguessable id gates it" comment was false. Fix: move list/get/delete under /w/<wsid>/ so the unguessable workspace id is the capability (consistent with clear/share), and exclude the read-only demo (isReadOnlyWsid) so the public showcase can't enumerate or mutate the library. Create was already wsid-scoped + demo-blocked. The library stays GLOBAL (any of your workspaces sees every template — cross-session reuse by id is preserved); only the access path is now gated. - server.ts: remove the top-level /templates and /template/<id> routes; add GET /w/<wsid>/templates and GET|DELETE /w/<wsid>/template/<id>, both demo-excluded; fix the misleading comment. - cli/template.ts: list/get/delete now use ${base} (…/w/<wsid>) instead of deriving the origin — simpler and matches the new routes. - client/viewer.ts: the Templates popover fetches ${apiBase}/templates and /template/<id>. Tests: server.test.ts gains a "template library" suite (create/list/get/delete, missing-board 404, 405, demo 403/404, origin-rooted routes gone, __templates__ not servable); CLI test asserts the wsid-scoped paths; template.e2e asserts the origin routes are gone + demo can't enumerate. Full chain: server 76, CLI 8, e2e rich 62 / board-sort 12 / template 14.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem (found in code review of #179)
The template library's read + delete routes were origin-rooted and ungated — they sat above the
/w/<wsid>dispatch with no wsid and no token. SinceGET /templatesreturned every template'sid+name, any anonymous caller could enumerate the whole global library andDELETE /template/<id>to wipe it. The deployed prod shares its origin with the public/w/demo/, so this was publicly reachable. The code comment "the unguessable id gates it" was false (the id was handed out by the catalog).Reproduced (before): anon
GET /templates→200(all ids), anonDELETE /template/<id>→204, library wiped.Fix
Move
list/get/deleteunder/w/<wsid>/so the unguessable workspace id is the capability (consistent withclear/share), and exclude the read-only demo (isReadOnlyWsid) so the public showcase can't enumerate or mutate it. Create was already wsid-scoped + demo-blocked. The library stays global (any of your workspaces sees every template — cross-session reuse by id preserved); only the access path is gated.server.ts: drop the top-level routes; addGET /w/<wsid>/templates+GET|DELETE /w/<wsid>/template/<id>, demo-excluded; fix the comment.cli/template.ts:list/get/deleteuse${base}(…/w/<wsid>) — drops the origin derivation.client/viewer.ts: popover fetches${apiBase}/templates+/template/<id>.Verification
Reproduced (after): anon
GET /templates→ 404, anonDELETE /template/<id>→ 404, demoGET /w/demo/templates→ 404, legitGET /w/<wsid>/templates→ 200, library count unchanged (not wiped).server.test.tsgains a template library suite (create/list/get/delete, missing-board 404, 405, demo 403/404, origin routes gone,__templates__not servable) → server 76; CLI 8 (wsid-scoped paths).template.e2eadds 3 auth-scoping assertions → 14/14; rich 62, board-sort 12.Follow-up to #179 (already merged/deployed); will redeploy on merge.