Left-pad incident (2016)

Jedan frustrirani developer u Oaklandu obrisao je 11 linija koda i na dva sata ugasio pola interneta — dobro jutro, moderni softver.

poglavlje 7/2618 min čitanja2011 – 2019
ti@kronika:~$ ./sviraj K6_7_leftpad.mp3

# da, poglavlje ima pjesmu. ne, nitko ne zna zašto.

Utorak, 22. ožujka 2016. Negdje popodne po pacifičkom vremenu, u uredu koji vjerojatno miriše na kavu od jučer, developer po imenu Azer Koçulu otvara terminal. Nema publike, nema live streama — samo on, tipkovnica i odluka koju je već donio u glavi prije nekoliko dana. Milijuni kilometara optičkih kablova dalje, na drugom kraju planeta, tisuće drugih developera upravo u tom trenutku rade nešto posve dosadno i posve rutinsko: upišu naredbu „npm install”, koja s interneta povuče sve sitne komadiće koda od kojih je njihov projekt sagrađen, i odlaze po kavu dok im se on sam sastavlja.

Godina je 2016. Poglavlje 6. već ti je rekao koliko je npm u tom trenutku krvotok cijelog JavaScript svijeta, ali reci to naglas: svaka moderna web stranica, svaka aplikacija, svaki startup koji je taj tjedan dobio rundu financiranja oslanja se na lanac paketića koje je netko, negdje, jednom davno napisao i objavio besplatno. Nitko ne pita tko je taj netko. Nitko ne provjerava. Naredba „npm install” izvodi se milijune puta dnevno, i svaki put je to mali čin vjere — vjere u nepoznatog stranca čije ime nikad nećeš pročitati, jer zašto bi, paket radi, zeleno je, idemo dalje.

Azer Koçulu jedan je od tih nepoznatih stranaca. Ima paket koji se zove kik. Ima i pravnike messenger aplikacije Kik na vratu, koji žele to ime za sebe. Ima npm koji je, kad je trebalo presuditi tko je u pravu, stao na stranu firme s odvjetnicima, a ne developera s principom. I ima — evo ključne riječi ovog poglavlja — bijes. Ne glasan, ne u velikim slovima. Onu tihu, odlučnu vrstu bijesa koja se ne svađa, nego jednostavno povuče utikač.

Sljedećih nekoliko sekundi Koçulu neće provjeravati što će se dogoditi. Neće razmišljati o tome da jedan od njegovih paketa — star, trivijalan, gotovo smiješno mali — drži u zraku pola interneta bez da to bilo tko znao. Pritisnut će enter na naredbi koja briše sve njegove pakete iz registra, sve odjednom, iz principa. Jedan od njih ima jedanaest linija koda. Zove se left-pad, i sve što radi jest da ispred nekog teksta dometne razmake ili druge znakove dok string ne naraste na željenu duljinu — sitnica kakvu bi svaki iole vičniji programer napisao sam u pauzi za kavu, samo što je netko to već napisao, objavio, i pola svijeta je odlučilo da je lakše preuzeti tih jedanaest linija nego ih otkucati. Zove se left-pad. I u naredna dva sata, dok sunce zalazi negdje na američkoj zapadnoj obali, taj paket će održati modernom softveru najbolju i najbolniju lekciju u njegovoj povijesti.

Utorak, 22. ožujka 2016., kasno popodne po pacifičkom vremenu. Koçulu sjedi pred ekranom i radi nešto što je u tom trenutku sasvim legalno, sasvim njegovo pravo, i — kako će se pokazati kroz dva sata — sasvim dovoljno da zapali cijeli internet. Briše svoje pakete s npm registra, one iste koje je sâm objavio. npm registar je, pojednostavljeno, ogromna online »baza« gdje programeri po cijelom svijetu objavljuju gotove komadiće koda (pakete) da ih drugi mogu besplatno preuzeti i ugraditi u svoj projekt, umjesto da isto pišu iz nule — a brisanje s tog registra znači da paket u trenu nestane svima koji su na njega računali. Briše ih sve. Svih 273.

Da vidimo kako je došlo do toga, jer priča nije počela u utorak. Počela je tjednima ranije, oko jedne riječi: kik. Koçulu je imao paket koji se tako zvao. Firma Kik Interactive — ona koja pravi messenger istog imena — poslala je njihovim odvjetnicima ono što odvjetnici šalju kad žele nešto tuđe: pismo. Sačuvani mailovi (da, cijela je prepiska poslije procurila i postala materijal za analizu na svakom developerskom forumu) pokazuju točno onoliko uglađene agresije koliko i očekuješ. Odvjetnik firme, hladno i korektno: naš klijent ima registriran trgovački znak »Kik«, vaš paket zbunjuje korisnike, molimo preimenujte ga ili ćemo se obratiti npm-u. Koçulu, jednako hladno, ali s principom umjesto branda iza sebe: paket se zove kik jer je on prvi upisao to ime u registar, mjesecima prije nego što je Kik Interactive i pomislio na npm, a po nepisanom pravilu registra — tko prvi stigne, njegovo je ime, bez obzira ima li iza sebe firmu s odvjetnicima ili tipa s laptopom u vlastitom stanu.

npm je presudio u korist Kika. Ne zato što su njihovi odvjetnici bili uvjerljiviji, nego zato što je Kik Interactive kupac, potencijalni i stvarni, a firma koja održava registar s nekim mora poslovati, i taj netko rijetko je tip iz Oaklanda s laptopom. Paket kik je prisilno preimenovan, bez pitanja vlasnika. E, to je za Koçulua bila crta. Ne novac, ne ime — nego princip: da neka korporacija može doći, mahnuti pravnim dopisom, i tvoje ime na tvom radu nestane preko noći, po odluci treće strane koja te nije ni pitala.

Napisao je poruku na svoj profil — nešto u fazonu da otkazuje suradnju s npm-om zbog toga kako su postupili, da je gotovo, hvala i doviđenja — i pritisnuo gumb koji rijetko tko koristi u toj mjeri: unpublish, ono dugme koje trajno briše paket iz registra, kao da nikad nije postojao. Ne samo kik. Sve. Svaki paket koji je ikad objavio, uključujući jedan toliko malen da ga je vjerojatno napisao za jedno popodne, prije godinu-dvije, bez ikakve namjere da postane povijesna točka. Zvao se left-pad.

I to je to. U nekoliko sekundi, 273 paketa nestaju iz registra — tiho, bez fanfare, bez upozorenja onima koji o njima ovise. Među njima i left-pad, paket koji ne radi ništa spektakularno: uzme string i, ako je kraći od zadane dužine, dopuni ga razmacima ili nulama s lijeve strane, tip stvari koju bi svaki iskusniji programer napisao u jednoj liniji za pet minuta, samo što je netko to već napisao, objavio, i pola interneta je odlučilo — zašto izmišljati toplu vodu, uzet ćemo tuđu. Nema crvenog alarma, nema obavijesti svijetu koji ovisi o tim datotekama. Samo praznina gdje su prije bili redovi koda, dostupni od jučer, danas, uvijek — sve dok nisu bili.

Na drugoj strani planeta, u uredima koji rade do kasno, developeri pokreću svoje build pipeline-ove kao i svaki drugi dan — onaj automatizirani proces u kojem alat (Jenkins, Travis i slični) sam pokupi kod, provjeri ga, sastavi i istestira prije nego što ide dalje, bez da čovjek ručno pipa svaki korak. Ništa neobično. Zapravo — baš ništa. Cijeli internet još spava u uvjerenju da je jučer bilo kao danas, a danas će biti kao sutra. Samo što je negdje na serveru npm-a upravo izbrisan blok od jedanaest linija koda, i nitko, baš nitko, u tom trenutku nema pojma da je upravo povučen okidač.

17:30 — svijet se ruši
§ 02

17:30 — svijet se ruši

Poslijepodne, negdje između ručka i kraja radnog dana. Netko u Berlinu pokreće build. Standardna stvar, radi je stotinu puta dnevno, kava još vruća pored tipkovnice. Terminal ispiše nešto što nikad prije nije ispisao: module not found: left-pad. Developer trepne. Left-what? Provjeri package.json — datoteku u kojoj je, kao na popisu za kupovinu, napisano koji sve paketi projektu trebaju — provjeri node_modules, mapu na disku gdje se te namirnice stvarno spremaju nakon što ih npm donese, provjeri je li mrežni kabel još u zidu. Pokrene ponovno. Ista poruka. U tom trenutku on još ne zna da nije sam — da u istoj sekundi identičnu poruku gleda netko u Austinu, netko u Bangaloreu, netko u sobi tri kata iznad njega u istoj zgradi, na drugom projektu, za drugog klijenta.

npm install se odvija bez pitanja odakle stvari dolaze — dok odjednom ne dolaze. A one koje ne dolaze su, ironično, apsurdno male. left-pad, ta sitnica koja dopunjuje stringove, ima kod koji stane u rubriku pored ovog teksta — jedanaest linija, funkcija koja bi na razgovoru za posao bila pitanje za pripravnika, ne infrastruktura na kojoj visi pola interneta. Pa opet visi. Koristio ga je, negdje duboko u lancu ovisnosti, Babel — alat koji noviji JavaScript kod prevodi u stariji da bi radio i na pretpotopnim preglednicima, i koji usput taj kod minificira, odnosno stisne datoteku da bude što manja i brža za učitavanje. Preko Babela, pola JavaScript ekosustava koji se transpilira, buildira i minificira svake minute negdje na planetu. React projekti, alati koji ovise o alatima koji ovise o alatima — deset, dvanaest slojeva duboko, dok na samom dnu, u temeljima, ne stoji beton nego jedanaest linija koje je jedan čovjek u Americi upravo obrisao iz principa.

Poslijepodne, 22. ožujka 2016. CI dashboardi po cijelom svijetu počinju mijenjati boju. Zeleno u crveno, red po red, kompanija po kompanija — kao da netko lije boju kroz vremenske zone. Jenkins u Berlinu, Travis u San Franciscu, timovi koji rade na dijametralno različitim proizvodima — bankovne aplikacije, igre za mobitele, interni alati koje nitko izvan firme nikad neće vidjeti — svi gledaju istu poruku o istom nepostojećem paketu. Netko na Twitteru (Twitter, ne X — ovo je 2016., svijet je bio jednostavniji) objavljuje snimku ekrana s crvenim buildom i natpisom: is npm down or am I losing my mind. Odgovori stižu brže nego što ih stigne pratiti — i mind, i npm, oboje odjednom.

Do 18:00 postaje jasno da to nije glitch, nije lokalni problem, nije nečiji loš deploy. Netko konačno spoji točke i objavi objašnjenje: čovjek po imenu Azer Koçulu povukao je 273 svoja paketa jer mu je npm, na zahtjev druge firme koja se zvala isto kao jedan od njegovih paketa, oduzeo pravo na to ime — a left-pad je bio slučajna žrtva u tom sukobu, kolateralna šteta rata koji nije imao nikakve veze s dopunjavanjem nizova znakova razmacima. Reakcija svijeta u tom trenutku ima dvije faze u razmaku od otprilike deset sekundi: prvo nevjerica da je moguće da baš TO srušilo baš SVE, a odmah iza nje, tiše i neugodnije, pitanje koje se ne izgovara na glas dok ne prođe panika — ako je jedanaest linija ovo mogla učiniti, što je, zapravo, sve to ostalo na čemu stojimo?

19:00 — presedan iz nužde
§ 03

19:00 — presedan iz nužde

Predvečer istog dana. Netko u npm-ovom uredu — pretpostavljam da je to već bio poluhisterični trg razgovora na internom Slacku (njihovom internom chatu), jer kako drugačije izgleda soba u kojoj gledaš kako ti se cijela industrija topi na dashboardu — donosi odluku koja u tom trenutku djeluje kao jedina razumna, a retrospektivno je jedna od najkontroverznijih u povijesti open sourcea (pojam za kod koji je javno dostupan i besplatan za korištenje, upravo zato što ga netko poput Koçulua odluči tako podijeliti sa svijetom). Vraćaju left-pad. Ne pitajući Koçulua. Ne tražeći dopuštenje. Uzimaju paket koji je autor namjerno, svjesno i s punim pravom obrisao, i stavljaju ga natrag na policu kao da se ništa nije dogodilo.

Zvuči tehnički dosadno kad to tako napišeš. Nije. To je trenutak u kojem jedna firma, preko noći, bez javne rasprave, bez glasanja, bez ičega što bi ličilo na demokratski proces, redefinira što znači »objaviti kod na internetu«. Do tog utorka pretpostavka je bila jasna: paket je tvoj, registar je samo vitrina, a ti odlučuješ što u njoj stoji. Poslije tog utorka pretpostavka je druga: paket je tvoj dok ga netko dovoljno ne zatreba. Onda postaje — pa, ne tvoj. Nečiji zajednički. Infrastrukturni. Prevelik da propadne, čak i kad ima jedanaest linija.

Vatra se gasi brzo — brže nego što se širila – jer čim se registar ažurira, CI pipelinei ponovno prolaze i svi ti crveni kvadratići u Berlinu i San Franciscu polako počinju svjetliti zeleno. Do kasne večeri 22. ožujka, praktički sve radi kao da se ništa nije dogodilo. Requiem od dva sata. Svijet nastavlja tipkati, slati kod na server (to je »deploy«), spajati tuđe promjene u svoj projekt (to je »pull request«) — ne znajući, ili ne mareći, da se ispod njihovih nogu upravo dogodila mala pravna i filozofska drama koju će pravnici, akademici i ljutiti developeri na forumima žvakati narednih godina.

Jer pitanja koja je taj potez otvorio nisu se zatvorila s incidentom, naprotiv, tek su se rasplamsala. Čiji je, zapravo, paket koji je objavljen javno, ali ga besplatno koristi pola planeta, bez da je ikad nekome platio, pitao ga za dozvolu ili mu barem zahvalio? Ima li autor pravo povući svoj kod kad to povlačenje šteti trećima koji nisu ni znali da taj kod postoji, a kamoli da o njemu ovise cijeli njihovi projekti? I, možda najneugodnije od svega, tko je odgovoran kad se sve sruši? Autor koji je maknuo kod koji je sam, dobrovoljno, dao svima? npm, koji je dopustio da jedanaest linija postane mjesto gdje cijeli internet može pući? Ili svi ti timovi koji su, godinama, instalirali tuđi kod bez da su ga uopće pogledali?

npm nije čekao kraj filozofske rasprave da donese odgovor — pravila se mijenjaju unutar tjedana. Povlačenje paketa (»unpublish«) više nije neograničeno pravo autora da u svakom trenutku izbriše svoje djelo s lica interneta. Paket stariji od 24 sata, ili s dovoljno preuzimanja, ili s previše projekata koji o njemu ovise, više se ne može jednostavno maknuti. Autonomija autora, ona sveta krava otvorenog koda, dobiva svoj prvi stvarni, dokumentirani ožiljak. Ne zato što je netko to htio iz principa, nego zato što je jedan čovjek, iz principa, umalo srušio internet, i firma koja drži ključeve odlučila je da se to više ne smije ponoviti — bez obzira koliko je čist bio motiv koji je do toga doveo.

Dan poslije: ogledalo
§ 04

Dan poslije: ogledalo

22. ožujka 2016., jutro. Požar je ugašen prije nego što je većina Amerike stigla na posao, ali dim se još osjeća. I, kao i svaki put kad nešto pregori, prva jutarnja aktivnost nije popravak — nego pisanje o tome što se upravo dogodilo. Netu je trebalo manje od dvanaest sati da iz šoka prijeđe u filozofiju. Prvi veliki tekst potpisuje Keith Collins, ali onaj koji je stvarno zapalio komentare zove se jednostavno: „Have we forgotten how to program?” Autor, David Haney, postavlja pitanje koje je pola JavaScript zajednice čekalo da netko izgovori naglas: ako je cijeli internet zaustavljen jer je nedostajalo jedanaest linija koda koje popune string razmacima do željene dužine, jesmo li mi to zaboravili napisati te razmake sami?

Argument je star koliko i samo programiranje, samo što se ovaj put odigrao uživo, pred kamerama. Zašto uvoziti tuđi paket za funkciju koju bi bilo koji junior napisao u pet minuta? Funkcija `String.prototype.padStart`, koja danas radi upravo to, tada još nije postojala u specifikaciji — mala, neugodna sitnica koja ironiju čini još debljom — ali suština prigovora ostaje: negdje između DRY principa („don't repeat yourself”, odnosno „ne piši isti kod dvaput”) i modernog paketnog menadžmenta, developeri su prestali pitati koliko te ovisnosti uopće koštaju. Svaki `npm install` postao je čin vjere. Vjere u nepoznatog čovjeka koji je jedne večeri, ljut, odlučio da mu je dosta.

Ono što je Haneyev tekst zapravo otkrio nije glupost jednog paketa, nego nešto puno neugodnije: nitko nije znao koliko je paketa zapravo ispod njega. Netko je tog jutra, iz čiste morbidne znatiželje, pokrenuo naredbu „npm ls” na prosječnom projektu izgrađenom na Reactu ili Babelu (dvije od najpopularnijih JavaScript alatki tog doba) i zapanjeno gledao izlaz koji se protezao kroz stotine, ponekad tisuće redaka. To su bile tranzitivne ovisnosti — paketi koje nisi ti instalirao, nego su ih instalirali paketi koje si ti instalirao, koje su instalirali paketi koje su instalirali neki drugi paketi, i tako u nedogled. Prosječan moderni JS projekt te 2016. znao je povlačiti stotine takvih tranzitivnih paketa. Stotine potpisa povjerenja, upisanih automatski, bez da ih je pročitao ni jedan par ljudskih očiju.

To je graf — zamisli ga kao ogromnu mrežu isprepletenih niti, poput obiteljskog stabla u kojem svaki paket „vjeruje” paketu koji je pozvao, koji vjeruje sljedećem, i tako u nedogled. Taj razgranat, nevidljiv graf povjerenja svakim „npm install” širi po serverima cijelog planeta, a nitko ga nikad nije nacrtao, jer nitko nije imao razloga. Dok radi, graf je transparentan kao zrak. Tek kad jedan čvor — jedna točka u toj mreži, jedan paket — nestane, cijela ta arhitektura postane vidljiva u trenu, kao rendgenska slika kostura koja se ukaže samo pod pravom vrstom udarca. Ironija je surova: alat koji je otkrio strukturu bio je paket manji od SMS poruke.

Haney na kraju svog esejа ne traži povratak u kameno doba pisanja svega ispočetka — priznaje da je to nemoguće i, iskreno, glupo. Njezina poanta je tiša i neugodnija: problem nije što postoje mali paketi, problem je što smo izgradili sustav u kojem se povjerenje dodjeljuje automatski, bez ičije svjesne odluke, milijunima puta dnevno. Programer koji upiše „npm install” ne potpisuje ugovor. Ne čita licencu. Ne provjerava autora. On samo — vjeruje. A vjera je, kao što je taj utorak dokazao, uvijek samo jedna loša volja daleko od povlačenja.

Ostavština parabole
§ 05

Ostavština parabole

Utorak je davno prošao, buildovi su zeleni, svi su otišli kući i, vjerojatno, neki od njih taj tjedan pili malo tiše nego inače. Ali riječi ostaju kad se prašina slegne, i jedna riječ koja je iz tog tjedna izašla i ušla u svakodnevni rječnik inženjera jest supply chain — lanac opskrbe. Do ožujka 2016. taj izraz je zvučao kao nešto iz udžbenika logistike: kontejneri, brodovi, skladišta. Poslije tog dana zvuči kao nešto što ti se može srušiti na glavu iz npm registra u petak popodne. Left-pad je bio prva lekcija. Prava katastrofa, ona koja će pokazati da lekcija nije bila dovoljno naučena, dogodit će se koju godinu kasnije s Log4Shellom (o tome opširnije u jednoj od narednih knjiga) — i tamo će se pokazati da je cijeli svijet i dalje visio na istim šibicama, samo veselijim.

Ali nešto se ipak promijenilo, i pravedno je to priznati. Poslije left-pada su lockfiles — datoteke koje bilježe točno koju verziju svakog paketa (i svakog paketa unutar tog paketa) tvoj projekt koristi — prestale biti opcija za pedante i postale zadana praksa. package-lock.json, yarn.lock, kasnije pnpm-lock.yaml — svi rade istu stvar: zamrzavaju stvarnost u trenutku kad je sve radilo, da te ne uhvati promjena koju nisi tražio i za koju nisi ni znao da postoji. Firme su počele voditi vlastite mirrore registra, privatne kopije cijelog npm svemira, da im tuđi bijes (ili tuđi odvjetnici) ne mogu ugasiti svjetlo. Vendoring — fizičko kopiranje tuđeg koda u vlastiti repozitorij, umjesto povlačenja s interneta svaki put — ponovno je postao respektabilna opcija, a ne znak da ne znaš koristiti alate. Imunosustav se, drugim riječima, počeo graditi. Sporo, i nikad potpuno, ali počeo.

Pa dobro, čemu onda cijela ova rekonstrukcija, ako pouka nije nova i imunosustav nikad nije dovršen? Zato što je ovo bila prva demonstracija, u realnom vremenu, s pravim satima i pravim panikama, da moderni softver nije zgrada od cigle. Zgrada od cigle ne stoji zato što je jedan od zidara dobro raspoložen. Ono što gradimo danas više podsjeća na katedralu sagrađenu od šibica — nevjerojatno visoku, impresivno detaljnu, punu tornjeva koji se penju jedan na drugi — a šibice drže volonteri koji su to radili besplatno, u slobodno vrijeme, i koji ostaju raspoloženi otprilike do prve nezahvalne poruke od odvjetnika, nakon koje mirno izvuku svoju šibicu i odu na kavu.