Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 2.5.0 · 2026-07-31 00:01 UTC

silvermpx / wse

WSE - Rust-powered WebSocket engine for Python. Up to 5M del/s fan-out, native cluster binary protocol, zero-GIL JWT, E2E encryption

Rust · Python · TypeScriptMIT★ 50 estrellas⑂ 1 forkdesde feb 2026Ver en GitHub ↗
TipoBibliotecacómo se determina

silvermpx/wse tiene un índice de salud de 65 sobre 100, lo que lo sitúa en la banda Bueno. Su puntuación más alta es Vitality (77/100) y la más baja, Sustainability & Governance (37/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

65
global / 100
Bueno

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala estandarizada de 1 a 100. El resultado global parte de su media ponderada, calibrada contra la distribución del registro público para que las bandas tengan significado percentil; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe un límite «En riesgo» de 34.

65
Excepcional93-100El nivel más alto del registro (≈ el 5% superior); cumple prácticamente todos los criterios evaluados
Excelente80-92Sólido en todos los frentes; carencias menores
Bueno65-79Saludable; carencias limitadas y manejables
Moderado50-64Aceptable con carencias notables; se recomienda revisión
Débil35-49Debilidades sustanciales en varias áreas
En riesgo20-34Debilidades significativas; su adopción exige cautela
Crítico1-19Problemas 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.

El resultado global ponderado 60 se calibra a 65 en la escala publicada del índice (calibración del registro 2026-08-02).

Titularidad

silvermpxCuenta personal
7 seguidores3 repositorios públicosdesde ago 2018

Este repositorio pertenece a una cuenta personal. Un proyecto con un único propietario conlleva más riesgo de continuidad que uno respaldado por una organización.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
npmwse-client2.4.127642hace 18 díaswebsocketreacthooksreal-timeeventspubsubencryptionrustzustand
PyPIwse-server2.4.1-39hace 18 díaswebsocketenginereal-timepubsubclusterencryptedrust
PyPIwse-client2.4.1-25hace 18 díasevent-streamingreal-timewebsocketwse

Métricas por categoría

Vitalidad

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

77Bueno · 21% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
4.8/36Cadencia de commits — 7/52 semanas con commits
18/18Volumen de commits — 264 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year264
human_commit_share0,92
days_since_last_push0
active_weeks_last_year7
Cómo se puntúa
27/27Publica versiones — 39 versiones publicadas
36/36Recencia de las versiones — última versión hace 18 días
27/27Cadencia de publicación — una versión cada ~14,8 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count39
latest_release_tagv2.4.1
releases_from_tagsno
days_since_latest_release18
mean_days_between_releases14,8

Comunidad y Adopción

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

46Débil · 17% del índice global
Cómo se puntúa
27.4/60Estrellas — 50 estrellas
0/25Forks — 1 forks
1.7/15Observadores — 3 observadores
Datos de entrada utilizados
forks1
stars50
watchers3
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
18/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
readme_badges
has_contributing
has_issue_templateno
has_code_of_conductno
readme_badge_services
has_pull_request_templateno
Cómo se puntúa
32.6/80Descargas mensuales — 276 descargas/mes en npm, pypi
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packageswse-client, wse-server, wse-client
dependents
ecosystemsnpm, pypi
total_downloads
monthly_downloads276
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

37Débil · 23% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
0/42Resolución de issues — sin issues o sin datos
7.1/30Aceptación de PR — 10/42 PR decididos fusionados
0/13Newcomer PR acceptance — ningún PR de un contribuyente primerizo decidido en 30 d
0/15OpenSSF Scorecard: Code-Review — Found 0/22 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs10
open_issues0
closed_issues0
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio
closed_unmerged_prs32
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
Excluidos de la puntuación (sin datos o no aplicable): Resolución de issues, newcomer_pr_acceptance. Los pesos restantes se han renormalizado.
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
6.5/25Alcance del propietario — 7 seguidores de silvermpx
16.4/25Trayectoria — 3 repos públicos, cuenta de ~7 años
Datos de entrada utilizados
followers7
owner_typeUser
is_verified
owner_loginsilvermpx
public_repos3
account_age_days2919
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 3 paquete(s) en npm, pypi
35/35Recencia de publicación — última publicación hace 18 días
20/20Historial de versiones — 42 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packageswse-client, wse-server, wse-client
ecosystemsnpm, pypi
any_deprecatedno
min_days_since_publish18

Calidad de Ingeniería

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

75Bueno · 19% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno

Documentación

85Excelente
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
10/10Topics — 10 topics
10/10Wiki
Datos de entrada utilizados
topicsencryption, high-performance, jwt, pyo3, python, real-time, rust, tokio, websocket, websocket-server
has_wiki
homepage
has_readme
has_docs_dir
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?

70Bueno · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — sin datos
2.5/2.5CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/22 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
3/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 6
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
3/7.5Vulnerabilities — 6 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate6,3
Excluidos de la puntuación (sin datos o no aplicable): branch_protection. Los pesos restantes se han renormalizado.
Cómo se puntúa
35/35Dependencias directas libres de avisos conocidos — ninguna dependencia directa tiene un aviso conocido
25/25Dependencias indirectas libres de avisos conocidos — ninguna dependencia indirecta tiene un aviso conocido
0/40Sin avisos pendientes — ningún aviso tiene fecha de publicación
Datos de entrada utilizados
sourceosv
advisories0
affected_packages0
assessed_packages2
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
Excluidos de la puntuación (sin datos o no aplicable): Sin avisos pendientes. Los pesos restantes se han renormalizado. Se cotejó el cierre de dependencias en tiempo de ejecución de npm:wse-client@2.4.1 —lo que arrastra la instalación del paquete publicado—: 2 paquetes. No se analiza la alcanzabilidad.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Tiene un peso deliberadamente pequeño (4%): las herramientas para agentes son una señal real de mantenimiento, pero un repositorio sin ninguna puede alcanzar igualmente 100/100.

61Moderado · 4% 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)
40/40Historial de commits legible — 78 de 92 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,848
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
12.6/18Arranque con un solo comando — benchmarks/rust-bench/Cargo.toml, rust/Cargo.toml (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — benchmarks/ts-bench/tsconfig.json, tsconfig.json, wse_server/py.typed
10/10Entorno reproducible — lockfile
0/10Práctica demostrada con agentes — ningún commit con autoría de agente entre los últimos 100
8/8Mantenimiento automatizado — 8 de los últimos 100 commits son actualizaciones automáticas de dependencias
6/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 6
Datos de entrada utilizados
has_nixno
has_tests
lockfilesCargo.lock, package-lock.json
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configsbenchmarks/ts-bench/tsconfig.json, tsconfig.json, wse_server/py.typed
agent_commit_share0
toolchain_manifestsbenchmarks/rust-bench/Cargo.toml, rust/Cargo.toml
dependency_bot_commit_share0,08
Cómo se puntúa
45/45Código verificable por tipos — Rust (tipado estático)
54.2/55Tamaños de archivo manejables — 2/138 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageRust
largest_source_bytes247.962
source_files_sampled138
oversized_source_files2
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
0/20Servidor MCP
40/40Ejemplos ejecutables — examples
Datos de entrada utilizados
example_dirsexamples
has_mcp_signalno
api_schema_files

Datos clave

50estrellas de GitHub
1contribuidores
264commits en los últimos 12 meses
0días desde el último push
39versiones publicadas
1factor bus
0issues abiertas
crates.io, npm, PyPIecosistemas de paquetes

Advertencias de recopilación de datos

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • Could not fetch crates package 'wse-accel' from its registry
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Más detalle

OpenSSF Scorecard 6.3 / 10
6.3agregado

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-31 00:01 UTC

10Binary-Artifactsno binaries found in the repo
n/dBranch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
10CI-Tests8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/22 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
6Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 6
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
4Vulnerabilities6 existing vulnerabilities detected
Dependencias directas 40
RegistroPaqueteRestricción de versiónManifiesto
npm@msgpack/msgpack^3.0.0package.json
npmpako^2.1.0package.json
PyPIwebsockets>=13.0python-client/pyproject.toml
crates.iopyo30.29rust/Cargo.toml
crates.ioserde1.0.228rust/Cargo.toml
crates.ioserde_json1.0.149rust/Cargo.toml
crates.ioflate21.1.9rust/Cargo.toml
crates.iormp-serde1.3.1rust/Cargo.toml
crates.iormpv1.3.1rust/Cargo.toml
crates.iohmac0.12.1rust/Cargo.toml
crates.iosha20.10.9rust/Cargo.toml
crates.iohex0.4rust/Cargo.toml
crates.ioahash0.8.12rust/Cargo.toml
crates.iodashmap6rust/Cargo.toml
crates.ioaes-gcm0.10rust/Cargo.toml
crates.iop2560.13rust/Cargo.toml
crates.iojsonwebtoken10rust/Cargo.toml
crates.iohkdf0.12rust/Cargo.toml
crates.iouuid1.22.0rust/Cargo.toml
crates.iobase640.22rust/Cargo.toml
crates.iochrono0.4.44rust/Cargo.toml
crates.ioregex1.12.3rust/Cargo.toml
crates.iotokio1.50.0rust/Cargo.toml
crates.iotokio-tungstenite0.29.0rust/Cargo.toml
crates.iofutures-util0.3.32rust/Cargo.toml
crates.iocrossbeam-channel0.5rust/Cargo.toml
crates.iotokio-util0.7rust/Cargo.toml
crates.iosocket20.6rust/Cargo.toml
crates.iobytes1rust/Cargo.toml
crates.iomimalloc0.1rust/Cargo.toml
crates.iotokio-rustls0.26rust/Cargo.toml
crates.iorustls0.23rust/Cargo.toml
crates.iorustls-pki-types1rust/Cargo.toml
crates.iozstd0.13rust/Cargo.toml
crates.ioparking_lot0.12rust/Cargo.toml
crates.ioindexmap2rust/Cargo.toml
crates.iozeroize1rust/Cargo.toml
crates.iotracing0.1rust/Cargo.toml
crates.iotracing-subscriber0.3rust/Cargo.toml
crates.ioarc-swap1rust/Cargo.toml
Todas las dependencias no recopilado

No fue posible recopilar el conjunto de dependencias resuelto para este informe: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Avisos de dependencias 0

Instalar npm:wse-client@2.4.1 arrastra 2 paquetes, directos y transitivos: 0 tienen avisos conocidos, de los cuales 0 son dependencias directas.

Ningún aviso conocido afecta a las dependencias evaluadas.

Un aviso significa que la versión registrada en el grafo de dependencias cae dentro del rango afectado de un aviso. No se analiza la alcanzabilidad, y el grafo incluye fijaciones de desarrollo y prueba: un hallazgo puede referirse al utillaje y no al software distribuido.

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [
        "encryption",
        "high-performance",
        "jwt",
        "pyo3",
        "python",
        "real-time",
        "rust",
        "tokio",
        "websocket",
        "websocket-server"
      ],
      "is_fork": false,
      "size_kb": 1735,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Rust": 927723,
        "Python": 364693,
        "TypeScript": 331420
      },
      "pushed_at": "2026-07-31T00:01:07Z",
      "created_at": "2026-02-20T23:23:52Z",
      "owner_type": "User",
      "updated_at": "2026-07-31T00:01:09Z",
      "description": "WSE - Rust-powered WebSocket engine for Python. Up to 5M del/s fan-out, native cluster binary protocol, zero-GIL JWT, E2E encryption",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Rust",
      "significant_languages": [
        "Rust",
        "Python",
        "TypeScript"
      ]
    },
    "owner": {
      "blog": null,
      "name": null,
      "type": "User",
      "login": "silvermpx",
      "company": null,
      "location": "Germany",
      "followers": 7,
      "avatar_url": "https://avatars.githubusercontent.com/u/42042558?v=4",
      "created_at": "2018-08-02T16:53:38Z",
      "is_verified": null,
      "public_repos": 3,
      "account_age_days": 2919
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.4.1",
          "kind": "patch",
          "published_at": "2026-07-12T13:32:32Z"
        },
        {
          "tag": "v2.4.0",
          "kind": "minor",
          "published_at": "2026-06-10T22:30:55Z"
        },
        {
          "tag": "v2.3.2",
          "kind": "patch",
          "published_at": "2026-03-22T21:49:28Z"
        },
        {
          "tag": "v2.3.1",
          "kind": "patch",
          "published_at": "2026-03-08T01:55:17Z"
        },
        {
          "tag": "v2.3.0",
          "kind": "minor",
          "published_at": "2026-03-07T18:57:09Z"
        },
        {
          "tag": "v2.2.1",
          "kind": "patch",
          "published_at": "2026-03-06T23:09:01Z"
        },
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2026-03-06T16:46:59Z"
        },
        {
          "tag": "v2.1.1",
          "kind": "patch",
          "published_at": "2026-03-01T11:06:20Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2026-03-01T04:53:40Z"
        },
        {
          "tag": "v2.0.8",
          "kind": "patch",
          "published_at": "2026-03-01T02:26:00Z"
        },
        {
          "tag": "v2.0.7",
          "kind": "patch",
          "published_at": "2026-02-28T15:47:08Z"
        },
        {
          "tag": "v2.0.6",
          "kind": "patch",
          "published_at": "2026-02-28T15:12:12Z"
        },
        {
          "tag": "v2.0.5",
          "kind": "patch",
          "published_at": "2026-02-28T14:29:44Z"
        },
        {
          "tag": "v2.0.4",
          "kind": "patch",
          "published_at": "2026-02-28T14:21:07Z"
        },
        {
          "tag": "v2.0.3",
          "kind": "patch",
          "published_at": "2026-02-28T14:00:41Z"
        },
        {
          "tag": "v2.0.2",
          "kind": "patch",
          "published_at": "2026-02-28T12:33:13Z"
        },
        {
          "tag": "v2.0.1",
          "kind": "patch",
          "published_at": "2026-02-28T11:55:03Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2026-02-28T05:51:34Z"
        },
        {
          "tag": "v1.4.4",
          "kind": "patch",
          "published_at": "2026-02-25T00:56:09Z"
        },
        {
          "tag": "v1.4.3",
          "kind": "patch",
          "published_at": "2026-02-24T22:52:36Z"
        },
        {
          "tag": "v1.4.1",
          "kind": "patch",
          "published_at": "2026-02-24T12:03:07Z"
        },
        {
          "tag": "v1.4.0",
          "kind": "minor",
          "published_at": "2026-02-24T10:06:07Z"
        },
        {
          "tag": "v1.3.9",
          "kind": "patch",
          "published_at": "2026-02-24T05:22:15Z"
        },
        {
          "tag": "v1.3.8",
          "kind": "patch",
          "published_at": "2026-02-23T23:22:19Z"
        },
        {
          "tag": "v1.3.7",
          "kind": "patch",
          "published_at": "2026-02-23T23:18:46Z"
        },
        {
          "tag": "v1.3.6",
          "kind": "patch",
          "published_at": "2026-02-23T08:00:31Z"
        },
        {
          "tag": "v1.3.4",
          "kind": "patch",
          "published_at": "2026-02-23T07:12:40Z"
        },
        {
          "tag": "v1.3.3",
          "kind": "patch",
          "published_at": "2026-02-23T06:56:21Z"
        },
        {
          "tag": "v1.3.2",
          "kind": "patch",
          "published_at": "2026-02-22T21:50:33Z"
        },
        {
          "tag": "v1.3.1",
          "kind": "patch",
          "published_at": "2026-02-22T21:32:15Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2026-02-22T20:35:38Z"
        },
        {
          "tag": "v1.2.2",
          "kind": "patch",
          "published_at": "2026-02-22T16:18:04Z"
        },
        {
          "tag": "v1.2.1",
          "kind": "patch",
          "published_at": "2026-02-22T02:25:05Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2026-02-22T02:12:04Z"
        },
        {
          "tag": "v1.1.1",
          "kind": "patch",
          "published_at": "2026-02-21T19:48:22Z"
        },
        {
          "tag": "v1.1.0",
          "kind": "minor",
          "published_at": "2026-02-21T20:21:53Z"
        },
        {
          "tag": "v1.0.3",
          "kind": "patch",
          "published_at": "2026-02-20T23:43:46Z"
        },
        {
          "tag": "v1.0.2",
          "kind": "patch",
          "published_at": "2026-02-20T23:32:08Z"
        },
        {
          "tag": "v1.0.1",
          "kind": "patch",
          "published_at": "2026-02-20T23:32:02Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "16836ae51c677eef4fa61c1f73c82580b37173b3",
          "body": "Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.\n- [Release notes](https://github.com/actions/upload-artifact/releases)\n- [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c\n[…]\nirect:production\n  update-type: version-update:semver-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 (#38)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-31T00:01:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fdbf4f6a49347127d67911b5f9aaf53a41fedac1",
          "body": "Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.6.1 to 3.0.2.\n- [Release notes](https://github.com/softprops/action-gh-release/releases)\n- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)\n- [Commits](https://github.com/so\n[…]\nirect:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): bump softprops/action-gh-release from 2.6.1 to 3.0.2 (#39)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-31T00:01:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "01d1adf953195f8636f57fda889a801066663638",
          "body": "Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.0 to 4.1.10.\n- [Release notes](https://github.com/vitest-dev/vitest/releases)\n- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)\n- [Commits](https://github.com/vitest-dev/vitest/commit\n[…]\nrect:development\n  update-type: version-update:semver-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps-dev): bump vitest from 4.1.0 to 4.1.10 (#42)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-31T00:00:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ef0fd9f161b77610dd0781b797d386c30cd6a89e",
          "body": "Bumps [zustand](https://github.com/pmndrs/zustand) from 5.0.12 to 5.0.14.\n- [Release notes](https://github.com/pmndrs/zustand/releases)\n- [Commits](https://github.com/pmndrs/zustand/compare/v5.0.12...v5.0.14)\n\n---\nupdated-dependencies:\n- dependency-name: zustand\n  dependency-version: 5.0.13\n  depend\n[…]\nrect:development\n  update-type: version-update:semver-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps-dev): bump zustand from 5.0.12 to 5.0.14 (#43)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-31T00:00:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "73a1b1f1e30f1de70df8ebd22f77e38c08f9f352",
          "body": "Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 25.5.0 to 26.1.2.\n- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)\n- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)\n\n---\nupdated-depe\n[…]\nrect:development\n  update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps-dev): bump @types/node from 25.5.0 to 26.1.2 (#44)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-31T00:00:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f3263df3746e8762ef132e9bd32d986dd1409146",
          "body": "Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 23869a5bd66c73db3c0ac40331f3206eb23791dc to c19371144df3bb44fab255c43d04cbc2ab54d1c4.\n- [Release notes](https://github.com/swatinem/rust-cache/releases)\n- [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG\n[…]\nb255c43d04cbc2ab54d1c4\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Bump Swatinem/rust-cache (#25)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-30T23:52:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f62b6128335e6fdd329904a696a7a45bedc7f13f",
          "body": "Bumps [PyO3/maturin-action](https://github.com/pyo3/maturin-action) from c0c6d69dce7c061509f7b0f5ea52050b45080fbc to 04ac600d27cdf7a9a280dadf7147097c42b757ad.\n- [Release notes](https://github.com/pyo3/maturin-action/releases)\n- [Commits](https://github.com/pyo3/maturin-action/compare/c0c6d69dce7c061\n[…]\n80dadf7147097c42b757ad\n  dependency-type: direct:production\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Bump PyO3/maturin-action (#26)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-30T23:52:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "178a1b46631c133b7cad4f7d2d6fe01819f5d6de",
          "body": "Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.13.0 to 1.14.0.\n- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)\n- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e...cef22109\n[…]\nirect:production\n  update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Bump pypa/gh-action-pypi-publish from 1.13.0 to 1.14.0 (#34)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-30T23:52:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "868800f28a947665c231147989769bf5a2de0575",
          "body": "The CI installed a floating 'pip install ruff', and ruff 0.16.1\n(released this week) no longer accepts the long-deprecated TCH rule\nselector — it dropped the whole [tool.ruff.lint] select on the floor\nand linted with the 0.16 defaults instead: 66 phantom errors (BLE001,\nS110, FURB, PYI...) from rule\n[…]\nsion the codebase is actually\nclean under, and TCH renamed to its TC alias (valid on both versions)\nso a future unpin does not trip over it again. ruff check + format\nverified clean locally on 0.15.4.",
          "is_bot": false,
          "headline": "ci: pin ruff to 0.15.4 and rename the removed TCH selector to TC",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-07-30T23:47:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cf553377921e60c712a63ba29b1d8c0ae98e6755",
          "body": null,
          "is_bot": false,
          "headline": "release: v2.4.2 — the ts-client gap-detector resync fix",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-07-30T23:44:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf33c7ce80c4da33ca397c16b137b313be129f74",
          "body": "… the store\n\nThe subscription_update ACK stored the server-reported positions only\nin the zustand store — the next-subscribe payload — while the\nEventSequencer's own topicPositions map kept the stale offset. After a\nNotRecovered response every later stamped message read 'gap', was\ndropped, and the w\n[…]\nad and the post-subscribe snapshot covers\nthe skipped window's state. (Found by the SQV live-stack sweep\n2026-07-30 S14-P1 — the server half landed in SQV as the\nsubscription_update inbound protocol.)",
          "is_bot": false,
          "headline": "fix(ts-client): a subscription ACK resyncs the gap detector, not just…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-07-30T23:29:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e2d22ca4f7c27236cd4ed0b7d7be054a9ca16a3d",
          "body": "…efresh\n\nThe v2.4.1 release run tripped on two independent gates that had drifted\nunder the unchanged rust code: cargo-audit now flags pyo3 0.28.2 (OOB read\nin PyList/PyTuple iterators + missing Sync bound on new_closure), fixed\nupstream in 0.29 - source-compatible for this crate; and stable clippy\n\n[…]\n-D warnings (presence.rs match -> ?).\ncargo update refreshes the remaining lock to latest compatible.\nVerified: fmt + clippy -D warnings on 1.97, maturin develop --release,\n38 integration tests green.",
          "is_bot": false,
          "headline": "build(rust): pyo3 0.29 (RUSTSEC-2026-0176/0177) + clippy 1.97 + dep r…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-07-12T13:24:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0ae8508a7a280a82a6491002d2f8d8f019cfe821",
          "body": "Same dead-end class as the TS 2.4.1 fix, two paths here: an OPEN breaker\nraised WSECircuitBreakerError inside the reconnect task and parked the\nclient in ERROR (the breaker's own half-open probe window was unreachable),\nand a rate-limit close never retried a transient condition. Both stay on\nthe backoff schedule now. Auth failures remain terminal by design - this\nclient has no token-refresh callback. Version 2.4.1 across both clients.",
          "is_bot": false,
          "headline": "fix(python-client): open circuit breaker and rate-limit close must retry",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-07-12T13:05:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "22ab0df9e54285bf524d0cff0892cbbbef26a6c3",
          "body": "…estart\n\nFour dead-end paths parked the client in ERROR until a page reload:\nmaxAttempts -1 (the documented infinite contract and the shipped default)\nsilently clamped to 10 attempts (~105s of backoff - shorter than a normal\nredeploy); an OPEN circuit breaker aborted reconnect() without scheduling\nt\n[…]\nped after logging; a 4429 rate-limit close never retried.\n\nAll paths now stay on the capped-backoff retry loop and -1 is honored as\ntruly infinite. Reconnection after any-length downtime is automatic.",
          "is_bot": false,
          "headline": "fix(ts-client): reconnect must never die permanently after a server r…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-07-12T12:53:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f32dbc133db9bafc047d2ebde7950dbe3bdfd3dc",
          "body": "cargo audit (the CI security gate) flagged three advisories in\nrustls-webpki 0.103.10, pulled in transitively via rustls/tokio-rustls\nfor cluster mTLS:\n- RUSTSEC-2026-0098: name constraints for URI names incorrectly accepted\n- RUSTSEC-2026-0099: name constraints accepted for wildcard-name certs\n- RUSTSEC-2026-0104: reachable panic in CRL parsing\n\n0.103.13 fixes all three. Lockfile-only change; verified `cargo check`\nstill builds and `cargo audit` now reports 0 vulnerabilities.",
          "is_bot": false,
          "headline": "deps: bump rustls-webpki 0.103.10 -> 0.103.13 (RUSTSEC fixes)",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T22:13:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d9150bfed96c465ba31f5e5164b4928eb45b9a2b",
          "body": "The deeply-nested decrypted-JSON on_message branch pushed the\nspawn_bounded_callback(&callback_sem, &state, move || {...}) call past\nrustfmt's line width, so `cargo fmt --check` (the CI rust-lint gate) failed.\nApply the canonical multi-line form. No behavior change.",
          "is_bot": false,
          "headline": "rustfmt: wrap spawn_bounded_callback call at the decrypted-JSON site",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T22:13:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "718009b313f84bf23b3f778635e7746b310644ff",
          "body": "Three version sources were missed in the earlier bump and still read 2.3.2,\nso the built artifacts would have shipped under the wrong version:\n- pyproject.toml [project].version -> the maturin-built `wse-server` wheel\n- wse_server/__init__.py __version__ -> the server package's runtime version\n- package-lock.json (root + self entry) -> the `wse-client` npm lockfile\n\nVerified by rebuild: `maturin develop --release` now produces\nwse_server-2.4.0-cp312-abi3 and `wse_server.__version__ == \"2.4.0\"`.",
          "is_bot": false,
          "headline": "release: bump remaining 2.3.2 version strings to 2.4.0",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T21:54:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3acb28d35684115c18079b4c6845d76afa1941e5",
          "body": "Fix module headers that still pointed at the old `client/...` TS path\n(now `ts-client/...`), and drop the removed \"out-of-order buffering\"\ndescription from the event sequencer header. Clarify in WSEEvent that\n`sequence` is the server's global counter (diagnostic only) -- ordering\nand dedup are per-topic via epoch/offset. Comments only; no behavior change.",
          "is_bot": false,
          "headline": "python-client: refresh stale module docstrings",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T21:37:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "69d6df48f290e85c40b14e18f82ad38748f7b5f8",
          "body": "Reconcile every user-facing doc with the v2.4.0 code (verified against\nsource), covering both the prior idempotency/hardening work and this\nrelease's additions.\n\nCHANGELOG: add the inbound callback bound, the real IV-reuse guard, and the\nNetworkMonitor/ConnectionPool client fixes to v2.4.0.\n\nPROTOCO\n[…]\n) idempotent dedup;\ndocument the recovery stamp, the hardening limits, the TS NetworkMonitor change\n(no app-layer packet loss), the missing Python constructor params, and add a\nv2.4 migration section.",
          "is_bot": false,
          "headline": "docs: complete the v2.4.0 documentation pass",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T21:37:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fa4ad6ed84673368174bc731f9e759590064877e",
          "body": "The exported WSE_VERSION constant still read 2.3.2 while every manifest\n(package.json, constants.ts WS_CLIENT_VERSION, the Rust/Python versions)\nis 2.4.0, so consumers reading WSE_VERSION saw the wrong release.",
          "is_bot": false,
          "headline": "ts-client: fix stale WSE_VERSION export (2.3.2 -> 2.4.0)",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T21:36:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03c39df4a221055f8b3e28db5aaa38a9f0e008d1",
          "body": "NetworkMonitor's analyze()/getLatencyStats() were fed nothing: recordLatency\nwas never called, so latencyHistory stayed empty and the monitor reported a\nconstant EXCELLENT / 0-jitter verdict regardless of the real connection. The\npacket counters were equally inert (recordPacketSent never called), an\n[…]\n-counting scaffolding (and the matching useWSE record calls).\n- Trim the unused INetworkMonitor interface to the surviving methods.\n\nNetworkDiagnostics keeps its shape, so the public API is unchanged.",
          "is_bot": false,
          "headline": "ts-client: make NetworkMonitor report real network quality",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T21:04:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b39a1b07192c468038fb827fecc5416f2aaf9939",
          "body": "ConnectionPool carried a private `connectionMetrics` map (and a file-local\nConnectionMetrics interface shadowing the public one in types.ts) that was\nonly ever cleared, never populated -- no call site recorded per-connection\nmessage/byte counts. The pool's live health scoring (recordSuccess/Failure,\nlatency-weighted scores, load balancing) is unaffected. Remove the dead map\nand its local interface; the public types.ts ConnectionMetrics is untouched.",
          "is_bot": false,
          "headline": "ts-client: drop ConnectionPool's dead per-connection metrics map",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T20:49:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "866397858fae2b6e2891f8f3b86828732bfc5af6",
          "body": "usedIVs recorded every IV but never CHECKED the set before encrypting, so\nthe reuse guard was write-only -- it could not have prevented anything. IV\nreuse under one key is catastrophic for AES-GCM (it leaks the GHASH auth\nkey), so consult the set before use: redraw on collision (bounded retries)\nand refuse to encrypt rather than reuse an IV. With a CSPRNG the redraw\neffectively never fires, but the guard is now real. Adds IV_REUSE to the\nSecurityError code union.",
          "is_bot": false,
          "headline": "ts-client: make the AES-GCM IV-reuse guard actually guard",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T20:46:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ad67afc06089e81b4dbc1b44db3dd6a3f72c323",
          "body": "Callback-mode on_message previously spawned an unbounded blocking task\nper inbound frame. A client flooding inbound messages could exhaust the\ntokio blocking pool and contend the GIL, starving every other connection.\n\nAdd a per-server semaphore (MAX_INFLIGHT_CALLBACKS = 256) and route all\nsix inboun\n[…]\nh spawn_bounded_callback.\nWhen the bound is reached the inbound work is SHED and counted in\nrate_limited_total rather than spawning. on_connect (once per connection)\nand outbound paths are unaffected.",
          "is_bot": false,
          "headline": "server: bound concurrent on_message callbacks (inbound flood guard)",
          "author_name": "Silver MPX",
          "author_login": null,
          "committed_at": "2026-06-10T20:40:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b2853dea4345bb96ac4af986806db51a9cac2f95",
          "body": "The per-topic (epoch, offset) idempotency replaced seq-based reordering, leaving\nprocess_sequenced_event / processSequencedEvent, record_sequence / recordSequence,\nthe out-of-order buffer and the expected-sequence cursor dead (the server's `seq`\nis a process-global counter, never a per-connection or\n[…]\n fields (current_sequence, duplicate_window_size, topic_positions).\nThe MessageProcessor's diagnostic recordSequence call is gone too.\n\nPython: 119 tests pass, ruff clean. TS: tsc clean, vitest green.",
          "is_bot": false,
          "headline": "chore(clients): remove the dead seq-based reorder machinery",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T20:28:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c45833b9b3f542f0407d8cacaea725008714fa9a",
          "body": "A received DRAIN frame was only logged; the docs promise that peers \"stop\nforwarding to the draining node\". On DRAIN, clear that peer's remote_interest so\nno new messages are routed to it, while keeping the connection open for in-flight\ndelivery and leaving generation / known_peers / presence intact\n[…]\n(it is not a\ndisconnect, and the peer may resume via a later periodic RESYNC). New\nInterestUpdate::Drain variant carries the signal from peer_reader to the manager.\n\ncluster tests green; clippy clean.",
          "is_bot": false,
          "headline": "cluster: act on DRAIN (lame duck) -- stop routing to a draining peer",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T20:20:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "db50c1c3ff8304402b39994430fcf6a3dc891d92",
          "body": "SUB/UNSUB interest deltas are fanned out best-effort (try_send drops them under\nback-pressure), and there was no reconciliation -- a single dropped frame left a\npeer's view of our interest permanently wrong (a dropped SUB withholds messages\nfor that topic forever; a dropped UNSUB forwards forever). \n[…]\nwriter\nchannel as PING (inner frame; peer_writer adds the length prefix). Both session\npaths (outbound run_peer_session, inbound handler) pass local_topic_refcount.\n\ncluster tests green; clippy clean.",
          "is_bot": false,
          "headline": "cluster: periodic full RESYNC to self-heal dropped SUB/UNSUB interest",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T20:17:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aabafdf6080adbbc33ea1625ee82102104afecbd",
          "body": "…rics trait\n\n- BufferedEvent stored a _sequence field that was never read -- the BTreeMap key\n  already carries the sequence. Drop it.\n- FanoutMetrics was a single-impl trait (ClusterMetrics) used only so\n  peer_dispatch_task could call add_delivered/add_dropped; it was never used as a\n  dyn object or generic bound. Fold the two methods into an inherent impl on\n  ClusterMetrics and delete the trait + its import.\n\nNo behavior change; tests green; clippy clean.",
          "is_bot": false,
          "headline": "chore: remove dead BufferedEvent._sequence + fold vestigial FanoutMet…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:30:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1ff5aa26e484ae095e4b70b7c1e8bf97d8df373a",
          "body": "The send_event dedup set was keyed by event id alone and shared across all\nconnections, so send_event(conn_B, {\"id\": X}) silently returned 0 (dropped) if\nconn_A had already received id X -- a legitimate distinct delivery to a\ndifferent connection was lost. Key the set by (conn_id, id). This also makes the\ndocs' \"per-connection deduplication\" claim actually true.",
          "is_bot": false,
          "headline": "server: dedup send_event per (connection, id), not globally by id",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:26:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "65b83aa9f361678d47683c9665ae9d9b518e7a73",
          "body": "max_connections only counts REGISTERED connections (a connection registers after\nthe WS upgrade + JWT). Without a separate bound, a slowloris that opens sockets\nbut never completes the upgrade -- each held up to the 10s handshake timeout --\nexhausts tasks and file descriptors before any limit fires.\n[…]\ngisters (or on any earlier handshake failure/timeout), so it bounds\nonly not-yet-established connections, not the live total.\n\nTest: HandshakeGuard increments on new, decrements on drop. clippy clean.",
          "is_bot": false,
          "headline": "server: cap concurrent pre-handshake connections (slowloris)",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:23:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "26580dc0b12902dccc1fb784c46145dd2e59fc54",
          "body": "A client could send client_hello repeatedly; each one with features.encryption\nre-ran derive_connection_key and overwrote the connection's AES cipher. That\nmade any in-flight message encrypted with the previous key undecryptable on the\nclient, and each hello forced a fresh P-256 keygen + ECDH -- a cheap asymmetric-\ncrypto DoS amplifier. Skip the derivation (keep the existing cipher) when the\nconnection already has one.",
          "is_bot": false,
          "headline": "server: client_hello key exchange is once-only (no mid-session re-key)",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:16:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "053002a1e5456bab14d5730b55305c2c989822d3",
          "body": "- decrypt_inbound split the 12-byte IV with split_at(12) + try_into().expect()\n  on attacker-controlled bytes. Use split_first_chunk::<12>() so the (unreachable\n  given the >=28 length check) short case is an Err, not a panic on the hot path.\n- The tungstenite accept_hdr callback's #[allow(clippy::result_large_err)] is now\n  #[expect(..., reason = ...)] per project policy (the Err type is fixed by the\n  third-party callback signature and cannot be boxed).",
          "is_bot": false,
          "headline": "server: non-panicking IV split in decrypt + #[expect] over #[allow]",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:14:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "27319462147b8b20b2b7395dada15e3c768df258",
          "body": "… interest\n\n- subscribe_connection drops any topic containing an ASCII control character at\n  the single chokepoint where topics enter local interest. The cluster RESYNC\n  wire format newline-delimits topics, so a '\\n' in a topic name was decoded by\n  a peer as two separate interest entries -- corru\n[…]\nT_PER_PEER so\n  a buggy or compromised (but authenticated) peer streaming distinct SUB frames\n  cannot grow it without limit; a re-sub of an existing topic always succeeds.\n\nTests green; clippy clean.",
          "is_bot": false,
          "headline": "cluster: reject control-char topics (RESYNC injection) + cap per-peer…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:12:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ea8511354736373c9d4b03700ae7e3eaed163d25",
          "body": "… (DoS)\n\n- encode_presence_update gained the MAX_FRAME_SIZE guard every other encoder\n  already has. presence_max_data_size is operator-configurable; a large presence\n  update could otherwise emit a frame the receiving peer_reader rejects (>1 MB),\n  disconnecting and flapping the peer on ordinary pr\n[…]\nSTER_PEERS, so a declared u16 count (up to 65535) cannot force a large\n  transient allocation and a 1 MB frame of tiny entries cannot expand into a\n  huge addr Vec.\n\ncluster tests green; clippy clean.",
          "is_bot": false,
          "headline": "cluster: frame-size guard on presence updates + bound PeerList decode…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:10:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7ed439968fdd37d70c1240c67948cb189b31d156",
          "body": "…READMEs\n\nThe \"Event Sequencing\" sections still described the old seq-based out-of-order\nbuffering, which was replaced by per-topic (epoch, offset) dedup + gap-triggered\nrecovery. Update both client READMEs to the current model: a duplicate (offset\nalready seen on the same epoch) is dropped, an offs\n[…]\nepoch change re-baselines, and positions survive\nreconnects; seq is diagnostic-only. Add the tp/e/o recovery-stamp fields to the\nPython WSEEvent doc and note the stamp in the TS wire-protocol summary.",
          "is_bot": false,
          "headline": "docs(clients): document the tp/e/o idempotent-delivery model in both …",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:04:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "26acf96668cb037f650559f0512e409e04041644",
          "body": "… to v2.4.0\n\n- PROTOCOL.md: document the per-message recovery stamp (tp = topic, e = epoch\n  8-hex, o = offset) -- the wire fields clients dedupe + recover on -- plus the\n  per-topic dedup / gap / recover logic and the cluster-trailer cross-reference.\n- Fix HKDF parameters across README / PROTOCOL /\n[…]\nmarising the hardening pass. Bump 2.3.2 -> 2.4.0\n  across rust/Cargo.toml, package.json, python-client, ts-client -- the new\n  tp/e/o fields are optional/additive, so a backward-compatible minor bump.",
          "is_bot": false,
          "headline": "docs: document tp/e/o recovery stamp; fix HKDF/epoch/path drift; bump…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T19:01:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "deb4c3e7b521a7ae88a8c0a476305265953c71f5",
          "body": "…t guard)\n\nWhen two nodes discover each other they BOTH dial, so two TCP links exist per\npair. Each node deduped locally (connected_instances.entry), and in ~half of\nraces kept opposite links -> both torn down, both reconnect, flapping (wasted\nhandshakes, transient split membership).\n\ncluster_link_s\n[…]\ntimization; correctness is covered here.)\n\nTest: lower-dialer survives, higher yields, equal rejected, and exactly one of\nA->B / B->A survives for any distinct pair. 145 lib tests green; clippy clean.",
          "is_bot": false,
          "headline": "cluster: deterministic duplicate-connection tiebreaker (+ self-connec…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T18:55:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a4d4810e8e9123a8423c86dd4feca1863403bac",
          "body": "…th python)\n\nConsume the server's per-message recovery stamp (tp/e/o) and drive dedup /\nordering / recovery by per-topic (epoch, offset), mirroring the Python client.\n\n- types: WSMessage gains tp/e/o (parsed automatically -- the wire frame is\n  returned verbatim from JSON.parse).\n- EventSequencer: t\n[…]\n- a replayed message keeps its original (old)\n  ts and would otherwise be dropped, silently breaking recovery.\n\nTest: 6 checkTopicStamp cases (vitest) parallel to the Python suite. tsc --noEmit\nclean.",
          "is_bot": false,
          "headline": "client(ts): idempotent (epoch,offset) dedup + gap recovery (parity wi…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T18:06:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "87d777937828c14321c39d4b2fe52f3431281408",
          "body": "…connect\n\nTwo reconnect-robustness bugs:\n\n1. Permanent lockout. store metric reconnectCount gates canReconnect() (blocks at\n   maxReconnectAttempts=10), but it was incremented on every SUCCESSFUL reconnect\n   and never reset -- so a long-lived flaky-network session that reconnected 10\n   times was l\n[…]\nen available for reconnection' every\n   time. The sentinel is now preserved for cookie auth (only a real bearer token\n   is cleared); the HTTP-only cookie is refreshed server-side. tsc --noEmit clean.",
          "is_bot": false,
          "headline": "client(ts): fix reconnect lockout after 10 successes + cookie-auth re…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T18:00:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ad97948fe4e491725b2a599653de32f141ee9d7a",
          "body": "SecurityManager.initialize generated a standalone RANDOM AES key when\nencryption was enabled, and the send path gated on isEncryptionEnabled() (true\nimmediately). So client_hello -- sent before any key exchange -- was encrypted\nwith a key the server never had. The server drops E:-frames with no regi\n[…]\ned; the send path gates on it, so client_hello goes plaintext\n(still carrying the client's ECDH public key via isEncryptionEnabled()) and only\npost-exchange messages are encrypted. tsc --noEmit clean.",
          "is_bot": false,
          "headline": "client(ts): don't encrypt before ECDH -- fixes E2E handshake deadlock",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:56:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dfcb39930352108653f61e99685716097e2c0459",
          "body": "…seq-reorder\n\nConsume the server's new per-message recovery stamp (tp/e/o) and make dedup /\nordering / recovery driven by per-topic (epoch, offset) instead of the global\n`seq`.\n\n- types/protocol: WSEEvent gains topic/epoch/offset; the codec parses tp/e/o\n  (with topic/epoch/offset long-name fallback\n[…]\ntual gap.\n\nTests: 6 check_topic_stamp cases (new/in-order/duplicate/gap-no-advance/epoch-\nreset/full-reset); server_hello test updated to the real nested wire shape. 124\nclient tests pass; ruff clean.",
          "is_bot": false,
          "headline": "client(py): idempotent (epoch,offset) dedup + recovery; drop unsound …",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:52:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "84a316c96a3fa95d097e872b8854fd682def3a3f",
          "body": "…nent zombie\n\n_heartbeat_loop calls `await self._force_reconnect()` on idle timeout, and\n_force_reconnect cancel-and-awaited self._heartbeat_task -- i.e. the CURRENTLY\nrunning task. Cancelling the current task makes the very next await (the\nasyncio.gather over the cancelled tasks) raise CancelledErr\n[…]\nnd-awaits the others, so the reconnect is\nalways scheduled. Regression test drives _force_reconnect from a task set as the\nheartbeat task and asserts the reconnect is scheduled. 118 client tests pass.",
          "is_bot": false,
          "headline": "client(py): fix idle-timeout reconnect cancelling itself into a perma…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:43:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a0a8c07e9b13f5f3c05f0a202c8697c2babfcdb3",
          "body": "…ecovery replay\n\nTwo coupled fixes sharing one root cause -- recovery stored PRE-FRAMED PLAINTEXT\nand framed the message before its offset was known:\n\n1. Idempotency stamping (was absent). Topic broadcasts now carry their recovery\n   coordinates as top-level JSON fields tp (topic), e (epoch, 8-hex),\n[…]\n lands.\n\nTests: push_stamped offset==storage invariant + recover returns stamped bytes;\nstamp_recovery_fields injection / empty-object / quote-escaping / non-object.\n144 lib tests green; clippy clean.",
          "is_bot": false,
          "headline": "wse: per-message (epoch,offset) stamping + per-connection encrypted r…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:38:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "60437b78ad96266926f141aac558f338a84a95cc",
          "body": "… leak)\n\nsubscribe_with_recovery called subscribe_connection (which filters the LIVE\nsubscription through the connection's topic ACL) but then ran the recovery loop\nover the ORIGINAL, unfiltered topic list. An authenticated connection scoped to\ne.g. user:SELF:* could pass user:OTHER:private: the liv\n[…]\nred the connection stays unrestricted (the\nfail-open default is tracked as a separate finding). Integration is covered by\nthe pytest suite against the live server; is_allowed has unit tests in jwt.rs.",
          "is_bot": false,
          "headline": "wse: fail-closed topic ACL on the recovery path (cross-tenant history…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:24:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "675ae0aced87930e9fe0f0f2eddce3a1d44b1a16",
          "body": "…pped\n\nencode_presence_full drops any frame over MAX_FRAME_SIZE, so a node hosting more\npresence than fits in one frame sent NO initial full-state to a joining peer --\nthat peer only ever learned the node's users from subsequent deltas, never the\npre-existing set.\n\nserialize_full_state_chunked split\n[…]\ns one chunk with all users; a tiny budget yields\nmultiple chunks whose union still covers every user, each independently valid\nJSON. 141 lib tests green; clippy clean. Completes the presence redesign.",
          "is_bot": false,
          "headline": "presence: chunk the full-state sync so a busy node isn't silently ski…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:11:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "363750e9374d5355f9b4c67ad57299e3f5924336",
          "body": "…sconnect\n\nThree interlocked cluster-presence correctness bugs:\n\n1. Per-origin sentinels. A remote user was tracked by a single global\n   __remote__{user_id} sentinel, added only when the entry had no connections.\n   If a user was present on two peers only the first created a sentinel, and a\n   leav\n[…]\nections) stay exact across all three paths. Tests:\nper-origin survival, LWW stale-leave ignore, purge removes only that peer's\nghosts, purge keeps a dual-homed user. 140 lib tests green; clippy clean.",
          "is_bot": false,
          "headline": "presence: per-origin sentinels + LWW leave + ghost cleanup on peer di…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T17:05:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2e1351cb187f9defb217cc649d92b6caf493b878",
          "body": "The JWT secret was already wrapped in Zeroizing, but symmetric key material was\nleft on the stack to be dropped un-wiped: rust_ecdh_generate_keypair's\nserialized private scalar, rust_ecdh_derive_shared_secret's derived AES-256 key,\nand derive_connection_key's per-connection AES key. Un-wiped key byt\n[…]\nnt `&*` deref in the ECDH\ntest (clippy borrow_deref_ref).\n\n136 lib tests green; clippy clean except the pre-existing cluster.rs:2315\nwarning, which the upcoming presence ghost-cleanup change resolves.",
          "is_bot": false,
          "headline": "security: zeroize derived AES keys and the serialized ECDH scalar",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T16:55:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "53686d85a4b3fa4a20cdad91cd9d4eb19716d221",
          "body": "… buffer\n\nRustEventSequencer::cleanup() removed a topic's expected-sequence cursor\n(expected_sequences) whenever its reorder buffer happened to be empty -- which\nis the HEALTHY in-order case, not idleness. Dropping the cursor reset gap\ndetection: the next event was treated as a brand-new topic start\n[…]\nly. reset_sequence clears last_activity too.\n\nTests: an active in-order topic with an empty buffer keeps its cursor; a topic\nidle past the TTL is evicted so the maps stay bounded. 136 lib tests green.",
          "is_bot": false,
          "headline": "sequencer: keep the per-topic ordering cursor across an empty reorder…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T16:48:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "810d07b21341356943cd021e6bb7aecf24c13a06",
          "body": "…erflow DoS)\n\nrmpv::decode::read_value is recursive-descent with no depth limit, so a client\non a ?format=msgpack connection could send a ~1MB frame of repeated 0x91\n(fixarray-len-1) markers, drive ~10^6 levels of recursion, and overflow the\nthread stack -> SIGABRT of the whole process (taking every\n[…]\n.rs).\n\nTests: shallow values pass, exactly-64 passes, 65 and a 100k-deep bomb are\nrejected, truncated/reserved/empty are rejected, guarded decode matches raw\nrmpv for valid input. 134 lib tests green.",
          "is_bot": false,
          "headline": "msgpack: reject over-deep inbound frames before rmpv decode (stack-ov…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T16:38:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c226a1317bb4afc2756fe0a86514fcb372046404",
          "body": "Two descending sort_unstable_by(|a,b| b.1.cmp(&a.1)) sorts (the Prometheus\ntop-50 per-topic message export and its test) tripped clippy's\nunnecessary_sort_by. Equal message counts have no meaningful order in a\ntop-N export, so the key form is equivalent; Reverse preserves the\ndescending order. No behavior change.",
          "is_bot": false,
          "headline": "clippy: use sort_unstable_by_key(Reverse) for metrics top-N",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T16:30:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e92d66cbc28a069a3f49e1df6d3951d0e3714ac6",
          "body": "…ble OOM\n\npeer_reader decoded every inbound MSG straight onto an UNBOUNDED dispatch\nchannel (mpsc::unbounded_channel) with a non-blocking send. The comment\nclaimed peer channels were \"bounded (10K) ... messages dropped\", but that only\nheld for the outbound writer (peer_write_tx); the inbound data pl\n[…]\n\nsignatures (peer_reader, peer_dispatch_task) move to the bounded channel.\n\nTest: dispatch_channel_is_bounded_and_sheds_when_full pins that try_send fails\npast the cap. cluster 53 / recovery 18 green.",
          "is_bot": false,
          "headline": "cluster: bound the inbound MSG dispatch queue to stop remote-triggera…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-06-10T16:28:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "529a08234ed15c7512bb449f69f5e76dde2bd046",
          "body": "Transitive dep via jsonwebtoken. WSE only uses JWT signature\nverification, never RSA decryption. Not exploitable. No upstream fix.",
          "is_bot": false,
          "headline": "CI: ignore RUSTSEC-2023-0071 (rsa Marvin Attack)",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T21:38:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e6efc2c38528cb02269cb6eeff22162ecae5ac3",
          "body": "Rust: tokio-tungstenite 0.28->0.29, cargo update (11 crates)\nnpm: zustand 5.0.12, @types/node 25.5.0, vitest 4.1.0\nCI: all actions bumped to latest node24 versions\nCI: added cargo-audit + npm audit security scan job",
          "is_bot": false,
          "headline": "Update all deps, CI actions to node24, add security audit",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T21:32:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0a353c0d887808bcf990af1862318c35b79f53f",
          "body": "Tests create AsyncWSEClient without calling connect(), so _event_queue\nand _server_ready_event were None after lazy init change.",
          "is_bot": false,
          "headline": "Fix test_client.py: initialize lazy asyncio primitives in test fixture",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T21:11:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d7ee36bdfc9e3cc8b50c54aee673f89c210d76a",
          "body": "Extract RustWSEServer::new body into build() with grouped param structs.\nExtract connect_cluster body into connect_cluster_inner with tuple grouping.\nExtract jwt_decode logic into jwt_decode_with_rotation helper.\n\n3 remaining #[expect(clippy::too_many_arguments)] are all PyO3 boundary\nfunctions where param count = Python API surface. #[expect] documents the\nreason and warns if the lint stops firing.",
          "is_bot": false,
          "headline": "Replace #[allow] with #[expect] for PyO3 boundary functions",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T21:07:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "88b0e3b9d18f759dd662969c324a671520e21a45",
          "body": "Only PyO3 boundary functions retain #[allow(clippy::too_many_arguments)]\n(3 remaining, down from 10).",
          "is_bot": false,
          "headline": "Refactor SharedState::new: SharedStateConfig struct replaces 14 args",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T18:47:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fbb51d1142550a5ab715fab63435e8dc6e66d64c",
          "body": "All 6 cluster peer functions now take 7 or fewer arguments.\nRemoved all #[allow(clippy::too_many_arguments)] from cluster.rs.\nNet -170 lines.",
          "is_bot": false,
          "headline": "Refactor cluster functions: ClusterContext struct replaces 15+ args",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T17:51:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23f39b2fa5129d33e0ef0de2e1053f0e162bc6ba",
          "body": "Security: fix HKDF salt/IKM swap (RFC 5869), add 10s handshake timeout,\nwarn on plaintext cluster connections, add max_subscriptions_per_connection,\nzeroize JWT secrets on drop.\n\nBugs: fix pending counter underflow (saturating_sub), fix PEER_SESSION_GENERATION\nordering (Relaxed -> AcqRel), fix recov\n[…]\nady\non reconnect.\n\nTS client: per-instance circuit breaker interval, configurable event throttle,\nfix interval leak on unmount-remount.\n\nDead code cleanup: remove all #[allow(dead_code)] suppressions.",
          "is_bot": false,
          "headline": "v2.3.2 -- Security fixes, bug fixes, client hardening",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-22T16:16:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7b87a40ecf27eab1c059e9eaf65da65944556550",
          "body": "…t everywhere",
          "is_bot": false,
          "headline": "Rename client/ to ts-client/, replace TypeScript client with TS clien…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-08T02:12:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f0b1883327b08e3723720580a432ef18240450d6",
          "body": "- Added /// docstrings to all 32 PyO3 methods (IDE hints + help())\n- Added prometheus_metrics() to .pyi type stub\n- Fixed drain_inbound() docstring (missing presence_join/presence_leave)\n- Bumped all packages to 2.3.1 (server, Python client, TS client)",
          "is_bot": false,
          "headline": "v2.3.1 -- PyO3 docstrings, .pyi stub fix, version sync",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-08T01:51:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "453583cc56f4c6271a26c6b36004553dbc3f7c5b",
          "body": null,
          "is_bot": false,
          "headline": "Fix drain() default values in docs (timeout=30, close_reason empty)",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-07T18:55:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bf42db9d492161c82577c8a95df07fd54c711c6",
          "body": null,
          "is_bot": false,
          "headline": "Fix cargo fmt in drain timeout handler",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-07T18:51:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92898a07e1c7caa5c378e047175bed87ebe5df84",
          "body": "… cluster topology API\n\nCluster phases:\n- Replicated recovery with crdt-style merge and cross-node RESYNC\n- Topic ACL with glob pattern matching (allow/deny per connection)\n- Graceful drain with close code 4300 and cluster peer notification\n- Queue groups with round-robin dispatch and cluster-aware \n[…]\nonsumer_drops\n\nTesting:\n- 5 new battle tests (queue-groups, topic-acl, drain, metrics, topology)\n- Fixed battle-presence Binary frame handling\n- 128 Rust unit tests passing, 15/15 battle tests passing",
          "is_bot": false,
          "headline": "v2.3.0 -- Queue groups, topic ACL, graceful drain, per-topic metrics,…",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-07T18:47:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bce45678cbd8b4348254f7044c823fb8bd651baf",
          "body": "Test JWT secret was 31 bytes, now 32+ to satisfy RFC 7518 min key check.",
          "is_bot": false,
          "headline": "Fix test secret length for 32-byte HS256 minimum",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-06T23:05:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e48b47213ae64c09ccc5e545401dac507ce4edd3",
          "body": "RS256 + ES256 asymmetric JWT algorithms via jsonwebtoken v10 crate.\nReplaces hand-rolled HMAC crypto. Algorithm confusion prevention,\nkey rotation for all algorithms, kid validation, min key enforcement.\n\nJWT hardening: 8KB token size limit, 30s clock skew, empty sub\nrejection, explicit error mapping for RSA/ECDSA failures, auth\nclose code 4401, eager PEM validation at startup.",
          "is_bot": false,
          "headline": "v2.2.1 -- RS256/ES256 JWT support, JWT hardening, review fixes",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-06T22:58:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f07786b50993dbc15859ff500ff06e4c51c458f2",
          "body": null,
          "is_bot": false,
          "headline": "Suppress result_large_err clippy lint on WS upgrade closure",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-06T16:41:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67fe1d43609b835e4957384e87b09eedde857fc8",
          "body": "OOM protection: per-connection byte-based backpressure (max_outbound_queue_bytes),\nslow consumer drops counter, two-phase zombie detection with 10s grace.\n\nFan-out rewrite: direct buffer writes (Mutex<BytesMut> + Notify) bypass mpsc\nchannels. Connection handles stored in topic subscriptions (no Hash\n[…]\n.md index, BENCHMARKS_FANOUT.md v2.2.0\nsections, INTEGRATION.md metrics, DEPLOYMENT.md alerts.\n\nDependencies: tokio 1.50, chrono 0.4.44, uuid 1.22, rmpv 1.3.1.\n\n81/81 tests pass, zero clippy warnings.",
          "is_bot": false,
          "headline": "v2.2.0 -- OOM protection, direct buffer fan-out, pre-release hardening",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-06T16:14:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a71780073412d78a2d45fe8fd6676da48d72f0c3",
          "body": "- Move fetch_sub after write completes (not at dequeue) for accurate\n  backpressure accounting, matching NATS/Centrifugo semantics\n- Hoist raw_slices Vec out of write task loop to avoid per-batch alloc\n- Track encrypt_outbound failures in slow_consumer_drops counter\n- Clean stale entries from suspected_slow set on disconnected connections\n- Pre-bake \"c\" field in benchmark to skip inject_category overhead",
          "is_bot": false,
          "headline": "Code review fixes: accurate backpressure, hoist write allocs, cleanup",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T21:59:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "27d5ccd232eab3c319c41e164ac86c72547ceba3",
          "body": "The timestamp-based throughput gating (only count messages where ts_us\n>= measurement_start_us) doesn't work with high-rate publishers. At\n400K+ msg/s, the server's per-connection channel builds a backlog\nfaster than the 2s drain warmup can clear. All messages during\nmeasurement end up \"stale\" (time\n[…]\nreal delivery.\n\nKeep timestamp gating only for latency recording: only measure\nlatency for messages published after measurement started, since\nbacklogged messages would show artificially high latency.",
          "is_bot": false,
          "headline": "Revert benchmark timestamp gating -- incompatible with pipeline backlog",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T21:04:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "673d0c61859d9e789c84cbb159aeb21e359a8ebf",
          "body": "Convert per-connection backpressure from message-count to byte-count\ntracking (industry standard per NATS/Centrifugo). Add ws_frame_size()\nhelper, rename max_outbound_queue_size -> max_outbound_queue_bytes\n(default 16MB), update all 40+ fetch_add/fetch_sub call sites.\n\nFix benchmark throughput infla\n[…]\n_received/local_bytes\non measurement_start_us timestamp so stale warmup messages aren't\ncounted. Fix cumulative Prometheus drops counter by capturing\nbefore/after delta per tier in all 3 fanout tests.",
          "is_bot": false,
          "headline": "Byte-based OOM protection, fix benchmark measurement accuracy",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T20:29:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4dcae55e06615fd9db6889d64c13d9224cd760b4",
          "body": "- Move pending.fetch_add() BEFORE tx.send() at all 17+ call sites\n  to prevent counter underflow when write task drains between send\n  and increment. Decrement on send failure.\n- Add continue after suspected_slow.insert() in zombie detector\n  to avoid sending ping to connections with full queues.\n- \n[…]\ne Vec allocation + N Arc clones in BroadcastText/BroadcastBytes\n  fast path: new fanout_all_connections() does fanout directly from\n  connections map while holding the read lock (send is synchronous).",
          "is_bot": false,
          "headline": "Fix TOCTOU race, zombie detector bug, optimize broadcast hot path",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T19:58:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "83645d4100a66f13f39856d46e4e2b731a328315",
          "body": "Bench server exposes Prometheus metrics via HTTP on port+1000.\nRust benchmark queries wse_slow_consumer_drops_total after each tier\nand prints the result. Covers single-node, cluster, and cluster-tls tests.",
          "is_bot": false,
          "headline": "Add slow_consumer_drops query to fanout benchmarks",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T18:45:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "29ed04f0a0c9c376cf612789b842bb8729f0340c",
          "body": "Per-connection outbound channels stay unbounded (no semaphore overhead),\nbut each connection tracks pending message count via Arc<AtomicUsize>\nwith Relaxed ordering (~3ns per send vs ~20ns for tokio bounded).\n\nFan-out hot path checks pending >= max_outbound_queue_size before send,\ndrops message if f\n[…]\n\nreconnect gaps.\n\nNew constructor param: max_outbound_queue_size (default 8192)\nNew Prometheus metric: wse_slow_consumer_drops_total\nCluster paths propagate limits through all peer dispatch functions.",
          "is_bot": false,
          "headline": "OOM protection: unbounded channels + AtomicUsize pending counter",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T18:35:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9f4693334699ff88f3e577ea48b575ce5e9136d5",
          "body": "Replace 2s sleep warmup with active drain loop that reads and discards\nall buffered messages. Add timestamp gating so only messages published\nafter measurement_start_us count toward latency (stale messages from\ninter-tier publishing still count for throughput).\n\nFixes invalid 37-250s latency numbers in benchmark output.",
          "is_bot": false,
          "headline": "Fix benchmark latency: active drain warmup + timestamp gating",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T18:01:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ddd02724bf0c9fc23aaf60604450d1e75132178",
          "body": "Add constructor parameters for rate_limit_capacity, rate_limit_refill,\nmax_message_size, ping_interval, idle_timeout with sensible defaults.\nRemove hardcoded constants and .min(131072) clamp on inbound queue.",
          "is_bot": false,
          "headline": "Make hardcoded server params configurable",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-02T13:18:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dd053e600884d6c4fc1c97f9115b95c8d09d51f5",
          "body": "- Fix Python client to read c field from JSON (not just wire prefix)\n- Update all docs, examples, tests, benchmarks to use c field format\n- Remove all remaining WSE{ wire prefix usage from non-receive paths",
          "is_bot": false,
          "headline": "v2.1.1 - Fix c field consistency across docs, tests, Python client",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T11:04:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4cf5e7f36b67251fe0812ba667146dfe1a7ffca",
          "body": "- Fix INTEGRATION.md: send/broadcast examples, presence events, wire format table\n- Fix SECURITY.md: add c field to signed message example\n- Fix README.md: wire protocol description\n- Fix integration tests: replace all WSE{ prefix with c field JSON\n- Fix bench_battle_server: replace WSE prefix in send() calls",
          "is_bot": false,
          "headline": "Update remaining docs, tests, benchmarks to use c field format",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T10:57:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "774af27ecea21da7a06cfe26be640de8b7f84d1d",
          "body": "- Update all PROTOCOL.md JSON examples from wire prefix to c field format\n- Fix Python client _parsed_to_event to read c field from JSON\n- Add c/v fields to examples/ send() calls (standalone_basic, standalone_recovery)\n- Remove old WSE wire prefix from standalone_recovery send()\n- Update wire protocol descriptions in client and python-client READMEs",
          "is_bot": false,
          "headline": "Update protocol examples and fix Python client c field parsing",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T05:21:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc670107f20bc19bf46c5417019d8862a91cd481",
          "body": null,
          "is_bot": false,
          "headline": "v2.1.0 - Prometheus metrics, wire prefix removal, message category field",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T04:49:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67d588cb2ee9e2dd7042cecd142b24a7ab1062af",
          "body": null,
          "is_bot": false,
          "headline": "v2.1.0 - Prometheus metrics, wire prefix removal, message category field",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T04:39:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03ffbe6506735922b213ad718c9d10873355b496",
          "body": null,
          "is_bot": false,
          "headline": "Update deployment docs with Prometheus, fix missed test prefix strip",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T04:37:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1e29aed07610364f6bac1f98996dc6514b4bcc4a",
          "body": "8 new atomic counters (messages in/out, bytes in/out, connections\naccepted/rejected, auth failures, rate limited) plus prometheus_metrics()\nPyO3 method returning text exposition format. 25 metrics total including\nexisting cluster, recovery, and presence stats.",
          "is_bot": false,
          "headline": "Add Prometheus metrics endpoint",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T04:31:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba0d67ce9b6ba17e880d224e460dfad79770a6dc",
          "body": "- Remove WSE{/S{/U{ wire prefix from all outbound messages\n- Add \"c\" field (category) as first field in JSON: {\"c\":\"U\",\"t\":\"bar_update\",...}\n- Field order: c first, t second, v last for DevTools readability\n- All messages now have c field (was missing on non-snapshot events)\n- Rename _msg_cat to c across server, transformer, TS and Python clients\n- Rust auto-injects c for broadcast_local/broadcast/broadcast_all\n- Backwards-compatible: clients still parse incoming wire prefix",
          "is_bot": false,
          "headline": "Replace wire prefix with c field inside JSON",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T03:59:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "289e7e3b0042ad10ea22b9b2736d6fbf42891eb3",
          "body": "- Add jwt_cookie_name parameter to RustWSEServer (default: \"access_token\")\n- Use configured cookie name instead of hardcoded value in auth\n- Add TS/React client file structure and provider setup guide\n- Add publishing patterns docs (Pattern A: publisher-based, Pattern B: event sourcing)\n- Update JWT auth docs across PROTOCOL.md, SECURITY.md, INTEGRATION.md, DEPLOYMENT.md",
          "is_bot": false,
          "headline": "v2.0.8 - Configurable JWT cookie name, publishing patterns docs",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-03-01T02:22:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a645ab391dc9231a8c032befbc1d6ef683e9689",
          "body": "Cluster protocol:\n- Only forward PeerAnnounce for newly discovered peers (dedup)\n- Remove gossip-discovered peers from known_peers on disconnect\n- Guard static peers from known_peers removal (prevent duplicate tasks)",
          "is_bot": false,
          "headline": "v2.0.7 - Fix gossip amplification and known_peers cleanup",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T15:46:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3a75a30c884e18187f56b920617c31941e9bcad",
          "body": "Server (Rust):\n- Skip presence events in recovery ring buffer (skip_recovery flag)\n- Fix presence user double-count with remote sentinels\n- Fix sweep_dead_connections race (remove -> remove_if)\n- Fix sweep leaving dead local conns with remote sentinels\n- Fix recovery get() silent drop in release bui\n[…]\nult (300s -> 3600s)\n- Fix record_success(0.0) spurious zero-latency entries\n- Fix send_bytes crash on non-UTF-8 data with E2E encryption\n\nTS client:\n- Fix SEQUENCE_WINDOW_SIZE constant (1000 -> 10000)",
          "is_bot": false,
          "headline": "v2.0.6 - Fix presence recovery, sweep race, client protocol bugs",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T15:11:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "db84958aff20dbec25fbc6be0198337265f03514",
          "body": null,
          "is_bot": false,
          "headline": "Fix ruff formatting",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T14:35:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1b2ad47eaede74d8ff2ce80a6fdb65d4f72c7f26",
          "body": "Align Python client with TS client:\n- PONG response: server_timestamp + client_timestamp keys\n- Rate limiter: discrete refill with interval snapback\n- ConnectionPool: scaled failure penalty, latency/consistency bonus, time decay\n- Fibonacci reconnect: match TS delay sequence\n\nFix TS SEQUENCE_WINDOW_SIZE constant (1000 -> 10000)",
          "is_bot": false,
          "headline": "v2.0.5 - Sync Python and TS client protocol behavior",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T14:29:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cfd47d3f6f280caee688c22c82037578f1b86aeb",
          "body": "- Fix change_endpoint() injecting sentinel into message iterator\n- Fix recv-loop exception leaving heartbeat running (double reconnect)\n- Fix offline queue losing message priority on partial flush\n- Fix CLIENT_VERSION constant not matching package version",
          "is_bot": false,
          "headline": "v2.0.4 - Fix Python client reconnect and queue bugs",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T14:20:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35257b56d5b549096d128b7829b180fd90ac96ec",
          "body": null,
          "is_bot": false,
          "headline": "Update CHANGELOG for v2.0.3",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T13:58:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1305901a102856ccb00af67a65bf6ce774e7a8df",
          "body": "- Fix HMAC signing auto-activation when encryption enabled\n- Fix send_bytes() bypassing E2E encryption\n- Fix key rotation not restarting after reconnect\n- Fix offline queue message loss on partial flush failure\n- Fix SyncWSEClient stale error state on retry\n- Fix connection pool active count growing on force-reconnect",
          "is_bot": false,
          "headline": "v2.0.3 - Python client bug fixes",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T13:53:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6dc4f760ec2ba1cec7be523fe4dda5e6e76a5529",
          "body": null,
          "is_bot": false,
          "headline": "v2.0.2 - Bug fixes and documentation updates",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T12:30:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b957557b8b5a34b791696307e827ce7dfd92c2f8",
          "body": null,
          "is_bot": false,
          "headline": "Fix import sorting in conftest.py",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T11:48:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cad6f9ad1c2ed87b87bb8067b5eea9524bdae598",
          "body": null,
          "is_bot": false,
          "headline": "Fix ruff lint and format errors",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T11:47:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d7fc15abc2e93889d4c0c43b56f66bc757cdf52",
          "body": null,
          "is_bot": false,
          "headline": "v2.0.1 - Minor fixes",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T11:43:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7bdcb093ef1693f7aaa64a642cd31cdf1794762d",
          "body": "IDE autocomplete and type hints for all PyO3 bindings:\n7 classes, 14 functions, full signatures and docstrings.\nUpdate pyproject.toml description.",
          "is_bot": false,
          "headline": "Add .pyi type stubs for Rust extension module",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T11:01:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "39c291ed6af6392a8ac3b8bdf594184a0141e086",
          "body": "- Fan-out standalone: 4.3M -> 5.0M del/s (new test run)\n- Fan-in JSON: 14.2M -> 14.7M msg/s, size matrix updated\n- README, BENCHMARKS.md, FANOUT, RUST_CLIENT tables updated\n- Kept old data for untested tiers (50K+)\n- Changelog date corrected to 2026-02-28\n- Remove em-dashes from TS and Python benchmark docs",
          "is_bot": false,
          "headline": "Update v2.0.0 benchmark numbers, fix changelog date",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T05:47:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e39c097773b2087006b1a09f5710977ae1e0258",
          "body": "Fresh run: peak 14.7M msg/s at 500-1000 conns (was 14.2M).\nUpdated throughput matrix across all payload sizes.",
          "is_bot": false,
          "headline": "Update Rust client benchmark numbers",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T04:32:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d2e312077afc021d164091438761463d7e176530",
          "body": "Removed \"Comparison with Alternatives\" section (throughput + features\ntables referencing Centrifugo, uWebSockets, Socket.IO, ws).",
          "is_bot": false,
          "headline": "Remove competitor comparison tables from benchmarks",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T04:32:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "950e0960c25b061acb7f66c050da801e76f427f9",
          "body": "Docs:\n- README: full rewrite with 7 feature tables, complete API reference\n- New docs: CONTRIBUTING.md, DEPLOYMENT.md, MIGRATION.md (v1->v2)\n- All docs verified against Rust source in 4 audit passes\n- Fixed health_snapshot field names (cluster_peer_count, all cluster metrics)\n- Fixed server_hello/se\n[…]\nS client: fixed UseWSEReturn.requestSnapshot type signature\n\nTests:\n- Added integration test suite (25 tests)\n- Added battle benchmark tests for presence and recovery\n- Removed /tests/ from .gitignore",
          "is_bot": false,
          "headline": "Comprehensive documentation overhaul, add integration tests",
          "author_name": "silvermpx",
          "author_login": "silvermpx",
          "committed_at": "2026-02-28T04:12:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 39,
      "commits_last_year": 264,
      "latest_release_at": "2026-07-12T13:32:32Z",
      "latest_release_tag": "v2.4.1",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 7,
      "days_since_latest_release": 18,
      "mean_days_between_releases": 14.8
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 71,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "wse-client",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "websocket",
            "react",
            "hooks",
            "real-time",
            "events",
            "pubsub",
            "encryption",
            "rust",
            "zustand"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/wse-client",
          "is_deprecated": false,
          "latest_version": "2.4.1",
          "repository_url": "https://github.com/silvermpx/wse",
          "versions_count": 42,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 276,
          "first_published_at": "2026-02-20T17:49:01.355000Z",
          "latest_published_at": "2026-07-12T13:20:02.065000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 18
        },
        {
          "name": "wse-server",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "websocket",
            "engine",
            "real-time",
            "pubsub",
            "cluster",
            "encrypted",
            "rust",
            "Development Status :: 5 - Production/Stable",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: MIT License",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Programming Language :: Python :: 3.14",
            "Programming Language :: Rust",
            "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
            "Topic :: System :: Networking",
            "Typing :: Typed"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/wse-server/",
          "is_deprecated": false,
          "latest_version": "2.4.1",
          "repository_url": "https://github.com/silvermpx/wse",
          "versions_count": 39,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-02-20T20:34:37.276477Z",
          "latest_published_at": "2026-07-12T13:19:34.531366Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 18
        },
        {
          "name": "wse-client",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "event-streaming",
            "real-time",
            "websocket",
            "wse",
            "Development Status :: 4 - Beta",
            "Framework :: AsyncIO",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: MIT License",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Topic :: Internet",
            "Topic :: Software Development :: Libraries",
            "Typing :: Typed"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/wse-client/",
          "is_deprecated": false,
          "latest_version": "2.4.1",
          "repository_url": "https://github.com/silvermpx/wse",
          "versions_count": 25,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-02-22T21:36:37.875816Z",
          "latest_published_at": "2026-07-12T13:20:23.230543Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 18
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 50,
      "watchers": 3,
      "fork_history": {
        "days": [
          {
            "date": "2026-04-07",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 4
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "benchmarks/ts-bench/tsconfig.json",
        "tsconfig.json",
        "wse_server/py.typed"
      ],
      "toolchain_manifests": [
        "benchmarks/rust-bench/Cargo.toml",
        "rust/Cargo.toml"
      ],
      "largest_source_bytes": 247962,
      "source_files_sampled": 138,
      "oversized_source_files": 2,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "package.json",
        "pyproject.toml",
        "python-client/pyproject.toml",
        "rust/Cargo.toml"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 2,
        "malicious_count": 0,
        "assessed_package": "npm:wse-client@2.4.1",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "crates",
        "npm",
        "pypi"
      ],
      "dependencies": [
        {
          "name": "@msgpack/msgpack",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.0.0"
        },
        {
          "name": "pako",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.0"
        },
        {
          "name": "websockets",
          "manifest": "python-client/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=13.0"
        },
        {
          "name": "pyo3",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.29"
        },
        {
          "name": "serde",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.0.228"
        },
        {
          "name": "serde_json",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.0.149"
        },
        {
          "name": "flate2",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.1.9"
        },
        {
          "name": "rmp-serde",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.3.1"
        },
        {
          "name": "rmpv",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.3.1"
        },
        {
          "name": "hmac",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.12.1"
        },
        {
          "name": "sha2",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.10.9"
        },
        {
          "name": "hex",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.4"
        },
        {
          "name": "ahash",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.8.12"
        },
        {
          "name": "dashmap",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "6"
        },
        {
          "name": "aes-gcm",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.10"
        },
        {
          "name": "p256",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.13"
        },
        {
          "name": "jsonwebtoken",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "10"
        },
        {
          "name": "hkdf",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.12"
        },
        {
          "name": "uuid",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.22.0"
        },
        {
          "name": "base64",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.22"
        },
        {
          "name": "chrono",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.4.44"
        },
        {
          "name": "regex",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.12.3"
        },
        {
          "name": "tokio",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.50.0"
        },
        {
          "name": "tokio-tungstenite",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.29.0"
        },
        {
          "name": "futures-util",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.3.32"
        },
        {
          "name": "crossbeam-channel",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.5"
        },
        {
          "name": "tokio-util",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.7"
        },
        {
          "name": "socket2",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.6"
        },
        {
          "name": "bytes",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1"
        },
        {
          "name": "mimalloc",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.1"
        },
        {
          "name": "tokio-rustls",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.26"
        },
        {
          "name": "rustls",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.23"
        },
        {
          "name": "rustls-pki-types",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1"
        },
        {
          "name": "zstd",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.13"
        },
        {
          "name": "parking_lot",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.12"
        },
        {
          "name": "indexmap",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "2"
        },
        {
          "name": "zeroize",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1"
        },
        {
          "name": "tracing",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.1"
        },
        {
          "name": "tracing-subscriber",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.3"
        },
        {
          "name": "arc-swap",
          "manifest": "rust/Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 4,
        "merged_prs": 10,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 32
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "silvermpx",
          "commits": 247,
          "avatar_url": "https://avatars.githubusercontent.com/u/42042558?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "Cargo.lock",
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/22 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 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": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 6,
            "reason": "dependency not pinned by hash detected -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 4,
            "reason": "6 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "16836ae51c677eef4fa61c1f73c82580b37173b3",
        "ran_at": "2026-07-31T00:01:25Z",
        "aggregate_score": 6.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-31T00:01:12Z",
      "oldest_open_prs": [
        {
          "number": 27,
          "created_at": "2026-03-27T00:10:33Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 32,
          "created_at": "2026-04-03T00:12:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 41,
          "created_at": "2026-04-17T00:12:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 46,
          "created_at": "2026-07-30T23:53:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-31T00:01:05Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/silvermpx/wse",
    "host": "github.com",
    "name": "wse",
    "owner": "silvermpx"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": "The weighted overall 60 is calibrated to 65 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 60,
            "calibrated": 65,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 65,
      "inputs": {
        "security": 70,
        "vitality": 77,
        "community": 46,
        "governance": 37,
        "calibration": "2026-08-02",
        "engineering": 75,
        "ai_readiness": 61,
        "weighted_overall_raw": 60
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 77,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 69,
            "inputs": {
              "commits_last_year": 264,
              "human_commit_share": 0.92,
              "days_since_last_push": 0,
              "active_weeks_last_year": 7
            },
            "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": "7/52 weeks with commits",
                "points": 4.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 7
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "264 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 264
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 39,
              "latest_release_tag": "v2.4.1",
              "releases_from_tags": false,
              "days_since_latest_release": 18,
              "mean_days_between_releases": 14.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "39 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 39
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 18 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 18
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~14.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 14.8
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "weak",
        "name": "Community & Adoption",
        "value": 46,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 29,
            "inputs": {
              "forks": 1,
              "stars": 50,
              "watchers": 3,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "50 stars",
                "points": 27.4,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 50
                    }
                  }
                ],
                "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": "3 watchers",
                "points": 1.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "readme_badges": null,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 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": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "weak",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 41,
            "inputs": {
              "packages": [
                "wse-client",
                "wse-server",
                "wse-client"
              ],
              "dependents": null,
              "ecosystems": "npm, pypi",
              "total_downloads": null,
              "monthly_downloads": 276
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "276 downloads/month across npm, pypi",
                "points": 32.6,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 276,
                      "ecosystems": "npm, pypi"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "weak",
        "name": "Sustainability & Governance",
        "value": 37,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 16,
            "inputs": {
              "merged_prs": 10,
              "open_issues": 0,
              "closed_issues": 0,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 32,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "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": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "10/42 decided PRs merged",
                "points": 7.1,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 10,
                      "decided": 42
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/22 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "weak",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 41,
            "inputs": {
              "followers": 7,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "silvermpx",
              "public_repos": 3,
              "account_age_days": 2919
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "7 followers of silvermpx",
                "points": 6.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 7,
                      "login": "silvermpx"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "3 public repos, account ~7 yr old",
                "points": 16.4,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 3
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 7
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "wse-client",
                "wse-server",
                "wse-client"
              ],
              "ecosystems": "npm, pypi",
              "any_deprecated": false,
              "min_days_since_publish": 18
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "3 package(s) on npm, pypi",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 3,
                      "ecosystems": "npm, pypi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 18 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 18
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "42 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 42
                    }
                  }
                ],
                "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": "good",
        "name": "Engineering Quality",
        "value": 75,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "topics": [
                "encryption",
                "high-performance",
                "jwt",
                "pyo3",
                "python",
                "real-time",
                "rust",
                "tokio",
                "websocket",
                "websocket-server"
              ],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "10 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "good",
        "name": "Security",
        "value": 70,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 63,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 6.3
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/22 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "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": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 6",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "6 existing vulnerabilities detected",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "exceptional",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the npm:wse-client@2.4.1 runtime dependency closure — what installing the published package pulls in — 2 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:wse-client@2.4.1",
                  "assessed": 2
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 2,
              "unassessed_packages": 0,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "exceptional",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 2,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "exceptional",
            "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"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 2
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 61,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "weak",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.848,
              "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": "78 of 92 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 78,
                      "sampled": 92
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "Cargo.lock",
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "benchmarks/ts-bench/tsconfig.json",
                "tsconfig.json",
                "wse_server/py.typed"
              ],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "benchmarks/rust-bench/Cargo.toml",
                "rust/Cargo.toml"
              ],
              "dependency_bot_commit_share": 0.08
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "benchmarks/rust-bench/Cargo.toml, rust/Cargo.toml (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "benchmarks/rust-bench/Cargo.toml, rust/Cargo.toml"
                    }
                  }
                ],
                "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": "benchmarks/ts-bench/tsconfig.json, tsconfig.json, wse_server/py.typed",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "benchmarks/ts-bench/tsconfig.json, tsconfig.json, wse_server/py.typed"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "8 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 8,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "exceptional",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "Rust",
              "largest_source_bytes": 247962,
              "source_files_sampled": 138,
              "oversized_source_files": 2
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Rust (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Rust"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "2/138 source files over 60KB",
                "points": 54.2,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 138,
                      "oversized": 2
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "weak",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "top": [
        "library"
      ],
      "labels": [
        "library"
      ],
      "scores": {
        "library": 12
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:npm",
          "weight": 6
        },
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:pypi",
          "weight": 6
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": false,
      "consumed_by_code": true
    },
    "metrics_version": "2.5.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "Could not fetch crates package 'wse-accel' from its registry",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-31T00:01:33.873611Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/silvermpx/wse.svg",
  "full_name": "silvermpx/wse",
  "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 v2.5.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 agregadasnpm, PyPI.