infocyph / pathwise
High-level PHP filesystem workflows powered by Flysystem, including safe I/O, uploads, downloads, archives, directory synchronization, retention, policy enforcement, auditing and storage adapters.
Requires
- php: >=8.4
- ext-fileinfo: *
- league/flysystem: ^3.35.2
- psr/log: ^3.0.2
Requires (Dev)
- infocyph/phpforge: dev-main@dev
Suggests
- ext-posix: required if you want to use permissions.
- ext-simplexml: required if you want to use XML parsing.
- ext-xmlreader: required if you want to use XML parsing.
- ext-zip: required if you want to use compression.
- league/flysystem-async-aws-s3: required for AsyncAWS S3 adapter support.
- league/flysystem-aws-s3-v3: required for AWS S3 adapter support.
- league/flysystem-azure-blob-storage: required for Azure Blob Storage adapter support.
- league/flysystem-ftp: required for FTP adapter support.
- league/flysystem-google-cloud-storage: required for Google Cloud Storage adapter support.
- league/flysystem-gridfs: required for MongoDB GridFS adapter support.
- league/flysystem-memory: required for in-memory adapter support.
- league/flysystem-path-prefixing: required for path-prefixing adapter wrapper support.
- league/flysystem-read-only: required for read-only adapter wrapper support.
- league/flysystem-sftp-v2: required for SFTP (v2) adapter support.
- league/flysystem-sftp-v3: required for SFTP (v3) adapter support.
- league/flysystem-webdav: required for WebDAV adapter support.
- league/flysystem-ziparchive: required for ZipArchive adapter support.
Provides
None
Conflicts
None
Replaces
None
README
Pathwise 4 is a framework-neutral PHP 8.4+ filesystem toolkit built on Flysystem 3. It combines safe local file operations with instance-scoped storage topology, hardened upload/download pipelines, archive controls, file-backed queueing, observability, retention, indexing, policy enforcement, and bounded native execution.
Requirements
- PHP
>=8.4 ext-fileinfoleague/flysystem ^3.35.2psr/log ^3.0.2
ZIP, POSIX ownership, XML parsing, and remote Flysystem adapters are optional capabilities. Install only the extensions/adapters your application uses.
composer require infocyph/pathwise:^4.0
Storage topology
Use StorageContext for applications, workers, long-lived runtimes, or any process that can host more than one storage topology. Contexts do not register process-global mounts.
use Infocyph\Pathwise\Storage\StorageContext; $storage = new StorageContext([ 'primary' => ['driver' => 'local', 'root' => '/srv/app/storage'], 'archive' => ['driver' => 'local', 'root' => '/srv/app/archive'], ], 'primary'); [$filesystem, $location] = $storage->resolve('archive://reports/q1.txt'); $filesystem->write($location, "ready\n"); $local = $storage->localPath('documents/readme.txt');
StorageFactory::createFilesystem() remains the stateless constructor for built-in/official Flysystem adapters. Custom driver factories belong to a StorageContext, not a global registry.
File and directory operations
use Infocyph\Pathwise\PathwiseFacade; $file = PathwiseFacade::at('/tmp/example.txt')->file(); $file->create("v1\n")->append("v2\n"); $report = PathwiseFacade::at('/tmp/source') ->directory() ->syncTo('/tmp/backup', deleteOrphans: true);
The facade is stateless convenience. Persistent storage topology belongs to StorageContext.
Framework-neutral uploads
use Infocyph\Pathwise\StreamHandler\MalwareScanMode; use Infocyph\Pathwise\StreamHandler\UploadProcessor; use Infocyph\Pathwise\StreamHandler\UploadSource; $uploader = new UploadProcessor(); $uploader->setStorageContext($storage); $uploader->setDirectorySettings('primary://uploads', tempDir: sys_get_temp_dir()); $uploader->setValidationProfile('document'); $uploader->setMalwareScanMode(MalwareScanMode::REQUIRED); $uploader->setMalwareScanner($scanner); $source = UploadSource::fromMover( mover: fn (string $target): void => $uploadedFile->moveTo($target), clientFilename: $uploadedFile->getClientFilename() ?? 'upload.bin', size: $uploadedFile->getSize(), clientMediaType: $uploadedFile->getClientMediaType(), error: $uploadedFile->getError(), ); $path = $uploader->ingestSource($source);
Pathwise owns the staging file created for UploadSource, cleans it on success/failure, scans before content parsing, and fails closed when malware scanning is required.
Secure downloads and ranges
use Infocyph\Pathwise\StreamHandler\DownloadProcessor; $downloads = new DownloadProcessor(); $downloads->setStorageContext($storage); $downloads->setAllowedRoots(['primary://downloads']); $prepared = $downloads->prepareDownload( 'primary://downloads/video.mp4', rangeHeader: $_SERVER['HTTP_RANGE'] ?? null, ); foreach ($downloads->streamChunks($prepared) as $chunk) { echo $chunk; }
DownloadPreparation carries status/headers/range metadata. streamChunks() revalidates the preparation, reads exactly the prepared range, and closes the source stream even when iteration ends early.
Durable local file queue
use Infocyph\Pathwise\Queue\FileJobQueue; $queue = new FileJobQueue('/var/lib/app/jobs.json'); $queue->enqueue('thumbnail', ['id' => 'asset-42']); $reservation = $queue->reserve(); if ($reservation !== null) { // Work with $reservation->payload, renew long jobs when required. $queue->acknowledge($reservation); }
The queue is intentionally direct-local: it uses typed opaque leases, stale-worker rejection, strict versioned state, locking, and crash-safe persistence. It is not a distributed broker.
Security model
Pathwise 4 includes explicit controls for:
- extension/MIME/signature validation and optional malware scanning;
- path/root restrictions, hidden-file blocking, safe symlink management;
- ZIP manifest validation, traversal/collision/special-entry rejection and extraction limits;
- bounded native commands with timeout/output ceilings and deterministic cleanup;
- safe serialization boundaries that do not instantiate untrusted objects;
- queue state size/payload/job limits and lease ownership;
- policy enforcement, audit sinks, retention, indexing, and watcher workloads.
Security-sensitive behavior is fail-closed where a configured capability is required. Adapter/native/metadata capabilities remain explicit rather than silently emulated.
Security
Do not disclose suspected vulnerabilities in a public issue, discussion or pull request. Follow SECURITY.md and use GitHub private vulnerability reporting.
Pathwise is protected by PHPForge, which provides automated tests, static and taint analysis, dependency auditing, architecture checks and release-readiness gates. Automated controls do not replace responsible disclosure or manual review.
Made with ❤️ for the PHP communityMIT Licensed
Documentation • Security • Code of Conduct • Contributing
🗂️ Bug • Feature • Documentation • Question • CI failure
🔀 General • Bug fix • Feature • Refactor • Performance • Security & reliability • Documentation • Maintenance