# The deploy is a file operation

> The deployable is derived from the routes the site serves, as shown in routes to site].

Page: Methodology · Ship
Canonical: https://banes-lab.com/disciplined-methodology/ship#the-deploy-is-a-file-operation

This section is stop 94 of 102 in the learning route. Previous: [44 - Scale follows from structure](https://banes-lab.com/disciplined-methodology/ship/scale-follows-from-structure.md). Next: [46 - Proxies give way](https://banes-lab.com/disciplined-methodology/ship/when-not.md). It builds on [43 - One chain](https://banes-lab.com/disciplined-methodology/ship/one-chain.md).

The deployable is derived from the routes the site serves, as shown in [C1·a routes to site](https://banes-lab.com/disciplined-methodology/ship#the-deploy-is-a-file-operation-panel-a). The deploy is a file operation with a [rollback](https://banes-lab.com/records/arch/rollback.md), and it never touches a process it does not own, which is [least privilege](https://banes-lab.com/records/arch/least-privilege.md) applied to a deploy. [Secrets management](https://banes-lab.com/records/arch/secrets-management.md) keeps every secret outside the tree. Every served surface uses [encryption in transit](https://banes-lab.com/records/arch/encryption-in-transit.md), including the local development server, because [environment parity](https://banes-lab.com/records/arch/environment-parity.md) means development exercises the same transport as production; otherwise it exercises something else.

### Derived from the routes

A deploy that ships a build folder ships whatever happened to be in it. A page fails to pre-render, and nothing reports it because the old file is still in the build folder, so the stale page ships. Nothing between the build and the upload asks whether a file is reachable.

For this reason the deployable is whatever a page can reach. The deployable is pruned from the routes rather than taken from the build folder on trust, and a file operation is chosen over a process operation for its rollback. In practice, the deploy starts from the served routes and follows every path a text artefact names. Every file that nothing reaches is deleted, and the whole of what is left is uploaded. One backup is kept of what is replaced, and it is restored on any failure. A command that touches a shared machine is handed to the developer who owns that machine rather than run, and every secret stays in the one artifact declared to hold it.

To check this, list every file in the deployable and the route that reaches it. A file that no route reaches is one the discovery check should have refused. On a machine that hosts other people's processes, nothing beyond your own files is touched. The deploy is a file operation because a file operation can be rolled back, while a process operation has a blast radius.

A discovery check derives, from the same registry the build reads, every route a page can serve and every file a route reaches. It fails the build on a route with no rendered file, a payload a machine cannot parse, or a file that nothing reaches, so the problem is found before a deploy rather than after.

C1·a routes to site

```mermaid
flowchart TB
routes["The served routes"]
follow["Follow every path a text artefact names"]
reached["What a page can reach"]
prune["Delete everything else"]
backup["Back up what is live"]
upload["Upload the whole of what is left"]
check{"Healthy?"}
done["Live"]
restore["Restore the backup"]
routes --> follow --> reached --> prune --> backup --> upload --> check
check -- yes --> done
check -- no --> restore
```

## Links to

- [Rollback](https://banes-lab.com/records/arch/rollback.md)
- [Least Privilege](https://banes-lab.com/records/arch/least-privilege.md)
- [Secrets Management](https://banes-lab.com/records/arch/secrets-management.md)
- [Encryption in Transit](https://banes-lab.com/records/arch/encryption-in-transit.md)
- [Environment Parity](https://banes-lab.com/records/arch/environment-parity.md)
