Volunteer worker daemon for the AuspexAI distributed compute network
Project description
AuspexAI Worker
The volunteer worker process for AuspexAI — runs on volunteer machines, executes work units dispatched by the coordinator, donates compute to AI safety research.
Status
Phase 1 — M1 + M2 + M3 + M4 SHIPPED 2026-05-20. First-run enrollment, signed-heartbeat loop, assignment-pull pipeline, and sandboxed runner subprocess all verified end-to-end against the coordinator. Phase 1 worker target is Linux x86_64 + ARM64 (per principles doc §5.13 + §5.19); macOS/WSL2 packaging arrives in Phase 2.
What's live:
auspexai-worker bootstrap— generates an Ed25519 keypair, persists to the OS keyring (libsecret) or an encrypted-file fallback, enrolls anonymously (T0) with the coordinator viaPOST /api/v0/workers/enroll, records the assignedworker_idin the local SQLite state DB. Idempotent on re-run.auspexai-worker status— shows worker_id, tier, pubkey fingerprint, enrollment timestamp, last heartbeat.auspexai-worker daemon— runs two threads concurrently: a heartbeat loop posting signedPOST /api/v0/workers/{id}/heartbeatwith capabilities (OS, arch, RAM total, CPU count, GPU observation + volunteer declaration, declared resource caps), and an assignment poller calling signedGET /api/v0/workers/{id}/assignmentsand running the M3 gate pipeline on every assignment received. SIGTERM/SIGINT trigger a clean stop on both.--max-ticks=N/--verbose.- Assignment-handling pipeline (M3):
- Manifest-pin defense (§5.14): first sighting of an experiment locks its
manifest_sha256; a later assignment under a different hash is refused as a manifest-swap attempt. - Sensitive-content gate (§5.14 + §5.12): assignments carrying
sensitive_content_flagsin the payload require an explicitaccept <experiment-id>to proceed (default-decline). Note: the M6-era coordinator does NOT yet ship this field onWorkUnitEnvelopeOut; the gate is plumbed and waits for the coordinator-side change. - Tenant allow/deny gate (§5.14): tenants on the deny list are always refused; a non-empty allow list restricts acceptance to listed tenants.
- Refusals call back to the coordinator via
POST /api/v0/workers/{id}/assignments/{unit_id}/refuseso the operator console can see the refusal reason and the unit's replication slot is freed for another worker (Option A per Q-W4). Each decision is also written to a localassignment_auditlog.
- Manifest-pin defense (§5.14): first sighting of an experiment locks its
- M4: sandboxed runner + signed result submission. On accept, the daemon spawns
auspexai-worker-runnerinside abubblewrapsandbox (Phase 1 permissive policy:--die-with-parent --new-session --dev-bind / /plus env passthrough). The runner reads the work-unit envelope from stdin, executes the M4 synthetic executor (echoes the payload — tenant code arrives later), writes a Result body to$AUSPEXAI_OUTPUT_PATH, exits. Daemon reads the output, signs it with the worker key over a canonical encoding, POSTs to/api/v0/workers/{id}/assignments/{unit_id}/result. Localsubmitted_resultstable mirrors the coordinator's ack. Per Q-W4: any failure during dispatch (runner crash, submit error) triggers an explicitrefuseto the coordinator. Per Q-W9: one-at-a-time on the poller thread; heartbeat thread runs independently. Per Q-W10: bubblewrap requires unprivileged user namespaces — on AppArmor-restricted hosts (Ubuntu 24.04 default) deploy needskernel.apparmor_restrict_unprivileged_userns=0or a worker AppArmor profile. Passthrough mode ([sandbox] use_bubblewrap = false) is the documented escape hatch for CI + dev hosts. auspexai-worker abort <unit-id>— reads the runner PID file from the workspace, sends SIGTERM, waits--grace-seconds(default 5), sends SIGKILL if still running. No-op when no workspace / no PID / process already exited; always writes an audit row.- M3 CLI verbs:
queue,peek <unit-id>,accept <coordinator-experiment-id>,refuse <unit-id>,tenant {allow,deny,list} <tenant-id>. - RFC 9421 HTTP Message Signature signer (
ed25519, covered@method+@path+@authority+content-digest, labelsig1,createdwindow enforced by the coordinator). Symmetric to the platform's verifier; wire format verified by an inline oracle in the worker's own test suite. - Keystore backends: libsecret (Secret Service) primary; encrypted-file (ChaCha20-Poly1305, key derived from
/etc/machine-id+ UID) fallback for headless hosts and containers. - Local SQLite state at
$XDG_STATE_HOME/auspexai-worker/worker.dbwith a sequential migration framework matching the coordinator's convention. Re-entrant transaction lock so the two daemon threads can write concurrently without colliding onBEGIN. systemd --userservice unit templates with Phase 1 hardening (PrivateTmp,ProtectHome=read-only,ProtectSystem=strict,NoNewPrivileges,SystemCallFilter=@system-service). Two variants ship:packaging/systemd/auspexai-worker.servicefor pip/uv installs (ExecStart=%h/.local/bin/auspexai-worker);packaging/systemd-deb/auspexai-worker.servicefor.debinstalls (ExecStart=/opt/auspexai-worker/bin/auspexai-worker, installed by the.debto/etc/systemd/user/auspexai-worker.service).- 157 tests on Python 3.11 + 3.12; ruff check + format-check clean.
Subsequent milestones (per design doc §14):
- M5 ✅ Receipts store on
submitted_results+receipts list/show+logCLI (SQLite-as-canonical-store per 2026-05-22 design update). - M6 ✅ T1 upgrade via OAuth Device Flow (
auspexai-worker login) +withdrawflow (auspexai-worker withdraw). - M7 ✅ SHIPPED 2026-05-23 — Cosign-signed
.deb+ source tarball + wheel as GitHub release artifacts.dh-virtualenv-built/opt/auspexai-worker/venv; system-installed user-unit at/etc/systemd/user/; AppArmor profile confining the daemon with acx -> bwrap_sandboxchild profile that grantsuserns,scoped to bwrap-as-child-of-the-daemon (Q-W10 Phase 2 durable fix); postinst probes the sandbox asnobodybefore declaring install successful. Release pipeline at.github/workflows/release.ymlsigns via Sigstore keyless GitHub Actions OIDC (no manual cosign step per release). SeeAUTHORIZED_SIGNERS.mdfor the trust roster.
Full design rationale: Documentation/AuspexAI/v0.1.0/worker_daemon_design.md (ratified into principles doc §5.19 on 2026-05-20).
Install
Phase 1 supported target: Ubuntu 24.04+ / Debian 12+, x86_64. ARM64 + Ubuntu 22.04 land in Phase 2.
Via .deb release artifact (recommended)
Download the .deb and its Cosign signature/cert from the latest release. Verify before installing (the signature anchors at the Maintainer's GitHub OIDC identity via Sigstore — no long-lived signing key to compromise):
# One-time: install cosign if you don't already have it
# (https://docs.sigstore.dev/cosign/installation)
# Verify the .deb
cosign verify-blob \
--certificate-identity-regexp='^https://github\.com/auspexai/.+/\.github/workflows/.+@.+$' \
--certificate-oidc-issuer='https://token.actions.githubusercontent.com' \
--signature auspexai-worker_<version>_amd64.deb.sig \
--certificate auspexai-worker_<version>_amd64.deb.cert \
auspexai-worker_<version>_amd64.deb
# Install
sudo apt install ./auspexai-worker_<version>_amd64.deb
The postinst will reload the AppArmor profile and probe the sandbox as user nobody. If the probe fails, the install fails with an actionable error pointing at either the sysctl bridge (kernel.apparmor_restrict_unprivileged_userns=0 for lab use) or the AppArmor profile path (durable fix on Ubuntu 24.04+).
After install, each volunteer user runs (as themselves, not root):
systemctl --user enable --now auspexai-worker.service
auspexai-worker status # confirms enrollment (T0 anonymous)
auspexai-worker login # binds to GitHub identity (T1)
Tail the daemon: journalctl --user -u auspexai-worker -f.
Open the local dashboard in a browser (since v0.1.4):
http://localhost:7799
Read-only view of your worker's identity, activity log, receipts, and loaded config. Localhost-only by design — bound to 127.0.0.1 and never exposed externally. Disable with [dashboard] enabled = false in ~/.config/auspexai-worker/worker.toml or AUSPEXAI_WORKER_DASHBOARD_ENABLED=0 if you'd rather not have the local HTTP server running.
Container / minimal host caveat
The encrypted-file keystore needs /etc/machine-id for host-specific entropy. Real Ubuntu / Debian / Fedora hosts always have one; minimal containers or stripped embedded images may not. If auspexai-worker bootstrap complains, seed it once:
sudo systemd-machine-id-setup
# or, if that's not available:
cat /proc/sys/kernel/random/uuid | tr -d - | sudo tee /etc/machine-id
Trust roster
The list of identities authorized to sign release artifacts and contribution receipts lives at auspexai/.github/security/AUTHORIZED_SIGNERS.md. Verifiers should match the cosign --certificate-identity-regexp against the entries in that file.
Build the .deb from source
packaging/build-deb.sh # builds in a podman/docker Ubuntu 24.04 container
packaging/build-deb.sh --test # also install-tests in a second clean container
Outputs land at /tmp/auspexai-deb-build/auspexai-worker_<version>_amd64.deb.
Scope
The Worker:
- Runs on volunteer machines — Linux x86_64 + ARM64 in Phase 1; macOS via Homebrew tap and Windows via WSL2 in Phase 2 (per §5.13)
- Generates an Ed25519 keypair on first run, stored in OS-native keystore (libsecret on Linux; Keychain / DPAPI in Phase 2 platforms) — volunteers never paste keys into web forms
- Enrolls anonymously (T0) or upgrades to verified identity via OAuth 2.0 Device Authorization Flow (T1+; M6)
- Executes work units within sandboxed limits (CPU, GPU, RAM, network caps; idle-only mode by default — Phase 2)
- Submits signed results (M4)
- Maintains a local audit log of what it ran, when, and for which manifest hash (M3+)
Worker trust tiers (T0 anonymous through T4 maintainer) govern work eligibility and quorum weight; see the AuspexAI Principles & Scope §6 for the trust model.
Identity binding (T0 → T1)
A fresh install enrolls as T0 anonymous with no user interaction. To bind the worker to a verifiable identity and unlock higher-trust roles (vouching, Approver eligibility, unique work-unit assignments) run:
auspexai-worker login
This launches an OAuth 2.0 Device Authorization Flow against GitHub:
- The worker prints a short code and a verification URL (
github.com/login/device). - Open the URL in any browser (any device — phone, laptop, the same machine — your choice), sign in to GitHub, enter the code.
- GitHub returns an access token to the worker; the worker hands it to the AuspexAI coordinator, which verifies it with GitHub and mints a one-shot binding token; the worker then exchanges that binding token for a T1 upgrade. The access token is never stored on the worker — it's discarded as soon as the binding completes.
The read:user scope is the only scope ever requested. Subsequent worker↔coordinator authentication continues to use the worker's own Ed25519 keypair, not the GitHub token.
Email-fallback for institutional contexts
Phase 1 is GitHub-only for the OAuth IdP. Institutional volunteers, researchers, or workers running in environments where GitHub Device Flow isn't usable can request an alternative binding path by emailing contact@auspexai.network. A formal email-based binding path is on the Phase 2 roadmap (per principles doc §5.10 + §9 Q5); pre-Phase-2 accommodations are case-by-case under the Maintainer's discretion.
Withdrawal
To retire a worker and remove its local state:
auspexai-worker withdraw
The command prints what will be deleted, prompts for explicit confirmation (you must type the word withdraw), then:
- Calls the coordinator's retire endpoint so the scheduler stops handing it work.
- Deletes the local SQLite state DB (
worker.db) — audit log, manifest pins, receipts, tenant lists, consent rows. - Deletes the worker's Ed25519 keypair from the keystore.
Receipts already issued by the coordinator REMAIN in the coordinator's transparency log per Principles & Scope §5.15. They stay signed and verifiable but become unattributed (severable-PII pattern). The CLI prints this verbatim at the confirmation prompt so the volunteer is reminded of the consent terms at the moment of withdrawal.
After withdrawal completes, follow up with your package manager (apt remove auspexai-worker, pipx uninstall auspexai-worker, etc.) to finish the uninstall.
Development
Requires Python 3.11+. Quick start:
uv venv
uv pip install -e ".[dev]"
auspexai-worker status # shows "not enrolled"
auspexai-worker bootstrap # enrolls against the
# public coord (default
# since v0.1.2)
auspexai-worker daemon --max-ticks=3 # run 3 heartbeats then exit
pytest
ruff check src tests
ruff format --check src tests
Running against a coordinator on your own machine (lab mode) — override
the default https://coord.auspexai.network:
AUSPEXAI_COORDINATOR_URL=http://127.0.0.1:8080 \
auspexai-worker bootstrap
AUSPEXAI_COORDINATOR_URL=http://127.0.0.1:8080 \
auspexai-worker daemon --max-ticks=3
Or persist via TOML at ~/.config/auspexai-worker/worker.toml:
[coordinator]
url = "http://127.0.0.1:8080"
Conduct on the network
Worker conduct on the AuspexAI network is governed by the Volunteer Terms of Participation (forthcoming, Phase 2). Network-level abuse — running malicious workers, abusing reputation systems, attempting to influence quorum — is handled through technical enforcement (revocation, ban, trust-tier demotion), not Code-of-Conduct enforcement.
License
AGPL-3.0 — workers are network-served clients of the AuspexAI coordinator and inherit the platform's copyleft posture.
Governance & policies
- Governance — roles, decision rules, recruitment, conflict of interest
- Code of Conduct — community standards, reporting, escalation pathway
- Contributing — DCO sign-off, PR workflow, RFC requirement for substantial architectural changes
- Research Ethics Policy — what AI safety research can run on the network and how it's reviewed
Watch this repo
Activity will begin as Phase 1 ramps up.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auspexai_worker-0.2.6.tar.gz.
File metadata
- Download URL: auspexai_worker-0.2.6.tar.gz
- Upload date:
- Size: 235.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f24b1f70e0787bc23c8f9f736540e58f72a0bd6311d1525d311df95cdb553e5
|
|
| MD5 |
8f11a8d7f739ca1804a8e450bc566165
|
|
| BLAKE2b-256 |
40c9e529c82d49f291878a1257c2a9562da9c5f56b58b0cbddac0c5a17e1c2b5
|
Provenance
The following attestation bundles were made for auspexai_worker-0.2.6.tar.gz:
Publisher:
release.yml on auspexai/worker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
auspexai_worker-0.2.6.tar.gz -
Subject digest:
2f24b1f70e0787bc23c8f9f736540e58f72a0bd6311d1525d311df95cdb553e5 - Sigstore transparency entry: 1804932735
- Sigstore integration time:
-
Permalink:
auspexai/worker@916b9aa6c9fea820dc3b31357354b5165f0972c4 -
Branch / Tag:
refs/tags/v0.2.6 - Owner: https://github.com/auspexai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@916b9aa6c9fea820dc3b31357354b5165f0972c4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file auspexai_worker-0.2.6-py3-none-any.whl.
File metadata
- Download URL: auspexai_worker-0.2.6-py3-none-any.whl
- Upload date:
- Size: 185.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06e7b2827480fc2ab9649d9e93c178c553100a7a0f585d0336e2efc16f064836
|
|
| MD5 |
8ca79ec67e5c26f98352eccff165fcdf
|
|
| BLAKE2b-256 |
7b1cee7a0255d6762e6fa4692e50124c624d28c20b4d44324b6cbdcdb0aad83c
|
Provenance
The following attestation bundles were made for auspexai_worker-0.2.6-py3-none-any.whl:
Publisher:
release.yml on auspexai/worker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
auspexai_worker-0.2.6-py3-none-any.whl -
Subject digest:
06e7b2827480fc2ab9649d9e93c178c553100a7a0f585d0336e2efc16f064836 - Sigstore transparency entry: 1804932775
- Sigstore integration time:
-
Permalink:
auspexai/worker@916b9aa6c9fea820dc3b31357354b5165f0972c4 -
Branch / Tag:
refs/tags/v0.2.6 - Owner: https://github.com/auspexai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@916b9aa6c9fea820dc3b31357354b5165f0972c4 -
Trigger Event:
push
-
Statement type: