Critical fixes:
- L3625: Remove {e} from regex error message → generic message with hint
- L3857: Remove {e} from content error message → generic message with hint
High priority fixes:
- L2748: Remove path from FILE_LOCKED error details
- L4529: Remove path from PERMISSION_DENIED (delete) error details
- L4606: Remove path from PERMISSION_DENIED (rename) error details
- L4682: Remove path from PERMISSION_DENIED (lockedit) error details
All error messages now return minimal information to prevent
information disclosure about internal state or other users' activities.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Security fixes:
- Replace bare except with except Exception at L4691
- Sanitize str(e) in ~35 error responses to prevent info leakage
- Remove sensitive data (user_id, conv_id) from lock error messages
- Add None-safety to _get_user_root, _get_conv_id, _resolve_zone
Robustness fixes:
- Add cleanup for partial ZIP extraction on error
- Define module-level constants (BYTES_PER_MB, ZIP_MAX_*, etc.)
Code quality:
- Move ZIP bomb limits to module constants
- Use MAX_HEXDUMP_BYTES constant instead of magic number
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
- _patch_text_impl: Move editzone operations inside try block so lock
is released by finally if mkdir/copy/touch fails after acquisition
- _patch_bytes_impl: Same fix as _patch_text_impl for binary patching
- shed_lockedit_open: Wrap post-lock operations in try/except to release
lock on failure (mkdir, copy to editzone)
- shed_lockedit_save: Use try/finally after successful copy to ensure
lock is released even if git commit or cleanup fails
These fixes prevent locks from being permanently stuck when errors occur
between lock acquisition and the main try block.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Security fixes:
- Add explicit symlink detection in _resolve_chroot_path
- Fix TOCTOU race conditions in _patch_text_impl and _patch_bytes_impl
- Sanitize SQLite error messages to prevent information leakage
- Add finally:conn.close() to prevent SQLite connection leaks
- Add readonly check for output_csv in shed_sqlite
Code quality:
- Replace bare except with specific exceptions (OSError, UnicodeDecodeError, etc.)
- Translate French comments to English in shed_import
- Refactor shed_sqlite to use centralized _resolve_zone()
API improvements:
- Change safe=False to safe=True by default in patch_text/patch_bytes
- Change message='' to message=None in zone movement functions
Documentation:
- Add comprehensive error codes reference table to SPEC.md
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Updated functions with allow_zone_in_path parameter and zone_name validation:
- shed_tree (path)
- shed_zipinfo (path)
- shed_file_type (path)
- shed_hexdump (path)
- shed_force_unlock (path - both group and personal zones)
- shed_group_set_mode (path)
- shed_group_chown (path)
Also fixed zone_name consistency:
- Changed "group:{id}" to "Group:{id}" in _patch_text_impl and _patch_bytes_impl
- Changed "group:{group}" to "Group:{group}" in shed_copy_to_group
All zone names now consistently use capital letters (Storage, Documents,
Uploads, Group:) for internal discipline while accepting case-insensitive
input from users.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Extended zone_name validation to:
- shed_move_uploads_to_storage
- shed_move_uploads_to_documents
- shed_copy_storage_to_documents
- shed_move_documents_to_storage
These functions previously had NO path validation and could create
duplicate zone folders (e.g., Storage/Storage/file.txt).
Also updated shed_help documentation to list all functions supporting
allow_zone_in_path parameter.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Extended zone_name validation to:
- All 5 lockedit_* functions (open, exec, overwrite, save, cancel)
- shed_copy_to_group (validates both src_path and dest_path)
Also updated shed_help paths documentation to include lockedit_* in
the list of functions supporting allow_zone_in_path.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Refactored path validation to detect when paths start with the zone name
(e.g., "Documents/folder" in zone="documents"), which causes unwanted
directory duplication. The validation rejects such paths by default with
a helpful error message.
Changes:
- Added zone_name and allow_zone_in_path params to _validate_relative_path
- Refactored _validate_path_args to call _validate_relative_path
- Extracted _is_expression_not_path helper for cleaner code
- Updated shed_exec, shed_patch_text, shed_patch_bytes, shed_delete,
shed_rename to pass zone context and allow_zone_in_path parameter
- Updated _patch_text_impl and _patch_bytes_impl accordingly
LLMs can now set allow_zone_in_path=True if they intentionally want a
subfolder named after the zone.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
LLMs often mistakenly include the zone name in paths (e.g., zone="Documents"
with args=["Documents/folder"]) creating unwanted duplicate folders. Added
detailed explanation with concrete examples showing the mistake and its
consequence.
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
Warn users that files imported to Uploads are permanent and NOT deleted
when the conversation is deleted. They must be removed manually with
shed_delete(zone='uploads', path='...').
https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
Remind users that the source ZIP file remains in Uploads after extraction,
that Uploads files are NOT deleted when the conversation is deleted,
and suggest using shed_delete to remove it manually.
https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
Use canonical zone names with capital letters (Uploads, Storage, Documents)
in documentation, hints, and response data for consistency with the rest
of the codebase.
https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
Allow extracting ZIP files from Uploads zone without moving them first.
The new src_zone parameter accepts "uploads", "storage", or "documents"
while zone parameter remains the destination (storage/documents only).
Bump version to 1.0.2.
https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf