Built for files you are trusted with
A trademark docket holds client confidences, unpublished marks and the correspondence around contested matters. It is treated that way.
One firm cannot see another
Every record belongs to exactly one organisation, and every query against tenant data carries that organisation as a predicate. This is not a filter applied in the interface, which can be forgotten. The query builder refuses to construct a tenant-scoped query without an organisation: a query that forgets it does not return the wrong rows, it throws. There is a test that proves this for every tenant-scoped table, and it runs on the live server.
Two ways in, both of them yours
Sign in with Google, or with an email address and a password. A password is stored only as a one-way hash using the algorithm PHP currently treats as strongest, and is re-hashed automatically as that moves on. We cannot read it, and neither can anyone who obtains a copy of the database.
Repeated wrong guesses lock the account for a few minutes and are rate-limited by address and by connection. A sign-in that fails says the same thing whether the address exists or the password was wrong, and takes the same time either way — so the form cannot be used to find out who banks their marks here.
Roles that mean something
Owner, admin, IP manager, attorney, trademark agent, paralegal, reviewer, client and read-only. Permissions resolve from the role, plus any explicit grant or denial on the individual — and then a client-scoped member has the internal permissions removed unconditionally. A client login cannot be granted access to internal notes by any override, by any administrator, by accident. That last step is not configurable, and it is tested.
Documents leave only through the docket
Uploads are stored outside the web root, under a name the application chooses from a ULID and the file type it read off the bytes — never a name anyone typed. A stored file is only ever served by a controller that has already checked who you are, which organisation you belong to and, for a client login, whether that specific document was shared with them. Anything that could carry script is sent as an attachment rather than displayed, and browsers are told not to guess the type.
Nothing is quietly deleted
Removing an event, a document or a person from a file removes it from the file, not from the record. The audit trail is append-only, is written on every change, and cannot be edited from inside the application by anybody, including us. A corrected date keeps what was believed before it and when — because on a contested matter that is sometimes the thing that matters.
Every write is checked twice
Forms are validated on the server, not only in the browser. Every state-changing request carries a one-time token tied to your session, and a request without it is refused. Sessions are regenerated on sign-in, expire when idle, and are dropped immediately if the membership behind them is suspended mid-session.
What we do not do
- We do not bypass the Registry's CAPTCHA, authentication or access controls, and never will.
- We do not sell your data, share it with advertisers, or use it to train any model.
- We run no analytics and no third-party trackers. There is one session cookie, which is why there is no cookie banner.
- We never see your card details. Those go to the payment gateway and do not reach this server.
Where it runs, and what that means
On shared hosting in India, over HTTPS, with the application code denied to the web server twice over and only the public folder reachable. Shared hosting is an honest constraint rather than a marketing claim: it means we do not control the physical machine, and it is one of the reasons the guarantees above are written into the application rather than into the infrastructure.
Retention, export and deletion are set out in the privacy policy. What the product cannot do is set out, at length, in what this does not do.