Звіт у форматі JSON машиночитний
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 3303,
"has_wiki": false,
"homepage": null,
"languages": {
"Go": 347119,
"HTML": 423,
"Shell": 73024,
"Dockerfile": 13944,
"TypeScript": 185449
},
"pushed_at": "2026-07-20T07:27:36Z",
"created_at": "2026-06-02T21:28:10Z",
"owner_type": "Organization",
"updated_at": "2026-07-20T07:27:46Z",
"description": "MoaV client — multi-protocol proxy with load balancing and web dashboard",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Go",
"significant_languages": [
"Go",
"TypeScript",
"Shell"
]
},
"owner": {
"blog": "https://moav.sh",
"name": "MoaV - Mother of all VPNs",
"type": "Organization",
"login": "MotherofallVPNs",
"company": null,
"location": null,
"followers": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/290194482?v=4",
"created_at": "2026-06-03T00:07:19Z",
"is_verified": null,
"public_repos": 3,
"account_age_days": 52
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v1.3.2",
"kind": "patch",
"published_at": "2026-07-13T21:18:20Z"
},
{
"tag": "v1.3.1",
"kind": "patch",
"published_at": "2026-06-09T14:04:53Z"
},
{
"tag": "v1.3.0",
"kind": "minor",
"published_at": "2026-06-08T23:20:44Z"
},
{
"tag": "v1.0.0",
"kind": "major",
"published_at": "2026-06-05T17:10:58Z"
}
],
"recent_commits": [
{
"oid": "0c24d7c076624f60a176dbbbb55c86c27ab20251",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-20T07:27:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f8fa6273a23889d9f00894289c19e90bc7e7a583",
"body": "feat: publish install.sh as release asset + moav.sh/client-install.sh",
"is_bot": false,
"headline": "Merge pull request #16 from MotherofallVPNs/feat/client-install-url",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-17T17:27:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b666483ed9bfb4535b60c1737d57a5deeac2f1fa",
"body": "…ll.sh\n\nAdd a publish-install workflow that uploads install.sh as the `client-install.sh`\nrelease asset on each release, so moav.sh can serve the latest installer\n(reachable in censored networks) — mirroring the MoaV server's install.sh.\nPoint the README (EN + FA), docs/INSTALL.md, and the installer\n[…]\nown usage\nbanner at the new moav.sh/client-install.sh URL.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01NzWWMGR3wAkaa9HHAQRtRL",
"is_bot": false,
"headline": "feat: publish install.sh as a release asset; use moav.sh/client-insta…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-07-17T17:22:01Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "68268173c2db580d9d2cb61067a6f24cfb5640c0",
"body": "…the grid\n\nPromote dashboard.gif to the top hero; the static Endpoints screenshot now\nopens the Web dashboard section above the Analytics/Plugins/Configs/Settings grid.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01NzWWMGR3wAkaa9HHAQRtRL",
"is_bot": false,
"headline": "docs: lead README with the walkthrough GIF, move Endpoints shot into …",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-07-17T16:16:45Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6fb209ae8c1aa7213dd7e1687753a03e6dba0eb2",
"body": "Wire the Endpoints hero, walkthrough GIF, and Analytics/Plugins/Configs/\nSettings tab screenshots into README.md and README-fa.md. All server IPs,\ndomains, bundle names, and personal egress IP are masked in the captures.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01NzWWMGR3wAkaa9HHAQRtRL",
"is_bot": false,
"headline": "docs: add dashboard screenshots + walkthrough GIF to README",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-07-17T15:53:45Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "fc74095bd24cc0c86e7fe2caa5118fa38b1d8b7f",
"body": "…ifier\n\nci: Telegram release/issue notifier (mirrors moav server)",
"is_bot": false,
"headline": "Merge pull request #15 from MotherofallVPNs/feat/telegram-release-not…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-15T16:11:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4abf49f8f67d5042546b7e10975955641d3ac28f",
"body": "Auto-posts to the shared MoaV Telegram channel on:\n- release published → title (prefixed \"moav-client\") + notes excerpt + links\n- issue labeled `announce` → title + link\n- workflow_dispatch → test message, or a real notification for a past\n release via the `release_tag` input\n\nMirror of Motherofall\n[…]\ns TELEGRAM_BOT_TOKEN\n+ TELEGRAM_CHAT_ID; sends skip cleanly when unset.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_012BWuTaD7kxGQksBLFHrUEp",
"is_bot": false,
"headline": "ci: Telegram release/issue notifier (mirrors moav server)",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-15T16:05:09Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b7f67e1aadd1f20d0eb8ee516330fc4f94104ea0",
"body": "…back\n\nfix(e2e): synthesize subscription.txt for text-only/older bundles",
"is_bot": false,
"headline": "Merge pull request #14 from MotherofallVPNs/fix/e2e-subscription-fall…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-14T00:51:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5b986cb38bfe8ed93e8cbbb6e84ae60f32f147be",
"body": null,
"is_bot": false,
"headline": "ci(e2e): reference the renamed `moav user base64` in the bundle_b64 help",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-14T00:48:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f30ba06aa6383c177c7a3411ce8a3bdbe0d491cf",
"body": "A text-only or older MoaV bundle can lack subscription.txt (it's normally\nwritten alongside the rendered README). Instead of failing, build it from the\nbundle's share-link files (base64 of the joined vless/trojan/ss/hysteria2/anytls\nURIs — MoaV's own format), so any server bundle works with the client e2e.",
"is_bot": false,
"headline": "fix(e2e): synthesize subscription.txt when a bundle omits it",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-14T00:48:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bf4bd054c368a95a014a5e9daf8757f6a665e694",
"body": "…d-masking\n\nci(e2e): dispatch config inputs + full logs + IP/domain masking",
"is_bot": false,
"headline": "Merge pull request #13 from MotherofallVPNs/ci/e2e-dispatch-config-an…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-14T00:23:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a8dc62efbd043a3ec42101f5b247934dd1b3c3c2",
"body": "- workflow_dispatch inputs bundle_b64 / sub_url / exit_ip override the standing\n secrets, so you can point the client e2e at any deployed MoaV server ad-hoc\n (e.g. paste the base64 from `moav test generate <user>`). On push/release the\n inputs are empty and the secrets are used.\n- full_logs input\n[…]\nthe assertion. Best-effort redaction of the known exit IP in artifacts.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_012BWuTaD7kxGQksBLFHrUEp",
"is_bot": false,
"headline": "ci(e2e): dispatch config inputs + full-log snapshots + IP/domain masking",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-14T00:11:54Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9ce4eaf181497476def5bb18ca50c42e88ea1759",
"body": "ci(e2e): run e2e on every push to main",
"is_bot": false,
"headline": "Merge pull request #12 from MotherofallVPNs/ci/e2e-on-push-main",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:40:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f066728b644981f7b5c715d91b44f2fc7617e0f6",
"body": "Adds `push: branches: [main]` alongside workflow_dispatch and release, so\neach merge to main validates the full client round-trip on the\nself-hosted runner (warm cache makes it ~30s). Manual dispatch and\non-release triggers are unchanged.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "ci(e2e): run the live e2e on every push to main (+ keep manual/release)",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:35:49Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "a646f2320c3976738cc4d61d9571da4e9a851ad8",
"body": "fix(api): build on Windows — platform-split IP_TTL setsockopt (#7)",
"is_bot": false,
"headline": "Merge pull request #11 from MotherofallVPNs/fix/windows-build-issue-7",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:30:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b25cfee2093ca7482becffda5258ce5443d4ab5b",
"body": "makeTTLControl (the /api/diag by-hand traceroute) called\nsyscall.SetsockoptInt(int(fd), ...), but a socket fd is int on Unix and\nsyscall.Handle on Windows, so `go build` failed on Windows:\n\"cannot use int(fd) ... as syscall.Handle value\". Move the setter into\napi/ttl_unix.go + api/ttl_windows.go behind build tags. Verified builds\non windows/linux/darwin; api tests pass. CI now cross-compiles for\nwindows+darwin so this class is caught.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(api): build on Windows — platform-split IP_TTL setsockopt (#7)",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:27:40Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "f58fde720cd639e9e270aa417cbc37e395bc144f",
"body": "release: v1.3.2",
"is_bot": false,
"headline": "Merge pull request #10 from MotherofallVPNs/release/1.3.2",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:17:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f8ff8cc7c94a9575567fdfd69a4dc29138be1533",
"body": "Bump VERSION / web-ui package.json / proxy-core cli.go fallback to 1.3.2\nand cut the [1.3.2] changelog. Ships the full CI/testing suite (Go +\nweb-ui unit tests, parity guard, coverage/golangci-lint/compose CI, live\ne2e), the docs/PROTOCOL-PARITY.md audit, and the Slipstream dead-stub\nremoval. No user-facing feature change — v2 will jump to 2.0.0.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "release: v1.3.2 — testing suite + parity audit",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:16:53Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "3e4a3df3b2d3168444309f42cabba7c0f2b19bd0",
"body": "test+ci: full testing suite + protocol parity audit (v2 hardening)",
"is_bot": false,
"headline": "Merge pull request #9 from MotherofallVPNs/test/full-testing-suite",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-13T21:04:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6f4719f205254b08db59dbf84e4ac1bcfde04b3e",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-13T07:35:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "59e6039d8a4962697f6cecd4c4829d6c363b793c",
"body": "# Conflicts:\n#\ttests/e2e-client.sh",
"is_bot": false,
"headline": "Merge remote-tracking branch 'origin/main' into test/full-testing-suite",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T20:38:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b4dbdc8c0d73f4574dc4b4d8aa31e7c3307eff49",
"body": "Run 6 exited via the runner's own IP — the balancer's involuntary direct\nfallback leaked when the picked endpoint failed, making the exit-IP\nassertion meaningless. Set block_direct=true so a fetch through :1080\negresses from the server or fails cleanly (no leak), and retry the\nexit-IP fetch (~75s) so the balancer can fail over to a working endpoint\nwhile probes settle.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(e2e): tunnel-only exit-IP check (block_direct) + retry",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T20:18:35Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "053e1d12161df629a7b7935b20dd0435cf19d6e7",
"body": "/api/endpoints returns {\"endpoints\":[...]} (a wrapper object) with\ncapitalized Go field names (.Status/.Protocol/.LatencyMs/.ID), not a\nbare array of lowercase-tagged objects. My jq read `length` (=1 for the\nobject) and `.[].status` (never matched) — so a run with 6 OK endpoints\nlooked like \"1 parse\n[…]\nds.\n\nThe artifact from run 5 confirmed the client actually connects: Reality,\nCDN, Trojan, Shadowsocks-2022, Hysteria2, WireGuard all validated.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(e2e): parse the real /api/endpoints shape",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T20:14:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c212b1c1c81018f177d2c276a5cae0738fa17990",
"body": "python3 -m zipfile / different zip tooling can nest the bundle under a\ntop-level dir, so the flat data/e2e-bundle/subscription.txt path missed.\nfind it wherever it landed and derive the bundle dir + wg confs from\nthere; dump the extracted file list if it's genuinely absent.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(e2e): find subscription.txt anywhere in the extracted bundle",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T20:09:00Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "1440796072c3e08ec375f1aefe1c86c58413ac3f",
"body": "The runner has no `unzip` (exit 127). Fall back to\n`python3 -m zipfile -e` (already present on the e2e box), or fail with a\nclear message if neither is available.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(e2e): portable bundle extraction (unzip or python3)",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T20:06:52Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2040ed3e94937bb2cc923987102207d3e8bda65b",
"body": "Two fixes from the first live run:\n- subscription.file wants a subscription.txt (a URI list), not a bundle\n .zip — feeding the zip parsed 1 lucky URI. Unzip the bundle and point\n file at data/e2e-bundle/subscription.txt (+ wireguard_files for the WG\n confs), so all the URI/WG protocols load.\n- PO\n[…]\nll\n /api/endpoints for status==\"ok\" afterward instead of reading the probe\n response, with a timeout and early-exit once all endpoints settle.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(e2e): unzip bundle for subscription.file + poll async probe",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T20:05:15Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "571d6d62d684192bf729d6837e6ad757f7305505",
"body": "docker-compose.yml declares env_file: .env (and bind-mounts ./.env), so\n`docker compose up` fails immediately (\"env file .env not found\") when\nit's absent. Seed it from .env.example in the helper, like the CI\ncompose-validate job does.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(e2e): seed .env before docker compose up",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:59:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6fcc997ebcbe6ce5d4d1ab5cbcbf73b22e05a398",
"body": "workflow_dispatch only lists a workflow when it lives on the default\nbranch, so add e2e.yml (+ its tests/e2e-client.sh helper) to main to\nsurface \"Run workflow\". The full testing suite it belongs to is in\nPR #9 (branch test/full-testing-suite); dispatch selecting that ref to\nrun against the complete changes.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "ci(e2e): add the e2e workflow to the default branch",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:57:13Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "1ed437b47aa80a632be87501e93e884dfa9eada3",
"body": "A full bundle's README.html + QR PNGs exceed GitHub's ~64KB secret cap;\ndocument dropping them and re-zipping the config files only.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs(e2e): note bundles must be stripped to fit the secret limit",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:54:27Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "159b405b8c695cdf1cdd0543a72dc1d356e5e0c3",
"body": "macOS base64 (BSD) has no -w0; document `base64 -i bundle.zip | tr -d '\\n'`\nfor macOS alongside the GNU `base64 -w0` form.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs(e2e): cross-platform base64 for the bundle secret",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:51:08Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "344a40f739ebafd2fc39a2baf4ade2de4cbe8c8f",
"body": "Add the live client e2e: tests/e2e-client.sh brings the stack up against\na provided MoaV server bundle and asserts endpoints parse, /api/probe\nvalidates >=1 endpoint (tunnel + TLS), and a fetch through SOCKS5 :1080\negresses from the server's IP (not the runner's). Driven by\n.github/workflows/e2e.yml\n[…]\ner run) with\nits open questions. The e2e is opt-in / not on the PR path, so it awaits\nrunner setup to validate — same rollout as the server e2e.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "test+ci: Phase 2 — live e2e workflow + self-hosted runner doc",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:36:45Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4a78d1413f73a84fe43e759e2eccc88ef8cd06cb",
"body": "Slipstream was declared (config toggle + manager entry + UI leftovers)\nbut had no docker-compose service, so enabling it made the balancer dial\na nonexistent slipstream:5302 host. Remove the stub across proxy-core\n(config.SidecarsConfig, sidecars manager) and web-ui (label + chart\ncolors). Go build/\n[…]\nabeled MasterDNS copy (runs the\nmasterdns binary), so a real dnstt client is separate feature work.\ndocs/PROTOCOL-PARITY.md updated accordingly.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(sidecars): remove dead Slipstream stub",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:32:38Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "0a20a839e401ecfa622a7a26e28ef60ccc0bb71c",
"body": "Go (proxy-core): unit tests for the previously-untested packages —\nbalancer (0→57%), state (0→75%), cmd (0→37%), sidecars (0→93%) — and a\nlift to the sing-box generator (46→88%). singbox/parity_test.go is a\nprotocol parity guard: it pins each protocol's outbound shape and\nasserts the Xray-only trans\n[…]\nOCOL-PARITY.md: client↔server protocol audit (13 full, 2\npartial; hard gaps wstunnel/XDNS/GooseRelay/Snowflake, Slipstream stub,\ndnstt unwired).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "test+ci: Phase 1 — Go/web-ui unit tests, parity guard, CI hardening",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T19:14:33Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2d9de8ce6031b190ff5cd29e1ed228780d495634",
"body": "chore(org): point MoaV links at MotherofallVPNs/moav",
"is_bot": false,
"headline": "Merge pull request #8 from MotherofallVPNs/chore/org-ref-sweep",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T14:18:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1e24c092be16801af6dadedd22278c1741f2c6b3",
"body": "The server repo moved shayanb/MoaV -> MotherofallVPNs/moav. Update the\nreferences in README/README-fa, CLAUDE.md, docs/MOAV_BUNDLE.md, and the\nweb-ui theme comment.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(org): point MoaV links at MotherofallVPNs/moav",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-12T14:16:14Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c72281a97d33a9f557fc02b29bf2ff673dbb6439",
"body": "feat: AnyTLS protocol support",
"is_bot": false,
"headline": "Merge pull request #6 from MotherofallVPNs/feat/anytls-protocol",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-07-11T20:49:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6491322faffe767f4af41370512652e918523b07",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-06T08:40:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0399e4fd7484ec38f2ee46eb5a7aaa2906459e2d",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-29T09:06:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d5b446e4ffa56c691c48d097323f1875f6a7a0db",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-22T10:14:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1f38fea4d6fe55cad3f98ac7cdb856401995507d",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-15T10:32:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "156927ccb441b331214539570920070de8ad2973",
"body": "Mirror the Trojan path end-to-end for the AnyTLS protocol:\n\n- subscription parser: parse anytls:// URIs (password userinfo, host,\n port, sni, insecure/allowInsecure flag, fragment label; bracketed IPv6)\n- sing-box generator: emit an anytls outbound with a TLS block\n (server_name, insecure) + utls \n[…]\nsplay map\n- tests: parser round-trip (incl. IPv6 + insecure aliases), sing-box\n outbound mapping, and moav bundle expansion coverage\n- docs: README (EN/FA), CLAUDE.md, ARCHITECTURE.md, MOAV_BUNDLE.md",
"is_bot": false,
"headline": "feat: AnyTLS protocol support",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-13T16:51:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "99d87afac07340a97818c0d12037dd6cd79a068a",
"body": "- moav-client api_curl(): send MOAV_DASHBOARD_USER/PASS basic-auth from .env to\n the API, so `stats`/`probe`/`status` work once a dashboard password is set\n (previously 401 after exposing on LAN).\n- update: restore a deleted data/.gitkeep before the local-changes guard, so a\n tracked dir-placehol\n[…]\nng…\" line) so it renders once with the real mode instead of\n painting loopback then reflowing to lan when the auth panels appear.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: wrapper API auth + update .gitkeep guard; settings exposure reflow",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T14:44:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b6b330bb34d0eee85c4810efefc4963d9638e8b2",
"body": "A stray `2>/dev/null` on the `read -r -p` calls in confirm_yes (update rebuild\nprompt) and cmd_uninstall hid the question — read writes its -p prompt to\nstderr, so users saw the warning then \"cancelled\" with no visible Y/N. Dropped\nthe redirect; </dev/tty alone handles the no-TTY case.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(cli): show the uninstall/update confirm prompts",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T14:04:26Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "7304f0cb1d5ebc1f97cf7b9e2a0c8d1f89c84fa1",
"body": null,
"is_bot": false,
"headline": "Merge remote-tracking branch 'origin/dev'",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T14:03:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6b6d812405338c14fd1b3a008a7f62dadb27613c",
"body": "…docs\n\n- Add mem_limit + cpus to every service in docker-compose.yml (matching the\n MoaV server): 256m/1.0 for proxy-core & sing-box, 256m/0.5 for xray/tor/\n amneziawg/trusttunnel/psiphon, 128m/0.5 for web-ui/masterdns/sni-spoof/caddy.\n Previously unbounded (could use all host RAM).\n- Replace est\n[…]\nper-service caps;\n footprint totals corrected (core ~276 MB disk / ~35 MB RAM, full ~970 MB /\n ~130 MB), build-cache note ~8 GB.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(compose): per-container memory/CPU limits; exact image sizes in …",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T13:46:09Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1b886ece611092bc6cabced5049c9c5bcfc92d84",
"body": "…ease notes\n\n- `moavc update` now asks `rebuild & restart now? [Y/n]` (default yes) after\n pulling; on no it leaves the new code pulled and notes that it only takes\n effect after a rebuild & restart. New confirm_yes helper (defaults yes when\n there's no TTY, so non-interactive updates still rebuild).\n- .gitignore: ignore .DS_Store and local RELEASE_v*.md paste artifacts.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): prompt before rebuild on update; gitignore .DS_Store / rel…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T13:40:27Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d0d7a78f2f91ee18a9dbc166b52483caa323129e",
"body": "…Tunnel msg\n\n- Add the GOPROXY=…|goproxy.cn|direct + GOSUMDB=off fallback to every\n Go-building image (proxy-core, sni-spoof, psiphon, amneziawg; xray already\n had it). Fixes `docker compose build` aborting on a 403 from Google's module\n CDN under rate-limiting (e.g. some VPS IPs/regions).\n- inst\n[…]\nITECTURE.md — the sidecar builds the official upstream\n client and only needs the bundle's client.toml (now a needs-config note).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(build): resilient GOPROXY in all Go images; install polish; Trust…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T13:28:17Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "afd7e18fb5f07ab3f665bc65393dfd01266d3bc3",
"body": "Release v1.3.1 — moavc alias, status fix, exposure-toggle restyle",
"is_bot": false,
"headline": "Merge pull request #5 from MotherofallVPNs/dev",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T13:13:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "967129958774a6344e195379d5a8e6486a7a39ae",
"body": "- Installer symlinks `moavc` into PATH alongside `moav-client` (and uninstall\n removes both). `moavc` is the short official alias.\n- Docs/READMEs use `moavc` in command examples, with a note that `moav-client`\n still works (quick-start + INSTALL).\n- Bump VERSION / cmd.Version / compose / Dockerfil\n[…]\nample / package.json\n to 1.3.1; CHANGELOG entry covering the alias, the empty-arg compose fix, and\n the exposure-toggle restyle.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add `moavc` alias, bump to v1.3.1",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-09T12:55:26Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4052470a56913fcfdb5e03706c253d807a644425",
"body": "…enabled\n\n`compose \"${args[@]:-}\" ps` expands an empty array to a single empty-string\nargument, so `docker compose \"\" ps` ran and errored. Use the\n`${args[@]+\"${args[@]}\"}` idiom, which expands to nothing when empty and the\nquoted elements otherwise. Fixes `moav-client status` (and up/down/logs/upda\n[…]\nNetwork-exposure on/off toggles as a real sliding switch\n(track + knob + label) so they clearly read as actionable, not just text.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(cli): don't pass an empty arg to docker compose when no sidecars …",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T23:23:41Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "0a1d954f6e4edffac3e52f023e06c6bb601b3f87",
"body": "Release v1.3.0 — installer/CLI overhaul, official Xray, version pinning, Settings redesign",
"is_bot": false,
"headline": "Merge pull request #3 from MotherofallVPNs/dev",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T23:17:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "430fc196ae729a75d12359865a48ceca12b99ff8",
"body": "- README / README-fa: auto-install + checklist wizard in quick-start; new CLI\n commands (status/info/expose/update -b/uninstall); official-XTLS xray row +\n updated footprint; Sources→Configs tab; Config tab folded into Settings;\n clarify management-wrapper vs proxy-core binary; version-pinning no\n[…]\n sections.\n- SIDECARS / TROUBLESHOOTING: Sources→Configs; add shallow-clone branch-switch\n recovery and uninstall/reset guidance.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: refresh READMEs + docs for v1.3.0",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T23:05:49Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2fa0533132173f89f3366c5aa96383bc0dcd2dbb",
"body": "Group the Settings page into responsive carded panels instead of one long\nscroll: strategy + probe alongside network exposure (row 1), access & URLs\nalongside SNI spoofing (row 2), then backup & restore and the collapsed\nadvanced YAML editor full-width. Single column on mobile.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui): two-column Settings layout to reduce overwhelm",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T22:58:28Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "f43f9df307574d8a6695e9a1646f4c7b975f27c8",
"body": "…u, size table, random password\n\n- update: fetch the target branch's tip explicitly and reset the local branch\n to it (git fetch --depth=1 origin <branch>; checkout -B … FETCH_HEAD), so it\n works on the installer's shallow single-branch clone where `fetch --all` and\n origin/<other-branch> don't e\n[…]\nprompt now auto-generates a random one when left\n empty and prints it (with where it's stored) instead of leaving the panel open.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli/install): shallow-clone-safe update, uninstall, checkbox men…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T22:55:17Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "87f3a74fd65ec45e429744782c0fa6dc34dbd47d",
"body": null,
"is_bot": false,
"headline": "chore: merge latest main (geoip refresh) into dev",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T22:48:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "50a6a1707c49bb733593314b0197eac5b640b2bd",
"body": "CLI wrapper\n- Replace the terse \"drop-in convenience\" help with a banner: MoaV ASCII logo,\n version (from VERSION), and repo/site links; grouped, relevant command list.\n- `status` is now a formatted Service/Status table plus endpoint health (X/Y +\n active strategy from the API) and the access URLs\n[…]\nntry covering the installer auto-install + wizard,\n official Xray image, version pinning, dashboard fixes, and this CLI redesign.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(cli): redesign moav-client wrapper + bump to v1.3.0",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T21:35:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "7896f61348bd3d94c77ae99ed8a692fde694740b",
"body": "…, tab cleanup\n\nInstaller\n- Wizard/confirm prompts now use `read -e` so arrow keys do line-editing\n instead of injecting ^[[A; make them bold cyan »-prefixed so it's clearly a\n question awaiting input (covers the build & start confirm).\n- After LAN exposure, detect when the host's primary IP is pu\n[…]\nlone Config tab; fold the config.yaml editor into the bottom\n of Settings as a collapsible \"advanced — edit config.yaml\" section.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(install/ui): readline prompts, public-IP warning, VPS URL display…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-08T16:58:55Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "706dda08a6b846236d107bead3bb8359cd12f0f9",
"body": null,
"is_bot": true,
"headline": "chore(geoip): refresh CIDR lists [skip ci]",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-06-08T09:03:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c8072d821efb43eff85ee6842db50a4e6cac174f",
"body": "…g, official xray, LAN exposure\n\nInstaller & wrapper UX\n- Fix the core bug: install.sh went headless under `curl | bash` (stdin not a\n TTY) and skipped every prompt. Now prefers /dev/tty and only falls back to\n headless with no terminal at all (genuine cloud-init/CI/cron).\n- Replace the per-item y\n[…]\nintTable surfaces \"run: moav-client sidecar add <kind>\".\n\nDocs: INSTALL.md covers the wizard, expose command, and version pinning.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(install): interactive-when-piped, sidecar wizard, version pinnin…",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-07T15:40:13Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5c76de1b15fb82700b6d0efbfccbe18bf51af3e6",
"body": "The installer previously exited when docker (or git/curl/python3) was\nmissing. It now installs them automatically:\n\n- detect_os() + package-manager helpers (apt/dnf/yum/apk/pacman/brew)\n- install_docker(): Linux via get.docker.com, Alpine via apk, macOS via\n Homebrew (Docker Desktop); Windows/unkno\n[…]\n\nNew knobs: --yes/-y (MOAV_ASSUME_YES), --no-docker-install\n(MOAV_NO_DOCKER_INSTALL). docs/INSTALL.md updated with platform table.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(install): auto-install missing prerequisites cross-platform",
"author_name": "Shayan Eskandari",
"author_login": "shayanb",
"committed_at": "2026-06-07T14:51:54Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "39d636e4d3dcc81b2e643be62ab2369dd396da79",
"body": "Document the plugin/routing system end to end: how a decision is made\n(torrent-blocker → first-match-wins chain → default proxy), all match types and\nactions, the hostname-vs-IP caveat, the block-direct kill-switch, geoip, the\nconfig.yaml shape, and the API. Full template catalog in two groups —\nnet\n[…]\nction + dashboard table (drop the removed\nir-geo-proxy, add the selective-app templates) and link the new doc from the\ndocs index.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: add docs/PLUGINS.md (routing engine + full template catalog)",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T13:33:24Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1f90490bbf5ef7f154ba78f1f0e8167ff487df2f",
"body": "…ync/streaming/games)\n\nCurated destination-based templates to keep specific apps off the VPN or block\ntheir background traffic — the practical approximation of TripMode/WireSock\nper-app tunneling, since a SOCKS5/HTTP proxy sees the destination, not the\noriginating process:\n\n- block-system-updates →\n[…]\n↔direct, add/remove domains) per the existing template\nflow. Shared-CDN apps can't be isolated this way — documented in each Help.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(plugins): selective-app routing templates (updates/zoom/icloud/s…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T13:18:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "020b3117b781bae0f34f70c276ffb9b7edd81a37",
"body": "…label\n\nDistinguish endpoints/sources that came from a MoaV bundle import from pasted\ncustom sources. Paste-added sources are tagged origin=custom; bundle imports and\nlegacy sources default to moav. /api/sources reports is_moav; the Endpoints tab\nprefixes the source with \"moav/\" and the Sources tab shows a \"moav\" badge.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui): mark MoaV-bundle sources with a moav badge / moav/<bundle> …",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T02:52:18Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "7bd76e4f30c279ca5dbbb44ae33f2aa24321edbe",
"body": "Bump proxy-core Version + web-ui package.json to 1.2.0 and write the 1.2.0\nCHANGELOG section (dashboard login, network exposure controls, responsive\nmobile UI, paste-text sources, source tags + sidecar attribution, rule\npersistence, comment-preserving config writes, and the related fixes).\n\nTag + GitHub release left for manual publishing.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(release): prepare v1.2.0",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T02:41:15Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2de0c12ac5440fa33aca13501201fb483a161337",
"body": "Naming (display-only; canonical IDs/names untouched for state + dedup):\n- displayEndpointName now strips the MoaV-/-<source> decoration and sidecar-\n prefix and pretty-cases known kinds, so the Source column owns the bundle and\n the name is just the label: \"MoaV-Hysteria2-beezhantest2\" → \"Hysteria\n[…]\nest/endpoint to nothing on phones;\n below 640px each flow is now a stacked row (id+bytes+result, then dest, then\n the endpoint).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: bare endpoint names, paste-text sources, readable flows on mobile",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T02:38:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a15470fd4bd465195b206cb6b14ae1b62bba51e1",
"body": "The subscription.txt path was noise — the bundle name (card title) plus the\ncomponent tags already convey what a source is. Drop the local file path in\nboth the mobile cards and the desktop table (rename that column \"Components\"),\nkeeping a remote URL when present.\n\n(Generic sidecars like psiphon/tor aren't bundle-attributed — handled by only\ntagging importer-written sidecars; the user's psiphon backfill was removed.)\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(ui): drop local file path from Sources, show URL + tags only",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T02:24:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4adc318e71400c4d1d76208b1c18f6a5be042b5e",
"body": "…ad row\n\n- The bundle importer now tags each sidecar config it writes with\n sidecars.<kind>.config.source = <bundle name>. SidecarManager surfaces that\n as the endpoint's Source, so the Endpoints tab shows the originating bundle\n (e.g. \"beezhantest2\") instead of the generic \"sidecars\" group. main\n[…]\npload row: the dropzone goes full-width with the ?/reload buttons on\n their own row on mobile, instead of three squished columns.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: attribute imported sidecars to their source bundle; mobile uplo…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T02:13:40Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "08bcfa5aa109e816eaecdc629d7a4391574d84c6",
"body": "Both rendered as wide tables that wrapped mid-word on phones (source paths\nbroke like \"subscr/iption.t/xt\", and the per-endpoint status stacked oddly).\nBelow 640px they now render as stacked cards — name + status on top, then the\naddress and the dials/err/failovers/up/down/last stats laid out cleanly — while\nthe desktop tables are unchanged.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "style(ui): card layouts for Sources + Analytics per-endpoint on mobile",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T01:59:30Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4855ce8f4f83d8a1caaa3ea74cf85e7564cc7f90",
"body": "Re-auth prompt: iOS Safari doesn't attach cached basic-auth credentials to a\nWebSocket handshake, so the basic-auth-protected /api/ws got 401'd and Safari\nre-prompted whenever a WS tab (Endpoints / Debug) mounted. Fix with a ticket:\n- proxy-core issues a short-lived single-use ticket at GET /api/ws-\n[…]\nthe header\nshowed \"no endpoints\". App now polls /api/endpoints so the count is always live.\n\nAlso drop two unused WS_BASE imports.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(ui): stop Safari WS re-auth prompt; keep header count on every tab",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T01:54:26Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f7fb22e0b3dba592ffcd3286e914b4944c30b331",
"body": "Comment-preserving YAML:\n- Add a shared yaml.Node-based editor (editYAMLFile + a yamlMap helper) that\n edits only the nodes it touches, so comments / key order / blank lines in\n config.yaml round-trip intact instead of being wiped by the old\n unmarshal-to-map / re-marshal path.\n- Convert all four\n[…]\nored password on save.\n\nAlso update the exposure tests for the reveal-when-authenticated behavior and\nadd a masked-when-open case.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: comment-preserving config writes + disable-auth toggles",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T01:36:56Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1a5bda723d01725291f6ee5ebccee2b1385f18cb",
"body": "…mplate\n\n- Dashboard rule edits (add / remove / enable / disable / reorder) now write\n back to config.yaml's plugins.routing_rules via PUT /api/plugins, so they\n survive a proxy-core restart instead of resetting to the on-disk config.\n- RoutingRuleConfig gains `enabled` (pointer → absent defaults \n[…]\nnfig.yaml\").\n\nVerified: a disabled rule persists as disabled across a restart; config.yaml\nround-trips with per-rule enabled/note.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(plugins): persist routing rules to config.yaml; drop ir-proxy te…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T01:13:17Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "6db6af5b2864049381c63ddca32add741a29ae50",
"body": "… clarify templates\n\n- Copy buttons did nothing over plain HTTP on a LAN IP because\n navigator.clipboard is undefined outside secure contexts. Add a copyText()\n helper with a hidden-textarea + execCommand fallback; use it in the ACCESS &\n URLS panel, the recreate-command copy, and Debug's copy-al\n[…]\n match IP\n literals only (no hostname resolution), and ir-geo-proxy notes it's the\n inverse of the default 'Iran → direct' rule.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(ui): clipboard fallback over HTTP, refresh URLs on exposure save;…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T01:06:03Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "bd0418db3ea026b64bfdcda2696ae17c849166e4",
"body": "The topbar controls were a single wrapping row that scattered on mobile.\nGroup them: status (clock + health pill) and actions (Refresh + Apply/restart)\nare now distinct rows on phones — health spans the status row, buttons stretch\nfull-width for tap targets — and stay inline on desktop. Slightly larger radius\nto match the pill tabs.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "style(ui): reorganize header into title / status / action groups",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T00:44:05Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9f1cb551e8456a5b96ce65cbedc75e63bd867da8",
"body": "- The selected tab is saved to localStorage and restored on load, so a refresh\n no longer snaps back to Endpoints.\n- ACCESS & URLS now shows the address appropriate to the exposure mode, using\n only local signals (no external IP lookup):\n loopback → 127.0.0.1\n lan → the LAN IP you're vi\n[…]\n clearly-marked placeholder + port-forward note\n Backend /api/exposure gains lan_ip from a local net.Interfaces scan.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui): persist active tab across refresh; mode-relative ACCESS & URLS",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T00:38:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b1ad987745ab7e5779d7c602ea463c3bd9800919",
"body": "…pply button\n\nAuth fields (Settings → exposure):\n- Add explicit auth_set / dashboard_set flags so the UI states plainly whether\n a password is set (✓/✗) instead of an empty field that looked filled because\n of a •••• placeholder.\n- Password inputs are now type=password with a show/hide toggle.\n- S\n[…]\ning breaks the affected endpoints. (No TLS cert is involved; it's\na uTLS ClientHello-injection passthrough, not a TLS terminator.)\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui): clearer auth set-state + reveal, fix URL/footer wrap, SNI a…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T00:28:49Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "85d2926dd3370205d472ef91befeefdcb2dc7139",
"body": "…polish\n\nDashboard auth that actually works:\n- The dashboard now calls /api on its OWN origin; nginx (and the existing Caddy\n https profile) reverse-proxy /api + /api/ws to proxy-core. Single origin means\n one set of browser basic-auth creds covers the UI and the API together — the\n previous dire\n[…]\nno longer overflow the screen (min-width:0 +\n border-box in the grid).\n- index.html served no-cache so new builds load on mobile.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(auth+ui): working dashboard login (separate from proxy), mobile …",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-06T00:09:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c7171f8febe8204609dac317c672e4235037851e",
"body": "…moav\"\n\n- nginx now serves a custom server block that marks index.html no-cache (so a\n fresh build's hashed bundle is picked up instead of a stale one cached by\n mobile Safari) while long-caching the content-hashed assets.\n- SOCKS5 auth defaults the username to \"moav\" when only a password is set, and\n the exposure form prefills \"moav\" — matching the expected default.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(ui): no-cache index.html so new builds load; default proxy user \"…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T23:57:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "795232930a974a288fb3f4e32e673c1bc376b678",
"body": "…ies-auth\n\nMobile:\n- Endpoints render as stacked cards below 640px (was an overflowing table);\n remaining wide tables (Analytics, Sources) scroll in their own containers.\n- Remove the card-level overflow-x that clipped the block-direct banner; share\n the useIsMobile hook.\n\nApply without a terminal\n[…]\n (username optional) — both\n main.go and server.go required both, silently leaving the proxy open when\n only a password was set.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui+auth): mobile card layout, apply-from-dashboard, restart-appl…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T23:40:43Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4832d680639955f5cafc13bb463d608a7e0b87b8",
"body": "Add a useIsMobile hook and adapt the layout below 640px: the topbar stacks\n(logo/title on one line, controls below) instead of overlapping the clock,\nthe decorative subtitle hides, page + card padding shrink, and wide tables\n(Endpoints, per-endpoint stats) scroll horizontally within the card via\noverflow-x + a min-width instead of overflowing the viewport.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(ui): responsive layout for phones",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T23:15:30Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b3e5e0a4653bfa8a9ebfa22f98425df36532f13b",
"body": "…he dashboard\n\nhandleExposure set SOCKS5_BIND/HTTP_BIND/UI_BIND but not API_BIND, so enabling\nLAN exposure made the dashboard (:3001) reachable while the API (:8088) it\nfetches from stayed loopback — the dashboard loaded over LAN but couldn't get\ndata. Bind API_BIND to the same interface.\n\nAdd an \"a\n[…]\nng that the dashboard is\n:3001 (not :1080, which is the SOCKS5 proxy), with a copy button each and a\nno-auth warning when exposed.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(exposure): bind the API too on lan/public + show access URLs in t…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T23:10:56Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "8904976cac106a2d5b00f2bd9c81c69548fd0005",
"body": "…ealthy\n\nA single transient blip (a momentary Reality handshake failure, a brief\nnetwork hiccup, a sidecar mid-restart) flipped an endpoint to \"error\" for a\nwhole 30s cycle. Retry once (after 300ms) on error/timeout before recording\nthe status; oks aren't retried. Smooths spurious flapping without delaying\ndetection of genuinely-down endpoints.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(prober): retry a failed probe once before marking an endpoint unh…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T19:01:37Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c10eb13bce2b4f7765428c77ec541dbfb5290713",
"body": "Per the intended default: the single enabled rule out of the box is\n`geoip:ir → direct` (Iranian destinations bypass the proxy, keeping domestic\ntraffic on the real IP to avoid VPN detection + IR-IP blocks). torrent_block\nnow defaults off; enable it and other curated rules from the dashboard.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "config: default to only the Iran-direct rule (torrent_block off)",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T19:00:27Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0e7ddbb77e2f4e82b98b2ac56b08804850fdc34e",
"body": "…y name\n\nSeveral endpoints share a protocol (Reality/CDN/XHTTP are all vless), so the\nbare ID was ambiguous in the logs. Add Endpoint.Label() (\"MoaV-XHTTP-beezhantest2\n(beezhantest2/vless:host:port)\") and use it in the probe + balancer-dial log\nlines so each line identifies which config it's about.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(logs): lead probe/balancer log lines with the endpoint's friendl…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T18:50:17Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "0f7caeeb2b5f88155f47cfc12bc64c83112ef4c9",
"body": "Both ran with no healthcheck, so a misgenerated config or a parse failure\nshowed as a plain \"Up\" rather than unhealthy. Add a config-validity check\n(sing-box check / xray run -test) guarded to stay healthy while an engine is\nlegitimately idling with no config yet.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(compose): healthchecks for sing-box + xray",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T18:40:09Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "268512cd7144dc5ce07367b22325734e6bcfddc8",
"body": "…with the TLS check\n\n- A failing probe with status=error now logs at ERROR level (timeout stays\n warn, ok stays info), so the Debug tab's error filter matches the endpoint's\n \"error\" status and shows the reason in red.\n- Latency is now measured at the SOCKS CONNECT grant (tunnel establishment),\n \n[…]\nhe handshake is kept as a pass/fail\n tunnel-liveness check but no longer ~doubles the reported ping (Reality\n ~1500ms → ~150ms).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(debug,prober): probe errors show as ERROR; don't inflate latency …",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T18:32:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "06fab8e7389b4e964252d26efa53a67cb8bf09fa",
"body": "Two bugs made the Debug tab useless for diagnosing unhealthy endpoints:\n\n1. socksConnect/tcpConnect discarded the dial/handshake error, so a probe\n line only said \"status=error\" with no cause. They now return the error\n and ProbeOne logs it (e.g. \"tunnel TLS handshake: connection reset by\n pee\n[…]\nfore classifying,\n and flag failing per-endpoint probes (status=error/timeout) as warn so\n they surface above the info stream.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(debug): surface probe failure reasons as WARN in the log tail",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T18:23:14Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "3fa6fb84ed3baa9cc76718e69c28c413d8faf835",
"body": "/api/sources marshaled a nil slice as JSON null; the Sources tab then read\n.length on null and crashed to a blank render. Return [] from the API and\nnormalise null→[] in the component so the empty state (upload area + \"no\nsources\" row) shows correctly.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(sources): blank page when no sources are configured",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T18:09:47Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9cb5325156556ac602ad1791b6bff7daeac4624c",
"body": "…p:ir → direct\n\nThe kill-switch now drops only the balancer's involuntary fallback (all\nendpoints down). A deliberate `direct` rule takes priority and is always\nhonored — so geoip:ir→direct and lan-direct keep working with it on. The\ndashboard toggle now names any enabled `direct` rules when the kil\n[…]\nDefault routing rules trimmed to a single `geoip:ir → direct` (Iranian\ndestinations stay domestic); other templates ship disabled.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(plugins): block_direct honors explicit direct rules; default geoi…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T17:30:36Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "bc3e125efb2efe4e66a4b9436b9ed646fc9b1988",
"body": null,
"is_bot": false,
"headline": "docs(changelog): note block-direct dashboard toggle under Unreleased",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T17:21:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "924c15a88d027151c0e916694e1e325371231ff0",
"body": "…able\n\nSurface block_direct in the UI (it was config-only). New GET/PUT\n/api/block-direct applies the flag live to the rule engine + balancer\n(no restart) and persists to config.yaml. A toggle banner sits above the\nEndpoints table, red-accented when active, with a caption noting it also\ndisables direct routing rules like lan-direct.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(dashboard): block-direct kill-switch toggle above the endpoint t…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T17:19:29Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "4eeaf54a88609419f5f02596be5fed04b09cd94e",
"body": null,
"is_bot": false,
"headline": "chore: gitignore .claude agent dir",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T13:37:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b5d25bfc52ee0beadf031ec38d353587be3e08b6",
"body": "Trim README to essentials; drop stale Known Limitations (xray/reality/amneziawg\nfixed) and the verbose download methodology. Move headless install, Psiphon and\nconfig detail into docs/ (INSTALL, SIDECARS). Rename INTERNALS→ARCHITECTURE, add\nTROUBLESHOOTING, refresh SNI_SPOOFING (both upstreams + source of truth +\nneeds-testing). Add screenshot/gif placeholders. Sync README-fa.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: lean README + /docs split, screenshot placeholders, Farsi sync",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T13:37:02Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "138569ed28785f63ef73ef9ffdcb92bb17460b50",
"body": "Bump version 0.1.0 → 1.0.0 and add CHANGELOG with the 1.0.0 release notes.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore(release): v1.0.0",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T13:36:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2f470bbcf487e9f9cf4148e0896bbe7f17cf40a4",
"body": "Symlink the management wrapper into /usr/local/bin (sudo fallback) like moav\ndoes, so it's usable as `moav-client ...` from anywhere. Closing tips use the\nglobal command when available, else ./moav-client.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(install): install moav-client as a global command",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T13:36:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9223282122bc13bd0e4dc2e4defa27abf298994c",
"body": "scripts/update-geoip.sh builds geoip/<cc>.txt from arastu/mikrotik-iran-\naddress-list (auto-aggregated) ∪ RIPE country-resource-list, filtered to valid\nIPv4 CIDRs. geoip/ir.txt ships in-repo (~2.3k CIDRs); the update-geoip Action\nrefreshes weekly.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(geoip): ship Iran CIDR list + weekly CI refresh",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T13:36:50Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "fd516ae880fe5911cb2048916d9f0d7e65443bc6",
"body": "…to-wire on import\n\n- TrustTunnel: pull the upstream prebuilt Linux client (TrustTunnelClient\n v1.0.49, Apache-2.0) and run it in SOCKS5 mode. configgen rewrites the\n bundle's [listener.tun] to a loopback [listener.socks] and socat\n republishes it on :5600 — no TUN/NET_ADMIN. Verified end-to-end \n[…]\nw wires amneziawg + trusttunnel source_path (like masterdns),\n so enabling those sidecars after an import needs no manual config.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(sidecars): integrate TrustTunnel client, fix Tor healthcheck, au…",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-05T13:36:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e106d332ba36b09d11bd4b3a2c04006ce088be3a",
"body": "Add real first-install network download figures, measured as the NIC RX\ndelta during a cold `docker builder prune -af` + full rebuild on Ubuntu\n24.04/amd64 (includes Go/Node/Debian base images, Go module + npm + apt\ndownloads, psiphon/amneziawg git clones, and pulled runtime images):\ncore-only ~190 \n[…]\nack ~810 MB. Clarify that the ~4 GB build\ncache is reclaimable and updates re-download only changed layers. Mirror\ninto README-fa.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: measured install download sizes (per-GB cost)",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-04T18:38:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c3b0286238b2281f11ee189f72576d2b00e13366",
"body": "block_direct (plugins.block_direct, default off): when on, any connection\nthat would go direct — a `direct` routing rule OR the balancer's\nall-endpoints-failed fallback — is dropped instead, so the host never\nmakes an unproxied connection that leaks its real IP. Engine rewrites\nDecisionDirect→Decisi\n[…]\nleak). Verified: a geoip block drops the\nconnection before any dial — the destination never reaches the balancer\nor a direct dial.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(plugins): block_direct kill-switch + make geoip rules actually work",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-04T18:32:16Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "da9781f926f89dff76a707e490386c2f15b47a8d",
"body": "- Resource footprint table now uses measured on-disk sizes (Tor was\n listed 15 MB but is 85 MB; xray 85→104; etc.) with a network column\n and RAM guidance.\n- Fix stale references: Tor is peterdavehello/tor-socks-proxy (not arti),\n analytics chart is overlay (not stacked), Debug uses per-level 800\n[…]\noof, diag, backup, restore,\n version, flows). Add the healthcheck CLI subcommand.\n- Add README-fa.md (Farsi) + language switcher.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: accurate resource table, refresh stale bits, add Farsi README",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-04T18:07:44Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "28b842805d363f4627fa877149fdc0603500c9fc",
"body": "proxy-core is FROM scratch (no wget/sh) so the wget-based healthcheck\nalways failed → container stuck \"unhealthy\" while serving fine. Add a\n`healthcheck` subcommand to the binary that hits its own /api/healthz,\nand point the compose healthcheck at it.\n\nweb-ui healthcheck used localhost:3000, which r\n[…]\nginx listens IPv4-only → connection-refused. Use\n127.0.0.1.\n\nFound while bringing the full sidecar stack up on a fresh Ubuntu box.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(health): working container healthchecks",
"author_name": "Beezhan",
"author_login": "ibeezhan",
"committed_at": "2026-06-04T18:07:33Z",
"body_truncated": true,
"is_coding_agent": true
}
],
"releases_count": 4,
"commits_last_year": 127,
"latest_release_at": "2026-07-13T21:18:20Z",
"latest_release_tag": "v1.3.2",
"releases_from_tags": false,
"days_since_last_push": 4,
"active_weeks_last_year": 8,
"days_since_latest_release": 11,
"mean_days_between_releases": 12.7
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 37,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": []
},
"popularity": {
"forks": 1,
"stars": 6,
"watchers": 1,
"fork_history": {
"days": [
{
"date": "2026-07-16",
"count": 1
}
],
"complete": true,
"collected": 1,
"total_forks": 1
},
"star_history": null,
"open_issues_and_prs": 2
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": true,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"web-ui/tsconfig.json"
],
"toolchain_manifests": [
"proxy-core/go.mod"
],
"largest_source_bytes": 62396,
"source_files_sampled": 81,
"oversized_source_files": 1,
"agent_instruction_files": [
"CLAUDE.md"
],
"agent_instruction_max_bytes": 18574
},
"dependencies": {
"manifests": [
"proxy-core/go.mod",
"web-ui/package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go",
"npm"
],
"dependencies": [
{
"name": "github.com/armon/go-socks5",
"manifest": "proxy-core/go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20160902184237-e75332964ef5"
},
{
"name": "gopkg.in/yaml.v3",
"manifest": "proxy-core/go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "react",
"manifest": "web-ui/package.json",
"ecosystem": "npm",
"version_constraint": "^18.3.1"
},
{
"name": "react-dom",
"manifest": "web-ui/package.json",
"ecosystem": "npm",
"version_constraint": "^18.3.1"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 12,
"open_issues": 2,
"closed_ratio": 0.5,
"closed_issues": 2,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 1,
"top_contributors": [
{
"type": "User",
"login": "ibeezhan",
"commits": 71,
"avatar_url": "https://avatars.githubusercontent.com/u/279766379?v=4"
},
{
"type": "User",
"login": "shayanb",
"commits": 49,
"avatar_url": "https://avatars.githubusercontent.com/u/309108?v=4"
}
],
"contributors_sampled": 2,
"top_contributor_share": 0.592
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"e2e.yml",
"publish-install.yml",
"telegram-notify.yml",
"update-geoip.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum",
"package-lock.json"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 1/13 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 10,
"reason": "project has 12 contributing companies or organizations",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": null,
"reason": "packaging workflow not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 2,
"reason": "8 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "0c24d7c076624f60a176dbbbb55c86c27ab20251",
"ran_at": "2026-07-25T00:36:32Z",
"aggregate_score": 2.9,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": null,
"oldest_open_prs": [],
"last_merged_pr_at": "2026-07-17T17:27:07Z",
"ci_last_conclusion": null,
"oldest_open_issues": [
{
"number": 1,
"created_at": "2026-06-02T22:59:24Z",
"last_comment_at": "2026-07-14T16:40:39Z",
"last_comment_author": "shayanb"
},
{
"number": 2,
"created_at": "2026-06-06T00:43:54Z",
"last_comment_at": null,
"last_comment_author": null
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/MotherofallVPNs/moav-client",
"host": "github.com",
"name": "moav-client",
"owner": "MotherofallVPNs"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"security": 29,
"vitality": 76,
"community": 29,
"governance": 43,
"engineering": 67
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 76,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "moderate",
"name": "Development activity",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"commits_last_year": 127,
"human_commit_share": 0.93,
"days_since_last_push": 4,
"active_weeks_last_year": 8
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 4 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 4
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "8/52 weeks with commits",
"points": 5.5,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 8
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "127 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 127
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 100,
"inputs": {
"releases_count": 4,
"latest_release_tag": "v1.3.2",
"releases_from_tags": false,
"days_since_latest_release": 11,
"mean_days_between_releases": 12.7
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "4 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 4
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 11 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 11
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~12.7 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 12.7
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 29,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 11,
"inputs": {
"forks": 1,
"stars": 6,
"watchers": 1,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "6 stars",
"points": 11.3,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 6
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "1 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 1
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "1 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 1
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "at_risk",
"name": "Sustainability & Governance",
"value": 43,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "at_risk",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 31,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 2,
"top_contributor_share": 0.592
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 59% of commits",
"points": 9.2,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 59
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "2 contributors",
"points": 2.7,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 2
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 12 contributing companies or organizations",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "moderate",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 62,
"inputs": {
"merged_prs": 12,
"open_issues": 2,
"closed_issues": 2,
"issue_closed_ratio": 0.5,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "50% of issues closed",
"points": 23.4,
"status": "partial",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 50
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "12/12 decided PRs merged",
"points": 38.2,
"status": "met",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 12,
"decided": 12
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 1/13 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "at_risk",
"name": "Ownership & stewardship",
"note": null,
"notes": [],
"value": 38,
"inputs": {
"followers": 2,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "MotherofallVPNs",
"public_repos": 3,
"account_age_days": 52
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "organization-owned",
"points": 30,
"status": "met",
"details": [
{
"code": "owner_organization",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "2 followers of MotherofallVPNs",
"points": 3.4,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 2,
"login": "MotherofallVPNs"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "3 public repos, account ~0 yr old",
"points": 4.7,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 3
}
},
{
"code": "account_age_years",
"params": {
"years": 0
}
}
],
"max_points": 25
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 67,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 68,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "5 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 5
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "moderate",
"name": "Documentation",
"note": null,
"notes": [],
"value": 65,
"inputs": {
"topics": [],
"has_wiki": false,
"homepage": null,
"has_readme": true,
"has_docs_dir": true,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "critical",
"name": "Security",
"value": 29,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "critical",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"packaging",
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 29,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 16,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 2,
"scorecard_aggregate": 2.9
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 1/13 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 12 contributing companies or organizations",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "8 existing vulnerabilities detected",
"points": 1.5,
"status": "partial",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 4
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "good",
"name": "AI Readiness",
"value": 79,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "excellent",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.978,
"agent_instruction_files": [
"CLAUDE.md"
],
"agent_instruction_max_bytes": 18574
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "CLAUDE.md",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "CLAUDE.md"
}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "91 of 93 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 91,
"sampled": 93
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "moderate",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 66,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum",
"package-lock.json"
],
"has_dockerfile": true,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [
"web-ui/tsconfig.json"
],
"agent_commit_share": 0.73,
"toolchain_manifests": [
"proxy-core/go.mod"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "proxy-core/go.mod (toolchain convention, no task runner)",
"points": 12.6,
"status": "partial",
"details": [
{
"code": "toolchain_convention",
"params": {
"files": "proxy-core/go.mod"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "web-ui/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "web-ui/tsconfig.json"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "Dockerfile, lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Dockerfile, lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "73 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 73,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 99,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 62396,
"source_files_sampled": 81,
"oversized_source_files": 1
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Go (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "1/81 source files over 60KB",
"points": 54.3,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 81,
"oversized": 1
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"Could not fetch go package 'github.com/ibeezhan/moav-client/proxy-core' from its registry",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-25T00:36:45.728812Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/m/MotherofallVPNs/moav-client.svg",
"full_name": "MotherofallVPNs/moav-client",
"license_state": "standard",
"license_spdx": "MIT"
}