feat(artifacts): capture Claude Docs docs and session documents, claim unowned rows

- A Claude Docs `batch` that creates a doc is captured like an `Artifact`
  publish, titled by the doc's name and linked by its own frame URL.
- At Stop/SessionEnd, each pptx/docx/xlsx/pdf/html a workspace session
  created or changed is snapshotted into its owner's library (`auto`);
  an unchanged file is skipped, a changed one refreshes its snapshot.
- Server mode: a page with no owner carries a suggested owner (the
  workspace or home its session ran in). The suggested user claims or
  declines it; an admin claims or assigns any. New tab Unowned /
  Is this yours? on the Artifacts page; all three actions audited.
This commit is contained in:
2026-10-23 08:33:55 +07:00
parent 241e19b713
commit 62b4520507
14 changed files with 736 additions and 44 deletions
+29
View File
@@ -38,6 +38,7 @@ const STATUS = {
EMARKETFETCH: 502,
ENEEDLOGIN: 502,
ETOOBIG: 413,
EOWNED: 409,
};
function sendError(res, err) {
@@ -362,6 +363,34 @@ router.post(
})
);
// A row nobody owns: its suggested user says "mine" or "not mine"; an admin
// takes it or gives it to someone (artifacts.js `claim`/`decline`/`assign`).
router.post(
"/:id/claim",
sameOriginGuard,
wrap((req, res) => {
const item = artifacts.claim(req, req.params.id);
changed(item);
res.json({ item });
})
);
router.post(
"/:id/decline",
sameOriginGuard,
wrap((req, res) => res.json(artifacts.decline(req, req.params.id)))
);
router.post(
"/:id/assign",
sameOriginGuard,
wrap((req, res) => {
const item = artifacts.assign(req, req.params.id, req.body?.userId);
changed(item);
res.json({ item });
})
);
router.post(
"/:id/uninstall",
sameOriginGuard,