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

vultisig / vultisig-ios

Vultisig iOS App

SwiftApache-2.0★ 40 estrellas⑂ 22 forksdesde ene 2024Ver en GitHub ↗

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

68
global / 100
Moderado

Índice de salud del software

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

68
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 — 1740 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year1740
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 5 días
27/27Cadencia de publicación — una versión cada ~4,6 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.42.67
releases_from_tagsno
days_since_latest_release5
mean_days_between_releases4,6

Comunidad y Adopción

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

48En riesgo · 18% del índice global
Cómo se puntúa
25.8/60Estrellas — 40 estrellas
11/25Forks — 22 forks
2.7/15Observadores — 4 observadores
Datos de entrada utilizados
forks22
stars40
watchers4
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?

73Bueno · 24% del índice global
Cómo se puntúa
25.2/54Factor bus — la mitad de los commits recae en 2 contribuyente(s)
15.2/22.5Distribución de commits — el principal contribuyente firma el 32% de los commits
13.5/13.5Amplitud de contribuyentes — 27 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 4 contributing companies or organizations
Datos de entrada utilizados
bus_factor2
contributors_sampled27
top_contributor_share0,325
Cómo se puntúa
46.3/46.8Resolución de issues — 99% de issues cerradas
36.3/38.3Aceptación de PR — 2508/2641 PR decididos fusionados
12/15OpenSSF Scorecard: Code-Review — Found 26/30 approved changesets -- score normalized to 8
Datos de entrada utilizados
merged_prs2508
open_issues20
closed_issues2185
issue_closed_ratio0,991
closed_unmerged_prs133
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?

61Moderado · 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
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 29 out of 29 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno

Documentación

50Moderado
Cómo se puntúa
30/30README
0/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_dirno
has_description

Seguridad

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

54Moderado · 16% del índice global
Cómo se puntúa
0/7.5Binary-Artifacts — binaries present in source code
3.8/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 29 out of 29 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/7.5Code-Review — Found 26/30 approved changesets -- score normalized to 8
2.5/2.5Contributors — project has 4 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — sin datos
5/5Pinned-Dependencies — all dependencies are pinned
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
3/7.5Vulnerabilities — 6 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate4,3
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
advisories6
affected_packages5
assessed_packages105
unassessed_packages0
affected_by_severityhigh 4, 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 105 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.

86Excelente · 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 — 99 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,99
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes7403
Cómo se puntúa
18/18Arranque con un solo comando — Makefile
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — Swift (tipado estático)
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 77 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
10/10OpenSSF Scorecard: Pinned-Dependencies — all dependencies are pinned
Datos de entrada utilizados
has_nixno
has_tests
lockfilesGemfile.lock, package-lock.json
has_dockerfileno
typed_language
bootstrap_filesMakefile
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0,77
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Swift (tipado estático)
54.9/55Tamaños de archivo manejables — 3/1876 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageSwift
largest_source_bytes78.072
source_files_sampled1876
oversized_source_files3

Datos clave

40estrellas de GitHub
27contribuidores
1740commits en los últimos 12 meses
0días desde el último push
100versiones publicadas
2factor bus
20issues abiertas
RubyGemsecosistemas de paquetes

Más detalle

Historial de estrellas y forks 40 ★ / 22 ⇿
40Estrellas
22Forks
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.

010203040402222024-032025-052026-07
Mayor 0Menor 13Parche 87

Cada punto abarca 3 días.

OpenSSF Scorecard 4.3 / 10
4.3agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-22 03:21 UTC

0Binary-Artifactsbinaries present in source code
5Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests29 out of 29 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
8Code-ReviewFound 26/30 approved changesets -- score normalized to 8
10Contributorsproject has 4 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
n/dPackagingpackaging workflow not detected
10Pinned-Dependenciesall dependencies are pinned
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
4Vulnerabilities6 existing vulnerabilities detected
Dependencias directas 2
RegistroPaqueteRestricción de versiónManifiesto
RubyGemsfastlane2.229.1VultisigApp/Gemfile
RubyGemsostructVultisigApp/Gemfile
Todas las dependencias 105

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

RegistroPaqueteVersiónRelación
RubyGemsfastlane2.229.1directa
RubyGemsostruct0.6.3directa
npm@cosmjs/crypto0.39.0indirecta
npm@cosmjs/encoding0.39.0indirecta
npm@cosmjs/math0.39.0indirecta
npm@cosmjs/utils0.39.0indirecta
npm@noble/ciphers2.2.0indirecta
npm@noble/curves2.2.0indirecta
npm@noble/hashes2.2.0indirecta
npm@scure/base2.2.0indirecta
npm@scure/bip392.2.0indirecta
npmbase64-js1.5.1indirecta
npmcosmjs-types0.11.0indirecta
npmreadonly-date-esm2.0.0indirecta
RubyGemsabbrev0.1.2indirecta
RubyGemsaddressable2.8.8indirecta
RubyGemsartifactory3.0.17indirecta
RubyGemsatomos0.1.3indirecta
RubyGemsaws-eventstream1.4.0indirecta
RubyGemsaws-partitions1.1211.0indirecta
RubyGemsaws-sdk-core3.241.4indirecta
RubyGemsaws-sdk-kms1.121.0indirecta
RubyGemsaws-sdk-s31.213.0indirecta
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.8.0indirecta
RubyGemsfaraday-cookie_jar0.0.8indirecta
RubyGemsfaraday-em_http1.0.0indirecta
RubyGemsfaraday-em_synchrony1.0.1indirecta
RubyGemsfaraday-excon1.1.0indirecta
RubyGemsfaraday-httpclient1.0.1indirecta
RubyGemsfaraday-net_http1.0.2indirecta
RubyGemsfaraday-net_http_persistent1.2.0indirecta
RubyGemsfaraday-patron1.0.0indirecta
RubyGemsfaraday-rack1.0.0indirecta
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.18.0indirecta
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.2indirecta
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 5

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

PaqueteVersiónRelaciónGravedadAvisosCorregido en
addressable2.8.8indirectaalta12.9.0
faraday1.8.0indirectaalta22.14.3
json2.18.0indirectaalta12.19.2
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": 744010,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "C": 194496,
        "Ruby": 2537,
        "Shell": 5766,
        "Swift": 9535004,
        "Python": 9583,
        "Makefile": 4040,
        "JavaScript": 7811,
        "Objective-C": 37152
      },
      "pushed_at": "2026-07-21T22:56:12Z",
      "created_at": "2024-01-28T02:41:10Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-21T22:56:15Z",
      "description": "Vultisig iOS App",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Swift",
      "significant_languages": [
        "Swift"
      ]
    },
    "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.42.67",
          "kind": "patch",
          "published_at": "2026-07-17T01:06:25Z"
        },
        {
          "tag": "v1.42.66",
          "kind": "patch",
          "published_at": "2026-07-14T05:07:23Z"
        },
        {
          "tag": "v1.41.65",
          "kind": "patch",
          "published_at": "2026-07-04T01:47:01Z"
        },
        {
          "tag": "v1.41.64",
          "kind": "patch",
          "published_at": "2026-07-03T00:09:35Z"
        },
        {
          "tag": "v1.40.63",
          "kind": "patch",
          "published_at": "2026-06-23T23:52:02Z"
        },
        {
          "tag": "v1.40.62",
          "kind": "patch",
          "published_at": "2026-06-21T23:32:15Z"
        },
        {
          "tag": "v1.39.61",
          "kind": "patch",
          "published_at": "2026-06-12T06:45:39Z"
        },
        {
          "tag": "v1.39.60",
          "kind": "patch",
          "published_at": "2026-06-09T23:44:54Z"
        },
        {
          "tag": "v1.38.59",
          "kind": "patch",
          "published_at": "2026-06-05T22:23:33Z"
        },
        {
          "tag": "v1.38.58",
          "kind": "patch",
          "published_at": "2026-06-05T10:09:35Z"
        },
        {
          "tag": "v1.37.57",
          "kind": "patch",
          "published_at": "2026-05-25T03:12:30Z"
        },
        {
          "tag": "v1.37.56",
          "kind": "patch",
          "published_at": "2026-05-24T03:11:09Z"
        },
        {
          "tag": "v1.36.55",
          "kind": "patch",
          "published_at": "2026-05-05T23:12:19Z"
        },
        {
          "tag": "v1.36.54",
          "kind": "patch",
          "published_at": "2026-05-04T21:58:51Z"
        },
        {
          "tag": "v1.36.53",
          "kind": "patch",
          "published_at": "2026-05-02T01:05:44Z"
        },
        {
          "tag": "v1.36.52",
          "kind": "patch",
          "published_at": "2026-04-30T00:10:17Z"
        },
        {
          "tag": "v1.36.51",
          "kind": "patch",
          "published_at": "2026-04-29T01:15:23Z"
        },
        {
          "tag": "v1.35.50",
          "kind": "patch",
          "published_at": "2026-03-27T04:21:24Z"
        },
        {
          "tag": "v1.35.49",
          "kind": "patch",
          "published_at": "2026-03-22T22:41:43Z"
        },
        {
          "tag": "v1.34.48",
          "kind": "patch",
          "published_at": "2026-03-09T22:47:02Z"
        },
        {
          "tag": "v1.34.47",
          "kind": "patch",
          "published_at": "2026-03-03T22:32:15Z"
        },
        {
          "tag": "v1.34.46",
          "kind": "patch",
          "published_at": "2026-03-01T22:42:30Z"
        },
        {
          "tag": "v1.33.45",
          "kind": "patch",
          "published_at": "2026-02-17T19:46:06Z"
        },
        {
          "tag": "v1.33.44",
          "kind": "patch",
          "published_at": "2026-02-12T21:27:53Z"
        },
        {
          "tag": "v1.33.43",
          "kind": "patch",
          "published_at": "2026-02-09T21:44:54Z"
        },
        {
          "tag": "v1.33.42",
          "kind": "patch",
          "published_at": "2026-02-05T23:11:01Z"
        },
        {
          "tag": "v1.33.41",
          "kind": "patch",
          "published_at": "2026-02-03T22:07:43Z"
        },
        {
          "tag": "1.33.40",
          "kind": "patch",
          "published_at": "2026-02-01T19:47:43Z"
        },
        {
          "tag": "1.33.39",
          "kind": "patch",
          "published_at": "2026-01-28T08:59:24Z"
        },
        {
          "tag": "v1.32.38",
          "kind": "patch",
          "published_at": "2026-01-12T21:54:13Z"
        },
        {
          "tag": "v1.32.37",
          "kind": "patch",
          "published_at": "2026-01-09T08:32:44Z"
        },
        {
          "tag": "v1.32.36",
          "kind": "patch",
          "published_at": "2026-01-06T05:50:12Z"
        },
        {
          "tag": "v1.32.35",
          "kind": "patch",
          "published_at": "2025-12-22T08:19:07Z"
        },
        {
          "tag": "v1.31.34",
          "kind": "patch",
          "published_at": "2025-12-08T22:26:54Z"
        },
        {
          "tag": "v1.31.32",
          "kind": "patch",
          "published_at": "2025-12-08T02:59:16Z"
        },
        {
          "tag": "v1.31.31",
          "kind": "patch",
          "published_at": "2025-12-05T02:46:48Z"
        },
        {
          "tag": "v1.31.30",
          "kind": "patch",
          "published_at": "2025-11-29T03:01:37Z"
        },
        {
          "tag": "v1.30.29",
          "kind": "patch",
          "published_at": "2025-11-25T23:14:01Z"
        },
        {
          "tag": "v1.29.28",
          "kind": "patch",
          "published_at": "2025-11-21T09:08:08Z"
        },
        {
          "tag": "v1.29.27",
          "kind": "patch",
          "published_at": "2025-11-19T21:51:00Z"
        },
        {
          "tag": "v1.29.26",
          "kind": "patch",
          "published_at": "2025-11-17T22:48:06Z"
        },
        {
          "tag": "v1.29.25",
          "kind": "patch",
          "published_at": "2025-11-15T00:16:18Z"
        },
        {
          "tag": "v1.29.24",
          "kind": "patch",
          "published_at": "2025-11-12T22:58:47Z"
        },
        {
          "tag": "v1.28.23",
          "kind": "patch",
          "published_at": "2025-11-04T07:01:05Z"
        },
        {
          "tag": "v1.28.22",
          "kind": "patch",
          "published_at": "2025-11-03T07:59:41Z"
        },
        {
          "tag": "v1.28.21",
          "kind": "patch",
          "published_at": "2025-10-30T22:34:43Z"
        },
        {
          "tag": "v1.28.20",
          "kind": "patch",
          "published_at": "2025-10-28T23:30:48Z"
        },
        {
          "tag": "v1.27.19",
          "kind": "patch",
          "published_at": "2025-10-22T21:57:35Z"
        },
        {
          "tag": "v1.27.18",
          "kind": "patch",
          "published_at": "2025-10-20T03:03:07Z"
        },
        {
          "tag": "v1.27.17",
          "kind": "patch",
          "published_at": "2025-10-15T22:27:49Z"
        },
        {
          "tag": "v1.27.16",
          "kind": "patch",
          "published_at": "2025-10-07T22:39:41Z"
        },
        {
          "tag": "v1.26.15",
          "kind": "patch",
          "published_at": "2025-10-07T01:12:40Z"
        },
        {
          "tag": "v1.26.14",
          "kind": "patch",
          "published_at": "2025-10-03T23:23:01Z"
        },
        {
          "tag": "v1.26.13",
          "kind": "patch",
          "published_at": "2025-10-02T23:39:59Z"
        },
        {
          "tag": "v1.26.12",
          "kind": "patch",
          "published_at": "2025-10-02T02:21:06Z"
        },
        {
          "tag": "v1.26.11",
          "kind": "patch",
          "published_at": "2025-09-30T22:55:01Z"
        },
        {
          "tag": "v1.26.10",
          "kind": "patch",
          "published_at": "2025-09-24T04:33:12Z"
        },
        {
          "tag": "v1.26.9",
          "kind": "patch",
          "published_at": "2025-09-19T23:37:15Z"
        },
        {
          "tag": "v1.25.8",
          "kind": "patch",
          "published_at": "2025-09-14T02:00:02Z"
        },
        {
          "tag": "v1.25.7",
          "kind": "patch",
          "published_at": "2025-09-11T11:02:49Z"
        },
        {
          "tag": "v1.25.6",
          "kind": "patch",
          "published_at": "2025-09-10T21:52:33Z"
        },
        {
          "tag": "v1.25.5",
          "kind": "patch",
          "published_at": "2025-09-09T23:13:40Z"
        },
        {
          "tag": "v1.25.0",
          "kind": "minor",
          "published_at": "2025-09-08T04:16:08Z"
        },
        {
          "tag": "v1.24.3",
          "kind": "patch",
          "published_at": "2025-09-02T23:03:21Z"
        },
        {
          "tag": "v1.24.2",
          "kind": "patch",
          "published_at": "2025-09-01T23:32:43Z"
        },
        {
          "tag": "v1.24.0",
          "kind": "minor",
          "published_at": "2025-08-28T09:59:53Z"
        },
        {
          "tag": "v1.23.5",
          "kind": "patch",
          "published_at": "2025-08-18T23:20:19Z"
        },
        {
          "tag": "v1.23.4",
          "kind": "patch",
          "published_at": "2025-08-18T07:18:39Z"
        },
        {
          "tag": "v1.23.3",
          "kind": "patch",
          "published_at": "2025-08-14T23:29:04Z"
        },
        {
          "tag": "v1.23.2",
          "kind": "patch",
          "published_at": "2025-08-13T04:11:03Z"
        },
        {
          "tag": "v1.23.1",
          "kind": "patch",
          "published_at": "2025-08-07T22:16:47Z"
        },
        {
          "tag": "v1.23.0",
          "kind": "minor",
          "published_at": "2025-08-03T23:00:29Z"
        },
        {
          "tag": "v1.22.3",
          "kind": "patch",
          "published_at": "2025-07-28T04:00:29Z"
        },
        {
          "tag": "v1.22.2",
          "kind": "patch",
          "published_at": "2025-07-24T23:47:32Z"
        },
        {
          "tag": "v1.22.1",
          "kind": "patch",
          "published_at": "2025-07-22T23:38:11Z"
        },
        {
          "tag": "v1.22.0",
          "kind": "minor",
          "published_at": "2025-07-17T23:47:20Z"
        },
        {
          "tag": "v1.21.2",
          "kind": "patch",
          "published_at": "2025-06-27T06:27:04Z"
        },
        {
          "tag": "v1.21.1",
          "kind": "patch",
          "published_at": "2025-06-25T21:41:40Z"
        },
        {
          "tag": "v1.21.0",
          "kind": "minor",
          "published_at": "2025-06-20T04:23:29Z"
        },
        {
          "tag": "v1.20.2",
          "kind": "patch",
          "published_at": "2025-06-10T23:40:21Z"
        },
        {
          "tag": "v1.20.1",
          "kind": "patch",
          "published_at": "2025-06-09T00:15:35Z"
        },
        {
          "tag": "v1.20.0",
          "kind": "minor",
          "published_at": "2025-06-04T10:28:18Z"
        },
        {
          "tag": "v1.19.0",
          "kind": "minor",
          "published_at": "2025-05-27T22:51:42Z"
        },
        {
          "tag": "v1.18.2",
          "kind": "patch",
          "published_at": "2025-05-18T21:32:00Z"
        },
        {
          "tag": "v1.18.1",
          "kind": "patch",
          "published_at": "2025-05-16T11:09:18Z"
        },
        {
          "tag": "v1.18.0",
          "kind": "minor",
          "published_at": "2025-05-13T22:27:13Z"
        },
        {
          "tag": "v1.17.4",
          "kind": "patch",
          "published_at": "2025-05-10T01:10:58Z"
        },
        {
          "tag": "v1.17.3",
          "kind": "patch",
          "published_at": "2025-05-09T06:06:04Z"
        },
        {
          "tag": "v1.17.2",
          "kind": "patch",
          "published_at": "2025-05-07T00:45:47Z"
        },
        {
          "tag": "v1.17.1",
          "kind": "patch",
          "published_at": "2025-05-03T07:24:23Z"
        },
        {
          "tag": "v1.17.0",
          "kind": "minor",
          "published_at": "2025-05-02T03:39:45Z"
        },
        {
          "tag": "v1.16.1",
          "kind": "patch",
          "published_at": "2025-05-01T04:47:07Z"
        },
        {
          "tag": "v1.16.0",
          "kind": "minor",
          "published_at": "2025-04-30T00:11:24Z"
        },
        {
          "tag": "v1.15.3",
          "kind": "patch",
          "published_at": "2025-04-15T14:38:10Z"
        },
        {
          "tag": "v1.15.2",
          "kind": "patch",
          "published_at": "2025-04-14T07:20:23Z"
        },
        {
          "tag": "v1.15.1",
          "kind": "patch",
          "published_at": "2025-04-07T03:15:45Z"
        },
        {
          "tag": "v1.15.0",
          "kind": "minor",
          "published_at": "2025-03-26T23:01:19Z"
        },
        {
          "tag": "v1.14.0",
          "kind": "minor",
          "published_at": "2025-03-19T21:54:07Z"
        },
        {
          "tag": "v1.13.4",
          "kind": "patch",
          "published_at": "2025-03-12T21:52:35Z"
        },
        {
          "tag": "v1.13.0",
          "kind": "minor",
          "published_at": "2025-03-08T00:44:04Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "9fc8f630bcfc6e1947d5b2d07ecf778bdd7fb16e",
          "body": "…tput (#4851)\n\n`buildThorchainSwapPayload` derived `toAmountLimit` as\n`expectedAmountOut * (10000 - toleranceBps) / 10000`, but no production\ncaller ever passed `toleranceBps` — it defaulted to\n`SwapService.defaultThorchainToleranceBps` (0) at all four call sites. The\npayload therefore claimed a min\n[…]\ne memo yields \"0\", which honestly means \"no floor asserted\";\nfalling back to the expected output is precisely the bug being fixed.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): derive toAmountLimit from the signed memo, not expected ou…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-21T22:35:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "137126da01e989d6d4edde0a4642b4c197740010",
          "body": "… % from bps, reconciled total (#4864)\n\n* Shared effective-affiliate-bps function; % from bps not fiat division\n\nExtract the effective affiliate-bps computation into THORChainSwaps\n(discountedAffiliateBps + effectiveAffiliateFeeBps) and have the three\nquote-request builders (ThorchainService/Mayacha\n[…]\nch site (ranking/hash/signing/service construction) and tests.\n\nDisplay/enum-shape only; SwapPayloadBuilder and the signed memo/amount are\nuntouched. Ranking reads outAmount (already net), unaffected.",
          "is_bot": false,
          "headline": "fix(swap): itemize the Verify fee rows — affiliate-only Vultisig Fee,…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-21T22:25:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d71d2f2c268dfff890a72abb0c24af9da78aebef",
          "body": "…parate cards (#4865)\n\n* feat(defi): read the RUJI auto-compounding position size from the staking API\n\nRujira's RUJI staking pool holds two independent positions per account: a\nbonded one (manually-claimable USDC revenue) and an auto-compounding one\nbacked by the sRUJI receipt. The staking API repo\n[…]\neach locale's established withdraw/rewards terms.\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(defi): surface RUJI's bonded and auto-compounding positions as se…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-21T22:01:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "516a0db78aa59e93726f81a80545b6cf4427b572",
          "body": "…866)\n\n* fix(tron): stop overstating the network fee on free native transfers\n\ngetBlockInfo substituted coin.feeDefault (0.1 TRX) whenever the total\ncalculated fee was 0. But a *successfully computed* 0 happens only for a native\ntransfer with sufficient bandwidth, no memo, and an active destination \n[…]\n the decoupled case. Addresses\nCodeRabbit review.\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(tron): block self-send + stop overstating network fee (#4863) (#4…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-21T21:54:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0db93831c5dfb98e8f50e440147a9b323095c760",
          "body": "…(#4860)\n\nThe browser extension added XRPL off-chain message signing for dApps\n(GemWallet signMessage) over the shared MPC custom-message keysign. For a\nSecure (multi-device) Vault an iPhone acting as co-signer must reproduce\nthe initiator's exact message digest, or the derived message-ID diverges\na\n[…]\n against SHA-512-half vectors computed outside Swift, so they\npin cross-platform byte identity rather than re-deriving iOS's own output,\nplus precedence guards against the raw-bytes and EIP-712 paths.",
          "is_bot": false,
          "headline": "feat(keysign): co-sign XRPL custom messages with SHA-512-half digest …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-20T22:09:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "24f3de91287e29359048b5cee812d7e4e03cc17e",
          "body": "… EVM addresses (#4847)\n\n* fix(send): don't auto-switch chain for ambiguous Terra addresses\n\nTerra and Terra Classic share the bech32 HRP `terra`, so a `terra1…`\naddress decodes cleanly on both networks and carries no information about\nwhich one it belongs to. `AddressService.detectChain` resolved i\n[…]\non about the address. A\nvault holding both Terra chains still gets LUNA-or-LUNC decided for it,\nand the caller auto-advances past the chain display; a picker is the real\nfix and is tracked separately.",
          "is_bot": false,
          "headline": "fix(send): switch into the right chain family for ambiguous Terra and…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-20T22:06:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2a35c5244f792b28114535a35a47d2591ab1b8bd",
          "body": "…of dust (#4848)\n\n* fix(send): fill the full balance on Max instead of stranding a digit of dust\n\nCoin.getMaxValue truncated the computed max to decimals - 1, so every Max\nsend left one unit-of-last-place behind. Non-native tokens never reach the\nnative fee-refine path, making a token's Max exactly\n\n[…]\nng all three paths, the\nfull-6-decimal case, and the fee-exceeds-balance guard. Expectations are\nbuilt through the same formatToDecimal the production code uses, so they\nhold on comma-decimal locales.",
          "is_bot": false,
          "headline": "fix(send): fill the full balance on Max instead of stranding a digit …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-20T22:00:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "84253aa7a60c95432c5fec20825864e7234f219f",
          "body": "* fix(send): fill the full balance on Max instead of stranding a digit of dust\n\nCoin.getMaxValue truncated the computed max to decimals - 1, so every Max\nsend left one unit-of-last-place behind. Non-native tokens never reach the\nnative fee-refine path, making a token's Max exactly\nbalanceDecimal.tru\n[…]\nnloaded sentinel the second test fails, and the cap can\nthen tell the two states apart.\n\nNo production behavior change.\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): size percentage presets by the asset's own precision (#4850)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-20T21:58:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8330df466533479114b8f00221d2c104d40e70b1",
          "body": "…page error (#4852)\n\nWhen THORChain or Maya simulates a swap whose output lands under the minimum-\noutput floor derived from the slippage tolerance, it rejects the quote with a\nbody like \"emit asset 42579895573 less than price limit 340083366993\". That fell\nthrough the classifier to `.serverError(me\n[…]\nalt message.\n\nLocalized in all 8 locales. Tests use the verbatim node bodies captured from\nlive THORChain and Mayanode rejections.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): map the node's price-limit rejection to an actionable slip…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-20T21:50:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9116522494afbd24406bff8caf2662e1330fee9b",
          "body": "…eue + Limit Orders tab (Phases 1–3) (#4816)\n\n* feat(limit-swap): add THORChain limit-swap memo foundation (§0)\n\nPure-logic foundation for THORChain limit swaps (#4232 Phase 1):\n\n- buildLimitSwapMemo: native memo builder for `=<:ASSET:DEST:LIM/INTERVAL/0:AFFILIATE:FEE`.\n- validateLimitSwapInputs: pr\n[…]\nitSwapPayloadAssembler. The real\nreason gasLimit: 0 is safe is that gas/gasLimit are market-swap fee-\ndisplay fields the limit flow never reads.\n\n* refactor(limit-swap): drop limit-mode quote-refresh…",
          "is_bot": false,
          "headline": "feat(limit-swap): track resting limit orders against the THORChain qu…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-20T21:48:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3054c5c26fff87e73bdc8edf98ad4c8335e62e11",
          "body": "* fix(substrate): surface RPC error details\n\nPreserve JSON-RPC error codes and prefer specific data reasons while retaining duplicate broadcast recovery. Remove the unreachable Bittensor catch and cover code 1010 plus message fallback.\n\nCo-Authored-By: Codex <noreply@anthropic.com>\n\n* refactor(rpc):\n[…]\nTransaction) via a shared BroadcastErrorClassifier.broadcastMethods\nset so the class and struct decoders stay in sync. Adds a regression test.\n\n---------\n\nCo-authored-by: Codex <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(substrate): surface RPC error details (#4845)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-20T11:49:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d020d190500a142f4901465a7eede954da5a3a6",
          "body": "…guarantee (#4834)\n\n* feat(icons): rebuild the icon set on Icons V3, make the compiler the guarantee\n\nReplace Assets.xcassets/Icons wholesale with Icons V3 art under V3 names, and\nchange `Icon` to take an `ImageResource` instead of a `String` so a missing or\nmisspelled icon is a compile error rather\n[…]\nght from V3\n(all single-colour, template). Re-records the CreateVault snapshot for the\nearlier scan/import icon change.\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(icons): rebuild the icon set on Icons V3, make the compiler the …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-17T23:39:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d3123dbe6ef1103937c272a8b1cd81f613af0acc",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): bump version to 1.42.67 (build 67) (#4833)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-17T01:43:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a253ac903f1d61fd7fcf39f2d46ce84a56a890c",
          "body": "…4828 — iOS) (#4831)\n\n* fix(assets): align chain-osmo monotone badge with design system\n\nThree fills in the Osmosis chain badge drifted from the design source:\n\n- the flask body used #3D6195 at 70% fill-opacity; it is a solid\n  #3E4A62 in the design\n- the lower-left arc used a literal `black` rather\n[…]\ned-color #02122B, preserves-vector-representation, and\ntemplate-rendering-intent \"original\" so it is never tinted. The symbol's\nframe is 32x32 at the origin, so no coordinate normalization was needed.",
          "is_bot": false,
          "headline": "fix(assets): reconcile monotone chain badge set with design source (#…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T23:38:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "798e79f6c328440bf3491b1abd76dbdca8f70fe7",
          "body": "… balance refresh (#4824)\n\n* fix(wallet): refresh per-chain fiat when rates land, not only after a balance refresh\n\nThe VaultMain chain list renders `ChainRowModel.fiatBalance`, a *formatted\nstring* baked when `VaultDetailViewModel.rows` is assigned. Nothing recomputes\nit when a rate arrives: `RateP\n[…]\n the signal must follow the cache, not the write.\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(wallet): refresh per-chain fiat when rates land, not only after a…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T23:36:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ee61608c31d8f5fe9ad960372bb1182023a21eea",
          "body": "…in Xcode (#4823)\n\nThe .xcodeproj is gitignored and generated from project.yml via XcodeGen, so\nopening it directly can use a stale (or missing) project. 'make open' runs\ngenerate first, then opens VultisigApp.xcodeproj — one step for newcomers and\nafter any project.yml change.",
          "is_bot": false,
          "headline": "chore(make): add 'make open' target to regenerate + open the project …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T23:26:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "760b210851e9bfe1a92ebaf19cc298f331a252ab",
          "body": "… before the execution condition (#4825)\n\n* fix(limit-swap): honor the source chain the user entered the swap with\n\nEntering Swap from THORChain chain detail preselected THORChain on the\nMarket tab, but switching to Limit silently switched the source to BTC.\n\n`preferredLimitSourceChain` prefers a hi\n[…]\niven keyboard accessory is attached to\nthe outer VStack, not to the cards, so reordering siblings cannot resurrect\nthe merged-accessory bug; focus order is tap-driven and follows the new\nvisual order.",
          "is_bot": false,
          "headline": "fix(limit-swap): honor the entered source chain + put asset selection…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T23:24:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8864ee983b6cd0d8eb2570bc886534c1ee1492f4",
          "body": "…EVM balance (#4829)\n\n* fix(balances): stop Multicall3 partial failures zeroing EVM balances\n\nA partial Multicall3 failure silently persisted a 0 balance over a funded\ncoin. `aggregate3` is called with allowFailure = true, so an individual\nsub-call returning success = false does NOT throw — the batc\n[…]\nive\nbatch with a deliberately reverting sub-call.\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(balances): stop a partial Multicall3 failure silently zeroing an …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T23:16:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f470013bd665da0dc9a2607ba27a38f7cbd9165e",
          "body": "…le) (#4818)\n\n* Step 1: bump VultisigCommonData pin to expose SignRipple\n\nBump the commondata Swift package pin from the dest-tag commit\n(2b92938) to c91f2ea, which adds `SignRipple { string raw_json }`\nat sign_ripple = 46 in KeysignPayload.sign_data. The new commit is a\nlinear descendant of the des\n[…]\n IOU value so the \"signed\" case matches its name.\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(keysign): co-signer support for XRPL dApp transactions (SignRipp…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T23:07:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ef0b96a1708a900c1b5fc23af99ff5353c3c565f",
          "body": "…ake it render on macOS (#4819)\n\n* fix(keygen): point the peer-discovery info pointer at \"Scan QR\" and make it render on macOS\n\nThe animated pointer in the keygen \"Scan the QR on your other devices\"\ninfo pop-up sat over empty space instead of the \"Scan QR\" button it\nexplains, and on macOS it did not\n[…]\ns as a steady\nfaint ring on the \"Scan QR\" button.\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(keygen): point the peer-discovery info pointer at \"Scan QR\" and m…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-16T22:57:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9076a4dcd8d3213f416fda8499b92e88a5bd26ab",
          "body": "* feat(limit-swap): add THORChain limit-swap memo foundation (§0)\n\nPure-logic foundation for THORChain limit swaps (#4232 Phase 1):\n\n- buildLimitSwapMemo: native memo builder for `=<:ASSET:DEST:LIM/INTERVAL/0:AFFILIATE:FEE`.\n- validateLimitSwapInputs: pre-build validation (asset format, expiry hours\n[…]\n safe is that gas/gasLimit are market-swap fee-\ndisplay fields the limit flow never reads.\n\n* refactor(limit-swap): drop limit-mode quote-refresh countdown\n\nLimit orders execute at a fixed target pri…",
          "is_bot": false,
          "headline": "feat(swap): THORChain limit-order Place flow (#4232) (#4319)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-15T23:25:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1bef342ada346eb2e7966a417e6403a1e6156ae6",
          "body": "… warning, success, backup guide) (#4763)\n\n* Step 1: redesign reshare entry screen with Start/Join option cards\n\nReplace the single centered ReshareView with a cross-platform\nReshareScreen matching the new Figma: left-aligned title and subtitle,\ndevices illustration with glow, and Start Reshare / Jo\n[…]\ntead of requiring every co-signer.\n\nCo-Authored-By: Codex <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(reshare): redesign the reshare flow to the new Figma (pre-flight…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-15T00:18:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9b576caeca033dd787b330fa51486dee657a08ec",
          "body": "…E+ mint (#4788) (#4807)\n\n* feat(swap): add dynamic THORChain secured-asset catalog\n\nPhase 1 of secured-asset discovery (#4788). Adds the source-of-truth\ncatalog that later feeds the swap destination picker:\n\n- ThorchainMainnetAPI: new `.securedAssets` endpoint -> /thorchain/securedassets\n- Thorchai\n[…]\nwap): fix SwapCoinSelectionLogic.sort call for static snapshot API\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": "feat(swap): discover THORChain secured assets + same-underlying SECUR…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-15T00:08:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "11726e9ac3a6c24222a8220d5c7c1666dde8e7b8",
          "body": "…#4813)\n\n* perf(swap): stop double reloadCoins on chain tap\n\nTapping a chain in the swap coin picker fired reloadCoins twice: once\ndirectly from onSelect(chain:) and once from the\n.onChange(of: selectedChain) observer that the same assignment triggers.\nEach reload re-runs the full assemble+merge+sor\n[…]\nsCancelled before the memoized fast-path publish.\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": "perf(swap): fix chain-picker jank on rapid back-and-forth switching (…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-14T22:31:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "08ae49b3af82db8879fa1e2abdcea40f76565001",
          "body": "iOS shipped only TRX + USDT on Tron; the desktop / SDK knownTokens\nregistry lists four. Add the missing three TRC-20 tokens so users can\nenable them from Choose Tokens without adding each as a custom token.\n\n- USDC   TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8   6dp  usd-coin\n- USDD   TXDk8mbtRbXeYuMNS83CfKP\n[…]\nisig-sdk packages/core/chain/coin/knownTokens. usdd & stusdt logos\nported from the shared core coin assets (usdc already present).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tron): add USDC, USDD & stUSDT tokens (desktop parity) (#4812)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-14T22:21:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1bf10ed5fe551db9da42439395290d3e8050a42b",
          "body": "* fix(defi): render cached Tron details immediately\n\n- hydrate dashboard balances and resources from warm cache\\n- defer portfolio balance refresh until detail data is populated\\n- cover Tron view model response mapping\\n\\nCo-Authored-By: Codex <noreply@anthropic.com>\n\n* fix(defi): align Tron dashbo\n[…]\nhboard matches the THORChain layout on iOS and macOS.\n\n* fix(defi): reduce Tron dashboard top inset\n\nRemove the stacked Screen top padding and use the same 16-point content inset across iOS and macOS.",
          "is_bot": false,
          "headline": "fix(defi): render cached Tron details immediately (#4809)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-14T22:12:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c74e59ec1b7f3b1212a6c89d326a7958aa64e18f",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): bump version to 1.42.66 (build 66) (#4810)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-14T05:36:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5209127eb522161b5b29511c0a190a09ca4e255a",
          "body": null,
          "is_bot": false,
          "headline": "update gitignore",
          "author_name": "Johnny Luo",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-14T05:00:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c61c0cfe68224c78b733034c38fee4c99b56338f",
          "body": "Restore the missing localized peer discovery guidance across all supported locales.\n\nCo-authored-by: Codex <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: restore peer discovery info description (#4808)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-13T23:39:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "35c26a255c7143d6e967208b4674f8695ca8dfa4",
          "body": "Prevent completed cards from retaining the in-progress layout when SwiftUI reuses a row, and cover the expansion policy with unit tests.\n\nCo-authored-by: Codex <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(history): derive transaction card expansion state (#4803)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-13T22:21:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6adb89efa8cccce42784422bb375f7a58bf1f30a",
          "body": "…ance (#4794) (#4797)\n\n* fix(defi): read Staked RUJI amount from on-chain x/staking-x/ruji balance\n\nThe DeFi Staked RUJI card read the staked amount from the Rujira staking\nAPI's `bonded.amount`, which can return 0 even when the vault holds sRUJI\nreceipt tokens on-chain — so the card showed `0 RUJI`\n[…]\nlve tests to match the convention (Codex review).\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(defi): read Staked RUJI amount from on-chain x/staking-x/ruji bal…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-13T17:22:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0d501352201db9c0907949834fc99e8b6f0e050f",
          "body": "… (#4796) (#4798)\n\n* fix(solana): gate signAllTransactions N>1 before the keysign ceremony\n\nSolanaHelper.getPreSignedImageHash looped over all\nsignSolana.rawTransactions, so a multi-transaction Solana batch\n(signAllTransactions, N>1) relayed to an iOS co-signer ran the full\nmulti-device keysign cere\n[…]\nas a co-signer. Comment only; no\nbehavior change.\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(solana): gate signAllTransactions N>1 before the keysign ceremony…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-13T11:31:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bc23cde2467a3e7c043066e005f27eb72b136688",
          "body": "…799)\n\n* feat(defi): curated bRUNE / ybRUNE tokens + liquid-bond contract\n\nAdd first-class Rujira bRUNE (Bonded RUNE, x/brune, 8dp) and its\nauto-compounding staking receipt ybRUNE (x/staking-x/brune, 8dp) as\ncurated TokensStore entries, plus the rujira-staking liquid-bond\ncontract constant.\n\n- Token\n[…]\nisting iOS idiom where sRUJI reuses xruji's logo.\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(defi): bRUNE / ybRUNE curated tokens + stake/unstake (#4778) (#4…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-13T11:13:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "11ceae3a5902ed48fb57856529f5c91e99f5c66c",
          "body": "…cate unknown vouchers (#4792)\n\n* Step 1: add modern IBC /denoms endpoint + CosmosIbcDenom model\n\nAdds CosmosAPI.Endpoint.ibcDenom(hash:) mapping to the modern ibc-go\nGET /ibc/apps/transfer/v1/denoms/{hash} path, which Terra Classic LCDs\nimplement (unlike the deprecated denom_traces path). Adds a Co\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 TerraClassic IBC token display: resolve to symbol/icon/fiat, trun…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-13T11:12:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "74e47d990d2e3da8c5daa0f993c505637981d931",
          "body": "… (#4790)\n\nThe broadcast error classifier mapped several non-duplicate rejections to\nthe duplicate-broadcast sentinel, which KeysignViewModel converts to a\nlocally computed hash and reports as success. A bare \"known\" matched every\n\"unknown ...\" message, \"nonce too high\" is a nonce gap (tx not accept\n[…]\nand\nRpcService (substrate, backing Polkadot + Bittensor). Collapse both into a\nshared BroadcastErrorClassifier that matches only true duplicate signals.\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(broadcast): stop dup-sentinel over-matching rejections as success…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-13T10:29:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ef48729cca10c60aa0370b61a68bf949ea7f446b",
          "body": "Base was excluded since KyberSwap's introduction with no documented\nreason. The SDK live-confirmed Kyber on Base and iOS's KyberSwapService\nalready maps .base -> \"base\", so this is a registry-only change.\n\nCloses #4793\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Enable KyberSwap on Base (#4795)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-12T09:49:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f9db7a52ac021ad76497453a5fc7a06d8723d063",
          "body": "* Slide address book selector background with the selection\n\nThe Send address-book picker's list selector was a hand-rolled two-button\nHStack where each cell drew its own background from an isSelected flag, so\nanimating the toggle just cross-faded the two static backgrounds on/off —\nthe highlight sw\n[…]\nt - 1 == -1); behavior unchanged for >= 1 option.\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": "Slide address book selector background with the selection (#4780)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-10T23:15:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8010648685d8b13ff14291d1d00618816cf1aa76",
          "body": "… lookup error (#4791)\n\nfetchTokenAssociatedAccountByOwner already derives the classic-SPL and\nToken-2022 ATAs and confirms them via getAccountInfo when\ngetTokenAccountsByOwner returns an empty result (the common indexer-lag\ncase right after an ATA is created). But when the primary\ngetTokenAccountsB\n[…]\nnely-missing account still yields not-found, and a successful\nprimary lookup returns its account without probing the derived ATAs.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(solana): fall back to ATA derivation on a transient token-account…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-10T22:30:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b6b269f37bd7c5e0eef02bc1e3044ba22bc79eee",
          "body": "… numeric fields (#4784)\n\nA keysign payload is untrusted data deserialized from a co-signer at the\nstart of a ceremony. BlockChainSpecific(from:) decoded chain-specific\nnumeric string fields with the trapping BigInt(stringLiteral:) initializer,\nwhich crashes on any non-numeric or empty string. A bug\n[…]\nmed (incl. explicit \"0\") compute_limit and priority_fee\nfor Solana, plus malformed-field cases for EVM and Polkadot.\n\ncloses #4782\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "[Fix] Harden BlockChainSpecific decoding of untrusted keysign payload…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-10T22:24:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fd0d9f6bc45b4409883a61a8007a83606b98175e",
          "body": "…al FAILED (#4789)\n\nTransient transport failures were mapped to .failed, which the status\npoller treats as terminal and isAlreadyOnChain treats as conclusive\nnegative evidence — a single network blip could permanently mark a live\nTHORChain/Maya tx as FAILED and poison the duplicate-broadcast net.\n\nN\n[…]\nling and\nthe duplicate-broadcast check keeps retrying. 429/5xx still map to\n.failed to surface the error; 404 stays .notFound.\n\nCovers Maya too — both route through THORChainTransactionStatusProvider.",
          "is_bot": false,
          "headline": "fix(thorchain): don't return timeout/network Midgard errors as termin…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-10T22:19:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "293b1a60075020452cf382a450a14ab460c03313",
          "body": "…68) (#4777)\n\n* Inline the Done overview into SigningKeysignScreen with a crossfade\n\nMake SigningKeysignScreen a single mounted container: a ZStack keyed on\ncoordinator.keysignFinished that renders KeysignView while signing and\ncrossfades in place to the flow's DoneScreen (SendDoneScreen/SwapDoneScr\n[…]\new (broadcasted + confirmed) to iterate the feel.\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": "Unify keysign progress + overview into one crossfading container (#47…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-09T22:45:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4e99b1ce4d935981241b84477383993ca45d9957",
          "body": "…dows (#4776)\n\nCosmos-family chains (Cosmos SDK, THORChain/Maya) sign the sha256 of a\ncustom message (Keplr ADR-36 signArbitrary over the StdSignDoc bytes),\nbut keysignMessages fell through to the keccak256 branch for them. The\nresulting digest — and the message-ID the relay derives from it —\ndiverg\n[…]\nustomMessageHex.ts: cosmos-family -> sha256, EdDSA -> raw,\neverything else (EVM, Tron) -> keccak256. EVM/EdDSA/Cardano/typed-data\nbehavior is unchanged.\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): sha256-hash cosmos custom messages to match Android/Win…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-09T22:15:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bb3f0c27e198f2ff0e79f87dc1c601bf11be4854",
          "body": "…+ one keysign route/screen (#4775)\n\n* Step 1: FastVaultKeysignBootstrap off-screen session helper + unit tests\n\nAdds FastVaultKeysignBootstrap, which runs the fast-vault relay-session\nbootstrap (register -> wake -> await peer -> kickoff) off-screen and\nassembles the finished KeysignInput. Built on \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": "Unify the keysign screen: fold fast-vault bootstrap into KeysignView …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-09T00:22:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ceedc97ff46b53c35d631cd441dccc9c95333cf",
          "body": "…te Continue (#4765)\n\nExtract the XRP destination base-reserve check out of SendDetailsViewModel\nbehind a chain-agnostic `SendAmountValidator` protocol (an input snapshot ->\n`.ok` / `.invalid(message:blocksContinue:)`), implemented for XRP by\n`RippleDestinationReserveValidator` under Blockchain/Ripp\n[…]\nrTests proving the generic\n  wiring blocks Continue independent of any chain.\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": "feat(send): generic SendAmountValidator + animate inline warning + ga…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-09T00:10:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "69441d2d7992d6e61560b0b29a7b738beb95031a",
          "body": "* feat(done): expand transaction details in place instead of pushing\n\nExtract the detail rows from SendCryptoSecondaryDoneView into a reusable\nheader-less/button-less TransactionDetailsCard that owns the\nadd-to-address-book flow, then convert DoneScreen's default\nDoneDetailContent slot to reveal tha\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": "Expand transaction details in place on the Done screen (#4767) (#4772)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-08T23:40:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "de097bfcac23cf094dd628c0f2f1cdffbb37b1b0",
          "body": "…emo & tag+memo support (#4749)\n\n* feat(ripple): hand-rolled XLS-5d X-address codec pinned to canonical vectors\n\nXRPL X-addresses bundle a classic account ID with an optional 32-bit\ndestination tag. WalletCore validates and signs them inside its Ripple\nsigner but exposes no Swift codec, so autofilli\n[…]\nsts don't wire (RequireDest is covered in the threading tests).\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(ripple): XRP Destination Tag as a first-class field + restored m…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-08T22:29:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b042ca975a65a8a2bf6c57c116c6bc5ac2ee172b",
          "body": "…n base reserve (#4764)\n\n* refactor(ripple): extract owner-aware reserve math into RippleReserve\n\nPull the reserve computation getBalance did inline (reserve_base +\nOwnerCount x reserve_inc, seeds on missing server_state fields) into a\npure RippleReserve enum, sibling to RippleFee, and delegate getB\n[…]\nd it to stay exhaustive.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>\nCo-authored-by: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(ripple): inline send-form validation of XRP amount vs destinatio…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-08T00:11:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "00279c68c5994106fe82fc7394e12ac13184057d",
          "body": "…nted static 1 XRP (#4748)\n\n* refactor(ripple): extract owner-aware reserve math into RippleReserve\n\nPull the reserve computation getBalance did inline (reserve_base +\nOwnerCount x reserve_inc, seeds on missing server_state fields) into a\npure RippleReserve enum, sibling to RippleFee, and delegate g\n[…]\nlled fee calc now also aborts quietly instead of surfacing a transport\nerror.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ripple): owner-aware reserve for MAX send — remove the double-cou…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-07T23:14:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5f145f9cba2fbf4a16903e2fc0538e76128713b0",
          "body": "…ite (#4736)\n\n* test(figma-parity): reusable Figma-parity comparator + hermetic self-test\n\nAdd VultisigAppTests/FigmaParity/: FigmaParityComparator renders a SwiftUI\nview at exact px via ImageRenderer, diffs it against a committed Figma\nexport, and emits similarity + perceptual (1 - meanDelta) score\n[…]\nhe unchanged committed\nreference PNG, so no reference regeneration is needed.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(figma-parity): reusable Figma-parity harness + /figma skill rewr…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-07T23:00:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "21757eceb1f7b03deb2d0dccf9b71408c94ead43",
          "body": "…alidation on the signed-fee source of truth (#4699)\n\n* fix(swap): co-signer network fee uses signed route gas, not the gasLimit floor\n\nOn a co-signed EVM aggregator swap (SwapKit/1inch/LiFi/Kyber ETH->token) the\nco-signer's Network fee under-displayed ~6-9x less than the vault actually pays\n(shows \n[…]\nture change\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>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(swap): unify EVM swap network fee across initiator, co-signer & v…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-07T22:51:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b2cfe10d8a01ece3a11d53dd2bb8e8c6b8056b80",
          "body": "…matches the signed fee (#4762)\n\nTerra Classic prices its fee as `gasLimit × price (+ burn tax)`. The\ninitiator now simulates a dynamic per-tx gas limit (CosmosSpecific.gas_limit)\nand the signer signs that relayed `gas_wanted`, but `chainSpecific.gas` was\nstill priced at the fixed 300k limit. The si\n[…]\neeps its own\nsigner-side re-derivation (same latent display gap, separate follow-up).\n\nTests updated: baseGas scaling per denom, and the signer echoing the priced\n`gas` verbatim under a relayed limit.",
          "is_bot": false,
          "headline": "fix(terraClassic): price send fee at the dynamic gas limit so Verify …",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-07T22:32:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b4fbda6dac33f264a38eb71bedad648cae617e7e",
          "body": "…locked) (#4754)\n\n* Step 1: retry XRPL requests on transient node errors (same-host, no fallback)\n\nAdd a bounded same-host retry at the Ripple request layer. The default XRPL\nhost (xrplcluster.com) is a load-balanced pool; some backends run stale rippled\nand answer amendmentBlocked (HTTP 200 with re\n[…]\n, each\nwithout retrying.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>\nCo-authored-by: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(ripple): retry XRPL requests on transient node errors (amendmentB…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-06T23:26:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "38b21d20730fe8da9469a8f5e70c54681140141d",
          "body": "…P txs (#4750)\n\n* feat(ripple): add SHA-512Half XRP transaction-hash helper\n\nAdd RippleHelper.signedTransactionHash(signedBlob:), computing the\ncanonical XRPL transaction identifying hash: SHA-512Half of the\n0x54584E00 (\"TXN\\0\") prefix + the serialized signed blob, rendered as\nuppercase hex. Pure fu\n[…]\ntput bytes; the\nsigning input, pre-image, and TSS/keysign flow are unchanged.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ripple): compute the deterministic transaction hash for signed XR…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-06T22:57:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cdcdc820c2b597d8875465b3c705be0d3d1ea11d",
          "body": "…already-submitted results (#4746)\n\n* feat(ripple): classify XRPL submit engine results; gate broadcast on tesSUCCESS\n\nThe XRPL submit endpoint echoes tx_json.hash for every engine result, so\nthe previous hash-presence gate reported rejected submits (tem/tef/tel/\nter/tec engine results) as successfu\n[…]\natusProvider semantics, and an injectable\nbackoff so tests run without delay.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ripple): gate broadcast on tesSUCCESS + verify-by-hash dedup for …",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-06T22:32:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "40f4905f82e51cd3bc58a83830217c6ead14e88a",
          "body": "…lection gating, cache-first seed heal (#4745)\n\n* fix(defi): gate the Solana staking card on the position selection\n\nThe Solana stake segment rendered its full staking card for every\nvault, ignoring the per-vault position opt-in that THOR/Maya/Cosmos\nstaking honors — a vault that never selected the \n[…]\nel heal-then-seed\n(first entry can't seed, refresh heals, a fresh VM paints).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(solana): staking DeFi fixes — validator 520 fallback, position-se…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-06T22:24:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "38f0d6e0aefb0e415decbf3188be826555dca5f0",
          "body": "…738)\n\nOn the swap Join Keysign screen the \"To\" row showed keysignPayload.toAddress,\nwhich for a swap is the provider's router/inbound contract — not a user-facing\ndestination. Surface a \"To\" address only when the user directed the swap output\nto an external recipient (an address other than their ow\n[…]\ntion share one parser and one notion\n  of address equality.\n- KeysignSwapConfirmView shows the external recipient instead of the raw router\n  toAddress.\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): don't show router address as To on join keysign screen (#4…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-06T11:59:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e5c249e2ff63a2a5539cb48aca00753f5b78c5e5",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): bump version to 1.41.65 (build 65) (#4737)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-04T02:00:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ca8b30bff2c8aa0766a5db81a70462b20ce90a6",
          "body": "…re (#4735)\n\n`TssKeysignResponse.getSignature()` builds an Ed25519 signature by reversing\n`r` and `s` (big-endian scalars from TSS) into little-endian and concatenating\nthem into R || S. It never left-padded the halves to 32 bytes.\n\ntss-lib emits `r`/`s` via Go's `hex.EncodeToString(bigInt.Bytes())`\n[…]\nh rebuilds bit-for-bit and\nverifies. Updates the custom-message EdDSA tests, which had pinned the old\nun-padded output using toy 2-byte values.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): pad EdDSA r/s to 32 bytes before assembling the signatu…",
          "author_name": "Danial",
          "author_login": "DanialV",
          "committed_at": "2026-07-04T00:59:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8e47a673980f59cef4f12d7a98f2eb783143eb47",
          "body": "…sic (#4733)\n\n* feat(cosmos): add CW20 token_info metadata query to the Cosmos resolver\n\nAdd a `{\"token_info\":{}}` wasm smart-query path so CW20 contract metadata\n(name, symbol, decimals) can be resolved from the chain's LCD — the same\nlookup the SDK/extension perform in getCw20MetaFromLCD:\n\n- Cosmo\n[…]\neview feedback on the PR.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(wallet): support adding custom CW20 tokens on Terra / Terra Clas…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-04T00:36:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "90346ca51284e662ff41d3da21f1d159353cfb83",
          "body": "…' while providers load (#4732)\n\n* fix(swap): publish local token list before awaiting destination providers\n\nThe destination \"Select asset\" picker rendered \"No result found.\" with an\nempty search query until every remote destination-token provider returned.\nThe cached fetch path clears the spinner \n[…]\ne test hermetic); cold-cache\nsource-side publishes once without the registry.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): destination asset picker no longer shows 'No result found.…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-04T00:20:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e73a6ac1b5f5062cb2476bddf72e7c79f69c9032",
          "body": "Vault Settings -> Rename accepted a cleared text field: Save stayed\nenabled and persisted the empty string, leaving the vault with a blank\nname in Vault Details and the home vault selector.\n\nReuse the vault-creation validation path instead of a rename-only rule:\n\n- VaultNameValidator now trims white\n[…]\nng a duplicate entry to folders).\n- No new user-facing strings: enterVaultName and vaultNameExists\n  already exist in all locales.\n\nCloses #4729\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(vault): reject empty/whitespace vault names in Rename Vault (#4731)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-04T00:14:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "39eced8060738ba87f6fba0d34d8edfd3b3e9305",
          "body": "* feat(zcash): add ZIP-317 conventional fee math\n\nByte-parity port of the SDK's zip317.ts (packages/core/chain/chains/utxo/\nfee/zip317.ts, landed in vultisig-sdk#773): conventional fee = 5,000 zats\nper logical action with a two-action grace window, where logical actions =\nmax(ceil(tx_in bytes / 150)\n[…]\n. Regression tests pin the Maya-shaped decode\nand the nil-flag gate behavior.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(zcash): re-plan memo txs to the ZIP-317 conventional fee (#4728)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-04T00:07:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "85b23be375e83afd3653398abdba037fb0c562a1",
          "body": "…re 4.7.0 auxiliaryData) (#4709)\n\n* feat(cardano): canonical CIP-20 memo CBOR encoder (pre-stage for #4708)\n\nAdd a pure, dependency-independent CIP-20 transaction-metadata encoder\n(label 674) that produces canonical CBOR { 674: { \"msg\": [chunks] } } with\n64-UTF-8-byte, codepoint-boundary chunking an\n[…]\neeA*auxLen.\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>\nCo-authored-by: hailhydra <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "feat(cardano): attach send memo on-chain as CIP-20 metadata (WalletCo…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-03T23:55:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "617d6f9b5e830b7bc8552aaa9b1a760c6f894bcf",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): bump version to 1.41.64 (#4725)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-03T00:54:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0fa0df6d5415866d7bdc9a4272c54338f9d80cd6",
          "body": "…ed gas limit (#4692)\n\n* fix(cosmos): enforce dynamic Akash fee floor for send + staking + dApp signing\n\niOS hard-coded the Akash fee at 3000 uakt, below Akash's own 0.025 uakt/gas\nnode minimum (5000 uakt at the 200k gas limit), so an ordinary send could be\nrejected on-chain with \"insufficient fee\".\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): dynamic Akash/Cosmos fees — safe floor + simulate-deriv…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-02T22:54:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b4ecf979b1d812f3fc58f820d087e0ad67dd33ad",
          "body": "…ocal Network check + error/retry + iPad back button) (#4722)\n\n* fix(keygen): detect Local Network permission on iPad join, add error + escape hatch\n\nJoining a Local-mode (Bonjour/LAN) keygen on iPad hung forever on\n\"Discovering\" when iOS Local Network access was denied (or Wi-Fi / AP\nclient-isolati\n[…]\nare form; NetService keeps the trailing-dot form.\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(keygen): iPad local-mode join no longer hangs on \"Discovering\" (L…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-02T22:42:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1d7ad62eb8b7073bfd9362032345b1dcc5f8422d",
          "body": "…r) (#4720)\n\n* feat(keysign): show fiat value on the co-sign send amount\n\nThe co-sign \"Send overview\" (\"Join transaction signing\") screen renders\nthrough the shared SendCryptoVerifySummary model + HeroCoinAmount, both of\nwhich carried fiat for the network fee but not for the amount. A co-signer\nsaw \n[…]\niat case (no\norphan gap). Previews updated to carry amountFiat.\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(keysign): show fiat value on the send amount (co-sign + initiato…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-02T22:34:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6b62986f8e78438c73ba636e4e3750eaf8af2f1e",
          "body": null,
          "is_bot": false,
          "headline": "chore(deps): bump WalletCore to v4.7.0 (#4721)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-07-02T01:53:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "160b784b96071602207fd7a411452063a7f1309e",
          "body": "On iPad, the \"Use standard mode\" button (SwitchToLocalLink) at the bottom\nof the keygen Pair screen in local mode sat flush against the bottom edge.\nThe switchLink computed var applied bottom padding only under #if os(macOS),\nso iOS/iPadOS got zero. iPhone is masked by the home-indicator safe area,\n\n[…]\ndding the primary button directly above\n(bottomButton) already uses, while preserving the existing macOS value (24).\n\nCloses #4713\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keygen): pad \"Use standard mode\" link on iPad Pair screen (#4719)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T23:24:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b37eca71b0deca425da81155e9a21989b2f9a671",
          "body": "…) (#4718)\n\nThe green checkmark ring rendered with a flat left edge on the Send/Swap\nverify screens. Checkbox draws the ring as a Circle().stroke on a 24x24\nframe; .stroke centers the 1pt line on the path, so ~0.5pt spills outside\nthe frame. The consent-checkbox row sits flush at the left edge of th\n[…]\ninside\nthe 24x24 bounds so it never overflows to be clipped. This fixes the clip\nfor every Checkbox usage without touching layout.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ui): round the consent-checkbox circle on Send/Swap verify (#4715…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T23:24:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "208e2b6aea0421f6d325f30d6848b2dbf95b9d63",
          "body": "The ⓘ info icon beside the \"Gas Limit\" label in the advanced-swap Gas\nLimit sub-sheet had no Button, tap gesture, or tooltip, so tapping it\ndid nothing — a fake interactive affordance. Per the maintainer's\ndecision, drop the dead icon rather than wire up a tooltip. With the\nicon gone the wrapping HStack becomes redundant, so collapse it to the\nbare label Text.\n\nCloses #4714\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): remove dead Gas Limit info icon in advanced settings (#4717)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T23:23:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cbc76143257eb61b620c857ac17a13adddbead02",
          "body": "…tion (#4711)\n\n* fix(swap): surface THORNode errors + guard secured-asset swap destination (#4321)\n\nSwapping into a THORChain secured asset (e.g. ETH-USDC) surfaced only a\ngeneric error while swapping out worked. Live mainnet testing confirms\nTHORNode requires a thor1... destination for a secured-as\n[…]\nflow and the error-surfacing logic are unchanged.\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): surface THORNode errors + guard secured-asset swap destina…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T23:21:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "828155f44deb8321a8a864d6ef5b3a013272b077",
          "body": "…#4704)\n\nMandatory Rule 6: use .foregroundStyle(), not the deprecated .foregroundColor().\nMechanical 1:1 swap across 139 files (378 sites), behavior-identical for Color\narguments (Color conforms to ShapeStyle).\n\nNot changed:\n- foregroundColor(for:isEnabled:) helper funcs in PrimaryButtonStyle/IconBu\n[…]\n of scope (follow-up: migrate to Theme.colors.*).\n\nPart of the iOS code-quality audit (Phase A — convention sweeps).\n\nCloses #4703\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: replace deprecated .foregroundColor with .foregroundStyle (…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T23:08:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "67ee4a95aeb85851aa23b19c80e4b69ea2186b1c",
          "body": "…ck) (#4702)\n\nReplace the byte-identical onChange { asyncAfter(0.5) { focusedField = newValue } }\n@FocusState workaround copy-pasted across 10 screens with a single\n.delayedFocus(from:to:delay:) View extension (behavior-identical, default 0.5s delay).\n\nSites: 9 FunctionTransaction screens (Amount, T\n[…]\ngate, TonStake) + Wallet VaultServerBackupScreen.\n\nPart of the iOS code-quality audit (Phase A — convention sweeps).\n\nCloses #4700\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract shared delayedFocus modifier (de-dupe FocusState ha…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T23:04:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "16b65f5a8ad3142f92d61f13eae5a8f8558763b4",
          "body": "…705)\n\nThe delegate form hardcoded a 1 SOL minimum active delegation. That value\nis a feature-gate-activated network constant, not a permanent one, and the\nVultisig RPC proxy blocks getStakeMinimumDelegation, so it could not be read\nthrough the normal path.\n\nRead it directly from a public Solana nod\n[…]\ne-parity; it is deliberately NOT routed through the custom-RPC override\n(which would repoint signing/broadcast too).\n\ncloses #4694\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(solana): fetch min-delegation dynamically from a public node (#4…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-07-01T12:29:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "42853ab0f7a22bf5a70da2330694f934f2cfe774",
          "body": "Per-token unit prices below one cent (e.g. LUNC ~$0.00006, USTC ~$0.0054)\nwere displayed as \"$0.00\", hiding the real price from users.\n\niOS keeps the rate full-precision end-to-end (no data-source pre-scaling\nto undo, unlike Android), so this is a pure display-layer change:\n\n- Add Decimal.formatToFi\n[…]\nings are unaffected: a tiny holding still shows \"$0.00\".\nParity with Android's asPrice fix (vultisig-android #5111).\n\nCloses #4688\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(tokens): show sub-cent token prices instead of $0.00 (#4701)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-30T23:51:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4be9133c25a444bf450391e3b5b5c18bd0643ef5",
          "body": "* feat(swap): add Jupiter Solana swap provider (Phase 1: routing + quote/swap, no fee)\n\nWire Jupiter as a swap provider for on-Solana token swaps (SOL<->SPL,\nSPL<->SPL). Jupiter is added to the Solana provider list and is Solana-only\nsame-chain: cross-chain pairs drop it automatically via the SwapCo\n[…]\nixture used a\nfee-owner-style value. (CodeRabbit)\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(swap): Jupiter Solana swap provider (#4669) (#4696)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-30T23:09:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "530ed9ff2a7e68b5d8fd69778d6201e32a129ae7",
          "body": "…thdraw) (#4690)\n\n* feat(solana): staking foundation — models + RPC read layer\n\n* feat(solana): validator metadata seam (Stakewiz, swappable)\n\n* feat(solana): delegate (stake) flow\n\n* feat(solana): deactivate (unstake) + withdraw\n\n* feat(solana): move stake / redelegate (guided, cross-epoch)\n\n* feat\n[…]\nng the cache-first paint shipped for the segment.\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(solana): native staking on the DeFi tab (delegate / unstake / wi…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-30T23:08:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c43c8f0301d652d48e4dd036cb339737113fbc93",
          "body": "Removes the unused Share Vault QR feature: the screen, its view model,\nthe QR rendering components, the public-key export model, and the\nnow-unused ImageFileDocument utility. Also removes the Settings toolbar\nentry point, its route/router/builder wiring, and the shareVaultQR\nlocalization keys from all locale files.",
          "is_bot": false,
          "headline": "chore: remove Share Vault QR screen (#4698)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-30T02:45:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e01813b36e2fb3d81f4b617eb0480e2955739324",
          "body": "…rrors (#4686)\n\nCompleteness: add 62 missing keys per locale (QBTC claim flow, Cosmos\nstaking errors, Cardano/validator errors, tx status, tier copy); rebuild\nstale Korean (ships in language picker); remove 11 dead renamed keys.\nFix live bug: noUnencryptedVaultsToImport used in code but missing from\n[…]\nan orphan %d.\n\nValidated: plutil-clean, sorted, full key parity, 0 format-spec mismatches.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>\nCo-authored-by: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "i18n: fill 62 missing iOS keys, rebuild Korean, fix ~83 translation e…",
          "author_name": "paaao",
          "author_login": "realpaaao",
          "committed_at": "2026-06-30T01:32:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9fd2c76ee863d1749da580b7e114f7e974351dfd",
          "body": "…695)\n\n* feat(qbtc): derive Bitcoin/QBTC claim accounts on the fly (#4679)\n\nThe QBTC claim flow blocked with `.missingCoin` unless both the Bitcoin\nand QBTC chains were already enabled in the vault. Derive the two native\ncoins in-memory from the vault's own keys (the pure, non-persisting\nCoinFactory\n[…]\n enabled,\n  and the derive-when-not-enabled case.\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(qbtc): derive Bitcoin/QBTC claim accounts on the fly (#4679) (#4…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-29T23:16:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "30fb0739143949c709936f5f61f1b116e493456d",
          "body": "…call3 (#4693)\n\n* perf(balance): run price + balance fetching concurrently (#4673)\n\nBalance fetching was gated behind a full price fetch: updateBalances awaited\nfetchPrices(vault:) before the per-coin balance task group ran, so a slow or\nfailing price provider froze all balances even though balances\n[…]\no it fails if balances ever await prices\n  first.\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": "perf(balance): decouple price fetching + batch EVM balances via Multi…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-29T23:10:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f79b92f9497356b7287f3df276777404e9eeb6bc",
          "body": "* feat(banners): global TTL-based promo-banner dismissal\n\nReplace the mixed promo-banner dismissal storage (app-wide permanent\n@AppStorage(\"appClosedBanners\") + per-vault permanent Vault.closedBanners)\nwith one global, per-device store keyed by a stable banner intent id.\n\n- PromoBannerDismissalStore\n[…]\nunder one\n  lock to close the lost-update window.\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(banners): global TTL-based promo-banner dismissal (#4691)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-29T22:58:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8119be05aea4bb627a0882b6c9bf14c7e347a5ae",
          "body": "At zero or insufficient from-balance the swap quote details were hidden\nbehind a blocking error tooltip: updateQuotes assigned the quote then\nthrew balanceError, which set self.error, and SwapDetailsSummary hid the\nwhole provider/fee/price-impact block while SwapDetailsScreen swapped the\nflip button\n[…]\nte is unchanged.\n- Localization: add swapInsufficientTokenBalance (\"Insufficient %@\n  balance\") to all 7 locale files and re-sort.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(swap): show quote details without sufficient balance (#4658)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-29T22:41:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aff668e475be2db6d1e8d0aa0114910f72b1afe3",
          "body": "… (#4644)\n\n* refactor(defi): generalize yield integration behind DefiYieldProvider\n\nExtract the DeFi-tab USDC-yield integration into a generic, provider-driven\nframework and migrate Circle onto it. Introduces the DefiYieldProvider\nprotocol + factory, shared YieldVault/Deposit/Withdraw shells and vie\n[…]\n-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: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "refactor(defi): generalize yield integration behind DefiYieldProvider…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-29T22:35:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1ba1014ca3a93b7251f6b984986265a4c0278e46",
          "body": "…LDSA-44 key (#4685)\n\nGenerating an MLDSA-44 key is a one-time action. The Advanced settings\n\"Post-Quantum Key\" row was always shown; tapping it on a vault that\nalready had the key surfaced an \"already generated\" notice. Hide the row\nentirely once the vault has the key instead.\n\n- Guard dilithiumKey\n[…]\nlt.publicKeyMLDSA44 == nil (matches\n  the existing reshareVaultRow pattern in this screen).\n- Remove the now-unreachable DilithiumAlreadyGeneratedSheet, its state,\n  and its localization keys (en/ko).",
          "is_bot": false,
          "headline": "feat(settings): hide Post-Quantum Key option when vault already has M…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-29T10:57:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6e4576c083f4173d9840deeeace5d1c8a90daa34",
          "body": "…684)\n\nThe QBTC claim flow signs its BTC ECDSA round exclusively via DKLS\n(QBTCClaimRoundRunner / QBTCClaimSecureVaultRoundDriver). GG20 keyshares\ncan't take part in that ceremony, so a GG20 vault that reached keysign\nhung and failed with \"DKLS sign message exhaust retries: fail to\ndownload setup me\n[…]\ndView.\n- QBTCClaimEligibilityChecker short-circuits to .ineligible (no network)\n  so the promo banner / Claim button never appear for GG20 vaults.\n- Localize the new title/detail across all 8 locales.",
          "is_bot": false,
          "headline": "fix(qbtc): block GG20 vaults from QBTC claim with a clear message (#4…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-29T10:55:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "73124a8e547ac7441a85f8a854efbc51a09fdf29",
          "body": "… (#4675)\n\nLI.FI's estimate.toAmount (dstAmount) is already net of the integrator\nfee, which LI.FI takes from the source token and marks included: true.\nThe ranking branch subtracted it again, understating LI.FI's ranked\nvalue by ~0.5% and flipping provider selection away from LI.FI on\nnear-ties at the in-band preference boundary.\n\nPass dstAmount through unchanged (same as 1inch/Kyber) and update the\nranking test vector that encoded the double-counted value.\n\nCloses #4674",
          "is_bot": false,
          "headline": "fix(swap): stop double-counting LI.FI integrator fee in quote ranking…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-28T23:15:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a261fd452fcdbce41ff22a1aedff8aeaa574c6b9",
          "body": "Co-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(assets): use jpg for qbtc coin icon (#4677)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-28T00:11:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "85530353727a69e0e25e5f94a31d0d93ec49c2b5",
          "body": "* feat(defi): TON staking on the DeFi tab (#4653)\n\nMove TON nominator-pool staking out of the generic Functions (FunctionCall)\nflow and into a dedicated TON section on the DeFi tab, reusing the same generic\nDefiChain staked-positions screens that THORChain / Maya / Cosmos already use.\n\n- Register .t\n[…]\n from the implementation, not invalid form state.\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(defi): TON staking on the DeFi tab (#4653) (#4654)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-25T22:11:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c1e6151184728ca83c84d6e0e2900e4315d0095e",
          "body": "Render an MLDSA key row in the Keys section of the vault Details card\nwhen the vault has a non-empty publicKeyMLDSA44, reusing the existing\ncopyable vaultKeyRow helper for parity with the ECDSA/EdDSA rows\n(including the shared/exported isForSharing view). The row is hidden\nfor vaults without an MLDSA key.\n\nAdds the \"MLDSA\" localization key to all 7 locale files.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(vault): show MLDSA key in vault details screen (#4651) (#4652)",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-25T21:58:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1917b6a122369d723498cd43432def3145dc4e57",
          "body": "…le pools (#4615) (#4616)\n\n* Add NativePoolAsset model + pool-id parsing for dynamic swap eligibility\n\nPure types + the synchronous eligibility predicate, no I/O. NativePoolAsset\nnormalizes a /pools asset id (CHAIN.TICKER-0XCONTRACT) into {chain, ticker,\nlowercased contract, isAvailable, isTradingHa\n[…]\n the halt gate reflects the network the quote actually deposits on.\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(swap): dynamic THORChain/Maya swap eligibility from live Availab…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-24T23:52:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f62c588e8da5dd78cda2722e0d1b804abe28fc72",
          "body": "…/unfreeze & resources sheet (#4648)\n\n* fix(defi): match Figma + adopt shared staking pattern for TRON freeze/unfreeze & resources sheet\n\n- FilledSegmentedControl: add optional icon/iconSelectedTint to the type\n  protocol (defaulted to nil so ScannerMode is unchanged) and a .filledPill\n  size matchi\n[…]\n-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: Johnny Luo <johnnyluo1980@gmail.com>",
          "is_bot": false,
          "headline": "fix(defi): match Figma + adopt shared staking pattern for TRON freeze…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-24T23:31:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f36cb9d3809d7ca4597fdcc1529b57c1ac330de3",
          "body": "…en (#4641)\n\nThe swap keysign confirmation screen showed from/to coin, amounts,\nprovider and fees but had no destination address, so a co-signer\n(non-initiating device) could not verify where funds go before signing.\n\nAdd a read-only destination-address row fed from KeysignPayload.toAddress\n(the pro\n[…]\ng the existing row styling and the localized \"to\" label. Display\nonly; no change to keysign payload construction, TSS, or signing.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): show swap destination address on co-signer confirm scre…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-24T23:05:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cb3347fb38551de4701371eba93b737a3b89acd8",
          "body": null,
          "is_bot": false,
          "headline": "release v1.40.63 (#4646)",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-24T00:10:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34f0ac8f509dad5dc671213aa1105b5a0de1f658",
          "body": "…s (#4645)\n\nLiFi swaps sourced from Solana omitted the integrator/fee params because\n`Coin.isLifiFeesSupported` only returned true for EVM chains. That left\nSolana routes uncharged while the UI still computed and displayed a ~0.5%\nfee that was never collected, and denied VULT holders their tier disc\n[…]\n.\nEVM-source routes (including Cronos/Hyperliquid) already charged the fee\nand are unaffected.\n\nAdds LiFiFeesSupportedTests pinning EVM + Solana as fee-charging and\nnon-LiFi source chains as excluded.",
          "is_bot": false,
          "headline": "fix(swap): charge VULT-discounted LiFi integrator fee on Solana route…",
          "author_name": "hailhydra",
          "author_login": "johnnyluo",
          "committed_at": "2026-06-23T23:20:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0e50592598dfe5dc8cfe38086f58e7f3a4e7662e",
          "body": "…en catalog refresh-on-open (#4643)\n\n* fix(swap): SwapKit provider gate fail-closed on cold cache miss + token catalog refresh-on-open\n\nTwo SwapKit cache reliability fixes.\n\nProvider gate: SwapKitProviderCache.isEnabled(chain:) now fails CLOSED on the\nno-snapshot edge. On a cold launch where the fir\n[…]\nack, pointing to SwapKitProviderCache.isEnabled for the rationale.\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(swap): SwapKit provider gate fail-closed on cold cache miss + tok…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-23T22:27:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4c7af45e5c3829483f5b4c0976b76d3b61360d80",
          "body": "…0bps (#4642)\n\nAmong swap quotes already within the provider-preference band (economically\nequivalent on net destination output), prefer the one with lower source-chain\ngas before applying provider preference — but only when BOTH compared quotes\nexpose gas in the same native-wei unit (same-chain EVM\n[…]\n the preference band from 100bps to 50bps so a \"preferred\"\nprovider can no longer be handed up to 1% (2x the 50bps affiliate fee).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): in-band lower-gas tie-break + tighten preference band to 5…",
          "author_name": "Gaston",
          "author_login": "gastonm5",
          "committed_at": "2026-06-23T21:52:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "44b3535af42fd9c31fbed169e031fd70f3e583b7",
          "body": "…636)\n\nThe keysign Rive animation exposes a `progessPercentage` bar, but\n`KeysignAnimationView` never bound it — only `KeygenAnimationView` did.\nThe bar therefore stayed empty during signing. For standard Send the\ncoin-logo glow filled that area so it looked populated, but swap and\ncustom-message fl\n[…]\ny\n- SendCryptoKeysignView: pass-through `progress` parameter\n- KeysignView: feed `viewModel.signingProgress` into the signing view\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(keysign): fill signing progress bar for swap & custom message (#4…",
          "author_name": "Amin",
          "author_login": "aminsato",
          "committed_at": "2026-06-23T21:46:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4089931199b42ed60df8d5349328816c4173c20c",
          "body": "…erance-v2\n\nfix(swap): default THORChain tolerance_bps to 0 so Auto swaps aren't rejected",
          "is_bot": false,
          "headline": "Merge pull request #4640 from vultisig/fix/thorchain-swap-auto-no-tol…",
          "author_name": "paaao",
          "author_login": "realpaaao",
          "committed_at": "2026-06-23T14:26:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1740,
      "latest_release_at": "2026-07-17T01:06:25Z",
      "latest_release_tag": "v1.42.67",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 52,
      "days_since_latest_release": 5,
      "mean_days_between_releases": 4.6
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 62,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 22,
      "stars": 40,
      "watchers": 4,
      "fork_history": {
        "days": [
          {
            "date": "2024-03-17",
            "count": 1
          },
          {
            "date": "2024-05-22",
            "count": 1
          },
          {
            "date": "2024-06-12",
            "count": 1
          },
          {
            "date": "2024-06-18",
            "count": 1
          },
          {
            "date": "2024-07-29",
            "count": 1
          },
          {
            "date": "2024-09-04",
            "count": 1
          },
          {
            "date": "2024-10-08",
            "count": 1
          },
          {
            "date": "2024-12-18",
            "count": 1
          },
          {
            "date": "2025-02-14",
            "count": 1
          },
          {
            "date": "2025-03-15",
            "count": 1
          },
          {
            "date": "2025-04-19",
            "count": 1
          },
          {
            "date": "2025-05-02",
            "count": 1
          },
          {
            "date": "2025-07-12",
            "count": 1
          },
          {
            "date": "2025-11-15",
            "count": 1
          },
          {
            "date": "2026-03-16",
            "count": 1
          },
          {
            "date": "2026-03-20",
            "count": 1
          },
          {
            "date": "2026-03-25",
            "count": 1
          },
          {
            "date": "2026-04-18",
            "count": 1
          },
          {
            "date": "2026-04-30",
            "count": 1
          },
          {
            "date": "2026-05-01",
            "count": 1
          },
          {
            "date": "2026-05-07",
            "count": 1
          },
          {
            "date": "2026-07-19",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 22,
        "total_forks": 22
      },
      "star_history": {
        "days": [
          {
            "date": "2024-04-18",
            "count": 1
          },
          {
            "date": "2024-04-19",
            "count": 1
          },
          {
            "date": "2024-05-01",
            "count": 1
          },
          {
            "date": "2024-06-16",
            "count": 1
          },
          {
            "date": "2024-07-04",
            "count": 1
          },
          {
            "date": "2024-07-07",
            "count": 1
          },
          {
            "date": "2024-07-10",
            "count": 1
          },
          {
            "date": "2024-08-12",
            "count": 1
          },
          {
            "date": "2024-08-15",
            "count": 1
          },
          {
            "date": "2024-08-20",
            "count": 1
          },
          {
            "date": "2024-08-29",
            "count": 1
          },
          {
            "date": "2024-09-04",
            "count": 1
          },
          {
            "date": "2024-09-07",
            "count": 1
          },
          {
            "date": "2024-09-23",
            "count": 1
          },
          {
            "date": "2025-03-29",
            "count": 1
          },
          {
            "date": "2025-04-19",
            "count": 1
          },
          {
            "date": "2025-04-21",
            "count": 1
          },
          {
            "date": "2025-05-28",
            "count": 1
          },
          {
            "date": "2025-06-13",
            "count": 1
          },
          {
            "date": "2025-07-30",
            "count": 1
          },
          {
            "date": "2025-08-07",
            "count": 1
          },
          {
            "date": "2025-10-14",
            "count": 1
          },
          {
            "date": "2025-10-15",
            "count": 1
          },
          {
            "date": "2025-12-03",
            "count": 1
          },
          {
            "date": "2026-01-25",
            "count": 1
          },
          {
            "date": "2026-02-25",
            "count": 1
          },
          {
            "date": "2026-03-23",
            "count": 1
          },
          {
            "date": "2026-04-08",
            "count": 1
          },
          {
            "date": "2026-04-20",
            "count": 1
          },
          {
            "date": "2026-04-21",
            "count": 1
          },
          {
            "date": "2026-04-30",
            "count": 1
          },
          {
            "date": "2026-05-04",
            "count": 1
          },
          {
            "date": "2026-05-07",
            "count": 1
          },
          {
            "date": "2026-05-19",
            "count": 1
          },
          {
            "date": "2026-05-22",
            "count": 1
          },
          {
            "date": "2026-05-28",
            "count": 1
          },
          {
            "date": "2026-06-03",
            "count": 1
          },
          {
            "date": "2026-06-10",
            "count": 1
          },
          {
            "date": "2026-06-14",
            "count": 1
          },
          {
            "date": "2026-07-21",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 40,
        "total_stars": 40
      },
      "open_issues_and_prs": 23
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 78072,
      "source_files_sampled": 1876,
      "oversized_source_files": 3,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 7403
    },
    "dependencies": {
      "manifests": [
        "VultisigApp/Gemfile"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "addressable",
            "direct": false,
            "version": "2.8.8",
            "severity": "high",
            "ecosystem": "rubygems",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-h27x-rffw-24p4"
            ],
            "fixed_version": "2.9.0",
            "advisory_count": 1,
            "oldest_advisory_days": 105
          },
          {
            "name": "faraday",
            "direct": false,
            "version": "1.8.0",
            "severity": "high",
            "ecosystem": "rubygems",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-33mh-2634-fwr2",
              "GHSA-98m9-hrrm-r99r"
            ],
            "fixed_version": "2.14.3",
            "advisory_count": 2,
            "oldest_advisory_days": 162
          },
          {
            "name": "json",
            "direct": false,
            "version": "2.18.0",
            "severity": "high",
            "ecosystem": "rubygems",
            "cvss_score": 8.2,
            "advisory_ids": [
              "GHSA-3m6g-2423-7cp3"
            ],
            "fixed_version": "2.19.2",
            "advisory_count": 1,
            "oldest_advisory_days": 124
          },
          {
            "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": 4,
          "moderate": 1
        },
        "advisory_count": 6,
        "affected_count": 5,
        "assessed_count": 105,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "rubygems"
      ],
      "dependencies": [
        {
          "name": "fastlane",
          "manifest": "VultisigApp/Gemfile",
          "ecosystem": "rubygems",
          "version_constraint": "2.229.1"
        },
        {
          "name": "ostruct",
          "manifest": "VultisigApp/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": "@cosmjs/crypto",
            "direct": false,
            "version": "0.39.0",
            "ecosystem": "npm"
          },
          {
            "name": "@cosmjs/encoding",
            "direct": false,
            "version": "0.39.0",
            "ecosystem": "npm"
          },
          {
            "name": "@cosmjs/math",
            "direct": false,
            "version": "0.39.0",
            "ecosystem": "npm"
          },
          {
            "name": "@cosmjs/utils",
            "direct": false,
            "version": "0.39.0",
            "ecosystem": "npm"
          },
          {
            "name": "@noble/ciphers",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@noble/curves",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@noble/hashes",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@scure/base",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@scure/bip39",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "base64-js",
            "direct": false,
            "version": "1.5.1",
            "ecosystem": "npm"
          },
          {
            "name": "cosmjs-types",
            "direct": false,
            "version": "0.11.0",
            "ecosystem": "npm"
          },
          {
            "name": "readonly-date-esm",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "abbrev",
            "direct": false,
            "version": "0.1.2",
            "ecosystem": "rubygems"
          },
          {
            "name": "addressable",
            "direct": false,
            "version": "2.8.8",
            "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.1211.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sdk-core",
            "direct": false,
            "version": "3.241.4",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sdk-kms",
            "direct": false,
            "version": "1.121.0",
            "ecosystem": "rubygems"
          },
          {
            "name": "aws-sdk-s3",
            "direct": false,
            "version": "1.213.0",
            "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.8.0",
            "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-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_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.18.0",
            "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.2",
            "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": 105,
        "direct_count": 2,
        "indirect_count": 103
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 2508,
        "open_issues": 20,
        "closed_ratio": 0.991,
        "closed_issues": 2185,
        "closed_unmerged_prs": 133
      },
      "bus_factor": 2,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "enriquesouza",
          "commits": 2519,
          "avatar_url": "https://avatars.githubusercontent.com/u/1700699?v=4"
        },
        {
          "type": "User",
          "login": "johnnyluo",
          "commits": 2199,
          "avatar_url": "https://avatars.githubusercontent.com/u/749608?v=4"
        },
        {
          "type": "User",
          "login": "Rockindash",
          "commits": 1784,
          "avatar_url": "https://avatars.githubusercontent.com/u/13535088?v=4"
        },
        {
          "type": "User",
          "login": "gastonm5",
          "commits": 564,
          "avatar_url": "https://avatars.githubusercontent.com/u/7192634?v=4"
        },
        {
          "type": "User",
          "login": "flypaper0",
          "commits": 545,
          "avatar_url": "https://avatars.githubusercontent.com/u/5384197?v=4"
        },
        {
          "type": "User",
          "login": "realpaaao",
          "commits": 47,
          "avatar_url": "https://avatars.githubusercontent.com/u/167348323?v=4"
        },
        {
          "type": "User",
          "login": "Dolloong",
          "commits": 21,
          "avatar_url": "https://avatars.githubusercontent.com/u/151611992?v=4"
        },
        {
          "type": "User",
          "login": "0x-suzume",
          "commits": 15,
          "avatar_url": "https://avatars.githubusercontent.com/u/265643117?v=4"
        },
        {
          "type": "User",
          "login": "Vaulty-bot",
          "commits": 13,
          "avatar_url": "https://avatars.githubusercontent.com/u/257854823?v=4"
        },
        {
          "type": "User",
          "login": "jpthor",
          "commits": 10,
          "avatar_url": "https://avatars.githubusercontent.com/u/41815753?v=4"
        }
      ],
      "contributors_sampled": 27,
      "top_contributor_share": 0.325
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "objective-c-xcode.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "Gemfile.lock",
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 0,
            "reason": "binaries present in source code",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 5,
            "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": "29 out of 29 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": 8,
            "reason": "Found 26/30 approved changesets -- score normalized to 8",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 4 contributing companies or organizations",
            "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": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 1 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": 10,
            "reason": "all dependencies are pinned",
            "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": 4,
            "reason": "6 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "9fc8f630bcfc6e1947d5b2d07ecf778bdd7fb16e",
        "ran_at": "2026-07-22T03:21:14Z",
        "aggregate_score": 4.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-21T23:12:34Z",
      "oldest_open_prs": [
        {
          "number": 4734,
          "created_at": "2026-07-03T18:09:19Z",
          "last_comment_at": "2026-07-03T18:09:48Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 4849,
          "created_at": "2026-07-20T11:25:27Z",
          "last_comment_at": "2026-07-21T15:01:45Z",
          "last_comment_author": "gastonm5"
        },
        {
          "number": 4857,
          "created_at": "2026-07-20T18:52:56Z",
          "last_comment_at": "2026-07-20T18:53:32Z",
          "last_comment_author": "coderabbitai"
        }
      ],
      "last_merged_pr_at": "2026-07-21T22:56:11Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 2122,
          "created_at": "2025-04-30T05:57:01Z",
          "last_comment_at": "2025-04-30T06:04:52Z",
          "last_comment_author": "jpthor"
        },
        {
          "number": 4309,
          "created_at": "2026-05-05T17:04:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4325,
          "created_at": "2026-05-07T19:58:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4375,
          "created_at": "2026-05-17T17:44:15Z",
          "last_comment_at": "2026-05-18T16:38:28Z",
          "last_comment_author": "gastonm5"
        },
        {
          "number": 4655,
          "created_at": "2026-06-25T15:55:57Z",
          "last_comment_at": "2026-07-05T22:46:33Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 4755,
          "created_at": "2026-07-06T18:51:40Z",
          "last_comment_at": "2026-07-09T03:30:22Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 4756,
          "created_at": "2026-07-06T18:59:52Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4757,
          "created_at": "2026-07-06T18:59:53Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4758,
          "created_at": "2026-07-06T18:59:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4760,
          "created_at": "2026-07-07T05:47:51Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4769,
          "created_at": "2026-07-08T13:48:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4800,
          "created_at": "2026-07-13T11:20:46Z",
          "last_comment_at": "2026-07-13T23:40:29Z",
          "last_comment_author": "johnnyluo"
        },
        {
          "number": 4817,
          "created_at": "2026-07-15T17:19:06Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4838,
          "created_at": "2026-07-18T05:51:06Z",
          "last_comment_at": "2026-07-21T14:50:12Z",
          "last_comment_author": "gastonm5"
        },
        {
          "number": 4846,
          "created_at": "2026-07-20T07:22:22Z",
          "last_comment_at": "2026-07-20T09:54:16Z",
          "last_comment_author": "realpaaao"
        },
        {
          "number": 4853,
          "created_at": "2026-07-20T12:59:46Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4854,
          "created_at": "2026-07-20T12:59:48Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4856,
          "created_at": "2026-07-20T18:24:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4858,
          "created_at": "2026-07-20T19:33:35Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4861,
          "created_at": "2026-07-21T06:46:27Z",
          "last_comment_at": "2026-07-21T06:49:37Z",
          "last_comment_author": "realpaaao"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/vultisig/vultisig-ios",
    "host": "github.com",
    "name": "vultisig-ios",
    "owner": "vultisig"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 68,
      "inputs": {
        "security": 54,
        "vitality": 96,
        "community": 48,
        "governance": 73,
        "engineering": 61
      },
      "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": 1740,
              "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": "1740 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1740
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 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.42.67",
              "releases_from_tags": false,
              "days_since_latest_release": 5,
              "mean_days_between_releases": 4.6
            },
            "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 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~4.6 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 4.6
                    }
                  }
                ],
                "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": 48,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "forks": 22,
              "stars": 40,
              "watchers": 4,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "below_threshold"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "40 stars",
                "points": 25.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 40
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "22 forks",
                "points": 11,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "4 watchers",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 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": 73,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "moderate",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "bus_factor": 2,
              "contributors_sampled": 27,
              "top_contributor_share": 0.325
            },
            "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 32% of commits",
                "points": 15.2,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 32
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "27 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 27
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 95,
            "inputs": {
              "merged_prs": 2508,
              "open_issues": 20,
              "closed_issues": 2185,
              "issue_closed_ratio": 0.991,
              "closed_unmerged_prs": 133
            },
            "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": "2508/2641 decided PRs merged",
                "points": 36.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 2508,
                      "decided": 2641
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 26/30 approved changesets -- score normalized to 8",
                "points": 12,
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 61,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "29 out of 29 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": 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": 54,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "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": 43,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 4.3
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "binaries present in source code",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 3.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "29 out of 29 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 26/30 approved changesets -- score normalized to 8",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "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": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 1 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": "all dependencies are pinned",
                "points": 5,
                "status": "met",
                "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": "6 existing vulnerabilities detected",
                "points": 3,
                "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 105 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": 105
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 6,
              "affected_packages": 5,
              "assessed_packages": 105,
              "unassessed_packages": 0,
              "affected_by_severity": "high 4, 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": 105,
              "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": 5
            },
            "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": "excellent",
        "name": "AI Readiness",
        "value": 86,
        "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": 0.99,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 7403
            },
            "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": "99 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 99,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 81,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "Gemfile.lock",
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.77,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "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": "Swift (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Swift"
                    }
                  }
                ],
                "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": "77 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 77,
                      "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": "all dependencies are pinned",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Swift",
              "largest_source_bytes": 78072,
              "source_files_sampled": 1876,
              "oversized_source_files": 3
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Swift (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Swift"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "3/1876 source files over 60KB",
                "points": 54.9,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 1876,
                      "oversized": 3
                    }
                  }
                ],
                "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:22:11.840475Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/v/vultisig/vultisig-ios.svg",
  "full_name": "vultisig/vultisig-ios",
  "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.