Public record
Software health reportschema 0.27.0 · metrics 1.13.0 · 2026-07-27 09:27 UTC

Art-of-WiFi / UniFi-API-client

A PHP API client class to interact with Ubiquiti's UniFi Controller API

PHPMIT★ 1,340 stars⑂ 242 forkssince Sep 2017View on GitHub ↗

Art-of-WiFi/UniFi-API-client holds a health index of 51 out of 100, placing it in the Moderate band. It scores highest on Vitality (69/100) and lowest on AI Readiness (23/100). It was last updated today. A single contributor accounts for most of its recent work.

51
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.

51
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

Art of WiFiOrganization
121 followers6 public repossince May 2017

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

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publishTags
Packagistart-of-wifi/unifi-api-clientv2.2.07,287109126 days agoapiclientcontrollerunifiubiquitiubntunifi-os

Metrics by category

Vitality

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

69Moderate · 22% of overall
How it's scored
36/36Push recency — last push 0 days ago
9/36Commit cadence — 13/52 weeks with commits
13.6/18Commit volume — 32 commits in the last year
2/10OpenSSF Scorecard: Maintained — 3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2
Inputs used
commits_last_year32
human_commit_share1
days_since_last_push0
active_weeks_last_year13
How it's scored
27/27Ships releases — 100 releases published
27/36Release recency — latest release 126 days ago
19.8/27Release cadence — a release every ~49.4 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count100
latest_release_tagv2.2.0
releases_from_tagsno
days_since_latest_release126
mean_days_between_releases49.4
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?

64Moderate · 18% of overall
How it's scored
50.7/60Stars — 1,340 stars
19.9/25Forks — 242 forks
10/15Watchers — 64 watchers
Inputs used
forks242
stars1,340
watchers64
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
How it's scored
51.5/80Monthly downloads — 7,287 downloads/month across packagist
3.2/20Registry dependents — 2 packages depend on it
Inputs used
packagesart-of-wifi/unifi-api-client
dependents2
ecosystemspackagist
total_downloads422,598
monthly_downloads7,287

Sustainability & Governance

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

60Moderate · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
1.7/22.5Commit distribution — top contributor authored 92% of commits
13.5/13.5Contributor breadth — 11 contributors
6/10OpenSSF Scorecard: Contributors — project has 2 contributing companies or organizations -- score normalized to 6
Inputs used
bus_factor1
contributors_sampled11
top_contributor_share0.925
How it's scored
45.1/46.8Issue resolution — 96% of issues closed
14.3/38.3PR acceptance — 21/56 decided PRs merged
1.5/15OpenSSF Scorecard: Code-Review — Found 3/30 approved changesets -- score normalized to 1
Inputs used
merged_prs21
open_issues6
closed_issues162
issue_closed_ratio0.964
closed_unmerged_prs35
How it's scored
30/30Ownership backing — organization-owned
0/20Verified domain
15/25Owner reach — 121 followers of Art-of-WiFi
18.2/25Track record — 6 public repos, account ~9 yr old
Inputs used
followers121
owner_typeOrganization
is_verified
owner_loginArt-of-WiFi
public_repos6
account_age_days3,347
How it's scored
25/25Published & resolvable — 1 package(s) on packagist
35/35Publish recency — latest publish 126 days ago
20/20Version history — 109 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packagesart-of-wifi/unifi-api-client
ecosystemspackagist
any_deprecatedno
min_days_since_publish126

Engineering Quality

Are baseline engineering and documentation practices in place?

25Critical · 20% of overall
How it's scored
0/24CI workflows
0/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — 0 out of 3 merged PRs checked by a CI test -- score normalized to 0
Inputs used
has_cino
has_testsno
has_editorconfigno
has_linter_configno
has_precommit_configno

Documentation

60Moderate
How it's scored
30/30README
0/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
10/10Topics — 10 topics
10/10Wiki
Inputs used
topicsunifi, ubnt, ubiquiti, api, client, class, php, api-client, controller, curl
has_wikiyes
homepage
has_readmeyes
has_docs_dirno
has_descriptionyes

Security

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

30At risk · 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
0/2.5CI-Tests — 0 out of 3 merged PRs checked by a CI test -- score normalized to 0
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0.8/7.5Code-Review — Found 3/30 approved changesets -- score normalized to 1
1.5/2.5Contributors — project has 2 contributing companies or organizations -- score normalized to 6
0/10Dangerous-Workflow — no data
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
1.5/7.5Maintained — 3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2
0/5Packaging — no data
0/5Pinned-Dependencies — no data
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 — no data
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate3
Excluded from scoring (no data or not applicable): dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. 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.

23Critical · 0% of overall
How it's scored
0/45Agent instructions — no CLAUDE.md / AGENTS.md / editor rules
0/15Machine-readable docs (llms.txt)
14.4/40Legible commit history — 27 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share0.27
agent_instruction_files
agent_instruction_max_bytes
How it's scored
0/18One-command bootstrap
0/22Automated tests
0/11Lint / format config
0/11Static type checking
0/10Reproducible environment
10/10Demonstrated agent practice — 7 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — no data
Inputs used
has_nixno
has_testsno
lockfiles
has_dockerfileno
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0.07
toolchain_manifests
dependency_bot_commit_share0
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.
How it's scored
0/45Type-checkable code — PHP without a type-check config
54/55Manageable file sizes — 1/57 source files over 60KB
Inputs used
primary_languagePHP
largest_source_bytes193,262
source_files_sampled57
oversized_source_files1
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
0/20MCP server
40/40Runnable examples — examples
Inputs used
example_dirsexamples
has_mcp_signalno
api_schema_files

Key facts

1,340GitHub stars
11contributors
32commits, last 12 months
0days since last push
100releases
1bus factor
6open issues
Packagistpackage ecosystems

Data collection warnings

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • No resolved dependencies carried a version and a supported ecosystem

More detail

Star and fork history 0 ★ / 242 ⇿
0Stars
242Forks
100Releases

When each star and fork was added, collected from GitHub and bucketed by day. Cumulative growth sits directly above the daily additions it is made of, so the two read against each other: steady organic accretion looks nothing like an abrupt, short-lived burst. Where that difference is measurable, it is reported as growth authenticity.

05010015020025024242017-092022-012026-06
Major 0Minor 2Patch 98

Each point covers 9 days.

OpenSSF Scorecard 3.0 / 10
3.0aggregate

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-27 09:26 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 3 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
1Code-ReviewFound 3/30 approved changesets -- score normalized to 1
6Contributorsproject has 2 contributing companies or organizations -- score normalized to 6
n/aDangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
2Maintained3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2
n/aPackagingpackaging workflow not detected
n/aPinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/aSigned-Releasesno releases found
n/aToken-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
All dependencies 3

Full resolved dependency set from the GitHub dependency graph: 0 direct and 3 indirect (transitive) packages. The transitive closure is complete when the repository commits a lockfile.

RegistryPackageVersionRelation
Packagistext-curlindirect
Packagistext-jsonindirect
Packagistphpindirect
Dependency advisories not assessed

Advisory matching could not run for this report: No resolved dependencies carried a version and a supported ecosystem

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [
        "unifi",
        "ubnt",
        "ubiquiti",
        "api",
        "client",
        "class",
        "php",
        "api-client",
        "controller",
        "curl"
      ],
      "is_fork": false,
      "size_kb": 520,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "PHP": 202479
      },
      "pushed_at": "2026-07-27T09:18:10Z",
      "created_at": "2017-09-05T09:35:21Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-27T09:19:18Z",
      "description": "A PHP API client class to interact with Ubiquiti's UniFi Controller API",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "PHP",
      "significant_languages": [
        "PHP"
      ]
    },
    "owner": {
      "blog": "http://artofwifi.net",
      "name": "Art of WiFi",
      "type": "Organization",
      "login": "Art-of-WiFi",
      "company": null,
      "location": "the Netherlands",
      "followers": 121,
      "avatar_url": "https://avatars.githubusercontent.com/u/29000406?v=4",
      "created_at": "2017-05-27T12:44:30Z",
      "is_verified": null,
      "public_repos": 6,
      "account_age_days": 3347
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2026-03-22T13:49:49Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2026-03-20T12:23:34Z"
        },
        {
          "tag": "v2.0.11",
          "kind": "patch",
          "published_at": "2025-12-23T13:18:06Z"
        },
        {
          "tag": "v2.0.10",
          "kind": "patch",
          "published_at": "2025-12-04T10:59:14Z"
        },
        {
          "tag": "v2.0.9",
          "kind": "patch",
          "published_at": "2025-11-25T11:47:06Z"
        },
        {
          "tag": "v2.0.8",
          "kind": "patch",
          "published_at": "2025-11-10T11:49:17Z"
        },
        {
          "tag": "v2.0.7",
          "kind": "patch",
          "published_at": "2025-10-21T10:20:17Z"
        },
        {
          "tag": "v2.0.6",
          "kind": "patch",
          "published_at": "2025-10-09T14:06:24Z"
        },
        {
          "tag": "v2.0.5",
          "kind": "patch",
          "published_at": "2025-03-09T11:14:47Z"
        },
        {
          "tag": "v2.0.4",
          "kind": "patch",
          "published_at": "2025-01-02T10:01:42Z"
        },
        {
          "tag": "v1.1.104",
          "kind": "patch",
          "published_at": "2025-01-02T09:56:25Z"
        },
        {
          "tag": "v2.0.3",
          "kind": "patch",
          "published_at": "2024-12-19T10:55:09Z"
        },
        {
          "tag": "v1.1.102",
          "kind": "patch",
          "published_at": "2024-12-19T10:02:05Z"
        },
        {
          "tag": "v2.0.2",
          "kind": "patch",
          "published_at": "2024-11-28T11:15:32Z"
        },
        {
          "tag": "v2.0.1",
          "kind": "patch",
          "published_at": "2024-11-27T15:44:16Z"
        },
        {
          "tag": "v1.1.101",
          "kind": "patch",
          "published_at": "2024-11-15T09:35:35Z"
        },
        {
          "tag": "v1.1.100",
          "kind": "patch",
          "published_at": "2024-10-29T11:17:49Z"
        },
        {
          "tag": "v1.1.99",
          "kind": "patch",
          "published_at": "2024-10-23T11:34:39Z"
        },
        {
          "tag": "v1.1.98",
          "kind": "patch",
          "published_at": "2024-10-17T14:45:16Z"
        },
        {
          "tag": "v1.1.97",
          "kind": "patch",
          "published_at": "2024-10-17T13:05:03Z"
        },
        {
          "tag": "v1.1.96",
          "kind": "patch",
          "published_at": "2024-10-14T12:39:54Z"
        },
        {
          "tag": "v1.1.95",
          "kind": "patch",
          "published_at": "2024-10-07T10:57:24Z"
        },
        {
          "tag": "v1.1.94",
          "kind": "patch",
          "published_at": "2024-08-12T08:25:44Z"
        },
        {
          "tag": "v1.1.93",
          "kind": "patch",
          "published_at": "2024-08-07T14:04:57Z"
        },
        {
          "tag": "v1.1.92",
          "kind": "patch",
          "published_at": "2024-08-06T10:33:36Z"
        },
        {
          "tag": "v1.1.91",
          "kind": "patch",
          "published_at": "2024-07-31T08:57:01Z"
        },
        {
          "tag": "v1.1.90",
          "kind": "patch",
          "published_at": "2024-02-27T17:49:55Z"
        },
        {
          "tag": "v1.1.89",
          "kind": "patch",
          "published_at": "2024-02-11T16:26:31Z"
        },
        {
          "tag": "v1.1.88",
          "kind": "patch",
          "published_at": "2024-02-11T13:47:59Z"
        },
        {
          "tag": "v1.1.87",
          "kind": "patch",
          "published_at": "2024-02-11T11:34:39Z"
        },
        {
          "tag": "v1.1.86",
          "kind": "patch",
          "published_at": "2024-02-10T12:28:09Z"
        },
        {
          "tag": "v1.1.85",
          "kind": "patch",
          "published_at": "2024-02-10T11:16:54Z"
        },
        {
          "tag": "v1.1.84",
          "kind": "patch",
          "published_at": "2024-02-09T17:15:10Z"
        },
        {
          "tag": "v1.1.83",
          "kind": "patch",
          "published_at": "2023-12-18T14:11:30Z"
        },
        {
          "tag": "v1.1.82",
          "kind": "patch",
          "published_at": "2023-12-18T10:44:32Z"
        },
        {
          "tag": "v1.1.81",
          "kind": "patch",
          "published_at": "2023-12-18T10:14:24Z"
        },
        {
          "tag": "v1.1.80",
          "kind": "patch",
          "published_at": "2023-03-28T10:29:58Z"
        },
        {
          "tag": "v1.1.79",
          "kind": "patch",
          "published_at": "2022-03-28T09:59:30Z"
        },
        {
          "tag": "v1.1.78",
          "kind": "patch",
          "published_at": "2022-03-11T12:26:24Z"
        },
        {
          "tag": "v1.1.77",
          "kind": "patch",
          "published_at": "2022-03-11T11:09:53Z"
        },
        {
          "tag": "v1.1.76",
          "kind": "patch",
          "published_at": "2021-12-29T14:04:10Z"
        },
        {
          "tag": "v1.1.75",
          "kind": "patch",
          "published_at": "2021-12-18T11:03:53Z"
        },
        {
          "tag": "v1.1.74",
          "kind": "patch",
          "published_at": "2021-11-08T09:32:22Z"
        },
        {
          "tag": "v1.1.73",
          "kind": "patch",
          "published_at": "2021-10-23T09:16:26Z"
        },
        {
          "tag": "v1.1.72",
          "kind": "patch",
          "published_at": "2021-10-19T08:41:59Z"
        },
        {
          "tag": "v1.1.71",
          "kind": "patch",
          "published_at": "2021-09-29T08:44:46Z"
        },
        {
          "tag": "v1.1.70",
          "kind": "patch",
          "published_at": "2021-03-22T11:00:57Z"
        },
        {
          "tag": "v1.1.69",
          "kind": "patch",
          "published_at": "2021-03-21T15:10:54Z"
        },
        {
          "tag": "v1.1.68",
          "kind": "patch",
          "published_at": "2021-01-24T17:11:01Z"
        },
        {
          "tag": "v1.1.67",
          "kind": "patch",
          "published_at": "2021-01-24T16:59:17Z"
        },
        {
          "tag": "v1.1.66",
          "kind": "patch",
          "published_at": "2021-01-24T13:22:46Z"
        },
        {
          "tag": "v1.1.65",
          "kind": "patch",
          "published_at": "2021-01-23T10:46:16Z"
        },
        {
          "tag": "v1.1.64",
          "kind": "patch",
          "published_at": "2021-01-21T10:02:34Z"
        },
        {
          "tag": "v1.1.63",
          "kind": "patch",
          "published_at": "2021-01-06T16:05:27Z"
        },
        {
          "tag": "v1.1.62",
          "kind": "patch",
          "published_at": "2020-12-10T13:55:21Z"
        },
        {
          "tag": "v1.1.61",
          "kind": "patch",
          "published_at": "2020-11-26T12:22:10Z"
        },
        {
          "tag": "v1.1.60",
          "kind": "patch",
          "published_at": "2020-11-12T10:11:12Z"
        },
        {
          "tag": "v1.1.59",
          "kind": "patch",
          "published_at": "2020-10-26T08:53:58Z"
        },
        {
          "tag": "v1.1.58",
          "kind": "patch",
          "published_at": "2020-10-22T12:26:13Z"
        },
        {
          "tag": "v1.1.57",
          "kind": "patch",
          "published_at": "2020-08-22T15:49:49Z"
        },
        {
          "tag": "v1.1.56",
          "kind": "patch",
          "published_at": "2020-06-13T10:30:58Z"
        },
        {
          "tag": "v1.1.55",
          "kind": "patch",
          "published_at": "2020-06-08T10:55:50Z"
        },
        {
          "tag": "v1.1.54",
          "kind": "patch",
          "published_at": "2020-06-07T12:24:58Z"
        },
        {
          "tag": "v1.1.53",
          "kind": "patch",
          "published_at": "2020-06-07T12:13:37Z"
        },
        {
          "tag": "v1.1.52",
          "kind": "patch",
          "published_at": "2020-04-14T13:02:48Z"
        },
        {
          "tag": "v1.1.51",
          "kind": "patch",
          "published_at": "2020-03-19T15:08:36Z"
        },
        {
          "tag": "v1.1.50",
          "kind": "patch",
          "published_at": "2020-02-22T16:23:23Z"
        },
        {
          "tag": "v1.1.49",
          "kind": "patch",
          "published_at": "2020-02-07T07:30:41Z"
        },
        {
          "tag": "v1.1.48",
          "kind": "patch",
          "published_at": "2020-02-06T10:52:38Z"
        },
        {
          "tag": "v1.1.47",
          "kind": "patch",
          "published_at": "2020-02-06T07:54:46Z"
        },
        {
          "tag": "v1.1.46",
          "kind": "patch",
          "published_at": "2020-01-31T11:16:05Z"
        },
        {
          "tag": "v1.1.45",
          "kind": "patch",
          "published_at": "2020-01-30T09:17:04Z"
        },
        {
          "tag": "v1.1.44",
          "kind": "patch",
          "published_at": "2020-01-27T12:21:48Z"
        },
        {
          "tag": "v1.1.43",
          "kind": "patch",
          "published_at": "2019-12-13T08:17:16Z"
        },
        {
          "tag": "v1.1.42",
          "kind": "patch",
          "published_at": "2019-10-15T12:49:48Z"
        },
        {
          "tag": "v1.1.41",
          "kind": "patch",
          "published_at": "2019-04-29T15:38:40Z"
        },
        {
          "tag": "v1.1.40",
          "kind": "patch",
          "published_at": "2019-01-21T08:43:49Z"
        },
        {
          "tag": "v1.1.39",
          "kind": "patch",
          "published_at": "2019-01-19T14:22:08Z"
        },
        {
          "tag": "v1.1.38",
          "kind": "patch",
          "published_at": "2018-12-14T10:32:35Z"
        },
        {
          "tag": "v1.1.37",
          "kind": "patch",
          "published_at": "2018-11-05T11:19:30Z"
        },
        {
          "tag": "v1.1.36",
          "kind": "patch",
          "published_at": "2018-10-24T07:59:35Z"
        },
        {
          "tag": "v1.1.35",
          "kind": "patch",
          "published_at": "2018-10-20T12:31:39Z"
        },
        {
          "tag": "v1.1.34",
          "kind": "patch",
          "published_at": "2018-10-10T08:16:37Z"
        },
        {
          "tag": "v1.1.33",
          "kind": "patch",
          "published_at": "2018-10-02T10:19:32Z"
        },
        {
          "tag": "v1.1.32",
          "kind": "patch",
          "published_at": "2018-08-28T12:47:45Z"
        },
        {
          "tag": "v1.1.31",
          "kind": "patch",
          "published_at": "2018-08-19T10:21:08Z"
        },
        {
          "tag": "v1.1.30",
          "kind": "patch",
          "published_at": "2018-07-02T13:09:45Z"
        },
        {
          "tag": "v1.1.29",
          "kind": "patch",
          "published_at": "2018-05-21T11:10:18Z"
        },
        {
          "tag": "v1.1.28",
          "kind": "patch",
          "published_at": "2018-04-11T05:53:22Z"
        },
        {
          "tag": "v1.1.27",
          "kind": "patch",
          "published_at": "2018-04-10T13:28:19Z"
        },
        {
          "tag": "v1.1.26",
          "kind": "patch",
          "published_at": "2018-03-30T12:00:38Z"
        },
        {
          "tag": "v1.1.25",
          "kind": "patch",
          "published_at": "2018-03-24T09:51:07Z"
        },
        {
          "tag": "v1.1.24",
          "kind": "patch",
          "published_at": "2018-02-01T16:18:12Z"
        },
        {
          "tag": "v1.1.23",
          "kind": "patch",
          "published_at": "2017-10-26T15:09:58Z"
        },
        {
          "tag": "v1.1.22",
          "kind": "patch",
          "published_at": "2017-10-19T09:56:15Z"
        },
        {
          "tag": "v1.1.21",
          "kind": "patch",
          "published_at": "2017-10-19T09:23:36Z"
        },
        {
          "tag": "v1.1.20",
          "kind": "patch",
          "published_at": "2017-10-18T07:06:58Z"
        },
        {
          "tag": "v1.1.19",
          "kind": "patch",
          "published_at": "2017-10-18T06:29:04Z"
        },
        {
          "tag": "v1.1.18",
          "kind": "patch",
          "published_at": "2017-10-12T15:24:26Z"
        },
        {
          "tag": "v1.1.17",
          "kind": "patch",
          "published_at": "2017-10-10T07:41:57Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "c5ab0a43edf1e82e9014821c1fd0b2c3838d9952",
          "body": "README:\n- the Authentication intro still said \"two authentication methods\" after the\n  Site Manager Proxy option was added in 2.2.0; corrected to three\n- repaired a garbled sentence in the UniFi OS Support section that was missing\n  a clause when describing ports 443 vs 8443\n- documented the ext-jso\n[…]\nbdirectory,\n  neither of which was ignored, so real controller credentials could be staged\n  for commit. Both paths are now ignored.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: correct README inaccuracies, fix author email, close gitignore gap",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-07-27T09:17:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a525e236b3ed1dd5735a49f4ebb4b401ff153621",
          "body": "The /stat/report/{interval}.ap endpoints silently cap their response at 10\naccess points when no AP filter is supplied, which is easily mistaken for\npagination or truncation. Which APs get dropped varies per interval.\n\nThe $mac parameter of stat_5minutes_aps(), stat_hourly_aps(), stat_daily_aps()\nan\n[…]\n not affect the .user or .site interval reports\nor stat_sites(), so those methods are left unchanged.\n\nBumps CLASS_VERSION to 2.2.1.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: work around controller 10-AP limit in stat_*_aps() methods",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-07-27T08:29:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "20e85ab166f646dcb39912452568644df4aac5b9",
          "body": "…ocblock",
          "is_bot": false,
          "headline": "added more supported attributes for the `stat_*_aps` methods to the d…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-06-08T10:19:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc0deabd20bef0e9b7725e6412455dcab0386a10",
          "body": "…2.0)\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge feature/site-manager-proxy: Add Site Manager proxy support (v2.…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-03-22T13:45:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "664e232951062506c538680296120a8cb9382745",
          "body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump version to 2.2.0 for Site Manager proxy feature",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-03-22T11:41:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "202696570768f2880560c0cffd08c8ba0c5b21fb",
          "body": "…i.com\n\nEnables managing remote UniFi OS consoles via the Ubiquiti Site Manager cloud\nproxy when no direct network path exists. Adds connect_via_site_manager() factory,\nenable/disable methods, ConsoleOfflineException for HTTP 408, SSL enforcement for\nproxy requests, and updated documentation.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add Site Manager proxy support for routing API requests through api.u…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-03-22T11:37:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0c6b1492ce4723a9152c44ead813d02087cb8bf5",
          "body": "- Add comprehensive Authentication section to README with API key and\n  username/password options, migration guide, and UniFi Fabric requirement\n- Improve api_key_auth.php example with exception handling\n- Update examples/README.md with authentication guidance\n- Improve config.template.php comments for API key usage\n- Bump version to 2.1.0\n- Add .claude/ to .gitignore\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "API client class v2.1.0 - Add API key authentication support",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-03-20T12:19:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "50befd0491e3d9d597d4359ff3c5bca2e8d6e400",
          "body": "API keys provide stateless authentication via X-API-KEY header,\nremoving the need for login/logout flows on UniFi OS-based consoles.\n\n- Add set_api_key(), get_api_key() and is_api_key_mode() methods\n- Skip CSRF token and cookie logic in API key mode\n- Return 401 errors immediately without re-login a\n[…]\n to config.template.php\n- Add examples/api_key_auth.php example\n- Update README.md and API_REFERENCE.md with API key documentation\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add API key authentication support for UniFi OS controllers",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2026-03-20T12:19:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "acc783520f4876f92d8ca8ba5425fb4e0dcf2c21",
          "body": null,
          "is_bot": false,
          "headline": "Add reboot_os_console method (#286)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2026-01-20T23:27:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e95961834b189ae12f7ef4b0ac7182ae1a07e2b5",
          "body": null,
          "is_bot": false,
          "headline": "applied tweak to wording in README",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-23T13:22:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6f8d90b4f000b1ef8ee3aa2815ebf06bf42bf1ad",
          "body": null,
          "is_bot": false,
          "headline": "Stop tracking TODO.md",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-23T13:15:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a9de7cb47287c8cc2589cdfbcfa3d07a857e3e1",
          "body": "- merged PR #284, contributed by @Jacobtims",
          "is_bot": false,
          "headline": "- API client class v2.0.11",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-23T13:12:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c1e398118dc07ba0391d88864bd9c9f8b985db94",
          "body": null,
          "is_bot": false,
          "headline": "Allow disabling prefix_path on custom_api_request method (#284)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2025-12-23T12:01:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "766eac594444078ec83f070b145ab6f99c83f29a",
          "body": "…old versions",
          "is_bot": false,
          "headline": "cleanup of docblocks to compact lines and to remove notes related to …",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-11T13:22:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0df4db012d3d3a2a116890860021282c1c87a2c",
          "body": null,
          "is_bot": false,
          "headline": "bumped version to 2.0.10",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-04T10:57:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0981857a39b0aea4566657af41895d1b78ab5b52",
          "body": "…dpo007\n\nminor code style tweaks, , contributed by @dpo007",
          "is_bot": false,
          "headline": "Fix deprecated nullable parameter in update_admin(), contributed by @…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-04T10:52:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f2050c1e00be66c484511d6f4c7b8e4c12b81d79",
          "body": null,
          "is_bot": false,
          "headline": "updated .gitignore",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-01T11:29:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "02c095329481844a1b14bc1c9831784464a4bbf8",
          "body": null,
          "is_bot": false,
          "headline": "updated API_REFERENCE.md to cover all public methods",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-01T11:01:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e9bdb783c93d9ce8a81656bfdf63a6bc7725a92e",
          "body": null,
          "is_bot": false,
          "headline": "applied tweaks to the the README file",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-12-01T10:39:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d240294cee97e8c16857023e482a0780752f40ee",
          "body": "- merged PR #282 to handle deprecated `curl_close()` function in PHP >8.5, contributed by @dream-rhythm",
          "is_bot": false,
          "headline": "- bumped version to v2.0.9",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-11-25T11:45:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba7e10f1c012de55d1e52b70038ec343622dddb4",
          "body": "Co-authored-by: Nick.Chen <nick.chen@dediprog.com>",
          "is_bot": false,
          "headline": "Fix curl_close() has a deprecated warning when using PHP 8.5 (#282)",
          "author_name": "陳琮斌",
          "author_login": "dream-rhythm",
          "committed_at": "2025-11-25T11:39:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "465c223c1527023fd8f191525fab3c0ce7719637",
          "body": null,
          "is_bot": false,
          "headline": "improved wording around UniFi OS support in the README",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-11-19T10:26:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6995d104190a1c3b94c454dcbdf29aafc2ca2f9a",
          "body": null,
          "is_bot": false,
          "headline": "added a \"Why use this API client?\" section to the README",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-11-19T10:07:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe4c18c53e3a9c5f967b82d25c15953f8a8a73a5",
          "body": "updated README with supported versions\nupdated README wording to improve readability",
          "is_bot": false,
          "headline": "updated docblocks for improved IDE hints",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-11-19T09:41:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "05cb58b9f18deb584e1363479364c7e67dc71b6a",
          "body": null,
          "is_bot": false,
          "headline": "updated link to point to new thread on the Ubiquiti community forum",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-11-11T08:45:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf354b1d6657858e00a31e943308ecf0b4a1b46f",
          "body": "- all Exceptions now extend the `\\UniFi_API\\Exceptions\\UnifiApiException` class so you can catch a single type when you want to handle all client errors uniformly. Suggested by @Jacobtims\n- updated README with supported versions and to cover the above changes\n- added docblocks to Exception classes\n- added methods to several Exception classes to retrieve more information when needed",
          "is_bot": false,
          "headline": "- bumped version to 2.0.8",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-11-10T11:44:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aca184263d948ed78b14494829c2223e9e721c03",
          "body": null,
          "is_bot": false,
          "headline": "updated tested version numbers",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-10-21T10:29:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a9ddf16fc9cbd6fb04baba437888ec4740dd5adf",
          "body": "- added the `list_models()` method to fetch UniFi device models",
          "is_bot": false,
          "headline": "- bumped version to v2.0.7",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-10-21T10:18:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b1e99f8747897fbdbe8d0b8f915535f58e3e2290",
          "body": "…dation",
          "is_bot": false,
          "headline": "refactored code to remove redundant logic related to the new MAC vali…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-10-09T15:56:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec86db23e1a6991bc118cc298ad47176089e0a5e",
          "body": "…essInvalidException",
          "is_bot": false,
          "headline": "added two new Exception classes: MacAddressEmptyException and MacAddr…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-10-09T14:00:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "272e8f65b2d3cca6295226621a40e1b1afb9811b",
          "body": null,
          "is_bot": false,
          "headline": "further changes to the README, added HostiFi",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-10-01T10:35:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25a12021e28e01ddb4a66639b8a2b7694f9e30b1",
          "body": null,
          "is_bot": false,
          "headline": "updated README for UniFi OS Server support",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-10-01T10:28:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa11f99d9dcf9b00dc843e5deaf18f6b065e2344",
          "body": null,
          "is_bot": false,
          "headline": "added short paragraph on Art of WiFi",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-08-27T09:40:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f5950504e8fb02160f7aa5d673e001ff37bdbde2",
          "body": "updated README to reflect support for UniFi OS Server",
          "is_bot": false,
          "headline": "updated API reference to fix incorrect function name",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-08-27T09:31:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ed2ceec9c4c1335ee1339681f656e59c9f9d83ad",
          "body": null,
          "is_bot": false,
          "headline": "added example for PPSKs",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-06-11T12:11:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b5992979c43236e2308fd7d0ee133b9bc167061",
          "body": "* Add is_super to update_admin method\n\n* Add grant_super_admin method",
          "is_bot": false,
          "headline": "Add grant_super_admin method (#272)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2025-06-11T12:09:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2cc60dbc3c3b3dcce43e975132de8bdfec794e98",
          "body": null,
          "is_bot": false,
          "headline": "- minor changes to apply consistent formatting/case",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-03-09T11:12:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e99b7b9a0e02b504b5ecca2a9a65689faa549f5",
          "body": "merging PRs",
          "is_bot": false,
          "headline": "Merge branch 'main' of github.com:Art-of-WiFi/UniFi-API-client into main",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-03-07T16:47:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23b931a6635a281a3dcb03e66deb2955b5cc9a4f",
          "body": "minor tweaks\nadded methods to handle DNS Records",
          "is_bot": false,
          "headline": "added an API reference document",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-03-07T16:45:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee0bfe430b2f4c9dac77f58b9d019da219ae4e94",
          "body": "* Add list active devices endpoint\n\n* Add list clients history endpoint\n\n* Add OS console update endpoints",
          "is_bot": false,
          "headline": "UniFi OS updates (#267)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2025-03-04T13:14:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "73ae5a46302b55065ed3bfcec6e4339fab2cb888",
          "body": null,
          "is_bot": false,
          "headline": "minor formatting change",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-03-03T13:23:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "13cb313cd994624b2b9a9d01321d6d2061044b61",
          "body": "* Add list active devices endpoint\n\n* Add list clients history endpoint",
          "is_bot": false,
          "headline": "Client devices history (#266)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2025-03-03T13:14:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d363deb18d860a5981e53df854dad1d5d7d8961",
          "body": null,
          "is_bot": false,
          "headline": "added code examples demonstrating how to work with PPSKs",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-03-03T13:06:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f343d3ccc41c473b1b3ac3cfb2d02411873fea7d",
          "body": null,
          "is_bot": false,
          "headline": "changed install instructions to only use composer",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-03T12:39:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f34cbd675b2f0c63290d64b72f6d814ddeee4110",
          "body": null,
          "is_bot": false,
          "headline": "further clarifications on the availability of versions 1.x.x",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-03T12:34:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64dcf6e4ad2855e0bc5ae0b0a8921f1d6e6dc2b3",
          "body": null,
          "is_bot": false,
          "headline": "added note on branch version_1",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-03T12:30:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d48e57c06cac037c974f00ba50a4169aa63356d",
          "body": "merging branch version_2 into main",
          "is_bot": false,
          "headline": "Merge branch 'version_2' into main",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-03T12:16:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f9ce6bf54fc01504de1afa041a143993b2de9cf4",
          "body": "…by @Kyouma54 in PR #251)\n\nbumped version to 2.0.4",
          "is_bot": false,
          "headline": "added curl option to specifically support http (originally suggested …",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-02T09:59:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "11c132b2634f9f534d607d438f2a769fa30fe287",
          "body": null,
          "is_bot": false,
          "headline": "bumped version to 1.1.104",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-02T09:54:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a64a0c844bd8cba37a728f6fa835accc85c6768",
          "body": "…by @Kyouma54 in PR #251)",
          "is_bot": false,
          "headline": "added curl option to specifically support http (originally suggested …",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2025-01-02T09:47:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "898703db5c40785563d375a3f484ce17a5d43894",
          "body": null,
          "is_bot": false,
          "headline": "further tweaks to README",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T11:17:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "551c1c3741b9495bb0b186658ffb438ee0643ceb",
          "body": null,
          "is_bot": false,
          "headline": "further tweaks",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T11:15:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a2bfd29590ad79719c614e5192c68f52946c1dce",
          "body": null,
          "is_bot": false,
          "headline": "tweaks to table",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T11:14:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "146495d4a1afd37a2c71b9eca45ee1dee91700fd",
          "body": null,
          "is_bot": false,
          "headline": "added note re support for versions 9.X",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T11:12:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1aa895644538c15068b7985d63ba6e13f89b6a94",
          "body": null,
          "is_bot": false,
          "headline": "added note re support for version 9.X",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T11:11:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "77c4b1700368cf8a22e8a55cc8c2d19ae612d846",
          "body": null,
          "is_bot": false,
          "headline": "added shields to README",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T11:05:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a5ca53a5b8a7e5202385258f6d590773a7cd40cf",
          "body": null,
          "is_bot": false,
          "headline": "- applied changes from PR #258, contributed by @mvarian",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T10:52:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "089b0b77aec2db835ec07713a48d56ef33bc763e",
          "body": null,
          "is_bot": false,
          "headline": "bumped version for next release",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T10:15:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0263c47be9fb71b6a34c017795806a404731247b",
          "body": null,
          "is_bot": false,
          "headline": "minor changes",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T10:13:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d722d7b8439d45f6f9fcb27d9895c346bd1a3c90",
          "body": null,
          "is_bot": false,
          "headline": "completed merge of #258, contributed by @mvarian",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T09:55:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3cf7b4d173767240efe934e316159e806e583e5b",
          "body": "merge #258 and review",
          "is_bot": false,
          "headline": "Merge branch 'main' of github.com:Art-of-WiFi/UniFi-API-client into main",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-12-19T09:39:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b230753a0d5960fa9f072bd418d430de43b48c4",
          "body": "Merge #258",
          "is_bot": false,
          "headline": "Fix for implicit null declarations resulting in PHP 8.4+ warnings (#258)",
          "author_name": "Michael Varian",
          "author_login": "mvarian",
          "committed_at": "2024-12-19T09:39:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "19dc76ddfb03e34f69ad882af53bf9825c6434cb",
          "body": null,
          "is_bot": false,
          "headline": "consistent use of \"PHP DocBlocks\"",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-28T11:24:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a1d1ff0cd0edefe0b4e01306d1d77c584959836",
          "body": null,
          "is_bot": false,
          "headline": "minor tweak to example",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-28T11:21:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8eeeb447c9207d16459fd469ebc4d69f92c09672",
          "body": null,
          "is_bot": false,
          "headline": "reformatted Exception handling example",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-28T11:19:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8acaa694cadd505c3272bcf1469118ad0f7d52e6",
          "body": "- updated @throws tags in the doc blocks to reflect the correct exception classes where necessary, in other cases \"Exception\" is mentioned\n- minor changes\n- bumped version to 2.0.2",
          "is_bot": false,
          "headline": "- updated the README file",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-28T11:11:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d81a3712394ce5bc4b9ce6944a8a2ccf9ff5a202",
          "body": "…` example",
          "is_bot": false,
          "headline": "further improvements to the `README.md` file and the `list_alarms.php…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-26T11:04:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a47bda1c01746781c8a4c72ce8b73f07b05e647",
          "body": null,
          "is_bot": false,
          "headline": "updates to `README.md` to explain how to get older 1.x versions.",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-26T10:53:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb493f4dc8415dede591f59795cfca2845a4f629",
          "body": "…s imports",
          "is_bot": false,
          "headline": "updated the PHP example in the README to include the Exception classe…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-26T10:27:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f19891d904c9cade2e1a933d959470bb9cf9236",
          "body": "updated the `examples/list_alarms.php` file to demonstrate Exception handling",
          "is_bot": false,
          "headline": "updated the README file",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-25T16:56:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a2432f067c46f8169ce92f27fb1117f9bd5bdf8",
          "body": "implement Exceptions in the main class",
          "is_bot": false,
          "headline": "added Exception classes",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-25T16:34:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "97510ec5ec03045123f276b77ddcd4a70c1e9239",
          "body": null,
          "is_bot": false,
          "headline": "prepared new version number",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-24T10:58:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9726378e3c47bb27e2164458cda6e616681d3d1e",
          "body": null,
          "is_bot": false,
          "headline": "bumped version to 1.1.101",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-15T09:33:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "494375f8b5b8e9e6cd05cd2ee7dc68d51c0d7458",
          "body": "… when the cookies were created/updated.\n\n- added a getter method get_cookies_created_at() to return the timestamp when the cookies were created/updated.\n  This information can be useful to determine how old the cookies are.\n- minor comments clean up",
          "is_bot": false,
          "headline": "- added a private property $cookies_created_at to store the timestamp…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-15T09:31:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3dbc24daca5d3885d997b576a281a1e520fac4fc",
          "body": null,
          "is_bot": false,
          "headline": "further tweaks",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-04T12:43:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "93d1d8ec3f58bf17ff6bbc4b5cc7988505e0cd05",
          "body": null,
          "is_bot": false,
          "headline": "tweaked hyperlink",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-04T12:38:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8620f7672a9593046d6af776d53b4777971dd2c",
          "body": null,
          "is_bot": false,
          "headline": "changed link to hyperlink",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-04T12:37:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1e2e709d4aa4f66a4b78c3466990f7f384256d55",
          "body": null,
          "is_bot": false,
          "headline": "inserted link to installation instructions",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-04T12:34:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "472d2eaa687f16bce7c8dcbf522dc0d95ac7405d",
          "body": null,
          "is_bot": false,
          "headline": "restructured and updated supported versions info",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-11-04T12:32:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1522992e495f94b9fa52ff1015fe1e99f9a24fe4",
          "body": "fixed incorrect return type for `create_voucher()`, reported by @pa-",
          "is_bot": false,
          "headline": "bumped version to 1.1.100",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-29T11:14:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70f6a374e2c73eb91a9aa20f6c9375b235d55ce1",
          "body": "…urns pages results\n\n- minor formatting changes",
          "is_bot": false,
          "headline": "- added get_system_log() method to get data from the system logs, ret…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-23T11:30:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff9e6f022528fad5be9b3a8f2d57b4a1af7fa6c5",
          "body": "…d, contributed by @Jacobtims\n\nminor additional change to allow changes to the payload of the `start_rolling_upgrade()` method",
          "is_bot": false,
          "headline": "merged #244 for a small change to the `start_rolling_upgrade()` metho…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-17T14:41:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "00a637dbc4c929997871701a7573f3f1a75ee7e0",
          "body": "* Fix payload start_rolling_upgrade method\r\n\r\n* Add \"uxg\" to start_rolling_upgrade payload",
          "is_bot": false,
          "headline": "Add \"uxg\" to start_rolling_upgrade payload (#244)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2024-10-17T14:31:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6498b0255b0963ad914076ddda7f74df4fd2eb73",
          "body": "merging #243",
          "is_bot": false,
          "headline": "Merge branch 'master' of github.com:Art-of-WiFi/UniFi-API-client",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-17T12:56:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "05e791bcf0d75a7bfd02d266f40e655bccacde6f",
          "body": null,
          "is_bot": false,
          "headline": "minor changes",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-17T12:56:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "192a1262c3777af13d0180486e9a6cf794ac00b5",
          "body": null,
          "is_bot": false,
          "headline": "Fix payload start_rolling_upgrade method (#243)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2024-10-17T12:55:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30056f50fcac4cb3a0860edd72b9e5847a399264",
          "body": "- removed @version tag in docblock as it contained redundant information\n- merged #241 which adds a method to download a generated backup, (contributed by @Jacobtims)",
          "is_bot": false,
          "headline": "- bumped version to 1.1.96",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-14T12:34:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d040c512a790c69237e41cb722447ff5808ed9c0",
          "body": "Merged PR #241",
          "is_bot": false,
          "headline": "Add method to download generated backup (#241)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2024-10-14T12:31:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b633fa54c738b7cfac5ca27b8126161eac5f8e5b",
          "body": "general minor clean up\nbumped version to 1.1.95",
          "is_bot": false,
          "headline": "added ability top determine attributes to fetch with AP and site stats",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-07T10:54:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5327d0c5348a9f096a46226432c3bd2e6d3ab3dd",
          "body": null,
          "is_bot": false,
          "headline": "minor changes",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-10-07T08:39:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1fc80f34f959ada22f2fe22bae45889736188af",
          "body": "- minor fix based on Scrutinizer feedback\n- re-added `update_admin()` method to the class; for some reason, the merge of #228 was not successful",
          "is_bot": false,
          "headline": "API client class v1.1.94",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-12T08:24:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f82d1a6b6442b6d52130ef4f3741e12667f424e8",
          "body": null,
          "is_bot": false,
          "headline": "removed exit following suggestion from Scrutinizer",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-08T15:56:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6f6e80e86229401f4556bef6409f8f2afbf60141",
          "body": null,
          "is_bot": false,
          "headline": "cleanup some comments/doc blocks",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-08T15:45:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4fefc11761654fd2d1e8a0b584bc33a302a30c08",
          "body": "…ithin the argument list",
          "is_bot": false,
          "headline": "simplified the contructor by assigning default values to properties w…",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-08T15:37:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0db5effe6f62f434d009967ca10337b74efaf43e",
          "body": null,
          "is_bot": false,
          "headline": "minor fix to return type hinting based on feedback from Scrutinizer",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-07T14:26:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fd69d844a668310e0f97605dbda32011a918cdad",
          "body": "- added the migrate_device() method to migrate one or more devices from one controller to another\n- added the cancel_migrate_device() method to cancel the migration for one or more devices\n- added the upgrade_all_devices() method to upgrade all devices of a selected type to the latest firmware versi\n[…]\nhanged the force_provision() method to allow for multiple MAC addresses to be passed as a parameter\n- minor changes to a number of doc-blocks\n- general changes for improved consistency and readability",
          "is_bot": false,
          "headline": "API client class v1.1.93",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-07T14:03:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "12b85ce9db041892c9054e5c232e67bb4eb7f193",
          "body": "reformatted single-line comments",
          "is_bot": false,
          "headline": "moved 2 properties to constants which seems more appropriate",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-06T10:30:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "54ec631d4bc183ea9c78d60334ca3b8bc616f90d",
          "body": null,
          "is_bot": false,
          "headline": "added a new example demonstrating the change of site settings",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-08-04T13:35:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fdea77fce0291d8c24a0fcf4dd353d81e5a5b790",
          "body": null,
          "is_bot": false,
          "headline": "Add days paramater to generate_backup method (#232)",
          "author_name": "Jacob Timmerman",
          "author_login": "Jacobtims",
          "committed_at": "2024-08-02T15:12:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "108ddd39954cc004ff919eae37d384c516f11ba6",
          "body": null,
          "is_bot": false,
          "headline": "further cleanup of notes in doc blocks",
          "author_name": "malle-pietje",
          "author_login": "malle-pietje",
          "committed_at": "2024-07-31T09:16:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 32,
      "latest_release_at": "2026-03-22T13:49:49Z",
      "latest_release_tag": "v2.2.0",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 13,
      "days_since_latest_release": 126,
      "mean_days_between_releases": 49.4
    },
    "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": [
        {
          "name": "art-of-wifi/unifi-api-client",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "api",
            "client",
            "controller",
            "unifi",
            "ubiquiti",
            "UBNT",
            "unifi os"
          ],
          "ecosystem": "packagist",
          "matches_repo": true,
          "registry_url": "https://packagist.org/packages/art-of-wifi/unifi-api-client",
          "is_deprecated": false,
          "latest_version": "v2.2.0",
          "repository_url": "https://github.com/Art-of-WiFi/UniFi-API-client",
          "versions_count": 109,
          "total_downloads": 422598,
          "dependents_count": 2,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 7287,
          "first_published_at": null,
          "latest_published_at": "2026-03-22T13:45:58Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 126
        }
      ]
    },
    "popularity": {
      "forks": 242,
      "stars": 1340,
      "watchers": 64,
      "fork_history": {
        "days": [
          {
            "date": "2017-09-05",
            "count": 1
          },
          {
            "date": "2017-09-07",
            "count": 1
          },
          {
            "date": "2017-10-14",
            "count": 1
          },
          {
            "date": "2017-11-17",
            "count": 1
          },
          {
            "date": "2017-11-24",
            "count": 1
          },
          {
            "date": "2017-11-28",
            "count": 1
          },
          {
            "date": "2017-12-07",
            "count": 1
          },
          {
            "date": "2018-01-02",
            "count": 1
          },
          {
            "date": "2018-02-20",
            "count": 1
          },
          {
            "date": "2018-02-22",
            "count": 1
          },
          {
            "date": "2018-03-09",
            "count": 2
          },
          {
            "date": "2018-03-12",
            "count": 1
          },
          {
            "date": "2018-03-17",
            "count": 1
          },
          {
            "date": "2018-03-27",
            "count": 1
          },
          {
            "date": "2018-05-07",
            "count": 1
          },
          {
            "date": "2018-05-23",
            "count": 1
          },
          {
            "date": "2018-06-08",
            "count": 1
          },
          {
            "date": "2018-07-11",
            "count": 1
          },
          {
            "date": "2018-08-04",
            "count": 1
          },
          {
            "date": "2018-08-07",
            "count": 1
          },
          {
            "date": "2018-08-27",
            "count": 1
          },
          {
            "date": "2018-09-22",
            "count": 1
          },
          {
            "date": "2018-09-28",
            "count": 1
          },
          {
            "date": "2018-10-01",
            "count": 1
          },
          {
            "date": "2018-10-12",
            "count": 1
          },
          {
            "date": "2018-10-23",
            "count": 1
          },
          {
            "date": "2018-11-20",
            "count": 1
          },
          {
            "date": "2018-12-05",
            "count": 1
          },
          {
            "date": "2018-12-13",
            "count": 1
          },
          {
            "date": "2018-12-24",
            "count": 1
          },
          {
            "date": "2019-01-05",
            "count": 1
          },
          {
            "date": "2019-01-16",
            "count": 1
          },
          {
            "date": "2019-01-30",
            "count": 1
          },
          {
            "date": "2019-02-02",
            "count": 1
          },
          {
            "date": "2019-03-07",
            "count": 1
          },
          {
            "date": "2019-03-08",
            "count": 1
          },
          {
            "date": "2019-03-17",
            "count": 1
          },
          {
            "date": "2019-03-24",
            "count": 1
          },
          {
            "date": "2019-04-01",
            "count": 1
          },
          {
            "date": "2019-04-29",
            "count": 1
          },
          {
            "date": "2019-05-12",
            "count": 2
          },
          {
            "date": "2019-05-30",
            "count": 1
          },
          {
            "date": "2019-06-05",
            "count": 1
          },
          {
            "date": "2019-06-07",
            "count": 1
          },
          {
            "date": "2019-06-23",
            "count": 1
          },
          {
            "date": "2019-08-18",
            "count": 1
          },
          {
            "date": "2019-08-29",
            "count": 1
          },
          {
            "date": "2019-09-10",
            "count": 1
          },
          {
            "date": "2019-09-13",
            "count": 1
          },
          {
            "date": "2019-09-15",
            "count": 1
          },
          {
            "date": "2019-09-18",
            "count": 1
          },
          {
            "date": "2019-09-20",
            "count": 1
          },
          {
            "date": "2019-10-01",
            "count": 1
          },
          {
            "date": "2019-10-08",
            "count": 1
          },
          {
            "date": "2019-10-28",
            "count": 1
          },
          {
            "date": "2019-11-19",
            "count": 1
          },
          {
            "date": "2019-11-21",
            "count": 1
          },
          {
            "date": "2019-12-30",
            "count": 1
          },
          {
            "date": "2020-01-07",
            "count": 1
          },
          {
            "date": "2020-01-24",
            "count": 1
          },
          {
            "date": "2020-01-31",
            "count": 1
          },
          {
            "date": "2020-02-05",
            "count": 1
          },
          {
            "date": "2020-02-07",
            "count": 1
          },
          {
            "date": "2020-03-02",
            "count": 1
          },
          {
            "date": "2020-03-10",
            "count": 1
          },
          {
            "date": "2020-03-20",
            "count": 1
          },
          {
            "date": "2020-03-22",
            "count": 1
          },
          {
            "date": "2020-04-02",
            "count": 1
          },
          {
            "date": "2020-04-16",
            "count": 1
          },
          {
            "date": "2020-04-19",
            "count": 1
          },
          {
            "date": "2020-05-13",
            "count": 1
          },
          {
            "date": "2020-05-27",
            "count": 1
          },
          {
            "date": "2020-06-20",
            "count": 1
          },
          {
            "date": "2020-06-23",
            "count": 1
          },
          {
            "date": "2020-06-24",
            "count": 1
          },
          {
            "date": "2020-06-29",
            "count": 1
          },
          {
            "date": "2020-06-30",
            "count": 1
          },
          {
            "date": "2020-07-07",
            "count": 1
          },
          {
            "date": "2020-07-16",
            "count": 1
          },
          {
            "date": "2020-07-30",
            "count": 1
          },
          {
            "date": "2020-07-31",
            "count": 1
          },
          {
            "date": "2020-08-14",
            "count": 1
          },
          {
            "date": "2020-08-29",
            "count": 1
          },
          {
            "date": "2020-09-23",
            "count": 2
          },
          {
            "date": "2020-10-03",
            "count": 1
          },
          {
            "date": "2020-10-12",
            "count": 1
          },
          {
            "date": "2020-10-14",
            "count": 1
          },
          {
            "date": "2020-10-23",
            "count": 1
          },
          {
            "date": "2020-11-12",
            "count": 1
          },
          {
            "date": "2020-11-20",
            "count": 1
          },
          {
            "date": "2020-11-24",
            "count": 1
          },
          {
            "date": "2020-12-01",
            "count": 1
          },
          {
            "date": "2020-12-16",
            "count": 1
          },
          {
            "date": "2021-01-06",
            "count": 1
          },
          {
            "date": "2021-01-09",
            "count": 1
          },
          {
            "date": "2021-01-24",
            "count": 1
          },
          {
            "date": "2021-01-25",
            "count": 1
          },
          {
            "date": "2021-01-27",
            "count": 1
          },
          {
            "date": "2021-01-28",
            "count": 1
          },
          {
            "date": "2021-01-31",
            "count": 1
          },
          {
            "date": "2021-02-03",
            "count": 1
          },
          {
            "date": "2021-03-17",
            "count": 1
          },
          {
            "date": "2021-03-22",
            "count": 1
          },
          {
            "date": "2021-03-24",
            "count": 1
          },
          {
            "date": "2021-03-28",
            "count": 1
          },
          {
            "date": "2021-03-30",
            "count": 1
          },
          {
            "date": "2021-04-07",
            "count": 1
          },
          {
            "date": "2021-04-17",
            "count": 1
          },
          {
            "date": "2021-04-26",
            "count": 1
          },
          {
            "date": "2021-05-08",
            "count": 1
          },
          {
            "date": "2021-05-29",
            "count": 1
          },
          {
            "date": "2021-06-02",
            "count": 1
          },
          {
            "date": "2021-06-28",
            "count": 1
          },
          {
            "date": "2021-07-09",
            "count": 1
          },
          {
            "date": "2021-08-03",
            "count": 1
          },
          {
            "date": "2021-08-16",
            "count": 2
          },
          {
            "date": "2021-09-21",
            "count": 1
          },
          {
            "date": "2021-09-24",
            "count": 1
          },
          {
            "date": "2021-09-29",
            "count": 1
          },
          {
            "date": "2021-10-04",
            "count": 1
          },
          {
            "date": "2021-10-12",
            "count": 1
          },
          {
            "date": "2021-10-20",
            "count": 1
          },
          {
            "date": "2021-10-23",
            "count": 1
          },
          {
            "date": "2021-10-28",
            "count": 1
          },
          {
            "date": "2021-11-04",
            "count": 1
          },
          {
            "date": "2021-12-15",
            "count": 1
          },
          {
            "date": "2021-12-17",
            "count": 1
          },
          {
            "date": "2021-12-20",
            "count": 1
          },
          {
            "date": "2022-01-08",
            "count": 1
          },
          {
            "date": "2022-01-21",
            "count": 2
          },
          {
            "date": "2022-01-31",
            "count": 1
          },
          {
            "date": "2022-02-04",
            "count": 1
          },
          {
            "date": "2022-02-18",
            "count": 1
          },
          {
            "date": "2022-02-21",
            "count": 1
          },
          {
            "date": "2022-02-28",
            "count": 1
          },
          {
            "date": "2022-03-08",
            "count": 1
          },
          {
            "date": "2022-03-15",
            "count": 1
          },
          {
            "date": "2022-03-16",
            "count": 1
          },
          {
            "date": "2022-03-20",
            "count": 1
          },
          {
            "date": "2022-03-22",
            "count": 1
          },
          {
            "date": "2022-03-25",
            "count": 1
          },
          {
            "date": "2022-04-20",
            "count": 1
          },
          {
            "date": "2022-04-27",
            "count": 1
          },
          {
            "date": "2022-05-08",
            "count": 1
          },
          {
            "date": "2022-05-30",
            "count": 1
          },
          {
            "date": "2022-06-06",
            "count": 1
          },
          {
            "date": "2022-06-13",
            "count": 1
          },
          {
            "date": "2022-06-29",
            "count": 1
          },
          {
            "date": "2022-07-04",
            "count": 1
          },
          {
            "date": "2022-07-10",
            "count": 1
          },
          {
            "date": "2022-07-15",
            "count": 1
          },
          {
            "date": "2022-08-04",
            "count": 1
          },
          {
            "date": "2022-08-10",
            "count": 1
          },
          {
            "date": "2022-08-22",
            "count": 1
          },
          {
            "date": "2022-08-23",
            "count": 1
          },
          {
            "date": "2022-08-27",
            "count": 1
          },
          {
            "date": "2022-09-05",
            "count": 1
          },
          {
            "date": "2022-10-23",
            "count": 1
          },
          {
            "date": "2022-10-30",
            "count": 1
          },
          {
            "date": "2022-11-04",
            "count": 2
          },
          {
            "date": "2022-12-31",
            "count": 1
          },
          {
            "date": "2023-01-26",
            "count": 1
          },
          {
            "date": "2023-01-30",
            "count": 1
          },
          {
            "date": "2023-02-05",
            "count": 1
          },
          {
            "date": "2023-02-28",
            "count": 1
          },
          {
            "date": "2023-03-27",
            "count": 1
          },
          {
            "date": "2023-04-13",
            "count": 1
          },
          {
            "date": "2023-05-07",
            "count": 1
          },
          {
            "date": "2023-05-15",
            "count": 1
          },
          {
            "date": "2023-05-16",
            "count": 1
          },
          {
            "date": "2023-05-17",
            "count": 1
          },
          {
            "date": "2023-05-22",
            "count": 1
          },
          {
            "date": "2023-06-10",
            "count": 1
          },
          {
            "date": "2023-07-20",
            "count": 1
          },
          {
            "date": "2023-07-30",
            "count": 1
          },
          {
            "date": "2023-08-28",
            "count": 1
          },
          {
            "date": "2023-09-30",
            "count": 1
          },
          {
            "date": "2023-10-17",
            "count": 1
          },
          {
            "date": "2023-11-09",
            "count": 1
          },
          {
            "date": "2023-11-15",
            "count": 2
          },
          {
            "date": "2023-11-28",
            "count": 1
          },
          {
            "date": "2023-12-13",
            "count": 1
          },
          {
            "date": "2024-01-14",
            "count": 1
          },
          {
            "date": "2024-01-26",
            "count": 1
          },
          {
            "date": "2024-02-06",
            "count": 1
          },
          {
            "date": "2024-02-14",
            "count": 1
          },
          {
            "date": "2024-03-07",
            "count": 1
          },
          {
            "date": "2024-03-17",
            "count": 1
          },
          {
            "date": "2024-04-09",
            "count": 1
          },
          {
            "date": "2024-04-18",
            "count": 1
          },
          {
            "date": "2024-04-19",
            "count": 1
          },
          {
            "date": "2024-05-10",
            "count": 1
          },
          {
            "date": "2024-06-04",
            "count": 1
          },
          {
            "date": "2024-06-13",
            "count": 2
          },
          {
            "date": "2024-06-18",
            "count": 1
          },
          {
            "date": "2024-06-25",
            "count": 2
          },
          {
            "date": "2024-07-04",
            "count": 1
          },
          {
            "date": "2024-07-14",
            "count": 1
          },
          {
            "date": "2024-07-19",
            "count": 1
          },
          {
            "date": "2024-07-30",
            "count": 1
          },
          {
            "date": "2024-08-15",
            "count": 1
          },
          {
            "date": "2024-08-16",
            "count": 1
          },
          {
            "date": "2024-09-14",
            "count": 1
          },
          {
            "date": "2024-09-15",
            "count": 1
          },
          {
            "date": "2024-10-03",
            "count": 1
          },
          {
            "date": "2024-10-24",
            "count": 1
          },
          {
            "date": "2024-11-04",
            "count": 1
          },
          {
            "date": "2024-11-17",
            "count": 1
          },
          {
            "date": "2024-11-24",
            "count": 1
          },
          {
            "date": "2024-12-18",
            "count": 1
          },
          {
            "date": "2025-01-18",
            "count": 1
          },
          {
            "date": "2025-02-12",
            "count": 1
          },
          {
            "date": "2025-02-26",
            "count": 1
          },
          {
            "date": "2025-03-11",
            "count": 1
          },
          {
            "date": "2025-04-05",
            "count": 1
          },
          {
            "date": "2025-04-16",
            "count": 1
          },
          {
            "date": "2025-04-29",
            "count": 1
          },
          {
            "date": "2025-05-13",
            "count": 1
          },
          {
            "date": "2025-07-11",
            "count": 1
          },
          {
            "date": "2025-07-12",
            "count": 1
          },
          {
            "date": "2025-07-16",
            "count": 1
          },
          {
            "date": "2025-07-27",
            "count": 1
          },
          {
            "date": "2025-09-01",
            "count": 1
          },
          {
            "date": "2025-11-19",
            "count": 1
          },
          {
            "date": "2025-12-15",
            "count": 1
          },
          {
            "date": "2026-01-15",
            "count": 1
          },
          {
            "date": "2026-01-19",
            "count": 1
          },
          {
            "date": "2026-01-20",
            "count": 1
          },
          {
            "date": "2026-02-02",
            "count": 1
          },
          {
            "date": "2026-03-19",
            "count": 1
          },
          {
            "date": "2026-06-05",
            "count": 1
          },
          {
            "date": "2026-06-16",
            "count": 1
          },
          {
            "date": "2026-06-19",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 242,
        "total_forks": 242
      },
      "star_history": null,
      "open_issues_and_prs": 7
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 193262,
      "source_files_sampled": 57,
      "oversized_source_files": 1,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "composer.json"
      ],
      "advisories": {
        "error": "No resolved dependencies carried a version and a supported ecosystem",
        "scope": "repository_graph",
        "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": 3,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "packagist"
      ],
      "dependencies": [],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "ext-curl",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "ext-json",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "php",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 3,
        "direct_count": 0,
        "indirect_count": 3
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 1,
        "merged_prs": 21,
        "open_issues": 6,
        "closed_ratio": 0.964,
        "closed_issues": 162,
        "closed_unmerged_prs": 35
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "malle-pietje",
          "commits": 236,
          "avatar_url": "https://avatars.githubusercontent.com/u/12016131?v=4"
        },
        {
          "type": "User",
          "login": "Jacobtims",
          "commits": 9,
          "avatar_url": "https://avatars.githubusercontent.com/u/75219092?v=4"
        },
        {
          "type": "User",
          "login": "pauloboc",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/679128?v=4"
        },
        {
          "type": "User",
          "login": "4oo4",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/15698835?v=4"
        },
        {
          "type": "User",
          "login": "Warafux",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/23029038?v=4"
        },
        {
          "type": "User",
          "login": "JaspervRijbroek",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/1225017?v=4"
        },
        {
          "type": "User",
          "login": "mvarian",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/842943?v=4"
        },
        {
          "type": "User",
          "login": "patrice-guillemette",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/4839086?v=4"
        },
        {
          "type": "User",
          "login": "sgrodzicki",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/712836?v=4"
        },
        {
          "type": "User",
          "login": "smos",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/175997?v=4"
        }
      ],
      "contributors_sampled": 11,
      "top_contributor_share": 0.925
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": false,
      "ci_workflows": [],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "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": 0,
            "reason": "0 out of 3 merged PRs checked by a CI test -- score normalized to 0",
            "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": 1,
            "reason": "Found 3/30 approved changesets -- score normalized to 1",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 6,
            "reason": "project has 2 contributing companies or organizations -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "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": 2,
            "reason": "3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2",
            "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": null,
            "reason": "no dependencies found",
            "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": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "c5ab0a43edf1e82e9014821c1fd0b2c3838d9952",
        "ran_at": "2026-07-27T09:26:57Z",
        "aggregate_score": 3,
        "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": "2026-07-27T09:18:11Z",
      "oldest_open_prs": [
        {
          "number": 192,
          "created_at": "2023-04-17T09:25:54Z",
          "last_comment_at": "2024-02-11T17:43:38Z",
          "last_comment_author": "sgrodzicki"
        }
      ],
      "last_merged_pr_at": "2026-01-20T23:27:59Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 216,
          "created_at": "2024-02-21T03:54:18Z",
          "last_comment_at": "2025-04-24T23:40:59Z",
          "last_comment_author": "nelis249"
        },
        {
          "number": 240,
          "created_at": "2024-10-12T15:07:44Z",
          "last_comment_at": "2024-10-31T20:39:11Z",
          "last_comment_author": "malle-pietje"
        },
        {
          "number": 259,
          "created_at": "2025-01-08T20:55:39Z",
          "last_comment_at": "2025-04-17T10:09:08Z",
          "last_comment_author": "malle-pietje"
        },
        {
          "number": 260,
          "created_at": "2025-01-24T04:13:26Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 275,
          "created_at": "2025-08-23T10:40:47Z",
          "last_comment_at": "2025-08-30T13:25:20Z",
          "last_comment_author": "malle-pietje"
        },
        {
          "number": 280,
          "created_at": "2025-10-08T21:09:09Z",
          "last_comment_at": "2026-03-23T19:57:54Z",
          "last_comment_author": "malle-pietje"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Art-of-WiFi/UniFi-API-client",
    "host": "github.com",
    "name": "UniFi-API-client",
    "owner": "Art-of-WiFi"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 51,
      "inputs": {
        "security": 30,
        "vitality": 69,
        "community": 64,
        "governance": 60,
        "engineering": 25
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 69,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 61,
            "inputs": {
              "commits_last_year": 32,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 13
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "13/52 weeks with commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 13
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "32 commits in the last year",
                "points": 13.6,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 32
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "good",
            "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": 82,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v2.2.0",
              "releases_from_tags": false,
              "days_since_latest_release": 126,
              "mean_days_between_releases": 49.4
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 126 days ago",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 126
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~49.4 days",
                "points": 19.8,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 49.4
                    }
                  }
                ],
                "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": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 64,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "good",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 81,
            "inputs": {
              "forks": 242,
              "stars": 1340,
              "watchers": 64,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1,340 stars",
                "points": 50.7,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1340
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "242 forks",
                "points": 19.9,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 242
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "64 watchers",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 64
                    }
                  }
                ],
                "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
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "packages": [
                "art-of-wifi/unifi-api-client"
              ],
              "dependents": 2,
              "ecosystems": "packagist",
              "total_downloads": 422598,
              "monthly_downloads": 7287
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "7,287 downloads/month across packagist",
                "points": 51.5,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 7287,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "2 packages depend on it",
                "points": 3.2,
                "status": "partial",
                "details": [
                  {
                    "code": "registry_dependents",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 60,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 30,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 11,
              "top_contributor_share": 0.925
            },
            "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 92% of commits",
                "points": 1.7,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 92
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "11 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 11
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 61,
            "inputs": {
              "merged_prs": 21,
              "open_issues": 6,
              "closed_issues": 162,
              "issue_closed_ratio": 0.964,
              "closed_unmerged_prs": 35
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "96% of issues closed",
                "points": 45.1,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 96
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "21/56 decided PRs merged",
                "points": 14.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 21,
                      "decided": 56
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 3/30 approved changesets -- score normalized to 1",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 63,
            "inputs": {
              "followers": 121,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "Art-of-WiFi",
              "public_repos": 6,
              "account_age_days": 3347
            },
            "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": "121 followers of Art-of-WiFi",
                "points": 15,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 121,
                      "login": "Art-of-WiFi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "6 public repos, account ~9 yr old",
                "points": 18.2,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 6
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 9
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "art-of-wifi/unifi-api-client"
              ],
              "ecosystems": "packagist",
              "any_deprecated": false,
              "min_days_since_publish": 126
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on packagist",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 126 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 126
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "109 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 109
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "critical",
        "name": "Engineering Quality",
        "value": 25,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "critical",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "has_ci": false,
              "has_tests": false,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": "0 out of 3 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "topics": [
                "unifi",
                "ubnt",
                "ubiquiti",
                "api",
                "client",
                "class",
                "php",
                "api-client",
                "controller",
                "curl"
              ],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "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": 0,
                "status": "missed",
                "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": "10 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 30,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 30,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 13,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 5,
              "scorecard_aggregate": 3
            },
            "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": "0 out of 3 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "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 3/30 approved changesets -- score normalized to 1",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": "3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2",
                "points": 1.5,
                "status": "partial",
                "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": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "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": 12
            },
            "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": "critical",
        "name": "AI Readiness",
        "value": 23,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "critical",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 14,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.27,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "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": "27 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 14.4,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 27,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "critical",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 11,
            "inputs": {
              "has_nix": false,
              "has_tests": false,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.07,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "7 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 7,
                      "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": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 54,
            "inputs": {
              "primary_language": "PHP",
              "largest_source_bytes": 193262,
              "source_files_sampled": 57,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "PHP without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "PHP"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/57 source files over 60KB",
                "points": 54,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 57,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "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",
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T09:27:09.912531Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/Art-of-WiFi/UniFi-API-client.svg",
  "full_name": "Art-of-WiFi/UniFi-API-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 statisticsPackagist.