Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

04 — Information Architecture (Files Module)

Global IA and nav patterns: 00-shared/05_Global_Information_Architecture. This file documents only the files domain — its record model, storage key space, and how file screens hang off context screens.


1. Domain model

FileRecord (collection: "files", file.schema.ts:7-8)
├── tenantId                 (inherited from BaseSchema — every business doc; auto-scoped)
├── isDeleted / timestamps   (BaseSchema — soft delete; filtered by BaseRepository)
├── originalName   String    (user-supplied, used verbatim in Content-Disposition)
├── mimeType       String    (client-supplied — NOT verified server-side)
├── size           Number
├── storageProvider String   (STORAGE_DRIVER ?? 'local', files.service.ts:40)
├── storageFileId  String    (provider object key/id; download by this)
├── storagePath    String    (= storageFileId today, files.service.ts:41-42)
└── optional, never populated today:
    etag, thumbnailFileId, thumbnailStoragePath, thumbnailSize, width, height
    (file.schema.ts:27-43) — (forward-looking)

Notes:

  • width/height are declared number but typed String in the schema prop (file.schema.ts:39-43) — schema bug to fix when thumbnails land (planned).
  • Files are context-agnostic documents: no folderId, no module, no entityRef field. A file's "context" (fee record, student, circular) exists only on the client or in the calling module's own linkage. Any folder/bucket UI is (planned).

2. Storage key space

LayerKey shapeSource
Local driverstorage/<tenantId>/<uuid>--<originalName>local-storage.provider.ts:24-27
R2 driver<tenantId>/<uuid>--<originalName>r2.provider.ts:39
Appwrite driverbucket APPWRITE_BUCKET_ID, object id = plain UUIDappwrite-storage.provider.ts:38-44
Blueprint targetsl/{tenantId}/{type}/{uuid}STORAGE_ARCHITECTURE.md:34 (planned)
  • Tenant isolation: mandatory key prefix (R2/local) OR bucket isolation; Appwrite relies on a single bucket + tenant-scoped metadata only (blueprint: "prefixing is mandatory", STORAGE_ARCHITECTURE.md:58-59 — Appwrite driver does not prefix, gap).
  • storageFileId doubles as storagePath in the service (files.service.ts:41-42); the filename on the key is the raw original name — no sanitization of originalName anywhere (files.service.ts:31).

3. Screens in IA

Files have no top-level tab. They appear as:

┌─ Module context screen (fees / student profile / circulars …)
│  └─ "Files" section or list (reads GET /files, client-filtered)
│     ├─ Upload sheet        (POST /files/upload)
│     ├─ File detail sheet   (GET /files/:id)
│     ├─ Download flow       (GET /files/:id/download)
│     └─ Delete confirm      (DELETE /files/:id)

Client-side grouping key: none server-side; the client may keep files.byContext local index (see 13_State_Management.md).

4. Navigation

  • Deep links (forward-looking): /files/:id (detail), /files/:id/download (direct download intent).
  • After upload: stay on context screen, tile appears (optimistic; rollback on failure).
  • After delete: tile removed; snackbar with no undo (no restore endpoint) (proposed: undo).

5. Information flows

FlowReadWrite
UploadStorage upload → Mongo create
ListMongo find (tenant-scoped, createdAt desc)
DownloadMongo findById → Storage download
DeleteMongo findByIdStorage delete → Mongo softDelete

6. Retention & lifecycle

  • No TTL on file records today. Global plan: 3-day retention tier for soft-deleted cleanup, GDPR erasure endpoint, cold storage (IMPLEMENTATION_PLAN.md:176) (planned).
  • Temp-upload expiry / cleanup job per blueprint STORAGE_ARCHITECTURE.md:66 (planned).