Dveře pro programy
Do 1.9 měl engine pro programy jedny dveře, a byly úzké. Telefon jimi doručil příspěvek: zkratka poslala soubor přes SSH, na druhé straně ho převzal receive.sh a odpověděl jedním objektem. Dva příkazy držely tenhle slib – add --json a publish --yes --json. Všechno ostatní byla obrazovka pro člověka: výpis, vlastnosti příspěvku, fronta, koš. Program, který se chtěl podívat, co je v archivu, neměl co zavolat.
1.10 otevírá dveře dokořán, a právě proto si dává záležet na tom, co jimi smí projít.
Každá obrazovka jako data
Každá obrazovka, kterou si člověk přečte, než něco udělá, a každá akce, kterou mu nabídne, má teď tvar --json: jeden objekt na standardním výstupu a nic jiného, každý klíč vždy přítomný. Odmítnutí je také objekt, {"ok": false, "error": "not_found", …}, a vrací nulu – návratový kód říká, jestli odpověď vůbec přišla, objekt říká, jaká byla. Program, který musí zkoušet, zda klíč existuje, si píše vlastní parser; tomu se tady předchází.
Z věty „u klávesnice nikdo není" plynou tři pravidla. Otázka, kterou dialog klade, je přepínač: slug opsaný pro potvrzení smazání je --yes, datum z dialogu plánování je --at, „posunout zbytek fronty?" je --compact. Bez přepínače je odpověď ne – program, který to neřekl, to nemyslel. Ty přepínače platí jen s --json: delete <slug> --yes v terminálu je odmítnuto, protože tam je dialog od toho, aby se zeptal, a přepínač, který potichu přeskočí potvrzení, je přesně to, čím historie shellu maže příspěvky. A příspěvek se jmenuje slugem a nikdy se nehádá: týž slug ve dvou letech je ambiguous_slug tam, kde by terminál ukázal oba a zeptal se.
Co stojí ve dveřích
Klíč programu nedostane shell. V authorized_keys má na řádku vynucený příkaz scripts/remote.sh, a ten umí dvě věci: spustit jeden příkaz a převzít zásilku. run přečte ze vstupu jeden řádek JSON, {"args": [...]}, tedy slova přesně tak, jak by je dostal ./blog.sh, a než je engine uvidí, každé z nich zkontroluje proti seznamu – příkazy, které program smí spustit, a ke každému přepínače, které smí dát. Nic se nikdy nečte jako shell; série „Procházky a výlety" cestuje jako jedno slovo a jako jeden argument dorazí.
Stejně důležité je, co v seznamu není, a schválně. add – příspěvek přichází jako zásilka, kterou převezme receive.sh se všemi svými kontrolami; pro odesílatele, který neumí zavřít proud, ji ukončí řádek end. export, preview, průvodci. doctor --online a check --online, protože sahají na síť pod účty autora; --strip-location, protože přepisuje fotografie; --repair. Každá z těch věcí buď otevírá editor, nebo se ptá, nebo zapisuje mimo archiv. Program s klíčem není autor u svého stolu.
Co engine ještě umí programu říct: version --json nese jméno webu, jeho barvy pro světlý i tmavý režim a jazyky, které vydává, aby se program mohl obléknout do barev blogu. A request může říct "lang": "cs" – nálezy check a doctor a to, co pair sám odmítne, pak přijdou v jazyce programu, ne blogu. Jen tyhle tři, protože nic nestaví; co dveře odmítnou dřív, než se engine vůbec spustí, říkají anglicky jako dosud.
Klíč, který se nepíše
Dostat program ke klíči znamenalo zkopírovat jeho veřejnou část a ručně napsat řádek do ~/.ssh/authorized_keys. To zůstává. Vedle toho ./blog.sh pair nakreslí v terminálu QR kód, program ho přečte a je připojený – nikdo nikam nepíše adresu, jméno účtu ani klíč.
Kód nese tři věci: kam se připojit, otisky vlastních klíčů serveru, aby program věděl, že dorazil na správný stroj, a klíč dobrý na jednu věc, jednou, deset minut – odevzdat veřejnou polovinu klíče, který si program vyrobil sám. Engine za něj pak zapíše obyčejný řádek, držený na scripts/remote.sh jako řádek psaný rukou. Klíč, na kterém program žije, zařízení nikdy neopustí; ten z obrazovky po použití neotevře nic.
pair --list zařízení očísluje, pair --revoke jedno vyhodí – číslem, jménem nebo otiskem; bez ničeho za sebou se terminál zeptá, které. Program smí totéž sám pro sebe: --list mu odpoví, které z nich je, a --revoke bez argumentu ho vyřadí, jen jeho. Kdo se ptá, ví engine ze slova na jeho vlastním řádku, --device=<otisk>, nikdy z toho, co request tvrdí. Ukázat kód a vyhodit cizí zařízení zůstává u terminálu.
K souboru, který rozhoduje, kdo se smí přihlásit: engine do něj píše jen řádky začínající restrict, s příkazem své vlastní instalace, nesahá na řádek, který nenapsal, a zbytek souboru nechá, jak byl. Blog v kontejneru chce svůj řádek stále napsaný rukou; doctor zmíní řádek po kódu, který nikdo nepoužil.
Pro koho ty dveře jsou
Pro skript, který každou neděli vypíše frontu. Pro program, který si přečte koncepty a jeden z nich naplánuje. Pro cokoli, co umí mluvit JSON přes SSH a nemá klávesnici. Dveře nejsou otevřené proto, aby se jimi dalo projít všude, ale aby se dalo přesně říct, kam ano: seznam povolených slov je to, co engine o programu ví, a na nic jiného se neptá.
Starší text o tom, co zbývá pokazit, je tady: What's left to get wrong.

Komentáře