Strona główna / Artykuły

Stwórz narzędzia dla programistów skupione na klientach, które nie wymagają ślepego zaufania

KitDev Space przechowuje hashe, JWT oraz archiwa w przeglądarce, używa Bun tylko wtedy, gdy wymagana jest obsługa natywna lub międzyhostowa, a także oznacza miejsce wykonywania każdego narzędzia.

Wydawca: REACTAPP.TOP6 min czytania1438 słów

Źródła: How I built KitDev Space, an open source hub of developer tools that never has to ask you to trust it

wklejanie tokena JWT z produkcji do pierwszego dekodera, który sugeruje wyszukiwarka, to powszechny nawyk. Celem jest jedynie odczytanie zawartych w nim danych, a mimo to token opuszcza urządzenie. Ten sam schemat występuje przy plikach .env w konwerterach oraz zdjęciach w narzędziach do usuwania danych EXIF: polityka prywatności twierdzi, że serwer nic nie przechowuje, a ta informacja jest przyjmowana bez krytyki.

KitDev Space ma na celu zmniejszenie tej potrzeby bezwarunkowego zaufania. Narzędzia codziennego użytku programistów nie powinny wymagać zaufania do operatora – włącznie z tym, który stworzył stronę. Kształt produktu opiera się na jednej wczesnej zasadzie, która została spisana i następnie uznana za niepodważalną.

Zasada

Należy preferować wykonywanie operacji po stronie klienta. Backend powinien być angażowany tylko wtedy, gdy środowisko strony rzeczywiście nie jest w stanie sprostać zadaniu.

Pierwsza połowa nie budzi kontrowersji. Druga połowa wymaga precyzyjnej definicji, w przeciwnym razie każda wygodna metoda przeniesie się na stronę serwera. Sytuacje, które rzeczywiście spełniają kryteria, były krótko opisane:

  1. Zadanie wymaga biblioteki natywnej. Kodowanie formatu AVIF lub rastrowanie plików SVG wymaga odpowiedniego kodera. Otwarcie połączenia TLS wymaga użycia socketa.
  2. Zadanie musi komunikować się z innym hostem. DNS, nagłówki odpowiedzi, RDAP oraz wstępne wyświetlanie treści OpenGraph nie działają lub powinny nie działać z strony ze względu na zasady CORS.
  3. Zadanie wymaga API działającego w czasie wykonywania, bez odpowiednika w przeglądarce, takiego jak Bun.dns lub Bun.Archive.
  4. Dane wejściowe są zbyt duże, by zmieściły się wygodnie w jednej karcie.

Jeśli narzędzie nie odpowiada żadnemu z tych kryteriów, pozostaje po stronie klienta. Wygoda skłoniła do wprowadzenia wyjątków w przypadkach, gdy ścieżka serwera składała się z dwudziestu linii, a ścieżka przeglądarki z dwustu. Te wyjątki jednak nie trafiły do ostatecznej wersji produktu.

Przeglądarka robi więcej, niż się spodziewano

Początkowe szacunki zakładały duży kod serwerowy. Większość zadań związanych z narzędziami deweloperskimi mieści się już w API platformy lub w małych zależnościach, które działają bez opuszczania strony.

  • Pomocniki do obliczania hashów od SHA-1 do SHA-512 za pomocą crypto.subtle.digest
  • Entropia i identyfikatory uzyskiwane za pomocą crypto.getRandomValues
  • Części kryptografii symetrycznej — AES-256-GCM, PBKDF2, HMAC — w ramach crypto.subtle
  • Modyfikacje geometryczne (zmiana rozmiaru, obrót, obcięcie) przy użyciu OffscreenCanvas oraz createImageBitmap
  • Eksport obrazów statycznych w formatach JPEG, PNG lub WebP za pomocą OffscreenCanvas.convertToBlob
  • Czytanie danych EXIF i GPS poprzez przeglądanie bajtów pliku za pomocą DataView
  • Kompresja i archiwizacja (gzip, deflate, tar) za pomocą biblioteki fflate
  • Formaty konfiguracji takie jak YAML, TOML, JSONC i JSON5 za pośrednictwem confbox
  • SQL w pamięci z użyciem sql.js działającego jako WebAssembly
  • Panel JWT sprawdza podpisy HS256 za pomocą Web Crypto i całkowicie pomija protokół HTTP. Ekran AES wytwarza potrzebne dane przy użyciu PBKDF2 wewnątrz karty. Przeglądarka plików archiwowych otwiera pliki tar bez konieczności ich przesyłania. Studio SQLite przechowuje bazę danych w pamięci. Wzorzec jest prosty: najpierw dokonuje się analizy platformy, a dopiero wtedy dodaje się odpowiednią ścieżkę, jeśli czegoś brakuje.

    Web Crypto nadal ma luki: brakuje funkcji MD5, CRC32 oraz xxHash. Biblioteka MD5 napisana wyłącznie w JavaScript mogłaby przeprowadzać haszowanie lokalnie, ale narzędzie to oferuje również xxhash64 i wyhash, a wysyłanie tych rzadko używanych algorytmów do każdego użytkownika wydawało się niewłaściwe. Te opcje wymagają ścieżki serwera, a interfejs jasno informuje o tym wybór po jego zaznaczeniu. Określenie trybu, który pozostawia obliczenia na urządzeniu, jest lepsze niż udawanie, że nic takiego nie dzieje się wcale.

    Jeden moduł, dwie ścieżki

    Kontynuowanie rozwijania wersji przeglądarkowych i serwerowych tego samego narzędzia prowadzi do cichej dywergencji. Dwa konwertery zaczynają się różnić, a identyczny wprowadzany danych nagle daje różne wyniki w zależności od środowiska wykonania. Wczesny konwerter formatów napotkał dokładnie taką awarię.

    Trwała struktura to wspólny moduł, który eksportuje zarówno proces wykonawczy, jak i małą sondę sprawdzającą możliwości. Interfejs użytkownika zadaje pytania sondzie, a ścieżka API importuje ten sam moduł. Dlatego logika haszowania znajduje się w jednym miejscu.

    // shared/utils/crypto/hash.ts
    const SUBTLE_NAMES = {
     sha1: 'SHA-1',
     sha256: 'SHA-256',
     sha384: 'SHA-384',
     sha512: 'SHA-512'
    }
    
    export function canHashInBrowser(algorithm: HashAlgorithm): boolean {
     return algorithm in SUBTLE_NAMES
    }
    
    // simplified page logic
    const result = canHashInBrowser(algorithm)
     ? await hashInBrowser(input, algorithm)
     : await $fetch('/api/hash', { method: 'POST', body: { input, algorithm } })
    

    Haszowanie, konwersja formatów, formatowanie kodu oraz semver wszystkie opierają się na tej strukturze. Nowe narzędzia z dwiema ścieżkami dziedziczą tę samą architekturę zamiast wymyślać kolejny podział.

    Jaki jest rzeczywisty cel serwera

    Narzędzia wspierane przez backend znajdują się na Bun. Każde z nich istnieje ze względu na jedną poważną wyjątkową sytuację:

    • Weryfikacja certyfikatów wymaga otwarcia rzeczywistego socketu w celu odczytu łańcuchów certyfikatów, danych SAN oraz uzgodnionych szyfrów.
  • Narzędzia do sprawdzania danych zdrowotnych wymagają informacji o typie A/MX/TXT oraz SPF, DKIM i DMARC.
  • Inspekcja nagłówków, wstępne wyświetlanie treści OpenGraph oraz RDAP wymagają pobierania danych od podmiotów trzecich.
  • Image Studio i funkcja pakowania ikon favicon wykorzystują Bun.Image, gdy konieczne jest stworzenie plików w formacie AVIF lub ICO.
  • Przekształcanie plików TS/JSX oraz narzędzia do edycji AST opierają się na wbudowanej implementacji OXC.
  • Trasy serwera są traktowane jako obciążenia i korzystają z tego samego listy kontrolnej przed wysłaniem żądania. Adresy URL muszą być zweryfikowane i mogą używać wyłącznie protokołów http lub https. Odrzucane są adresy localhost, prywatne zakresy IP, adresy link-local, punkty końcowe metadanych chmurowych oraz formy przejściowe IPv6, które ukrywają adresy IPv4 (takie jak NAT64 i Teredo, które pojawiły się podczas tworzenia tej listy odrzuceń). Porty docelowe są ograniczone, aby inspekcja TLS nie mogła skanować sieci. Sprawdzana jest długość treści, ciała żądań są przesyłane strumieniowo, a odczyty zatrzymują się po osiągnięciu ustalonego limitu, zamiast być buforowane w nieskończoność. Limity przepustowości wykorzystują klucz klienta niezwiązaný z x-forwarded-for, który jest łatwy do sfałszowania. Pliki przesyłane są przechowywane w pamięci, a nie na dysku. Dane wejściowe i wyjściowe nie są zachowywane.

    Analityka również podlega tym samym zasadom. Zdarzenia zawierają jedynie identyfikator narzędzia, nic więcej. Użytkowanie wizualizatora cron jest widoczne; wyrażenie wpisane przez użytkownika nie jest.

    Udostępnianie reguły

    Zasada, której nikt nie może zobaczyć, to marketing, a nie kontrola prywatności. Dlatego nawigacja wskazuje miejsce wykonywania operacji.

    Każda pozycja ma przypisaną etykietę. Oznaczenie „Client” oznacza, że strona nigdy nie wysyła żadnych danych. Oznaczenie „Bun” oznacza, że każda akcja trafia do serwera tła. Narzędzia z obiema ścieżkami pomijają etykietę oraz informację o tym, który gest powoduje zamknięcie karty. Te oznaczenia są generowane na podstawie dwóch flag rejestru – tego samego rejestru, który steruje tytułami i wyszukiwaniem – więc dokumentacja nie może być sprzeczna z implementacją.

    Zasób jest objęty licencją MIT i ma link w stopce strony. Etykietę „Client” można sprawdzić, otwierając moduł i upewniając się, że nigdy nie wywołuje on żadnej ścieżki. Ostatnim elementem projektu jest weryfikacja, a nie zaufanie.

    Co się tam znajduje

    Rozmiar katalogu zmienia się niemal co tydzień, więc liczba pozycji byłaby błędna już jutro. Najczęściej używane narzędzia, posortowane według funkcji:

    Praca z danymi: piękny wyświetlacz JSON, który obsługuje również JSON5/JSONC, generowanie typów TypeScript z JSON, swobodne przemieszczanie się między YAML, TOML, XML i CSV (w tym konwertowanie wierszy CSV na zapytania SQL), przeglądanie dużych tabel CSV oraz uruchamianie w przeglądarce studia SQLite.

    Pomocniki deweloperskie: notatnik z regularnymi wyrażeniami, który opisuje każdy token, kalendarz cron z informacjami o kolejnych uruchomieniach, konwertery z cURL do fetch, Axios, Python lub Go, konwertery HTML/SVG przeznaczone dla JSX lub Vue, narzędzie do pracy z plikami glob oraz lokalny przeglądarka plików tar.

    Kontrole sieciowe: sprawdzanie łańcucha certyfikatów, zapytania DNS, weryfikacja stanu autoryzacji skrzynek pocztowych, przeglądanie surowych nagłówków HTTP, obliczenia CIDR, dekodowanie plików cookie oraz wyszukiwania w RDAP.

    Narzędzia kryptograficzne: funkcje hashowania, HMAC, sprawdzanie tokenów JWT, kody TOTP, szyfrowanie/deszyfrowanie AES, a także generatorzy UUID i haseł.

    Narzędzia do kolorów: konwersja OKLCH, ocena kontrastu według WCAG, gradienty Tailwind, kompozycja gradientów CSS oraz wyodrębnianie palety z obrazu.

    Narzędzia do obrazów: łączone funkcje przycięcia/zmiany rozdzielczości/zawracania/konwersji, inspekcja lub usuwanie danych EXIF, rasteryzacja SVG do formatów PNG/WebP w rozdzielczościach 1x/2x/4x oraz narzędzie do pakowania ikon favicon w plik ZIP.

    Nie ma kont ani ścian płatności. Temat dostosowuje się do ustawień systemu operacyjnego, więc nie trzeba szukać oddzielnego sterowania trybem jasnym/ciemnym.

    Wnętrze aplikacji

    Stack implementacyjny został celowo utrzymany w prostocie: Nuxt 4 z Nuxt UI 4 w przeglądarce, komponenty VueUse, edytory CodeMirror, trasy uruchamiane za pomocą Bun, testy Vitest w połączeniu z Playwright oraz deploj na Vercel.

    Potrzebuję twojej pomocy

    Próbowałem https://kitdev.space – najbardziej przydatne są dwa raporty: który narzędzie było brakujące oraz czy jakieś narzędzie wysyłało dane na stronę serwera, mimo że powinno zostać zapisane lokalnie. Drugi raport wskazuje na brak w regułach.

    Repozytorium znajduje się zaledwie jeden kliknięciem od stopki strony. Witamy zgłoszenia i prośby o integrację dotyczące nowych narzędzi, poprawek lub korekt odznak. Taki ośrodek rozwija się dzięki większej liczbie osób angażujących się w niego – to główny powód, dla którego kod jest otwarty.

    Gdy tworzysz podobne narzędzia gdzie indziej, zachowaj tę samą krótką listę przypadków, w których przeglądarka naprawdę nie może dokończyć zadania. Wszystko inne powinno zostać zapisane na komputerze użytkownika.

    Literatura pokrewna

  • Pięć wskazówek dotyczących atrybutu rel, które przyspieszają pierwsze wyświetlenie treści — Użyj elementów preconnect, preload, dns-prefetch, prefetch oraz modulepreload w nagłówku dokumentu, aby przygotować połączenia i ograniczyć zużycie zasobów, bez konieczności przepisywania aplikacji.
  • Kiedy JavaScript przestaje być syntaksem i zaczyna być narzędziem — Początkujący często dążą do większej ilości kodu JavaScript, podczas gdy w rzeczywistości potrzebują projektów, informacji zwrotnej oraz umiejętności rozwiązywania problemów. Praktyczne punkty kontrolne i testy samopроверочные, które przekształcają syntakę w użyteczne narzędzie.