Public record
Software health reportschema 0.27.0 · metrics 1.13.0 · 2026-07-25 00:36 UTC

MotherofallVPNs / moav-client

MoaV client — multi-protocol proxy with load balancing and web dashboard

Go · TypeScript · ShellMIT★ 6 stars⑂ 1 forksince Jun 2026View on GitHub ↗

MotherofallVPNs/moav-client holds a health index of 50 out of 100, placing it in the Moderate band. It scores highest on AI Readiness (79/100) and lowest on Security (29/100). It was last updated 4 days ago. A single contributor accounts for most of its recent work.

50
overall / 100
Moderate

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At risk ceiling of 49. AI Readiness sits outside the overall score.

50
Excellent85-100Exemplary; meets essentially all checked criteria
Good70-84Healthy; minor gaps
Moderate50-69Acceptable with notable gaps; review recommended
At risk30-49Significant weaknesses; adoption warrants caution
Critical1-29Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

Ownership

2 followers3 public repossince Jun 2026

This repository is backed by an organization — shared, accountable stewardship that can outlive any single maintainer.

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

76Good · 22% of overall
How it's scored
36/36Push recency — last push 4 days ago
5.5/36Commit cadence — 8/52 weeks with commits
18/18Commit volume — 127 commits in the last year
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Inputs used
commits_last_year127
human_commit_share0.93
days_since_last_push4
active_weeks_last_year8

Release discipline

100Excellent
How it's scored
27/27Ships releases — 4 releases published
36/36Release recency — latest release 11 days ago
27/27Release cadence — a release every ~12.7 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count4
latest_release_tagv1.3.2
releases_from_tagsno
days_since_latest_release11
mean_days_between_releases12.7
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

29Critical · 18% of overall
How it's scored
11.3/60Stars — 6 stars
0/25Forks — 1 forks
0/15Watchers — 1 watchers
Inputs used
forks1
stars6
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (MIT)
0/18CONTRIBUTING guide
0/13.5Code of conduct
0/7.2Issue template
0/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

43At risk · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
9.2/22.5Commit distribution — top contributor authored 59% of commits
2.7/13.5Contributor breadth — 2 contributors
10/10OpenSSF Scorecard: Contributors — project has 12 contributing companies or organizations
Inputs used
bus_factor1
contributors_sampled2
top_contributor_share0.592
How it's scored
23.4/46.8Issue resolution — 50% of issues closed
38.2/38.3PR acceptance — 12/12 decided PRs merged
0/15OpenSSF Scorecard: Code-Review — Found 1/13 approved changesets -- score normalized to 0
Inputs used
merged_prs12
open_issues2
closed_issues2
issue_closed_ratio0.5
closed_unmerged_prs0
How it's scored
30/30Ownership backing — organization-owned
0/20Verified domain
3.4/25Owner reach — 2 followers of MotherofallVPNs
4.7/25Track record — 3 public repos, account ~0 yr old
Inputs used
followers2
owner_typeOrganization
is_verified
owner_loginMotherofallVPNs
public_repos3
account_age_days52

Engineering Quality

Are baseline engineering and documentation practices in place?

67Moderate · 20% of overall
How it's scored
24/24CI workflows — 5 workflow(s)
24/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configno
has_precommit_configno

Documentation

65Moderate
How it's scored
30/30README
25/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
0/10Topics
0/10Wiki
Inputs used
topics
has_wikino
homepage
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

29Critical · 16% of overall
How it's scored
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 1/13 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 12 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — no data
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — no data
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
1.5/7.5Vulnerabilities — 8 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate2.9
Excluded from scoring (no data or not applicable): packaging, signed_releases. Remaining weights renormalized.

AI Readiness

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.

79Good · 0% of overall
How it's scored
45/45Agent instructions — CLAUDE.md
0/15Machine-readable docs (llms.txt)
40/40Legible commit history — 91 of 93 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share0.978
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes18,574
How it's scored
12.6/18One-command bootstrap — proxy-core/go.mod (toolchain convention, no task runner)
22/22Automated tests
0/11Lint / format config
11/11Static type checking — web-ui/tsconfig.json
10/10Reproducible environment — Dockerfile, lockfile
10/10Demonstrated agent practice — 73 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Inputs used
has_nixno
has_testsyes
lockfilesgo.sum, package-lock.json
has_dockerfileyes
typed_languageyes
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configsweb-ui/tsconfig.json
agent_commit_share0.73
toolchain_manifestsproxy-core/go.mod
dependency_bot_commit_share0
How it's scored
45/45Type-checkable code — Go (statically typed)
54.3/55Manageable file sizes — 1/81 source files over 60KB
Inputs used
primary_languageGo
largest_source_bytes62,396
source_files_sampled81
oversized_source_files1

Key facts

6GitHub stars
2contributors
127commits, last 12 months
4days since last push
4releases
1bus factor
2open issues
Go, npmpackage ecosystems

Data collection 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

More detail

OpenSSF Scorecard 2.9 / 10
2.9aggregate

Independent, tool-agnostic security assessment from the open-source OpenSSF Scorecard. Each check rewards a security practice, not a specific vendor's tool. Checks Scorecard could not determine are marked n/a and excluded from the security score (never counted as zero).Scorecard v5.5.0 · 2026-07-25 00:36 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 1/13 approved changesets -- score normalized to 0
10Contributorsproject has 12 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
n/aPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/aSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
2Vulnerabilities8 existing vulnerabilities detected
Direct dependencies 4
RegistryPackageVersion constraintManifest
Gogithub.com/armon/go-socks5v0.0.0-20160902184237-e75332964ef5proxy-core/go.mod
Gogopkg.in/yaml.v3v3.0.1proxy-core/go.mod
npmreact^18.3.1web-ui/package.json
npmreact-dom^18.3.1web-ui/package.json
All dependencies not collected

The resolved dependency set could not be collected for this report: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Raw JSON report machine-readable
{
  "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"
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v1.13.0, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statistics.