feat: F5.6b server F as an image: the editor from F itself, one stack per environment

F hands out the editor's page and bundle (editor/ beside main.mjs, or
FILIUS_EDITOR_DIR): GET and HEAD only, one wall against leaving the folder,
F's own routes first, assets/ cached a year, the rest asked for again; the
build lays .br and .gz beside the files and F sends the better one the
browser takes (bundle 695 KB to 212 KB).

deploy/Dockerfile: two stages, Node 24, no node_modules, not root.
deploy/docker-compose.yml with an env file per environment: the file sets
the stack's name, volume, image tag and port (test 8081, production 8080).
Measured with both stacks side by side behind nginx and Chromium.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 17:43:51 +00:00
co-authored by Claude Opus 5.5
parent 709146b58a
commit 087721cba3
19 changed files with 714 additions and 10 deletions
+10
View File
@@ -283,6 +283,7 @@ Swift-Pfade relativ zu `filius-ipad/ios/FiliusPad/TopologyEditor/` (Stand
| `src/sync.ts` (Zugang gleich zu Beginn, stille Absage) | Plan §8.5 | geändert (F5.3b): jede Verbindung erfährt ihren Zugang sofort nach der Anmeldung (Nachricht `access`), damit der Editor weiß, ob er liest und warum; eine Absage trägt keinen Meldungstext — Hocuspocus schreibt sonst die Meldung eines gescheiterten Hooks auf die Konsole, außerhalb des JSON-Protokolls |
| `src/sync.ts` (`you`), `protocol/src/sync.ts` (`AccessMessage.you`) | Plan §7.4 | erweitert (F5.4): die Zugangsnachricht beim Verbinden nennt die Person (Kennung, Name, Farbe aus der Karte), damit der Editor sich den anderen zeigen kann — der Keks ist für die Seite nicht lesbar |
| `src/blobs.ts`, `src/blobRoutes.ts`, `src/simWorker.ts` (Blobs), `src/simRooms.ts` (Blobs), `src/simChannel.ts`, `src/server.ts` (`/blobs`), `src/main.ts`, `test/blobs.test.ts` | Plan §5.1 | neu (F5.5): die Blobs auf F, inhaltsadressiert (`filius_blob`, F rechnet den Namen selbst aus); `GET /blobs/<sha>?project=` mit Berechtigung am Projekt, `POST /blobs?project=` mit Schreibstufe, nicht eingefroren, nur von der Herkunft des Editors, höchstens 16 MiB; CORS für die Herkünfte des Editors; der Raumfaden fragt nach den Blobs seines Dokuments, ein Start wartet auf die gefragten, was F noch nicht hat, wird ein paar Mal neu gefragt und kommt in die laufende Simulation; ein Blob, den die Simulation macht, wird gespeichert, bevor die Änderung, die ihn nennt, angewandt wird. Noch nicht: Blobs vergessen, die kein Projekt mehr nennt |
| `src/editorFiles.ts`, `src/precompress.ts`, `src/precompressMain.ts`, `src/server.ts` (Editor), `src/main.ts` (`FILIUS_EDITOR_DIR`), `test/editorFiles.test.ts`, `editor/browser/fromF.spec.ts` | Plan §8.2, §8.3 | neu (F5.6b): F liefert die Seite und das Bundle des Editors selbst aus (Ordner `editor/` neben `main.mjs`), damit der Editor von Fs Herkunft kommt und sie als seinen Server nimmt; nur GET und HEAD, nur Dateien im Ordner (jedes `..`, auch kodiert, wird aufgelöst und außerhalb abgewiesen); Fs eigene Wege gehen vor; `assets/` (Vite benennt nach dem Inhalt) ein Jahr im Cache, alles andere jedes Mal neu gefragt; der Build legt `.br` und `.gz` daneben, wo sie kleiner sind, F schickt die bessere, die der Browser nimmt (das Bundle 695 KB → 212 KB mit brotli). Ohne Ordner beantwortet F nur seine Wege und meldet es im Protokoll |
| `test/editorConnection.test.ts` | — | neu (F5.3b), erweitert (F5.4: Identität von F, die anderen über die Awareness, auch eine lesende Person, weg mit dem Schließen): `connectSharedDoc` des Editors gegen einen echten F — bereit mit Schreib- und Lesestufe, eingefroren und aufgetaut (neues Dokument, die verirrte Änderung ist weg, Schreiben geht wieder), eingefroren von Beginn an, Absage, Widerruf, Löschen, Loslassen |
| `test/sim.test.ts`, `test/harness.ts` (Faden) | — | neu (F5.3a): echte Sockets, der echte Faden (esbuild bündelt ihn wie der Build), Beispiel internetwork_komplett: ein Start für alle mit Namen, Ping in einer Befehlszeile bei der anderen, Zurückschreiben ins Dokument und eine Datei aus dem Dokument im Raum, Lesestufe, Absagen, Nachlauf, Einfrieren, Löschen, Widerruf, Wahl des Fadens, scheiternder Faden, Herunterfahren, Ping |
| `test/ticket.test.ts`, `test/tickets.ts`, `test/tickets.python.json` | `tools/ticket-oracle` | neu (F5.2): jede Karte des Python-Orakels liest Node wie Python (Nutzlast oder derselbe Grund der Ablehnung); in Node signierte Karten tragen dasselbe JSON zum selben Zeitpunkt (Nodes zlib packt anders, ungepackt byte-gleich); die Ansprüche |
@@ -300,3 +301,12 @@ antwortet: `packages/server/test/tickets.python.json`.
Baut den unveränderten Swift-Kern (Stand `3b5ded0`) unter Linux, nur zwei
Ausdrücke sind für den Linux-Compiler aufgeteilt (`patches/`). Die Quellen
selbst werden beim Bau geholt und nicht eingecheckt.
## deploy
`Dockerfile`, `docker-compose.yml`, `test.env.example`,
`production.env.example`, `proxy.conf`, dazu `.dockerignore` — neu
(F5.6a/b): das Image von F (zwei Stufen, Node 24, ohne `node_modules`, nicht
als root), ein Stack je Umgebung mit eigenem Namen, Volume, Image-Tag und Port
(Test 8081, Produktion 8080) und der Eintrag für den externen OpenResty.