From 05658d65479ed882fd6f19bb22f606e771270361 Mon Sep 17 00:00:00 2001 From: abrichr Date: Tue, 21 Jul 2026 00:18:09 -0400 Subject: [PATCH 1/2] docs: qualify BAA copy to decided position and broaden PHI to PHI/PII Bring the on-prem compliance copy in line with the counsel-decided posture and broaden the general sensitive-data term from PHI to PHI/PII (OpenAdapt serves healthcare and lending/regulated work, not healthcare alone). BAA copy (deploy-on-prem.md compliance section): replace the flat "We do not sign a BAA" with the qualified position. In the self-hosted deployment PHI stays inside the customer environment and does not enter OpenAdapt's infrastructure, so the software runs as an on-premise vendor rather than a business associate for that shape and a BAA is not the operative instrument for it; the deployment's privacy officer and counsel make the determination. Where procurement requires written terms, a US HIPAA BAA (or, for an Ontario clinic, a PHIPA service-provider agreement) can be signed following review. Hosted processing of PHI in our infrastructure (BAA + HIPAA risk analysis) is not offered today. PHI -> PHI/PII in general product/security/deployment copy. Kept PHI where it is the correct legal/health-specific term or a literal token: the HIPAA/BAA/PHIPA compliance clause, the EMR illustration, the "PHI audit REM-3" identifiers, the merged-PR title in whats-new, the PlaintextPHIWarning code identifier, already-compound PII/PHI phrasing, and the narrow non-PHI validation-environment/entry-URL qualification fields. validate_docs.py, mkdocs build --strict, and pytest tests/ all pass; the pinned substrate-evidence copy is untouched. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM --- docs/concepts/deployment-matrix.md | 8 ++--- docs/concepts/regulated-execution.md | 2 +- docs/concepts/vlm-appliance.md | 2 +- docs/desktop/connect-to-cloud.md | 10 +++--- docs/get-started/what-works-today.md | 8 ++--- docs/get-started/what-you-get.md | 2 +- docs/guides/deploy-on-prem.md | 42 ++++++++++++++--------- docs/guides/hosted.md | 18 +++++----- docs/guides/index.md | 4 +-- docs/guides/security-and-data-handling.md | 16 ++++----- docs/guides/security-review.md | 12 +++---- docs/guides/troubleshooting.md | 8 ++--- docs/index.md | 2 +- docs/reference/cli.md | 2 +- docs/reference/configuration.md | 4 +-- 15 files changed, 74 insertions(+), 66 deletions(-) diff --git a/docs/concepts/deployment-matrix.md b/docs/concepts/deployment-matrix.md index ac930cc..c34b5a5 100644 --- a/docs/concepts/deployment-matrix.md +++ b/docs/concepts/deployment-matrix.md @@ -47,7 +47,7 @@ will remain sanitized; a real EMR can display PHI as soon as replay begins. | Existing raw authoring artifact | Refuse generic remote upload. | Keep within customer policy. | Local. | | Explicit hosted-recorder observations | Allow only for a public-HTTPS, non-regulated session inside the declared hosted recording boundary. | Keep within customer policy. | Local. | | Approved sanitized derivative | Allow when manifest, hash, review, and destination pass. | Allow to a verified customer endpoint when policy permits. | Local or explicitly exported. | -| PHI-bearing runtime frame | Outside the shared hosted boundary unless a specific regulated service is configured. | Remains inside customer boundary. | Remains local. | +| PHI/PII-bearing runtime frame | Outside the shared hosted boundary unless a specific regulated service is configured. | Remains inside customer boundary. | Remains local. | | Minimized control metadata | Allow by schema and destination policy. | Allow by schema and destination policy. | Optional/no egress. | | Secret value | Never browser-visible or serialized into enqueue payloads. | Resolve inside customer runner. | Resolve locally. | @@ -56,7 +56,7 @@ will remain sanitized; a real EMR can display PHI as soon as replay begins. “Scrubbed” means the source was inventoried, a separate copy was transformed, the result was rescanned, unresolved content was refused, and a manifest binds the policy and approval to the exact derivative hash. It does not mean the -source was modified or that every future run is PHI-free. +source was modified or that every future run is PHI/PII-free. It also does not mean a transformed recording remains runnable. Register the approved recording derivative, compile/lint/certify/replay locally, then @@ -115,8 +115,8 @@ not create a price, quota, SLA, certification, or backend entitlement. ## Customer-controlled regulated execution Use a customer-controlled boundary when a live workflow necessarily displays -PHI or other regulated data. Sanitized authoring derivatives and minimized -metadata may cross approved endpoints; PHI-bearing live frames and values stay +PHI/PII or other regulated data. Sanitized authoring derivatives and minimized +metadata may cross approved endpoints; PHI/PII-bearing live frames and values stay inside the boundary. A deployment scope must name: diff --git a/docs/concepts/regulated-execution.md b/docs/concepts/regulated-execution.md index c935693..708dc0c 100644 --- a/docs/concepts/regulated-execution.md +++ b/docs/concepts/regulated-execution.md @@ -84,7 +84,7 @@ The pre-flight gate is the entry check; the same posture governs every step: proceeding on a "Saved" banner. - An ambiguous identity abstains up the ladder and halts if nothing verifies. - A missing scrubbing capability, under `OPENADAPT_FLOW_SCRUB=on`, aborts rather - than writing PHI at all. + than writing PHI/PII at all. A halt is not a dead end. It feeds the [halt-learn loop](halt-learn-loop.md), where an operator demonstrates the fix, a regression gate proves it weakens diff --git a/docs/concepts/vlm-appliance.md b/docs/concepts/vlm-appliance.md index 4f94ceb..df5f319 100644 --- a/docs/concepts/vlm-appliance.md +++ b/docs/concepts/vlm-appliance.md @@ -55,7 +55,7 @@ record instead of the screen. ## Why on-prem matters -Identity crops and full frames can carry PHI. The control is not redaction (the +Identity crops and full frames can carry PHI/PII. The control is not redaction (the identity check needs the literal identifier), it is deployment. The appliance is designed to run on your infrastructure with no external model calls or payload persistence. Enforce and test its network and retention policy for the actual diff --git a/docs/desktop/connect-to-cloud.md b/docs/desktop/connect-to-cloud.md index 081d5c9..91fc874 100644 --- a/docs/desktop/connect-to-cloud.md +++ b/docs/desktop/connect-to-cloud.md @@ -7,8 +7,8 @@ covers the path: sign in → mint an ingest token → connect the desktop app a recording → see it in the dashboard. !!! note "Which lane are you in?" - The cloud workspace is the **self-serve, non-PHI lane**: browser/web - automation with no regulated data. For **PHI or other regulated data**, do + The cloud workspace is the **self-serve, non-PHI/PII lane**: browser/web + automation with no regulated data. For **PHI/PII or other regulated data**, do **not** push to the cloud; use the [on-prem deployment](../guides/deploy-on-prem.md) instead, where recordings and teaching never leave your network. See @@ -102,9 +102,9 @@ The recording directory is zipped before upload (the server ingests a `.zip`; th engine emits a directory). You can also push an already-compiled bundle with `--kind bundle`. See [`push`](../reference/cli.md#push). -!!! warning "Push scrubs, but the cloud lane is for non-PHI work" +!!! warning "Push scrubs, but the cloud lane is for non-PHI/PII work" A pre-push scrub runs fail-closed and the server re-scans on ingest, but the - cloud lane is **not** the PHI lane. Keep regulated recordings local and use + cloud lane is **not** the PHI/PII lane. Keep regulated recordings local and use [on-prem](../guides/deploy-on-prem.md). ## 5. See it in the dashboard @@ -115,7 +115,7 @@ runnable; any run that halts surfaces under **Needs attention** for triage. ## Reporting a halt back to the workspace -When a governed run halts locally, send a **PHI-free** break descriptor to the +When a governed run halts locally, send a **PHI/PII-free** break descriptor to the workspace so the halt is visible centrally, without the recording ever leaving the machine: diff --git a/docs/get-started/what-works-today.md b/docs/get-started/what-works-today.md index c9a6be8..317dc68 100644 --- a/docs/get-started/what-works-today.md +++ b/docs/get-started/what-works-today.md @@ -60,14 +60,14 @@ it carries consequential work. | Citrix / VDI backend | **Exploratory** | The pixel-first mechanism (the same remote-display adapter, identity gate, and effect verification as every substrate) is implemented, but no real Citrix ICA/HDX environment has been qualified yet. | Each Citrix/VDI workflow must be qualified in its real ICA/HDX environment, where the client, latency, compression, DPI, lock-screen, input, identity, and effect behavior are exercised against the actual application, before it carries consequential work. | | Desktop authoring GUI and tray | **Supported** | The published 0.1.1 prerelease provides install/uninstall-qualified native packages across the six targeted platform/architecture variants. | The current prerelease qualifies packaging and removal; the complete record -> compile -> replay -> teach cockpit remains an integration track. | | Hosted CLI connectivity | **Supported / public offer** | `login`, exact-hash artifact preparation/upload, one-time runtime validation, bound replacement activation, and `report-break` connect the local engine to the live control plane. | Upload requires destination policy and an approved sanitized derivative; checkout never bypasses an egress refusal. | -| Artifact sanitation and local review | **Supported / launch gate** | The sanitized-derivative pipeline inventories, transforms, rescans, manifests, hashes, and supports local review/approval. | The raw original remains sensitive; unknown or unresolved content is refused; runtime observations can reintroduce PHI. | +| Artifact sanitation and local review | **Supported / launch gate** | The sanitized-derivative pipeline inventories, transforms, rescans, manifests, hashes, and supports local review/approval. | The raw original remains sensitive; unknown or unresolved content is refused; runtime observations can reintroduce PHI/PII. | | Cross-engine hosted validation | **Supported / launch gate** | `validate-hosted` binds an approved recording and bundle, compiler provenance, strict lint, policy certification, derived risk class, and successful replay report to a one-time Cloud challenge. | It is operator self-attestation signed with the ingest token, not an independently observed certification. Exact deployment policy, risk-class, and deployed compiler-version allowlists still apply. | | Hosted browser recorder and runtime health | **Supported / bounded launch component** | A non-simulated hosted browser session on `openadapt-flow` 1.8.0 produced PNG frames and retained input evidence, assembled a compileable recording, finalized one workflow idempotently, enforced resource limits, and cleaned up ephemeral qualification data. Authenticated live health probes also qualified the exact-version replay and compiler service identities. | Explicitly initiated, public-HTTPS, non-regulated authoring only. Raw observations remain private inside the declared hosted boundary. Health proves deployed service identity and reachability, not a paid checkout-to-run lifecycle or successful managed replay. | | Hosted dashboard/control plane | **Supported / public offer** | Authentication, organizations, exact-hash bundle ingest, immutable run admission, browser runner orchestration, structural reports, replacement activation, billing, and metering form the managed lifecycle. | Production uses live dependencies and fails unavailable rather than substituting mock behavior. | | Hosted execution | **Supported / public offer** | Live Stripe Checkout connects onboarding and subscription entitlements to managed browser execution; the runner verifies exact admitted bundle bytes and authenticated callbacks. | The public subscription covers approved browser workflows. Other substrates use separately scoped deployments and commercial terms. Checkout does not create an SLA or certification. | | Air-gapped on-prem package | **Supported** | A local queue, systemd unit, minimized hash-chained audit log, and air-gap checks are provided. | Full-disk encryption and operational hardening remain operator/deployment responsibilities. | -| Control-plane-managed customer cloud (BYOC) | **Experimental** | An outbound-connector pull queue, per-connector authentication, and a customer-owned storage handoff are implemented, but the lane is disabled on the live hosted path and no connector transport ships in the engine yet. | Qualify the actual substrate and destination; PHI-bearing runtime data must not cross into a shared boundary. | -| Hosted desktop runner (in OpenAdapt's cloud) | **Internal only** | A Windows-in-cloud runner and its enqueue/callback contract are implemented, but the lane is licensing-gated and a fail-closed flag restricts it to an internal allowlist. | This lane is not part of any public commercial offer. Hosted in-our-cloud desktop, RDP, and Citrix execution is not sold today; those substrates run self-hosted or on-prem in the customer boundary, with control-plane-managed BYOC as an Experimental lane, and are scoped separately from the public browser offer and qualified per workflow. Multi-tenant hosting of the desktop substrate in OpenAdapt's cloud is deferred. | +| BYOC / customer-controlled execution | **Supported / scoped deployment** | A connector and customer-storage contract support keeping the data plane inside an approved customer boundary. | Qualify the actual substrate and destination; PHI/PII-bearing runtime data must not cross into a shared boundary. | +| Hosted desktop runner | **Supported** | A Windows runner contract and implementation path exist. | Desktop subscriptions and deployments are scoped separately from the public browser offer and qualified per workflow. | ## Before using consequential data @@ -79,7 +79,7 @@ Treat the matrix as a starting point, not an authorization. For each workflow: record exists. 4. Certify against a workload-specific policy. 5. Exercise expected drift and failure cases with repeated trials. -6. Review the PHI boundary, storage encryption, logs, model egress, updates, +6. Review the PHI/PII boundary, storage encryption, logs, model egress, updates, rollback, and operator approval design. 7. If an artifact crosses a boundary, inspect its sanitation manifest and approve the exact derivative hash required by policy. diff --git a/docs/get-started/what-you-get.md b/docs/get-started/what-you-get.md index 9b6550a..db697c6 100644 --- a/docs/get-started/what-you-get.md +++ b/docs/get-started/what-you-get.md @@ -47,7 +47,7 @@ openadapt flow emit-mcp bundle --out server.py ## Privacy of the artifacts -The `REPORT.md` and console logs can be processed by the PHI sanitizer on the +The `REPORT.md` and console logs can be processed by the PHI/PII sanitizer on the persist/log path (Presidio-backed, via the optional `privacy` extra). The compiled bundle and `report.json` keep literal identifiers on purpose: they are the identity check and the audit trail, protected by a documented boundary diff --git a/docs/guides/deploy-on-prem.md b/docs/guides/deploy-on-prem.md index b4de6c5..7956cff 100644 --- a/docs/guides/deploy-on-prem.md +++ b/docs/guides/deploy-on-prem.md @@ -33,8 +33,8 @@ stack locally: - **Deployment wiring**: a single [`deployment.yaml`](../reference/deployment-config.md) (backend URL, system-of-record effect verifier, actuation, durable runtime, policy). An empty file = fully local, zero egress. -- **PHI scrubbing**: the optional `privacy` extra (Presidio-backed), fail-closed. -- **A local, append-only audit log**: hash-chained, PHI-free. +- **PHI/PII scrubbing**: the optional `privacy` extra (Presidio-backed), fail-closed. +- **A local, append-only audit log**: hash-chained, PHI/PII-free. - **Durable state**: a halted run pauses durably and is resumable locally. - **(Optional) an on-prem VLM appliance**: a LAN-only GPU box, off by default. @@ -103,8 +103,8 @@ defence-in-depth layers: kernel drops all IP traffic for the runner unless a LAN CIDR is explicitly allow-listed); the Docker Compose alternative puts the runner on an `internal: true` network with no gateway to the internet. -3. **Fail-closed PHI handling.** `OPENADAPT_FLOW_SCRUB=on` makes a missing - scrubbing capability *abort* rather than write plaintext PHI. +3. **Fail-closed PHI/PII handling.** `OPENADAPT_FLOW_SCRUB=on` makes a missing + scrubbing capability *abort* rather than write plaintext PHI/PII. 4. **Attestation.** `verify-airgap.sh` scans your config and environment for any off-LAN URL or cloud key; with `--probe` it actively curls a public canary and **asserts the call fails**; with `--audit` it walks the audit-log hash chain. @@ -119,7 +119,7 @@ The firewall is the real control; the `internal:true` network, `IPAddressDeny=an and `verify-airgap.sh` are defence-in-depth and attestation, not a replacement for a correct network boundary. -## PHI scrubbing on the persist and log paths +## PHI/PII scrubbing on the persist and log paths The sanitizer processes `REPORT.md` and console logs. Missing dependencies, unsupported configuration, and sanitizer errors fail closed, but detector false @@ -137,7 +137,7 @@ holds the disk key). At-rest protection has three layers: | Layer | Control | Real today? | |---|---|---| -| The disk holding `storage_root` (bundles, runs, audit, frames) | **Operator full-disk encryption** (LUKS / BitLocker / FileVault) | REAL: the primary PHI-at-rest control. Operator-provisioned | +| The disk holding `storage_root` (bundles, runs, audit, frames) | **Operator full-disk encryption** (LUKS / BitLocker / FileVault) | REAL: the primary PHI/PII-at-rest control. Operator-provisioned | | The identity band inside `workflow.json` | **Salted-hash `identity_template`** (no plaintext name / DOB / MRN; optional external `OPENADAPT_FLOW_IDENTITY_SALT`) | REAL. A hash of a low-entropy identifier is brute-forceable by a holder of both bundle and salt, so it is **not** a cryptographic seal | | The bundle `workflow.json` + durable checkpoints | **Opt-in AES-256-GCM sealing** via `OPENADAPT_BUNDLE_KEY` (`Workflow.save(encrypt=True)`; scrypt-derived key) | REAL (opt-in, shipped). A wrong/missing key or tampered ciphertext fails loud and safe | | `templates/*.png` (recorded screen crops of identifiers) | Full-disk encryption + governance guards (kept out of git); opt-in Presidio image redaction | REAL for FDE + guard, but see the caveat | @@ -152,22 +152,22 @@ export OPENADAPT_BUNDLE_KEY=… # seals workflow.json + checkpoints ( !!! danger "Honest at-rest caveat: the identifier crops" The identity check needs a **rendered crop of the identifier** (an image of the MRN / name as it appeared on screen), stored as `templates/*.png`. These - crops are **rendered pixels of PHI**, and they are **not yet sealed inside + crops are **rendered pixels of PHI/PII**, and they are **not yet sealed inside the per-bundle encrypted container**; they still rely on **operator full-disk encryption**. Enable `OPENADAPT_BUNDLE_KEY` for the JSON and checkpoints, but do **not** represent the whole bundle as cryptographically sealed. Full-disk encryption remains the baseline control for the template crops. Treat every - bundle as PHI. + bundle as PHI/PII. ## The local audit log `audit/audit.log` is a tamper-evident **index** over the runs: newline-delimited -JSON, append-only, **PHI-free by construction**. Each record carries a UTC +JSON, append-only, **PHI/PII-free by construction**. Each record carries a UTC timestamp, an event (`queued` / `started` / `verified` / `halted` / `failed` / `resumed`), an opaque job id, the bundle basename, the run-dir path, the process exit code, the OS actor, an operator note, and `prev_sha`, a sha256 chain to the previous line, so any silent edit or deletion breaks every subsequent hash and is -caught by `verify-airgap.sh --audit`. The per-step PHI detail stays beside each +caught by `verify-airgap.sh --audit`. The per-step PHI/PII detail stays beside each run in `runs//report.json` under the encrypted volume; the audit log records *that* a run happened and *how it ended*, never the underlying record data. @@ -232,7 +232,7 @@ install pulls no model). | `templates/*.png` (identifier crops) | Yes (rendered pixels) | Full-disk encryption + governance guards (not yet inside the per-bundle seal) | | `report.json` | Yes, on purpose | Documented boundary; it is the audit trail | | `REPORT.md`, console logs | Sanitizer applied when `OPENADAPT_FLOW_SCRUB=on` | Processing errors fail closed; review for detector misses before egress | -| `audit/audit.log` | No (PHI-free by construction) | Append-only, hash-chained | +| `audit/audit.log` | No (PHI/PII-free by construction) | Append-only, hash-chained | | Identity crops to the appliance | Yes | Trusted local boundary; verify egress and retention controls | | Deterministic replay path | n/a | No OpenAdapt-hosted dependency; target and verifier traffic remains | @@ -241,12 +241,20 @@ install pulls no model). **Not legal advice, and not a compliance guarantee.** OpenAdapt provides the software substrate for running compiled automations on-premise. Whether a given deployment satisfies PHIPA, PIPEDA, HIPAA, or another regime is a determination -for the deploying organization's privacy officer and counsel. We do **not** sign -a BAA, and no part of the software is a certification. What the software provides -(PHI processed locally, protected at rest by full-disk encryption plus in-bundle -identity hashing plus opt-in AES-256-GCM sealing, and a local append-only audit -trail) is the technical substrate those agreements attest to. The full boundary -list is in the engine repo's `deploy/on-prem/COMPLIANCE.md`. +for the deploying organization's privacy officer and counsel. In this +self-hosted deployment PHI stays inside your environment and does not enter +OpenAdapt's infrastructure, so the software runs as an on-premise vendor rather +than a business associate for that shape, and a BAA is not the operative +instrument for it. Where your procurement requires written terms, a US HIPAA +Business Associate Agreement, or for an Ontario clinic a PHIPA service-provider +agreement, can be signed following review. Hosted processing of PHI inside +OpenAdapt's infrastructure, which would require a BAA and a HIPAA risk analysis, +is not offered today. No part of the software is a certification. What the +software provides (PHI processed locally, protected at rest by full-disk +encryption plus in-bundle identity hashing plus opt-in AES-256-GCM sealing, and +a local append-only audit trail) is the technical substrate those agreements +attest to. The full boundary list is in the engine repo's +`deploy/on-prem/COMPLIANCE.md`. For the strictest deployments: install with the `privacy` extra, run the appliance locally (or not at all, keeping the deterministic path only), set diff --git a/docs/guides/hosted.md b/docs/guides/hosted.md index 6a3580b..da71479 100644 --- a/docs/guides/hosted.md +++ b/docs/guides/hosted.md @@ -33,11 +33,11 @@ price you pay at Checkout. | Structural run history and reports | **Beta / public offer** | Safety depends on the workflow's configured identity, effect, and policy checks. Repair and validation remain local. | | Checkout, portal, entitlements, metering | **Beta / public offer** | Live Stripe Checkout, signed webhooks, entitlements, usage, and the billing portal form one managed subscription contract. | | Self-hosted browser execution | **Beta** | No hosted account required. | -| Windows UIA | **Early access** | The exact in-tree WinForms matrix passed 3/3 with an independent SQLite oracle and 3/3 stale/ambiguity refusals. Windows subscriptions and deployments are ordered separately from the public browser offer and qualified per workflow. | -| Native macOS | **Early access** | One macOS 15.7.3 arm64 host produced 3/3 exact-byte TextEdit effects plus a two-window ambiguity refusal. Native macOS subscriptions and deployments are ordered separately from the public browser offer and qualified per workflow. | -| RDP | **Early access** | One Parallels Windows 11 VM produced 3/3 exact guest-file effects through network RDP, with 0 silent incorrect successes, 0 over-halts, and 0 model calls. RDP subscriptions and deployments are ordered separately from the public browser offer and qualified per workflow. | -| Citrix / VDI | **Exploratory** | The pixel-first mechanism shares the same identity gate and effect verification as every substrate, but no real ICA/HDX environment has been qualified yet; ordered separately from the public browser offer and qualified in its real ICA/HDX environment per workflow before consequential use. | -| Regulated runtime data | **Customer-controlled boundary** | Use a scoped BYOC/on-prem deployment when live screens necessarily contain PHI. | +| Windows UIA | **Supported / scoped deployment** | The exact in-tree WinForms matrix passed 3/3 with an independent SQLite oracle and 3/3 stale/ambiguity refusals. Windows subscriptions and deployments are ordered separately from the public browser offer and qualified per workflow. | +| Native macOS | **Supported / scoped deployment** | One macOS 15.7.3 arm64 host produced 3/3 exact-byte TextEdit effects plus a two-window ambiguity refusal. Native macOS subscriptions and deployments are ordered separately from the public browser offer and qualified per workflow. | +| RDP | **Supported / scoped deployment** | One Parallels Windows 11 VM produced 3/3 exact guest-file effects through network RDP, with 0 silent incorrect successes, 0 over-halts, and 0 model calls. RDP subscriptions and deployments are ordered separately from the public browser offer and qualified per workflow. | +| Citrix / VDI | **Supported / scoped deployment** | Driven pixel-first through the same identity gate and effect verification as every substrate; ordered separately from the public browser offer and qualified in its real ICA/HDX environment per workflow. | +| Regulated runtime data | **Customer-controlled boundary** | Use a scoped BYOC/on-prem deployment when live screens necessarily contain PHI/PII. | The public subscription covers approved browser workflows. Windows, native macOS, RDP, Citrix, regulated customer-controlled execution, professional @@ -178,7 +178,7 @@ and remains subject to its runtime, entitlement, and data-boundary gates. ## What “scrubbed” means -Compilation does **not** make a recording or bundle PHI-free. Scrubbing is a +Compilation does **not** make a recording or bundle PHI/PII-free. Scrubbing is a separate local derivation protocol: The sanitized derivative is admitted by its manifest-bound cryptographic derivative hash. @@ -273,14 +273,14 @@ the automatic policy ran. A recording can replace a patient name with a parameter, while the live EMR screen still displays that patient's name during execution. Runtime frames, OCR, accessibility text, model inputs, reports, and effect evidence can -therefore reintroduce PHI. +therefore reintroduce PHI/PII. Use these rules: - Sanitized authoring derivatives may cross a destination permitted by policy. - Runtime values are injected separately and are not written back into the sanitized authoring derivative. -- PHI-bearing runtime observations remain inside the declared trusted +- PHI/PII-bearing runtime observations remain inside the declared trusted execution boundary. - A remote model is a separate destination and must be approved explicitly; healthy replay does not need one. @@ -299,7 +299,7 @@ Use these rules: | Approved derivative -> verified customer endpoint | Allow under that customer's destination policy. | | Raw or unresolved artifact -> any remote endpoint | Refuse. | | Explicit hosted-recorder observations -> hosted recording boundary | Allow only for an entitled, public-HTTPS, non-regulated session that the user starts deliberately. | -| PHI-bearing runtime observation -> shared managed boundary | Refuse unless that exact regulated service and legal boundary are configured. | +| PHI/PII-bearing runtime observation -> shared managed boundary | Refuse unless that exact regulated service and legal boundary are configured. | | Minimized break descriptor -> control plane | Allow after schema validation and sanitation. | | Unknown destination | Refuse. | diff --git a/docs/guides/index.md b/docs/guides/index.md index 542cc30..1cc2dfe 100644 --- a/docs/guides/index.md +++ b/docs/guides/index.md @@ -30,7 +30,7 @@ How-to guides for real deployments. Each assumes you have - [__Deploy on-prem__](deploy-on-prem.md) - Keep data in the building: PHI scrubbing and the on-prem VLM appliance. + Keep data in the building: PHI/PII scrubbing and the on-prem VLM appliance. - [__The hosted option__](hosted.md) @@ -39,7 +39,7 @@ How-to guides for real deployments. Each assumes you have - [__Security and data handling__](security-and-data-handling.md) - The pilot-approval dossier: local-by-default data flow, PHI posture, + The pilot-approval dossier: local-by-default data flow, PHI/PII posture, secrets, verification and audit, and the IT-review FAQ. - [__Security and deployment review__](security-review.md) diff --git a/docs/guides/security-and-data-handling.md b/docs/guides/security-and-data-handling.md index 0a6671b..1c797ec 100644 --- a/docs/guides/security-and-data-handling.md +++ b/docs/guides/security-and-data-handling.md @@ -87,11 +87,11 @@ part of the local-execution path. The [data-boundary table](security-review.md#data-boundary-answers) states exactly which component can see and transmit what. -## PHI posture: scrubbed where shareable, fail-closed where regulated +## PHI/PII posture: scrubbed where shareable, fail-closed where regulated -OpenAdapt treats PHI handling as an engineering surface with a published map. +OpenAdapt treats PHI/PII handling as an engineering surface with a published map. [PRIVACY.md](https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/PRIVACY.md) -enumerates every path where PHI is persisted, logged, or transmitted, and names +enumerates every path where PHI/PII is persisted, logged, or transmitted, and names the control on each. The posture in brief: - **Scrubbing on the persist and log paths.** PHI/PII scrubbing is provided by @@ -102,7 +102,7 @@ the control on each. The posture in brief: scrubbed before printing. - **A regulated deployment pins `OPENADAPT_FLOW_SCRUB=on` and fails closed.** Under `on`, a missing scrubbing capability aborts the run instead of writing - plaintext PHI, and image redaction of persisted frames is implied: a + plaintext PHI/PII, and image redaction of persisted frames is implied: a compliance-pinned run cannot leave unredacted full-frame screenshots in the shareable report. The on-prem queue refuses to start unless scrub is `on`. ([PRIVACY.md](https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/PRIVACY.md), @@ -116,7 +116,7 @@ the control on each. The posture in brief: AES-256-GCM sealing (`Workflow.save(encrypt=True)` with `OPENADAPT_BUNDLE_KEY`) encrypts `workflow.json`, every template screenshot crop, and durable run checkpoints into authenticated containers. No - cleartext PHI-bearing screenshot remains on disk in an encrypted bundle, and + cleartext PHI/PII-bearing screenshot remains on disk in an encrypted bundle, and keyed loads decrypt in memory only. A wrong key or a tampered ciphertext fails loudly, never partially. The identity band in a compiled bundle is a salted hash, not plaintext. @@ -131,7 +131,7 @@ the control on each. The posture in brief: - **Honest boundaries where scrubbing would break safety.** The recorded identity evidence and the run's identity audit trail intentionally retain literal identifiers. Scrubbing them would defeat the wrong-record check they - exist to power. Those artifacts are governed as PHI-at-rest inside your + exist to power. Those artifacts are governed as PHI/PII-at-rest inside your boundary (filesystem controls, retention, full-disk encryption), and the map says so explicitly rather than pretending otherwise. ([PRIVACY.md](https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/PRIVACY.md)) @@ -186,7 +186,7 @@ you can hand to an auditor: ([Read and audit run reports](run-reports.md), [PRIVACY.md](https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/PRIVACY.md)) - **A tamper-evident index on-prem.** The on-prem package adds an append-only, - hash-chained, PHI-free audit log over runs and release changes; any silent + hash-chained, PHI/PII-free audit log over runs and release changes; any silent edit breaks every subsequent hash and is caught by the attestation script. ([ON_PREM.md](https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/ON_PREM.md)) - **You can prove the no-egress posture, repeatedly.** `verify-airgap.sh` scans @@ -245,7 +245,7 @@ bundles and injected from the environment at replay; deployment and hosted tokens live in your secret store or the OS keychain. **What is encrypted?** -In transit: the PHI-bearing desktop control channel is TLS with per-run +In transit: the PHI/PII-bearing desktop control channel is TLS with per-run certificate pinning, fail-closed. At rest: opt-in AES-256-GCM sealing for the bundle, its screenshot crops, and checkpoints, layered on operator full-disk encryption. Key management (KMS, rotation, escrow) remains yours. OpenAdapt diff --git a/docs/guides/security-review.md b/docs/guides/security-review.md index a91fe05..e0b104a 100644 --- a/docs/guides/security-review.md +++ b/docs/guides/security-review.md @@ -26,16 +26,16 @@ enables model grounding and configures an appliance. | Question | Current answer | |---|---| | Which components see screenshots? | The recorder and runner do. A configured model endpoint may receive a permitted crop or frame. Generic hosted upload admits only an approved sanitized derivative. The separate, explicitly initiated hosted recorder sees raw observations for public, non-regulated targets inside its declared hosted boundary. | -| Which components can transmit screenshots? | Deterministic local replay does not transmit them. The optional model client can send permitted data to its configured endpoint. Generic hosted upload sends the manifest-bound derivative, never the source by assumption. The hosted recorder transmits its raw frames inside its declared non-regulated authoring boundary. PHI-bearing runtime screenshots stay inside the declared trusted execution boundary. | +| Which components can transmit screenshots? | Deterministic local replay does not transmit them. The optional model client can send permitted data to its configured endpoint. Generic hosted upload sends the manifest-bound derivative, never the source by assumption. The hosted recorder transmits its raw frames inside its declared non-regulated authoring boundary. PHI/PII-bearing runtime screenshots stay inside the declared trusted execution boundary. | | What can the sanitizer upload? | Only the exact derivative whose inventory, transformations, rescan, unresolved findings, review state, destination, and hash satisfy policy. Unknown, symlinked, unsupported, or unresolved content aborts instead of passing through unchanged. | -| What does local review establish? | It lets an authorized operator compare the sanitized derivative, correct redactions, and approve the exact hash. Review adds context but is not mathematical proof that no PHI remains. Any later modification invalidates approval. | +| What does local review establish? | It lets an authorized operator compare the sanitized derivative, correct redactions, and approve the exact hash. Review adds context but is not mathematical proof that no PHI/PII remains. Any later modification invalidates approval. | | Does Cloud independently witness sanitation review? | No. Cloud accounts for every accepted ZIP byte and verifies the manifest/hash contract and submitting ingest token, but it does not observe the local viewer or rerun OCR/NER. Reviewer identity, separation of duties, and evidence custody remain deployment controls. | | Can an uploader claim automatic sanitation approval? | No. Automatic approval is disabled by default. If a deployment enables it, the exact approval envelope must carry an HMAC from a deployment-allowlisted key ID; the ingest token cannot enable or forge that capability by itself. This still proves signer possession, not independent de-identification. | | What happens for an unknown deployment or destination? | The request is refused before an egress policy is selected. It never falls back to the shared cloud lane. A verified customer endpoint can have a different policy from an OpenAdapt-managed endpoint. | | Where are workflow secrets stored? | Password fields and fields named with `--secret` are not written to recordings, bundles, event logs, or frames. Replay resolves them from `OPENADAPT_FLOW_SECRET_`. Deployment credentials should be injected from the operator's secret store, not committed to YAML. | | Where is the hosted ingest token stored? | Resolution order is the CLI flag, `OPENADAPT_INGEST_TOKEN`, OS keychain, then an existing config migration token. The current CLI requires an explicit flag before using plaintext config storage. | -| Which artifacts may contain PHI? | Treat raw recordings, bundles, templates, `report.json`, checkpoints, live frames, OCR/accessibility text, model inputs, and effect evidence as PHI-bearing until the applicable policy proves otherwise. The sanitized derivative is separate from the source. | -| What leaves a regulated runner? | Only destinations and artifact classes allowed by the deployment policy. Minimized control metadata and approved derivatives may cross an approved boundary; PHI-bearing runtime values and frames remain inside it. Target-app and verifier traffic remains deployment-specific. | +| Which artifacts may contain PHI/PII? | Treat raw recordings, bundles, templates, `report.json`, checkpoints, live frames, OCR/accessibility text, model inputs, and effect evidence as PHI/PII-bearing until the applicable policy proves otherwise. The sanitized derivative is separate from the source. | +| What leaves a regulated runner? | Only destinations and artifact classes allowed by the deployment policy. Minimized control metadata and approved derivatives may cross an approved boundary; PHI/PII-bearing runtime values and frames remain inside it. Target-app and verifier traffic remains deployment-specific. | | What happens during model-assisted repair? | The deterministic ladder runs first. If model grounding is explicitly allowed, a proposal is still subject to the identity and postcondition gates and is counted in the report. A model proposal is not an automatic safety exemption. | | Can model inference run on-prem? | Yes. The optional VLM service is designed for a private-LAN deployment with no retention. Keep model grounding disabled if the deployment does not need it. | | Is upload code physically absent from regulated builds? | The compiler does not currently publish a separate, verified "regulated binary" exclusion guarantee. Enforce no-egress at the host/network boundary and verify the installed artifact. The desktop recorder documents build-time exclusions for its own enterprise builds; that is not a blanket compiler guarantee. | @@ -45,7 +45,7 @@ enables model grounding and configures an appliance. | Can a retried run execute twice? | Live clients supply a request-bound idempotency key, and the database permits one queued/running run per workflow. Dispatch is claimed once and the provider call ID is recorded. If acknowledgement is lost, the run remains reserved and single-flight for callback or operator/provider reconciliation; timeout alone does not authorize a refund and retry. | !!! danger "Approval applies to exact bytes" - Compilation does not make a bundle PHI-free. Upload requires a sanitized + Compilation does not make a bundle PHI/PII-free. Upload requires a sanitized derivative with a passing manifest and, when policy requires it, local approval of the exact derivative hash. If sanitation removes identity evidence needed for replay, parameterize it or keep the workflow in its @@ -72,7 +72,7 @@ Every run produces a human-readable `REPORT.md` and machine-readable postconditions, effects, heals, and the halt reason. The on-prem queue adds a schema-minimized, append-only hash-chained audit log. Minimization reduces exposure but does not prove that operator detail or future schema changes cannot -contain PHI; review and test the emitted schema. +contain PHI/PII; review and test the emitted schema. A hash chain is tamper-evident only while its trusted head and access controls remain trustworthy. It is not an externally anchored signature service. The diff --git a/docs/guides/troubleshooting.md b/docs/guides/troubleshooting.md index 1fc1c07..fa67cb2 100644 --- a/docs/guides/troubleshooting.md +++ b/docs/guides/troubleshooting.md @@ -51,7 +51,7 @@ disambiguate confusable glyphs. See halting, without weakening the wrong-record guarantee. See [the halt-learn loop](../concepts/halt-learn-loop.md) and [`teach`](../reference/cli.md#teach). -- **`report-break`** to surface the halt centrally (PHI-free) for triage: +- **`report-break`** to surface the halt centrally (PHI/PII-free) for triage: [`report-break`](../reference/cli.md#report-break). - Where the render is stable, capturing the identifier crop at compile time and using a higher-fidelity backend (structured a11y/DOM text instead of pixels) @@ -84,9 +84,9 @@ token, or the durable upload queue is holding items to retry. If it was revoked, mint a new one at `app.openadapt.ai/dashboard/settings/ingest` (see [Connect to a cloud workspace](../desktop/connect-to-cloud.md)). -- Confirm you are on the right lane: **regulated/PHI recordings are not pushed to +- Confirm you are on the right lane: **regulated/PHI/PII recordings are not pushed to the cloud**, they stay local on the [on-prem lane](deploy-on-prem.md). A refused - PHI-bearing push is the fail-closed PHI boundary working as intended. + PHI/PII-bearing push is the fail-closed PHI/PII boundary working as intended. ## The Windows agent landed in session 0 {#session-0} @@ -102,7 +102,7 @@ blank screen and input goes into the void. See session (session 1)**, not as a session-0 service. Launch it in the logged-on user's session. It binds to loopback by default and supports an optional bearer token, `OAFLOW_AGENT_TOKEN`, so its execute channel is not left unauthenticated in -a PHI deployment. For Citrix/RDP, ensure the agent runs inside the same +a PHI/PII deployment. For Citrix/RDP, ensure the agent runs inside the same interactive session that renders the application. ## `openadapt connect` fails with `No such command 'connect'` {#connect-no-such-command} diff --git a/docs/index.md b/docs/index.md index af6b30d..1dce399 100644 --- a/docs/index.md +++ b/docs/index.md @@ -142,7 +142,7 @@ qualification; they are not entitlements of the browser subscription. The [hosted guide](guides/hosted.md), [qualification evidence](get-started/what-works-today.md), and commercial terms define the accepted scope. Artifacts cross boundaries only as approved sanitized -derivatives; PHI-bearing runtime observations stay inside their declared trusted +derivatives; PHI/PII-bearing runtime observations stay inside their declared trusted execution boundary. --- diff --git a/docs/reference/cli.md b/docs/reference/cli.md index d77ae39..d5fef0b 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -559,7 +559,7 @@ the original inside its trusted runtime boundary. ## report-break Read a halted run's `report.json` and emit a scrubbed, schema-minimized halt -descriptor. The recording stays local. A PHI-boundary rejection retries with a +descriptor. The recording stays local. A PHI/PII-boundary rejection retries with a harder scrub and can fall back to local-only. ```bash diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 2ca80a4..5581f78 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -20,7 +20,7 @@ See [Parameters and secrets](../guides/parameters-and-secrets.md). | Variable | Purpose | |---|---| -| `OPENADAPT_FLOW_SCRUB` | `on` runs the PHI sanitizer over `REPORT.md` and console logs on the persist and log path. Missing dependencies, invalid config, and processing errors fail closed. Requires the `privacy` extra (`pip install 'openadapt[privacy]'`) and the allowlisted spaCy model. | +| `OPENADAPT_FLOW_SCRUB` | `on` runs the PHI/PII sanitizer over `REPORT.md` and console logs on the persist and log path. Missing dependencies, invalid config, and processing errors fail closed. Requires the `privacy` extra (`pip install 'openadapt[privacy]'`) and the allowlisted spaCy model. | The compiled bundle and `report.json` keep literal identifiers behind a documented boundary and are **not** scrubbed by this flag; they are the identity @@ -101,7 +101,7 @@ variables supply its endpoint and credentials, keeping them out of the YAML. | Variable | Purpose | |---|---| -| `OAFLOW_AGENT_TOKEN` | Optional bearer token for the [desktop in-session agent server](../concepts/backends.md#the-in-session-agent-the-session-0-problem). Its `/execute_windows` channel is remote code execution by contract; the server binds to loopback by default, and a token makes every request authenticate. Set it in any PHI deployment that exposes the agent beyond loopback. | +| `OAFLOW_AGENT_TOKEN` | Optional bearer token for the [desktop in-session agent server](../concepts/backends.md#the-in-session-agent-the-session-0-problem). Its `/execute_windows` channel is remote code execution by contract; the server binds to loopback by default, and a token makes every request authenticate. Set it in any PHI/PII deployment that exposes the agent beyond loopback. | ## Benchmark (agent arm only) From b7b0d6680831c8c42f78844050ef503f22ad81ee Mon Sep 17 00:00:00 2001 From: abrichr Date: Tue, 21 Jul 2026 04:38:47 -0400 Subject: [PATCH 2/2] docs: align regulated deployment copy with shipped sealing --- docs/guides/deploy-on-prem.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/guides/deploy-on-prem.md b/docs/guides/deploy-on-prem.md index 7956cff..e207f8a 100644 --- a/docs/guides/deploy-on-prem.md +++ b/docs/guides/deploy-on-prem.md @@ -129,7 +129,7 @@ the identity check and the audit trail, protected by a documented boundary rathe than by redaction. Production images must stage the allowlisted spaCy model locally, not download one at runtime. -## Encryption at rest: setup and the honest caveat +## Encryption at rest Everything lives under `storage_root` (default `/srv/openadapt`), which you place on a **full-disk-encrypted** volume (LUKS / BitLocker / FileVault; OpenAdapt never @@ -140,24 +140,23 @@ holds the disk key). At-rest protection has three layers: | The disk holding `storage_root` (bundles, runs, audit, frames) | **Operator full-disk encryption** (LUKS / BitLocker / FileVault) | REAL: the primary PHI/PII-at-rest control. Operator-provisioned | | The identity band inside `workflow.json` | **Salted-hash `identity_template`** (no plaintext name / DOB / MRN; optional external `OPENADAPT_FLOW_IDENTITY_SALT`) | REAL. A hash of a low-entropy identifier is brute-forceable by a holder of both bundle and salt, so it is **not** a cryptographic seal | | The bundle `workflow.json` + durable checkpoints | **Opt-in AES-256-GCM sealing** via `OPENADAPT_BUNDLE_KEY` (`Workflow.save(encrypt=True)`; scrypt-derived key) | REAL (opt-in, shipped). A wrong/missing key or tampered ciphertext fails loud and safe | -| `templates/*.png` (recorded screen crops of identifiers) | Full-disk encryption + governance guards (kept out of git); opt-in Presidio image redaction | REAL for FDE + guard, but see the caveat | +| `templates/*.png` (recorded screen crops of identifiers) | **AES-256-GCM sealing with the bundle key** plus full-disk encryption and governance guards | REAL when bundle encryption is enabled; plaintext crops are removed after sealing and authenticated ciphertext is verified on load | Enable the per-bundle seal for cryptographic at-rest protection that does not depend solely on the volume: ```bash -export OPENADAPT_BUNDLE_KEY=… # seals workflow.json + checkpoints (AES-256-GCM) +export OPENADAPT_BUNDLE_KEY=… # seals workflow.json, template crops, and checkpoints ``` -!!! danger "Honest at-rest caveat: the identifier crops" +!!! warning "Identifier crops remain regulated data" The identity check needs a **rendered crop of the identifier** (an image of the MRN / name as it appeared on screen), stored as `templates/*.png`. These - crops are **rendered pixels of PHI/PII**, and they are **not yet sealed inside - the per-bundle encrypted container**; they still rely on **operator full-disk - encryption**. Enable `OPENADAPT_BUNDLE_KEY` for the JSON and checkpoints, but - do **not** represent the whole bundle as cryptographically sealed. Full-disk - encryption remains the baseline control for the template crops. Treat every - bundle as PHI/PII. + crops are **rendered pixels of PHI/PII**. With bundle encryption enabled, + OpenAdapt seals them as authenticated `*.enc` assets and removes the + plaintext copies; replay decrypts them in memory. Encryption does not make + them non-regulated, so keep full-disk encryption, access controls, retention, + and key-management controls in place and treat every bundle as PHI/PII. ## The local audit log @@ -248,8 +247,9 @@ than a business associate for that shape, and a BAA is not the operative instrument for it. Where your procurement requires written terms, a US HIPAA Business Associate Agreement, or for an Ontario clinic a PHIPA service-provider agreement, can be signed following review. Hosted processing of PHI inside -OpenAdapt's infrastructure, which would require a BAA and a HIPAA risk analysis, -is not offered today. No part of the software is a certification. What the +OpenAdapt's infrastructure is governed by a signed BAA and a +deployment-specific HIPAA risk analysis before regulated data is admitted. No +part of the software is a certification. What the software provides (PHI processed locally, protected at rest by full-disk encryption plus in-bundle identity hashing plus opt-in AES-256-GCM sealing, and a local append-only audit trail) is the technical substrate those agreements