Clinical Intake (healthcare)

A behavioral-health intake that makes compliance visible, not just claimed — for digital-health builders. Synthetic data only.

What it is — compliance you can see

clinical-intake is the healthcare-lead exemplar blueprint: a behavioral-health intake record whose PHI fields are handled by the platform, not by your app code. The point is that you can demonstrate the handling — open a record, look at its history, run a search — in about 60 seconds, rather than take a compliance claim on faith. Everything below runs on synthetic data against an invite-only 0.x preview.

What bootstrap provisions

vectros bootstrap --blueprint clinical-intake provisions one context (clinical-intake), one schema (intake, indexMode: HYBRID), a service principal, a least-privilege access profile, a narrow scoped key, and one synthetic seed record. The intake schema separates working fields from PHI:

Non-sensitive working fields (safe to index, search, and filter):

  • caseId — required; the stable dedup/lookup key.
  • presentingConcernsearchable: true; a non-PHI summary, safe to put in the index.
  • programfilterable: true; the service line the intake routes to.
  • statusfilterable: true; enum new | in_review | scheduled | closed.
  • submittedAt — ISO-8601 date; range-queryable (a coordinator can pull "intakes submitted this week").

Sensitive (PHI) fields — each marked sensitive: true:

  • clientName
  • dateOfBirth
  • ssn
  • clinicalNote

The schema sets capabilities.auditHistory: true explicitly (it is the platform default, but a compliance exemplar self-documents its posture).

It declares five lookup fields — four exact-match, one range — each a deliberate, permanent choice (a field's lookup shape is locked once the schema is live):

  • caseId (unique) — exact get/upsert by the stable intake id.
  • program and status (non-unique equality) — so a coordinator can enumerate a worklist directly via record_query: "all outpatient-counseling intakes", "all new intakes". The deterministic, no-query counterpart to semantic hybrid_search.
  • clientName — a sensitive blind-index lookup. The PHI value is HMAC'd into a per-tenant index, never stored in the clear and never in the search index, yet a coordinator can still find the intake for an exact client name. A blind hash is not orderable, so this lookup is exact-match only (never range).
  • submittedAt — a range lookup: ordered date windows ("intakes submitted this week"), distinct from the equality enumerations above.

The other PHI fields (dateOfBirth, ssn, clinicalNote) are deliberately not lookup fields here. (Equality lookups draw on the schema's 7 fast index slots; the range lookup uses a relationship row instead.)

The access profile is deliberately narrow:

allowedActions: ['records:r', 'records:c', 'records:u', 'search:r', 'schemas:r']

Note what is absent: there is no records:d (intakes are retained, not deleted) and no s reveal scope — so the bootstrapped key itself cannot un-redact the PHI fields. That is the whole point of the demo: the credential you are handed literally has no path to the plaintext sensitive data.

Before you start

Honest prerequisites:

  • An invite to the 0.x preview and the Vectros CLI.
  • A dev-portal Cognito bridge token (a human step) so the CLI can talk to the API.
  • For the visual part of the demo, access to app.vectros.ai (the reference data-plane app) and/or the MCP server wired into your agent.

Synthetic data only — never enter real PHI. This is a preview demo tenant. The seed record and every example field below are fictional. Do not type a real name, real date of birth, real SSN, or any real clinical text into it. The clientName: 'Jordan Sample', ssn: '000-00-0000', and clinical note in the seed are illustrative, not a real person.

1. Bootstrap the blueprint

# install once: npm i -g @vectros-ai/cli  (or use npx @vectros-ai/cli, below)
npx @vectros-ai/cli bootstrap --blueprint clinical-intake

This provisions the schema, context, service principal, gated access profile, and the seed record, then prints a scoped key (ssk_*). The bootstrap is idempotent. If you are driving an agent via MCP, the key is auto-merged into your Claude Desktop config (for Cursor/Cline, pass --print and paste the mcpServers.vectros block) so the agent can act as the intake service principal — with exactly the five scopes above and nothing more.

2. Create a synthetic intake

Create an intake either through the MCP server (record_create) or directly in the data-plane app. Use synthetic PHI only — for example:

{
  "caseId": "demo-intake-001",
  "presentingConcern": "Sleep difficulty and low mood over the past month; seeking counseling.",
  "program": "outpatient-counseling",
  "status": "new",
  "submittedAt": "2026-06-14",
  "clientName": "Jordan Sample",
  "dateOfBirth": "1990-01-01",
  "ssn": "000-00-0000",
  "clinicalNote": "Synthetic note for demonstration. Reports difficulty sleeping; no acute safety concerns noted."
}

The four sensitive fields are written through the same API as the rest — your app does nothing special. The platform takes over from there.

Expected: when you read the record back through this blueprint's key, the four sensitive fields come back masked ([redacted]) — that is the feature working, not a bug. The bootstrapped key deliberately carries no s reveal scope, so it cannot un-mask PHI; revealing plaintext requires a separate, more-privileged key minted with records:r:<type>:s. The non-sensitive fields read back normally.

3. Watch the redaction (the aha)

Three observations, each of which proves a specific, implemented claim.

(a) Open the record's History in app.vectros.ai. Navigate to the record detail page and look at the History card. Every version row shows the change type, when it happened, who made it, and which fields changed — but the sensitive fields are never rendered in plaintext, in any version row, regardless of your scope. Why this proves it: the PHI was redacted at write time — destroyed before the audit snapshot was ever persisted, not masked behind a permission check. There is no plaintext copy in the history to leak, so no scope can surface one.

(b) Edit a non-sensitive field and watch the audit trail grow. Change status from new to in_review and reload the History. A new immutable version row appears, recording the change to status — while the sensitive fields stay redacted across every row. Why this proves it: the audit/version history is append-only and tamper-evident (a SHA-256 state-continuity chain), so the trail of who changed what, when is preserved — without ever capturing the PHI.

(c) hybrid_search for a phrase from the clinical note → zero hits. Run a hybrid search for a distinctive phrase that exists only in clinicalNote (e.g. "difficulty sleeping"). It returns no results. Then search for a phrase from presentingConcern and confirm the record does come back. Why this proves it: sensitive fields are excluded from the search index at write time, so a note phrase can never leak through search results — while the non-PHI working fields remain fully searchable.

How it maps to Vectros compliance

Each bullet is tied to an implemented capability:

  • Redact-at-write (PHI): sensitive fields are stripped from audit snapshots and structured diffs at write time — destroyed before persist, unrecoverable regardless of scope. This is not reversible masking.
  • Immutable, tamper-evident audit / version history: every write to an audited model emits an immutable version row (change type, who, previous content, changed fields), with heavy content externalized to a WORM Object-Lock (GOVERNANCE) bucket. The state-continuity chain is tamper-evident (SHA-256), not tamper-proof.
  • Search-index exclusion: sensitive fields never enter the search index, so PHI cannot leak via search results — while non-PHI fields stay searchable.
  • Blind-index lookup (find-by-PHI without exposing it): clientName is a sensitive lookup — the value is HMAC'd into a per-tenant blind index, so an exact find-by-name works without the plaintext ever being stored in the clear or entering search. (The lookup value travels in the request body, not the URL.)
  • Read-time masking + the s scope: in responses, sensitive fields are masked unless the token carries the s reveal scope. This blueprint's key does not carry s, so the demo credential cannot un-redact PHI.
  • Context isolation: contextId is a mandatory, auth-derived, fail-closed partition key on records/schemas/documents/folders, and lookups are same-context-only.
  • Least-privilege keys: the bootstrapped ssk_* carries exactly five data-plane scopes — no delete, no reveal, no control-plane.
  • Independent security auditing: the platform has been through independent security audits with prior Criticals remediated, and stays under active pre-launch re-auditing through the preview.

Notes & limits

  • Synthetic data only. Never enter real PHI into the demo tenant.
  • Tamper-evident, not tamper-proof. The audit chain detects tampering; a continuous external verifier is not part of this claim.
  • Not claimed here: end-subject right-to-erasure, data residency, and BYOK / per-tenant CMK are not part of this walkthrough and are not implemented for this demo. Do not read them in.
  • Legal terms. BAA and single-region posture are scoped to the partner data plane and are available for discussion under NDA — treat specific legal coverage as soft until confirmed with us directly.