Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CAPABILITIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ improvising or retrying when something is off.
| Admit a record check only after a fault suite written to a store copy shows it catches every fault it claims, and sign its coverage into the receipt | On main | Synthetic (in-memory REST store, SQLite copy) | `openadapt_flow/fault_gate.py`, `scaffold-verifier --fault-gate`, `verify-run` `admission:` |
| Check that the saved record matches its source document, not only the parameters: intake keeps each value's line, a second reading must agree before a guarded save, and a round trip compares the read-back with the document | On main | Synthetic (MockMed, text referral) | `openadapt_flow/provenance.py`, `intake`, `verify-run --provenance`, guarded save |
| Guarded save: a safety layer any agent wraps around one write (check the record, hold for approval, read back) | On main ([#1258](https://github.com/OpenAdaptAI/OpenAdapt/pull/1258)) | Synthetic | `GUARDED_SAVE.md` |
| A person's approval in Desktop is signed with a key kept behind Touch ID on a Mac: one-prompt setup in the app, a prompt for every answer, and Flow never sees the key | On main ([#1500](https://github.com/OpenAdaptAI/OpenAdapt/pull/1500)) | Unit tests; opt-in test on a real Secure Enclave | `packages/desktop/openadapt_desktop/approver_keychain.py`, [APPROVAL_MODES.md](packages/flow/docs/APPROVAL_MODES.md#the-approver-key) |
| Draft a record check from the demonstration's write steps (`scaffold-verifier`) | Released | Synthetic | `openadapt-flow scaffold-verifier` (a person fills in the draft) |
| Build a working record check from the reads the app made while the person viewed the saved record, and test it against injected bad writes before anyone reviews it | On main ([#1284](https://github.com/OpenAdaptAI/OpenAdapt/pull/1284)) | Synthetic (MockMed, OpenEMR fixture) | `openadapt-flow scaffold-verifier` |
| Check a save on desktop, RDP or Citrix by looking the record up in a separate read-only session | On main ([#1280](https://github.com/OpenAdaptAI/OpenAdapt/pull/1280)) | Synthetic (WinForms, RDP and Citrix stand-ins) | `runtime/effects/` |
Expand Down
1 change: 1 addition & 0 deletions llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ improvising or retrying when something is off.
| Admit a record check only after a fault suite written to a store copy shows it catches every fault it claims, and sign its coverage into the receipt | On main | Synthetic (in-memory REST store, SQLite copy) | `openadapt_flow/fault_gate.py`, `scaffold-verifier --fault-gate`, `verify-run` `admission:` |
| Check that the saved record matches its source document, not only the parameters: intake keeps each value's line, a second reading must agree before a guarded save, and a round trip compares the read-back with the document | On main | Synthetic (MockMed, text referral) | `openadapt_flow/provenance.py`, `intake`, `verify-run --provenance`, guarded save |
| Guarded save: a safety layer any agent wraps around one write (check the record, hold for approval, read back) | On main ([#1258](https://github.com/OpenAdaptAI/OpenAdapt/pull/1258)) | Synthetic | `GUARDED_SAVE.md` |
| A person's approval in Desktop is signed with a key kept behind Touch ID on a Mac: one-prompt setup in the app, a prompt for every answer, and Flow never sees the key | On main ([#1500](https://github.com/OpenAdaptAI/OpenAdapt/pull/1500)) | Unit tests; opt-in test on a real Secure Enclave | `packages/desktop/openadapt_desktop/approver_keychain.py`, [APPROVAL_MODES.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/APPROVAL_MODES.md#the-approver-key) |
| Draft a record check from the demonstration's write steps (`scaffold-verifier`) | Released | Synthetic | `openadapt-flow scaffold-verifier` (a person fills in the draft) |
| Build a working record check from the reads the app made while the person viewed the saved record, and test it against injected bad writes before anyone reviews it | On main ([#1284](https://github.com/OpenAdaptAI/OpenAdapt/pull/1284)) | Synthetic (MockMed, OpenEMR fixture) | `openadapt-flow scaffold-verifier` |
| Check a save on desktop, RDP or Citrix by looking the record up in a separate read-only session | On main ([#1280](https://github.com/OpenAdaptAI/OpenAdapt/pull/1280)) | Synthetic (WinForms, RDP and Citrix stand-ins) | `runtime/effects/` |
Expand Down
14 changes: 14 additions & 0 deletions packages/desktop/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# CHANGELOG


## v0.24.0 (2026-10-24)

### Features

- **desktop**: set up the approver key in the app, behind Touch ID

### Bug Fixes

- **desktop**: a locked Mac isn't a Mac without a Secure Enclave
- **desktop**: re-register a stored approver key only after it opens behind Touch ID
- **desktop**: a Mac that can keep the key behind Touch ID never falls back to a terminal-made key



## v0.23.0 (2026-10-24)

### Bug Fixes
Expand Down
11 changes: 10 additions & 1 deletion packages/desktop/docs/OPERATOR_SCREENS.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,16 @@ How it works:
reaches Flow only through the child process's environment. Flow re-checks
the answer, re-reads the form and runs the right-record check again before
it saves.
- Set the key up once per computer, at a terminal. With
- On a Mac with a Secure Enclave (Apple silicon or a T2 chip), the
approval screen shows **Set up your approver key** in place of Approve
until the key exists. One click and one Touch ID (or login password)
prompt make the key, seal it to the Secure Enclave, keep it in the login
Keychain and register its public key under `approvers` with Flow's own
`register_principal`. Each answer prompts again, and Flow gets only the
signature (`--approver-signer stdio`). Settings > Approver key replaces
the key (the new one is registered before the old one is retired) or
removes it. See `openadapt_desktop/approver_keychain.py`.
- Elsewhere, set the key up once per computer, at a terminal. With
`OPENADAPT_JIT_KEY_PASSPHRASE` set, run `openadapt-flow jit keygen --out
~/.openadapt/approver/desktop-approver.pem`, then a person registers the
public key it prints: `openadapt-flow jit register --role approver
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/openadapt_desktop/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
+-- backends/ Storage backend plugins
"""

__version__ = "0.23.0"
__version__ = "0.24.0"
7 changes: 6 additions & 1 deletion packages/desktop/openadapt_desktop/approver_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,12 @@ def approver_key_environment(


def setup_instructions(route: Route = "desktop") -> str:
"""The one-time terminal steps that make this computer's answers count."""
"""The one-time terminal steps that make this computer's answers count.

For computers where the app can't keep the key behind a presence check
(Windows, Linux, a Mac without a Secure Enclave). On a Mac that can, the
key is set up in OpenAdapt and a file key isn't used.
"""

path = approver_key_path(route)
name = _ROUTES[route][2]
Expand Down
Loading
Loading