Files
dogfather-universe/tools/workspace-stempel.mjs
T
DogFatherGitandClaude Opus 5 3cda64568d Die Modi-App bekommt ihre eigene Adresse: crew.dogfather-universe.com
Filipe: "ich will dass es eine eigene app wird" -- und dann "subdomain
machen jetzt sofort". Name von ihm gewaehlt: crew. (unauffaellig).

Auf einem Ursprung laesst sich genau EINE App installieren (w3c/manifest
Nr. 1180). Derselbe Grund, aus dem der Workspace am 06.09. umgezogen ist.
Getrennt wird ueber den HOSTNAMEN: ein Dienst, eine Datenbank, ein
Verzeichnis wie bisher.

DIE REGEL STEHT AN EINER STELLE
crew-adresse.js beantwortet: Darf diese Rolle auf dieser Adresse
angemeldet sein? Eingehaengt in sitzungLesen() -- durch die Funktion geht
jedes der 26 Fachmodule und jede Seitenschranke. Eine Middleware daneben
kann man in einem neuen Modul vergessen, und ein vergessener Rechteschutz
faellt nicht auf, weil dann alles geht.

  crew.      nur Modis; jeder andere bekommt 401 wie bei einem Tippfehler
  workspace. keine Modis mehr; sie bekommen den Weg zur neuen Adresse
  localhost  UNVERAENDERT

Die dritte Zeile ist der Kern: Die Regel ist eine AUFZAEHLUNG der drei
echten Adressen, nicht "alles ausser crew". Sonst wuerden sieben andere
Pruefdateien ab sofort messen, dass ein Modi nirgends hereinkommt -- gruen,
weil sie nichts mehr finden.

ZWEI APPS, ZWEI NAMEN
Beide Adressen liefern dieselben HTML-Dateien. Auf crew. wird
/workspace/app.webmanifest serverseitig auf crew.webmanifest umgebogen --
so braucht keine der 30 Seiten eine zweite Zeile, die man bei der 31.
vergisst. "Team Dogi" statt "Creator Workspace", eigenes Zeichen:
derselbe Husky, aber ohne Chili (die gehoert zu Spicy Media, nicht zu
ihnen) und im Modi-Ton #5f8a9f.

tools/crew-symbol.mjs erzeugt die sechs Symbole und bricht ab, wenn sie
sich zu weniger als 10 % vom Workspace-Symbol unterscheiden. Gemessen:
43 bis 53 %.

GEMESSEN
pruef-crew-adresse    74 Pruefungen, 0 Fehler -- mit Gegenprobe: der Modi
                      bekommt in der Datenbank die Rolle 'manager', danach
                      MUSS dieselbe Sitzung auf crew. ins Leere laufen
pruef-rollen          245, unveraendert (die Regel ist lokal wirkungslos)
pruef-workspace-umzug 31 Faelle
pruef-zwischenspeicher 21 -- ein Stempel im Haus, jetzt ueber 23 Dateien

Der Server kennt die Adresse damit. DNS und Caddy bleiben Filipes Schritt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 13:07:12 +02:00

127 lines
5.3 KiB
JavaScript

/* =====================================================================
workspace-stempel.mjs — Versionsstempel an die Workspace-Dateien.
WARUM ES DAS GIBT:
Cloudflare speichert JS und CSS vier Stunden im Browser -- es
ueberschreibt damit das "no-cache", das der Server korrekt schickt.
Nach einem Deploy sah man deshalb bis zu vier Stunden lang die ALTE
Oberflaeche, obwohl der Server laengst die neue auslieferte. Genau so
ist es passiert: eine neue Kachel war live, aber nicht sichtbar.
Die HTML-Seiten kommen dagegen immer frisch an (no-cache, DYNAMIC).
Deshalb genuegt es, in der HTML einen Stempel an die Adressen zu
haengen: Neue Seite -> neue Adresse -> Cloudflare kennt sie nicht ->
frische Datei. Ohne Cloudflare-Einstellung, ohne Zutun von aussen.
Der Stempel ist die Minute des Aufrufs. Er wird bei jedem Lauf neu
gesetzt, auch wenn schon einer dasteht.
AUFRUF: node tools/workspace-stempel.mjs
Gehoert vor jeden Deploy, der JS oder CSS im Workspace anfasst.
===================================================================== */
import { readdirSync, readFileSync, writeFileSync, existsSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const HIER = dirname(fileURLToPath(import.meta.url));
const ORDNER = join(HIER, "..", "workspace");
const d = new Date();
const p = (n) => String(n).padStart(2, "0");
const STEMPEL = `${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}${p(d.getHours())}${p(d.getMinutes())}`;
/* Trifft href="assets/..." und src="assets/..." -- mit oder ohne
vorhandenen Stempel, damit wiederholte Laeufe nicht anhaengen. */
const MUSTER = /(href|src)="(assets\/(?:css|js)\/[A-Za-z0-9._-]+)(?:\?v=\d+)?"/g;
/* ZWEITES MUSTER: DIE APP-SYMBOLE (09.09.2026).
Sie stehen mit absolutem Pfad in der Seite (`/assets/img/app-symbole/…`)
und fielen deshalb durch das Muster oben durch. Der Server gibt Bildern
einen Tag Haltbarkeit -- ein neu gezeichnetes Symbol war damit bis zu
24 Stunden lang unsichtbar, obwohl es ausgeliefert wurde. Genau die
Luecke, die der Stempel eigentlich schliessen soll, nur fuer Bilder
statt fuer Stilvorlagen.
Die Reiter-Kennung und das Apple-Symbol bekommen deshalb denselben
Stempel wie alles andere. Dass es DERSELBE ist, ist wichtig: Die
Pruefung `pruef-zwischenspeicher` verlangt genau einen Stempel im
ganzen Haus, und eine zweite Zahl waere sofort rot. */
const MUSTER_SYMBOL =
/(href)="(\/assets\/img\/app-symbole\/[A-Za-z0-9._-]+)(?:\?v=\d+)?"/g;
let dateien = 0;
let stellen = 0;
for (const name of readdirSync(ORDNER)) {
if (!name.endsWith(".html")) continue;
const pfad = join(ORDNER, name);
const alt = readFileSync(pfad, "utf8");
let n = 0;
const neu = alt
.replace(MUSTER, (_, was, datei) => {
n += 1;
return `${was}="${datei}?v=${STEMPEL}"`;
})
.replace(MUSTER_SYMBOL, (_, was, datei) => {
n += 1;
return `${was}="${datei}?v=${STEMPEL}"`;
});
if (neu !== alt) {
writeFileSync(pfad, neu);
dateien += 1;
stellen += n;
console.log(` ${name.padEnd(20)} ${n} Verweise`);
}
}
/* DAS MANIFEST GEHOERT DAZU (09.09.2026).
Aus ihm holt sich das Betriebssystem das Symbol der installierten App.
Ohne Stempel zeigen Android und Windows nach einer Neuzeichnung
weiter das alte Bild -- die Adresse hat sich ja nicht geaendert, und
ein einmal installiertes Symbol wird nicht von sich aus nachgeladen.
Das Manifest selbst wird ohne Haltbarkeit ausgeliefert, kommt also
frisch an; nur die Adressen darin waren starr.
Derselbe Stempel wie in den Seiten -- `pruef-zwischenspeicher`
verlangt im ganzen Haus genau eine Zahl und wuerde eine zweite sofort
melden. */
/* ES SIND ZWEI MANIFESTE (10.09.2026). Seit die Modi-App unter ihrer
eigenen Adresse laeuft, gibt es neben app.webmanifest auch
crew.webmanifest -- dasselbe Haus, anderer Name, andere Symbole.
ALS LISTE UND NICHT ALS ZWEITER BLOCK: Ein kopierter Block waere beim
dritten Manifest ein dritter, und irgendwann bleibt einer stehen. Ein
fehlendes Manifest ist hier ausserdem ein FEHLER und kein
Ueberspringen -- sonst faellt das Ausbleiben nicht auf. */
const MANIFESTE = ["app.webmanifest", "crew.webmanifest"];
const MUSTER_MANIFEST =
/("src":\s*")(\/assets\/img\/app-symbole\/[A-Za-z0-9._-]+)(?:\?v=\d+)?(")/g;
for (const name of MANIFESTE) {
const pfad = join(ORDNER, name);
if (!existsSync(pfad)) {
console.error(`FEHLER: ${name} fehlt -- erwartet in ${ORDNER}.`);
process.exit(1);
}
const alt = readFileSync(pfad, "utf8");
let n = 0;
const neu = alt.replace(MUSTER_MANIFEST, (_, vor, datei, nach) => {
n += 1;
return `${vor}${datei}?v=${STEMPEL}${nach}`;
});
/* Findet das Muster nichts, ist das ein FEHLER und kein Achselzucken:
Dann hat jemand das Manifest umgebaut, und ab da laeuft das Symbol
still auf dem alten Stand weiter. */
if (n === 0) {
console.error(`FEHLER: in ${name} keine Symboladresse gefunden -- Muster pruefen.`);
process.exit(1);
}
if (neu !== alt) { writeFileSync(pfad, neu); dateien += 1; stellen += n; }
console.log(` ${name.padEnd(20)} ${n} Verweise`);
}
console.log(`\nStempel ${STEMPEL} auf ${stellen} Verweise in ${dateien} Dateien gesetzt.`);
if (!dateien) console.log("Nichts geaendert -- stimmt das Muster noch?");