Skip to content

Documents Module — Production Readiness Audit

FieldValue
Date2026-08-17
Re-verified2026-08-17 (full open-finding remediation → 1.0.1)
StatusGo for production after migrate + uploads disk confirmation + Storage-first smoke
ScopeFree Marketplace opt-in documents 1.0.1 (hard dependency on storage)
Branchfeature/documents-module-mvp-b5f1
CompanionDocuments ops · Developer · User · API

PRs: Backend #117 · Frontend #112 · Docs #138 · Website #31


Executive summary

Documents is a flat internal file library (upload, flat categories, download, soft/force delete) on Storage quota. Catalog is free, not default-included, with a hard Storage dependency.

Audit open findings M2–M4 and L2 are remediated in 1.0.1. Notes/timeline/assignment remain intentional MVP deferrals (L1).

Go / No-Go: Go — engineering complete; ops completes migrate-only rollout, object-storage uploads disk, and staging smoke.

GateResult
Catalog: documents / operations / 1.0.1 / free / not defaultPass
Hard dependency Documents → StoragePass
Permissions sync + default role mapsPass (force.delete owner-only — intentional)
Quota on create / replace / restorePass
Soft-deleted disk lifecycle + trash purgePass (TrashPurgeRegistry + forceDeleting disk cleanup)
Force delete disk-before-DBPass (forceDeleting hook)
Platform audit create/update/delete/restore/forcePass
Multipart update via POST /documents/{id}Pass
Pest DocumentTestPass
Playwright headed DocumentsPass (prior 1.0.0 session; replace path still POST)
Docs + marketing free / availablePass
Notes / timeline / assign / nested foldersAccepted — deferred MVP (L1)

Remediation log (audit → fix)

IDWasFix
H1Restore could exceed Storage quotaassertCanStore on restore + Pest
M1No Pest for file replaceMultipart POST /documents/{id} Pest
M2Soft-deleted objects linger forever on diskDocument (+ category) in TrashPurgeRegistry; purge uses workspace trash.retention_days
M3DB force-delete before disk → orphan objectsDocument::forceDeleting deletes via FileUploadService before row removal (covers API + trash:purge-expired)
M4No platform audit for restore / force deletedocument_restored + document_force_deleted (Help Desk–style force flag)
L2True HTTP PUT multipart unreliableNamed POST documents/{id} twin (documents.update.post); SPA posts FormData without _method
D1No production-readiness pageThis page

Accepted / intentional

ItemNotes
L1 notes / timeline / assignmentDeferred flat-library MVP
force.delete not on admin defaultsOwner / custom grant (Assets / Vendors parity)
Soft-deleted show → not foundTrash list + restore / force remain
Concurrent soft over-quotaCheck-then-write; Storage class residual
Local uploads disk in non-prodProduction must use object storage

Security summary

ControlStatus
Tenant isolationPass
Module gate + Spatie permissions + policiesPass
File validation max 50 MB + mime allow-listPass
Download authzPass
Path / disk not in API resourcesPass
Trash purge removes objectsPass

Test evidence

SuiteResultNotes
php artisan test --compact tests/Feature/Tenant/Document/DocumentTest.php16 passed (81 assertions)create/list, categories, CRUD trash, download, quota, restore-over-quota, POST replace, audit restore/force, trash purge + disk, registry
npm run test:e2e:documents:headedPass (~47s prior)Re-run on staging after 1.0.1

Deploy order

  1. Deploy Backend (through 2026_08_17_100005 catalog bump to 1.0.1)
  2. php artisan migrate --force
  3. Confirm FILESYSTEM_UPLOADS_DISK + object-storage credentials
  4. Confirm scheduler runs trash:purge-expired daily (onOneServer)
  5. Deploy Frontend (multipart update POST)
  6. Deploy Docs / marketing
  7. Staging smoke → production

Suggested merge order: Backend → Frontend → Docs → Website.


Pre-flight checklist

#CheckOwnerPass?
1Migrations through Documents 100005 appliedOps
2Catalog documents version 1.0.1, free, not defaultOps
3module_dependencies Documents → StorageOps
4Uploads disk is object storageOps
5trash:purge-expired scheduledOps
6Pest Document suite green in CIEng
7Headed Playwright Documents on stagingQA
8Storage entitled before Documents installQA

Staging smoke (human)

  1. Install Documents without Storage → blocked
  2. Install Storage → Documents → upload / categorize / download
  3. Soft delete → used bytes drop → restore → bytes return
  4. Soft-delete → fill quota → restore blocked (STORAGE_QUOTA_EXCEEDED)
  5. Soft-delete → set retention 30 → age deleted_attrash:purge-expired removes DB row and object
  6. Force delete removes object; category delete blocked while docs reference it
  7. Multipart replace via POST /documents/{id} (no _method required)
  8. Platform audit: create, soft delete, restore, force delete

Rollback

  • Forward-fix only — do not migrate:rollback
  • Feature rollback = revert SPA/API deploys; catalog entitlements may remain

Sign-off

RoleNameDateDecision
Engineering☐ Prod Go
Ops (migrate + uploads disk + scheduler)
Product

Current decision (2026-08-17): Go — ship after migrate-only rollout, object-storage confirmation, and staging smoke.

Official documentation for the EloSync SaaS Platform.