Tachibana

Neo6502 › Artikelen › Prophet

Een Prophet-server bouwen voor de Neo6502

Prophet is de programmarepository van de Neo6502-gemeenschap: een client op het bordje, een server ergens. Wij hebben de server in Go herschreven, veiligheid voorop, en prophet.3617.fr online gezet — met onze eigen programma's erin.

Door bmarty · Tachibana · 16 september 2026

Op de Neo6502 installeer je programma's vanaf de console: prophet.neo, de gemeenschapsclient die bocianu in Mad Pascal schreef, praat via een wifi-modem (AT-commando's) met een server en downloadt het bestand in blokken. De upstream-server, prophet-server, is geschreven in Python/Flask en gepubliceerd zonder licentiebestand; de huidige client kan geen TLS, dus de publieke server draait over HTTP. Wij wilden een eigen server — om AsteroNeo te publiceren, om het protocol te leren vóór we onze eigen client schrijven, en om hem zelf te hosten met onze eigen beheerregels. Neo6502Prophet is een onafhankelijke herimplementatie in Go, compatibel op protocolniveau, zonder één gekopieerde regel. Vier sprints in twee dagen; dit is wat we deden.

1. Het protocol vastleggen vóór er een regel geschreven wordt

Eerste stap: de client lezen, niet de server. prophet.pas stuurt GET met een header ResponseFormat: cli en parseert ruwe tekst, regeleinden \n\r inbegrepen: /cat voor de categorieën, gepagineerde /list/<cat>, /search, /app/<id> voor de fiche, /dirs en /files voor de boom, en dan /files/<id>/<n> in Range-blokken met antwoord 206. Twee stuurbytes (\x83, \x82) omsluiten het id in lijsten. /files/prophet/1 levert de update van de client zelf. De datarepository is een boom van mappen categorie/pakket/desc.yaml, oudere versies onder _N/. Alles staat in docs/ANALYSE-AMONT.md — met dank aan bocianu, wiens client, server en datarepository dit alles mogelijk maken — en met wat niet is geverifieerd: de publieke server kan afwijken van de gepubliceerde code.

2. Onze beveiligingskeuzes

Een programmarepository is een publieke HTTP-dienst die bestanden verspreidt die bordjes gaan uitvoeren. Vóór het schrijven hebben we de klassieke risico's van zo'n dienst opgelijst en besloten elk ervan te beantwoorden: nooit een debugmodus, standaard lokaal luisteren; elke actie — het verversen van de repository, dat een git pull doet — geauthenticeerd; gevalideerde en begrensde parameters, fouten zonder stacktrace; geleverde bestanden ingeperkt tot hun map, links genegeerd; gefilterde id's; een logboek met rotatie; geen toestand gedeeld tussen verzoeken; catalogus in het geheugen herladen zonder tussenbestand; een vingerafdruk voor elk geleverd bestand. Negen punten, vastgelegd in SECURITY.md en getest.

3. De onze: Go, alleen-lezen, veiligheid voorop

Standaardbibliotheek en yaml.v3, één statische binary. Geen schrijf-API; /refresh vereist een token van minstens 16 tekens, vergeleken in constante tijd, respecteert een minimale wachttijd, doet git pull --ff-only zonder shell en met time-out — zonder token bestaat het endpoint niet (404). Id's gefilterd op reguliere expressie, begrensde gehele getallen, sortering via witte lijst, beperkte zoeksleutel, begrensde verzoekbody; elke ongeldige invoer geeft een tekstuele 400 of 404, nooit een stacktrace. Bestandspaden worden vanaf de root herberekend en gecontroleerd: binnen de map, regulier bestand, geen link. De catalogus wordt in het geheugen gescand en atomair vervangen; elk bestand toont zijn SHA-256 in de JSON. De server luistert standaard op 127.0.0.1.

Het tekstformaat van de client is byte voor byte nagemaakt en zo getest. Eén toevoeging: de console van de Neo toont alleen ASCII, dus titels en beschrijvingen worden voor de client getranslitereerd terwijl de JSON UTF-8 blijft. En een dubbele listener: HTTP op 8998 voor de huidige clients, native HTTPS (TLS ≥ 1.2) voor de modems die het straks kunnen — de Pico W van PicoWiFiModemUSB, de story "picowifitls" aan de kant van Neo6502drive.

4. Niet zomaar alles serveren

Een programmarepository verspreidt binaries die mensen gaan uitvoeren. Twee vangrails. Statisch: neocheck leest elk .neo-bestand (header, blokken, grenzen, kernelgebied); een ongeldig bestand wordt niet geleverd, een "ruw" bestand wordt gemarkeerd (neo = ok/raw/invalid in de JSON). Dynamisch: neotrace speelt elk programma af in Phosphoneo met de trace van API-aanroepen (--api-log) en het effectieve adres van elke schrijfactie, en reconstrueert wat het programma met de kernel deed. Herhaling van 16 september: 56 programma's van de 56 (46 .neo, 10 .bas) draaien, geen onopgeloste schrijfactie, geen kwaadaardig gedrag waargenomen; één aantekening: zc.neo schrijft in het kernelgebied (tabel op $FC20) zonder zichtbaar effect. De audit vond ook een bug in Phosphoneo — een grafisch blok $FFFF dat bij het laden werd genegeerd — inmiddels verholpen.

5. Een webinterface, zonder de client te breken

Geserveerd op / alleen aan browsers (Accept: text/html zonder ResponseFormat: cli): catalogusraster met hoes, zoeken en filteren, fiche met beschrijving, versie, bestanden, grootte, .neo-status, SHA-256 en download. Ingebedde HTML, CSS en JS, geen afhankelijkheden, strikte CSP. De hoezen zijn schermafbeeldingen die een script in Phosphoneo maakt — 42 pakketten van de 42. Een aparte test controleert dat de tekstclient exact hetzelfde antwoord krijgt als voorheen.

6. In productie: prophet.3617.fr

Een eigen niet-geprivilegieerde Debian 13-container (1 kern, 512 MB), geharde systemd-service (systemd-analyze security blootstelling 1.3), nftables dat poort 8998 alleen vanaf de reverse proxy toelaat, automatische beveiligingsupdates. Caddy beëindigt TLS (https://prophet.3617.fr) en geeft ook onversleuteld HTTP op 8998 door voor ESP8266-clients, met Crowdsec; een uurlijkse timer ververst de spiegel van de gemeenschapsrepository via het lokale token. Meerdere datamappen worden naast elkaar geserveerd: de spiegel van bocianu en onze eigen repository, waar AsteroNeo 0.2.0 het eerste gepubliceerde pakket is (/app/asteroneo, hoes inbegrepen). Per 16 september: 37 spellen, 5 tools, 1 overig.

7. Wat we niet beweren

De server is nog nooit bevraagd vanaf een echt Neo6502-bordje: we hebben er geen, en de end-to-end-test via de Pico W-modem wacht op de TLS-story van Neo6502drive. De upstream-client controleert de SHA-256 die wij tonen niet — alleen een aangepaste client zal dat doen. De dynamische audit zegt wat de programma's in de emulator deden, niet wat ze op een bordje met andere invoer zouden doen. De code van de server heeft nog geen publieke repository. Volgende stap: een native grafische client ("B") voor de Neo6502, met vooraf geconverteerde hoezen, TLS en controle van de vingerafdruk.

Bronnen & links

← Neo6502 · AsteroNeo → · Neo6502 →