Repository navigation
Orion-X Phoenix Edition v3.0.0
What this release is. The v2.2.0 release-candidate line (rc5–rc9, below), taken
through a full quality pass and shipped as Orion-X Phoenix Edition 3.0.0: eight
independent reviews of the rc9 image (operator experience, Python, shell, systemd and
AppArmor, packages and build, documentation, security, release engineering — 253
findings), five fix groups working in parallel worktrees, and a second round of
defects found by booting and recording the image for the release video. Nothing
below was accepted without a test that failed before the fix and passes after it.
ISO identity. SHA-256 c952ca5be03789208e39ef1807c1f09c1c15fb1f82c223272c8c3c2007332386,
3,131,211,776 bytes (3.13 GB), built 2026-10-08 16:25–16:58 MDT from 2da37512 with a
clean chroot (only the bootstrap stage reused). Baked ISO_VERSION=v3.0.0, baked README ==
repo. Gates on this image: hooks-applied 19/0; content-presence in release mode
(ORIONX_RELEASE_GATE=1 ORIONX_EXPECT_VERSION=v3.0.0, shellcheck and lsinitramfs present)
391/0/0; QEMU BIOS 104 s / UEFI 112 s. Booted on the reference laptop (Lenovo) by the
owner on 2026-10-18: works as advertised (DEC-PHASE13-001 satisfied). The
CHANGELOG, README and User Guide copies baked into the image predate this identity line,
as every release's must.
Added
- Boot menu entry "Orion-X Live (no questions)" — appends
orionx.wizard=0; the
first-boot wizard takes every default. Prompts now time out after 30 s (an
unattended boot waits about 2 minutes, not 6) (DEC-PHASE12-106). - A real training capture.
~/Analysis/pcaps/apt_malware_traffic.pcapwas a
42-byte text placeholder that tshark read as an empty capture; it is now a
deterministic synthetic intrusion (DNS + HTTP stager, jittered TLS beacons with
SNI, DNS TXT tunnelling, an internal SYN sweep, SMB2 negotiate) over RFC 1918 /
RFC 5737 addresses and.examplenames, generated by
tools/samples/make_training_pcap.py(DEC-PHASE12-141). - Team pre-shared key for the mesh, optional and exchanged out of band:
orionx-mesh psk generate|install|remove|status. Two stock decks peer without it. - Release tooling.
scripts/release/stage-split-release.shpublishes the >2 GB
ISO as signed 190 MiB parts with SHA256SUMS/SHA512SUMS and reassembly
instructions;scripts/release/ci-local.shruns the CI gates locally; lint, e2e
and QEMU workflows run onrelease/**branches (DEC-PHASE12-115, -123). - Two release videos — the guided walkthrough (
docs/media/orionx-guided-demo-v3.0.0.*)
and the trailer (docs/media/orionx-trailer-v3.0.0.*), each as mp4 + vtt + transcript +
poster, 720p in the repo, 1080p masters on the release — and their one pipeline
(tools/guided-demo/cinematic/): boot footage
captured from the real ISO in QEMU, UI scenes recorded from the ISO's own root
filesystem, the deck's own R.A.I.N. cues and voice, a synthesised score and an
offline neural narrator; captions and transcript derive from one script
(DEC-PHASE12-062 … -064, -140). - New test suites:
test_cockpit_gtk(the Cockpit under a real GTK main loop on
Xvfb),test_firewall_behaviour(real packets through network namespaces),
test_unit_sandbox(systemd-analyze verify+ a real dumpcap run),
test_apparmor_load,test_firefox_policies,test_bus_reader,
test_operator_surfaces,test_release_promises,test_release_tooling,
test_makefile_gates,test_hooks_applied_gate,test_sample_pcaps,
test_artifact_analyzer_cli,test_cockpit_honesty.
Fixed — Cockpit
orionx-cockpit --tab Xalways opened LIVE, including from the menu entry
andorionx-control-center: GtkNotebook ignores a page selection made before
show_all(). Found while recording the release video.- Choosing a threat-posture tier says "requested" until
orionx-postured
confirms enforcement, or says NOT enforced with the remedy. A failed write
reverts the control and shows the error. Every state change toasts whether it
survives reboot (DEC-PHASE12-065…074). - The Comms tab derives the client URL from the listener Synapse actually binds
(/etc/matrix-synapse/conf.d/orionx.yaml, thenhomeserver.yaml); it used to
printhttps://<ip>:8008, which matched nothing. - "Download Samples" and "Storyboard Generator" guided actions pass arguments the
scripts accept (both could never run). Orion Tools lists catalogue entries
installed as Debian packages (nmap, tshark, yara … were hidden). - DEFENSIVE ACTIONS reads
orionx-heald's published/run/orionx/healing-status.json
(root-only chain is no longer read, and the panel no longer shows nothing when
actions are in force). A missing or stale snapshot says so. - The panel mesh widget, Mesh tab, Awareness and the LIVE LED read the root-written
mesh snapshot; nothing in the GUI runssudo. "stale (N s)" past 30 s. - Probes run in worker threads and only for the visible tab; a slow
systemctl,
nmcliormatrix-commanderno longer freezes the window (was up to 27 s). - The LIVE tab fits 1366×768 and opens maximised; text is measured and ellipsised;
the drill-down wraps and pages; severity is a word as well as a colour; no text
under 11 px; one toast system with a log at~/.cache/orionx/cockpit.log.
Ctrl+Q quits; a strayq/Esc no longer closes the live view; Alt+1…8 switch tabs. - Squelch/tune results keep
orionx-tune's lines with "survives reboot" first;
nothing is cut at 160 characters. - "Test alert" reports
orionx-rain's real exit status;orionx-rain --testexits
1 when no cue played. - Event-bus readers (Cockpit and R.A.I.N.) no longer lose a line read mid-write or
events written just after a rotation; R.A.I.N. survives the bus file being
deleted (it crashed and stayed dead for the session). - Retired names are gone from every operator-facing string: "Control Center",
"IR Tools", "Investigation Surface".orionx-control-center --versionreports
the image's version.
Fixed — daemons and detection
- One malformed entry in
tuning.jsonsilenced every IDS alert (the error was
swallowed); rules are validated on load, bad ones reported once on the bus. - Operator-writable tuning text reached root's Suricata threshold file unescaped
(a newline injectedsuppress gen_id 0, sig_id 0); fields are validated and
single-line before root writes them. - Root daemons read tuning and posture files only from the operator's home, never
through a symlink or a file another user can write (they chose "newest across
every/home/*"). - The healing engine acts only on bus events signed by root producers (HMAC, key in
a root-only file); anything else can at most become a labelled suggestion. - The event-bus speech validator no longer rejects sentences with words ending in
"s"; R.A.I.N. remedies name the shippednebulaCLI (they saidorionx-nebula,
which does not exist). - On-demand PCAP capture works: the
orionx-capture@sandbox killed dumpcap with
SIGSYS, andReadWritePaths=/var/lib/orionxnamed a directory the image did not
have (postured failed with 226/NAMESPACE). - LAN mesh discovery never added a peer (the listener read the sender address from a
variable that was never set and then died). Beacons are validated (single host in
the mesh subnet, never rewriting an existing peer), rate-limited, rejects logged.
joinstarts the discovery/beacon/health/status units andleavestops them
(they stayed dead after a leave).mesh_genkeysfails loudly on a write error. setup-matrix.sh --mode serverdied at the registration-secret line (SIGPIPE
under pipefail). It now writes one listener (http, 8008, bound to 127.0.0.1 and
the wg0 address), keeps registration closed, passes the admin password through a
file, checks for root and a route first, and pins the matrix.org and Element apt
keys by fingerprint. One Synapse unit: the package'smatrix-synapse.service
with an Orion-X drop-in;matrix-synapse-orionx.service(never installed) is gone.artifact-analyzer.pywrote./analysis_resultswherever the terminal was and
died with a raw traceback from an unwritable directory; it now writes under
~/Analysis/results/and reports an unwritable-oin a sentence.- The Workbench rejects requests not addressed to 127.0.0.1/localhost (DNS-rebinding
defence), sendsnosniff, no longer builds its full status for every static file,
runs one server per operator (--status,--stop), and opens in its own tmpfs
Firefox profile, never the OSINT browsing profile (DEC-PHASE12-142).
Fixed — security posture (default image)
- Firewall: 22, 8008, 8448 and 55555 were open on every interface. Now: on
LAN interfaces only established/related, DHCP, WireGuard 51820/udp and the
rate-limited mesh beacon; SSH and Matrix only onwg0; restarting the firewall
reloads only its own table (it used to flush Auto-Healing's blocks)
(DEC-PHASE12-104). - sshd is installed but not started at boot. The first-boot wizard's "SSH admin
one-shot" (a root private key and its passphrase, written world-readable to the
pre-login banner, for a login sshd refuses) is removed (#98). Key-only login for
orionx-operatoroverwg0when the operator starts sshd. - ollama's "no outbound network" is enforced by the kernel (
IPAddressDeny=any+
IPAddressAllow=localhoston the unit); the AppArmor profile could not express it
and also lacked exec permission for ollama's own runner. The dead Synapse AppArmor
profile (attached to a symlink) is removed; the AppArmor loader reports failed
profiles by name and the Nebula runtime refuses to start unconfined. - The wizard no longer creates mesh keys at all (
orionx-mesh joinmakes them,
0600, on first use), no longer renames the account into a state without
sudo/polkit, and no longer says the
account is "passwordless" (the password islive). Wi-Fi PSKs go to a 0600
keyfile, not nmcli's argv. - The deck sends no DHCP hostname, no mesh beacon before a join, runs no apt timers,
and exim4 no longer runs. Firefox ships an enterprise policy (telemetry, studies,
DoH and WebRTC address leaks off). Root unit log files under/var/log/orionx
can no longer be squatted (the directory stays 1777 for operator tools, DEC-PHASE12-108). - Build-time supply chain: every pip install is pinned with sha256 hashes
(/usr/share/orionx/pip/), volatility3 lives in its own venv (volkept on PATH),
nuclei-templates is pinned to a commit, the Zeek apt key is fingerprint-pinned and
scoped withsigned-by, every optional installer verifies a SHA-256, CesiumJS's
shared default token is removed and its licence ships.
Fixed — build, release and gates
make test-unithid Python failures (2>/dev/null || echo "No Python unit tests found yet"; 12 were failing) and stopped at the first failing bash suite. It now
runs everything and lists every failure (#11). The 11 stale pytest tests assert
real state.- The macOS build wrapper copied every ISO in the build volume back to the host,
including stale ones; it publishes only this build's ISO, only on success.
build-iso.shrefuses a release-looking tag without a CHANGELOG section and
fails on stale-stage reuse;extract-release-notes.shfails loudly. - The content-presence gate asserts every tool the README promises and every
rc5–rc9 deck fix in the squashfs, and nine checks that recorded PASS on missing
evidence now FAIL; sections 29–33 read the image, not the source tree
(DEC-PHASE12-119). The hooks gate derives its list from the hook directories. - volatility3, stix2, pyfiglet and the nucleotide table are hard-fail installs
(soft-fail let a build ship without README-listed tools and stay green). make cleankeeps release ISOs unlessCLEAN_ISOS=1; orphaned Qt5 purged
(~60 MB);--allow-remove-essentiallimited to live-build's own step;
0500-bootloader-serial.hook.binaryretired (it never found its targets; the
config generator is the authority);orionx-diagverifies the model blobs the
manifest lists (check 7c always skipped).
Fixed — documentation and surfaces
- Every current-release string says v3.0.0; the rendered User Guide takes its
release line from/etc/orionx-versionso it cannot drift again. The baked
README and User Guide called themselves rc5. - The
~/AnalysisREADME named a--outputflag that does not exist
(--samples-dir). The User Guide said nothing forwards Suricata alerts to the bus
(postured does), named a "◈ COCKPIT" button that does not exist, said the Control
Center starts automatically, and had a broken table-of-contents link. - Rename propagation finished everywhere user-visible; the Cockpit has a desktop
icon and a panel launcher; "Orion Cockpit — Tabs" is "Orion Cockpit — Network tab"
(what it opens); the "Orion-X Mesh" menu entry runssudo orionx-mesh status
instead of printing usage; MOTD andorionx-helplist what ships, from one list. - README: Nebula "listens on 127.0.0.1 only; AppArmor-confined" (the old "no
outbound network" claim was false); Known issues section; Hack is MIT/Expat +
Bitstream Vera (not Apache-2.0) and DejaVu Sans Mono also ships. - New User Guide sections: Firewall and Remote Access, mesh keys and PSK, the real
Synapse listener, the live account and administrator rights (sudo without a
prompt is by design for a single-operator live deck).
Known issues and decisions deferred to the owner
Each item below now has an owner decision, recorded 2026-10-18 in
MASTER_PLAN.md § Decision Log as DEC-PHASE13-001 … 012 (taken through the
/decide configurator on this list; nothing here changes the v3.0.0 image).
- Boot-tested in QEMU (BIOS + UEFI) and, on 2026-10-18, on the reference laptop
(Lenovo) by the owner: boots and works as advertised. DEC-PHASE13-001 is
satisfied; the deck-only checks (Mesh tab, "Set up as server", Element's keyring
prompt, AppArmor enforcement of ollama, the Synapse drop-in sandbox) remain to be
exercised one by one on that hardware as 3.0.1 work begins. radare2andfonts-iosevkaare not shipped (#85) — DEC-PHASE13-002: close
#85 as won't-ship (Ghidra viainstall-ghidra.sh; Hack + DejaVu Sans Mono).
Zeek has no managed capture unit (ingest only) — DEC-PHASE13-004: ship
orionx-zeek@.servicein 3.0.1, templated on the interface like
orionx-capture@, started by the Tier-1 plan beside Suricata. The gomuks
installer refuses (upstream's asset 404s) — DEC-PHASE13-003: remove
install-gomuks.sh; Element is the Matrix client path. TrID pins fail closed
when the vendor updates — DEC-PHASE13-005: keep fail-closed; add a
--print-pinoperator path.- NetworkManager MAC randomisation was not applied — DEC-PHASE13-006:
cloned-mac-address=stablefor Wi-Fi and Ethernet (hardware MAC never leaves
the deck; per-network address is stable so portals and DHCP survive). exim4 is
masked rather than purged — DEC-PHASE13-007: purge in the 0900 trim hook
(drop the 0620 mask; handle rkhunter's default-mta Recommends). Firmware scope —
DEC-PHASE13-008: the current Wi-Fi set plusintel-microcodeand
amd64-microcode. - LAN mesh discovery is unauthenticated beyond beacon validation — DEC-PHASE13-009:
auto-peer only when a team PSK is installed; otherwise hold beacons as candidates
the Mesh tab lists. (Gated on 001.) orionx-scanwatchand the posture/healing daemons still run as uid 0 —
DEC-PHASE13-010: a dedicatedorionxsystem user with ambient capabilities;
journal and nftables access verified on the deck first. (Gated on 001.)install-duckdb.shinstalls an unpinnedduckdbinto system Python and
install-geoip.shfetches without a checksum — DEC-PHASE13-011: pin duckdb
(version + hash) in a venv under/opt/orionx/venvs; GeoIP records the SHA-256 of
each monthly file and refuses a changed re-download.- The old guided-demo recorder (
tools/guided-demo/build_demo.py, #99) drove the
retired Control Center window — DEC-PHASE13-012 (amended): keep both videos,
one pipeline. The guided walkthrough is nowtools/guided-demo/cinematic/ walkthrough.yaml, rendered by the trailer's builder from footage of the shipped
ISO;build_demo.pyand its container mirror are removed.
Download and verify
GitHub caps release assets at 2 GiB per file, so the 3131211776-byte ISO is
published as 16 parts (part-aa … part-ap). Download ALL 16 parts,
SHA256SUMS and SHA256SUMS.asc into one directory.
1. Reassemble (Linux / macOS):
cat orionx-phoenix-edition-v3.0.0.iso.part-* > orionx-phoenix-edition-v3.0.0.iso
Windows (cmd, or PowerShell via cmd /c):
copy /b orionx-phoenix-edition-v3.0.0.iso.part-aa + orionx-phoenix-edition-v3.0.0.iso.part-ab + orionx-phoenix-edition-v3.0.0.iso.part-ac + orionx-phoenix-edition-v3.0.0.iso.part-ad + orionx-phoenix-edition-v3.0.0.iso.part-ae + orionx-phoenix-edition-v3.0.0.iso.part-af + orionx-phoenix-edition-v3.0.0.iso.part-ag + orionx-phoenix-edition-v3.0.0.iso.part-ah + orionx-phoenix-edition-v3.0.0.iso.part-ai + orionx-phoenix-edition-v3.0.0.iso.part-aj + orionx-phoenix-edition-v3.0.0.iso.part-ak + orionx-phoenix-edition-v3.0.0.iso.part-al + orionx-phoenix-edition-v3.0.0.iso.part-am + orionx-phoenix-edition-v3.0.0.iso.part-an + orionx-phoenix-edition-v3.0.0.iso.part-ao + orionx-phoenix-edition-v3.0.0.iso.part-ap orionx-phoenix-edition-v3.0.0.iso
2. Verify. The reassembled ISO MUST hash to:
c952ca5be03789208e39ef1807c1f09c1c15fb1f82c223272c8c3c2007332386
Linux: sha256sum -c SHA256SUMS
macOS: shasum -a 256 -c SHA256SUMS
Windows: Get-FileHash orionx-phoenix-edition-v3.0.0.iso -Algorithm SHA256
SHA256SUMS also lists each part, so a bad download can be pinpointed and
re-fetched without pulling everything again.
Then check the signature on the checksums (signing key
4CB08BD1D0B3281613DD15DB1DCCDF47FEEDEEEF — compare it with the fingerprint published outside this repository):
gpg --recv-keys 4CB08BD1D0B3281613DD15DB1DCCDF47FEEDEEEF # or import it from a trusted copy
gpg --verify SHA256SUMS.asc SHA256SUMS
3. Write to USB (8 GB or larger; the ISO is hybrid: UEFI and legacy BIOS):
Linux: sudo dd if=orionx-phoenix-edition-v3.0.0.iso of=/dev/sdX bs=4M status=progress conv=fsync
macOS: sudo dd if=orionx-phoenix-edition-v3.0.0.iso of=/dev/rdiskN bs=1m
Do not flash a single .part-* file. It is not bootable on its own.