fix(artifacts): a page published from its session's scratchpad keeps a viewable copy

The Artifact tool writes a page into the session's own Claude Code
scratchpad by default (<tmp>/claude-<uid>/<project>/<session>/scratchpad),
but pageCopy took the file only from the workspace folder, so such a page
got no copy and Preview said "the file ... is gone" while it was still there.

pageCopy now also accepts that ONE scratchpad, named from the publishing
session's id, its cwd and the workspace account's uid; before reading,
each of its four folders must be a real directory of that account, and each
file is realpath-confined, opened O_NOFOLLOW and must be a regular file of
that uid. Supporting files come only from the page's own root. The older-
page backfill (POST /api/artifacts/:id/copy) uses the session's cwd too.
The noCopy message now says the file may also lie outside both.
This commit is contained in:
2026-11-05 11:20:34 +07:00
parent 2a31537b80
commit c356cf96a1
6 changed files with 215 additions and 26 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ One place to keep what agents PRODUCE, and (in server mode) to share it:
| `plugin` | A plugin by marketplace source + name (no files) | picked from the list a marketplace link answers (`POST /api/artifacts/plugin/inspect`), or typed as `name@marketplace` |
- **Local mode:** one personal library, no sharing UI.
- **Server mode:** every artifact is the OWNER's and private by default. The owner can **Share** it with everyone — it appears in the **Hub** for every signed-in user — or with chosen people only (`artifact_shares`; they find it under **Shared with you**). A `page` keeps a viewable copy — its HTML file, or the copy Claude exports of a Doc / Slides / Design (`artifacts-export/`) — so the people it is shared with need no access to the claude.ai account that published it. A shared skill or plugin can be **installed** into the viewer's own account.
- **Server mode:** every artifact is the OWNER's and private by default. The owner can **Share** it with everyone — it appears in the **Hub** for every signed-in user — or with chosen people only (`artifact_shares`; they find it under **Shared with you**). A `page` keeps a viewable copy — its HTML file (from the workspace folder, or from the publishing session's own Claude Code scratchpad, where the Artifact tool writes a page by default), or the copy Claude exports of a Doc / Slides / Design (`artifacts-export/`) — so the people it is shared with need no access to the claude.ai account that published it. A shared skill or plugin can be **installed** into the viewer's own account.
## Rules (binding, same spirit as CLAUDE.md)