Skip to content
ExploreFor youFor businessHow it worksPricing

Trust

How privacy works in IDOFO

An assistant that answers your phone hears things you would not put in an email. Separation between customers is not a feature we added — it is the shape of the data layer, and the product is built on top of it.

One place builds every query

All customer data is read and written through a single tenant-bound handle. It binds tenant_id = ? into every statement before it reaches the database, and it has no method that can address another account. Its one raw escape hatch refuses to run SQL that does not carry the tenant predicate:

scoped(sql: string, params: SqlValue[] = []): Row[] {
  if (!sql.includes('{{TENANT}}')) {
    throw new Error('Scoped query is missing the {{TENANT}} predicate. Refusing to run an unscoped query.');
  }
  ...
}

The rule this enforces: authenticate, determine the account, check permission, then query only that account. Nothing in IDOFO fetches broadly and filters afterwards.

Record ids are not keys

Knowing another account's appointment id achieves nothing. The lookup is scoped, so it returns nothing — and the error is worded identically to a genuinely missing record, so ids cannot be probed for existence.

The AI has no database access

The model cannot query anything. It can only ask for a named tool — check availability, quote a configured price, take a message. Each tool runs inside the caller's account, checks the permission and the plan, validates its input, writes an audit record and returns only what is needed to say one sentence.

This is also why the assistant does not invent facts: every statement it makes came out of a tool result computed from your own records. When there is no answer, it says so and flags the question for you.

Even we need permission

An IDOFO staff account is not a key to customer data. To look inside an account, staff must open a support session with a written reason and an expiry. It defaults to read-only, every action is stamped with the grant, and both the start and the end are written to your activity log, not only ours.

What is logged, and what is not

Audit records hold who did what, to which object, and whether it succeeded. They deliberately exclude message bodies, transcripts, notes and contact details — because those logs are read during support. Webhook payloads follow the same rule: identifiers and counts, never content.

It is tested, not asserted

An automated suite builds four real accounts, fills them with data, and then actively tries to cross the boundary: swapping record ids into service calls, tampering with the session's account, forging a tenant field on write, pointing one account's API key at another's data, asking the AI tool layer for another account's information, and opening a customer account as staff without a grant.

Every attempt must fail for the suite to pass. The results, including exactly what was attempted, are written to SECURITY_TEST_REPORT.md in the repository on each run.

For health, legal and financial work

IDOFO is built with the technical foundations that sensitive work needs: strict tenant isolation, audit trails, role-based least-privilege access, session control, configurable retention, deletion and export. That is not a compliance claim. IDOFO does not claim HIPAA compliance. Getting there requires contracts, BAAs, vendor review, hosting decisions and operational policy — work that sits alongside the software, not inside it.

Honest limits of this beta

  • It runs locally on a file-backed database. Production hosting, encryption at rest and backups are deployment decisions still to be made.
  • Multi-factor authentication is designed for but not yet enabled.
  • No third-party analytics or session-recording tools are embedded, and none will be added to pages that display customer data.