* feat(io): add pkg/io with symlink-safe path validation
- Add pkg/io with Medium interface for filesystem abstraction
- Add pkg/io/local with sandboxed filesystem implementation
- Add symlink-safe path validation to prevent bypass attacks
- Add sentinel errors (ErrPathTraversal, ErrSymlinkTraversal)
- Add NewSandboxed() for creating sandboxed Medium instances
- Add MockMedium for testing
Closes#169
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(io): extend Medium interface with Delete, Rename, List, Stat operations
Add missing filesystem operations to Medium interface:
- Delete(path) - removes file or empty directory
- DeleteAll(path) - removes path and contents recursively
- Rename(old, new) - moves or renames files/directories
- Exists(path) - checks if path exists
- IsDir(path) - checks if path is a directory
- List(path) - returns directory contents as []os.DirEntry
- Stat(path) - returns file info as os.FileInfo
Implements both local.Medium and MockMedium with full support.
Closes#102
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(io): MockMedium.Read returns os.ErrNotExist for consistency
Ensures os.IsNotExist(err) works with MockMedium like with real filesystem.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>