File Storage Reference Public

Reference

Developer and integrator reference for the ERPat File Storage module: database tables, controllers and routes, models, service libraries, cron jobs, dashboard widgets, config sidecars, permission keys, and system_logs event keys.

Guide version: r1 Module version: 1.0.0 Updated: 2026-07-30 Estimated time: 8 min 3 views

Orientation

File Storage (modules/FileStorage/, slug file_storage, module setting module_file_storage) is a logical layer over ERPat's shared general_files registry. It manages only its own logical files (file_nodes) and never surfaces or mutates files owned by other modules. Physical bytes reuse ERPat's local / AWS S3 pipeline (private objects, signed URLs).

Everything is multi-tenant: all rows live in the tenant database with no tenant_id column — isolation comes from the per-tenant connection. New rows end with the standard audit block (created_by, created_at, updated_at, deleted) and are soft-deleted.

app: file_storageadmin: file_storage_adminpublic: f/* client API: /api/v1/file-storageend-user API: /v1/api/file-storage

Data model — tables

Thirteen tenant-database tables. Every table filters deleted = 0 and carries the standard audit columns.

TablePurpose (one line)
file_spacesTeam Spaces — tenant-owned shared containers (department-synced membership, min. two managers).
file_nodesThe logical tree — folders and files owned by File Storage (the module's own view over storage).
file_versionsImmutable version history per file node; each version points at a general_files row.
general_file_referencesReference ledger linking logical files/versions to physical general_files bytes (drives reference-aware purge).
file_acl_entriesRole-based access grants on nodes/spaces (viewer → owner); inherited and computed server-side.
file_upload_sessionsIn-flight upload intake — validated staging consumed by the upload-pipeline cron.
file_activity_eventsActivity feed rows (per-node/space event stream shown in the Activity tab).
file_favoritesPer-user starred nodes (the Starred tab).
file_commentsThreaded comments on file nodes (R2 collaboration).
file_share_linksExternal share links — stores only the SHA-256 token hash, scope, expiry, max-opens, Argon2id password, OTP settings.
file_legal_holdsLegal-hold definitions that block permanent purge (fail-closed governance).
file_legal_hold_itemsThe specific nodes/versions bound to a legal hold.
Ownership is by construction: the general_files rows the module creates are owner-less to the rest of ERPat, so other modules' listings never see File Storage bytes and vice-versa.

Screens (tabs)

Workspace — FileStorage (one page, lazy tabs, never reloads)

TabShows
My FilesThe signed-in user's personal folder tree and files.
Team SpacesTenant-owned shared spaces the user can access.
Shared with MeFiles/folders granted to the user directly, by group, department, or tenant-wide.
RecentRecently touched files.
StarredFiles the user favorited (file_favorites).
TrashSoft-deleted items, recoverable via restore.
ActivityThe user-scoped activity feed.

Governance console — FileStorage_admin (separate admin page)

TabShows
PoliciesPurpose-policy registry and storage policy settings.
QuarantineUpload quarantine review queue.
Legal HoldsCreate and manage legal holds that block purge.
RiskRisk dashboard (populated by the risk-scan cron).

Controllers & routes

App workspace — FileStorage

Authenticated staff controller. Base URL prefix file_storage. Gated by module_file_storage and the file_storage permission.

Route prefixPurpose
file_storageWorkspace shell (lazy tabs listed above).

Governance console — FileStorage_admin

High-risk admin controller for the governance console. Base URL prefix file_storage_admin. Gated by the governance permission family.

Route prefixPurpose
file_storage_adminGovernance console (Policies, Quarantine, Legal Holds, Risk).

Public share pages — FileShare (GuestController)

Unauthenticated share-link surface. Only the SHA-256 token hash is stored server-side; scopes, expiry, atomic max-opens, Argon2id password, and email OTP are enforced here.

RoutePurpose
f/sShare-link landing (resolve token → gate on password/OTP/expiry/opens).
f/dDownload the shared file (only when the link scope permits downloads).
f/verifyVerify the link password gate.
f/otpEmail one-time-passcode gate for the link.
f/ruUpload-only file request — recipient submits files (upload_only scope).
f/requestFile-request landing (collect files through an upload-only link).
These routes are the module's only public surface. They never expose a raw storage URL — access is mediated by the token hash and the per-link gates.

Integration (client) API — FileStorage_api

Machine-to-machine API. Base path /api/v1/file-storage. Every action calls authorizeScope() as its first line; scopes are filestorage:read and filestorage:write.

Base pathScopesPurpose
/api/v1/file-storage/*filestorage:read, filestorage:writeIntegration access to logical files and folders (read/write gated per action).

End-user API — FileStorage_euapi

Self-service API for a signed-in end user. Base path /v1/api/file-storage. Every action runs requireModule('module_file_storage') + requirePermit(...) and resolves identity only through selfUserId().

EndpointPurpose
/v1/api/file-storage/listList the caller's own files/folders.
/v1/api/file-storage/viewView metadata for a file the caller owns/can access.
/v1/api/file-storage/downloadDownload a file the caller can access.
/v1/api/file-storage/recentThe caller's recent files.
/v1/api/file-storage/starredThe caller's starred files.
Identity is always the authenticated subject via selfUserId() — the end-user API cannot act on another user's files.

Models

Models extend Crud_model and hold all SQL. They map to the tables above (e.g. spaces, nodes, versions, references, ACL entries, upload sessions, activity events, favorites, comments, share links, legal holds). All queries filter deleted = 0 and are tenant-DB scoped.

Service libraries (libraries/)

Business logic lives in services so controllers stay thin. Each is a CI-loadable class.

ServiceResponsibility
File_registry_serviceBridges logical files to the shared general_files registry and the reference ledger.
File_node_serviceFolder/file tree operations — create, rename, move, trash, restore, star.
File_upload_serviceValidated intake — reuses ERPat's extension/MIME/magic-byte checks and stages upload sessions.
File_lifecycle_serviceVersioning, trash/restore, and reference-aware safe purge (fail-closed).
File_authorization_serviceComputes effective ACLs server-side with folder + space inheritance.
File_share_serviceCreates/validates share links — token hashing, scope, expiry, max-opens, password, OTP.
File_scanner_servicePluggable scanner hook (quarantine/CDR/AV integration point — no engine enabled today).
File_purpose_policyPurpose-policy registry — resolves storage policy for a file's declared purpose.
File_scanner_service is a hook only: real AV / content-disarm scanning is a future integration and is not active. Upload safety today rests on ERPat's existing validation pipeline.

Cron jobs

Advanced Cron jobs discovered from modules/FileStorage/jobs/. Each runs per-tenant and self-gates on module_file_storage.

SlugSchedulePurpose
file_storage_upload_pipelineevery 1 min (*/1)Processes validated upload sessions into logical files/versions.
file_storage_access_expirerevery 5 min (*/5)Expires share links / access grants past their expiry.
file_storage_membership_syncdailySyncs Team Space membership from department membership.
file_storage_registry_reconcilehourlyReconciles the reference ledger against the general_files registry.
file_storage_safe_purgedailyReference-aware permanent purge (blocked by active reference, current version, retention, or legal hold).
file_storage_risk_scandailyPopulates the Governance risk dashboard.

Dashboard widgets

WidgetPurpose
My Recent FilesQuick access to the user's most recently touched files.
Storage UsageAt-a-glance storage consumption for the user/tenant.
Both widgets are gated by module_file_storage + the file_storage permission.

Config sidecars (modules/FileStorage/config/)

FilePurpose
module_config.phpManage-Modules registration (module_key = file_storage).
routes.phpAll module routes — app, admin, and the public f/* share pages.
menu.phpLeft-menu slice under the "Storage" group.
default_menu.phpDefault-left-menu slice for the customization editor.
permissions.phpRBAC keys for the Roles editor (see below).
widgets.phpDashboard widget registry (My Recent Files, Storage Usage).
api_routes.php / euapi_routes.phpClient API (/api/v1/file-storage) and end-user API (/v1/api/file-storage) route DSL.
api_scope.phpOAuth scope catalog: filestorage:read, filestorage:write.
system_logs.phpAudit event-key registration.

Permission keys

Base CRUD plus sharing/space/request grants, plus a high-risk governance family.

KeyGrants
file_storageBase access to the module.
file_storage_createCreate folders/files.
file_storage_updateRename/move/version files.
file_storage_deleteTrash/restore/delete files.
file_storage_share_internalShare files with other ERPat users/groups.
file_storage_share_externalCreate external share links.
file_storage_manage_permissionsManage ACL grants on nodes/spaces.
file_storage_create_spaceCreate Team Spaces.
file_storage_manage_spaceManage Team Space settings/membership.
file_storage_create_file_requestCreate upload-only file requests.

Governance (high-risk)

KeyGrants
governance_view_activityView the governance activity/audit views.
governance_manage_quarantineReview and release/reject quarantined uploads.
governance_manage_policiesEdit purpose/storage policies.
governance_legal_holdCreate and manage legal holds.
governance_purgePerform reference-aware permanent purge.
The governance_* keys gate destructive and compliance-critical actions — grant them only to compliance/admin roles.

ACL roles

Role-based ACL entries on nodes/spaces, computed server-side with folder + space inheritance. From least to most privileged:

viewercommentercontributor editormanagerowner upload_only

upload_only is a special role for file requests — it permits contributing files without read access to the container.

Share-link scopes

ScopeMeaning
restrictedOnly explicitly named recipients.
tenantAnyone in the tenant.
external_recipientsSpecified external email recipients.
anyoneAnyone with the link.
upload_onlyFile request — recipients upload, cannot browse/download.
Links can additionally require an Argon2id password and/or an email OTP, set an expiry, and cap opens with an atomic max-opens counter. Download can be turned off entirely.

Audit — system_logs event keys

Registered in config/system_logs.php. File Storage writes an audit entry for every mutation; events are keyed <field_name>:<module_name> under the module's namespace.

Event areaLogged when
File / folder lifecycleCreate, rename, move, trash, restore, new version.
SharingInternal share granted/revoked; external link created/opened/expired.
PermissionsACL entry added/changed/removed.
Team SpacesSpace created; membership synced/changed.
File requestsUpload-only request created; file submitted.
GovernancePolicy change, quarantine review, legal hold placed/lifted, purge performed.
The activity feed (Activity tab) is fed by file_activity_events; the compliance audit trail is the standard ERPat system_logs. They are complementary — one is user-facing, one is immutable audit.

Setup quick reference

1. Enable the module            (Settings → Manage Modules → File Storage)
2. php erpat migrate:modules    (creates the 13 tenant tables)
3. Assign permissions           (Roles editor: file_storage_*, governance_*)
4. (optional) Set policies       (Governance → Policies)
5. (optional) php erpat db:seed FileStorageDemo
Reference-aware purge is fail-closed: a file is never permanently removed while it has an active reference, is a current version, is within retention, or is under a legal hold. Deletes are soft-delete first and recoverable from Trash.
Was this guide helpful?

Report a content problem