What's Changed
Added
--versionflag.startwrt --versionnow reports the StartWRT version (e.g.
0.1.0-beta.4); the CLI previously exposed no--version.
Changed
-
OpenWrt base upgraded 25.12.4 → 25.12.5 (
r33051-f5dae5ece4), picking up
the upstream stable-branch fixes. All three Start9 build-infra patches apply
unchanged, and no upstream path collides with the Start9 overlay. -
The OpenWrt image now builds from pristine upstream OpenWrt (the release
tarball pinned by sha256 inbuild/openwrt-version) with the Start9 delta
applied at build time from in-repoopenwrt-patches/(3 build-infra patches)
andopenwrt-overlay/(the SpacemiT K1 target + boot packages). The
Start9Labs/openwrtfork and the monorepo's last git submodule are retired;
cloning no longer needs--recursive, and theopenwrt/build workspace
contains no git repo at all. The prepared tree is byte-identical to the
former fork (verified by git tree hash), so image contents are unchanged.
Fixed
-
Changing the admin password now enforces the 12-character minimum. The
Settings → Password form and itsauth.set-passwordbackend endpoint (also
reached via thestartwrt auth set-passwordCLI) accepted passwords shorter
than 12 characters, even though first-time setup required it and the docs
documented the minimum. Both the frontend form and the backend now reject
passwords under 12 characters on change, matching initial setup. -
Changing the Router IP can no longer strand the network on a colliding subnet.
The LAN IPv4 page exposed a "Router IP" (3rd-octet) field that duplicated the
Admin Security Profile's subnet field but, unlike it, had no collision guard —
so setting the router onto a subnet already used by another profile put two
interfaces on the same /24, producing overlapping routes that silently broke
all access to the router (unrecoverable even by a keep-settings reflash). The
duplicate field is removed (the LAN page now only selects the /16 network
block; the Admin profile is the single source of truth for the 3rd octet), and
the backend now rejectsprofiles.create/profiles.editrequests whose /24
collides with an existing profile (including the admin LAN). Thelan.ipv4-set
endpoint (reached via the CLI) is covered by the same guard, so a direct
RPC/CLI call can't strand the router either. -
The Settings → General Build field no longer goes stale after new commits.
build.mkhad lost the wiring that refreshesbuild/env/GIT_HASH.txton every
build and treats it as a prerequisite ofweb/config.json, so the UI'sgitHash
froze at whatever it was whenconfig.jsonwas first generated.build.mknow
refreshesGIT_HASH.txtat parse time and re-stampsconfig.jsonwheneverHEAD
moves. -
The Build field now shows the
-modifiedmarker on a dirty build. It shortened
the 40-char hash withslice(0, 12), which dropped the trailing-modifiedsuffix;
it now preserves any trailing marker (matching the-dirtyindicator the
startwrt verifyCLI already shows). -
Adding an Outbound VPN no longer silently does nothing. On submit the dialog
calledtuiMarkControlAsTouchedAndValidate, which re-ran the WireGuard.conf
async validator and left the form stuckPENDING(the in-flight validation is
cancelled when the file input remounts during the pending phase), so the create
request was never sent. Submit now completes directly when the form is already
valid, and only marks fields touched — without re-validating — when it isn't. -
Web-only changes are now re-embedded into the
startwrtbinary on rebuild. The
UI is baked in at compile time viainclude_dir!, which does not register the
embedded files as cargo dependencies, soctrl'sbuild.rsnow emits a
cargo:rerun-if-changedfor the webdistdirectory. Previously a changed web
bundle was silently ignored unless a.rsfile also changed, shipping a stale
UI.
Changed
- Relocated into the
start-technologiesmonorepo as thestart-wrtproduct. The
three backend crates (startwrt-core/ctrl,uciedit,uciedit_macros) are now
members of the root Cargo workspace and build against the sharedstart-core
crate (shared-libs/crates/start-core, pulled in aliased asstartos), the
vendoredrpc-toolkit, and the vendoredimbl-value— replacing the previously
embeddedstart-ossubmodule and the git/crates.io copies of those deps. openwrtis now the monorepo's only git submodule; the embeddedstart-os
submodule was removed.- Build orchestration moved from the standalone product
Makefileto
projects/start-wrt/build.mk(included by the rootMakefile):make start-wrt,
make start-wrt-image,make start-wrt-update. - The Angular web UI is now a project (
start-wrt) in the root Angular workspace
instead of a standalone app. It shares the rootpackage.json/node_modules/
tsconfig.jsonand builds vianpm run build:wrt(servenpm run start:wrt,
type-checknpm run check:wrt) — and so upgrades in lockstep with the other Start9
Angular apps.RELATIVE_URL,pauseFor, and the markdown pipe now come from
@start9labs/shared. The HTTP/RPC/connection stack (its aborting-timeout, code-0
reconnect flow is deliberately different from shared's), the bespoke error surfacing,
WorkspaceConfig, the WebSocket progress types, and the i18n-routedvalidation-errors
provider stay local where the shared code would regress behavior or the shapes don't fit. @start9labs/sharedis now markedsideEffects: falseso importing a few symbols from
its barrel tree-shakes cleanly (start-wrt's embedded UI bundle would otherwise pull in
~875 kB of unused shared code). This also shrinks the other apps' bundles.- Restored the release CI that the monorepo migration had dropped, then folded StartWRT
into the monorepo-wide release tool:start-wrt.yamlagain has adeployjob, but it
now only uploads the built images to S3 (s3://startwrt-images) — the CDN the registry
serves from. To matchstartos-iso.yaml, it isworkflow_dispatch-gated on adeploy: releaseinput (rather than the old standalone workflow'sv*-tag push) and reads the
version frombackend/ctrl/Cargo.toml(the standalone workflow read the now-removed
web/package.json). Tagging, cutting the GitHub release, and the registry publishing are
now driven by the top-levelscripts/manage-release.sh(a newwrtproject kind alongside
os/cli/deb/npm), which replaces the standalone
projects/start-wrt/scripts/manage-release.sh. Registry publishing mirrors the OS's staged
flow:register start-wrtindexes a CI build into a beta registry, where beta routers
(UCIstartwrt.system.registrypointed at it) soak the version as a normal OTA update, and
release start-wrtthen promotes it into the production registry — both deliberate local,
developer-key-gated steps. Releases are cut onStart9Labs/start-technologieswith the
monorepo's<project>/v<version>tag convention (start-wrt/v<version>), since the
monorepo hosts every product's releases on independent cadences. Release assets follow the
startos naming convention —
startwrt-<version>-<git hash>_spacemit-k1-{sdcard.img.gz,sysupgrade.img.gz}— instead
of the raw OpenWrt output names, which carried no product, version, or hash; the sdcard
image is now gzipped (it was previously published raw), and balenaEtcher flashes the
.img.gzdirectly. - Restored the OpenWrt download-cache keying the migration had narrowed: the
imagejob's
cache key again includesbuild/feeds.conf(so changing the feed set busts the cache) and
carries arestore-keysfallback (so a partial older cache can seed a fresh run).
Image Downloads
StartWRT Checksums
SHA-256
BLAKE-3