Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-28 15:14 UTC

flarum / testing

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

PHPMIT★ 0 estrellas⑂ 1 forkdesde ene 2021Ver en GitHub ↗

flarum/testing tiene un índice de salud de 52 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Sustainability & Governance (75/100) y la más baja, Engineering Quality (27/100). Se actualizó por última vez hoy. 2 personas concentran la mayor parte del trabajo reciente.

52
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

52
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

FlarumOrganización
798 seguidores53 repositorios públicosdesde sept 2013

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
Packagistflarum/testingv2.0.0-rc.521.71725hace 101 díasforumdiscussion

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

64Moderado · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
2.8/36Cadencia de commits — 4/52 semanas con commits
6.3/18Volumen de commits — 4 commits en el último año
0/10OpenSSF Scorecard: Maintained — 1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Datos de entrada utilizados
commits_last_year4
human_commit_share0,99
days_since_last_push0
active_weeks_last_year4
Cómo se puntúa
27/27Publica versiones — 22 versiones publicadas
36/36Recencia de las versiones — última versión hace 19 días
19.8/27Cadencia de publicación — una versión cada ~48 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count22
latest_release_tagv2.0.0-rc.5
releases_from_tagsno
days_since_latest_release19
mean_days_between_releases48
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

38En riesgo · 18% del índice global
Cómo se puntúa
0/60Estrellas — 0 estrellas
0/25Forks — 1 forks
2.7/15Observadores — 4 observadores
Datos de entrada utilizados
forks1
stars0
watchers4
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
0/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
18/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readmeno
has_license
has_contributing
has_issue_templateno
has_code_of_conductno
has_pull_request_template
Cómo se puntúa
57.8/80Descargas mensuales — 21.717 descargas/mes en packagist
17.4/20Dependientes en el registro — 411 paquetes dependen de él
Datos de entrada utilizados
packagesflarum/testing
dependents411
ecosystemspackagist
total_downloads391.233
monthly_downloads21.717

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

75Bueno · 24% del índice global
Cómo se puntúa
25.2/54Factor bus — la mitad de los commits recae en 2 contribuyente(s)
15.7/22.5Distribución de commits — el principal contribuyente firma el 30% de los commits
13.5/13.5Amplitud de contribuyentes — 15 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 13 contributing companies or organizations
Datos de entrada utilizados
bus_factor2
contributors_sampled15
top_contributor_share0,304
Cómo se puntúa
0/46.8Resolución de issues — sin issues o sin datos
35.3/38.3Aceptación de PR — 12/13 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs12
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs1
Excluidos de la puntuación (sin datos o no aplicable): Resolución de issues. Los pesos restantes se han renormalizado.
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
20.9/25Alcance del propietario — 798 seguidores de flarum
24.6/25Trayectoria — 53 repos públicos, cuenta de ~12 años
Datos de entrada utilizados
followers798
owner_typeOrganization
is_verified
owner_loginflarum
public_repos53
account_age_days4688
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en packagist
35/35Recencia de publicación — última publicación hace 101 días
20/20Historial de versiones — 25 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesflarum/testing
ecosystemspackagist
any_deprecatedno
min_days_since_publish101

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

27Crítico · 20% del índice global
Cómo se puntúa
0/24Flujos de trabajo de CI
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
6.4/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_cino
has_tests
has_editorconfig
has_linter_configno
has_precommit_configno
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: CI-Tests. Los pesos restantes se han renormalizado.

Documentación

10Crítico
Cómo se puntúa
0/30README
0/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
0/10Wiki
Datos de entrada utilizados
topics
has_wikino
homepage
has_readmeno
has_docs_dirno
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

48En riesgo · 16% del índice global
Cómo se puntúa
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 — sin datos
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 — sin datos
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — 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 — sin datos
0/5Pinned-Dependencies — sin datos
0/5SAST — no SAST tool detected
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — sin datos
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated12
scorecard_versionv5.5.0
checks_inconclusive6
scorecard_aggregate4,8
Excluidos de la puntuación (sin datos o no aplicable): ci_tests, dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

39En riesgo · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
33.9/40Historial de commits legible — 63 de 99 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,636
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
0/11Configuración de lint / formato
0/11Verificación estática de tipos
0/10Entorno reproducible
2/10Práctica demostrada con agentes — 1 de los últimos 100 commits con autoría o crédito de agente
8/8Mantenimiento automatizado — 1 de los últimos 100 commits son actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — sin datos
Datos de entrada utilizados
has_nixno
has_tests
lockfiles
has_dockerfileno
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0,01
toolchain_manifests
dependency_bot_commit_share0,01
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Pinned-Dependencies. Los pesos restantes se han renormalizado.
Cómo se puntúa
0/45Código verificable por tipos — PHP sin configuración de verificación de tipos
55/55Tamaños de archivo manejables — 0/20 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languagePHP
largest_source_bytes11.108
source_files_sampled20
oversized_source_files0

Datos clave

0estrellas de GitHub
15contribuidores
4commits en los últimos 12 meses
0días desde el último push
22versiones publicadas
2factor bus
0issues abiertas
Packagistecosistemas de paquetes

Advertencias de recopilación de datos

  • No resolved dependencies carried a version and a supported ecosystem

Más detalle

OpenSSF Scorecard 4.8 / 10
4.8agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).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
n/dCI-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
n/dDangerous-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
n/dPackagingpackaging workflow not detected
n/dPinned-Dependenciesno dependencies found
0SASTno SAST tool detected
10Security-Policysecurity policy file detected
n/dSigned-Releasesno releases found
n/dToken-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
Dependencias directas 1
RegistroPaqueteRestricción de versiónManifiesto
Packagistmockery/mockery^1.5composer.json
Todas las dependencias 6

Conjunto completo de dependencias resueltas según el grafo de dependencias de GitHub: 1 paquetes directos y 5 indirectos (transitivos). El cierre transitivo es completo cuando el repositorio incluye un lockfile.

RegistroPaqueteVersiónRelación
Packagistmockery/mockerydirecta
Packagistext-jsonindirecta
Packagistflarum/coreindirecta
Packagistflarum/testingindirecta
Packagistflarum/testing-testsindirecta
Packagistphpunit/phpunitindirecta
Avisos de dependencias sin evaluar

El cotejo de avisos no pudo ejecutarse para este informe: No resolved dependencies carried a version and a supported ecosystem

Informe JSON sin procesar legible por máquina
{
  "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"
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadasPackagist.