Users
There is no public sign-up. Accounts exist because an administrator created them, and that is the entire access-control model: anyone who can upload is someone you put on the list.
Members and guests
Members are your team. They sign in with a password, send transfers, and see their own dashboard. A member with the admin role can also manage users.
Guests are outside contacts. They have no password, sign in only by one-time link, and can do exactly one thing: upload files to a member they pick from a list. Every member-only endpoint excludes them explicitly — a guest's session is an ordinary session, so being a guest has to be checked rather than assumed.
Adding someone
Users → New user. Name, address, and whether they are a member or a guest. A member can be given a password, or sent a welcome e-mail with one.
Adding a guest is the whole setup for receiving files from them. There is nothing else to configure.
Deleting someone
Deleting a user deletes every transfer they ever sent, files included. That is deliberate — an account's transfers are its data — but it is not what everyone expects, so the confirmation says so.
Their API keys go with them, as do their sessions and any outstanding magic links, so a link already sitting in an inbox cannot resurrect access.
What survives is any transfer_recipients row that merely named their address
on somebody else's transfer. That is part of that transfer's history, not this
account's data.
Passwords
Account passwords are hashed with bcrypt in a table of their own. The minimum is 8 characters and there is no character-class checklist — length beats a mandatory punctuation mark.
Sign-in, password reset and magic-link endpoints are rate limited per IP, and all of them answer identically for known and unknown addresses, so the app cannot be used to test whether someone has an account.