- README.md: new Russian product README (what/features/architecture
mermaid/install both feeds/build/repo layout/CI/upstream/docs/license)
- README.en.md: concise English mirror (root readme was previously English)
- README.ru.md: demoted to a pointer stub (was the sing-box-lx fork readme,
a competing Russian README) -> points to README.md + engine-fork docs
- docs-shater/README.md: folder index
Install commands copied verbatim from docs-shater/INSTALL.md; all links
verified against existing files.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Upstream sing-box-lx already ships a docs/ mkdocs site; keep our project docs
separate and unambiguous in docs-shater/ (parallels upstream's docs-lx/).
Updated all references in README.md, CLAUDE.md, CONTEXT.md, ARCHITECTURE.md.
Foundation pivot. The complete, working, VM-verified xray-based project is
preserved on the `v0.1` branch; `main` is reset to a docs-first scaffold for
v0.2, which will be built as a FORK of sing-box-lx with our control-plane,
DNS filter, stats and admin panel embedded in the one binary.
- Preserve everything on branch v0.1 (pushed).
- Remove the v0.1 implementation + old design docs from main (recoverable from
v0.1); keep LICENSE, .gitignore, .gitattributes, dist/shater-feed.pub (feed
signing key 5ac4b177689cb8e0 carries over).
- License -> GPL-3.0 (sing-box is GPL-3.0).
- Add full project context so it survives compaction:
docs/CONTEXT.md (start here), DECISIONS.md, ARCHITECTURE.md, ROADMAP.md,
FEATURES.md, and a new README.
Engine/UI decisions (see docs/DECISIONS.md): fork sing-box-lx (AmneziaWG 2.0 +
broad protocols, GPL-3.0, library-first) and embed the whole product for tight
integration; keep the fork maintainable via an additive overlay (shater/, panel/,
openwrt/) rebased on upstream tags. UI = thin LuCI launcher + a separate admin
panel served by the daemon, entered via a short-lived token minted in the
authenticated LuCI session. Do NOT write a proxy engine from scratch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLthkP2S8WAfxu7fcYbPfE
Repository housekeeping so the tree is clean and navigable:
- Remove 11 stale internal working docs (00-07 planning/audit/design drafts,
ACCEPTANCE, PROOFS, STATUS) and the architecture.html artifact — history stays
in git.
- Consolidate docs under docs/: BUILD.md, FEED.md (moved), CONFIG.md (English
translation of the old Russian CONTRACT.md — full UCI schema + xrayctl/ubus
interface), ARCHITECTURE.md (distilled English, keeps the Mermaid diagrams).
- Rewrite README.md as a proper English project readme; add a Russian mirror
README.ru.md. Both cross-link.
- Add LICENSE (GPL-2.0-or-later) and unify PKG_LICENSE across all three package
Makefiles (was MIT / GPL-2.0 / GPL-2.0-or-later).
- Drop dist/README.md and dist/make-feed.sh (superseded by docs/FEED.md and the
hardened ci/make-index.sh); keep dist/shater-feed.pub.
- Fix all dangling doc references (CONTRACT.md -> docs/CONFIG.md, dead numbered
docs) in examples/, shater-core on-device comments, xrayctl/main.go, CI notes.
- Delete build junk from the worktree (shater.zip, xrayctl.exe, out/).
No code behavior change; go build + vet still pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLthkP2S8WAfxu7fcYbPfE
The published feed is now usign-signed, so routers keep opkg's signature
verification ON instead of needing --no-check-signature.
- ci/install-usign.sh builds the standalone usign on the runner (the index steps
run on the bare runner, not in the SDK container).
- ci/make-index.sh signs Packages -> Packages.sig with the secret key from the
Gitea repo secret KEY_BUILD; it now FAILS the build if KEY_BUILD is set but
usign is missing/broken, rather than silently shipping an unsigned feed.
- build.yml installs usign in both the per-arch build and the combined-index
release step, passes KEY_BUILD to the release step, and publishes the public
key (dist/shater-feed.pub) as the release asset shater-feed.pub.
- Setup is now: install the public key once into /etc/opkg/keys/<fingerprint>,
then plain opkg update/install/upgrade with check_signature left on.
Verified locally on the VM: usign -S/-V round-trips, and with check_signature=1
and only the signed feed, `opkg update` + `opkg install luci-app-shater` succeed
with no --no-check-signature. FEED.md/README updated (key rotation documented).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLthkP2S8WAfxu7fcYbPfE
Surface the one-line feed install (`opkg install luci-app-shater` from the Gitea
release) right under the status badge, plus the upgrade command and a pointer to
FEED.md in the docs table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLthkP2S8WAfxu7fcYbPfE
Two release-blocking defects found via live 512M OpenWrt VM testing.
1) Fork-storm / OOM (critical). Reconcile() -> reloadXray() ->
"/etc/init.d/shater reload" -> reload_service -> shater_reconcile ->
`xrayctl reconcile` -> Reconcile() was an infinite mutual recursion; each
level blocked on CombinedOutput and spawned a process (854x reconcile +
853x reload observed), exhausting RAM and pinning both vCPUs -> OOM-killer.
- Reconcile() no longer calls reloadXray(); procd's file-watch on run.json
restarts xray. Reconcile runs inside the init lifecycle, so calling the
init back is the recursion.
- reloadXray() now runs `/etc/init.d/shater start` (not `reload`); it is only
invoked from Apply()/Rollback() (LuCI/ubus/CLI), never the init lifecycle.
- init reload_service() simplified to start/stop (dropped the double reconcile).
Verified: `xrayctl apply` 0.39s (was >185s hang); 93 procs / load 0.00 stable
with an active 254-node config on 512M; xray binds :10853 API + :12345 tproxy.
2) UCI config namespace clash. shater shipped /etc/config/xray, which collides
with the xray-core dependency's own /etc/config/xray (opkg dropped ours to
/etc/config/xray-opkg, so the schema never took effect). Renamed the UCI
namespace xray -> shater everywhere (Go uci export/commit, all 11 LuCI views +
acl, init scripts, hotplug, Makefile conffiles, examples). Runtime paths
(/etc/xray/run.json, /usr/share/xray), the xray-core package, and the ubus
object name are intentionally unchanged.
Also: ci/pack-xrayctl.sh (local ipk packer) with a postinst chmod so the binary
is executable regardless of host-tar mode handling; PKG_RELEASE bumped to r3.
Verified end-to-end on a fresh 512M OpenWrt 24.10.3 VM: feed install
(opkg install luci-app-shater pulls xrayctl+shater-core), real LAN client
(netns in br-lan) proxied through a live subscription node -> exit IP changed
(104.156.233.234 vs 45.131.214.140 direct); per-client nft counters + xray
stats API populated. See PROOFS.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI failed: 'No feed for package xrayctl found' / 'No rule to make target
package/xrayctl/download' — gh-action-sdk indexes packages at the feed (repo)
ROOT, not a nested package/ dir. Moved xrayctl/, luci-app-shater/, shater-core/
to root; fixed workflow comment and doc paths.