Registro público
Informe de salud del softwareesquema 0.26.0 · métricas 1.13.0 · 2026-07-22 03:21 UTC

vultisig / vultisig-android

Vultisig Android App

KotlinApache-2.0★ 21 estrellas⑂ 16 forksdesde abr 2024Ver en GitHub ↗

vultisig/vultisig-android tiene un índice de salud de 71 sobre 100, lo que lo sitúa en la banda Bueno. Su puntuación más alta es Vitality (96/100) y la más baja, Community & Adoption (43/100). Se actualizó por última vez hoy. 2 personas concentran la mayor parte del trabajo reciente.

71
global / 100
Bueno

Índice de salud del software

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

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

Perfil de puntuación

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

Titularidad

132 seguidores72 repositorios públicosdesde ene 2024

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

Métricas por categoría

Vitalidad

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

96Excelente · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
36/36Cadencia de commits — 52/52 semanas con commits
18/18Volumen de commits — 1412 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 19 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year1412
human_commit_share1
days_since_last_push0
active_weeks_last_year52
Cómo se puntúa
27/27Publica versiones — 100 versiones publicadas
36/36Recencia de las versiones — última versión hace 7 días
27/27Cadencia de publicación — una versión cada ~4,5 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count100
latest_release_tagv1.0.114
releases_from_tagsno
days_since_latest_release7
mean_days_between_releases4,5

Comunidad y Adopción

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

43En riesgo · 18% del índice global
Cómo se puntúa
21.1/60Estrellas — 21 estrellas
9.8/25Forks — 16 forks
0/15Observadores — 2 observadores
Datos de entrada utilizados
forks16
stars21
watchers2
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonbelow_threshold
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (Apache-2.0)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_template

Sostenibilidad y Gobernanza

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

72Bueno · 24% del índice global
Cómo se puntúa
25.2/54Factor bus — la mitad de los commits recae en 2 contribuyente(s)
14.2/22.5Distribución de commits — el principal contribuyente firma el 37% de los commits
13.5/13.5Amplitud de contribuyentes — 16 contribuyentes
6/10OpenSSF Scorecard: Contributors — project has 2 contributing companies or organizations -- score normalized to 6
Datos de entrada utilizados
bus_factor2
contributors_sampled16
top_contributor_share0,368
Cómo se puntúa
46.3/46.8Resolución de issues — 99% de issues cerradas
36.1/38.3Aceptación de PR — 2630/2785 PR decididos fusionados
13.5/15OpenSSF Scorecard: Code-Review — Found 28/30 approved changesets -- score normalized to 9
Datos de entrada utilizados
merged_prs2630
open_issues24
closed_issues2537
issue_closed_ratio0,991
closed_unmerged_prs155
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
15.3/25Alcance del propietario — 132 seguidores de vultisig
18/25Trayectoria — 72 repos públicos, cuenta de ~2 años
Datos de entrada utilizados
followers132
owner_typeOrganization
is_verified
owner_loginvultisig
public_repos72
account_age_days906

Calidad de Ingeniería

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

74Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 1 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
6.4/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 30 out of 30 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfig
has_linter_configno
has_precommit_configno
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
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
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?

61Moderado · 16% del índice global
Cómo se puntúa
6.8/7.5Binary-Artifacts — binaries present in source code
0.8/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 30 out of 30 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
6.8/7.5Code-Review — Found 28/30 approved changesets -- score normalized to 9
1.5/2.5Contributors — project has 2 contributing companies or organizations -- score normalized to 6
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 19 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — sin datos
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate5,1
Excluidos de la puntuación (sin datos o no aplicable): packaging. 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
0/25Dependencias indirectas libres de avisos conocidos — el conjunto transitivo no es separable de las dependencias de desarrollo y prueba en este alcance
0/40Sin avisos pendientes — ningún aviso tiene fecha de publicación
Datos de entrada utilizados
sourceosv
advisories3
affected_packages3
assessed_packages95
unassessed_packages0
affected_by_severityhigh 2, moderate 1
direct_affected_packages0
Excluidos de la puntuación (sin datos o no aplicable): Dependencias indirectas libres de avisos conocidos, Sin avisos pendientes. Los pesos restantes se han renormalizado. Se cotejaron 95 dependencias resueltas con OSV. Este repositorio no publica ningún paquete que el índice resuelva, por lo que se evaluó en su lugar el grafo de dependencias del repositorio. Ese grafo mezcla fijaciones de desarrollo y prueba con las dependencias distribuidas, de modo que solo se puntúan las dependencias declaradas en tiempo de ejecución; los hallazgos transitivos se informan como contexto y quedan excluidos de la puntuación. 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? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

79Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 100 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes19.254
Cómo se puntúa
12.6/18Arranque con un solo comando — app/build.gradle.kts, build.gradle.kts, data/build.gradle.kts (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — Kotlin (tipado estático)
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 71 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilesGemfile.lock
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0,71
toolchain_manifestsapp/build.gradle.kts, build.gradle.kts, data/build.gradle.kts
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Kotlin (tipado estático)
54.7/55Tamaños de archivo manejables — 8/1718 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageKotlin
largest_source_bytes154.512
source_files_sampled1718
oversized_source_files8

Datos clave

21estrellas de GitHub
16contribuidores
1412commits en los últimos 12 meses
0días desde el último push
100versiones publicadas
2factor bus
24issues abiertas
Maven, RubyGemsecosistemas de paquetes

Más detalle

Historial de estrellas y forks 21 ★ / 16 ⇿
21Estrellas
16Forks
100Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

04812162024211622024-042025-062026-07
Mayor 0Menor 0Parche 100

Cada punto abarca 3 días.

OpenSSF Scorecard 5.1 / 10
5.1agregado

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-22 03:21 UTC

9Binary-Artifactsbinaries present in source code
1Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
9Code-ReviewFound 28/30 approved changesets -- score normalized to 9
6Contributorsproject has 2 contributing companies or organizations -- score normalized to 6
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 19 issue activity found in the last 90 days -- score normalized to 10
n/dPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
7Vulnerabilities3 existing vulnerabilities detected
Dependencias directas 2
RegistroPaqueteRestricción de versiónManifiesto
RubyGemsfastlane2.229.1Gemfile
RubyGemsostructGemfile
Todas las dependencias 95

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

RegistroPaqueteVersiónRelación
RubyGemsfastlane2.229.1directa
RubyGemsostruct0.6.3directa
RubyGemsabbrev0.1.2indirecta
RubyGemsaddressable2.9.0indirecta
RubyGemsartifactory3.0.17indirecta
RubyGemsatomos0.1.3indirecta
RubyGemsaws-eventstream1.4.0indirecta
RubyGemsaws-partitions1.1201.0indirecta
RubyGemsaws-sdk-core3.241.2indirecta
RubyGemsaws-sdk-kms1.119.0indirecta
RubyGemsaws-sdk-s31.210.1indirecta
RubyGemsaws-sigv41.12.1indirecta
RubyGemsbabosa1.0.4indirecta
RubyGemsbase640.2.0indirecta
RubyGemsbigdecimal4.0.1indirecta
RubyGemsCFPropertyList3.0.8indirecta
RubyGemsclaide1.1.0indirecta
RubyGemscolored1.2indirecta
RubyGemscolored23.1.2indirecta
RubyGemscommander4.6.0indirecta
RubyGemscsv3.3.5indirecta
RubyGemsdeclarative0.0.20indirecta
RubyGemsdigest-crc0.7.0indirecta
RubyGemsdomain_name0.6.20240107indirecta
RubyGemsdotenv2.8.1indirecta
RubyGemsemoji_regex3.2.3indirecta
RubyGemsexcon0.112.0indirecta
RubyGemsfaraday1.10.5indirecta
RubyGemsfaraday-cookie_jar0.0.8indirecta
RubyGemsfaraday-em_http1.0.0indirecta
RubyGemsfaraday-em_synchrony1.0.1indirecta
RubyGemsfaraday-excon1.1.0indirecta
RubyGemsfaraday-httpclient1.0.1indirecta
RubyGemsfaraday-multipart1.2.0indirecta
RubyGemsfaraday-net_http1.0.2indirecta
RubyGemsfaraday-net_http_persistent1.2.0indirecta
RubyGemsfaraday-patron1.0.0indirecta
RubyGemsfaraday-rack1.0.0indirecta
RubyGemsfaraday-retry1.0.4indirecta
RubyGemsfaraday_middleware1.2.1indirecta
RubyGemsfastimage2.4.0indirecta
RubyGemsfastlane-sirp1.0.0indirecta
RubyGemsgh_inspector1.1.3indirecta
RubyGemsgoogle-apis-androidpublisher_v30.54.0indirecta
RubyGemsgoogle-apis-core0.11.3indirecta
RubyGemsgoogle-apis-iamcredentials_v10.17.0indirecta
RubyGemsgoogle-apis-playcustomapp_v10.13.0indirecta
RubyGemsgoogle-apis-storage_v10.31.0indirecta
RubyGemsgoogle-cloud-core1.8.0indirecta
RubyGemsgoogle-cloud-env1.6.0indirecta
RubyGemsgoogle-cloud-errors1.5.0indirecta
RubyGemsgoogle-cloud-storage1.47.0indirecta
RubyGemsgoogleauth1.8.1indirecta
RubyGemshighline2.0.3indirecta
RubyGemshttp-cookie1.0.8indirecta
RubyGemshttpclient2.9.0indirecta
RubyGemsjmespath1.6.2indirecta
RubyGemsjson2.19.2indirecta
RubyGemsjwt2.10.2indirecta
RubyGemslogger1.7.0indirecta
RubyGemsmini_magick4.13.2indirecta
RubyGemsmini_mime1.1.5indirecta
RubyGemsmulti_json1.19.1indirecta
RubyGemsmultipart-post2.4.1indirecta
RubyGemsmutex_m0.3.0indirecta
RubyGemsnanaimo0.4.0indirecta
RubyGemsnaturally2.3.0indirecta
RubyGemsnkf0.2.0indirecta
RubyGemsoptparse0.8.1indirecta
RubyGemsos1.1.4indirecta
RubyGemsplist3.7.2indirecta
RubyGemspublic_suffix7.0.5indirecta
RubyGemsrake13.3.1indirecta
RubyGemsrepresentable3.2.0indirecta
RubyGemsretriable3.1.2indirecta
RubyGemsrexml3.4.4indirecta
RubyGemsrouge3.28.0indirecta
RubyGemsruby2_keywords0.0.5indirecta
RubyGemsrubyzip2.4.1indirecta
RubyGemssecurity0.1.5indirecta
RubyGemssignet0.21.0indirecta
RubyGemssimctl1.6.10indirecta
RubyGemssysrandom1.0.5indirecta
RubyGemsterminal-notifier2.0.0indirecta
RubyGemsterminal-table3.0.2indirecta
RubyGemstrailblazer-option0.1.2indirecta
RubyGemstty-cursor0.7.1indirecta
RubyGemstty-screen0.8.2indirecta
RubyGemstty-spinner0.9.3indirecta
RubyGemsuber0.1.0indirecta
RubyGemsunicode-display_width2.6.0indirecta
RubyGemsword_wrap1.0.0indirecta
RubyGemsxcodeproj1.27.0indirecta
RubyGemsxcpretty0.4.1indirecta
RubyGemsxcpretty-travis-formatter1.0.1indirecta
Avisos de dependencias 3

Este repositorio no publica ningún paquete que el índice resuelva, así que se evaluó su propio grafo de dependencias — 95 paquetes, que incluyen también fijaciones de desarrollo y prueba que nunca se distribuyen: 3 tienen avisos conocidos, de los cuales 0 son directas.

PaqueteVersiónRelaciónGravedadAvisosCorregido en
faraday1.10.5indirectaalta12.14.3
jwt2.10.2indirectaalta13.2.0
excon0.112.0indirectamoderada11.5.0

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": [],
      "is_fork": false,
      "size_kb": 250256,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Ruby": 1739,
        "Shell": 7601,
        "Kotlin": 11573842,
        "JavaScript": 2413
      },
      "pushed_at": "2026-07-21T23:56:28Z",
      "created_at": "2024-04-22T02:25:31Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-21T23:56:30Z",
      "description": "Vultisig Android App",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Kotlin",
      "significant_languages": [
        "Kotlin"
      ]
    },
    "owner": {
      "blog": "vultisig.com",
      "name": "Vultisig: Secure Crypto Vault",
      "type": "Organization",
      "login": "vultisig",
      "company": null,
      "location": null,
      "followers": 132,
      "avatar_url": "https://avatars.githubusercontent.com/u/157932671?v=4",
      "created_at": "2024-01-28T01:22:46Z",
      "is_verified": null,
      "public_repos": 72,
      "account_age_days": 906
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.0.114",
          "kind": "patch",
          "published_at": "2026-07-14T10:27:19Z"
        },
        {
          "tag": "v1.0.113",
          "kind": "patch",
          "published_at": "2026-07-06T00:28:02Z"
        },
        {
          "tag": "v1.0.112",
          "kind": "patch",
          "published_at": "2026-07-03T01:12:42Z"
        },
        {
          "tag": "v1.0.111",
          "kind": "patch",
          "published_at": "2026-06-29T00:00:15Z"
        },
        {
          "tag": "v1.0.110",
          "kind": "patch",
          "published_at": "2026-06-25T23:39:44Z"
        },
        {
          "tag": "v1.0.109",
          "kind": "patch",
          "published_at": "2026-06-21T23:33:46Z"
        },
        {
          "tag": "v1.0.108",
          "kind": "patch",
          "published_at": "2026-06-12T09:33:43Z"
        },
        {
          "tag": "v1.0.107",
          "kind": "patch",
          "published_at": "2026-06-05T22:10:32Z"
        },
        {
          "tag": "v1.0.106",
          "kind": "patch",
          "published_at": "2026-06-05T09:48:20Z"
        },
        {
          "tag": "v1.0.105",
          "kind": "patch",
          "published_at": "2026-06-04T02:37:50Z"
        },
        {
          "tag": "v1.0.104",
          "kind": "patch",
          "published_at": "2026-06-03T23:36:15Z"
        },
        {
          "tag": "v1.0.103",
          "kind": "patch",
          "published_at": "2026-05-19T06:42:54Z"
        },
        {
          "tag": "v1.0.102",
          "kind": "patch",
          "published_at": "2026-05-14T10:22:16Z"
        },
        {
          "tag": "v1.0.101",
          "kind": "patch",
          "published_at": "2026-04-28T04:08:48Z"
        },
        {
          "tag": "v1.0.100",
          "kind": "patch",
          "published_at": "2026-04-25T06:42:34Z"
        },
        {
          "tag": "v1.0.99",
          "kind": "patch",
          "published_at": "2026-04-23T01:41:00Z"
        },
        {
          "tag": "v1.0.98",
          "kind": "patch",
          "published_at": "2026-03-26T06:06:48Z"
        },
        {
          "tag": "v1.0.97",
          "kind": "patch",
          "published_at": "2026-03-17T21:57:22Z"
        },
        {
          "tag": "v1.0.96",
          "kind": "patch",
          "published_at": "2026-02-26T21:57:20Z"
        },
        {
          "tag": "v1.0.95",
          "kind": "patch",
          "published_at": "2026-02-03T09:48:16Z"
        },
        {
          "tag": "v1.0.94",
          "kind": "patch",
          "published_at": "2026-02-02T22:33:39Z"
        },
        {
          "tag": "v1.0.93",
          "kind": "patch",
          "published_at": "2026-01-15T21:49:05Z"
        },
        {
          "tag": "v1.0.92",
          "kind": "patch",
          "published_at": "2026-01-15T00:44:19Z"
        },
        {
          "tag": "v1.0.91",
          "kind": "patch",
          "published_at": "2026-01-13T23:00:24Z"
        },
        {
          "tag": "v1.0.90",
          "kind": "patch",
          "published_at": "2026-01-07T22:03:48Z"
        },
        {
          "tag": "v1.0.89",
          "kind": "patch",
          "published_at": "2025-12-11T23:33:15Z"
        },
        {
          "tag": "v1.0.88",
          "kind": "patch",
          "published_at": "2025-12-09T23:14:30Z"
        },
        {
          "tag": "v1.0.87",
          "kind": "patch",
          "published_at": "2025-11-29T01:50:15Z"
        },
        {
          "tag": "v1.0.86",
          "kind": "patch",
          "published_at": "2025-11-26T23:56:24Z"
        },
        {
          "tag": "v1.0.85",
          "kind": "patch",
          "published_at": "2025-11-26T05:26:24Z"
        },
        {
          "tag": "v1.0.84",
          "kind": "patch",
          "published_at": "2025-11-18T09:06:56Z"
        },
        {
          "tag": "v1.0.83",
          "kind": "patch",
          "published_at": "2025-11-15T05:32:41Z"
        },
        {
          "tag": "v1.0.82",
          "kind": "patch",
          "published_at": "2025-11-03T23:25:04Z"
        },
        {
          "tag": "v1.0.81",
          "kind": "patch",
          "published_at": "2025-10-28T08:25:37Z"
        },
        {
          "tag": "v1.0.80",
          "kind": "patch",
          "published_at": "2025-10-27T08:49:49Z"
        },
        {
          "tag": "v1.0.79",
          "kind": "patch",
          "published_at": "2025-10-21T01:14:52Z"
        },
        {
          "tag": "v1.0.78",
          "kind": "patch",
          "published_at": "2025-10-18T23:32:48Z"
        },
        {
          "tag": "v1.0.77",
          "kind": "patch",
          "published_at": "2025-10-09T09:34:50Z"
        },
        {
          "tag": "v1.0.76",
          "kind": "patch",
          "published_at": "2025-10-07T22:38:11Z"
        },
        {
          "tag": "v1.0.75",
          "kind": "patch",
          "published_at": "2025-10-07T00:46:28Z"
        },
        {
          "tag": "v1.0.74",
          "kind": "patch",
          "published_at": "2025-10-02T05:59:03Z"
        },
        {
          "tag": "v1.0.73",
          "kind": "patch",
          "published_at": "2025-09-15T22:51:48Z"
        },
        {
          "tag": "v1.0.72",
          "kind": "patch",
          "published_at": "2025-09-08T05:59:44Z"
        },
        {
          "tag": "v1.0.71",
          "kind": "patch",
          "published_at": "2025-08-22T09:42:30Z"
        },
        {
          "tag": "v1.0.70",
          "kind": "patch",
          "published_at": "2025-08-20T07:01:35Z"
        },
        {
          "tag": "v1.0.69",
          "kind": "patch",
          "published_at": "2025-08-05T01:17:42Z"
        },
        {
          "tag": "v1.0.68",
          "kind": "patch",
          "published_at": "2025-08-04T09:54:47Z"
        },
        {
          "tag": "v1.0.66",
          "kind": "patch",
          "published_at": "2025-08-01T10:48:34Z"
        },
        {
          "tag": "v1.0.65",
          "kind": "patch",
          "published_at": "2025-07-21T23:23:20Z"
        },
        {
          "tag": "v1.0.64",
          "kind": "patch",
          "published_at": "2025-07-18T10:10:05Z"
        },
        {
          "tag": "v1.0.63",
          "kind": "patch",
          "published_at": "2025-07-17T00:32:26Z"
        },
        {
          "tag": "v1.0.62",
          "kind": "patch",
          "published_at": "2025-07-06T22:54:54Z"
        },
        {
          "tag": "v1.0.61",
          "kind": "patch",
          "published_at": "2025-07-04T10:24:17Z"
        },
        {
          "tag": "v1.0.60",
          "kind": "patch",
          "published_at": "2025-07-03T11:59:26Z"
        },
        {
          "tag": "v1.0.59",
          "kind": "patch",
          "published_at": "2025-06-21T00:47:02Z"
        },
        {
          "tag": "v1.0.58",
          "kind": "patch",
          "published_at": "2025-06-11T23:05:23Z"
        },
        {
          "tag": "v1.0.57",
          "kind": "patch",
          "published_at": "2025-05-29T01:14:05Z"
        },
        {
          "tag": "v1.0.56",
          "kind": "patch",
          "published_at": "2025-05-16T06:52:59Z"
        },
        {
          "tag": "v1.0.55",
          "kind": "patch",
          "published_at": "2025-05-07T06:53:30Z"
        },
        {
          "tag": "v1.0.54",
          "kind": "patch",
          "published_at": "2025-05-01T15:02:48Z"
        },
        {
          "tag": "v1.0.53",
          "kind": "patch",
          "published_at": "2025-04-30T22:55:33Z"
        },
        {
          "tag": "v1.0.52",
          "kind": "patch",
          "published_at": "2025-04-29T21:59:27Z"
        },
        {
          "tag": "v1.0.51",
          "kind": "patch",
          "published_at": "2025-04-28T10:41:26Z"
        },
        {
          "tag": "v1.0.50",
          "kind": "patch",
          "published_at": "2025-04-25T10:08:09Z"
        },
        {
          "tag": "v1.0.49",
          "kind": "patch",
          "published_at": "2025-04-14T08:22:51Z"
        },
        {
          "tag": "v1.0.48",
          "kind": "patch",
          "published_at": "2025-04-07T06:52:19Z"
        },
        {
          "tag": "v1.0.47",
          "kind": "patch",
          "published_at": "2025-03-23T23:54:14Z"
        },
        {
          "tag": "v1.0.46",
          "kind": "patch",
          "published_at": "2025-03-20T22:03:00Z"
        },
        {
          "tag": "v1.0.45",
          "kind": "patch",
          "published_at": "2025-03-19T23:00:19Z"
        },
        {
          "tag": "v1.0.44",
          "kind": "patch",
          "published_at": "2025-03-13T21:26:05Z"
        },
        {
          "tag": "v1.0.43",
          "kind": "patch",
          "published_at": "2025-03-12T05:52:02Z"
        },
        {
          "tag": "v1.0.42",
          "kind": "patch",
          "published_at": "2025-02-27T00:15:07Z"
        },
        {
          "tag": "v1.0.41",
          "kind": "patch",
          "published_at": "2025-02-13T21:36:11Z"
        },
        {
          "tag": "v1.0.40",
          "kind": "patch",
          "published_at": "2025-02-13T07:36:52Z"
        },
        {
          "tag": "v1.0.39",
          "kind": "patch",
          "published_at": "2025-02-06T01:53:18Z"
        },
        {
          "tag": "v1.0.38",
          "kind": "patch",
          "published_at": "2025-01-22T23:14:51Z"
        },
        {
          "tag": "v1.0.37",
          "kind": "patch",
          "published_at": "2025-01-09T22:00:21Z"
        },
        {
          "tag": "v1.0.36",
          "kind": "patch",
          "published_at": "2024-12-09T23:07:13Z"
        },
        {
          "tag": "v1.0.35",
          "kind": "patch",
          "published_at": "2024-12-04T22:20:09Z"
        },
        {
          "tag": "v1.0.34",
          "kind": "patch",
          "published_at": "2024-11-20T23:29:57Z"
        },
        {
          "tag": "v1.0.33",
          "kind": "patch",
          "published_at": "2024-11-14T02:27:51Z"
        },
        {
          "tag": "v1.0.32",
          "kind": "patch",
          "published_at": "2024-11-02T00:26:04Z"
        },
        {
          "tag": "v1.0.31",
          "kind": "patch",
          "published_at": "2024-10-30T23:30:10Z"
        },
        {
          "tag": "v1.0.30",
          "kind": "patch",
          "published_at": "2024-10-18T22:16:09Z"
        },
        {
          "tag": "v1.0.29",
          "kind": "patch",
          "published_at": "2024-10-14T11:37:29Z"
        },
        {
          "tag": "v1.0.27",
          "kind": "patch",
          "published_at": "2024-10-08T21:14:06Z"
        },
        {
          "tag": "v1.0.26",
          "kind": "patch",
          "published_at": "2024-10-07T00:17:56Z"
        },
        {
          "tag": "v1.0.25",
          "kind": "patch",
          "published_at": "2024-09-26T08:43:58Z"
        },
        {
          "tag": "v1.0.24",
          "kind": "patch",
          "published_at": "2024-09-25T22:48:58Z"
        },
        {
          "tag": "v1.0.23",
          "kind": "patch",
          "published_at": "2024-09-16T22:32:55Z"
        },
        {
          "tag": "v1.0.22",
          "kind": "patch",
          "published_at": "2024-09-11T10:57:37Z"
        },
        {
          "tag": "v1.0.21",
          "kind": "patch",
          "published_at": "2024-09-11T01:46:46Z"
        },
        {
          "tag": "v1.0.20",
          "kind": "patch",
          "published_at": "2024-09-05T05:28:24Z"
        },
        {
          "tag": "v1.0.19",
          "kind": "patch",
          "published_at": "2024-09-02T05:54:20Z"
        },
        {
          "tag": "v1.0.18",
          "kind": "patch",
          "published_at": "2024-08-28T22:08:39Z"
        },
        {
          "tag": "v1.0.17",
          "kind": "patch",
          "published_at": "2024-08-24T00:55:56Z"
        },
        {
          "tag": "v1.0.16",
          "kind": "patch",
          "published_at": "2024-08-18T02:38:27Z"
        },
        {
          "tag": "v1.0.15",
          "kind": "patch",
          "published_at": "2024-08-11T02:39:54Z"
        },
        {
          "tag": "v1.0.14",
          "kind": "patch",
          "published_at": "2024-08-06T06:13:57Z"
        },
        {
          "tag": "v1.0.13",
          "kind": "patch",
          "published_at": "2024-08-03T06:19:06Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2c230ced6fed249f439e9fbca9c707458f369ce1",
          "body": "…#5360)\n\n* fix(cardano): recover loser device on duplicate-broadcast rejection\n\nOn a multi-device Cardano keysign the losing device rebroadcasts the peer's\nbyte-identical signed tx and Ogmios rejects it with \"All inputs are spent.\nTransaction has probably already been included\". The old recovery req\n[…]\n\n  every recovery path rethrows instead of reporting an untrackable success.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cardano): recover loser device on duplicate-broadcast rejection (…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-21T23:56:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f939c3e06b9fd77c5e25b450b1072b39b1c5f5d0",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump targetSdk to 36 (#5370)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-21T23:34:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf94f1910c4af079807c6e6f222f914207a646ce",
          "body": "* fix(solana): count Solana swap priority fee once, not twice\n\ncalculateDefaultFees added a computed priority fee on top of a base-fee\nconstant that already bundled the floor priority fee, roughly doubling\nthe displayed swap fee. Use a genuine base-only signature-fee constant so\nthe priority fee is \n[…]\ncom>\n\n* address review comments: clarify single-signer scope in fee comment\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(solana): count swap priority fee once, not twice (#5359)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-21T22:54:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "11182faa0c5cc8d764ae1a2b836070f8a81a978e",
          "body": "Co-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>",
          "is_bot": false,
          "headline": "style: apply ktfmt formatting (#5365) (#5367)",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-21T11:41:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b42df2d93610d1d7ec1bc8378cc857661f8e6845",
          "body": "…reen (#5354)\n\n* fix(deposit): correct From/To/pool on Mint LP transaction-complete screen\n\nA MayaChain Mint (add-liquidity) deposit reached the Transaction-complete\nscreen with three display defects versus the pre-sign Function overview:\n\n- From showed the raw chain address instead of \"VaultName (a\n[…]\nrim the test comment to what toUiTransactionInfo() actually asserts.\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(deposit): correct From/To/pool on Mint LP transaction-complete sc…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-21T10:05:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6091a9a4ea6c5e9b2ce7e0b3a36d967db025a942",
          "body": "Co-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>",
          "is_bot": false,
          "headline": "style: apply ktfmt formatting (#5328) (#5362)",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-21T09:47:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "219fce05ef874ade8a9b53ee785e40cb4b465848",
          "body": "* fix: check swap inbound status before signing\n\n* fix: address swap preflight review\n\n* address review comments\n\n- default gasRate/gasRateUnits to empty to keep the shared inbound model\n  from decode-failing (and false-blocking) when Maya omits gas fields\n- assert isSigning resets to false on the b\n[…]\nross tests as\nUncaughtExceptionsBeforeTest. The VM already injects ioDispatcher for\nexactly this reason (withVaultLabels uses it).\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: check swap inbound status before signing (#5342)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-21T09:26:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0a0a65182ae7978305462dd526354c8afebef855",
          "body": "The Schnorr initiator regenerated and re-uploaded a fresh setup message\non every retry because its upload branch lacked the `attempt == 0` guard\nthat DklsKeysign and MldsaKeysign already use. A peer still mid-protocol\non the previous setup message would then desync, signing against a\ndifferent sessi\n[…]\noad on the first attempt so retries fall through to\nthe existing download branch and reuse the setup message already on the\nrelay.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): reuse Schnorr setup message on retry (#5327) (#5353)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-20T22:50:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b59e8dac91b1bde3ac6b9f0e9865ed06059c771d",
          "body": "* fix(swap): dispatch SwapKit UTXO signer by chain, not txType\n\nJoining a SwapKit swap sourced from Dogecoin/BitcoinCash/Dash/Zcash and\ninitiated on another client (e.g. the browser extension) failed with\n\"Unsupported SwapKit txType for signing\" or silently signed with the\nwrong signer. SwapKit's wi\n[…]\nch test\n\nCodeRabbit flagged e.message!! as a potential NPE if the exception carries\nno message; use a null-safe assertion instead so a missing message fails\nthe assertion cleanly rather than throwing.",
          "is_bot": false,
          "headline": "fix(swap): resolve SwapKit UTXO signer by chain, not txType (#5346)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-20T22:44:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ec951cb358101e67afe8a12b48dd8ca4e83323f1",
          "body": "* feat(icons): adopt Icons V3 for 29 icons at parity with iOS #4834\n\nSwap 29 UI drawables to their Icons V3 geometry, taken byte-for-byte from\nthe V3 art iOS shipped in #4834 (its imageset SVGs). Because Android resolves\ndrawables by filename through R, each file is edited in place under its\nexistin\n[…]\nfixes the aspect distortion\nwithout changing any rendered icon size.\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(icons): adopt Icons V3 across UI drawables (42 icons) (#5352)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-20T22:41:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7500e69997e5a14ec446d32b8077f4e504e80f68",
          "body": "…#5350)\n\nTwo same-shaped bugs where a per-chain lookup silently returned a wrong\nvalue instead of failing:\n\n- String.getChain() resolved any unknown ticker to ThorChain, so a rename\n  upstream could misroute a secured-asset withdrawal. It now throws; the\n  DepositFormViewModel catch surfaces a user \n[…]\n  and the chain-variable symbol display sites through it, and marked the\n  WalletCore accessors as unsafe for display/amount math.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(chain): make Coins the single source for chain identity (#5323) (…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-20T10:28:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fd65ee0144e6b98903626483c86d5dc26f4e4006",
          "body": "* feat(solana): sign and broadcast dApp transaction batches\n\nsignAllTransactions/signAndSendAllTransactions batches were hashed and\nsigned in full by the keysign ceremony, but assembly only delivered the\nfirst transaction, so the whole batch died with an opaque Signing Error\nafter the user had alrea\n[…]\nPayload test helper\ninstead of a near-identical solPayload, and add direct coverage for\nSigningHelper.getSignedTransactions' batch-vs-single routing, which was\npreviously only exercised through mocks.",
          "is_bot": false,
          "headline": "feat(solana): sign and broadcast dApp transaction batches (#5265)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-20T10:22:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dca2b35ab385f416b9b0c3df290e6d5f6a9695bd",
          "body": "…(#5349)\n\nXRPL (GemWallet signMessage) custom messages sign SHA-512-half — the\nfirst 32 bytes of SHA-512 — of the message bytes. Android's custom-message\nkeysign had no Ripple branch, so a `chain: Ripple` message fell through to\nkeccak256 and diverged from the initiator's digest, so a Secure-Vault\nA\n[…]\nsetup message and co-signing 404'd.\n\nAdd `toSha512ByteArray()` and a `Chain.Ripple` branch to the digest `when`,\nmirroring the shared contract in vultisig-windows getCustomMessageHex.ts.\n\nCloses #5341",
          "is_bot": false,
          "headline": "feat(ripple): SHA-512-half digest for XRPL custom-message co-signing …",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-20T10:01:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d67248a4a05e7ec4bb22bd1651b5e63a38a6e974",
          "body": "…21) (#5332)\n\n* fix(swap): stop zeroing the SwapKit swap fee on Cardano (#5321)\n\nCardano is classified as TokenStandard.UTXO, so `isSwapKitUtxoSwap` in\nSwapQuotePipeline.buildSuccess treated ADA like a PSBT-broadcast UTXO chain\nand zeroed the displayed swap fee — understating the fee on ADA SwapKit \n[…]\ntValueToString dependency from SwapQuotePipeline.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): keep SwapKit swap fee zeroed on Cardano, hide the row (#53…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-19T23:27:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1c1f9553e552583756065ae93e7da2fb9249d13f",
          "body": "…39) (#5340)\n\nThe swap overview suppressed the \"on <chain>\" indicator on native assets,\nso a native From asset (e.g. BTC) showed no chain while a token To asset\n(e.g. USDC on Ethereum) did — an inconsistent read of the two sides. Gate\nthe indicator on isSwap alone so both rows communicate their chain.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): show chain indicator on both swap-overview token rows (#53…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-19T12:27:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "90b361570bde76e749d92502c4792ca1952a3374",
          "body": "…(#5338)\n\n* fix(substrate): stop reporting success on a malformed broadcast body (#5320)\n\nA truncated or proxy-mangled author_submitExtrinsic response decodes to\n(null, null) under the production explicitNulls=false config. That null was\nindistinguishable from the intended \"duplicate -> resolve to k\n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(substrate): stop reporting success on a malformed broadcast body …",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-19T12:19:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0cc3bb3ba70c537da6ecbb8576299408f9c28670",
          "body": "…ddress) (#5333) (#5336)\n\n* fix: format swap complete screen From/To as VaultName (Address) (#5333)\n\nThe swap Transaction-complete screen rendered From/To as bare\ntruncated addresses, unlike Send/Deposit which already show\nVaultName (Address). Resolve src/dst vault names in KeysignViewModel\nvia the \n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Swap complete screen: From/To addresses not formatted as VaultName (A…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-19T10:24:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "486e9f95930fcf7921772e587341cefdf0abf19c",
          "body": "…ined devices (#5329) (#5330)\n\n* style: apply ktfmt formatting (#5329)\n\n* fix: resolve CI compile error in SwapTransactionBuilder (#5329)\n\nquote.fees is a TokenValue with no 'token' back-reference, so\nquote.fees.token.{chain.id,contractAddress,decimal} failed to compile.\nThe swap-fee coin context is\n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Swap overview: Network Fee & Swap Fee differ between initiator and jo…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-18T23:48:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "296a9ce42bf15f72660e564230c0946fa0da167a",
          "body": "* feat(swap): make THORChain secured assets discoverable in swap picker\n\nSecured assets (btc-btc, eth-usdc-..., etc.) were only shown in the\nswap destination picker if the vault already held a balance, since the\nTHORChain token catalog had no secured-asset entries. Populate the\ncatalog from THORChai\n[…]\ne file), which could let a double-tap on two same-ticker rows\nleak a stale selection into a later, unrelated picker visit. Fixed with\na per-visit UUID plus a re-entrancy guard in SelectAssetViewModel.",
          "is_bot": false,
          "headline": "Make THORChain secured assets discoverable in the swap picker (#5271)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-18T23:37:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "38c8f7b29798f0d6678126898598ddd4292f03a1",
          "body": "\"Max\" captured the balance and gas fee once at tap time and never\nre-clamped when either moved before submit — a cached balance correcting\ndownward after network hydration, or EVM gas rising. The stale-high\nsnapshot then exceeded what was actually spendable and submit validation\nrejected it as \"insu\n[…]\nive token-balance shortfall to its own error\nstring without the \"with fees\" framing that wrongly implied reserving\ntokens for gas.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(send): re-clamp Max to current balance/fee at submit (#5316) (#5325)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-18T10:16:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5ce9389124542b847cb481d32a86332792b602cc",
          "body": "…314) (#5324)\n\n* fix(keysign): recover DKLS-family signature from relay on failure (#5314)\n\nA DKLS-family keysign device whose local session never reaches\n`isFinished` — e.g. when a final-round relay message is lost to a\ntransport error — would fail with \"signatures empty\" even though the\npeer alrea\n[…]\nresume.\nApplied to all three DKLS-family classes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): recover DKLS-family signature from relay on failure (#5…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-18T09:57:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3060455294e4b5461aeb444fed491b546682e286",
          "body": "…#5312)\n\n* fix(evm): stop persisting a failed balance read as a real 0 (#5308)\n\nA funded EVM account showed 0/$0.00 after a single transient network\nfailure, and that zero was written to Room over the last-known balance,\nsurviving app restarts until a successful refresh — reading as \"my funds\ndisapp\n[…]\npick.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>\nCo-authored-by: Roman <32820910+rkokhatskyi@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(evm): stop persisting a failed balance read as a real 0 (#5308) (…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-18T06:28:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ebf95647819a2ff7aa6e9c34a4702256bcb9c1d0",
          "body": "…ir (#5311)\n\n* fix(swap): drop late quote resolved for a different amount on the same pair\n\napplyQuoteResult's late-result guard only checked isLiveInputQuotable\n(\"is something quotable now\"), never whether the resolved fetch matched\nthe amount now in the field. A fetch queued for an earlier amount \n[…]\n Claude Opus 4.8 <noreply@anthropic.com>\n\n* fix(swap): reject superseded quote results\n\n* fix(swap): bind quotes to routing settings\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): drop late quote resolved for a different amount on same pa…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-18T00:48:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0eeacd873c302de6386e05c108507568e0179283",
          "body": "* fix(thorchain): label Unbond confirmation \"Unbonding\" with formatted From/To (#5301)\n\nThe THORChain Unbond \"Function overview\" confirmation mislabeled the action\nas \"You're sending\" and showed the From/To vault address as a raw thor1…\nstring.\n\nThe node-management Unbond flow builds its DepositTran\n[…]\nsolation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(thorchain): Unbond confirmation label + formatted From/To (#5306)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-17T09:13:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d630679314bd2d75ebb8cbca8912258d301fa2d4",
          "body": "hypurrscan only serves HyperEVM txs under an /evm/tx/ prefix; its bare\n/tx/<hash> path — what the generic explorer path produced — errors with\n\"Unexpected error (code=358)\". Switch the Hyperliquid base to\nhyperevmscan.io, an Etherscan-style explorer whose /tx/ and /address/\npaths resolve through the existing generic cases, fixing both\ntransaction and address links without special-casing.",
          "is_bot": false,
          "headline": "fix(hyperliquid): point explorer links at hyperevmscan (#5305) (#5307)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-16T11:49:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0eabdd7c45ad556291955fd61910bbc99ce1fe47",
          "body": "* fix(swap): stop placeholder skeletons blinking on empty amount\n\nThe destination/fee skeletons flashed true→false on form open and on a\npair/destination change because isLoading was raised unconditionally: the\ninput onEach fired for the empty-field emission, and the slippageBps /\nexternalRecipient \n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): stop placeholder skeletons blinking on empty amount (#5297)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-16T11:39:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "781cad4ca4d2d648425bf7c443ed8eea05d0ec1d",
          "body": "* feat(keysign/ripple): co-sign dApp XRPL transactions (SignRipple)\n\nCarry a dApp-supplied XRPL transaction (via the extension's GemWallet\nprovider) to the Secure Vault co-signer verbatim and sign its raw JSON\nthrough WalletCore's rawJson path, so every device produces byte-identical\nsigning bytes m\n[…]\nd verify_transaction_consent_dapp_transaction across all 10 locales.\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(keysign): co-sign dApp XRPL transactions (SignRipple) #5298 (#5303)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-16T10:34:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12064887514b316d640f27ca9a03aed639711ff2",
          "body": "SEI is EVM-compatible (chainId 1329, secp256k1, 0x addresses, derivation\npath m/44'/60'/0'/0/0). It was mapped to WalletCore's native CoinType.SEI,\nwhose raw derivationPath() is the Cosmos path m/44'/118'/0'/0/0 — papered\nover with compatibleType/compatibleDerivationPath/compatibleChainId\noverrides \n[…]\nvation path consistent across platforms.\n\nAdds SeiEvmCoinTypeTest pinning Chain.Sei -> ETHEREUM, path m/44'/60', and\nchainId 1329.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(sei): map SEI to the Ethereum coin type (#5300)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-15T12:17:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aa09c08783ece755822803fe09f1a258d9d8b17c",
          "body": "…ntil amount entered (#5294) (#5295)\n\n* fix: TRON un/freeze fee loads on entry & Continue gated on amount (#5294)\n\nThe TRON Freeze/Unfreeze screens reuse the shared SendForm. Their gas-fee\npipeline returned early when the amount field was empty, so isGasFeeLoading\nnever cleared — leaving the fee row\n[…]\ny@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: aminsato <amin.saradar@yahoo.com>",
          "is_bot": false,
          "headline": "TRON Unfreeze/Freeze: Continue disabled & Network Fee stuck loading u…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-15T10:19:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8b67e7c266fa25c23b5d4625a59151e9828bd47c",
          "body": "* feat: add USDC, USDD & stUSDT Tron tokens for desktop parity (#5286)\n\nAdd USDC, USDD and stUSDT TRC-20 tokens to the built-in Tron token\nregistry so they appear in the \"Choose Tokens\" screen with balances,\nUSD prices and logos, matching the desktop token set.\n\n- Add USDC (usd-coin), USDD (usdd) an\n[…]\nn (ios parity)\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "Tron: add USDC, USDD & stUSDT tokens (desktop parity) (#5286) (#5287)",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-15T00:57:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d7b262714fe4adce893c1a2b50b77dbbbb55cc91",
          "body": "…ating (#5275) (#5284)\n\n* fix(thorchain): auto-discover bRUNE/ybRUNE and correct stale identities\n\nA fresh wallet only ever seeds native RUNE, so getRefreshTokens' enabledDenoms\ngate dropped a newly received bRUNE/ybRUNE bank denom before it could reach the\ncanonicalization block — the tokens only s\n[…]\no-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(thorchain): bRUNE/ybRUNE follow-ups — discovery, pricing & swap g…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-14T23:06:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3ed662c94bde4fe75ba7d60d7e6e39e5b9c6b872",
          "body": "* fix(keysign): friendly message for unfunded Cosmos accounts\n\nA Cosmos SDK code=9 (ErrUnknownAddress) broadcast rejection - the\nfee-payer account has no on-chain presence, e.g. a never-funded QBTC\nvault - fell through to the generic broadcast-rejected copy, which\ninterpolates the node's raw_log ver\n[…]\nrted locales.\n\n* fix(keysign): clarify Dutch \"fund the wallet\" wording\n\n\"Schakel ... in\" reads as \"switch on/enable\", not \"top up\" - switch to\n\"Vul de wallet eerst aan\" per CodeRabbit review on #5292.",
          "is_bot": false,
          "headline": "fix(keysign): friendly message for unfunded Cosmos accounts (#5292)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-14T22:21:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4ba569f8147b3f206898ac557dcb414e06233422",
          "body": "…0 (#5276) (#5288)\n\nRippleApi.getBalance() swallowed every non-cancellation exception into\nBigInteger.ZERO, so a network timeout was indistinguishable from a\ngenuinely empty account and the UI committed a false $0.00 — reading as\n\"the funds disappeared\".\n\nLet the failure propagate: AccountsRepositor\n[…]\nnstead of\nflattening it into an IllegalStateException with no cause, so the\ntransport kind (timeout / no connectivity) survives for classification.\n\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(ripple): propagate balance fetch failures instead of showing $0.0…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-14T12:28:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7d6eb0c815c91edeb09e1fb58d7c573439a68f7d",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to 1.0.114 (#5289)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-14T10:29:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90c4fda6fe026833522478c386fb261c7c49bea9",
          "body": "…d) (#5277) (#5281)\n\n* fix(ripple): treat expired/unconfirmed XRP tx as neutral, not Error (#5277)\n\nXRPL returns a txnNotFound error response for a tx that never reached a\nvalidating node before its LastLedgerSequence. getTsStatus deserialized\nstrictly into the success shape and threw MissingFieldEx\n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "XRP send shows 'Error' when tx expired/never confirmed (no funds move…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-14T10:06:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "335682e4633bb1b58181a3d45a552e427d921769",
          "body": "…(#5280)\n\nWhen the OS reclaims the process, tapping a keysign push notification\ncold-starts MainActivity and replays the full branded AnimatedSplash\nbefore the keysign flow appears, so the cold path looks like the app\nrestarting from scratch — unlike the warm onNewIntent path which shows\nno splash.\n\n[…]\n destination resolves\n(isLoading) rather than starting on the stale Route.Home default, then\nroute straight into the keysign flow.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): skip branded splash on notification cold start (#5269) …",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-14T09:56:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0ec13342c1c4e34ebad3a9c7e871cc3d9fc307b7",
          "body": "…rongly shows \"Add to Address Book\" (#5272) (#5278)\n\n* fix(keysign): resolve To-address to vault name via pubkey-derived address on joined devices (#5272)\n\nThe To field resolved dstVaultName by matching the destination only against\neach vault's enabled coins. On a joined co-signer the destination co\n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Joined device doesn't resolve To-address to saved vault/contact and w…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-14T09:53:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "451bedbc54b367965fd86672f0ad775c60319965",
          "body": "…e fee is ready (#5270) (#5273)\n\n* style: apply ktfmt formatting (#5270)\n\n* fix: re-arm gas-fee loading state on recomputes (#5270)\n\nisGasFeeLoading was only ever set false, so the shimmer + disabled\nContinue happened only on the first estimate. Add collectGasFeeLoading()\nto set it back to true when\n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Send: Network Fee shows nothing while loading; Continue enabled befor…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-14T09:50:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3e4ad01e6d5df798f73eb51f048b016af913f25b",
          "body": "…(#5283)\n\n* fix(tron): operation-aware Verify header for freeze/unfreeze (#5274)\n\nTRON freeze/unfreeze routes through the Send form and carries its\noperation only as an internal memo prefix (FREEZE:/UNFREEZE:<resource>).\nBy the Verify layer no operation signal survived, so the last\npre-signing check\n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tron): operation-aware Verify header for freeze/unfreeze (#5274) …",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-14T09:42:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0c9e64e9bf7feb126274877ae89bc3410053dc70",
          "body": "…success (#5266)\n\n* fix(broadcast): on-chain verify Cosmos/QBTC code-32 before reporting success\n\nThe joined-device duplicate-broadcast recovery trusted a Cosmos code=32\n(account sequence mismatch) blindly and returned the local hash as success —\nso a sequence consumed by an unrelated tx surfaced a \n[…]\nunded / Failed; only Pending / NotFound / TimedOut propagate the rejection.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(broadcast): on-chain verify Cosmos/QBTC code-32 before reporting …",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-13T22:23:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "965aebc72b70d6948fd2d393fa9121c9f2f61f90",
          "body": "…g (#5267)\n\n* fix(cardano): emit Conway-era 4-element tx envelope with is_valid flag\n\nWalletCore's compileWithSignatures emits the legacy 3-element Cardano\nenvelope [body, witness_set, aux_data]. Conway-era nodes reject it and\nrequire the 4-element form [body, witness_set, is_valid, aux_data].\n\nSpli\n[…]\n SwapKitCardanoSigner's walker. Also\nhardens extractCardanoTransactionBody.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cardano): emit Conway-era 4-element tx envelope with is_valid fla…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-13T22:23:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c1bb9b50ce92502b5eb39741f295b8bec28d281f",
          "body": "…(#5264)\n\n* fix(thorchain): treat bRUNE as an LP token so it's excluded from asset pickers\n\nThe `isLpToken` equality check for `x/brune` sat under the `Chain.MayaChain`\nbranch, but `x/brune` is a THORChain bank denom — so the check was unreachable\nand bRUNE was never filtered out of the swap/asset-s\n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(thorchain): add bRUNE & ybRUNE (display, pricing, LP exclusion) …",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-13T11:07:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "72ae8b96314145462b1b1b5be373c03b593352a5",
          "body": "…246)\n\n* fix(solana): sign dApp raw transactions over their original bytes\n\nCo-signing a dApp-supplied raw Solana transaction decoded it into\nWalletCore's representation and re-serialized it before hashing and\nsigning. That re-encode is not guaranteed to reproduce the original\nbytes for a v0 message\n[…]\nature-count decode into a small\ndocumented helper so parseRawTransaction reads as pure structure, and\nreplace the magic 64 with a named SIGNATURE_LENGTH constant that also\nguards the signature splice.",
          "is_bot": false,
          "headline": "fix(solana): sign dApp raw transactions over their original bytes (#5…",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-12T22:49:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2f0e6368089a8786f18d20d972e338a9a5f3fb31",
          "body": "* feat(solana): staking foundation + validator-metadata seam (Phases 1-2 of #5078)\n\nPhase 1 — Foundation: Solana stake-account/validator/epoch models, staking\nconfig, and RPC + caching read layer (getVoteAccounts / getProgramAccounts /\ngetEpochInfo / getMinimumBalanceForRentExemption). No UI, no sig\n[…]\no-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(solana): native staking on the DeFi tab (epic #5078) (#5239)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-12T22:37:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0d7c97c7af4d9bcefcd4df598e36a2fb1723ede4",
          "body": "… RequireDest gate) (#5247)\n\n* feat(ripple): dedicated XRP Destination Tag field (+ X-addr autofill, RequireDest gate)\n\nAdds first-class XRPL destination-tag support to the XRP send flow, mirroring\nthe iOS combo design (vultisig-ios#4749).\n\n- Sync commondata submodule to include RippleSpecific.desti\n[…]\nwe\n  intentionally keep it as free text rather than claim exact iOS parity.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ripple): dedicated XRP Destination Tag field (+ X-addr autofill,…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-12T09:57:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c2f0b5073e45ec28dc5382a801ef4b9f77c3e22d",
          "body": "…wn Confirmed (#5263)\n\nEvery TON send is signed with IGNORE_ACTION_PHASE_ERRORS, so a transfer that\ncan't be paid for (e.g. value+fees exceed balance under PAY_FEES_SEPARATELY) is\nsilently skipped instead of aborting: the wallet tx lands un-aborted with the\nseqno consumed but no funds moved. TonStat\n[…]\ng-sdk#1119).\n\nCovered by 13 unit tests, including the exact aborted:false + no_funds:true case\nand a verbatim production toncenter payload decoded through the real\nserialization pipeline.\n\nFixes #5249",
          "is_bot": false,
          "headline": "fix(ton): detect action-phase failures so failed transfers aren't sho…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-12T09:26:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b8c8d71487537e4563d7015f13562c5b4cd6a98d",
          "body": "* fix(deposit): remove duplicate Amount row on Function overview (#5216)\n\nThe amount is already shown in the \"You're sending\" header\n(SwapToken) at the top of the summary card. The separate \"Amount\"\nrow below repeated the same value, adding redundant visual noise.\n\nRemove the row and the now-unused \n[…]\nmissal is\npreserved, and the opt-in stays scoped to this one screen.\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(reshare): adopt new Figma reshare-flow entry (#5175) (#5222)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-12T09:23:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "04170b107747ea384ef531b8719483a54110a47c",
          "body": "Base's provider-table arm has offered only LIFI/THORCHAIN/SWAPKIT since\nthe table was created (#4313), while iOS and the SDK both quote 1inch and\nKyberSwap on Base. Both are same-chain aggregators (sameChainOnly), so the\narm now matches the BSC/Avalanche EVM pattern via the shared\nthorchainPlusEvmAggregators / evmAggregators sets.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): enable 1inch and KyberSwap on Base (#5255, #5256) (#5259)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-12T08:47:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "507cba016837e5ce2f13f6c2c1a89c3944257d7d",
          "body": "…5261)\n\n* fix(thorchain): read on-chain sRUJI receipt for Staked RUJI amount (#5258)\n\nThe DeFi Staked RUJI amount was read from the Rujira GraphQL `bonded`\nfield, which returns 0 even when the vault holds x/staking-x/ruji receipt\ntokens on-chain — so real positions showed 0. Two root causes:\n\n- `sta\n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(thorchain): read on-chain sRUJI receipt for Staked RUJI amount (#…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-12T08:16:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a00400372a68114a382563ed7a64325224338591",
          "body": "…ing (#5260) (#5262)\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: add horizontal padding to I understand button on Backups onboard…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-12T07:35:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3e878b29321701825efa4e9d64f0307e8014612e",
          "body": "…#5257)\n\n* fix(ton): apply wallet-level bounceable to every TonConnect message\n\nMulti-message TonConnect swaps (e.g. STON.fi) never finished co-signing:\nthe joiner polled GET /router/setup-message forever (404). In DKLS keysign\nthe setup message is keyed by md5(pre-image-hash), so a co-signer that\nc\n[…]\nce flag for pool comments to match the initiator.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ton): apply wallet-level bounceable to every TonConnect message (…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-12T06:42:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7020dcc4e6d5d460ada4f67f6148b2bb91b9c7ee",
          "body": "…s success (#5254)\n\n* fix(broadcast): verify tx on-chain before reporting dedup rejections as success\n\nThe per-chain broadcast dedup heuristics accepted string evidence without an\non-chain check, so genuine rejections surfaced as success (issue #5250):\n\n- EVM: drop the bare \"known\" match (also match\n[…]\nccess\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>\nCo-authored-by: Roman <32820910+rkokhatskyi@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(broadcast): verify tx on-chain before treating dedup rejections a…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-12T06:27:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "114c81e0f33019c2e2e1a629398d0d2cb144e9ed",
          "body": "…253)\n\nRippleStatusProvider marked a tx Confirmed on RPC-level status==\"success\",\nwhich for the XRPL `tx` method only means the tx was found. That reported\nvalidated tec* failures (fee burned, no funds delivered) as Confirmed, and\nmade not-yet-validated txs terminally Confirmed even if later dropped\n[…]\n AND meta.TransactionResult==\"tesSUCCESS\";\ntec* -> Failed(code); unvalidated or meta-absent -> keep polling. Mirrors the\nSolana finalized gate.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ripple): gate Confirmed on validated + meta.TransactionResult (#5…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-10T22:14:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ccfa1fd7f81c07a6bfc68d4c0668a0554f49b5fa",
          "body": "getTokenAssociatedAccountByOwner made a single getTokenAccountsByOwner call\nand treated an empty or failed response as \"no token account\". Right after an\nATA is created the indexer can lag, which gave the sender a false \"missing\ntoken account\" error and made the recipient path try to recreate an ATA\n[…]\ned-token addresses and confirm existence with a direct getAccountInfo\nlookup before concluding the account is missing. A normal successful lookup is\nunchanged. Mirrors iOS SolanaService.\n\nCloses #5224",
          "is_bot": false,
          "headline": "fix(solana): fall back to ATA derivation when the indexer lags (#5245)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-09T23:06:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5366edb53509182ca1b66524d87778e0f623f432",
          "body": "The inbound keysign payload mapper parsed the Solana `compute_limit`\nfield with a throwing `toBigInteger()`, so a peer sending a non-numeric\nstring crashed the receiving device with an uncaught NumberFormatException\nduring a keysign ceremony. The sibling `priority_fee` field already fails\nsoft; mirror it with `toBigIntegerOrNull()` so malformed input falls back\nto the default compute-unit limit. Valid values, including an explicit 0,\nare parsed unchanged.",
          "is_bot": false,
          "headline": "fix(solana): fail soft on malformed inbound compute_limit (#5244)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-09T23:03:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06f9c23244d61a17a263fa2d6145d2075683e911",
          "body": "* feat(keysign): animate signing → broadcast → result transitions\n\nThe broadcast flow advanced between states with hard screen cuts. Wrap the\ntwo render seams in Compose transitions so it reads as one screen updating\nin place:\n\n- KeysignView: AnimatedContent over a coarse phase key (progress/finishe\n[…]\no-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(keysign): animate signing → broadcast → result transitions (#5232)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-09T10:47:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bd850632851dabf8a1cde9c49a819e0c84127518",
          "body": "The Verify/Send overview screen rendered the Memo row whenever tx.memo\nwas non-null, so an empty-string memo produced a blank Memo label with\nno value, wasting vertical space in the summary card.\n\nGuard the row with isNullOrBlank() so it only appears when a memo is\nactually present. Also adds a PreviewActivity entry (verify_send_empty_memo)\ncovering the empty-memo case.\n\nFixes #5234\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(send): hide Memo row on Send overview when memo is blank (#5243)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-09T09:43:30Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "301920c80ef1aaea210ef129ca019ddbadca0bd6",
          "body": "… (#5240)\n\nThe custom-message keysign path (SigningHelper.getKeysignMessages) keccak256'd\nthe message for every non-EdDSA chain. But cosmos-family chains (THORChain,\nMaya, Cosmos, ...) sign the sha256 of the message — Keplr ADR-36 signArbitrary\nover the StdSignDoc bytes — so Android's digest, and th\n[…]\n> raw, everything else (EVM, Tron) -> keccak256.\n\nAdds ByteArray.toSha256ByteArray() and unit tests covering the cosmos sha256 path.\n\nCo-authored-by: ahdzib-maya <ahdzib-maya@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(keysign): sha256-hash cosmos custom messages instead of keccak256…",
          "author_name": "Itzamna",
          "author_login": "ahdzib-maya",
          "committed_at": "2026-07-09T02:00:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8ef5ce9921beb418fd78deca35576513e4105f7a",
          "body": "…5233)\n\nSolanaStatusProvider treated a non-null err as an immediately terminal\nFailed result regardless of confirmation level. Roughly 5% of Solana\nblocks at processed/confirmed never finalize (they can be forked out\nand re-included with a different outcome), so a transient err observed\nat that earl\n[…]\ntrictly\ninside the finalized case.\n\nRestructure the dispatch so err is only consulted once confirmationStatus\nis finalized; confirmed/processed/null all report Pending regardless of\nerr, matching iOS.",
          "is_bot": false,
          "headline": "fix(solana): gate tx-status err check to finalized commitment only (#…",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-09T01:39:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b31f74066b05bc15e7b01657c91ec75e49bd8030",
          "body": "The Cosmos bank endpoint returns every denom for an address in one\nresponse, but the balance layer calls it once per token — each picking a\nsingle denom and discarding the rest — so opening the Select asset sheet\nfired ~N identical GET /cosmos/bank/v1beta1/balances/{address} requests.\n\nAdd a shared \n[…]\ntrip whether the\ncalls arrive concurrently or back-to-back. getBalance is only used for\nbalance display and token discovery — never the signing/fee path — so a\nshort cache carries no correctness risk.",
          "is_bot": false,
          "headline": "fix(cosmos): coalesce per-token bank-balance requests (#5161) (#5230)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-09T00:17:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "86fa0e9ebd9872d92c54a2cefb0dae778a6919aa",
          "body": "…string (#5229)\n\n* fix(solana): throw on blockhash RPC error instead of returning empty string\n\ngetRecentBlockHash logged a JSON-RPC error response and returned \"\" instead\nof throwing, unlike the adjacent malformed/missing-result branch a few lines\nbelow it, which already throws. The empty string th\n[…]\nerror: ...\" reads\nas an internal detail rather than something a user should see. Reword to\nmatch the plain \"<Chain> RPC error: <message>\" idiom used elsewhere in the\napi package (DashApi, CardanoApi).",
          "is_bot": false,
          "headline": "fix(solana): throw on blockhash RPC error instead of returning empty …",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-08T10:56:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "94412cd269ad9d853428629cd4413e4d488c74ae",
          "body": "…200)\n\n* fix(thorchain): unbond MAX/percentage use bonded amount, not wallet balance\n\nThe THORChain unbond form reused the generic Send form with the wallet's\nspendable RUNE account, so MAX/percentage and the submit-time balance check\noperated on the wallet balance (max bondable) instead of the amou\n[…]\nnthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(thorchain): unbond MAX uses bonded amount, not wallet balance (#5…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-08T10:21:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bb90193467e3b8f681a5308444f1c703a8914033",
          "body": "* fix(deposit): remove duplicate Amount row on Function overview (#5216)\n\nThe amount is already shown in the \"You're sending\" header\n(SwapToken) at the top of the summary card. The separate \"Amount\"\nrow below repeated the same value, adding redundant visual noise.\n\nRemove the row and the now-unused \n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(deposit): remove duplicate Amount row on Function overview (#5221)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-08T09:39:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "60163b4297db26d6ab73393b61884c89604e5889",
          "body": "…y matches signed fee (#5218)\n\n* fix(terraClassic): price send fee at the effective gas limit so Verify matches the signed fee\n\nPorts vultisig-ios#4762. TerraClassicTax.baseGas already prices the base at\nthe (effective) gas limit up front, so chainSpecific.gas is the final fee.\nDrop the redundant sc\n[…]\n\n\n* docs(keysign): update stale fee-helper KDoc for Cardano/Cosmos branches\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(terraClassic): price send fee at the effective gas limit so Verif…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-08T09:39:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3e90f123652a3a499de6948921d9c905240ad831",
          "body": "…#5220)\n\nReplace the bespoke Scaffold + VsTopAppBar + ad-hoc 16dp padding with the\nstandard V3Scaffold so the screen matches the app-wide V3 content inset\n(24dp horizontal / 12dp vertical), topbar, and background. The bottom CTA\npadding now references the V3Scaffold companion constants.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(referral): migrate Create Referral screen to V3Scaffold (#5219) (…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-08T00:36:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "746b311913a47c8055c9d987c92f09bca5ca813c",
          "body": "…08) (#5215)\n\nRippleApi.getBalance already returns the owner-aware, reserve-net balance\n(base + OwnerCount * increment reserves subtracted live from server_state),\nso the account tokenValue reaching ChainValidationService.checkIsReapable is\nalready net of the true on-chain reserve.\n\ncheckIsReapable \n[…]\nales\nand cover the XRP MAX / reserve-band cases in ChainValidationServiceTest.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(ripple): stop double-counting XRP reserve in reaping warning (#52…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-08T00:15:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "862b755961be81e0b1a1f556adc79d6c88ab9e58",
          "body": "…86) (#5214)\n\n* fix(send): reject hex/scientific-notation amounts before signing (#5186)\n\nThe send amount field's InputTransformation blocks non-decimal characters\nfrom IME and paste, but a `vultisig://send?...&amount=1e5` deeplink writes\nthe amount into the field programmatically via setTextAndPlac\n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(send): reject hex/scientific-notation amounts before signing (#51…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T10:07:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "10b963c770a34bfaf43407180b296f813d5d0c1f",
          "body": "…5213)\n\nThe coin badge used width()/height(), which the header card's fixed\n118dp height clamped down — so the badge rendered small and fully\ncontained instead of the large, edge-bleeding badge in the Figma spec.\n\nSwitch to requiredWidth/requiredHeight so the drawable keeps its\nintended 200.78×206 size and its concentric gold ring bleeds past the\ncard edge (clipped by the card's rounded shape), matching the design.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(qbtc): size Claimable QBTC header badge to match Figma (#5072) (#…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T10:04:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fc1af83ef408b7fe53036027162117ad2953080c",
          "body": "* feat(cosmos): honor relayed CosmosSpecific.gas_limit in the SignDoc (#5112)\n\nReads the relayed per-tx gas limit (commondata CosmosSpecific.gas_limit, field\n7) and uses it as the signed fee gas limit when an initiator sets one, falling\nback to the static per-chain limit otherwise. The value is part\n[…]\no-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(cosmos): honor relayed CosmosSpecific.gas_limit (#5112) (#5191)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T09:21:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1d3ee3c18a72433591e6ed87b0929b9f699c6c56",
          "body": "…never detected (#5162) (#5192)\n\n* fix(swap): resolve Omniston (TON) swap settlement on-chain (#5162)\n\nA same-chain TON swap routed through Omniston deposits the source jettons\ninto an escrow; SwapKit's /track only sees the deposit leg and reports\n`completed` with `fromAsset == toAsset`, so the app \n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Omniston (TON) swap shown as successful when escrow refunds — refund …",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-07T05:18:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e37765f490582c96659c6f49ddd815c1de9a345e",
          "body": "* feat(ton): gate TON DeFi staking and remove generic-deposit stake path\n\nTON staking now lives exclusively on the DeFi tab. Add Chain.Ton to the\nDeFi-supported / crypto-connection sets, and drop it from isDepositSupported +\nthe generic deposit option list so Stake/Unstake no longer surface in the\nF\n[…]\n\n* style: rewrap comment in TonDeFiBalanceService\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ton): TON nominator-pool staking on the DeFi tab (#5041) (#5133)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T01:56:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a5ab0f4e870d6f5c915c508f2f5c00ac73a7e8e7",
          "body": "…ast failure (#5207)\n\nXRPL echoes the deterministic tx_json.hash back regardless of engine result.\nPreviously a rejected submit returned the engine message as a fake txid, so the\nkeysign persisted a garbage hash instead of surfacing the failure.\n\nPort the iOS RippleService classification into Ripple\n[…]\nef*) throws a typed\n  RippleBroadcastException carrying the engine code + message.\n- broadcastTransaction does HTTP in a try (rewrapping non-broadcast errors),\n  then classifies the result outside it.",
          "is_bot": false,
          "headline": "fix(ripple): stop returning the error string as the tx hash on broadc…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T01:56:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "45f9d14523fca22d9bf60f5c2589581bcee6fc79",
          "body": "The swap \"Transaction pending\" done screen renders the Track button only\nwhen getSwapProgressLink() returns a non-blank URL. For EVM/Solana swaps\nthat link was gated behind the affiliate swapFee parsing as a BigInteger,\nbut EVMSwapQuoteJson.swapFee defaults to \"\" and \"\".toBigIntegerOrNull()\nis null.\n[…]\n the link\nfrom the src chain + tx hash (both always present for a broadcast swap).\nSwapKit-routed swaps are unaffected: they return earlier from the\ntrack.swapkit.dev branch before reaching this code.",
          "is_bot": false,
          "headline": "fix(swap): decouple Track link from parseable swapFee (#5206)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T01:20:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d78bb3044505c73e8d4f7e747fa0284ffa8727e",
          "body": "…s (#5204)\n\nThe foreground \"Join transaction\" banner popped in with no entrance\nanimation whenever a new signing request arrived. `key(qrCodeData)`\ndisposes and recreates the overlay AnimatedVisibility on each new\nrequest, so the node is born with `visible == true` and the\n`visible: Boolean` overloa\n[…]\nthe reserved-space expand) run on the freshly keyed node.\nThe key(qrCodeData) is kept, preserving the swipe-offset reset behavior.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(banner): restore Join-transaction banner slide-in for new request…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-07T01:12:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "127213368b9d8c03dcf8e1b2cfa8fc0976ac0bc4",
          "body": "…5203)\n\nThe Export Vaults flow could leave the user with a broken 0 KB archive:\na 1-character backup password validated as Valid (only non-empty +\nmatching were checked), and any export failure left the empty file SAF\nhad already created on disk with only a transient, generic snackbar.\n\n- Enforce a \n[…]\nrings for the two new messages across all locales.\n- Add regression tests for length validation and failure cleanup.\n\nCloses #5197\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(backup): validate PIN length and clean up failed vault exports (#…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-06T12:15:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "29615c6689450ca20d0a24c4427c4c146b79e4c8",
          "body": "…199)\n\nKeysignTxStatusPoller (which binds the running foreground service) and\nKeysignFlowViewModel.complete() (which cancels its notification) each\ninjected their own TransactionStatusServiceManager. Without a shared\nscope, completion cancelled a never-bound instance and the notification\nwas left showing after the transaction settled.",
          "is_bot": false,
          "headline": "fix(keysign): scope tx-status notification manager as a singleton (#5…",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-06T11:06:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae1acc81cd5a37616c5024a60eda124a82a58b64",
          "body": "…(#5198)\n\n* fix(tokens): require connectivity and retry on token-refresh failure\n\nToken discovery work now sets a NetworkType.CONNECTED constraint and\nreturns Result.retry() when a chain refresh fails, instead of a\nconstraint-free request that runs offline and either fails permanently\nor silently dr\n[…]\n-tokens read failure path\n\nTokenRefreshWorkerTest only exercised getRefreshTokens() throwing;\nadd a case for vaultRepository.getEnabledTokens() throwing, the other\nretryOrFail() call site in doWork().",
          "is_bot": false,
          "headline": "fix(tokens): require connectivity and retry on token-refresh failure …",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-06T10:57:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4d772b9c4c12336cea76046b2b8c20be5887244b",
          "body": "…5195)\n\n#5121 reports the SwapKit EVM verify-screen Network Fee as understated —\ntaken from SwapKit's near-zero `fees[].inbound` placeholder instead of the\noracle-priced broadcast gas, with the same understatement feeding the\ngas-sufficiency check. Tracing the code, that does not hold on Android: a\n\n[…]\nted Fees\" row; Network Fee and Total are the oracle bond.\n\nThis is the Android mirror of the iOS parity test in vultisig-ios#4723.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(swap): pin SwapKit EVM network fee to the oracle bond (#5121) (#…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-06T10:29:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3338603636f4c159d13f3da5089323a58fc935cf",
          "body": "…#5174) (#5190)\n\nLocks the #5115 fix (PR #5156): getFeeForMessage already folds the\nComputeBudget priority fee into the message fee, so the send estimate is\nmessageFee + rentExemption — never messageFee + priority + rent.\n\nThe path was previously untestable because constructing SolanaFeeService\ntrig\n[…]\n native SOL, SPL (with/without recipient token account), and\nthe swap default path's micro-lamports-per-CU to lamports conversion.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(solana): guard send fee estimate against priority double-count (…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-06T09:46:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c625e621dee75ab4389155d9812601f20b0d97ff",
          "body": "Co-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>",
          "is_bot": false,
          "headline": "style: apply ktfmt formatting (#5187) (#5189)",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-06T09:38:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f5e76e9ca320c12d5af826e04fe8294a47d8fc21",
          "body": "…(#5172)\n\n* fix(swap): show refund/failure reason on the transaction done screen (#5152)\n\nWhen a swap is refunded or fails, the app already resolves a human-readable\nreason (e.g. \"deposits are paused for asset (ETH.USDT…)\") and carries it on\nTransactionStatus.Refunded/Failed. The done screen — the e\n[…]\n\nCo-Authored-By: aminsato <Amin.saradar@yahoo.com>\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): show refund/failure reason on the transaction done screen …",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-06T09:17:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c867fa53405720f1e7a1d4f0285adf6c93930af",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to 1.0.113 (#5183)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-06T00:35:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8bfe1275f39198c6211d564b9c1b5016ed0f2be",
          "body": "* fix(qbtc): block claim co-sign when the vault password is empty\n\nNeither the password sheet's Confirm button nor the ViewModel guarded\nagainst a blank password, so the IME \"Go\" action (and, on an unmodified\nbutton, a tap) could reach the server co-sign call with nothing typed.\nDisable Confirm whil\n[…]\na password of only spaces through to the co-sign call.\nSwitch both the ViewModel guard and the sheet's canSubmit check to\nisBlank() so an all-whitespace entry is rejected the same way an empty\none is.",
          "is_bot": false,
          "headline": "fix(qbtc): block claim co-sign when the vault password is empty (#5182)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-05T23:50:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4d6d587ce3891bed0a056a3108c509730ca7d6b2",
          "body": "* fix(send): block XRP/DOT sends that would fall below the chain reserve\n\nMAX and manually-entered near-full sends on Polkadot and XRP could pass\nclient-side validation, run the full MPC signing ceremony, and still get\nrejected on-chain because the existential deposit / account reserve was\nonly ever\n[…]\nunderlying cause. Log it via Timber so a\ntransient RPC failure stays debuggable, matching the BTC-like plan\nerror path in the same file.\n\n---------\n\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(send): block XRP/DOT sends below the chain reserve (#5180)",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-05T23:35:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "45d1173e62e700fb0f333d16d67def0b7706e647",
          "body": "* fix(keysign): reach a terminal state on a hashless broadcast\n\nA successful broadcast that yields no tx hash (Broadcasted.txHash is\nnullable; orKnownHash returns null when both the RPC hash and the local\ntx hash are blank) left signingState stuck at the last signing state —\nan infinite spinner with\n[…]\now before the terminal state lands and invite a\n  force-retry double-send).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): reach a terminal state on a hashless broadcast (#5170)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-05T23:05:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3278ed057b55c0b53ca28bd0e367c24d805a03dd",
          "body": "…kup (#5177)\n\n* fix(backup): wait for the vault list before writing an all-vaults backup\n\nBackupPasswordViewModel and BackupPasswordRequestViewModel loaded the vault\nlist asynchronously in init but backupAllVaults/backupWithoutPassword read it\nfrom a plain var with no guard, so a backup requested be\n[…]\n performs; poll with coVerify's\n  timeout instead of asserting immediately after completing the gate.\n- Switch the new tests from kotlin.test to Kotest assertions per the\n  project's test conventions.",
          "is_bot": false,
          "headline": "fix(backup): wait for the vault list before writing an all-vaults bac…",
          "author_name": "Roman",
          "author_login": "rkokhatskyi",
          "committed_at": "2026-07-05T23:04:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "27286e02007c769da33303db85c0ffc96fdcfff5",
          "body": "…re 4.7.0) (#5169)\n\n* feat(cardano): attach send memo on-chain as CIP-20 metadata (label 674)\n\nCardano's send memo was previously typed by the user but silently dropped at\nsigning time (the TODO in CardanoHelper). WalletCore 4.7.0 exposes the native\nCardano.SigningInput.auxiliary_data field, so we c\n[…]\neply@anthropic.com>\n\n* clarify memo field is optional in GasFeeOrchestrator\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cardano): attach send memo on-chain as CIP-20 metadata (WalletCo…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-05T22:47:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5dec8d9b082c1c5bd004175ef7462fedb2ba0535",
          "body": "…s (#5171)\n\n* fix(ripple): populate the canonical transaction hash on signed XRP txs\n\nRippleHelper.getSignedTransaction returned an empty transactionHash,\nunlike every other chain helper. The empty hash left XRP sends\nuntrackable (status polling, explorer deep-links) and also disabled the\nduplicate-\n[…]\ndoc\n\nThe hash prefix is 0x54584E00 (TXN + zero byte), not a trailing space.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ripple): populate the canonical transaction hash on signed XRP tx…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-05T11:44:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e5f3c966a63ca24e834e56911496b3efff8f41ea",
          "body": "WalletCore's `zip_0317` planner sizes an OP_RETURN output at a flat ~34\nbytes and ignores `byteFee`, so ZEC memo transactions (MayaChain-routed\nswaps carry the swap instruction in an OP_RETURN; sends with memo too)\nplan one logical action short — e.g. 15,000 zats where the network\nrequires 20,000. E\n[…]\ne plan-level golden\nvectors mirror iOS against the same wallet-core 4.7.0 pin.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(zcash): re-plan memo txs to the ZIP-317 conventional fee (#5165)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-05T01:59:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2980c449b725b2428a2cadc458c1579062306535",
          "body": "…ic (#5164)\n\n* feat(terra): support adding custom CW20 tokens on Terra / Terra Classic\n\nLet users add a custom CW20 token by pasting the contract address on\nthe custom-token screen — parity with the extension and iOS (#4733).\nSearchTokenUseCase previously dispatched only EVM / SOL / Kujira, so a\nter\n[…]\nay consistent.\n\nAddresses CodeRabbit review feedback on the PR.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(terra): support adding custom CW20 tokens on Terra / Terra Class…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-04T23:21:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1d7406ab4d2120c29eea94fcd2e7d334f62ec099",
          "body": "… SUI sign (#5168)\n\nPulls in commondata updates:\n- feat(keysign): add CosmosSpecific.gas_limit for relayed dynamic gas\n- feat(tokens): rebrand TON native token to GRAM\n- feat: SUI signing support\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(commondata): bump submodule for cosmos gas_limit, GRAM rebrand,…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-04T22:45:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "685be91ce729b8db10b176ae3f977c445784f9ab",
          "body": "…5160)\n\nTHORChain's only Cosmos Hub pool is native ATOM, but the provider table\noffered THORCHAIN for every GaiaChain coin. Selecting an IBC token like\nrKUJI as the destination sent `GAIA.rKUJI-ibc/...` to Thornode, which\ndeterministically 400s with \"bad to asset: invalid symbol\" — surfaced as\nthe m\n[…]\napError, so any\n  remaining path that reaches the node reports the route as unsupported\n  rather than suggesting an amount change.\n\nCloses #5113\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): stop offering unroutable Cosmos IBC tokens on THORChain (#…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-04T10:23:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "65b6c2bf05caca005edd8f86cb5cf93651bb46c9",
          "body": "…ly fails (#5158)\n\n* fix(keysign): stop joined device faking a txid when broadcast genuinely fails\n\nrecoverJoinedDeviceBroadcast swallowed every non-cancellation exception on a\njoined (co-signing) device and returned the locally computed hash, showing a\nsuccess screen + explorer link for a transacti\n[…]\ns; never recover for the initiator or a blank hash;\npropagate cancellation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): stop joined device faking a txid when broadcast genuine…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-04T10:14:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fddab24a709420048e621a147ab0d57c50618b21",
          "body": "The \"enable post-quantum key\" (Dilithium/MLDSA keygen) option in advanced\nvault settings was shown for GG20 vaults, but a GG20 vault can't run the\nDKLS-based keygen — it must migrate to DKLS first. The option was gated on\n`libType != KeyImport`, which let GG20 through.\n\nGate it on `libType == DKLS` \n[…]\nt import, and GG20 vaults are now excluded. Since the settings screen\nfilters out `isEnabled = false` items, the row is hidden for GG20 vaults.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(settings): hide post-quantum keygen for legacy GG20 vaults (#5157)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-04T01:00:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7723ed5208ebb06c1bb760912e4bb8ddf53c3030",
          "body": "* feat(qbtc): add \"New quantum security\" intro screen before claim (#5074)\n\nIntroduces the onboarding/explainer screen that precedes the QBTC claim\nflow. The hero area plays the quantum_key_pair Rive animation inside a\ndashed frame, followed by three explainer rows (generate key pair, link\nto vault,\n[…]\naim routing, dilithium\nkeygen enablement, and intro navigation.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(qbtc): \"New quantum security\" intro screen before claim (#5123)",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-03T09:47:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3bddbc03114f3c9d94fea04d42fab557cbc3bdfc",
          "body": "…#5156)\n\ngetFeeForMessage already includes the prioritization fee, because the\nserialized message carries the ComputeBudget (SetComputeUnitPrice /\nSetComputeUnitLimit) instructions. calculateFees then added a second\npriority term on top, so the displayed SOL network fee was\nbase + 2x priority + rent\n[…]\nbase + 100000 priority at the 1,000,000 uLam/CU floor).\n\nTake the RPC message fee as the full base+priority and only add\nrent-exemption on top.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(solana): stop double-counting priority fee in send fee estimate (…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-03T09:22:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6ac25725603872d1bd62fd8502dd01fc52f48675",
          "body": "…ing parity (#5154)",
          "is_bot": false,
          "headline": "chore(deps): bump wallet-core 4.6.13 -> 4.7.0 for cross-platform sign…",
          "author_name": "paaao",
          "author_login": "realpaaao",
          "committed_at": "2026-07-03T07:53:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7fead7ab650673fc3949b9e5acfb52d469e0d673",
          "body": "Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.0.112 (#5153)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-03T01:19:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d3f2d2d1b352483408181ff56c3fe4347f9f557e",
          "body": "…top it covering home content (#5134) (#5144)\n\nThe \"Join transaction\" foreground banner had two blocking-popup UX flaws:\n\n- Dismissal was wired to horizontal drag only, so the natural swipe-up\n  did nothing and the banner read as non-dismissable. Switch to\n  detectDragGestures and accept an upward f\n[…]\npushed down while the banner is\n  shown; the overlay itself is unchanged, preserving its status-bar bleed\n  and rounded-corner gradient reveal.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): make Join-transaction banner swipe-up dismissable and s…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-07-02T23:02:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "90d5e5f96865e8ac3d61bd76b74b4e281e19017e",
          "body": "…ching master (#5138) (#5139)\n\n* style: apply ktfmt formatting (#5138)\n\n* fix: revert out-of-scope comment reformat in JupiterSwapQuoteJson (#5138)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* style: apply ktfmt formatting (#5138)\n\n* fix: canonicalize TON addresses before\n[…]\n-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Vaulty-bot <vaulty-bot@vultisig.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "TON: wrong jetton balance shown first jetton wallet taken without mat…",
          "author_name": "Vaulty",
          "author_login": "Vaulty-bot",
          "committed_at": "2026-07-02T11:55:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1412,
      "latest_release_at": "2026-07-14T10:27:19Z",
      "latest_release_tag": "v1.0.114",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 52,
      "days_since_latest_release": 7,
      "mean_days_between_releases": 4.5
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 50,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 16,
      "stars": 21,
      "watchers": 2,
      "fork_history": {
        "days": [
          {
            "date": "2024-05-22",
            "count": 1
          },
          {
            "date": "2024-06-12",
            "count": 1
          },
          {
            "date": "2025-02-05",
            "count": 1
          },
          {
            "date": "2025-02-09",
            "count": 1
          },
          {
            "date": "2025-03-09",
            "count": 1
          },
          {
            "date": "2025-12-17",
            "count": 1
          },
          {
            "date": "2026-01-21",
            "count": 1
          },
          {
            "date": "2026-03-05",
            "count": 1
          },
          {
            "date": "2026-03-16",
            "count": 1
          },
          {
            "date": "2026-03-26",
            "count": 1
          },
          {
            "date": "2026-04-02",
            "count": 1
          },
          {
            "date": "2026-04-27",
            "count": 1
          },
          {
            "date": "2026-05-05",
            "count": 2
          },
          {
            "date": "2026-07-08",
            "count": 1
          },
          {
            "date": "2026-07-20",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 16,
        "total_forks": 16
      },
      "star_history": {
        "days": [
          {
            "date": "2024-04-22",
            "count": 1
          },
          {
            "date": "2024-05-25",
            "count": 1
          },
          {
            "date": "2024-05-28",
            "count": 1
          },
          {
            "date": "2024-06-15",
            "count": 1
          },
          {
            "date": "2024-08-12",
            "count": 1
          },
          {
            "date": "2024-09-02",
            "count": 1
          },
          {
            "date": "2024-11-24",
            "count": 1
          },
          {
            "date": "2025-04-21",
            "count": 1
          },
          {
            "date": "2025-06-21",
            "count": 1
          },
          {
            "date": "2025-07-11",
            "count": 1
          },
          {
            "date": "2025-10-14",
            "count": 1
          },
          {
            "date": "2025-12-08",
            "count": 1
          },
          {
            "date": "2026-01-19",
            "count": 1
          },
          {
            "date": "2026-01-30",
            "count": 1
          },
          {
            "date": "2026-04-21",
            "count": 1
          },
          {
            "date": "2026-05-01",
            "count": 1
          },
          {
            "date": "2026-05-07",
            "count": 1
          },
          {
            "date": "2026-05-11",
            "count": 1
          },
          {
            "date": "2026-05-14",
            "count": 1
          },
          {
            "date": "2026-05-28",
            "count": 1
          },
          {
            "date": "2026-07-20",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 21,
        "total_stars": 21
      },
      "open_issues_and_prs": 28
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "app/build.gradle.kts",
        "build.gradle.kts",
        "data/build.gradle.kts"
      ],
      "largest_source_bytes": 154512,
      "source_files_sampled": 1718,
      "oversized_source_files": 8,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 19254
    },
    "dependencies": {
      "manifests": [
        "Gemfile",
        "app/build.gradle.kts",
        "build.gradle.kts",
        "data/build.gradle.kts"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "faraday",
            "direct": false,
            "version": "1.10.5",
            "severity": "high",
            "ecosystem": "rubygems",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-98m9-hrrm-r99r"
            ],
            "fixed_version": "2.14.3",
            "advisory_count": 1,
            "oldest_advisory_days": 32
          },
          {
            "name": "jwt",
            "direct": false,
            "version": "2.10.2",
            "severity": "high",
            "ecosystem": "rubygems",
            "cvss_score": 7.4,
            "advisory_ids": [
              "GHSA-c32j-vqhx-rx3x"
            ],
            "fixed_version": "3.2.0",
            "advisory_count": 1,
            "oldest_advisory_days": 64
          },
          {
            "name": "excon",
            "direct": false,
            "version": "0.112.0",
            "severity": "moderate",
            "ecosystem": "rubygems",
            "cvss_score": 6.5,
            "advisory_ids": [
              "GHSA-48rx-c7pg-q66r"
            ],
            "fixed_version": "1.5.0",
            "advisory_count": 1,
            "oldest_advisory_days": 11
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 2,
          "moderate": 1
        },
        "advisory_count": 3,
        "affected_count": 3,
        "assessed_count": 95,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "maven",
        "rubygems"
      ],
      "dependencies": [
        {
          "name": "fastlane",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": "2.229.1"
        },
        {
          "name": "ostruct",
          "manifest": "Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": null
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "fastlane",
            "direct": true,
            "version": "2.229.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "ostruct",
            "direct": true,
            "version": "0.6.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "abbrev",
            "direct": false,
            "version": "0.1.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "addressable",
            "direct": false,
            "version": "2.9.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "artifactory",
            "direct": false,
            "version": "3.0.17",
            "ecosystem": "rubygems"
          },
          {
            "name": "atomos",
            "direct": false,
            "version": "0.1.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-eventstream",
            "direct": false,
            "version": "1.4.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-partitions",
            "direct": false,
            "version": "1.1201.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sdk-core",
            "direct": false,
            "version": "3.241.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sdk-kms",
            "direct": false,
            "version": "1.119.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sdk-s3",
            "direct": false,
            "version": "1.210.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sigv4",
            "direct": false,
            "version": "1.12.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "babosa",
            "direct": false,
            "version": "1.0.4",
            "ecosystem": "rubygems"
          },
          {
            "name": "base64",
            "direct": false,
            "version": "0.2.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "bigdecimal",
            "direct": false,
            "version": "4.0.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "CFPropertyList",
            "direct": false,
            "version": "3.0.8",
            "ecosystem": "rubygems"
          },
          {
            "name": "claide",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "colored",
            "direct": false,
            "version": "1.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "colored2",
            "direct": false,
            "version": "3.1.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "commander",
            "direct": false,
            "version": "4.6.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "csv",
            "direct": false,
            "version": "3.3.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "declarative",
            "direct": false,
            "version": "0.0.20",
            "ecosystem": "rubygems"
          },
          {
            "name": "digest-crc",
            "direct": false,
            "version": "0.7.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "domain_name",
            "direct": false,
            "version": "0.6.20240107",
            "ecosystem": "rubygems"
          },
          {
            "name": "dotenv",
            "direct": false,
            "version": "2.8.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "emoji_regex",
            "direct": false,
            "version": "3.2.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "excon",
            "direct": false,
            "version": "0.112.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday",
            "direct": false,
            "version": "1.10.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-cookie_jar",
            "direct": false,
            "version": "0.0.8",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-em_http",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-em_synchrony",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-excon",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-httpclient",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-multipart",
            "direct": false,
            "version": "1.2.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-net_http",
            "direct": false,
            "version": "1.0.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-net_http_persistent",
            "direct": false,
            "version": "1.2.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-patron",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-rack",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday-retry",
            "direct": false,
            "version": "1.0.4",
            "ecosystem": "rubygems"
          },
          {
            "name": "faraday_middleware",
            "direct": false,
            "version": "1.2.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "fastimage",
            "direct": false,
            "version": "2.4.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "fastlane-sirp",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "gh_inspector",
            "direct": false,
            "version": "1.1.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-apis-androidpublisher_v3",
            "direct": false,
            "version": "0.54.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-apis-core",
            "direct": false,
            "version": "0.11.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-apis-iamcredentials_v1",
            "direct": false,
            "version": "0.17.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-apis-playcustomapp_v1",
            "direct": false,
            "version": "0.13.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-apis-storage_v1",
            "direct": false,
            "version": "0.31.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-cloud-core",
            "direct": false,
            "version": "1.8.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-cloud-env",
            "direct": false,
            "version": "1.6.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-cloud-errors",
            "direct": false,
            "version": "1.5.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "google-cloud-storage",
            "direct": false,
            "version": "1.47.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "googleauth",
            "direct": false,
            "version": "1.8.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "highline",
            "direct": false,
            "version": "2.0.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "http-cookie",
            "direct": false,
            "version": "1.0.8",
            "ecosystem": "rubygems"
          },
          {
            "name": "httpclient",
            "direct": false,
            "version": "2.9.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "jmespath",
            "direct": false,
            "version": "1.6.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "json",
            "direct": false,
            "version": "2.19.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "jwt",
            "direct": false,
            "version": "2.10.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "logger",
            "direct": false,
            "version": "1.7.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "mini_magick",
            "direct": false,
            "version": "4.13.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "mini_mime",
            "direct": false,
            "version": "1.1.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "multi_json",
            "direct": false,
            "version": "1.19.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "multipart-post",
            "direct": false,
            "version": "2.4.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "mutex_m",
            "direct": false,
            "version": "0.3.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "nanaimo",
            "direct": false,
            "version": "0.4.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "naturally",
            "direct": false,
            "version": "2.3.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "nkf",
            "direct": false,
            "version": "0.2.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "optparse",
            "direct": false,
            "version": "0.8.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "os",
            "direct": false,
            "version": "1.1.4",
            "ecosystem": "rubygems"
          },
          {
            "name": "plist",
            "direct": false,
            "version": "3.7.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "public_suffix",
            "direct": false,
            "version": "7.0.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "rake",
            "direct": false,
            "version": "13.3.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "representable",
            "direct": false,
            "version": "3.2.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "retriable",
            "direct": false,
            "version": "3.1.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "rexml",
            "direct": false,
            "version": "3.4.4",
            "ecosystem": "rubygems"
          },
          {
            "name": "rouge",
            "direct": false,
            "version": "3.28.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "ruby2_keywords",
            "direct": false,
            "version": "0.0.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "rubyzip",
            "direct": false,
            "version": "2.4.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "security",
            "direct": false,
            "version": "0.1.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "signet",
            "direct": false,
            "version": "0.21.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "simctl",
            "direct": false,
            "version": "1.6.10",
            "ecosystem": "rubygems"
          },
          {
            "name": "sysrandom",
            "direct": false,
            "version": "1.0.5",
            "ecosystem": "rubygems"
          },
          {
            "name": "terminal-notifier",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "terminal-table",
            "direct": false,
            "version": "3.0.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "trailblazer-option",
            "direct": false,
            "version": "0.1.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "tty-cursor",
            "direct": false,
            "version": "0.7.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "tty-screen",
            "direct": false,
            "version": "0.8.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "tty-spinner",
            "direct": false,
            "version": "0.9.3",
            "ecosystem": "rubygems"
          },
          {
            "name": "uber",
            "direct": false,
            "version": "0.1.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "unicode-display_width",
            "direct": false,
            "version": "2.6.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "word_wrap",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "xcodeproj",
            "direct": false,
            "version": "1.27.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "xcpretty",
            "direct": false,
            "version": "0.4.1",
            "ecosystem": "rubygems"
          },
          {
            "name": "xcpretty-travis-formatter",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "rubygems"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 95,
        "direct_count": 2,
        "indirect_count": 93
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 4,
        "merged_prs": 2630,
        "open_issues": 24,
        "closed_ratio": 0.991,
        "closed_issues": 2537,
        "closed_unmerged_prs": 155
      },
      "bus_factor": 2,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "aminsato",
          "commits": 1098,
          "avatar_url": "https://avatars.githubusercontent.com/u/32006742?v=4"
        },
        {
          "type": "User",
          "login": "johnnyluo",
          "commits": 571,
          "avatar_url": "https://avatars.githubusercontent.com/u/749608?v=4"
        },
        {
          "type": "User",
          "login": "yvebe",
          "commits": 403,
          "avatar_url": "https://avatars.githubusercontent.com/u/14962060?v=4"
        },
        {
          "type": "User",
          "login": "JaimeToca",
          "commits": 288,
          "avatar_url": "https://avatars.githubusercontent.com/u/11850271?v=4"
        },
        {
          "type": "User",
          "login": "Vaulty-bot",
          "commits": 198,
          "avatar_url": "https://avatars.githubusercontent.com/u/257854823?v=4"
        },
        {
          "type": "User",
          "login": "yevhen1sec",
          "commits": 179,
          "avatar_url": "https://avatars.githubusercontent.com/u/173691873?v=4"
        },
        {
          "type": "User",
          "login": "rkokhatskyi",
          "commits": 172,
          "avatar_url": "https://avatars.githubusercontent.com/u/32820910?v=4"
        },
        {
          "type": "User",
          "login": "realpaaao",
          "commits": 37,
          "avatar_url": "https://avatars.githubusercontent.com/u/167348323?v=4"
        },
        {
          "type": "User",
          "login": "LucasFernandes01",
          "commits": 18,
          "avatar_url": "https://avatars.githubusercontent.com/u/25087381?v=4"
        },
        {
          "type": "User",
          "login": "gomesalexandre",
          "commits": 14,
          "avatar_url": "https://avatars.githubusercontent.com/u/17035424?v=4"
        }
      ],
      "contributors_sampled": 16,
      "top_contributor_share": 0.368
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "android.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": true,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "Gemfile.lock"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 9,
            "reason": "binaries present in source code",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 1,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "30 out of 30 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": 9,
            "reason": "Found 28/30 approved changesets -- score normalized to 9",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 6,
            "reason": "project has 2 contributing companies or organizations -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 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 19 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": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 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": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "2c230ced6fed249f439e9fbca9c707458f369ce1",
        "ran_at": "2026-07-22T03:21:00Z",
        "aggregate_score": 5.1,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-22T00:06:27Z",
      "oldest_open_prs": [
        {
          "number": 5331,
          "created_at": "2026-07-19T02:00:22Z",
          "last_comment_at": "2026-07-21T23:58:05Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 5364,
          "created_at": "2026-07-21T10:27:52Z",
          "last_comment_at": "2026-07-21T10:28:10Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 5368,
          "created_at": "2026-07-21T11:30:44Z",
          "last_comment_at": "2026-07-21T11:31:05Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 5369,
          "created_at": "2026-07-21T11:42:59Z",
          "last_comment_at": "2026-07-21T21:46:25Z",
          "last_comment_author": "Vaulty-bot"
        }
      ],
      "last_merged_pr_at": "2026-07-21T23:56:25Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 4006,
          "created_at": "2026-04-06T02:01:59Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4154,
          "created_at": "2026-04-23T01:21:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4331,
          "created_at": "2026-04-30T09:37:31Z",
          "last_comment_at": "2026-05-18T10:17:04Z",
          "last_comment_author": "realpaaao"
        },
        {
          "number": 5079,
          "created_at": "2026-06-28T20:20:55Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5080,
          "created_at": "2026-06-28T20:42:53Z",
          "last_comment_at": "2026-07-09T09:20:49Z",
          "last_comment_author": "Vaulty-bot"
        },
        {
          "number": 5210,
          "created_at": "2026-07-06T18:59:55Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5211,
          "created_at": "2026-07-06T18:59:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5212,
          "created_at": "2026-07-06T18:59:58Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5227,
          "created_at": "2026-07-08T08:08:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5235,
          "created_at": "2026-07-08T14:29:56Z",
          "last_comment_at": "2026-07-08T23:48:09Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 5252,
          "created_at": "2026-07-10T08:36:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5317,
          "created_at": "2026-07-18T05:18:21Z",
          "last_comment_at": "2026-07-19T10:11:05Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 5318,
          "created_at": "2026-07-18T05:18:24Z",
          "last_comment_at": "2026-07-20T07:33:01Z",
          "last_comment_author": "realpaaao"
        },
        {
          "number": 5334,
          "created_at": "2026-07-19T07:32:46Z",
          "last_comment_at": "2026-07-20T07:43:48Z",
          "last_comment_author": "realpaaao"
        },
        {
          "number": 5335,
          "created_at": "2026-07-19T07:43:13Z",
          "last_comment_at": "2026-07-20T07:43:47Z",
          "last_comment_author": "realpaaao"
        },
        {
          "number": 5343,
          "created_at": "2026-07-20T07:22:23Z",
          "last_comment_at": "2026-07-20T09:52:11Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 5344,
          "created_at": "2026-07-20T07:50:08Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5345,
          "created_at": "2026-07-20T07:50:20Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5348,
          "created_at": "2026-07-20T08:36:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5356,
          "created_at": "2026-07-20T15:20:06Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/vultisig/vultisig-android",
    "host": "github.com",
    "name": "vultisig-android",
    "owner": "vultisig"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 71,
      "inputs": {
        "security": 61,
        "vitality": 96,
        "community": 43,
        "governance": 72,
        "engineering": 74
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 96,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "excellent",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "commits_last_year": 1412,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 52
            },
            "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": "52/52 weeks with commits",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 52
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1412 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1412
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 19 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": 100,
              "latest_release_tag": "v1.0.114",
              "releases_from_tags": false,
              "days_since_latest_release": 7,
              "mean_days_between_releases": 4.5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 7 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 7
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~4.5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 4.5
                    }
                  }
                ],
                "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": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 43,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 31,
            "inputs": {
              "forks": 16,
              "stars": 21,
              "watchers": 2,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "below_threshold"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "21 stars",
                "points": 21.1,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 21
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "16 forks",
                "points": 9.8,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 16
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "2 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 57,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "good",
        "name": "Sustainability & Governance",
        "value": 72,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "moderate",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 59,
            "inputs": {
              "bus_factor": 2,
              "contributors_sampled": 16,
              "top_contributor_share": 0.368
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "2 contributor(s) cover half of all commits",
                "points": 25.2,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 37% of commits",
                "points": 14.2,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 37
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "16 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 16
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 96,
            "inputs": {
              "merged_prs": 2630,
              "open_issues": 24,
              "closed_issues": 2537,
              "issue_closed_ratio": 0.991,
              "closed_unmerged_prs": 155
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "99% of issues closed",
                "points": 46.3,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 99
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "2630/2785 decided PRs merged",
                "points": 36.1,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 2630,
                      "decided": 2785
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 28/30 approved changesets -- score normalized to 9",
                "points": 13.5,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 63,
            "inputs": {
              "followers": 132,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "vultisig",
              "public_repos": 72,
              "account_age_days": 906
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "132 followers of vultisig",
                "points": 15.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 132,
                      "login": "vultisig"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "72 public repos, account ~2 yr old",
                "points": 18,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 72
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 2
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 74,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "moderate",
        "name": "Security",
        "value": 61,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 51,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 5.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "binaries present in source code",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "30 out of 30 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 28/30 approved changesets -- score normalized to 9",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no 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 19 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 not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "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": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 95 resolved dependencies against OSV. This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 95
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 3,
              "affected_packages": 3,
              "assessed_packages": 95,
              "unassessed_packages": 0,
              "affected_by_severity": "high 2, moderate 1",
              "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": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "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": "excellent",
            "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": 95,
              "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": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 3
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 79,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 19254
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 66,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "Gemfile.lock"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.71,
              "toolchain_manifests": [
                "app/build.gradle.kts",
                "build.gradle.kts",
                "data/build.gradle.kts"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "app/build.gradle.kts, build.gradle.kts, data/build.gradle.kts (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "app/build.gradle.kts, build.gradle.kts, data/build.gradle.kts"
                    }
                  }
                ],
                "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": "Kotlin (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Kotlin"
                    }
                  }
                ],
                "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": "71 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 71,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Kotlin",
              "largest_source_bytes": 154512,
              "source_files_sampled": 1718,
              "oversized_source_files": 8
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Kotlin (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Kotlin"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "8/1718 source files over 60KB",
                "points": 54.7,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 1718,
                      "oversized": 8
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [],
  "report_type": "repository",
  "generated_at": "2026-07-22T03:21:28.441383Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/v/vultisig/vultisig-android.svg",
  "full_name": "vultisig/vultisig-android",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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

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

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