Anchored regex was too strict — `strings` concatenates adjacent printable
bytes so the version never sits on its own line. The 1.5.0-alpha binary
DOES contain the version but as part of `1.5.0-alpharpcNot Found`. Fixed
by switching to `grep -qF $VERSION`: substring match is safe because the
version string is specific enough that accidental collisions are
vanishingly unlikely.
Caught mid-build today: check rejected the correct local binary, fell
through to container source-build — ISO still produced correctly but
wasted ~10 min on an unnecessary rebuild.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1. FIPS daemon config schema drifted: upstream jmcorgan/fips now takes
`node.identity.persistent: true` (keys read from config-dir/fips.key)
and `transports.udp.bind_addr: "0.0.0.0:PORT"` instead of
`identity.key_file/pub_file` + `transports.udp.enabled/port`. The
`tor:` transport was dropped entirely; archipelago handles Tor
fallback itself. fips.yaml generated by archipelago::fips::config
now matches the upstream schema, and archipelago-fips.service stops
crashlooping on Activate. Observed on .198: 52 restarts with
"data did not match any variant of untagged enum TransportInstances
at line 7 column 3".
2. ISO backend-binary capture didn't verify that the captured binary
matched the checked-out Cargo.toml version. Today's 14:40 ISO
shipped a stale 1.4.0 binary because `core/target/release/archipelago`
pre-dated the 1.5.0-alpha bump — the build grabbed it via the
first-priority "local release build" path without looking at it.
All four capture sources now go through verify_backend_version()
which greps the binary for the expected version string; mismatches
are skipped so the build falls through to the source-build path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On this host (and potentially others with a particular podman/overlay
state), passing the multi-hundred-line stage-2 script via
`debian:trixie bash -c '...'` caused debootstrap to fail at
"Extracting apt... tar failed" on the very first package — no matter
what patch, storage cleanup, or env-reset we tried.
Running the exact same script body via a bind-mounted file
(`bash /installer-env.sh`) succeeds. So: write the body to a temp
file in WORK_DIR, bind-mount it read-only, and have the container
bash execute it from the file. Same behavior, different invocation,
works.
Was blocking every ISO rebuild since ~10:57 local. First successful
build since: 14:40, sha256 41fad2ff…, 2.3GB.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Debian Trixie apt 3.0.3's data.tar has duplicate entries for the same
path (regular file + symlink at e.g. libapt-private.so.0.0), and tar
bails on the second entry with "Cannot create symlink: File exists",
failing debootstrap on the very first package. Patch debootstrap's
tar invocation to use --skip-old-files so the duplicate is ignored.
Was blocking every unbundled ISO rebuild since the Trixie apt bump.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous build's STEP 47/50 log showed:
RUN for svc in nostr-vpn archipelago-wg archipelago-wg-address; do
rm -f /etc/systemd/system/.service
ln -sf /dev/null /etc/systemd/system/.service
done
The Dockerfile is generated via <<DOCKERFILE heredoc in the build
script, so unescaped $svc resolved in the outer bash BEFORE Docker
ever saw it, leaving nostr-vpn/wg masks as a hidden `.service` file
with no effect. nostr-vpn still tries to start on boot → [FAILED].
Fixed with \$svc so the literal lands in the Dockerfile for Docker's
shell to expand per iteration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fresh install of .198 reported "FIPS has an npub but says inactive".
The debian package writes /etc/fips/fips.pub during install (whence
the npub) but leaves the upstream fips.service disabled. Result:
FipsStatus.service_active = false, dashboard shows "inactive" until
the user hits Activate. Explicit `systemctl enable fips.service`
in the Dockerfile so first boot brings the daemon up immediately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1. nostr-vpn still failing despite last mask attempt — confirmed in
the 6th ISO's rootfs.tar: the .service file was present but
not in multi-user.target.wants. Previous `systemctl mask` silently
no-oped because the real file was already there. Fixed properly
with explicit `rm -f` + `ln -sf /dev/null` for nostr-vpn,
archipelago-wg, and archipelago-wg-address — same /dev/null
symlink state that `mask` would produce on a clean install.
2. Kiosk didn't come up on first boot, only on reboot. Extended the
ExecStartPre health-poll from 30s → 120s (unbundled ISO takes
longer to settle on first boot: archipelago initializes state,
pulls FileBrowser, frontend settles), raised TimeoutStartSec to
180s, and added After=systemd-user-sessions.service +
After=network-online.target so X / Chromium aren't racing.
3. /init: line 29: can't create /root/etc/network/interfaces error
on installer boot — debootstrap --variant=minbase omits ifupdown
so the target has no /etc/network/ directory, and live-boot's
init tries to seed it. Non-fatal but noisy. Added ifupdown +
isc-dhcp-client to the debootstrap --include list.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5th ISO attempt died in rustables's build.rs (which uses bindgen to
wrap libnftnl) with "couldn't find any valid shared libraries
matching: libclang". bindgen requires libclang.so at build time
to parse C headers. rustables also needs libnftnl-dev + libmnl-dev
for the actual wrappers.
Added to the fips-builder stage apt install line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Third time's the charm. The upstream fips Cargo.toml puts fips-gateway
behind features.gateway = ["dep:rustables"], so the previous two
attempts (--bins, --workspace --bins) never produced the binary —
only the default feature set was compiled. cargo deb --no-build then
panics looking for the missing binary.
Inspected /tmp/fips-investigate (fresh clone of upstream main on
2026-04-19) to confirm — the feature flag is the gate, not a
workspace layout issue.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plain `cargo build --release --bins` only built the root crate's
binary targets. fips-gateway is a workspace member, so we need
--workspace to pull every member's bins. Without it cargo deb
--no-build panics looking for target/release/fips-gateway.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rust:1-slim-bookworm doesn't include dbus/ssl dev headers, and
jmcorgan/fips upstream started linking against libdbus-sys + openssl
at some recent commit. Observed during the 2026-04-19 v1.5.0-alpha
rebuild: libdbus-sys's build.rs panics when pkg-config can't find
dbus-1.pc, which kills the whole cargo build → the whole ISO build
→ ships an ISO without FIPS installed.
Also mask nostr-vpn.service + archipelago-wg*.service in the rootfs
Dockerfile: these have WantedBy=multi-user.target so systemd pulls
them into the default boot target, but their EnvironmentFile + an
ExecStartPre guard cause them to [FAILED] in the boot MOTD on every
fresh install until onboarding writes their env files. Masking
keeps the startup clean; the onboarding / install RPC handlers
unmask + start them when prerequisites exist (same model as
archipelago-fips).
Bonus discovery from same diag: the default build was silently
reusing a stale rootfs cache from Apr 12 — before the FIPS
integration landed. So the v1.5.0-alpha ISO I shipped had no FIPS
package at all. Rebuild pass with --rebuild forces fresh rootfs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bakes the FIPS (Free Internetworking Peering System) mesh daemon into
the node stack, supervised by archipelago alongside Tor. Runs as a
system service, identity derives from the same BIP-39 master seed, and
user-triggered updates track upstream main.
Identity
seed.rs: new HKDF label archipelago/fips/secp256k1/v1 → dedicated
secp256k1 key, distinct from the Nostr-node key for crypto isolation
but still seed-recoverable
identity.rs: writes fips_key[.pub] to /data/identity on onboarding,
chmod 0600; fips_key_exists / load_fips_keys / fips_npub accessors
Transport
TransportKind::Fips=3 inserted between LAN and Tor (Tor bumps to 4)
→ router prefers FIPS over Tor for all peer traffic
PeerRecord gains fips_npub + last_fips fields (serde(default) for
backward-compat with older nodes)
transport/fips.rs: NodeTransport stub, reports unavailable until the
daemon is live so router falls through to Tor cleanly
Federation invites
FederatedNode and FederationInvite carry optional fips_npub
create_invite / accept_invite / peer-joined callback thread it end
to end; signature domain deliberately unchanged — FIPS Noise does
its own session auth, so the unsigned hint only affects path
selection
crate::fips
config.rs: renders /etc/fips/fips.yaml and sudo-installs key material
service.rs: systemctl status/activate/restart/mask wrappers
update.rs: GitHub API check against upstream main; apply stubbed
until per-commit .deb artefact source is decided
RPC + dashboard
fips.status / fips.check-update / fips.apply-update / fips.install /
fips.restart registered in dispatcher
HomeNetworkCard.vue shipped standalone (unmounted — place in Home.vue
when ready); shows state pill, version, FIPS npub, update button,
activate button when key is present but service is down
ISO + systemd
archipelago-fips.service: conditional on key presence, masked by
default — backend unmasks after onboarding writes the key
build-auto-installer-iso.sh: multi-stage Dockerfile builds the FIPS
.deb from jmcorgan/fips main (fail-loud), COPYs it into rootfs, apt
installs it so trixie resolves deps; unit copied + masked
Version bump: 1.3.5 → 1.4.0
Tests: 33 new/updated passing (seed, identity, transport, federation,
fips module, transport::fips).
Known gaps: fips.apply-update returns a clear stub error until
upstream publishes per-commit .deb artefacts; HomeNetworkCard is not
mounted in Home.vue by default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add deploy_secondary() function for deploying to multiple LAN nodes
- --both now deploys to .198 and .253 (previously .198 only)
- Fleet deploy updated for 3 LAN nodes
- Mesh DM fixes: protocol frame format, DM-via-channel routing
- Federation pending requests, discover modal
- VPN status UI improvements
- Image versions and container specs updates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Timeout now wraps stderr reader + wait (was only wrapping wait, so
hung pulls were never killed). 23.182.128.160:3000 is now primary
registry since git.tx1138.com is unreachable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. registries.conf includes docker.io search + fallback 23.182.128.160
2. First-boot pull_with_fallback() tries primary then fallback registry
3. FileBrowser created with noauth config on persistent volume
4. Backend dynamic registries.json pre-created in ISO
5. Filebrowser password secret created for token flow
Fixes: apps stuck at 0% download, filebrowser not working, dynamic
catalog not loading on fresh installs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ISO builder: run npm ci before npm run build to prevent stale UI artifacts
- Unbundled ISO: clean container-images dir to prevent bundled tars leaking
- WireGuard: use After=network.target instead of network-online.target for
faster wg0 startup on install
- VPN status: check actual nvpn0 interface instead of config tunnel_ip to
prevent NostrVPN from showing standalone WireGuard IP
- ContainerApps: filter out not-installed bundled apps (fixes Bitcoin Knots
appearing on clean unbundled installs)
- Kiosk: persist kiosk mode to localStorage before /kiosk redirect so
App.vue can skip remote relay (fixes input doubling with companion app)
- IndeedHub: fix port mapping and X-Forwarded-Prefix passthrough
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All hardcoded references to the old IP-based registry replaced across
Rust backend, Vue frontend, shell scripts, Dockerfiles, CI, and docs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Unbundled ISO: first-boot only creates FileBrowser (marker file .unbundled)
Users install apps from Marketplace — no more bitcoin/mempool on clean install
- VPN status: read tunnel IP from config file (instant) instead of nvpn status (22s)
- Kiosk: App.vue skips remote relay on /kiosk path (prevents duplicate input)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ISO boot failed in emergency mode because:
- fsck.ext4 binary missing (no e2fsprogs in rootfs)
- LUKS data volume never opened (no cryptsetup-initramfs in initramfs)
Both packages were in the installer debootstrap but not the target rootfs
Dockerfile. The initramfs regeneration at install time now includes LUKS
support since cryptsetup-initramfs is present.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update all references from Debian 12 (Bookworm) to Debian 13 (Trixie)
- Enable SystemCallArchitectures, RestrictAddressFamilies, RestrictRealtime
in archipelago.service (safe on systemd 256+ which respects NoNewPrivileges=no)
- Update GLIBC compatibility checks from 2.36 to 2.40
- ISO filename, build container, and docs updated throughout
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ISO build no longer copies netavark from build host (Debian 13/GLIBC 2.41)
which broke container networking on Debian 12 targets. Rootfs already
installs netavark from Debian 12 repos — just configure the backend.
Install RPC now adopts existing containers (from first-boot) instead of
erroring on duplicates. Container scanner extracts real versions from
image tags and detects available updates against pinned versions.
Frontend shows update button with version info when updates are available.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standalone WireGuard (wg0:51820):
- New archipelago-wg.service creates wg0 independent of NostrVPN
- Keypair generated on first-boot, persisted on LUKS partition
- vpn.create-peer uses wg genkey/pubkey (no nvpn dependency)
- wg-address service depends on archipelago-wg, not nostr-vpn
Networking fixes:
- Remove nos.lol from default relays (requires PoW, events rejected)
- Add Tor hidden service for private relay (port 7777) — NAT'd peers
can reach relay over Tor for NostrVPN signaling
- Fix Tor hostname sync race: wait loop before copying hostname files
- Add tor-hostnames + wireguard dirs to LUKS partition setup
- Include relay in hostname sync loops (setup-tor.sh + first-boot)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
polkit denies reboot/shutdown for non-root users without a local seat
(e.g. SSH sessions). Since archipelago has NOPASSWD sudo, add shell
aliases so reboot/shutdown/halt/poweroff transparently use sudo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues on fresh ISO install:
1. nostr-vpn.service was enabled in rootfs but env file doesn't exist
until first-boot generates Nostr identity — crash-loop on boot.
Now only enabled by first-boot-containers.sh after identity exists.
2. LUKS encrypted partition mounts over /var/lib/archipelago/, hiding
the relay config.toml the Dockerfile put there. Now copies relay
config and creates nostr-relay/nostr-vpn dirs on the LUKS partition.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dockerfile RUN steps execute under /bin/sh (dash on Debian), which
doesn't support brace expansion {a,b,c}. The nostr-relay directory
was never created, causing the config copy to fail (build #444).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Runner is Debian 13 (glibc 2.41), ISO rootfs is Debian 12/bookworm
(glibc 2.36). Dynamic binary crashes with GLIBC_2.41 not found.
Musl static build eliminates the dependency entirely.
Also set GRUB_DISTRIBUTOR="Archipelago" so installed system boot
menu says "Archipelago" not "Debian GNU/Linux".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add nostr-rs-relay as native system service (port 7777) for VPN
signaling. Every node runs its own private relay from first boot.
Update nvpn binary from v0.3.4 to v0.3.7 (fixes mesh event
processing). Add WireGuard helper and address service for peer VPN.
First-boot script configures relay, nvpn identity, relay URLs
(direct + Tor onion), and syncs daemon config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- VPN card: relay URLs, device management, invite QR, add participant
- Backend: vpn.invite, vpn.add-participant, vpn.peer-config RPCs
- nvpn v0.3.7 system service (fixes event processing bug in v0.3.4)
- First-boot: auto-configure nvpn with node identity and endpoint
- Service: AF_NETLINK for WireGuard, NoNewPrivileges=no for sudo wg
- TASK-50: networking stack reliability from first install
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Revert CI to normal cargo build --release (musl was false positive)
- Add acpid + acpi-support-base to rootfs packages
- Add acpi=force to GRUB and ISOLINUX boot params (installer + installed)
- Fixes "Maybe missing ACPI. Shutdown not powering off" on some hardware
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add NostrVPN as a native systemd service (extracted from container)
- Add VPN status detection for nostr-vpn in backend vpn.rs
- ISO build extracts nvpn binary from container image
- First-boot auto-configures NostrVPN with node's Nostr identity
- Change Claude Auth from login iframe to API key input field
- Remove duplicate ChangePasswordSection from Settings.vue
- FIPS and Routstr remain as installable container apps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical:
- BUILD_VERSION was hardcoded as "1.3.0-alpha" — now reads from Cargo.toml
This caused ALL ISOs to show v1.3.0 regardless of actual binary version
Kiosk:
- Remove --disable-gpu flags (broke display scaling on some monitors)
- Add --start-fullscreen --window-size for reliable fullscreen
New apps:
- Nostr VPN, FIPS, Routstr, noStrudel, BotFights, NWNN, 484 Kitchen,
Call the Operator, Arch Presentation, Syntropy Institute, T-0
Rust: suppress dead_code and unused_assignments warnings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add firmware-linux-nonfree to ISO (fixes missing Realtek NIC firmware)
- Pre-create nbxplorer/Main and btcpay/Main data directories
- Fix fedimint data dir permissions (chmod 775 for non-root container)
- GRUB GFX fallback: gfxpayload=keep + console fallback for incompatible hardware
- Kill stale Chromium before kiosk restart (prevents duplicate processes)
- Suppress Rust warnings: #[allow(dead_code)] on run_boot_reconciliation,
#[allow(unused_assignments)] on history_dirty
- Version bump to 1.3.3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude proxy no longer crashes when ANTHROPIC_API_KEY is not set.
Instead serves a 401 with a helpful message telling users to configure
their API key in Settings. Fixes blank AIUI on fresh installs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Onboarding:
- Persist current step in localStorage — page refresh resumes where user was
- Router afterEach saves step; guard redirects to saved step, not always intro
- Show npub alongside DID on restore success screen
UI fixes:
- Clipboard polyfill for HTTP contexts (fixes Copy DID crash on non-HTTPS)
- AppCard installing overlay shows for pkg.state=installing (survives refresh)
- Hide uninstall button during installation
- Frontend version bumped to 1.3.2
App store:
- OnlyOffice fully removed from marketplace, curated apps, app config
- Replaced with CryptPad references throughout
- Remove OnlyOffice from ISO capture patterns
Container stability:
- UI containers (bitcoin-ui, lnd-ui, electrs-ui) pull from registry first
- Added --cap-add FOWNER for rootless Podman compatibility
- electrs-ui now included in first-boot loop alongside bitcoin-ui and lnd-ui
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ISO build:
- Remove stale archipelago-rootfs-tmp container before creating new one
(previous failed builds leave it behind, blocking subsequent builds)
Container ports:
- OnlyOffice: fix LAN address from 8044 to 9980 (actual mapped port)
- Nginx Proxy Manager: fix from 8181 to 81 (correct admin port)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The CI build server's /opt/archipelago/web-ui/aiui resolves to the
same path as the build workspace. cp -r fails with "same file" error
which aborts the build under set -e. Use rsync instead (handles
same-src/dest gracefully), with cp fallback + || true.
This was the root cause of CI build #373 failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Frontend:
- Add remote-relay.ts: receives companion input via /ws/remote-relay,
dispatches keyboard/mouse/scroll events into browser DOM
- Add CompanionIndicator.vue: NES gamepad icon when companion connected
- Wire relay start/stop to auth state in App.vue
Kiosk:
- Move Chromium data dir to /var/lib/archipelago/chromium-kiosk (encrypted)
- Disable MetricsReporting, AutofillServerCommunication, PasswordManager
- Remove --metrics-recording-only (contradicts disable-metrics)
CSS:
- Fix Chromium ghost rectangles: only apply preserve-3d + backface-visibility
during transitions, not always-on (causes Chromium to skip painting
off-viewport cards)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sync MODEL_MAP from deploy script to ISO build's inline claude-api-proxy.
Maps short model names (claude-sonnet-4) to full API IDs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Container stability:
- Merge scan results instead of full replacement (prevents UI flapping)
- Absence threshold: 3 consecutive missed scans before removing from state
- container-list RPC uses cached scanner state for consistency
- Increased Podman API timeout 30s → 60s (scanner + health monitor)
- Keep crashed containers visible as "exited" instead of podman rm -f
- Resolve host-gateway IP via ip route (podman 4.3.x compatibility)
ISO build fixes:
- AIUI web app inclusion: searches 5 paths + CI step to copy from build server
- Claude API proxy: systemctl enable with symlink fallback
- AIUI nginx: try_files =404 (was /aiui/index.html redirect loop)
- Build version set to 1.3.0
Container fixes:
- lnd-ui: nginx listens on 8080 (was 80, Permission denied in rootless)
- first-boot: image-versions.sh sourced from correct path with validation
- first-boot: host-gateway resolved to actual gateway IP
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The unbundled build was generating a 73-line inline script that only
created FileBrowser. This meant no lnd.conf, no UI sidecars, no
--add-host DNS fix for any app. Now uses the full first-boot-containers.sh
which handles both bundled (load tarballs) and unbundled (pull from
registry) modes, and includes all fixes for LND config, nginx sidecars,
and DNS resolution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The UNBUNDLED build path didn't copy scripts/lib/ to the ISO,
so install-tui.sh was never available on unbundled installs.
The installer sourced it but the file wasn't there — no animations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build versioning:
- Sequential build counter (/opt/archipelago/build-counter)
- Version format: 0.1.0-beta.N (written to build-info.txt)
- Backend reads version from build-info.txt at startup, falls
back to Cargo.toml version — no recompile needed
- UI sidebar + settings show the build version automatically
LND fix (belt + suspenders):
- Added NET_RAW capability (config.rs, first-boot, container-specs)
- Combined with tlsextraip=0.0.0.0 from previous commit
Status labels:
- Both "exited" AND "stopped" states with non-zero exit codes
now show "crashed" in the UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add install-tui.sh library with boot scan, logo decrypt reveal,
bouncing Bitcoin symbol progress bar, and celebration strobe.
The installer sources it if available, falls back to plain text
if missing (easy revert: just remove the source line).
Animations: CRT power-on scan, BIOS memory check simulation,
3D ASCII logo with character-by-character decrypt reveal,
progress bar with ₿ bouncing DVD-screensaver style during
long operations, logo color party on completion, flashing
"REMOVE THE USB DRIVE NOW" warning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>