These effects were passing the raw JS callback function through rpcRound
without converting it to a CallbackId via context.callbacks.addCallback().
Since functions are dropped by JSON.stringify, the Rust side never received
a callback, breaking the const() reactive pattern.
Update version references from Angular 20 to Angular 21 and Taiga UI to
Taiga UI 5 across architecture docs. Update web/CLAUDE.md with improved
Taiga golden rules: prioritize MCP server for docs, remove hardcoded
component examples in favor of live doc lookups.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move firmware config files to boot/firmware/ to match raspi-firmware
package layout in Debian Trixie
- Use nested mounts (firmware and efi inside boot) so squashfs boot
files land on the correct partitions without manual splitting
- Pre-calculate root partition size from squashfs instead of creating
oversized btrfs and shrinking (avoids ioctl failure on loop devices)
- Use named loop devices (/dev/startos-loop-*) with automatic cleanup
of stale devices from previous failed builds
- Use --rbind for /boot in upgrade scripts so nested mounts (efi,
firmware) are automatically carried into the chroot
Add a typed DbWatch at the end of add_tunnel and remove_tunnel that
waits up to 15s for the sync loop to commit the gateway state change
to patch-db before returning.
Replace the flush+add cycle in apply_policy_routing with ip route
replace for each desired route, then delete stale routes. This
eliminates the window where the per-interface routing table is empty,
which caused temporary connectivity loss on other gateways.
- Use generated TS types for tunnel API params and data models
- Simplify API service methods to use typed RPC calls
- Update port forward UI for optional labels
- Add TS derive and type annotations to all tunnel API param structs
- Export tunnel bindings to a tunnel/ subdirectory with index generation
- Change port forward label from String to Option<String>
- Add TunnelDatabase::init() with default subnet creation
- Add tunnel migration framework with m_00_port_forward_entry migration
to convert legacy string-only port forwards to the new entry format
The old raspberrypi.gpg.key has SHA1-only UID binding signatures,
which sqv (Sequoia PGP) on Trixie rejects as of 2026-02-01. Fetch the
key from the raspberrypi-archive-keyring package instead, which has
re-signed bindings using SHA-256/512.
Install a /etc/grub.d/07_startos_installer script that searches for a
.startos-installer marker file at boot. When found, it creates a
"StartOS Installer" menu entry that loads the USB's own grub.cfg via
configfile, making it the default with a 5-second timeout.
Uses configfile instead of chainloader because on hybrid ISOs the
.startos-installer marker and /boot/grub/grub.cfg are on the ISO9660
root partition, while the EFI binary lives on a separate embedded ESP.
chainloader would look for the EFI binary on the wrong partition.
Replace the serialized os_partitions field in ServerConfig with runtime
fstab parsing. OsPartitionInfo::from_fstab() resolves PARTUUID/UUID/LABEL
device specs via blkid and discovers the BIOS boot partition by scanning
for its GPT type GUID via lsblk.
Also removes the efibootmgr-based boot order management (replaced by
GRUB-based USB detection in a subsequent commit) and adds a dedicated
bios: Option<PathBuf> field for the unformatted BIOS boot partition.
Generate DKMS MOK key pair during OS install, sign all unsigned kernel
modules, and enroll the MOK certificate using the user's master password.
On reboot, MokManager prompts the user to complete enrollment. Re-enrolls
on every boot if the key exists but isn't enrolled yet. Adds setup wizard
dialog to inform the user about the MokManager prompt.
When a restart is requested while the service is already restarting
(stopped but not yet started), set restart_again so the actor will
perform another stop→start cycle after the current one completes.
Rename ifconfig_url to echoip_urls and iterate through configured URLs,
falling back to the next one on failure. Reduces timeout per attempt
from 10s to 5s.
Previously, traffic was only classified as private if the source IP was
in a known interface subnet. This prevented private access from VPNs on
different VLANs. Now all RFC 1918 IPv4 and ULA/link-local IPv6 addresses
are treated as private, and DNS resolution for private domains works for
these sources by returning IPs from all interfaces.
Unconditionally enabling serial terminal broke gfxterm on EFI systems
without a serial port. Now installs a /etc/grub.d/01_serial script
that probes for the serial port before enabling it. Also copies
unicode.pf2 font to boot partition for GRUB graphical mode.
- Update patch-db submodule: fixes DB null-nuke caused by ciborium's
broken deserialize_str, and stack overflow from recursive apply_patches
- Create /media/startos with mode 750 in initramfs before subdirectories
Add After/Wants network-online.target to prevent race where
start-tunneld starts before the network interface is up, causing
missing MASQUERADE rules. Rename `web reset` to `web uninit` for
clarity.
Eliminates boilerplate across 7 wrapper classes (GetContainerIp,
GetHostInfo, GetOutboundGateway, GetServiceManifest, GetSslCertificate,
GetStatus, GetSystemSmtp) by moving shared const/once/watch/onChange/
waitFor logic into an abstract Watchable<T> base class.
- Extract DbWatchedCallbacks<K> abstraction in callbacks.rs using SyncMutex
for the repeated patchdb subscribe-wait-fire-remove callback pattern
- Move get_host_info and get_status callbacks to use TypedDbWatch instead of
raw db.subscribe, eliminating race conditions between reading and watching
- Make getStatus return Option<StatusInfo> to handle uninstalled packages
- Add getStatus .const/.once/.watch/.onChange wrapper in container-runtime
for legacy SystemForEmbassy adapter
- Add SDK watchable wrapper classes for all callback-enabled effects:
GetStatus, GetServiceManifest, GetHostInfo, GetContainerIp, GetSslCertificate