Repository navigation
Releases
openadapt-verify 0.2.0
Install without the vision stack
- Depend on
openadapt-flow[receipts]>=3.0.0,<4. Flow 3's base install has
no vision, OCR, browser or GUI stack, sopip install openadapt-verify
installs 21 distributions and 41 MB of site-packages instead of 33 and
302 MB (uv install, Python 3.12, macOS arm64; 67 MB instead of 348 MB with
pip, which also writes bytecode). The direct Pillow requirement is gone. - Support Python 3.10, 3.11 and 3.12. The 3.11 floor came from the Pillow
advisory, and Pillow is no longer installed. tests/test_import_boundary.pyruns every verify module, the quickstart and
both plain-Python helpers in an interpreter that refuses NumPy, OpenCV,
Pillow, RapidOCR, ONNX Runtime, Playwright, Torch and the GUI modules.
Features
openadapt-verify audit: run your own automation through an HTTP fault
proxy and count the wrong saves its success check reports as success
(no_persist,rejected,partial,wrong_value,duplicate,
extra_write,lost_response, andwrong_recordwhen given a field),
judged by the contract's independent read path. The fault goes to the
first write whose body carries a declared value, or that matches
--write-path. Prints a table and writes a
JSON report.--demoaudits two bundled scripts against a synthetic store.openadapt-verify quickstart: three scripted agent writes (correct, wrong
value, claimed but not saved) against REST, SQLite and FHIR R4, and
PostgreSQL and MySQL when given a disposable database. Each gets
CONFIRMED,REFUTEDorUNCERTAINwith a checked signed receipt.@verified(contract): Flow'sWriteGuardas a decorator for sync and async
functions.checked_write(contract, values): the canonicalbegin_writeand
verify_writepair as a context manager, with a portable write receipt.mysqlextra (PyMySQL, MIT). No PostgreSQL extra: its read-only-capable
drivers are LGPL-3.0.
The verifier, ledger, journal, charset guards and receipt code are Flow's;
this package adds no check of its own.
OpenAdapt Desktop 0.30.1
OpenAdapt Desktop 0.30.1: the PyPI package and the native installers.
Signing in this release
- macOS: ad-hoc signed, not notarized. macOS asks you to confirm the first time you open it (System Settings > Privacy & Security).
- Windows: unsigned. SmartScreen warns before install; choose More info > Run anyway.
- Linux: no package signature; the GitHub attestation covers the exact DEB and AppImage bytes.
Verify any download against SHA256SUMS and its GitHub attestation with verify-openadapt-native-release.py, using this release's openadapt-desktop-channel.json.
Native Release Candidates
OpenAdapt Desktop native packages are unadmitted candidates for the
installed authoring, teaching, and local-pairing companion. They bundle and start the
Python sidecar, connect the Tauri/React cockpit to it over local JSON-lines IPC,
and register the openadapt:// operating-system handler. The handler accepts
only the fixed openadapt://connect action and forwards it to the sidecar's
strict, transactional pairing flow.
The canonical compiler and governed runtime remain in openadapt-flow. Each
native installer freezes the exact openadapt-flow[browser,console]==2.4.1
runtime and its playwright==1.61.0 browser automation dependency into the
Desktop sidecar. The console extra is what lets an installed application
serve the attended decision console the mobile decision portal relays; the
browser extra carries the frozen Playwright driver.
Compile, replay, run, and teach therefore work without a separate Python,
openadapt-flow, or playwright installation on PATH. Desktop starts with no
browser download. The first browser workflow downloads the Chromium revision
pinned by the bundled Playwright runtime unless an approved browser cache is
pre-provisioned; native desktop, RDP, and Citrix workflows never enter that
setup path.
The mobile decision portal shows the current phone
interface, one-use pairing flow, local evidence boundary, hosted outbound lane,
runner revalidation, and typed result contract.
Desktop keeps separately licensed media and vision components outside its MIT
installer. On first use, it downloads the exact release-reviewed component for
the current platform, verifies the pinned URL, byte count, and SHA-256, installs
it into a versioned local cache, and re-verifies every extracted file before
loading it. This applies to the managed FFmpeg 8.1.2 runtime used for capture
encoding and the RapidOCR 1.4.4/OpenCV 5.0.0.93 runtime used for visual
resolution. A partial or drifted download is never activated; rerunning the
operation retries it. Enterprise images can pre-provision the same exact cache
without changing the runtime contract. Developer ID builds carry the narrow
macOS library-validation entitlement required to load that independently
signed, hash-verified OpenCV extension; the manifest and full-file cache audit
remain the admission boundary.
Each Desktop version is one immutable openadapt-desktop-vX.Y.Z release in the
OpenAdapt monorepo. It carries the Python wheel and sdist (the same bytes as on
PyPI), these native installers, and the release's own attested channel. The
native version comes from package.json, src-tauri/Cargo.toml, and
src-tauri/tauri.conf.json, with matching entries in both lockfiles; a Desktop
release pull request sets them and the Python version together
(scripts/prepare_release.py). When it merges, the Desktop release workflow
builds and smoke-tests every package, attests the exact bytes, attaches
everything to a draft, publishes the wheel and sdist to PyPI, and publishes the
draft once. If any build fails, nothing is published. OpenAdapt's releases are
immutable, so a published release is never edited; a newer release supersedes
an older one by version. This transaction doesn't change the admission-driven
Production channel. The release policy is in
RELEASES.md.
Artifact labels
Every new filename includes Candidate, the native version, operating system,
architecture, and signing state. The matrix and the signing each platform can
carry:
| Platform | Architectures | Packages | Signing labels |
|---|---|---|---|
| macOS | Apple Silicon (arm64), Intel (x86_64) |
DMG | adhoc today; developer-id-notarized once credentials exist |
| Windows | x86_64 |
MSI and NSIS setup executable | unsigned, or authenticode once the SignPath policy is release-signing |
| Linux | x86_64 |
DEB and AppImage | github-attested exact bytes |
The "Signing in this release" section above states which labels this release
uses. With Authenticode, SignPath signs the MSI and every program file in it,
and the NSIS setup itself; the files the NSIS setup installs are not signed. The build workflow installs
and uninstalls every package on clean hosted runners and verifies the
executable architecture and the declared signing policy: the exact Developer ID
authority and Team ID on macOS when used, and a valid signer and timestamp on
each Windows installer when signed. The workflow launches every installed
application and requires the process to survive a 20-second startup window
(catching launch panics before they ship), and stages the exact tested bytes.
The repository test matrix also checks that only the openadapt scheme is
registered and that its handoff is fixed to connect_uri without a shell or
general navigation escape hatch. These checks do not replace qualification of
a complete real workflow.
Integrity and provenance
Release jobs stage the exact post-signing, smoke-tested files and scan that
assembled installer set with Syft to publish a machine-readable CycloneDX JSON
software bill of materials (SBOM). The workflow refuses an empty or malformed
SBOM, includes it and the public build-provenance identity in the sorted
SHA256SUMS manifest, verifies the exact inventory, and creates a GitHub
artifact attestation over every named file. It also attests SHA256SUMS itself.
The release verifier requires the signed subjects to equal that inventory. It
binds the exact reviewed-main workflow, source commit, published engine tag and
release, run ID, run attempt, and GitHub-hosted runner. Consumers must
authenticate SHA256SUMS before they trust its digests:
gh attestation verify SHA256SUMS \
--repo OpenAdaptAI/OpenAdapt \
--cert-identity "https://github.com/OpenAdaptAI/OpenAdapt/.github/workflows/desktop-release.yml@refs/heads/main" \
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
--deny-self-hosted-runners
sha256sum -c SHA256SUMS
python verify-openadapt-native-release.py --directory . --manifest SHA256SUMSThe final helper refuses missing, extra, linked, non-regular, duplicate, or
digest-mismatched files. Each release also carries its own attested
openadapt-desktop-channel.json. It binds this release's SHA256SUMS and
provenance by hash, states every platform's signing mode, and names the
previous release's channel by hash. Pass it with --channel (and the last
channel you accepted with --previous-channel) to authenticate the whole chain
before trusting any digest. A download service must select the newest valid
openadapt-desktop-v* release this way, never from mutable release-note text.
After a native release succeeds, its channel is the authority for that version.
An attestation binds bytes to a build identity; it does not establish that the
software is secure or functionally complete.
Signing credentials
The protected native-release environment of OpenAdaptAI/OpenAdapt holds the
signing credentials. Every set is complete-or-absent: a partial set fails the
build, and an absent set ships the platform's unsigned label instead.
- Windows Authenticode through SignPath (free for open source projects through
the SignPath Foundation):SIGNPATH_API_TOKEN,SIGNPATH_ORGANIZATION_ID,
SIGNPATH_PROJECT_SLUG(OpenAdapt), and
SIGNPATH_SIGNING_POLICY_SLUG(release-signing). The pipeline policy is in
.signpath/policies/OpenAdapt/release-signing.ymlat the monorepo
root. - macOS Developer ID and notarization, if it is ever configured:
APPLE_CERTIFICATE,APPLE_CERTIFICATE_PASSWORD,APPLE_SIGNING_IDENTITY,
APPLE_ID,APPLE_PASSWORD, andAPPLE_TEAM_ID. Until then macOS builds are
ad-hoc signed. - Linux uses the GitHub OIDC exact-byte attestation above. It has no secret and
is not described as native-signed.
The updater stays disabled until its independent public/private signing-key
lifecycle and recovery procedure are established.
The signing runbook lists the secrets to add and the claims each public surface
can make. See CODE_SIGNING.md.
openadapt-flow 3.0.0
Breaking: the vision stack is the vision extra (3.0.0)
-
pip install openadapt-flowno longer installs NumPy, OpenCV, Pillow or
RapidOCR. They are the newvisionextra. The base install is the
record-check verifier, write ledger, protected journal, SQL, REST and FHIR
read paths and receipt signing: 17 distributions and 40 MB of site-packages
instead of 29 and 301 MB (uv install, Python 3.12, macOS arm64).
openadapt-verify depends on this base install. -
The recording and replay extras (
browser,capture,windows,macos,
linux,rdp,native-ocr,local-grounding,openenv) include
vision, sopip install 'openadapt-flow[browser]'installs what it did in
2.x. To record, compile or replay with none of those, install
openadapt-flow[vision]. Without it, those commands print that install
command and exit 2. -
On the base install,
openadapt-flow --help,openadapt-flow receipt verify
andopenadapt-flow verify-runwork. The perturbation harness, the repair
campaigns andcompile_recordingload Pillow and NumPy on first use instead
of when the CLI builds its parser. Theflow-baseCI smoke runs those
commands' help on the base install. -
The on-prem release installs
openadapt-flow[privacy,vision]. -
RemoteFrameContractimports Pillow only when it hashes a frame, so loading
a deployment config no longer needs it.
tests/test_verifier_import_boundary.pyrefuses the vision modules and
checks that the verifier path imports and signs a receipt without them. -
No verifier, ledger, journal or guard code changed. Fail-closed behavior is
unchanged. -
SQL effect readback now requires opaque SQLite and PostgreSQL adapters to
declaresql_dialect. Native drivers are still recognized automatically. -
Keep deferred typing, scrolling and click gestures tied to their emitting
document. A known document change preserves both actions; uncertain ownership
or a mixed-document batch refuses publication.
openadapt-flow 2.7.1
Flow 2.7.1 fixes loading of programs certified before Nov 8. Two optional
workflow fields added since then changed their certification digest, so they
failed to load. They now load under the reviewed sealed-omission rule, while a
program whose content changed is still refused. The release also makes write
ledger settlement atomic and extends zero-config verifier generation.
Upgrade notes
- A custom
LedgerBackendmust providetransaction(key), an exclusive journal transaction shared byevents()andappend(); a backend without it refuses ledger mutations. A held write is released only by a person:settle_sno longer releases it, andhalted_before_effectis nowREFUTEDwithretry_safe=False. See Verifier API. scaffold-verifier --proveno longer accepts the built-inmockmedandeffect-e2efixtures. It runs only against a proof source the caller passes tomain(record_check_proof_source=...).
Fixes
- Programs certified before the
Anchor.form_identityandTokenTemplate.bearingfields were added load again. When the current workflow-contract digest does not match, the loader tries the older form, leaving out only fields on the reviewed sealed-omission list for the bundle's format version that are unset andNone, and accepts it only if it reproduces the bound digest exactly. A program whose content changed is still refused. - Ledger settlements record the journal revision they observed, so a stale or concurrent observation cannot release a hold, grant a retry, complete a recheck or hand back an older result. Rechecks are bound to the original receipt and the exact set of validated later receipts.
Changed
scaffold-verifiercloses three gaps the zero-config benchmark found. A generated REST read now carriesrecords_complete: truewhen--complete-readdeclares it or one unpaged response was seen to hold the whole collection; otherwise it stays incomplete andverify-runreturns INDETERMINATE. A step counts as a write when the capture shows the page sending a POST, PUT, PATCH or DELETE to its own origin, or its store snapshots differ, not only when its label looks like Save.--probe-reads(with optional--probe-base) finds a read for an app that never reads the saved record back: it probes the collection and item reads the write implies with GET on the local machine, uses one only when it returns the written values and nothing outside it could change unseen (otherwise it refuses and writes the TODO draft), and records every probe (read_discoveryin the proof, orread_discovery.jsonwhen none confirms).
v1.21.0
Requirements
- Require
openadapt-flow>=2.7.0,<3.0.0in the base install and every Flow
extra.openadapt doctorandopenadapt deployreport older Flow releases
as unsupported. Flow 2.7 supplies the wrap command and the--demo-app
replay option shown in the launcher's help.
Upgrade notes
- The launcher rejects abbreviated long options. Spell each option in full.
- Replay no longer serves the bundled demo app unless asked: pass
--url, a
backend.urlin--config, or--demo-app.
Features
openadapt wrapruns one operator-configured agent task. The first call
runs the agent, checks the saved record and compiles the run; later calls
replay the checked program with new inputs and no model calls.
openadapt wrap --serveoffers the task as a local stdio MCP tool, and
openadapt wrap --helplists every option.openadapt record,openadapt compileandopenadapt runforward to the
matching Flow commands. Run summaries show the result, the next step and
where the report is.openadapt --helpgroups commands into the same 15 tasks as Flow. Earlier
command names still work.openadapt doctorchecks macOS Accessibility and Screen Recording access.
--recordingalso checks Capture and FFmpeg for a native backend, and
--install-browserdownloads Playwright's matching Chromium.
openadapt-flow 2.7.0
Flow adds openadapt wrap, which turns one agent task into a compiled program
that replays with new inputs and no model calls. It also teaches writes in the
browser and on desktop apps under a signed authorization, and checks more of
what a write changed. Verification still refuses a write when the record or its
outcome cannot be established.
Upgrade notes
- No command falls back to the demo app on its own.
replayneeds a target:
--url,backend.urlin--config, or--demo-appto serve the bundled
MockMed (the tutorial and quickstart commands pass it;--driftneeds it).
--demo-appwith an attached browser is refused. The variant router's
first-screen probe captures nothing without a URL.qualify accept's break-it
check no longer runs every workflow's oracle against MockMed: it builds the
lie from the workflow itself (a store that did not change, and a screen
showing the workflow's own success text and every value the run typed). The
reference Execute worker refuses, before running anything, an admission whose
target_urlit cannot drive. - Every command-line parser rejects abbreviated long options. Spell each
option in full:run --permissionno longer selects--permission-trust. - Paged REST and FHIR reads must declare an immutable-snapshot contract and
completeness. A read that does not declarerecords_complete(or that
returns a missing or changing snapshot token, duplicate identities or mixed
identity domains) is indeterminate, not confirmed. - FHIR reads refuse query parameters in configured searches, requests,
effective URLs and self links, because a capped or filtered result cannot
establish a complete read-back. Acollectionbundle is accepted only with a
total equal to its entry count. Standard searchset paging is unchanged. - A workflow recorded with locale, date-order and keyboard-layout facts refuses
replay on a computer whose facts differ or cannot be read. Workflows recorded
before this release carry no such binding and are not checked. - Identity bands are stricter. A recorded token that carries a digit (an id,
date, age or count) must match the live band raw, label and hint words no
longer count toward coverage, and a band with no identity-bearing token
abstains. Some same-name rows that verified before now refuse. - SQLite rows are hashed with each cell's storage class, so a value that
changes from integer to text (or similar) changes the row hash. A connection
with type converters is refused. - All database watch routes in one shadow configuration must share the same
frame.databasesettings.
Features
openadapt wrap(andpython -m openadapt_flow.wrap.cli) runs one
operator-configured, parameterized task. The first call for a task runs the
agent once, checks the saved record independently, compiles the run and
admits it; later calls replay the admitted program with new inputs and no
model calls.--serveexposes the task as a local stdio MCP tool whose input
schema is exactly the task's declared parameters. A request ID makes a
repeated or interrupted call return the original run instead of sending the
write again. A failed or uncertain replay is held until a person approves a
repair through the normal signed admission and canaries. Model spend and run
time are capped before each model call (--max-cost-usd,
--max-run-seconds), and the run reports its usage.- The model never sees the task's own identity or inputs. Where a listing or
screenshot shows a value bound to the task (a declaredon_screenidentity
string or a task input), it is sent as a typed placeholder such as
⟦task.identity_1⟧or⟦task.note⟧: in text, and as a labelled box in the
redacted screenshot. Before, the scrubber redacted the task's own patient name
and MRN, and Claude stopped at read-back because it could not tell the task's
row from any other. Unbound personal data is still redacted generically. The
agent may type a placeholder; the harness types the value. The save gate and
the read-back still check the real values locally. openadapt wraptakes--max-input-bytes. Claude's default ceiling on one
rendered request is now 4 MiB (was 64 KiB, which ended every
screenshot-per-turn run on turn 2); OpenAI keeps 64 KiB. No setting may exceed
32 MiB, and a request above the setting is still never sent.- Commands are grouped into 15 tasks in
openadapt-flow --help(for example
setup teach-authorization,verify shadow). Every earlier command name
still works as an alias. - Browser teach writes: an agent can teach a save in the browser under a
person-signed teach authorization (openadapt.teach-authorization/v1). The
authorization names the task, inputs, origins, permitted writes and forbidden
actions; run 1 starts only when it verifies and covers the write, and every
click, key and select is checked against it.openadapt-flow teach-authorization create,signandverifymanage authorizations. - An agent can teach a save on a desktop or remote app over MCP, get it
admitted, and call the taught tool. Teach authorizations accept desktop and
remote surface origins, and a desktop teach scope is bound to the app the
person taught. - Native authoring trees:
authoring_tree()on the Windows (UI Automation),
macOS (Accessibility) and Linux (AT-SPI) backends lists each control by its
element identity.compile-agent --configandserve-execute --configrun
desktop and remote apps from the deployment'sbackendsection. - Verifier audit:
python -m openadapt_flow.verifier_audit run --target module:factory --out DIRtests an environment's own scorer rather than an
agent. It replays a reference trajectory with mechanical faults (an
unauthorized side effect, the wrong record, a wrong value, a duplicate write,
a partial write, a write after the success claim, a claim with no write) plus
an incidental-change positive control. It reads the end state independently
and reports, per family, where the scorer accepted a wrong end state or
rejected a legitimate one, with counterexamples and Wilson 95% intervals.
Adapters for AgentDojo and AppWorld ship as examples; private family sets
plug in with--families-module. Design:docs/VERIFIER_AUDIT.md. - Database shadow mode watches clients that write directly to a database. The
agent announces each action (/begin,/end); Flow checks the action's
database contract and watches for changes between actions. A change no action
covers isREFUTEDwhen the app's audit names the agent's user and
UNCERTAINotherwise.--guardrefuses actions that cannot be checked or
that follow an unconfirmed result. - Writes stay provisional while a history recheck is owed. The recheck reads
retained versions and deletions, refuses incomplete history, and needs
server-controlled provenance to attribute another actor's edit. - Reusable subroutines: a typed signature plus a program body, identified by
digest and kept in a versioned library. Certification registers each
workflow's uses, and every run re-admits embedded subroutines against the
current library (--subroutine-library), so publishing a new version sends
older users back to qualification. - A small, safe expression language computes parameters between steps and
evaluates generated effect predicates. It has its own parser and type
checker (noeval), a closed standard library and hard bounds; anything
outside it refuses. Seedocs/EXPRESSIONS.md. - API steps cover multipart saves, the clicked submit button's
name=value,
and saves sent by page scripts. - A new built-in certification policy,
record-write, asks for the same
evidence asclinical-writefor any non-clinical system of record. Select it
withcampaign.policy: record-writeor--policy record-write. - Setup learns how a selected record reader corresponds to database rows and
columns (learn_frame_identities), and drafts REST read setups from explicit
API paging, total, snapshot and equality semantics. Missing or ambiguous
correspondences refuse setup. verifier.sessionworks for FHIR and GraphQL read-backs, renewed for each
qualification trial.- Taught-tool parameters can declare the intake field they come from. A run is
refused when a value disagrees with an operator-registered intake grant bound
to the source document and the exact bundle that runs. - Regulated approvals can require a named-person binding (WebAuthn passkey,
OIDC or SAML evidence), carried in the Seal as digests only. - The local console authorizes each request against a deployment-resolved
identity with reader, operator and administrator permissions. - Explicit retention removes finalized sealed runs after a signed policy
interval (dry run by default), and sealed-set data keys can be rewrapped
without re-encrypting payloads.OPENADAPT_FLOW_AT_REST=strictencrypts
every run directory and refuses what it cannot encrypt. - Recorded native single-select choices replay by their exact option value.
- Flow ingests evidence from an optional Manifest V3 Chrome extension: open
shadow-DOM target paths, cross-origin iframe context and redacted network
saves, with secrets withheld before they leave the page. - Trusted
before_capture(backend)preparation runs on the recording's own
backend before the first capture; publication waits for cleanup. - A modal dialog target's identity band is read on the dialog alone, so
confirm steps in dialogs (such as a duplicate-record prompt) can arm
identity.
Fixes
- The scrubber no longer rewrites a listing's element refs:
[e3] button "Open"
came back as[<US_DRIVER_LICENSE>] button "Open". Only page text is
scrubbed, cell by cell; ref tokens never reach the scrubber. openadapt wrapon a held task reportsCACHE_HALTEDwith the halt reason
and exits 1. It used to treat the hold as a cache miss and exi...
OpenAdapt Desktop 0.28.1
OpenAdapt Desktop 0.28.1: the PyPI package and the native installers.
Signing in this release
- macOS: ad-hoc signed, not notarized. macOS asks you to confirm the first time you open it (System Settings > Privacy & Security).
- Windows: unsigned. SmartScreen warns before install; choose More info > Run anyway.
- Linux: no package signature; the GitHub attestation covers the exact DEB and AppImage bytes.
Verify any download against SHA256SUMS and its GitHub attestation with verify-openadapt-native-release.py, using this release's openadapt-desktop-channel.json.
Native Release Candidates
OpenAdapt Desktop native packages are unadmitted candidates for the
installed authoring, teaching, and local-pairing companion. They bundle and start the
Python sidecar, connect the Tauri/React cockpit to it over local JSON-lines IPC,
and register the openadapt:// operating-system handler. The handler accepts
only the fixed openadapt://connect action and forwards it to the sidecar's
strict, transactional pairing flow.
The canonical compiler and governed runtime remain in openadapt-flow. Each
native installer freezes the exact openadapt-flow[browser,console]==2.4.1
runtime and its playwright==1.61.0 browser automation dependency into the
Desktop sidecar. The console extra is what lets an installed application
serve the attended decision console the mobile decision portal relays; the
browser extra carries the frozen Playwright driver.
Compile, replay, run, and teach therefore work without a separate Python,
openadapt-flow, or playwright installation on PATH. Desktop starts with no
browser download. The first browser workflow downloads the Chromium revision
pinned by the bundled Playwright runtime unless an approved browser cache is
pre-provisioned; native desktop, RDP, and Citrix workflows never enter that
setup path.
The mobile decision portal shows the current phone
interface, one-use pairing flow, local evidence boundary, hosted outbound lane,
runner revalidation, and typed result contract.
Desktop keeps separately licensed media and vision components outside its MIT
installer. On first use, it downloads the exact release-reviewed component for
the current platform, verifies the pinned URL, byte count, and SHA-256, installs
it into a versioned local cache, and re-verifies every extracted file before
loading it. This applies to the managed FFmpeg 8.1.2 runtime used for capture
encoding and the RapidOCR 1.4.4/OpenCV 5.0.0.93 runtime used for visual
resolution. A partial or drifted download is never activated; rerunning the
operation retries it. Enterprise images can pre-provision the same exact cache
without changing the runtime contract. Developer ID builds carry the narrow
macOS library-validation entitlement required to load that independently
signed, hash-verified OpenCV extension; the manifest and full-file cache audit
remain the admission boundary.
Each Desktop version is one immutable openadapt-desktop-vX.Y.Z release in the
OpenAdapt monorepo. It carries the Python wheel and sdist (the same bytes as on
PyPI), these native installers, and the release's own attested channel. The
native version comes from package.json, src-tauri/Cargo.toml, and
src-tauri/tauri.conf.json, with matching entries in both lockfiles; a Desktop
release pull request sets them and the Python version together
(scripts/prepare_release.py). When it merges, the Desktop release workflow
builds and smoke-tests every package, attests the exact bytes, attaches
everything to a draft, publishes the wheel and sdist to PyPI, and publishes the
draft once. If any build fails, nothing is published. OpenAdapt's releases are
immutable, so a published release is never edited; a newer release supersedes
an older one by version. This transaction doesn't change the admission-driven
Production channel. The release policy is in
RELEASES.md.
Artifact labels
Every new filename includes Candidate, the native version, operating system,
architecture, and signing state. The matrix and the signing each platform can
carry:
| Platform | Architectures | Packages | Signing labels |
|---|---|---|---|
| macOS | Apple Silicon (arm64), Intel (x86_64) |
DMG | adhoc today; developer-id-notarized once credentials exist |
| Windows | x86_64 |
MSI and NSIS setup executable | unsigned, or authenticode once the SignPath policy is release-signing |
| Linux | x86_64 |
DEB and AppImage | github-attested exact bytes |
The "Signing in this release" section above states which labels this release
uses. With Authenticode, SignPath signs the MSI and every program file in it,
and the NSIS setup itself; the files the NSIS setup installs are not signed. The build workflow installs
and uninstalls every package on clean hosted runners and verifies the
executable architecture and the declared signing policy: the exact Developer ID
authority and Team ID on macOS when used, and a valid signer and timestamp on
each Windows installer when signed. The workflow launches every installed
application and requires the process to survive a 20-second startup window
(catching launch panics before they ship), and stages the exact tested bytes.
The repository test matrix also checks that only the openadapt scheme is
registered and that its handoff is fixed to connect_uri without a shell or
general navigation escape hatch. These checks do not replace qualification of
a complete real workflow.
Integrity and provenance
Release jobs stage the exact post-signing, smoke-tested files and scan that
assembled installer set with Syft to publish a machine-readable CycloneDX JSON
software bill of materials (SBOM). The workflow refuses an empty or malformed
SBOM, includes it and the public build-provenance identity in the sorted
SHA256SUMS manifest, verifies the exact inventory, and creates a GitHub
artifact attestation over every named file. It also attests SHA256SUMS itself.
The release verifier requires the signed subjects to equal that inventory. It
binds the exact reviewed-main workflow, source commit, published engine tag and
release, run ID, run attempt, and GitHub-hosted runner. Consumers must
authenticate SHA256SUMS before they trust its digests:
gh attestation verify SHA256SUMS \
--repo OpenAdaptAI/OpenAdapt \
--cert-identity "https://github.com/OpenAdaptAI/OpenAdapt/.github/workflows/desktop-release.yml@refs/heads/main" \
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
--deny-self-hosted-runners
sha256sum -c SHA256SUMS
python verify-openadapt-native-release.py --directory . --manifest SHA256SUMSThe final helper refuses missing, extra, linked, non-regular, duplicate, or
digest-mismatched files. Each release also carries its own attested
openadapt-desktop-channel.json. It binds this release's SHA256SUMS and
provenance by hash, states every platform's signing mode, and names the
previous release's channel by hash. Pass it with --channel (and the last
channel you accepted with --previous-channel) to authenticate the whole chain
before trusting any digest. A download service must select the newest valid
openadapt-desktop-v* release this way, never from mutable release-note text.
After a native release succeeds, its channel is the authority for that version.
An attestation binds bytes to a build identity; it does not establish that the
software is secure or functionally complete.
Signing credentials
The protected native-release environment of OpenAdaptAI/OpenAdapt holds the
signing credentials. Every set is complete-or-absent: a partial set fails the
build, and an absent set ships the platform's unsigned label instead.
- Windows Authenticode through SignPath (free for open source projects through
the SignPath Foundation):SIGNPATH_API_TOKEN,SIGNPATH_ORGANIZATION_ID,
SIGNPATH_PROJECT_SLUG(OpenAdapt), and
SIGNPATH_SIGNING_POLICY_SLUG(release-signing). The pipeline policy is in
.signpath/policies/OpenAdapt/release-signing.ymlat the monorepo
root. - macOS Developer ID and notarization, if it is ever configured:
APPLE_CERTIFICATE,APPLE_CERTIFICATE_PASSWORD,APPLE_SIGNING_IDENTITY,
APPLE_ID,APPLE_PASSWORD, andAPPLE_TEAM_ID. Until then macOS builds are
ad-hoc signed. - Linux uses the GitHub OIDC exact-byte attestation above. It has no secret and
is not described as native-signed.
The updater stays disabled until its independent public/private signing-key
lifecycle and recovery procedure are established.
The signing runbook lists the secrets to add and the claims each public surface
can make. See CODE_SIGNING.md.
OpenAdapt Desktop 0.28.0
OpenAdapt Desktop 0.28.0: the PyPI package and the native installers.
Signing in this release
- macOS: ad-hoc signed, not notarized. macOS asks you to confirm the first time you open it (System Settings > Privacy & Security).
- Windows: unsigned. SmartScreen warns before install; choose More info > Run anyway.
- Linux: no package signature; the GitHub attestation covers the exact DEB and AppImage bytes.
Verify any download against SHA256SUMS and its GitHub attestation with verify-openadapt-native-release.py, using this release's openadapt-desktop-channel.json.
Native Release Candidates
OpenAdapt Desktop native packages are unadmitted candidates for the
installed authoring, teaching, and local-pairing companion. They bundle and start the
Python sidecar, connect the Tauri/React cockpit to it over local JSON-lines IPC,
and register the openadapt:// operating-system handler. The handler accepts
only the fixed openadapt://connect action and forwards it to the sidecar's
strict, transactional pairing flow.
The canonical compiler and governed runtime remain in openadapt-flow. Each
native installer freezes the exact openadapt-flow[browser,console]==2.4.1
runtime and its playwright==1.61.0 browser automation dependency into the
Desktop sidecar. The console extra is what lets an installed application
serve the attended decision console the mobile decision portal relays; the
browser extra carries the frozen Playwright driver.
Compile, replay, run, and teach therefore work without a separate Python,
openadapt-flow, or playwright installation on PATH. Desktop starts with no
browser download. The first browser workflow downloads the Chromium revision
pinned by the bundled Playwright runtime unless an approved browser cache is
pre-provisioned; native desktop, RDP, and Citrix workflows never enter that
setup path.
The mobile decision portal shows the current phone
interface, one-use pairing flow, local evidence boundary, hosted outbound lane,
runner revalidation, and typed result contract.
Desktop keeps separately licensed media and vision components outside its MIT
installer. On first use, it downloads the exact release-reviewed component for
the current platform, verifies the pinned URL, byte count, and SHA-256, installs
it into a versioned local cache, and re-verifies every extracted file before
loading it. This applies to the managed FFmpeg 8.1.2 runtime used for capture
encoding and the RapidOCR 1.4.4/OpenCV 5.0.0.93 runtime used for visual
resolution. A partial or drifted download is never activated; rerunning the
operation retries it. Enterprise images can pre-provision the same exact cache
without changing the runtime contract. Developer ID builds carry the narrow
macOS library-validation entitlement required to load that independently
signed, hash-verified OpenCV extension; the manifest and full-file cache audit
remain the admission boundary.
Each Desktop version is one immutable openadapt-desktop-vX.Y.Z release in the
OpenAdapt monorepo. It carries the Python wheel and sdist (the same bytes as on
PyPI), these native installers, and the release's own attested channel. The
native version comes from package.json, src-tauri/Cargo.toml, and
src-tauri/tauri.conf.json, with matching entries in both lockfiles; a Desktop
release pull request sets them and the Python version together
(scripts/prepare_release.py). When it merges, the Desktop release workflow
builds and smoke-tests every package, attests the exact bytes, attaches
everything to a draft, publishes the wheel and sdist to PyPI, and publishes the
draft once. If any build fails, nothing is published. OpenAdapt's releases are
immutable, so a published release is never edited; a newer release supersedes
an older one by version. This transaction doesn't change the admission-driven
Production channel. The release policy is in
RELEASES.md.
Artifact labels
Every new filename includes Candidate, the native version, operating system,
architecture, and signing state. The matrix and the signing each platform can
carry:
| Platform | Architectures | Packages | Signing labels |
|---|---|---|---|
| macOS | Apple Silicon (arm64), Intel (x86_64) |
DMG | adhoc today; developer-id-notarized once credentials exist |
| Windows | x86_64 |
MSI and NSIS setup executable | unsigned, or authenticode once the SignPath policy is release-signing |
| Linux | x86_64 |
DEB and AppImage | github-attested exact bytes |
The "Signing in this release" section above states which labels this release
uses. With Authenticode, SignPath signs the MSI and every program file in it,
and the NSIS setup itself; the files the NSIS setup installs are not signed. The build workflow installs
and uninstalls every package on clean hosted runners and verifies the
executable architecture and the declared signing policy: the exact Developer ID
authority and Team ID on macOS when used, and a valid signer and timestamp on
each Windows installer when signed. The workflow launches every installed
application and requires the process to survive a 20-second startup window
(catching launch panics before they ship), and stages the exact tested bytes.
The repository test matrix also checks that only the openadapt scheme is
registered and that its handoff is fixed to connect_uri without a shell or
general navigation escape hatch. These checks do not replace qualification of
a complete real workflow.
Integrity and provenance
Release jobs stage the exact post-signing, smoke-tested files and scan that
assembled installer set with Syft to publish a machine-readable CycloneDX JSON
software bill of materials (SBOM). The workflow refuses an empty or malformed
SBOM, includes it and the public build-provenance identity in the sorted
SHA256SUMS manifest, verifies the exact inventory, and creates a GitHub
artifact attestation over every named file. It also attests SHA256SUMS itself.
The release verifier requires the signed subjects to equal that inventory. It
binds the exact reviewed-main workflow, source commit, published engine tag and
release, run ID, run attempt, and GitHub-hosted runner. Consumers must
authenticate SHA256SUMS before they trust its digests:
gh attestation verify SHA256SUMS \
--repo OpenAdaptAI/OpenAdapt \
--cert-identity "https://github.com/OpenAdaptAI/OpenAdapt/.github/workflows/desktop-release.yml@refs/heads/main" \
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
--deny-self-hosted-runners
sha256sum -c SHA256SUMS
python verify-openadapt-native-release.py --directory . --manifest SHA256SUMSThe final helper refuses missing, extra, linked, non-regular, duplicate, or
digest-mismatched files. Each release also carries its own attested
openadapt-desktop-channel.json. It binds this release's SHA256SUMS and
provenance by hash, states every platform's signing mode, and names the
previous release's channel by hash. Pass it with --channel (and the last
channel you accepted with --previous-channel) to authenticate the whole chain
before trusting any digest. A download service must select the newest valid
openadapt-desktop-v* release this way, never from mutable release-note text.
After a native release succeeds, its channel is the authority for that version.
An attestation binds bytes to a build identity; it does not establish that the
software is secure or functionally complete.
Signing credentials
The protected native-release environment of OpenAdaptAI/OpenAdapt holds the
signing credentials. Every set is complete-or-absent: a partial set fails the
build, and an absent set ships the platform's unsigned label instead.
- Windows Authenticode through SignPath (free for open source projects through
the SignPath Foundation):SIGNPATH_API_TOKEN,SIGNPATH_ORGANIZATION_ID,
SIGNPATH_PROJECT_SLUG(OpenAdapt), and
SIGNPATH_SIGNING_POLICY_SLUG(release-signing). The pipeline policy is in
.signpath/policies/OpenAdapt/release-signing.ymlat the monorepo
root. - macOS Developer ID and notarization, if it is ever configured:
APPLE_CERTIFICATE,APPLE_CERTIFICATE_PASSWORD,APPLE_SIGNING_IDENTITY,
APPLE_ID,APPLE_PASSWORD, andAPPLE_TEAM_ID. Until then macOS builds are
ad-hoc signed. - Linux uses the GitHub OIDC exact-byte attestation above. It has no secret and
is not described as native-signed.
The updater stays disabled until its independent public/private signing-key
lifecycle and recovery procedure are established.
The signing runbook lists the secrets to add and the claims each public surface
can make. See CODE_SIGNING.md.
OpenAdapt Desktop 0.27.0
OpenAdapt Desktop 0.27.0: the PyPI package and the native installers.
Signing in this release
- macOS: ad-hoc signed, not notarized. macOS asks you to confirm the first time you open it (System Settings > Privacy & Security).
- Windows: unsigned. SmartScreen warns before install; choose More info > Run anyway.
- Linux: no package signature; the GitHub attestation covers the exact DEB and AppImage bytes.
Verify any download against SHA256SUMS and its GitHub attestation with verify-openadapt-native-release.py, using this release's openadapt-desktop-channel.json.
Native Release Candidates
OpenAdapt Desktop native packages are unadmitted candidates for the
installed authoring, teaching, and local-pairing companion. They bundle and start the
Python sidecar, connect the Tauri/React cockpit to it over local JSON-lines IPC,
and register the openadapt:// operating-system handler. The handler accepts
only the fixed openadapt://connect action and forwards it to the sidecar's
strict, transactional pairing flow.
The canonical compiler and governed runtime remain in openadapt-flow. Each
native installer freezes the exact openadapt-flow[browser,console]==2.4.1
runtime and its playwright==1.61.0 browser automation dependency into the
Desktop sidecar. The console extra is what lets an installed application
serve the attended decision console the mobile decision portal relays; the
browser extra carries the frozen Playwright driver.
Compile, replay, run, and teach therefore work without a separate Python,
openadapt-flow, or playwright installation on PATH. Desktop starts with no
browser download. The first browser workflow downloads the Chromium revision
pinned by the bundled Playwright runtime unless an approved browser cache is
pre-provisioned; native desktop, RDP, and Citrix workflows never enter that
setup path.
The mobile decision portal shows the current phone
interface, one-use pairing flow, local evidence boundary, hosted outbound lane,
runner revalidation, and typed result contract.
Desktop keeps separately licensed media and vision components outside its MIT
installer. On first use, it downloads the exact release-reviewed component for
the current platform, verifies the pinned URL, byte count, and SHA-256, installs
it into a versioned local cache, and re-verifies every extracted file before
loading it. This applies to the managed FFmpeg 8.1.2 runtime used for capture
encoding and the RapidOCR 1.4.4/OpenCV 5.0.0.93 runtime used for visual
resolution. A partial or drifted download is never activated; rerunning the
operation retries it. Enterprise images can pre-provision the same exact cache
without changing the runtime contract. Developer ID builds carry the narrow
macOS library-validation entitlement required to load that independently
signed, hash-verified OpenCV extension; the manifest and full-file cache audit
remain the admission boundary.
Each Desktop version is one immutable openadapt-desktop-vX.Y.Z release in the
OpenAdapt monorepo. It carries the Python wheel and sdist (the same bytes as on
PyPI), these native installers, and the release's own attested channel. The
native version comes from package.json, src-tauri/Cargo.toml, and
src-tauri/tauri.conf.json, with matching entries in both lockfiles; a Desktop
release pull request sets them and the Python version together
(scripts/prepare_release.py). When it merges, the Desktop release workflow
builds and smoke-tests every package, attests the exact bytes, attaches
everything to a draft, publishes the wheel and sdist to PyPI, and publishes the
draft once. If any build fails, nothing is published. OpenAdapt's releases are
immutable, so a published release is never edited; a newer release supersedes
an older one by version. This transaction doesn't change the admission-driven
Production channel. The release policy is in
RELEASES.md.
Artifact labels
Every new filename includes Candidate, the native version, operating system,
architecture, and signing state. The matrix and the signing each platform can
carry:
| Platform | Architectures | Packages | Signing labels |
|---|---|---|---|
| macOS | Apple Silicon (arm64), Intel (x86_64) |
DMG | adhoc today; developer-id-notarized once credentials exist |
| Windows | x86_64 |
MSI and NSIS setup executable | unsigned, or authenticode once the SignPath policy is release-signing |
| Linux | x86_64 |
DEB and AppImage | github-attested exact bytes |
The "Signing in this release" section above states which labels this release
uses. With Authenticode, SignPath signs the MSI and every program file in it,
and the NSIS setup itself; the files the NSIS setup installs are not signed. The build workflow installs
and uninstalls every package on clean hosted runners and verifies the
executable architecture and the declared signing policy: the exact Developer ID
authority and Team ID on macOS when used, and a valid signer and timestamp on
each Windows installer when signed. The workflow launches every installed
application and requires the process to survive a 20-second startup window
(catching launch panics before they ship), and stages the exact tested bytes.
The repository test matrix also checks that only the openadapt scheme is
registered and that its handoff is fixed to connect_uri without a shell or
general navigation escape hatch. These checks do not replace qualification of
a complete real workflow.
Integrity and provenance
Release jobs stage the exact post-signing, smoke-tested files and scan that
assembled installer set with Syft to publish a machine-readable CycloneDX JSON
software bill of materials (SBOM). The workflow refuses an empty or malformed
SBOM, includes it and the public build-provenance identity in the sorted
SHA256SUMS manifest, verifies the exact inventory, and creates a GitHub
artifact attestation over every named file. It also attests SHA256SUMS itself.
The release verifier requires the signed subjects to equal that inventory. It
binds the exact reviewed-main workflow, source commit, published engine tag and
release, run ID, run attempt, and GitHub-hosted runner. Consumers must
authenticate SHA256SUMS before they trust its digests:
gh attestation verify SHA256SUMS \
--repo OpenAdaptAI/OpenAdapt \
--cert-identity "https://github.com/OpenAdaptAI/OpenAdapt/.github/workflows/desktop-release.yml@refs/heads/main" \
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
--deny-self-hosted-runners
sha256sum -c SHA256SUMS
python verify-openadapt-native-release.py --directory . --manifest SHA256SUMSThe final helper refuses missing, extra, linked, non-regular, duplicate, or
digest-mismatched files. Each release also carries its own attested
openadapt-desktop-channel.json. It binds this release's SHA256SUMS and
provenance by hash, states every platform's signing mode, and names the
previous release's channel by hash. Pass it with --channel (and the last
channel you accepted with --previous-channel) to authenticate the whole chain
before trusting any digest. A download service must select the newest valid
openadapt-desktop-v* release this way, never from mutable release-note text.
After a native release succeeds, its channel is the authority for that version.
An attestation binds bytes to a build identity; it does not establish that the
software is secure or functionally complete.
Signing credentials
The protected native-release environment of OpenAdaptAI/OpenAdapt holds the
signing credentials. Every set is complete-or-absent: a partial set fails the
build, and an absent set ships the platform's unsigned label instead.
- Windows Authenticode through SignPath (free for open source projects through
the SignPath Foundation):SIGNPATH_API_TOKEN,SIGNPATH_ORGANIZATION_ID,
SIGNPATH_PROJECT_SLUG(OpenAdapt), and
SIGNPATH_SIGNING_POLICY_SLUG(release-signing). The pipeline policy is in
.signpath/policies/OpenAdapt/release-signing.ymlat the monorepo
root. - macOS Developer ID and notarization, if it is ever configured:
APPLE_CERTIFICATE,APPLE_CERTIFICATE_PASSWORD,APPLE_SIGNING_IDENTITY,
APPLE_ID,APPLE_PASSWORD, andAPPLE_TEAM_ID. Until then macOS builds are
ad-hoc signed. - Linux uses the GitHub OIDC exact-byte attestation above. It has no secret and
is not described as native-signed.
The updater stays disabled until its independent public/private signing-key
lifecycle and recovery procedure are established.
The signing runbook lists the secrets to add and the claims each public surface
can make. See CODE_SIGNING.md.
v1.20.0
Requirements
- Require
openadapt-flow>=2.6.0,<3.0.0in the base install and every Flow
extra.openadapt doctorandopenadapt deployreport older Flow releases
as unsupported. This supplies the persistent owed-recheck API used by
ledger listing.
Features
openadapt verify ledger listshows provisional confirmed writes whose
rechecks are still owed, with their due time and actor. Owed rechecks remain
visible after the server restarts and disappear when the recheck completes.
An empty ledger reports that no held writes, open writes or owed rechecks
remain.- The platform manifest and compatibility report select published component
releases, including Desktop 0.25.1.