Security · state of the running system

Every gate here fails shut.

A missing key, an unrecognised action or an unreachable database stops the platform and waits for a person. This page lists the controls that run today, each one traceable to a line of code or a live response, and the ones that do not exist yet.

Live posture

Fail-shut

TransportTLS 1.2 / 1.3
HSTSmax-age 63072000
At restAES-256 · Neon
Operator API401 without session
Public body cap10 KB
DefaultClosed until proven
UNISTAFF.AIUNISTAFF.AIUNISTAFF.AIUNISTAFF.AIUNISTAFF.AIUNISTAFF.AIUNISTAFF.AIUNISTAFF.AI

Fail-shut, in five conditions

Operator key unset

Every session cookie is rejected

Trigger secret unset

Scheduled jobs answer unauthorized

Action missing from the matrix

Human approval required

Approval expired

The decision is refused

Governance database unreachable

Outbound write stops

How the protection works

Twenty-four controls, one page.

Each row describes a mechanism that exists in the running system. Where a control belongs to the hosting provider, the provider is named in the row.

01 · Access

Who gets in

05 controls

01

Signed session cookie

The operator cockpit accepts one cookie: an HMAC of a versioned string computed with a server-side key, set httpOnly and marked secure over https. A deployment running without that key rejects every cookie presented to it.

HMAC-SHA256
02

Gated APIs answer 401

Operator endpoints verify the session themselves, on every host the deployment serves, before they touch the database. A request without one gets 401 and no payload — the answer /api/leads/list gives on unistaff.ai right now.

HTTP 401
03

Rotation ends every session

The cookie is derived from the key and a version string, so changing either makes every cookie issued earlier fail verification. One rotation signs everyone out at once.

Key rotation
04

One answer at the login

An empty key and a wrong key return the same 401. The comparison hashes both sides to a fixed length first, then walks the bytes without an early exit, so timing and length give nothing away.

Constant time
05

Machine triggers carry a secret

Scheduled and machine-triggered jobs present a bearer secret. With no secret configured, the endpoint reports an unauthorized state and stays closed.

Bearer secret

02 · Customer data

Where the data sits

07 controls

01

One deployment, one customer

Separation runs on the deployment boundary: its own database, its own operator key, its own credential key. The schema holds no tenant, organisation or workspace column splitting one shared table between customers, so a row belonging to another business has no route into a query.

Single-tenant
02

Encrypted in transit

Requests travel over HTTPS on TLS 1.2 or 1.3 with forward-secrecy ciphers, and responses carry HSTS with a two-year max-age. Neon requires TLS on database connections as well.

TLS 1.2 / 1.3
03

Encrypted at rest

Neon keeps the database on storage encrypted with AES-256 and retains encrypted backups for 30 days. That encryption is the provider's platform default, applied by Neon underneath our application.

AES-256 · Neon
04

Platform credentials sealed before storage

An ad-platform token is encrypted with AES-256-GCM under a key held in the environment before it reaches the database; the row keeps ciphertext, a random 12-byte initialisation vector and the auth tag. With the key missing, the store raises an error and writes nothing.

AES-256-GCM
05

Lead records leave the cockpit masked

Outside an operator session, a lead reads as an initial plus the names of the channels the person offered. Names, phone numbers, email addresses and free-text answers stay in the database.

PII withheld
06

Logs hold ids and outcomes

Notification logging emits a lead id, an outcome code, or the names of unset environment variables. Database failures return a fixed message to the caller, so driver text that can echo submitted values stops at the server boundary.

No PII in logs
07

Every query value is bound

Filters, ranges and page sizes travel as bound parameters while the SQL text carries placeholders. An injection attempt stays what it started as — a string sitting in a parameter slot.

Parameterized SQL

03 · Public surface

What the open endpoints accept

04 controls

01

Body cap counted in bytes

The two public form endpoints stop at 10 KB and the operator login at 4 KB, measured in bytes before any parsing, so multibyte text cannot slip past a character count. An oversize post to the contact endpoint comes back 413.

10 KB · 413
02

Bot trap answers like a real submission

A hidden field sits in the form, invisible to a person and attractive to a bot. When it arrives filled, the response carries the same 200 and a freshly minted id, and the database stays untouched.

Honeypot
03

Page size clamped on the server

List endpoints clamp the requested page size into range before it reaches the query, so a crafted URL returns one page and stops there.

Limit ≤ 200
04

Platform DDoS mitigation

The application runs on Vercel, whose platform-wide firewall applies automatic DDoS mitigation to every deployment with no configuration on our side.

Vercel firewall

04 · Autonomy limits

What the AI is allowed to do

08 controls

01

Kill switch, read before the write

The switch is the first gate on every outbound write to a connected ad account, checked ahead of the mutation. Engaging it takes a written reason, which the record keeps. A blocked request holds its approved state and waits.

Global · meta · ai
02

Spend caps stop the mutation

Each write compares its daily spend against the daily and monthly caps and throws when it exceeds them. A cap left unset has nothing to compare against and the gate passes it, which is why the approval gate below carries the weight until you set one.

Daily · monthly
03

An unlisted action waits for a person

The autonomy matrix answers “requires approval” for any action with no rule of its own, so a new capability arrives gated and stays that way until someone writes the rule.

Default: approval
04

Writes run against an approved request

A mutation executes when an approved change request matches it exactly, tied to a recorded decision with its timestamp and note. Anything else raises approval_required and goes nowhere.

Change request
05

An expired approval stays expired

A pending item that runs past its clock keeps its status in the database and gets refused at decision time. A decided item resists a quiet second decision: the update carries the pending state and the expiry inside its own condition.

Timeout ≠ consent
06

Objects are created paused

Campaigns, ad sets and ads made through the write path come into existence paused, so a new object spends nothing until a person starts it.

Status: paused
07

Journal of runs and decisions

Agent runs, sync attempts, change requests and approval decisions land in tables with timestamps, parameters and outcome, failures included. One caveat worth stating plainly: the actor on a decision is a label supplied by the caller, since operator access today is a shared key.

Timestamped
08

No database, no write

Gate checks read from the governance database. When it is unreachable, the write raises enforcement_unavailable and stops — a client without a database can mutate nothing.

Enforcement required

The access, masking, encryption and gating paths above are pinned by an automated suite: 788 tests, 0 failures on the last run. The tests state the closing direction as clearly as the opening one — a rotated key invalidating every issued cookie, a forged cookie refused, a tampered auth tag throwing, and no outcome putting personal data into a log line.

Today and later

What runs today, and what does not exist yet.

The right-hand column is the whole list as of today, printed in full so a procurement checklist can be answered in one pass. Each line there is a control this platform lacks; the date any of them arrives stays unset until it ships.

Running today

Encryption in transit
TLS 1.2 / 1.3 · HSTS 2 years
Encryption at rest
AES-256 · Neon default
Database backups
30 days, encrypted · Neon
Operator session
Signed cookie, fail-shut
Machine triggers
Bearer secret, fail-shut
Lead masking outside the cockpit
Initial + channel names
Stored platform credentials
AES-256-GCM
Outbound write gate
Approved change request
Kill switch
3 scopes, reason required
Spend caps
Daily + monthly, checked per write
Action journal
Timestamps, outcomes, failures
Automated test suite
788 tests, 0 failures

Not built yet

  • SOC 2 report for Unistaff
  • ISO 27001 / ISO 27701 for Unistaff
  • HIPAA controls and a signed BAA
  • GDPR DPA, subprocessor list, standard contractual clauses
  • SSO, SAML, OIDC, SCIM provisioning
  • Per-user accounts, roles and permission scopes
  • Multi-factor authentication on operator login
  • Row-level separation between customers inside one database
  • Rate limiting and lockout on public endpoints
  • CSP and the other security response headers
  • Third-party penetration test of this application
  • Bug bounty and a published disclosure policy
  • Data residency selection
  • Retention purge and TTL enforcement
  • Self-serve data export and deletion
  • Customer-facing audit-log search and export
  • Column-level encryption of lead contact data
  • Per-session revocation
  • CAPTCHA or a managed bot-defence service
  • Uptime SLA and a public status page
  • Key management service and automated secret rotation
  • Documented restore drill of our own data

On provider certifications · Unistaff holds no certification of its own. Our hosting providers hold theirs and publish them on their own trust pages, where they cover those platforms. A claim that this application is certified would be false, whoever repeated it — including if the sentence borrows a provider's badge to say it.

How to request details

Every claim here has a source behind it.

Name the control you need to check and the answer points at what backs it: the file, the migration, the provider document, or the live response you can reproduce yourself. When a control sits in the unbuilt column, the answer says that in the first line.

Security email
hello@unistaff.aiOne inbox for questionnaires, pilot reviews and anything on this page you want to verify.
Reporting an issue
Same address, subject line “security”A published disclosure policy and a bug bounty sit in the unbuilt column, so the route today is the inbox.

Questions procurement asks

Frequently asked questions

A full lead record has two doors: an operator session or a bearer secret. The API verifies one of them itself before it touches the database, independent of the page gate. Every other caller receives a masked record — an initial and the names of the contact channels, with the name, phone, email and free-text answers left in storage.

Traffic runs over HTTPS on TLS 1.2 or 1.3 with forward-secrecy ciphers, and responses carry HSTS with a two-year max-age. Neon requires TLS on database connections, keeps the data on AES-256 encrypted storage, and retains encrypted backups for 30 days. The at-rest encryption comes from the provider's platform default; our application code adds no encryption layer of its own on top of it.

No. Unistaff holds no certification of its own, and none is in progress. Our hosting providers publish their own certifications on their own trust pages; those cover their platforms and say nothing about this application. Treating a provider's audit as an audit of Unistaff would be wrong, and we say so before a procurement review has to ask.

Separation runs on the deployment boundary: a deployment carries its own database, operator key and credential key. The schema holds no tenant, organisation or workspace column, so row-level separation inside one shared database stays absent today. Ask which deployment your pilot would run in before you plan around it.

Four gates sit ahead of every outbound write to an ad account: the kill switch, the daily and monthly spend caps, the autonomy matrix, and a matching approved change request. An action missing from the matrix requires human approval by default, an expired approval stays expired, and an unreachable governance database stops the write where it stands. One limit worth stating: a cap you have not set gives the caps gate nothing to compare against, so it passes and the approval gate is what holds the spend.

Those three do not exist today. Operator access is a single shared key with no per-user accounts, MFA or SSO; the journals are internal tables with no customer-facing search or export; and no DPA, subprocessor list or standard contractual clauses have been drafted. Write to hello@unistaff.ai before you build a rollout plan that depends on any of them.

The record is written first, then the notification is attempted with a five-second timeout. A delivery failure is recorded as an error line carrying the lead id and an outcome code, with the submitted values and the mail provider key left out of the log entirely.

The rest of the questions — pricing, launch, connectors, metrics — are grouped in the AI employee FAQ, and the data answers there point back to this page.