Flow has no accounts, no server and no secrets yet. The decisions below are the ones that will matter once it has them.
| Input | Where it enters | Treated as |
|---|---|---|
| A document | flowApi.ensureLoaded |
Untrusted: shape is normalised at the adapter, unknown node types fall back to a safe entry rather than rendering nothing |
| A shared link | useOpenSharedLink |
Untrusted: the fragment is decompressed and read by parseFlow, like typed text; a damaged one is refused with a message, and opening one is an undoable change |
| Imported text | The Import dialog and the text pane | Untrusted: parsed by pure functions that never evaluate it; YAML is read as data only, with no custom tags; the result is rendered as text like any document |
| Form fields | The drawer and create dialog | Untrusted: validated before a mutation, capped in length |
localStorage |
ensureLoaded |
Untrusted: parsed in a try, falls back to a sample when it holds anything unexpected |
Nothing in the app uses v-html. Every document string, shape title, description and edge label
goes through Vue's text interpolation, which escapes it. Shape outlines are SVG path data computed
from numbers in src/domain/shapes.js, never from document text.
The one thing to keep watching: if a future requirement asks for formatted labels, the answer is a
sanitiser with an allowlist, not v-html.
The app makes no requests of its own. The samples are bundled into the build and every edit
is saved to localStorage, so there is no proxy, no CORS surface and nothing to configure. When a
real backend lands (see BACKLOG.md), it replaces src/api/flowApi.js and this section
returns.
docker/nginx.conf serves the production build. For a real deployment it should also
carry:
| Header | Value | Against |
|---|---|---|
Content-Security-Policy |
default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' |
Injected scripts |
X-Content-Type-Options |
nosniff |
MIME confusion |
Referrer-Policy |
strict-origin-when-cross-origin |
Leaking URLs, which contain node ids |
X-Frame-Options |
DENY |
Clickjacking |
unsafe-inline for styles is what Vue's scoped styles and the canvas transforms need; scripts do
not require it.
There are none, and .env is gitignored so it stays that way. Note that VITE_* variables are inlined into the bundle at build time and are readable by anyone
with the page, so nothing secret may ever be named with that prefix.
Seven runtime dependencies. npm audit is clean at the
time of writing. CI installs with npm ci, which fails if package.json and the lockfile disagree,
so a dependency cannot change without the lockfile change being in the diff.