Öffentliches Register
Software-GesundheitsberichtSchema 0.26.0 · Metriken 1.13.0 · 2026-07-22 03:22 UTC

vultisig / vultisig-ios

Vultisig iOS App

SwiftApache-2.0★ 40 Sterne⑂ 22 Forksseit Jan. 2024Auf GitHub ansehen ↗

vultisig/vultisig-ios erreicht einen Gesundheitsindex von 68 von 100 und liegt damit im Bereich Mittel. Am stärksten schneidet es bei Vitality (96/100) ab, am schwächsten bei Community & Adoption (48/100). Zuletzt heute aktualisiert. 2 Mitwirkende tragen den Großteil der jüngsten Arbeit.

68
gesamt / 100
Mittel

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

68
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Eigentümerschaft

132 Follower72 öffentliche Reposseit Jan. 2024

Dieses Repository wird von einer Organisation getragen — geteilte, rechenschaftspflichtige Trägerschaft, die jeden einzelnen Maintainer überdauern kann.

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

96Exzellent · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 0 Tagen
36/36Commit-Rhythmus — 52/52 Wochen mit Commits
18/18Commit-Volumen — 1.740 Commits im letzten Jahr
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Verwendete Eingangsdaten
commits_last_year1.740
human_commit_share1
days_since_last_push0
active_weeks_last_year52
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 100 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 5 Tagen
27/27Release-Rhythmus — ein Release etwa alle 4,6 Tage
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Verwendete Eingangsdaten
releases_count100
latest_release_tagv1.42.67
releases_from_tagsnein
days_since_latest_release5
mean_days_between_releases4,6

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

48Gefährdet · 18 % des Gesamtindex
Wie die Bewertung erfolgt
25.8/60Stars — 40 Stars
11/25Forks — 22 Forks
2.7/15Watcher — 4 Watcher
Verwendete Eingangsdaten
forks22
stars40
watchers4
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonbelow_threshold
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (Apache-2.0)
0/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
6.3/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
has_pull_request_templateja

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

73Gut · 24 % des Gesamtindex
Wie die Bewertung erfolgt
25.2/54Bus-Faktor — 2 Beitragende decken die Hälfte aller Commits ab
15.2/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 32 % der Commits
13.5/13.5Breite der Beitragenden — 27 Beitragende
10/10OpenSSF Scorecard: Contributors — project has 4 contributing companies or organizations
Verwendete Eingangsdaten
bus_factor2
contributors_sampled27
top_contributor_share0,325
Wie die Bewertung erfolgt
46.3/46.8Issue-Lösungsquote — 99 % der Issues geschlossen
36.3/38.3PR-Annahme — 2.508/2.641 entschiedene PRs gemergt
12/15OpenSSF Scorecard: Code-Review — Found 26/30 approved changesets -- score normalized to 8
Verwendete Eingangsdaten
merged_prs2.508
open_issues20
closed_issues2.185
issue_closed_ratio0,991
closed_unmerged_prs133
Wie die Bewertung erfolgt
30/30Organisatorische Trägerschaft — im Besitz einer Organisation
0/20Verifizierte Domain
15.3/25Reichweite des Inhabers — 132 Follower von vultisig
18/25Kontohistorie — 72 öffentliche Repos, Kontoalter ca. 2 Jahre
Verwendete Eingangsdaten
followers132
owner_typeOrganization
is_verified
owner_loginvultisig
public_repos72
account_age_days906

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

61Mittel · 20 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 1 Workflow(s)
24/24Tests vorhanden
0/16Linter-Konfiguration
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 29 out of 29 merged PRs checked by a CI test -- score normalized to 10
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfignein
has_linter_confignein
has_precommit_confignein
Wie die Bewertung erfolgt
30/30README
0/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
10/10Wiki
Verwendete Eingangsdaten
topics
has_wikija
homepage
has_readmeja
has_docs_dirnein
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

54Mittel · 16 % des Gesamtindex

Sicherheitslage

43Gefährdet
Wie die Bewertung erfolgt
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.5Lizenz — 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 — keine Daten
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
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate4,3
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): packaging. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
35/35Direkte Abhängigkeiten ohne bekannte Advisories — keine direkte Abhängigkeit trägt ein bekanntes Advisory
0/25Indirekte Abhängigkeiten ohne bekannte Advisories — transitive Menge in diesem Bereich nicht von Entwicklungs- und Test-Abhängigkeiten trennbar
0/40Keine offenen Advisories — kein Advisory trägt ein Veröffentlichungsdatum
Verwendete Eingangsdaten
sourceosv
advisories6
affected_packages5
assessed_packages105
unassessed_packages0
affected_by_severityhigh 4, moderate 1
direct_affected_packages0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Indirekte Abhängigkeiten ohne bekannte Advisories, Keine offenen Advisories. Die verbleibenden Gewichte wurden renormalisiert. 105 aufgelöste Abhängigkeiten wurden mit OSV abgeglichen. Dieses Repository veröffentlicht kein Paket, das der Index auflöst; bewertet wurde daher der Abhängigkeitsgraph des Repositorys. Dieser Graph vermischt Entwicklungs- und Test-Pins mit ausgelieferten Abhängigkeiten, daher werden nur die deklarierten Laufzeit-Abhängigkeiten bewertet; transitive Befunde werden als Kontext ausgewiesen und fließen nicht in die Bewertung ein. Erreichbarkeit wird nicht analysiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

86Exzellent · 0 % des Gesamtindex
Wie die Bewertung erfolgt
45/45Agentenanweisungen — AGENTS.md, CLAUDE.md
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 99 von 100 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,99
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes7.403
Wie die Bewertung erfolgt
18/18Bootstrap mit einem Befehl — Makefile
22/22Automatisierte Tests
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — Swift (statisch typisiert)
10/10Reproduzierbare Umgebung — lockfile
10/10Belegte Agentenpraxis — 77 der letzten 100 Commits von Agenten verfasst oder ihnen zugeschrieben
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
10/10OpenSSF Scorecard: Pinned-Dependencies — all dependencies are pinned
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfilesGemfile.lock, package-lock.json
has_dockerfilenein
typed_languageja
bootstrap_filesMakefile
has_devcontainernein
has_linter_confignein
typecheck_configs
agent_commit_share0,77
toolchain_manifests
dependency_bot_commit_share0
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — Swift (statisch typisiert)
54.9/55Handhabbare Dateigrößen — 3/1.876 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageSwift
largest_source_bytes78.072
source_files_sampled1.876
oversized_source_files3

Eckdaten

40GitHub-Sterne
27Mitwirkende
1.740Commits, letzte 12 Monate
0Tage seit letztem Push
100Releases
2Bus-Faktor
20offene Issues
RubyGemsPaket-Ökosysteme

Weitere Details

Stern- und Fork-Verlauf 40 ★ / 22 ⇿
40Sterne
22Forks
100Releases

Wann jeder Stern und Fork hinzugefügt wurde, von GitHub erfasst und nach Tagen gruppiert. Das kumulierte Wachstum steht direkt über den täglichen Zugängen, aus denen es besteht, sodass beide gegeneinander lesbar sind: stetiger organischer Zuwachs sieht ganz anders aus als ein abrupter, kurzlebiger Ausschlag. Wo dieser Unterschied messbar ist, wird er als Wachstumsauthentizität ausgewiesen.

010203040402222024-032025-052026-07
Major 0Minor 13Patch 87

Jeder Punkt umfasst 3 Tage.

OpenSSF Scorecard 4.3 / 10
4.3Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).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
k. A.Packagingpackaging 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
Direkte Abhängigkeiten 2
RegistryPaketVersionsvorgabeManifest
RubyGemsfastlane2.229.1VultisigApp/Gemfile
RubyGemsostructVultisigApp/Gemfile
Alle Abhängigkeiten 105

Vollständig aufgelöster Abhängigkeitssatz aus dem GitHub-Abhängigkeitsgraphen: 2 direkte und 103 indirekte (transitive) Pakete. Die transitive Hülle ist vollständig, wenn das Repository eine Lockfile eincheckt.

RegistryPaketVersionBeziehung
RubyGemsfastlane2.229.1direkt
RubyGemsostruct0.6.3direkt
npm@cosmjs/crypto0.39.0indirekt
npm@cosmjs/encoding0.39.0indirekt
npm@cosmjs/math0.39.0indirekt
npm@cosmjs/utils0.39.0indirekt
npm@noble/ciphers2.2.0indirekt
npm@noble/curves2.2.0indirekt
npm@noble/hashes2.2.0indirekt
npm@scure/base2.2.0indirekt
npm@scure/bip392.2.0indirekt
npmbase64-js1.5.1indirekt
npmcosmjs-types0.11.0indirekt
npmreadonly-date-esm2.0.0indirekt
RubyGemsabbrev0.1.2indirekt
RubyGemsaddressable2.8.8indirekt
RubyGemsartifactory3.0.17indirekt
RubyGemsatomos0.1.3indirekt
RubyGemsaws-eventstream1.4.0indirekt
RubyGemsaws-partitions1.1211.0indirekt
RubyGemsaws-sdk-core3.241.4indirekt
RubyGemsaws-sdk-kms1.121.0indirekt
RubyGemsaws-sdk-s31.213.0indirekt
RubyGemsaws-sigv41.12.1indirekt
RubyGemsbabosa1.0.4indirekt
RubyGemsbase640.2.0indirekt
RubyGemsbigdecimal4.0.1indirekt
RubyGemsCFPropertyList3.0.8indirekt
RubyGemsclaide1.1.0indirekt
RubyGemscolored1.2indirekt
RubyGemscolored23.1.2indirekt
RubyGemscommander4.6.0indirekt
RubyGemscsv3.3.5indirekt
RubyGemsdeclarative0.0.20indirekt
RubyGemsdigest-crc0.7.0indirekt
RubyGemsdomain_name0.6.20240107indirekt
RubyGemsdotenv2.8.1indirekt
RubyGemsemoji_regex3.2.3indirekt
RubyGemsexcon0.112.0indirekt
RubyGemsfaraday1.8.0indirekt
RubyGemsfaraday-cookie_jar0.0.8indirekt
RubyGemsfaraday-em_http1.0.0indirekt
RubyGemsfaraday-em_synchrony1.0.1indirekt
RubyGemsfaraday-excon1.1.0indirekt
RubyGemsfaraday-httpclient1.0.1indirekt
RubyGemsfaraday-net_http1.0.2indirekt
RubyGemsfaraday-net_http_persistent1.2.0indirekt
RubyGemsfaraday-patron1.0.0indirekt
RubyGemsfaraday-rack1.0.0indirekt
RubyGemsfaraday_middleware1.2.1indirekt
RubyGemsfastimage2.4.0indirekt
RubyGemsfastlane-sirp1.0.0indirekt
RubyGemsgh_inspector1.1.3indirekt
RubyGemsgoogle-apis-androidpublisher_v30.54.0indirekt
RubyGemsgoogle-apis-core0.11.3indirekt
RubyGemsgoogle-apis-iamcredentials_v10.17.0indirekt
RubyGemsgoogle-apis-playcustomapp_v10.13.0indirekt
RubyGemsgoogle-apis-storage_v10.31.0indirekt
RubyGemsgoogle-cloud-core1.8.0indirekt
RubyGemsgoogle-cloud-env1.6.0indirekt
RubyGemsgoogle-cloud-errors1.5.0indirekt
RubyGemsgoogle-cloud-storage1.47.0indirekt
RubyGemsgoogleauth1.8.1indirekt
RubyGemshighline2.0.3indirekt
RubyGemshttp-cookie1.0.8indirekt
RubyGemshttpclient2.9.0indirekt
RubyGemsjmespath1.6.2indirekt
RubyGemsjson2.18.0indirekt
RubyGemsjwt2.10.2indirekt
RubyGemslogger1.7.0indirekt
RubyGemsmini_magick4.13.2indirekt
RubyGemsmini_mime1.1.5indirekt
RubyGemsmulti_json1.19.1indirekt
RubyGemsmultipart-post2.4.1indirekt
RubyGemsmutex_m0.3.0indirekt
RubyGemsnanaimo0.4.0indirekt
RubyGemsnaturally2.3.0indirekt
RubyGemsnkf0.2.0indirekt
RubyGemsoptparse0.8.1indirekt
RubyGemsos1.1.4indirekt
RubyGemsplist3.7.2indirekt
RubyGemspublic_suffix7.0.2indirekt
RubyGemsrake13.3.1indirekt
RubyGemsrepresentable3.2.0indirekt
RubyGemsretriable3.1.2indirekt
RubyGemsrexml3.4.4indirekt
RubyGemsrouge3.28.0indirekt
RubyGemsruby2_keywords0.0.5indirekt
RubyGemsrubyzip2.4.1indirekt
RubyGemssecurity0.1.5indirekt
RubyGemssignet0.21.0indirekt
RubyGemssimctl1.6.10indirekt
RubyGemssysrandom1.0.5indirekt
RubyGemsterminal-notifier2.0.0indirekt
RubyGemsterminal-table3.0.2indirekt
RubyGemstrailblazer-option0.1.2indirekt
RubyGemstty-cursor0.7.1indirekt
RubyGemstty-screen0.8.2indirekt
RubyGemstty-spinner0.9.3indirekt
RubyGemsuber0.1.0indirekt
RubyGemsunicode-display_width2.6.0indirekt
RubyGemsword_wrap1.0.0indirekt
RubyGemsxcodeproj1.27.0indirekt
RubyGemsxcpretty0.4.1indirekt
RubyGemsxcpretty-travis-formatter1.0.1indirekt
Abhängigkeits-Advisories 5

Dieses Repository veröffentlicht kein vom Index auflösbares Paket, daher wurde sein eigener Abhängigkeitsgraph bewertet – 105 Pakete, darunter auch Entwicklungs- und Test-Pins, die nie ausgeliefert werden: 5 tragen bekannte Advisories, davon 0 direkte.

PaketVersionBeziehungSchweregradAdvisoriesBehoben in
addressable2.8.8indirekthoch12.9.0
faraday1.8.0indirekthoch22.14.3
json2.18.0indirekthoch12.19.2
jwt2.10.2indirekthoch13.2.0
excon0.112.0indirektmittel11.5.0

Ein Advisory bedeutet, dass die im Abhängigkeitsgraphen erfasste Version in den betroffenen Bereich eines Advisories fällt. Erreichbarkeit wird nicht analysiert, und der Graph enthält Entwicklungs- und Test-Pins — ein Fund kann das Werkzeug betreffen und nicht die ausgelieferte Software.

JSON-Rohbericht maschinenlesbar
{
  "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"
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v1.13.0, Schema v0.26.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte Statistiken.