20 Commits
Author SHA1 Message Date
marc 3f8b98b869 Eine Biene als Wappen, an allen vier Stellen
Aus dem Quadrat links in beiden Leisten wird eine Pixelbiene von der Seite:
braune Streifen, schwarze Beine, Fluegel mit Kerbe. Sie steht in genau einem
Raster (tools/biene.py, 16x16 Zeichen); daraus entstehen SVG, PNG und eine
Fassung aus Schriftzeichen.

SVG statt PNG in den Leisten: Die HoneyBar laeuft in fremden Apps, und ob ein
<img> dort laedt, entscheidet deren CSP. Markup kann niemand blockieren.

Im System-Fenster und ueber dem Startlauf steht die Biene aus Schriftzeichen —
beides sind Textflaechen, ein Bild darin waere ein Fremdkoerper.

Das Wappen liegt an drei Stellen (Datei, Modul, HoneyBar-Zeile), weil die
Leiste nichts nachladen kann. TestWappenIstUeberallDasselbe haelt sie gleich.
2026-09-02 10:21:03 +02:00
marc 3807ddca24 Notiz zeigt sich sofort gesetzt, Widgets nach Wunsch des Nutzers
Aus dem Zettel wird die Notiz: Der Text steht immer formatiert da, roh ist nur
die Zeile mit der Schreibmarke. Dazu eine kleine Werkzeugleiste (Aufgabe,
Aufzaehlung, Nummer, Ueberschrift, fett, Linie), Enter fuehrt Listen fort,
Backspace am Zeilenanfang nimmt erst den Vorsatz. Fuer groessere Umbauten
bleibt der Quelltext-Knopf.

Kein contenteditable: Der Quelltext bleibt die Wahrheit und wird nie aus dem
HTML zurueckgerechnet, das der Browser beim Tippen erzeugt.

Reihenfolge und An/Aus der Widgets liegen jetzt je Nutzer auf dem Server, in
einer Einstellung ("benutzer,notiz,-system,wetter,bild"). Der Schalter fuer das
Wetter auf dem Schreibtisch faellt damit weg — es ist ein Widget wie jedes
andere.

Die Einstellungen sind in Abschnitte sortiert (Darstellung, HoneyBar, Widgets,
Wetter, Programme, Konto), Beschriftung links, Schalter rechts.
2026-08-31 01:24:50 +02:00
marc c0abfbb491 Zwei Widgets: Zettel mit kleinem Markdown, Bild je Nutzer
Zettel: ein Textfeld, mehr nicht — InkNote gibt es schon. Gelesen wird
gesetzt (Ueberschriften, Haken, Aufzaehlungen, fett/kursiv/code, Strich),
geschrieben wird roh. Haken lassen sich ohne Bearbeiten setzen und
aendern die Quelle. Gespeichert wird 800 ms nach dem letzten Anschlag,
sofort beim Verlassen und beim Schliessen des Tabs (keepalive statt
sendBeacon: der kann nur POST und traegt keine Kopfzeilen). Grenze 4000
Zeichen, vom Server durchgesetzt.

Bild: genau eines je Nutzer, hochgeladen oder verlinkt. Die erste Datei,
die HoneyOS ablegt — in bilder/ neben honeyos.json, benannt nach einem
Fingerabdruck der Nutzerkennung. Ein neues Bild ersetzt das alte samt
Datei, die Adresse traegt einen Versionsanteil gegen den Zwischen-
speicher. SVG kommt nicht herein (Text, kann Skripte tragen), und der
Typ wird an den Bytes erkannt, nicht an der Angabe des Browsers.

Der Rahmen kann jetzt Widgets mit eigenem DOM: 'stabil' haelt den Inhalt,
'montiert' verdrahtet ihn. Ohne das haette das Anklopfen bei den Apps
alle zwei Minuten den Text unter den Fingern ausgetauscht.

Nebenbei: Der Aufrufhelfer setzte bei jedem Schreibzugriff
Content-Type: application/json — auch fuer Bildbytes.
2026-08-31 00:44:20 +02:00
marc b7cc06b7c1 Widget-Rahmen: Widgets sind Beschreibungen, keine Kaesten in der Seite
widgetAnmelden({ id, titel, wo, sichtbar, laden, leer, inhalt, takt }) —
der Rahmen macht daraus ein Fenster in der Spalte (Terminal) oder ein
Schild (Desktop), kennt lädt/fertig/nichts da/Fehler und haelt den
Nachladetakt. Benutzer, Wetter und Systemzustand sind umgestellt; aus
index.html sind vier feste Kaesten verschwunden und aus dem Raster die
Einzelplaetze.

Zwei Dinge, die erst dabei sichtbar wurden:

- Der Server meldete 'kein Ort eingestellt' und 'Dienst nicht
  erreichbar' beide als 204. Ein Ausfall sah damit aus wie ein
  abgeschaltetes Widget. Ausfall ist jetzt 502, mit Test.
- Die Reihenfolge haengt nicht mehr an der Modulauswertung: Seit
  glyphs.js seine Raster mit await auf oberster Ebene laedt, laufen
  Module ohne Symbole vorher durch — der Systemzustand stand deshalb
  ueber dem Benutzer. widgetsOrdnen() macht die Reihenfolge zur Angabe,
  und genau dort haengt spaeter die im Server gespeicherte ein.
2026-08-30 03:12:00 +02:00
marc cc7a50c621 Erst die Sitzung, dann der Schluessel
Der Schluessel kennt keinen Nutzer und landete beim Standardnutzer — auch
dann, wenn die App unter derselben Site liegt und der Browser das
HoneyOS-Cookie laengst mitschickt (cloud.honeyos.… und honeyos.… sind
dieselbe Site, duckdns.org steht auf der Public-Suffix-Liste). Damit trug
die HoneyBar in Aether die Farben eines fremden Nutzers.

Jetzt sieht /api/apps erst nach der Sitzung, und nur bei eigener
Anmeldung: Im offenen Betrieb und hinter einem Anmelde-Proxy gilt jede
Anfrage als angemeldet, dort bleibt der Schluessel das letzte Wort.
Test dazu, mit zwei Nutzern, damit der Rueckfall auf den einzigen Nutzer
das Ergebnis nicht zufaellig richtig aussehen laesst.
2026-08-29 23:29:53 +02:00
marc 6fe6533667 Kein alter Stand mehr im Zwischenspeicher, Einsetzer heisst HoneyBar-Proxy
Die HoneyBar kommt bei fremden Apps ueber deren eigenen Ursprung — das
loest CSP, CORS und COEP auf einmal, setzt sie aber auch deren Zwischen-
speicher aus. Eine alte HoneyBar dort sieht aus wie ein Fehler in HoneyOS.
Statt no-cache jetzt no-store, must-revalidate; dazu ein Abschnitt in der
README, wie man einen haengengebliebenen Stand erkennt.

Und der nginx davor heisst nicht mehr 'Einsetzer', sondern HoneyBar-Proxy
(Dienst und Behaelter honeybar-proxy bzw. <app>-honeybar). Er ist ein
Reverse Proxy, der die HoneyBar einsetzt — der alte Name sagte das
Gegenteil von dem, was man im docker ps sehen will. LEISTE_PORT heisst
jetzt HONEYBAR_PROXY_PORT.
2026-08-29 22:36:56 +02:00
marc 53ab62d220 Symbole in beiden Leisten, aus einer Quelle
Die Pixelraster stehen jetzt in web/glyphs.json — einmal. Der Schreibtisch
laedt die Datei selbst, die HoneyBar bekommt sie mit der App-Liste mit;
sie bleibt damit eine einzelne Datei ohne zweite Anfrage. Die abgetippten
Wettersymbole in honeybar.js sind weg, und die Symbolauswahl im
Programm-Editor kommt jetzt aus derselben Datei statt aus einer Liste im
Quelltext.

Neu: Symbole neben den App-Namen im Streifen beider Leisten, mit einem
Schalter (Einstellungen -> HoneyBar) fuer beide zugleich. In den
Aufklappmenues und auf den Kacheln stehen sie immer.
2026-08-29 22:21:53 +02:00
marc 6d75ce78c2 Abmelden nur noch in den Einstellungen, App-Menue statt Zahnrad
Marcs Entscheidung: In der HoneyBar fremder Apps steht kein Abmelden mehr
— es war dort ohnehin nur ein Link auf den Schreibtisch. Als einzige
Schaltflaeche, die eine Sitzung beendet, steht es jetzt an genau einer
Stelle: unten in den Einstellungen, sichtbar nur bei eigener Anmeldung.
Damit faellt auch der ?abmelden=1-Pfad wieder weg und /api/apps braucht
das oidc-Feld nicht mehr.

Das Zahnrad rechts in der Menueleiste ist durch den Pfeil mit der
App-Liste ersetzt — derselbe wie in der HoneyBar. Beide Leisten tragen
damit dieselben vier Dinge: Logo, Apps, Wetter/Uhr, Aufklappmenue.
2026-08-29 21:51:00 +02:00
marc 0a5cd94ba0 Systemmenue im Logo, in beiden Leisten
Das ■ HONEYOS ist jetzt ein Menue statt eines Links: Schreibtisch,
Einstellungen, HoneyBar einklappen, Abmelden. In fremden Apps sind es
Links auf den Schreibtisch (?einstellungen=1 / ?abmelden=1), weil die
HoneyBar dort nicht schreiben darf — Sitzung und CSRF-Pruefwort ueber-
leben die Site-Grenze nicht, und ein Abmelden per Aufruf koennte jede
Seite ausloesen.

Der Abmeldeknopf in der Menueleiste faellt weg (stand doppelt), und
Abmelden erscheint nur, wenn HoneyOS ueberhaupt anmeldet — dafuer gibt
/api/apps jetzt oidc mit heraus. Nebenbei: restliche 'Leiste' im Text
zu 'HoneyBar' vereinheitlicht.
2026-08-29 21:23:11 +02:00
marcandClaude Opus 5 52deffa30e refactor: aufgeraeumt — Pakete hinten, Widgets vorne
Go: store, auth, weather und config sind eigene Pakete unter internal/. Vorher
lagen fuenf Dateien in einem Topf, und jede kannte jede.

Web: os.js hatte 1425 Zeilen und alles darin. Jetzt core.js (Zustand, Server,
Einstellungen), glyphs.js (die Pixelraster), js/widgets/ mit einem Widget je
Datei, os.js nur noch die Ansichten. Stylesheet nach css/.

Die HoneyBar bleibt eine einzelne Datei ohne Importe — sie wird von fremden
Seiten mit einer Zeile eingebunden, da darf nichts nachladen.

Nebenbei: Das gebaute Binary lag mit 9,8 MB im Repo und ist jetzt ignoriert.
Und der Test gegen eine zweite Versionsnummer geht nicht mehr auf os.js, sondern
durch alle .js — sonst haette ihn dieser Umbau still ausgehebelt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 20:51:21 +02:00
marcandClaude Opus 5 fc4dd12c5e feat!: Token-Schluessel und Wer-bin-ich entfernt, Version 1.0
Beides brachte allein einen Anzeigenamen. Seit der Benutzer als Widget auf dem
Schreibtisch steht, kommt der aus der HoneyOS-Anmeldung — keine App muss mehr
etwas dafuer bereitstellen, und beide Leisten tragen ueberall dasselbe.

Der Token-Schluessel hatte zudem eine scharfe Kante: Zeigte das Feld
Wer-bin-ich auf eine fremde Adresse, ging der Ausweis der App dorthin.

Weg sind damit auch checkAuth, askMe und die Anmeldezeile auf den Kacheln. Alte
honeyos.json-Dateien werden weiter gelesen; die Felder verfallen beim naechsten
Speichern still.

1.0, weil die Bedienung sich aendert und der Stand rund ist: zwei Leisten mit
gleichem Inhalt, Widgets fuer Benutzer und Wetter, die HoneyBar auch in fremden
Apps.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 20:17:18 +02:00
marcandClaude Opus 5 5dbadf212f fix(leiste): mit Cross-Origin-Resource-Policy ausliefern
Apps, die COEP „require-corp" setzen — alles mit WASM oder SharedArrayBuffer,
etwa BentoPDF — lehnen jede fremde Datei ab, die sich nicht ausdruecklich zur
Einbettung bekennt. Genau das ist der Zweck der Leiste, also sagt sie es jetzt.

Die Alternative waere gewesen, im Proxy das COEP der App zu entfernen. Das
haette ihr die Faehigkeiten genommen, fuer die sie es setzt.

Gefunden beim Einsetzen in BentoPDF hinter einem nginx.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 19:35:21 +02:00
marcandClaude Opus 5 99f1ed4a58 fix(wetter): der Schalter „in der Leiste" wirkt auch auf dem Schreibtisch
Die Leiste am oberen Rand von HoneyOS ist nicht honeybar.js, sondern die
Menueleiste des Schreibtischs — anderer Code, gleiches Aussehen. Das Wetter
stand deshalb nur in fremden Apps, waehrend der Schalter dort, wo man ihn
umlegt, nichts zu bewirken schien.

Fuer den, der davorsitzt, ist beides dieselbe Leiste. Ein Schalter, der nur
woanders wirkt, ist nicht zu erklaeren.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:31:40 +02:00
marcandClaude Opus 5 4e38ccdec1 feat(wetter): Wetter auf dem Schreibtisch und in der Leiste
Zwei Schalter, unabhaengig voneinander: Schreibtisch, Leiste, beides oder
keins. Die Stadt wird einmal gesucht und mit ihren Koordinaten gespeichert,
sonst suchte jede Abfrage den Ort erneut.

Geholt wird serverseitig und zehn Minuten zwischengespeichert. Der Grund ist
nicht Sparsamkeit: Die Leiste steht auf jeder Seite jeder App, und fragte sie
selbst an, ginge bei jedem Seitenaufruf eine Anfrage samt IP an einen Fremden —
und die CSP jeder App muesste ihn erlauben.

Kein Ort eingestellt oder Dienst nicht erreichbar: 204, und das Symbol bleibt
weg. Eine Zahl von gestern waere schlechter als keine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:12:09 +02:00
marcandClaude Opus 5 7db45f67f0 fix(leiste): die Aussparung des Geraets gehoert der Leiste
Aether und InkNote setzen viewport-fit=cover — als installierte App reicht ihr
Inhalt bis unter die Statusleiste. Eine Leiste, die stur bei 0 anfaengt, liegt
dort unter Uhrzeit und Akkustand. Sie waechst jetzt um env(safe-area-inset-top)
und polstert sich selbst; im Browser ist der Wert null und alles bleibt bei
32 px.

Das Polster der Seite wird dabei nicht mehr ausgerechnet, sondern gerechnet:
env() kennt nur der Browser, und erst beim Anzeigen. Nebenbei behebt das einen
Rundungsfehler beim Ausblenden — der urspruengliche Wert wird jetzt gemerkt
statt zurueckgerechnet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 10:21:25 +02:00
marcandClaude Opus 5 b4dcb74404 fix: das Aussehen erreicht die Leiste auch über die Site-Grenze
Marcs Frage: gilt die Einstellung vom Rechner auch für die Leiste am Handy?

Sie hätte es nicht getan, sobald HONEYOS_USER_HEADER gesetzt ist: die
Einstellungen liegen dann unter "proxy:marc", die Leiste fragt aber ohne
Sitzung und landet beim Standardnutzer — dessen Satz ist leer, die Leiste
wäre bernsteinfarben geblieben, während der Schreibtisch grün leuchtet.

SettingsFor() hilft nach: gibt es genau einen Nutzer mit Einstellungen,
gelten dessen. Bei mehreren bleibt es beim Standard, dann ist nicht zu
erraten, wer da schaut.

Nachgestellt mit einem Pixel-7-Profil ohne jedes Cookie: die Leiste kommt
grün an.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 22:47:19 +02:00
marcandClaude Opus 5 5cf210ae97 fix: Version stand an zwei Stellen und lief auseinander
Die Oberfläche zeigte 0.2, während die Images schon 0.4 hiessen: os.js trug
eine eigene Konstante, die ich beim Taggen nie mitgezogen habe.

Jetzt steht sie nur noch in main.go. build.sh liest sie von dort und vergibt
denselben Tag, die Oberfläche holt sie über /api/public und /api/me. Ein Test
schlaegt an, falls je wieder eine zweite Version in os.js auftaucht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 22:45:36 +02:00
marcandClaude Opus 5 5ed4e30179 feat: Leiste trägt die Röhre vom Server, Einklappen ist umkehrbar
Zwei Sachen, die beim Benutzen aufgefallen sind.

- "leiste ausblenden" war eine Einbahnstraße: die Leiste verschwand ganz und
  liess sich nur über die Entwicklerkonsole zurückholen. Jetzt bleibt ein
  3px-Strich stehen, ein Klick darauf holt sie wieder. ?honeybar=1 an der
  Adresse ist der Notausgang, falls der Strich übersehen wird.
- Die Leiste hatte ihre Farben fest eingetragen und blieb bernsteinfarben,
  auch wenn der Schreibtisch auf grün stand. Genau dieser Bruch liess sie wie
  etwas Angeklebtes wirken. /api/apps liefert deshalb jetzt {apps, settings};
  die Leiste setzt Röhre, Glühen und Scanlines danach.

Dass das auch über Site-Grenzen geht, war so nicht erwartet: der Schlüssel
für die App-Liste trägt das Aussehen einfach mit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 22:37:06 +02:00
marcandClaude Opus 5 1c3218939b feat: Betrieb hinter einem Anmelde-Proxy, Schlüssel für die App-Liste
Marc stellt Pangolin davor und will keinen zweiten Anmeldeschirm.

- HONEYOS_PROXY_AUTH=true: HoneyOS prüft nicht mehr selbst, der Start sagt
  deutlich, dass der Container dann nur über den Proxy erreichbar sein darf.
  Mit HONEYOS_USER_HEADER bekommt jeder Name seine eigenen Einstellungen.
- HONEYOS_APPS_KEY schützt /api/apps. Nötig, weil HoneyOS auf einer anderen
  Site liegt als die Apps (duckdns.org steht auf der Public-Suffix-Liste) –
  der Browser schickt die Sitzung dort nicht mit, und der Pfad muss im Proxy
  von der Anmeldung befreit sein.

Beim Durchspielen mit zwei echten Hostnamen fiel ein Loch auf: Ohne eigene
Anmeldung gilt jede Anfrage als angemeldet, also gab der Rückfall auf diese
Prüfung die Liste an jeden heraus – auch ohne oder mit falschem Schlüssel.
Der Rückfall greift jetzt nur noch, wo es wirklich eine Sitzung geben kann.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 22:09:37 +02:00
marcandClaude Opus 5 283f9a1850 feat: Backend mit OIDC-Anmeldung, Apps und Einstellungen im Server
Aus der statischen Seite wird ein Go-Binary mit eingebetteter Oberfläche.
Grund: Apps über .env zu pflegen wurde unübersichtlich, und kosmetische
Einstellungen sollen auf jedem Gerät gleich sein.

- Anmeldung über den eigenen OIDC-Anbieter (PocketID), mit PKCE. Ohne
  Anmeldung gibt es nichts zu sehen – auch keine App-Liste.
- Sitzung als signiertes Cookie ohne Gegenstück im Server; Schreibzugriffe
  zusätzlich über ein lesbares CSRF-Cookie abgesichert
- Apps werden in der Oberfläche angelegt und bearbeitet, nicht mehr in der
  .env. Der Server prüft jeden Eintrag und meldet zurück, was er behält.
- Einstellungen liegen je Nutzer im Server; localStorage ist nur noch der
  Vorschuss, damit die Röhre beim Laden nicht in der falschen Farbe blitzt
- die Leiste holt die App-Liste aus /api/apps – freigegeben sind allein die
  Ursprünge, die selbst als App eingetragen sind
- Tests fahren einen echten OIDC-Anbieter hoch und gehen den Anmeldeweg
  einmal ganz durch

Ohne HONEYOS_OIDC_ISSUER läuft alles offen – für die Entwicklung, mit
deutlicher Warnung beim Start.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:20:55 +02:00