Der Upload zu App Store Connect scheiterte am Namen. „Halo" ist eine
eingetragene Marke von Microsoft; im App Store heisst zwar keine App exakt
so, aber reservierte und markenrechtlich belegte Namen tauchen in keiner
Suche auf. Der einzige verlässliche Test war die Eingabe dort, und die ging
daneben.
**Der Name wurde diesmal vorher geprüft.** Zwanzig Kandidaten gegen den
deutschen und amerikanischen App Store, auf exakte Treffer und auf ähnliche
Namen. „Kavo" wäre dieselbe Wand gewesen — exakt belegt in beiden Stores, in
Deutschland von KaVo Dental GmbH. „Flare" ist mit 42 ähnlichen Apps je Store
der am dichtesten besetzte Name der ganzen Runde. **Flaro** ist in beiden
frei und liest sich als eigenes Wort, nicht als Flare mit Tippfehler.
Das bleibt eine Store-Suche und keine Markenrecherche — reservierte Namen
ohne veröffentlichte App sieht sie nicht. Aber es ist mehr Prüfung, als beim
letzten Mal stattfand.
---
2160 Textvorkommen in 273 Dateien, 49 Pfade. Betroffen ist diesmal auch der
Server: `Flaro.Api`, `Flaro.Core`, `Flaro.Data`, `Flaro.Media`,
`Flaro.Metadata`, `FlaroContext`, `FlaroPaths`, `flaro.db`, die Variablen
`FLARO_DATA`, `FLARO_CACHE`, `FLARO_TRANSCODE`, `FLARO_WRITE_SIDECARS`, und
das Image.
**Vor dem Ersetzen geprüft**, ob „halo" irgendwo als Teil eines anderen
Wortes steckt — und ob es im TMDB-Token vorkommt. Tat es nicht; ein blindes
Ersetzen hätte den sonst zerlegt.
`docs/superpowers/specs/` bleibt wie beim letzten Mal unangetastet: datierte
Entwurfsdokumente sind ein Protokoll getroffener Entscheidungen. Das
Server-Dokument hat stattdessen einen Nachtrag bekommen, damit es niemanden
in die Irre führt.
**Die Bundle-ID wandert mit**, zum zweiten Mal an einem Tag:
`com.scarriffleservices.flaro`. Wer die vorige Fassung installiert hat, hat
jetzt zwei Karteileichen auf dem Gerät — beide löschen, dann ist Ruhe.
308 Server-Tests grün, 368 im Swift-Paket, null Warnungen. iOS und tvOS
bauen, das Image baut, und ein frischer Container läuft durch Einrichtung
und Anmeldung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reine Umbenennung, kein Verhalten geändert — bewusst als eigener Commit,
damit „umbenannt" und „umgebaut" im Nachhinein auseinanderzuhalten sind.
712 mal `Flixy`, 778 mal `flixy`, 7 mal `FLIXY` in 169 Dateien, dazu 25
Pfade. Ziele: `Halo`, `HaloTV`, `HaloTopShelf`, `HaloUITests`, `HaloKit` mit
`HaloDesign`, `HaloDownloads`, `HaloPlayback` und `HaloProbe`. `MediaKit`,
`JellyfinKit` und `DownloadWidget` tragen den Namen nicht und bleiben.
`docs/superpowers/specs/` ist ausgenommen. Datierte Entwurfsdokumente sind
ein Protokoll getroffener Entscheidungen; sie nachträglich umzuschreiben
hiesse, die Vergangenheit zu glätten.
**Die Bundle-ID wandert mit** — ausdrücklich so gewollt, mit bekanntem Preis:
`com.scarriffleservices.halo` ist für iOS eine *andere* App. Die installierte
Fassung bleibt daneben stehen, mit Downloads und Anmeldung in ihrem Container;
Halo startet leer. Einmal neu anmelden, heruntergeladene Folgen einmal neu
laden. Dasselbe gilt für die App-Gruppe, die sich TV-App und Top Shelf teilen.
**Eine Folge davon, die beim Entscheiden noch nicht auf dem Tisch lag:** der
Aufräumschritt aus dem vorigen Commit kommt an die alten Plex-Token nicht mehr
heran. Der Schlüsselbund grenzt nach Team und Bundle-Kennung ab — was unter
`…flixy` liegt, ist für `…halo` unerreichbar. Erledigt wird es trotzdem, nur
anders: **die alte App löschen.** iOS räumt deren Schlüsselbund-Einträge beim
Deinstallieren mit ab. Der Code bleibt stehen, weil er für jeden Stand vor
dieser Umbenennung richtig ist und im Jahr einen Startvergleich kostet.
Die Projektdatei ist aus `project.yml` neu erzeugt, der alte Ordner gelöscht
statt umbenannt — sie steht ohnehin nicht im Repo.
Das Verzeichnis des Repos selbst heißt weiter `Flixy`; das umzubenennen ist
ein Handgriff ausserhalb des Projekts.
368 Tests grün. iOS und tvOS bauen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Schritt 2 des Plans, erste Hälfte. Vite mit TypeScript, und ein Server
ohne eine einzige Abhängigkeit — er soll auf einem kleinen Container
laufen, nicht sein halbes Verzeichnis mitschleppen.
Der Server ist nicht Zierde. Er löst zwei Dinge, gegen die keine Zeile im
Frontend etwas ausrichten kann: Anfragen laufen über dieselbe Adresse wie
die Seite, womit CORS erledigt ist, auch beim Streamen. Und läuft der
Medienserver im Klartext, während die Seite verschlüsselt ausgeliefert
wird, blockiert der Browser sonst den Strom.
Geprüft: Weiterreichen mitsamt Autorisierung und richtig gesetztem Host,
Ausliefern gebauter Dateien, unbekannte Wege landen auf der Seite — und
ein Ausbruchsversuch mit "../../../etc/passwd" liefert die Seite statt
der Passwortdatei.
Der Körper wird durchgereicht statt gepuffert: ein Film ist ein Strom,
und ihn erst vollständig einzulesen hieße, ihn zwischenzuspeichern.
Die einzelne Datei bleibt vorerst, sie läuft ja.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beim Schließen wurde das Video abgeräumt, und dabei fiel currentTime auf
null — bevor die Stopp-Meldung hinausging. Jellyfin bekam "gestoppt bei
0:00" und löschte den Fortschritt. Der Film war zur Hälfte gesehen und
stand trotzdem nicht unter "Weiterschauen".
Jetzt wird die Stelle getrennt vom Element gehalten und die Meldung
gesendet, bevor abgeräumt wird. Nachgemessen: bei 45 Sekunden
geschlossen, 45 Sekunden gemeldet. Dazu PlayMethod und CanSeek, ohne die
Jellyfin die Meldung keiner Art von Wiedergabe zuordnet, und sofortige
Meldung bei Anhalten und Weiterlaufen — wer pausiert und weggeht, hatte
sonst bis zur nächsten Zehn-Sekunden-Marke nichts hinterlassen.
Und das eingefrorene Bild bei laufendem Ton nach einem
Anwendungswechsel: Der Browser hält das Entpacken an, während der Tab
verdeckt ist, und hls.js findet danach nicht von selbst in den Puffer
zurück. Jetzt wird beim Zurückkommen an derselben Stelle neu angestoßen,
mit einem winzigen Sprung — ohne den bleibt das zuletzt gezeigte Bild
stehen, obwohl längst wieder Segmente ankommen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>