# Part 1 · Files

## 1.1 Opening a file

**Who** · Whoever the file's record allows: an export's own person (while they may still export that log), whoever may
run a purge for its archives.

**Where** · A link to the file: the export e-mail's **Download it**, the Purges page's archive.

**Before you start** · Be in the workspace the file belongs to.

**The steps**
1. Open the link. A picture or a PDF opens in the browser; anything else downloads. Add `?download=1` to save a picture.
2. A long file can be read part by part (a video seeks): only the part asked for is decrypted.

**What the record shows** · The file access log: who, which file, when, from where (one line an opening, not a line a
part).

**Who is told** · Nobody.

**What can go wrong**
- *"Not found".* The file isn't yours to open, belongs to another workspace, was removed, or is still being scanned.
  The page never says which, so a file's existence isn't given away.

## 1.2 What happens to an upload

**Who** · Anyone adding a file where a page takes one (the import, S15).

**Where** · The page's file field.

**Before you start** · The file's type must be on Input Fields' **Upload types**, within its size.

**The steps**
1. The file is checked: its extension and its bytes must agree (a program renamed `.pdf` is refused), and its size.
2. It waits, unreadable to anyone, while the malware scanner checks it, usually seconds.
3. Clean: a phone photo loses its location, and the file is encrypted into the vault. Infected: it is removed.

**What the record shows** · The audit log: **File added**, then **File refused by the scan** if it was.

**Who is told** · The page shows the file's state.

**What can go wrong**
- *"… can't be added: a file may be PDF, Image, Document or Spreadsheet."* The type isn't on the list.
- *"… isn't really of the type …"* Its bytes aren't what its name says.
- *"… files can be up to … MB".* Too big for its type.
- *Removed: the scanner found something.* It isn't kept.
- *Removed: the scanner didn't answer in time.* After **Give up scanning after** (24 hours): add it again later.

## 1.3 Choosing what may be uploaded (Service)

**Who** · The Service (`lookup.manage`).

**Where** · Platform › **Input Fields** › **Upload types**.

**Before you start** · A type's file extensions and the types its bytes may read as are set with the code
(`extensions`, `mimes`); the page changes its name, its size and whether it is offered.

**The steps**
1. Open a type, change **max_mb**, save; or switch a type off.

**What the record shows** · The audit log: **List value changed**.

**Who is told** · Nobody.

**What can go wrong**
- *A type you want isn't there.* A new type is added with the code, with the extensions and the byte types it takes.

## 1.4 How long removed files and the access log are kept

**Who** · The Service for the platform; an Owner or Admin for the workspace's own access log.

**Where** · Platform settings › **Files** (**Keep a removed file for**, **Give up scanning after**) and › **Logs** (**Keep
the file access log for**); a workspace's **Settings** › **Logs**.

**Before you start** · Nothing.

**The steps**
1. Change the figure and save.
2. Every night at 02:30 the purge removes the files taken away longer ago than that (their bytes and their rows), and the
   access log's entries older than its age. The Purges page shows both.

**What the record shows** · The audit log: **Setting changed**; each night, **Logs purged**.

**Who is told** · Nobody.

**What can go wrong**
- *A file removed by mistake.* Until the night it is purged, it can be brought back from the database (no page yet).

## 1.5 Setting up the vault (operator)

**Who** · The operator, on the server.

**Where** · `.env`; ClamAV.

**Before you start** · ClamAV's daemon (`clamd`) running beside the app.

**The steps**
1. `php artisan vault:key` prints a key; set it as `FILE_VAULT_KEY` and keep a copy somewhere safe: without it no file
   opens again.
2. Point the scanner at clamd: `CLAMAV_SOCKET` (a Unix socket), or `CLAMAV_HOST` and `CLAMAV_PORT`.
3. The vault's files are in `storage/app/vault` (`FILE_VAULT_ROOT`); uploads wait in `storage/app/holding`
   (`FILE_VAULT_HOLDING`). Back up the vault with the database: a row without its bytes, or bytes without their row,
   open nothing.

**What the record shows** · Nothing.

**Who is told** · Nobody.

**What can go wrong**
- *"The file vault has no key".* `FILE_VAULT_KEY` is missing or not "base64:" and 32 bytes; exports fail until it is set.
- *Uploads stay "being scanned".* clamd isn't answering; they are removed after **Give up scanning after**.

## 1.6 Changing the vault's key (operator)

**Who** · The operator, on the server.

**Where** · `.env`; `php artisan vault:rewrap`.

**Before you start** · A new key (`php artisan vault:key`).

**The steps**
1. Put the old key in `FILE_VAULT_PREVIOUS_KEYS` and the new one in `FILE_VAULT_KEY`. Every file still opens.
2. Run `php artisan vault:rewrap`: each file's own key is wrapped again with the new one; the files aren't rewritten.
3. Empty `FILE_VAULT_PREVIOUS_KEYS`.

**What the record shows** · Nothing.

**Who is told** · Nobody.

**What can go wrong**
- *"The master key that wrapped file … isn't configured".* The old key was removed before `vault:rewrap` ran: put it back
  in `FILE_VAULT_PREVIOUS_KEYS` and run it again.
