公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-28 15:14 UTC

flarum / testing

[READ ONLY] Subtree split of Flarum's backend testing utility library.

PHPMIT★ 0 星标⑂ 1 复刻始于 2021年1月在 GitHub 上查看 ↗

flarum/testing 的健康指数为 100 分中的 52 分,处于「中等」区间。 其得分最高的类别是Sustainability & Governance(75/100),最低的是Engineering Quality(27/100)。 最近一次更新在今天。 近期的大部分工作由 2 位贡献者完成。

52
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

52
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

Flarum组织
798 关注者53 个公开仓库始于 2013年9月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
Packagistflarum/testingv2.0.0-rc.521,71725101 天前forumdiscussion

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

64中等 · 占总体的 22%

开发活跃度

45存在风险
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
2.8/36提交节奏 — 52 周中有 4 周有提交
6.3/18提交量 — 最近一年 4 次提交
0/10OpenSSF Scorecard:Maintained — 1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
所用输入
commits_last_year4
human_commit_share0.99
days_since_last_push0
active_weeks_last_year4

发布纪律

92优秀
评分方式
27/27有发布版本 — 已发布 22 个发布版本
36/36发布时效 — 最近一次发布版本于 19 天前
19.8/27发布节奏 — 约每 48 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count22
latest_release_tagv2.0.0-rc.5
releases_from_tags
days_since_latest_release19
mean_days_between_releases48
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

38存在风险 · 占总体的 18%
评分方式
0/60星标 — 0 个星标
0/25复刻 — 1 个复刻
2.7/15关注者 — 4 位关注者
所用输入
forks1
stars0
watchers4
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

52中等
评分方式
0/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
18/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
6.3/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
57.8/80月度下载量 — packagist 合计每月 21,717 次下载
17.4/20注册表被依赖数 — 411 个软件包依赖它
所用输入
packagesflarum/testing
dependents411
ecosystemspackagist
total_downloads391,233
monthly_downloads21,717

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

75良好 · 占总体的 24%
评分方式
25.2/54巴士系数 — 2 位贡献者贡献了半数提交
15.7/22.5提交分布 — 头号贡献者编写了 30% 的提交
13.5/13.5贡献者广度 — 15 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 13 contributing companies or organizations
所用输入
bus_factor2
contributors_sampled15
top_contributor_share0.304
评分方式
0/46.8议题解决 — 没有议题或无数据
35.3/38.3PR 接受 — 已裁定的 PR 中 12/13 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs12
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs1
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
20.9/25所有者影响力 — flarum 有 798 位关注者
24.6/25既往记录 — 53 个公开仓库,账户约 12 年
所用输入
followers798
owner_typeOrganization
is_verified
owner_loginflarum
public_repos53
account_age_days4,688
评分方式
25/25已发布且可解析 — packagist 上有 1 个软件包
35/35发布时效 — 最近一次发布于 101 天前
20/20版本历史 — 25 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesflarum/testing
ecosystemspackagist
any_deprecated
min_days_since_publish101

工程质量

基础的工程与文档实践是否到位?

27危急 · 占总体的 20%

工程实践

38存在风险
评分方式
0/24CI 工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
6.4/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 无数据
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config
已排除计分(无数据或不适用):OpenSSF Scorecard:CI-Tests。 其余权重已重新归一化。

文档

10危急
评分方式
0/30README
0/25文档目录
0/15文档 / 主页站点
10/10仓库描述
0/10主题标签
0/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

48存在风险 · 占总体的 16%

安全态势

48存在风险
评分方式
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/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 13 contributing companies or organizations
0/10Dangerous-Workflow — 无数据
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
0/7.5Maintained — 1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
0/5Packaging — 无数据
0/5Pinned-Dependencies — 无数据
0/5SAST — no SAST tool detected
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — 无数据
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated12
scorecard_versionv5.5.0
checks_inconclusive6
scorecard_aggregate4.8
已排除计分(无数据或不适用):ci_tests, dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions。 其余权重已重新归一化。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

39存在风险 · 占总体的 0%
评分方式
0/45代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则
0/15机器可读文档(llms.txt)
33.9/40可读的提交历史 — 99 次人类提交中有 63 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.636
agent_instruction_files
agent_instruction_max_bytes
评分方式
0/18一条命令的引导启动
22/22自动化测试
0/11Lint / 格式化配置
0/11静态类型检查
0/10可复现环境
2/10已体现的代理实践 — 最近 100 次提交中有 1 次由代理编写或署名代理
8/8自动化维护 — 最近 100 次提交中有 1 次为自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — 无数据
所用输入
has_nix
has_tests
lockfiles
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.01
toolchain_manifests
dependency_bot_commit_share0.01
已排除计分(无数据或不适用):OpenSSF Scorecard:Pinned-Dependencies。 其余权重已重新归一化。
评分方式
0/45可类型检查的代码 — PHP,未配置类型检查
55/55可控的文件大小 — 采样的 20 个源文件中有 0 个超过 60KB
所用输入
primary_languagePHP
largest_source_bytes11,108
source_files_sampled20
oversized_source_files0

关键数据

0GitHub 星标
15贡献者
4最近 12 个月提交数
0距最近推送天数
22发布版本数
2巴士系数(bus factor)
0开放议题
Packagist软件包生态系统数

数据采集警告

  • No resolved dependencies carried a version and a supported ecosystem

更多细节

OpenSSF Scorecard 4.8 / 10
4.8综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-28 15:14 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 13 contributing companies or organizations
不适用Dangerous-Workflowno workflows found
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintained1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
不适用Packagingpackaging workflow not detected
不适用Pinned-Dependenciesno dependencies found
0SASTno SAST tool detected
10Security-Policysecurity policy file detected
不适用Signed-Releasesno releases found
不适用Token-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
直接依赖 1
注册表软件包版本约束清单文件
Packagistmockery/mockery^1.5composer.json
全部依赖 6

来自 GitHub 依赖图的完整解析依赖集合:1 个直接依赖与 5 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
Packagistmockery/mockery直接
Packagistext-json间接
Packagistflarum/core间接
Packagistflarum/testing间接
Packagistflarum/testing-tests间接
Packagistphpunit/phpunit间接
依赖安全公告 未评估

本报告未能完成公告比对:No resolved dependencies carried a version and a supported ecosystem

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 110,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "PHP": 44230
      },
      "pushed_at": "2026-07-28T13:17:56Z",
      "created_at": "2021-01-07T23:14:42Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-28T13:21:15Z",
      "description": "[READ ONLY] Subtree split of Flarum's backend testing utility library.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "2.x",
      "license_spdx_raw": "MIT",
      "primary_language": "PHP",
      "significant_languages": [
        "PHP"
      ]
    },
    "owner": {
      "blog": "http://flarum.org",
      "name": "Flarum",
      "type": "Organization",
      "login": "flarum",
      "company": null,
      "location": null,
      "followers": 798,
      "avatar_url": "https://avatars.githubusercontent.com/u/5549034?v=4",
      "created_at": "2013-09-26T11:15:45Z",
      "is_verified": null,
      "public_repos": 53,
      "account_age_days": 4688
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.0.0-rc.5",
          "kind": "prerelease",
          "published_at": "2026-07-08T15:55:02Z"
        },
        {
          "tag": "v2.0.0-rc.4",
          "kind": "prerelease",
          "published_at": "2026-06-18T11:59:55Z"
        },
        {
          "tag": "v2.0.0-rc.3",
          "kind": "prerelease",
          "published_at": "2026-06-09T18:54:15Z"
        },
        {
          "tag": "v2.0.0-rc.2",
          "kind": "prerelease",
          "published_at": "2026-06-01T18:18:07Z"
        },
        {
          "tag": "v2.0.0-rc.1",
          "kind": "prerelease",
          "published_at": "2026-04-20T10:16:32Z"
        },
        {
          "tag": "v2.0.0-beta.8.1",
          "kind": "prerelease",
          "published_at": "2026-04-18T21:10:52Z"
        },
        {
          "tag": "v2.0.0-beta.7",
          "kind": "prerelease",
          "published_at": "2026-02-22T17:16:17Z"
        },
        {
          "tag": "v2.0.0-beta.6",
          "kind": "prerelease",
          "published_at": "2026-01-30T09:27:52Z"
        },
        {
          "tag": "v2.0.0-beta.5",
          "kind": "prerelease",
          "published_at": "2025-12-20T22:45:39Z"
        },
        {
          "tag": "v2.0.0-beta.3",
          "kind": "prerelease",
          "published_at": "2025-05-02T08:30:51Z"
        },
        {
          "tag": "v2.0.0-beta.2",
          "kind": "prerelease",
          "published_at": "2025-01-17T09:17:11Z"
        },
        {
          "tag": "v2.0.0-beta.1",
          "kind": "prerelease",
          "published_at": "2024-12-11T17:10:49Z"
        },
        {
          "tag": "v1.8.0",
          "kind": "minor",
          "published_at": "2023-05-20T17:52:21Z"
        },
        {
          "tag": "v1.7.0",
          "kind": "minor",
          "published_at": "2023-03-10T13:44:37Z"
        },
        {
          "tag": "v1.6.0",
          "kind": "minor",
          "published_at": "2022-11-15T11:50:54Z"
        },
        {
          "tag": "v1.5.0",
          "kind": "minor",
          "published_at": "2022-09-13T09:35:02Z"
        },
        {
          "tag": "v1.4.1",
          "kind": "patch",
          "published_at": "2022-08-02T18:05:28Z"
        },
        {
          "tag": "v1.4.0",
          "kind": "minor",
          "published_at": "2022-07-13T12:34:04Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2022-05-12T10:35:33Z"
        },
        {
          "tag": "v1.0.1",
          "kind": "patch",
          "published_at": "2021-06-21T07:44:54Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2021-05-27T08:30:34Z"
        },
        {
          "tag": "v0.1.0-beta.16.1",
          "kind": "prerelease",
          "published_at": "2021-03-11T18:08:10Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "8b4cf12e5a7dbedd7afbc5dc716c9cbc56248442",
          "body": "Binding db.transactions (#4787) means listeners implementing\nShouldHandleEventsAfterCommit are deferred to the surrounding\ntransaction's commit. The integration harness wraps each test in a\ntransaction that is rolled back and never committed, so those callbacks\nwere attached to it and silently disca\n[…]\nat\nreports no applicable pending transactions, so addCallback() runs each\ncallback immediately. db.transactions stays bound and\nConnection::afterCommit() still works, keeping #4787 intact.\n\nRefs #4814",
          "is_bot": false,
          "headline": "Run after-commit callbacks inline in integration tests (#4833)",
          "author_name": "IanM",
          "author_login": "imorland",
          "committed_at": "2026-07-24T14:13:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d0344b4928a230638f9f3ed64538b0159ffa954a",
          "body": "Unblocks composer install on flarum/testing consumers: the PHPUnit 11.x\nline has no fix for GHSA-qrr6-mg7r-m243 (PKSA-5jz8-6tcw-pbk4), so every\n11.x version is filtered by Composer's advisory check.\n\nPHPUnit 12 requires PHP 8.3+, which matches the 2.x floor. Flarum's own\ntest suites already use PHP 8 attributes exclusively; third-party\nextensions still using @test / @dataProvider docblock annotations will\nneed to migrate.\n\nCloses #4584",
          "is_bot": false,
          "headline": "chore: bump phpunit/phpunit to ^12.5.22 (#4585)",
          "author_name": "IanM",
          "author_login": "imorland",
          "committed_at": "2026-04-18T09:09:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6a06f40dbd3d3a1c51b67a6f1c3faf470d67bd30",
          "body": "* Added support for pgsql's search_path\n\n* Put schema after database name\n\n* Add schema arguments and order 'ask's\n\n* Fixed errors",
          "is_bot": false,
          "headline": "feat: Add support for pgsql's search_path (#4241)",
          "author_name": "Johann Rodríguez",
          "author_login": "johannsa",
          "committed_at": "2026-03-22T20:10:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e224bb24a5a3ba5918a3a9bb40b4399ee25d57c",
          "body": "…atic analysis (#4450)\n\nIntelephense reports \"Undefined method 'getDriverName'\" (and similar)\nbecause the `database` property and `TestCase::database()` return\n`ConnectionInterface`, which doesn't declare concrete `Connection`\nmethods.\n\nKeep `ConnectionInterface` as the actual PHP type so custom con\n[…]\nt add `@var Connection|null` / `@return Connection` PHPDoc\nannotations so Intelephense and PHPStan resolve the concrete methods.\n\nFixes #4432\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(testing): narrow database property/method types via PHPDoc for st…",
          "author_name": "IanM",
          "author_login": "imorland",
          "committed_at": "2026-03-15T07:01:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e4a4ffbfa107737e26c184bead527aec19ac160d",
          "body": null,
          "is_bot": false,
          "headline": "chore(testing): use sqlite by default",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-12-06T19:23:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "afdabe66516ecd9ffc767b1a101d592a594d5825",
          "body": "* feat: separate mariadb driver\r\n* chore: add mariadb install dump",
          "is_bot": false,
          "headline": "feat: separate mariadb driver (#4132)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-12-02T09:17:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1755040252d7212536ff812cd2fe63978e77477b",
          "body": null,
          "is_bot": false,
          "headline": "Apply fixes from StyleCI",
          "author_name": "StyleCI Bot",
          "author_login": "StyleCIBot",
          "committed_at": "2024-11-29T12:54:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "944da2d402a7a25e9991d8a3c4b1ed5a895bcbdd",
          "body": "* chore(testing): run flarum/testing packages tests back again\r\n\r\nThese tests were not run on each framework build, I enabled them again.\r\nTwo of the tests were failing so I disabled them for now, it is more\r\nimportant to have some tests running than none at all.\r\n\r\n* chore(testing): remove flarum/t\n[…]\ng dedicated workflow\r\n\r\nIt is useless now that the tests are run in the framework repo.\r\nAlso this workflow was not working anymore.\r\n\r\n---------\r\n\r\nCo-authored-by: Sami Mazouz <sychocouldy@gmail.com>",
          "is_bot": false,
          "headline": "test(testing): run `flarum/testing` package tests (#3844)",
          "author_name": "Nicolas Peugnet",
          "author_login": "n-peugnet",
          "committed_at": "2024-11-29T12:54:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "06c627f02d552c1feb4973c94b8ba6f98a8e74d9",
          "body": "* test: php 8.4\r\n\r\n* fix: php 8.4 deprecations\r\n\r\n* fix: make argument required\r\n\r\n* chore: review changes",
          "is_bot": false,
          "headline": "test: php 8.4 (#4103)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-11-08T16:33:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "090079c4ef9fdbdbe5ae789641e280d4ed5462b0",
          "body": "* chore: phpunit 10\r\n\r\n* chore: config\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* chore: phpunit 11 (php 8.2 minimum requirement)\r\n\r\n* feat: laravel 11\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* feat: carbon v3\r\n\r\n* fixes",
          "is_bot": false,
          "headline": "chore: update dependencies (#4012)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-08-06T15:50:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8ac2d4b6b843a076dd98907520a2d8ec66815b5d",
          "body": "* feat: add support for `PgSQL`\r\n* chore: generate dump\r\n* feat: query exception errors db driver hint\r\n* feat: allow defining supported databases\r\n* chore: review comments\r\n* feat: setting for pgsql preferred search config",
          "is_bot": false,
          "headline": "feat: add support for PgSQL (#3985)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-06-22T07:03:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "77e2e63aa3371e1e0b34ef6d21778cbc96150bb3",
          "body": "* refactor: json:api refactor iteration 1\r\n* chore: delete dead code\r\n* fix: regressions\r\n* chore: move additions/changes to package\r\n* feat: AccessTokenResource\r\n* feat: allow dependency injection in resources\r\n* feat: `ApiResource` extender\r\n* feat: improve\r\n* feat: refactor tags extension\r\n* feat\n[…]\nt\r\n* feat: eager loading\r\n* test: adapt\r\n* test: phpstan\r\n* test: adapt\r\n* fix: typing\r\n* fix: approving content\r\n* tet: adapt frontend tests\r\n* chore: typings\r\n* chore: review\r\n* fix: breaking change",
          "is_bot": false,
          "headline": "refactor: JSON:API (#3971)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-06-21T08:36:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "93258af33f1c9232a907bb149409edc6d527960c",
          "body": "* feat: add support for sqlite\r\n\r\n* chore: add warning on install\r\n\r\n* fix: ignore constraints before transaction begins\r\n\r\n* chore: update workflow\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* chore: generate sqlite dump and manually add foreign keys\r\n\r\n* chore: fix actions\r\n\r\n* chore: fix actions\r\n\r\n* chore\n[…]\nhore: fix actions\r\n\r\n* chore: fix actions\r\n\r\n* chore: fix actions\r\n\r\n* test: fix\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* fix: sqlite with db prefix\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* fix: statistics sqlite",
          "is_bot": false,
          "headline": "feat: add support for `SQLite` (#3984)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-06-21T06:25:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9ef773e68e13e5db7de907242c4744208844ad47",
          "body": "* feat: low maintenance mode (maintenance with admin access) (#3975)\r\n* feat: low maintenance mode (maintenance with admin access)\r\n* Apply fixes from StyleCI\r\n* chore: only required when basic\r\n* chore: more concise code\r\n* chore(review): enum\r\n* feat: enable through settings\r\n* Apply fixes from StyleCI\r\n* core: typing\r\n* feat: safe mode (#3978)\r\n* feat: safe mode\r\n* feat: add extension page warning\r\n* feat: `safe_mode_extensions`\r\n* Apply fixes from StyleCI",
          "is_bot": false,
          "headline": "feat: advanced maintenance modes (#3977)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-05-03T13:05:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "949b2d9b6ee015b219c88431c4ed858c4047666a",
          "body": null,
          "is_bot": false,
          "headline": "feat: eloquent factories (primarily for tests) (#3982)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2024-05-03T08:20:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "14823131be03781a356b50cf4858432f6953519f",
          "body": null,
          "is_bot": false,
          "headline": "Apply fixes from StyleCI",
          "author_name": "StyleCI Bot",
          "author_login": "StyleCIBot",
          "committed_at": "2024-01-09T15:06:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "450ea893c974aefd5f3e9c915d3ed22c0303b822",
          "body": null,
          "is_bot": false,
          "headline": "fix(testing): use cookie for testing authentication (#3924)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-11-10T21:35:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40167f9c7a0166c9a71cbd9df2a12616923dcff6",
          "body": "…ntract (#3862)\n\n* chore: merge the app with the container & implement the ApplicationContract\r\n\r\nIlluminate components always expect the app to be the container, but also expect the app to be implementing the laravel app contract. This means that very often between minor illuminate updates we get a\n[…]\n: service provider no longer has to change app type\r\n* chore: unimplement `terminat(e/ing)`\r\n* Apply fixes from StyleCI\r\n* chore: recover `container` prop\r\n* chore: return types\r\n* fix: phpstan errors",
          "is_bot": false,
          "headline": "chore: merge the app with the container & implement the ApplicationCo…",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-09-15T08:30:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "51828db2100eb056b47b5b904cedf0c50ea40944",
          "body": "* Do not catch exceptions when testing Console commands\r\n\r\nThis allows to easily test a case where a command should throw using `$this->expectException()`.\r\n\r\n* Rewrite ConsoleTest to use expectException\r\n\r\nNow that the ConsoleApplication is set to not catch exceptions.\r\n\r\n---------\r\n\r\nCo-authored-by: IanM <16573496+imorland@users.noreply.github.com>",
          "is_bot": false,
          "headline": "Do not catch exceptions when testing Console commands (#3813)",
          "author_name": "Nicolas Peugnet",
          "author_login": "n-peugnet",
          "committed_at": "2023-06-21T07:14:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a93309ca44946351ff13b3f35185b5d8789dda96",
          "body": "…es (#3835)",
          "is_bot": false,
          "headline": "chore(phpstan): upgrade to be compatible with latest dependency updat…",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-06-15T16:49:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ff80f37855b9007f8a308b0099c3d9dca31e8a7",
          "body": "Allows running tests without constantly running `composer install` on each extension.",
          "is_bot": false,
          "headline": "chore: improve test suite (#3814)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-06-15T12:26:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe7f169672d8b774fff2b930036c359b16b14c5f",
          "body": "* wip: laraval and symfony upgrades\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* bump var dumper to 6.3\r\n\r\n* require guzzle 7.7\r\n\r\n* remove docbloc\r\n\r\n* lock symfony/translation-contracts to 2.5\r\n\r\n* fix: require mailgun package\r\n\r\n* remove docblock\r\n\r\n* fix: flysystem tests\r\n\r\n*\n[…]\n fixes from StyleCI\r\n\r\n---------\r\n\r\nCo-authored-by: StyleCI Bot <bot@styleci.io>\r\nCo-authored-by: Daniël Klabbers <luceos@users.noreply.github.com>\r\nCo-authored-by: Sami Mazouz <sychocouldy@gmail.com>",
          "is_bot": false,
          "headline": "chore: Upgrade dependencies (#3830)",
          "author_name": "IanM",
          "author_login": "imorland",
          "committed_at": "2023-06-14T13:46:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bc34b358ed84147edf2ba4b546bfbf4be51ed1d1",
          "body": "Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>",
          "is_bot": false,
          "headline": "fix(regression): caught errors",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-05-31T08:50:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2aaabd1d54e23eb92a45e0fa4fee6a996f300cef",
          "body": "* chore: set minimum php version to 8.1\r\n\r\nSigned-off-by: Sami Mazouz <sychocouldy@gmail.com>\r\n\r\n* chore: update codebase to php8.1\r\n\r\nSigned-off-by: Sami Mazouz <sychocouldy@gmail.com>\r\n\r\n* Apply fixes from StyleCI\r\n\r\n* chore: update workflow php version\r\n\r\nSigned-off-by: Sami Mazouz <sychocouldy@g\n[…]\nail.com>\r\n\r\n* fix: one last error\r\n\r\nSigned-off-by: Sami Mazouz <sychocouldy@gmail.com>\r\n\r\n---------\r\n\r\nSigned-off-by: Sami Mazouz <sychocouldy@gmail.com>\r\nCo-authored-by: StyleCI Bot <bot@styleci.io>",
          "is_bot": false,
          "headline": "chore: update codebase to php8.1 (#3827)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-05-30T10:36:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fd9251f9cf540c7df074bc6e7dfeb35de321efb4",
          "body": "This prevent tests from interacting between each other through the cache.",
          "is_bot": false,
          "headline": "fix(testing): always clear cache in integration test's tearDown (#3818)",
          "author_name": "Nicolas Peugnet",
          "author_login": "n-peugnet",
          "committed_at": "2023-05-02T18:24:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0c31cd504db6d395ba1da91178d36677ad761660",
          "body": null,
          "is_bot": false,
          "headline": "feat(testing): add a trait to flush the formatter cache in tests (#3811)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-04-30T08:48:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35f96f607acb0798fe6828ce85d76b59ad0292fd",
          "body": "Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>\r\nCo-authored-by: David <hi@davwheat.dev>",
          "is_bot": false,
          "headline": "feat: access tokens user management UI (#3587)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2023-02-21T13:14:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "44c92b807bd6e9926512fe9e2934f9f1bb69ba5e",
          "body": "* Make it possible to extend Flarum\\Testing\\integration\\Setup\\SetupScript and added public methods to add settings or extensions to in initial installation pipeline\r\n\r\n* Fix syntax error, unexpected 'static'\r\n\r\n* Remove `addExtensions` method and document `addSettings`",
          "is_bot": false,
          "headline": "feat(test): Make it possible to extend SetupScript (#3643)",
          "author_name": "Rafael Horvat",
          "author_login": "iPurpl3x",
          "committed_at": "2022-09-23T11:44:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ebd19f5443deada50b9528b937a221f1a2afd3b8",
          "body": null,
          "is_bot": false,
          "headline": "feat: customizable session driver (#3610)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2022-09-14T17:10:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64c6b2125c0da42cbb77deac5ea62913b97a0e0a",
          "body": null,
          "is_bot": false,
          "headline": "chore: v1.5.0 preparations",
          "author_name": "Daniël Klabbers",
          "author_login": "luceos",
          "committed_at": "2022-09-13T08:55:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9199962f6fcd3382a484c143fcbfef6c098f7f60",
          "body": "* test: password tokens are generated and deleted on password change\r\n* chore: delete all password tokens when the password is changed\r\n* test: email tokens are generated and deleted on email change\r\n* test: email tokens are deleted after password reset\r\n* chore: delete email tokens after password change\r\n* test: password tokens are deleted after email change\r\n* chore: delete password tokens after email change\r\n* chore: syntactic sugar\r\n* chore: unify event listening",
          "is_bot": false,
          "headline": "feat: clear password & email tokens when appropriate (#3567)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2022-07-30T12:02:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "37f36d0a7f87b8e7668e50a92f846b8ef1aee8c6",
          "body": "With all the commits below, we resolve all outstanding typing issues in the repo, and CI jobs run green.\r\n\r\n* fix: Convert DashboardPage and DashboardWidget to TypeScript\r\n\r\n* fix: fix type errors in package manager ext\r\n\r\n* fix: Convert Post component to TypeScript\r\n\r\n* fix: avatar typings should a\n[…]\nlarum-cli audit infra --monorepo --fix\r\n\r\n* feat: make `app.data` typings extensible\r\n\r\n* chore(core): format\r\n\r\n* chore: boost tags TypeScript coverage\r\n\r\n* fix(tags): further increase type coverage.",
          "is_bot": false,
          "headline": "fix: Assorted Typing Fixes (#3348)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2022-03-23T15:43:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "97df6620ce295b08502a43425b5060420922551d",
          "body": "…i/js (#3345)\n\n* chore(deps): bump glob-parent in /extensions/emoji/js\r\n\r\nBumps [glob-parent](https://github.com/gulpjs/glob-parent) from 3.1.0 to 5.1.2.\r\n- [Release notes](https://github.com/gulpjs/glob-parent/releases)\r\n- [Changelog](https://github.com/gulpjs/glob-parent/blob/main/CHANGELOG.md)\r\n-\n[…]\nrt@github.com>\r\n\r\n* Apply fixes from StyleCI\r\n\r\n[ci skip] [skip ci]\r\n\r\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>\r\nCo-authored-by: StyleCI Bot <bot@styleci.io>",
          "is_bot": true,
          "headline": "chore(deps): bump glob-parent from 3.1.0 to 5.1.2 in /extensions/emoj…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2022-03-11T23:11:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "33cbae8106b6a5303c6c0284a705b28127f3ad30",
          "body": null,
          "is_bot": false,
          "headline": "chore: set up composer path repos",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2022-03-11T23:02:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6a60493cff12a3f90392062f6edf53f04e76affd",
          "body": "- Remove .github conf folder from Flarum packages\n\n- Remove styleci config from all packages",
          "is_bot": false,
          "headline": "chore: remove centralizable repo config",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2022-03-11T23:01:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "617cf037e58e4c3ec1f1b84f5c2e9a1f6b008f30",
          "body": null,
          "is_bot": false,
          "headline": "allow empty db password \"\" again",
          "author_name": "Daniel Klabbers",
          "author_login": "luceos",
          "committed_at": "2021-06-21T07:32:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2b9890970975a5c6d8fd22eebe93ac691f98ed14",
          "body": null,
          "is_bot": false,
          "headline": "fix branch alias",
          "author_name": "Daniel Klabbers",
          "author_login": "luceos",
          "committed_at": "2021-05-25T20:59:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fefd46886ff42c600ae035b71d0c97fa62ffd6b3",
          "body": null,
          "is_bot": false,
          "headline": "Update copyright year",
          "author_name": "David Wheatley",
          "author_login": "davwheat",
          "committed_at": "2021-05-14T23:58:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "68bda3f994065797a08b93427b2219bec0f79dfc",
          "body": "Before boot, we consider them \"disabled\" so they get migrated.",
          "is_bot": false,
          "headline": "Extensions should be considered enabled after boot.",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-05-11T23:31:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0960a93d8be2eede83373773fcb2270423740ec3",
          "body": null,
          "is_bot": false,
          "headline": "Ensure that migrations run",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-05-11T21:15:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9ef0e5af606669865a0f9c8f8cec4c62af4f391b",
          "body": null,
          "is_bot": false,
          "headline": "get/set enabled extensions from test case, not DB",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-05-11T20:24:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e7f4e2bbe8536403410870b5950d86e1ee3e36ed",
          "body": "The transaction is already started in the proper `BeginTransactionAndSetDatabase` extender.",
          "is_bot": false,
          "headline": "Remove second beginTransaction",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-05-03T05:27:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06e04c6c24281621b127243ac6b828128cfa8cfc",
          "body": "In normal Flarum, extensions are only enabled during requests. Here, however, we enable some during boot. This resolves the FilesystemManager early, which resolves the Url Generator early. To fix this, we directly provide a filesystem disk for assets instead of getting it from the filesystem manager.",
          "is_bot": false,
          "headline": "Don't resolve routes early.",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-23T22:26:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d88991d1abfe28bc6bc7e31d2989f8f74547eb49",
          "body": null,
          "is_bot": false,
          "headline": "Ensure app is booted when getting database",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-23T19:20:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c7190e4565553a956cf5314190c55838848b265",
          "body": "This ensures a clean state for the extension currently being tested. The alternative requires the user to create and keep track of multiple test databases, or manually delete/re-recreate the database every time they switch between extensions being tested. Now, a simple `composer test:setup` will always reset the test environment to the original state.",
          "is_bot": false,
          "headline": "Drop all DB tables before installation during setup. (#9)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-20T18:47:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4d9caf8f8a2c4d353cca0a22b82b2ade07c2745",
          "body": "Similarly to `settings`, this allows setting/overriding config prior to application boot.",
          "is_bot": false,
          "headline": "TestCase Config method (#13)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-14T20:27:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4c4b70b6bd2d76e27db884f9f0bed66c759b9d83",
          "body": null,
          "is_bot": false,
          "headline": "Remove UsesSettingsTrait (#12)",
          "author_name": "Sami Mazouz",
          "author_login": "SychO9",
          "committed_at": "2021-04-14T03:46:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "056d06663d7803762d6732ced9f33d1745cf8d44",
          "body": "This make a cleaner state more likely, and ensures that settings set via `$this->setting` are cleaned up after the test case runs.",
          "is_bot": false,
          "headline": "Start transactions before the app is fully booted. (#11)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-12T14:26:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eae3eca5183e8318c7b4642e00fd4debf0eade62",
          "body": null,
          "is_bot": false,
          "headline": "Add a few more automated tests",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-12T03:00:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "281d165edca3f6b81a29f60732defcce9aa4a8e4",
          "body": "Since we're making changes for the dev version of core, we should test against that too.\n\nFor now, this fixes issues with the `extensions` method of `Installation` being undefined.",
          "is_bot": false,
          "headline": "Test against dev version of core",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-12T02:47:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ac376c810bf0fe6ff5e65e59eb730c1aa6d302cb",
          "body": null,
          "is_bot": false,
          "headline": "Don't enable extensions during installation (#7)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-08T22:39:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6dca45010855fa45ab571e440f49c1b834c4f98a",
          "body": null,
          "is_bot": false,
          "headline": "Add automated tests for `flarum/testing`",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-07T21:38:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "181fa93105700cc3fbc08f2950b947a1f57f1114",
          "body": "This allows adding settings before the app is booted. In the past we've used hacky workarounds like manually resetting a binding to override singletons to use custom setting values. It makes sense to support this through `TestCase`.",
          "is_bot": false,
          "headline": "Add `setting` method to integration TestCase",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-04-07T19:01:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "231101bfd1fe5400d82ab673f1283a747292dd4c",
          "body": "Add ext-json to composer requirements\r\nUpdate editorconfig to match core\r\nUpdate phpdoc to not reference missing import",
          "is_bot": false,
          "headline": "Requirement and formatting fixes (#5)",
          "author_name": "Clark Winkelmann",
          "author_login": "clarkwinkelmann",
          "committed_at": "2021-03-21T18:26:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d503e27159b6df6b4446e62ff4d1c0cef93d9aae",
          "body": "Replace bind with singleton, otherwise singleton behavior is lost",
          "is_bot": false,
          "headline": "Add missing import for ExtensionManager (#6)",
          "author_name": "Clark Winkelmann",
          "author_login": "clarkwinkelmann",
          "committed_at": "2021-03-21T18:25:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cc1d6940da87e1e317b908348f3309f4938463b2",
          "body": "It's not causing any issue because the correct variable name is always used to set and read the value, and PHP is fine setting new attributes on a class dynamically. It's just the explicit variables declared don't match with those actually used later.",
          "is_bot": false,
          "headline": "Fix variable names (#4)",
          "author_name": "Clark Winkelmann",
          "author_login": "clarkwinkelmann",
          "committed_at": "2021-03-20T22:46:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1756fcf740357f8a49066fc82adcdad19d549cac",
          "body": null,
          "is_bot": false,
          "headline": "Ignore generated tmp",
          "author_name": "SychO9",
          "author_login": "SychO9",
          "committed_at": "2021-03-11T18:07:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "859abdcdcf0468a511ae62544bd37add5515b5f9",
          "body": null,
          "is_bot": false,
          "headline": "Add required argument",
          "author_name": "SychO9",
          "author_login": "SychO9",
          "committed_at": "2021-03-11T18:07:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb60426e94d9a8a01233d331718dda51a5224927",
          "body": null,
          "is_bot": false,
          "headline": "Use mockery 1.4",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-03-06T23:58:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f2d4acde3908f6409be389f774f432933e3a1ea",
          "body": null,
          "is_bot": false,
          "headline": "Update PHPUnit to v9",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-03-06T23:38:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b14bee7e6db7d5b3770f013462f10b062ed6b79",
          "body": null,
          "is_bot": false,
          "headline": "Update BuildsHttpRequests for new token system",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-03-06T23:38:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c7f29633462e487114198cf5d7a3aee7696cde19",
          "body": null,
          "is_bot": false,
          "headline": "Configurable Tmp Dir Location (#2)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-02-10T13:59:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "21cf1a3b061fbf081ded4356cd0dfa4fc32d2eff",
          "body": "Core's ExtensionManager only looks for extensions in the vendor directory, which makes sense for a Flarum instance, but is problematic if used in the context of a test suite for an extension. This PR:\r\n\r\n- Adds a class extending ExtensionManager to include the current package\r\n- Adds an extender that replaces ExtensionManager with this new class in container bindings\r\n\r\nEffectively, this package can now be used to test extensions.",
          "is_bot": false,
          "headline": "If current package is an extension, add it to the extension manager (#1)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-24T17:13:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "063c71a44ec0d242f8fce6e9cc2fad6c74911644",
          "body": null,
          "is_bot": false,
          "headline": "Fix vendor path",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T21:49:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "27da25243f2ca60c0c6b9472a3e63c9db6177d70",
          "body": null,
          "is_bot": false,
          "headline": "Move setup script to importable class",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T21:22:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2401525a4e3085e206e807544636e2c7ae6cff52",
          "body": null,
          "is_bot": false,
          "headline": "Add composer.json",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:27:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "146f4c9d3543dda5ee2e41edb5cab8e4113048a8",
          "body": null,
          "is_bot": false,
          "headline": "Move test infrastructure to Testing namespace in src directory",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:27:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "551284de665ec9c6ed3f7378926caea96d61e14e",
          "body": "Some tests need to change settings, but since MemoryCacheSettingsRepository caches settings in-memory, those changes aren't reflected. The new `purgeSettingsCache` removes it from the container, eliminating that cache.\n\nFor UserTest, we also need to regenerate the display name driver, since that's set statically on boot, before we'll get a change to clear the settings cache.",
          "is_bot": false,
          "headline": "Tests: purge settings cache",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "290943b70b7e806eadbb48fabe952fd19f56d2e4",
          "body": null,
          "is_bot": false,
          "headline": "Add @inheritDoc to all setUp and tearDown methods",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79af839ee96ee607aa6b829c26e71c4d0dcb971f",
          "body": null,
          "is_bot": false,
          "headline": "Tests: Always start transaction before seeding",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c64712d7a45ddeac23d69a728a62a785698d8bd",
          "body": null,
          "is_bot": false,
          "headline": "Tests: Stop using Eloquent models for seeding data",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "003a48ea9aa844f88d1983573d2698fcedcab1b5",
          "body": null,
          "is_bot": false,
          "headline": "Tests: Rely on admin user, groups, permissions from test setup script",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "abd3ed841ee17be4161047a25490b08086f52011",
          "body": null,
          "is_bot": false,
          "headline": "Run integration tests in a transaction",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0cde58df60e4361d01b13ac964fc121597a6e593",
          "body": null,
          "is_bot": false,
          "headline": "Add vscode config to gitignore",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0a728626e493721bd670a2cd68e9916bf76f795",
          "body": null,
          "is_bot": false,
          "headline": "Improve developer experience by forcing LF line endings (#2321)",
          "author_name": "Wadim Kalmykov",
          "author_login": "w-4",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0fecc6cfa1d6a6751bb33f050dd4f34126ac498",
          "body": null,
          "is_bot": false,
          "headline": "Use Config class for data from config.php",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "665b3a2822df18eb852d66ab3dda0b8a44b2743a",
          "body": "* Write source map without creating temp file\r\n\r\nLess I/O, and one less place where we access the global path helpers.\r\n\r\n* Drop useless app_path() helper\r\n\r\nThis was probably taken straight from Laravel. There is no equivalent\r\nconcept in Flarum, so this should be safe to remove.\r\n\r\n* Deprecate glo\n[…]\nm Application class\r\n\r\n* Avoid using public_path() in prerequisite check\r\n\r\na) The comparison was already outdated, as a different path was passed.\r\nb) We're trying to get rid of these global helpers.",
          "is_bot": false,
          "headline": "Clean up usages / deprecate path helpers (#2155)",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b4fb4b4eb3bb62647d851629d62e5f57709e61ed",
          "body": "We did pass multiple extenders to this method in the tests for the\n`Model` extender - now this actually has the desired effect.",
          "is_bot": false,
          "headline": "Tests: Actually accept multiple extenders",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9cecb797bee055c18796b57605da568329069dea",
          "body": "Not needed, and not working without a full Laravel installation.",
          "is_bot": false,
          "headline": "Test setup: Do not use env() helper",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7273de507fae8c0000de4fd1926a2c816e5991f6",
          "body": "- Stop trying to implement Laravel's Application contract, which\n  has no value for us.\n- Stop inheriting from the Container, injecting one works equally\n  well and does not clutter up the interfaces.\n- Inject the Paths collection instead of unwrapping it again, for\n  better encapsulation.\n\nThis brings us one step closer toward upgrading our Laravel\ncomponents (#2055), because we no longer need to adopt the changes\nto the Application contract.",
          "is_bot": false,
          "headline": "Split up Application and Container",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79230246bfc4ff97c26d0ff241f847f21928a901",
          "body": "* Made the console command system extender-friendly\n\n* Added console extender\n\n* Added ConsoleTestCase to integration tests\n\n* Added integration tests for console extender\n\n* Marked event-based console extension system as deprecated\n\n* Moved trimming command output of whitespace into superclass\n\n* Renamed 'add' to 'command'\n\n* Added special processing for laravel commands\n\n* Code style fixes\n\n* More style fixes\n\n* Fixed $this->container",
          "is_bot": false,
          "headline": "Add console extender (#2057)",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "094c45b192b1fc31a36a2f71c22e416ec356c6bc",
          "body": "[ci skip] [skip ci]",
          "is_bot": false,
          "headline": "Apply fixes from StyleCI",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d297bbd644494a02b38978b0b1514e1e7690129",
          "body": "I feel this makes the parameters a bit more clear, does not rely on\ninheritance (you can only inherit from one class, but we might want more\nof these helpers in the future), and has less side effects (e.g. no\ncreation and, more importantly, deletion of users in the database).\n\nRefs #2052.",
          "is_bot": false,
          "headline": "Replace authenticatedRequest() by request() option",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9244753edc2914981ce9f5a08e2e0f4bf23d9a0b",
          "body": null,
          "is_bot": false,
          "headline": "Tests: Extract trait for building requests",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0653d109f44fc6488acd73da6f4083f74e9f13e3",
          "body": null,
          "is_bot": false,
          "headline": "Add Authenticated Test Case utility",
          "author_name": "Alexander Skvortsov",
          "author_login": "askvortsov1",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ed9263e211f62fc82540504dc38d1e516c09c62a",
          "body": null,
          "is_bot": false,
          "headline": "Integration tests: Allow registering extenders",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "65dfe987613e502cbc8cbdc67fb7a761c932a940",
          "body": "This allows sending requests directly in an integration test, without\nhaving *explicitly* booted the app.",
          "is_bot": false,
          "headline": "Integration tests: Add lazy server helper",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "acf74ebcc9cbe0acf87788669d0340f2b7060357",
          "body": "This will allow registering extenders in test scenarios. Previously,\nthis would not have had any effect as the app would have booted already.",
          "is_bot": false,
          "headline": "Integration tests: Create app lazily when needed",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bf138360ac2895b6c8d138089a810ffa5b257d23",
          "body": "Also ensure backwards compatibility for extensions that use the Zend framework but don't explicitly require it.",
          "is_bot": false,
          "headline": "Change Zend namespace to Laminas (#1963)",
          "author_name": "Matt Kilgore",
          "author_login": "tankerkiller125",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6e9974f289b2a38f58051efefd6a898c17bc6cc",
          "body": "[ci skip] [skip ci]",
          "is_bot": false,
          "headline": "Apply fixes from StyleCI",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c74bde8f9e7fd9a7b9227417ad197796d98b87be",
          "body": "- Use provided PhpUnit listener to enforce verification of expectations.\n- Include Mockery's trait to auto-close Mockery after each test.",
          "is_bot": false,
          "headline": "Automatically set up Mockery for unit tests",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "245b7ef62c5322ce428641e8c0ba5d5be0468e45",
          "body": "- Fix base url when is appended with a script filename\r\n- Add default base url http://flarum.local when CLI wizard used\r\n- Remove some code duplication\r\n- Add minor improvement to the UX when CLI wizard used\r\n- Add tests\r\n- Extract base url normalisation into its own value object",
          "is_bot": false,
          "headline": "Normalize Base URL during installation",
          "author_name": "Stefan Totev",
          "author_login": "relax4o",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d22fcd7a48ccd0e4337a0a6861cc4e064cb39947",
          "body": "…s from tempnam when storing files in tmp",
          "is_bot": false,
          "headline": "fixed tests on master, missing views directory and suppressing notice…",
          "author_name": "Daniël Klabbers",
          "author_login": "luceos",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c8df5fd856ce96192e4ce0f6bcac6cc7ca199b42",
          "body": "[ci skip] [skip ci]",
          "is_bot": false,
          "headline": "Apply fixes from StyleCI (#1800)",
          "author_name": "Daniël Klabbers",
          "author_login": "luceos",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "81f7abd982cc08ec64091a9e689752ad3db7a187",
          "body": "…ver you re-run them once smtp is set.\n\nFixed, badly, the test to create users etc caused by the prepareDatabase flushing all settings by default.",
          "is_bot": false,
          "headline": "Using a different setting key now, so that it won't break tests whene…",
          "author_name": "Daniël Klabbers",
          "author_login": "luceos",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "692c18671fb336565edfaaab4c09aceffa1fe9d7",
          "body": "…to notice.\n\nFixed csrf test that assumed an access token allows application access, which is actually api token.\nImproved return type hinting in the StartSession middleware",
          "is_bot": false,
          "headline": "Fixed issue with tmp/storage/views not existing, this caused tmpname …",
          "author_name": "Daniël Klabbers",
          "author_login": "luceos",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e0c6f7425faae9624b44d5a8369c04d630612e9f",
          "body": "Multiple tests now provide JSON request bodies, and others copy cookies\nfrom previous responses, so let's provide convenient helpers for these.",
          "is_bot": false,
          "headline": "Refactor tests to shorten HTTP requests",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "68a8f24e23624c84a854bfcdc30a4562580aacd7",
          "body": "Now that this is possible, make the easy change...",
          "is_bot": false,
          "headline": "Integration tests: Configure vendor path",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3ac90ab7ea0615431e69e6855528674917a4e3e3",
          "body": "This is useful to send HTTP requests (or their PSR-7 equivalents)\nthrough the entire application's middleware stack (instead of\ntalking to specific controllers, which should be considered\nimplementation detail).",
          "is_bot": false,
          "headline": "Integration tests: Memoize request handler as well",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "21a79358ab80947eb7e602dcbc3c5f58c621e328",
          "body": null,
          "is_bot": false,
          "headline": "Integration tests: Fix test setup",
          "author_name": "Franz Liedke",
          "author_login": "franzliedke",
          "committed_at": "2021-01-13T06:21:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 22,
      "commits_last_year": 4,
      "latest_release_at": "2026-07-08T15:55:02Z",
      "latest_release_tag": "v2.0.0-rc.5",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 4,
      "days_since_latest_release": 19,
      "mean_days_between_releases": 48
    },
    "community": {
      "has_readme": false,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 62,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "flarum/testing",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "forum",
            "discussion"
          ],
          "ecosystem": "packagist",
          "matches_repo": true,
          "registry_url": "https://packagist.org/packages/flarum/testing",
          "is_deprecated": false,
          "latest_version": "v2.0.0-rc.5",
          "repository_url": "https://github.com/flarum/testing",
          "versions_count": 25,
          "total_downloads": 391233,
          "dependents_count": 411,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 21717,
          "first_published_at": null,
          "latest_published_at": "2026-04-18T09:09:56Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 101
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 0,
      "watchers": 4,
      "fork_history": {
        "days": [
          {
            "date": "2026-05-06",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "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": 11108,
      "source_files_sampled": 20,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "composer.json",
        "tests/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": 6,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "packagist"
      ],
      "dependencies": [
        {
          "name": "mockery/mockery",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^1.5"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "mockery/mockery",
            "direct": true,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "ext-json",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "flarum/core",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "flarum/testing",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "flarum/testing-tests",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "phpunit/phpunit",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 6,
        "direct_count": 1,
        "indirect_count": 5
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 12,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 1
      },
      "bus_factor": 2,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "askvortsov1",
          "commits": 31,
          "avatar_url": "https://avatars.githubusercontent.com/u/38059171?v=4"
        },
        {
          "type": "User",
          "login": "franzliedke",
          "commits": 23,
          "avatar_url": "https://avatars.githubusercontent.com/u/249125?v=4"
        },
        {
          "type": "User",
          "login": "SychO9",
          "commits": 22,
          "avatar_url": "https://avatars.githubusercontent.com/u/20267363?v=4"
        },
        {
          "type": "User",
          "login": "luceos",
          "commits": 7,
          "avatar_url": "https://avatars.githubusercontent.com/u/504687?v=4"
        },
        {
          "type": "User",
          "login": "imorland",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/16573496?v=4"
        },
        {
          "type": "User",
          "login": "clarkwinkelmann",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/5264300?v=4"
        },
        {
          "type": "User",
          "login": "n-peugnet",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/23519418?v=4"
        },
        {
          "type": "User",
          "login": "StyleCIBot",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/11048387?v=4"
        },
        {
          "type": "User",
          "login": "davwheat",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/7406822?v=4"
        },
        {
          "type": "User",
          "login": "johannsa",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/214734?v=4"
        }
      ],
      "contributors_sampled": 15,
      "top_contributor_share": 0.304
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": true,
      "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": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 13 contributing companies or organizations",
            "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": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0",
            "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": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file 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": "8b4cf12e5a7dbedd7afbc5dc716c9cbc56248442",
        "ran_at": "2026-07-28T15:14:00Z",
        "aggregate_score": 4.8,
        "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-28T13:17:57Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2021-04-20T18:47:07Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/flarum/testing",
    "host": "github.com",
    "name": "testing",
    "owner": "flarum"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 52,
      "inputs": {
        "security": 48,
        "vitality": 64,
        "community": 38,
        "governance": 75,
        "engineering": 27
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 64,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "at_risk",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "commits_last_year": 4,
              "human_commit_share": 0.99,
              "days_since_last_push": 0,
              "active_weeks_last_year": 4
            },
            "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": "4/52 weeks with commits",
                "points": 2.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "4 commits in the last year",
                "points": 6.3,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 92,
            "inputs": {
              "releases_count": 22,
              "latest_release_tag": "v2.0.0-rc.5",
              "releases_from_tags": false,
              "days_since_latest_release": 19,
              "mean_days_between_releases": 48
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "22 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 19 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 19
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~48 days",
                "points": 19.8,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 48
                    }
                  }
                ],
                "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": 4,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 4 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 38,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 3,
            "inputs": {
              "forks": 1,
              "stars": 0,
              "watchers": 4,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "4 watchers",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 52,
            "inputs": {
              "has_readme": false,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": 18,
                "status": "met",
                "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": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "good",
            "name": "Ecosystem adoption (downloads)",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "packages": [
                "flarum/testing"
              ],
              "dependents": 411,
              "ecosystems": "packagist",
              "total_downloads": 391233,
              "monthly_downloads": 21717
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "21,717 downloads/month across packagist",
                "points": 57.8,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 21717,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "411 packages depend on it",
                "points": 17.4,
                "status": "partial",
                "details": [
                  {
                    "code": "registry_dependents",
                    "params": {
                      "count": 411
                    }
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "good",
        "name": "Sustainability & Governance",
        "value": 75,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "moderate",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "bus_factor": 2,
              "contributors_sampled": 15,
              "top_contributor_share": 0.304
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "2 contributor(s) cover half of all commits",
                "points": 25.2,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 30% of commits",
                "points": 15.7,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 30
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "15 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 15
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 13 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 66,
            "inputs": {
              "merged_prs": 12,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 1
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "12/13 decided PRs merged",
                "points": 35.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 12,
                      "decided": 13
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 76,
            "inputs": {
              "followers": 798,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "flarum",
              "public_repos": 53,
              "account_age_days": 4688
            },
            "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": "798 followers of flarum",
                "points": 20.9,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 798,
                      "login": "flarum"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "53 public repos, account ~12 yr old",
                "points": 24.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 53
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 12
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "flarum/testing"
              ],
              "ecosystems": "packagist",
              "any_deprecated": false,
              "min_days_since_publish": 101
            },
            "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 101 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 101
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "25 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 25
                    }
                  }
                ],
                "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": 27,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 38,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": true,
              "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": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "critical",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": false,
              "has_docs_dir": false,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 48,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 48,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 12,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 6,
              "scorecard_aggregate": 4.8
            },
            "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 13 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "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": "update tool detected",
                "points": 7.5,
                "status": "met",
                "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": "1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "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": 21
            },
            "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": "at_risk",
        "name": "AI Readiness",
        "value": 39,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 34,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.636,
              "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": "63 of 99 human commits state their intent (structured subject or explanatory body)",
                "points": 33.9,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 63,
                      "sampled": 99
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "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": 36,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.01,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0.01
            },
            "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": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": 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": "1 of the last 100 commits agent-authored or agent-credited",
                "points": 2,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 1,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "1 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 1,
                      "sampled": 100
                    }
                  }
                ],
                "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": 55,
            "inputs": {
              "primary_language": "PHP",
              "largest_source_bytes": 11108,
              "source_files_sampled": 20,
              "oversized_source_files": 0
            },
            "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": "0/20 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 20,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T15:14:13.222055Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/f/flarum/testing.svg",
  "full_name": "flarum/testing",
  "license_state": "standard",
  "license_spdx": "MIT"
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计Packagist.