Security
Your data cannot reach another customer’s account
Most multi-tenant software separates customers with a WHERE clause and a code review. That works until one query is written without it. We assumed that query would eventually be written, and made it fail anyway.
Keeping accounts apart
Row-level security, enabled and forced
Every table holding customer data has PostgreSQL row-level security turned on and FORCED, so even the table owner is subject to it. The policy is applied by a script that finds every table with an account column and covers it, which is why a table added next month cannot ship unprotected. A separate test re-derives the list independently and fails the build on a gap.
The application cannot bypass it
The API connects as a database role without the BYPASSRLS privilege, and refuses to start if it is pointed at a superuser connection. A query written without an account filter returns nothing. It does not return someone else’s rows.
Composite keys, not just policies
Child records reference their parent through a key that includes the account id. A lease pointing at another customer’s unit is not blocked by a rule that could be misconfigured — it is a key that does not exist in the index.
Scoping is ambient, not an argument
The account is established once per request and carried implicitly. No function takes an account id as a parameter, so there is no call site that can be given the wrong one.
Keeping residents apart from each other
A second policy layer inside each account
Account isolation alone would show every resident of a tower the whole building’s ledger, because they share an account. A second, restrictive layer of database policy narrows each resident to their own tenancy. Measured on a seeded 360-unit building: staff see 340 leases, a resident sees one.
Tables residents cannot read at all
Audit logs, subscriptions, staff lists, owner records and site configuration are denied to portal sessions explicitly, by name. "We never built an endpoint for it" is not a security control.
Portal sessions cannot widen themselves
A resident session is pinned to one account and one person by the hostname they signed in through. It carries no memberships and cannot switch accounts, so somebody who is a resident in one building and staff in another cannot cross between them.
Signing in
No passwords anywhere
Sign-in is an emailed link plus a six-digit code, valid fifteen minutes and single-use. There is no password to reuse across sites, to phish, or to leak in a breach elsewhere — which removes the most common route into a small business.
Links are bound to where they were issued
A link emailed for one company’s resident portal is refused at the staff dashboard and at any other company’s portal. Requesting a new link retires the previous ones, so a message sent to the wrong address stops working the moment you ask for another.
Sessions and codes are stored hashed
Session tokens and sign-in codes are never stored in a readable form. The codes are keyed with a secret held by the application, so a copy of the database alone does not yield a working sign-in.
Data handling
Identity documents and bank details are encrypted
Emirates ID, Iqama and passport numbers, owner payout IBANs and cheque drawer accounts are encrypted with AES-256-GCM before they reach the database, under keys held in the application environment. A database copy that travels without that environment — a backup, a restored snapshot, an export — does not carry them.
An audit trail that cannot be rewritten
Changes are recorded with the actor, the time, the address and the before-and-after, inside the same transaction as the change itself, so a change cannot commit without its record. The table rejects updates and deletes at the database level; a correction is a new row.
Deleted means gone from view
Deletions are recoverable rather than destructive, and the database removes deleted records from every query by default — including queries written later by someone who did not know to exclude them.
What we do not claim
- We hold no SOC 2 or ISO 27001 certification today. We will say so plainly rather than describe ourselves as "aligned with" a standard we have not been audited against.
- Data is hosted on managed infrastructure in the provider’s regions. Contractual data residency is available on the Enterprise plan and is not something we can promise on the self-serve tiers.
- The dedicated-database isolation mode is designed and its seam exists in the code, but it is not implemented. Every account today shares one database, separated by the controls above.
- Encryption at the application layer protects copies of the database. It cannot protect against a compromise of the running application, which necessarily holds the keys.