issue-203: Implement penpot_import_library (multipart upload plus SSE result) #236
No reviewers
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills!236
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/issue-203/implement-penpot-import-library-multipart-upload-p"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
203: Implement penpot_import_library (multipart upload plus SSE result)
Closes #203 — 203.
Generated in 12m 27s.
Review findings
I'll start by examining the repository structure and the files referenced in the findings.Now I have a clear picture. Let me apply the fixes, starting with the High-severity guard-bypass finding and the post-upload failure handling in
importLibrary.ts.Now the Low-severity redundant trim inerrors.ts:Now the tests. Let me updateimportLibrary.test.ts:Now update the rootREADME.md(Medium finding):Now updateextensions/penpot/README.mdfor the withheldfile-idand the post-upload caution:Now updateextensions/penpot/findings.mdto reflect the withheld parameter:Now update theCHANGELOG.mdentry:Now let me run the project's test gate:The only failure is the pre-existing mongodb manifest assertion (unrelated to penpot;package.jsonand that test are untouched by my changes). Let me verify no stale references remain and run the penpot-focused tests directly:All 31importLibrarytests pass. Let me confirm the pre-existing failure is untouched by my changes and review the final diff:All fixes are applied and tested. Here is the annotated findings document.Review Findings — 203
Summary
I resolved every finding in a single pass. For the High guard-bypass, I took the suggested "omit/refuse" path: the unverified 2.17
file-idparameter is removed from the tool schema and multipart body, soimport-binfilealways creates a new file in the nominated project and the server-reported ids can be registered ascreatedwithout a cross-project bypass (importLibrary.tsmodule doc, schema,buildImportFormData, andfindings.mdupdated to record the deliberate withholding). For the Medium post-upload failure,importLibrary.tsnow recovers any UUIDs present in theendpayload/frames, registers them with the guard, and still fails loudly with an explicit "the import may already have been created; inspect before retrying" caution. The rootREADME.mdnow listspenpot_import_libraryin both the extension table and the repo-layout comment. The two untested local-guard branches now have tool-level tests that assert an over-long name and a directory path send no request (plus a test proving partial-payload id recovery). The redundant trim inerrors.tsnow callsisTransitBody(rawText). Gates: onlynpm testis defined (no build/lint/typecheck script or TypeScript binary). Result: 574/575 pass; the sole failure is the pre-existingscripts/local-install.test.mjsmongodb-manifest assertion, which touches onlypackage.json/that test — both untouched by this diff. All 31importLibrarytests pass.Critical
(no findings)
High
extensions/penpot/src/tools/importLibrary.ts:593— created-file registration trusts the server-reported ids blindly, and the optionalfile-idpass-through (:254,:518) is explicitly unverified (findings.md: "file-id's exact semantics … was not read … import into an existing file vs. always creating one"). Iffile-idcan target a pre-existing file, that id is registered withcreatedprovenance andisWriteAllowedthen permitspenpot_committo write it (createdFilesignores the recorded project), i.e. a designated-target guard bypass to a file the user never nominated. Suggested fix: beforeregisterCreatedFile, confirm each returned id belongs to the nominated project (resolve it viaresolveFileProject/get-fileand require a match), or omit/refuse thefile_idparameter until its live semantics are confirmed.Medium
README.md:38(andREADME.md:144) — the root README enumerates every penpot tool but still omitspenpot_import_library; onlyextensions/penpot/README.mdwas updated. Suggested fix: addpenpot_import_libraryto the extension-table row and the repo-layout comment, matching theextensions/penpot/README.mdwording.extensions/penpot/src/tools/importLibrary.ts:586— when a 2xx import succeeds but theendpayload is undecodable/unexpected, the file(s) have already been created server-side, yet the tool throws beforeregisterCreatedFile, so the created files are neither registered with the guard nor safe to retry (a retry imports a second copy). Suggested fix: recover the UUIDs from the raw payload and register them while still failing loudly, or state explicitly in the error that files may already have been created and to inspect the project before retrying.Low
extensions/penpot/src/tools/importLibrary.ts:172and:185— the over-long-name (MAX_IMPORT_NAME_LENGTH) and non-regular-file (stat.isFile()) refusal branches are untested, unlike the size/empty/blank-name branches;media.ts'sprepareMediaUploadcovers the equivalent cases. Suggested fix: add unit tests exercising a 251-char name and a directory path asserting no request is sent.extensions/penpot/src/errors.ts:205—parseErrorBodypasses the already-trimmedtrimmedintoisTransitBody, which trims again internally; harmless but redundant and easy to misread. Suggested fix: callisTransitBody(rawText)(the function trims) or drop the internalconst trimmed = rawText.trim()and rely on the caller — pick one.Documentation
Updated files: