Compare commits
1
Commits
1ec7aedf04
...
3cafc92d49
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cafc92d49 |
@@ -24,6 +24,8 @@ Integrations-Backend.
|
|||||||
Eintrag begründen, alte Einträge nie löschen. Besonders D13 (Backend-Stack)
|
Eintrag begründen, alte Einträge nie löschen. Besonders D13 (Backend-Stack)
|
||||||
und D14 (Parser-Hoheit) beachten.
|
und D14 (Parser-Hoheit) beachten.
|
||||||
- Ziele: docs/ROADMAP.md · Offene Arbeit: docs/TASKS.md (Checkboxen pflegen).
|
- Ziele: docs/ROADMAP.md · Offene Arbeit: docs/TASKS.md (Checkboxen pflegen).
|
||||||
|
- Pull Requests: jeder PR bekommt ein Dokument unter `docs/prs/` — Konvention
|
||||||
|
in docs/prs/README.md.
|
||||||
- Änderungen: @docs/CHANGELOG.md — **jedes Feature und jeder behobene Fehler
|
- Änderungen: @docs/CHANGELOG.md — **jedes Feature und jeder behobene Fehler
|
||||||
bekommt dort eine Zeile**, englisch, ein Satz, unter der Überschrift des
|
bekommt dort eine Zeile**, englisch, ein Satz, unter der Überschrift des
|
||||||
Tages (`## JJJJ-MM-TT`). Die Datei speist das Neuigkeiten-Popup im Editor
|
Tages (`## JJJJ-MM-TT`). Die Datei speist das Neuigkeiten-Popup im Editor
|
||||||
|
|||||||
+15
-15
@@ -57,7 +57,7 @@ einer externen Textdatei beziehen — praktisch zum Teilen eines Plans oder wenn
|
|||||||
die Quelle in Git oder einem Wiki gepflegt wird:
|
die Quelle in Git oder einem Wiki gepflegt wird:
|
||||||
|
|
||||||
```
|
```
|
||||||
https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-0.werkbaum
|
https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-0.werkbaum
|
||||||
```
|
```
|
||||||
|
|
||||||
Fertige Beispiele in [`docs/examples/`](docs/examples/) — **nacheinander
|
Fertige Beispiele in [`docs/examples/`](docs/examples/) — **nacheinander
|
||||||
@@ -66,11 +66,11 @@ Editor-Titelzeile zwischen allen umschalten:
|
|||||||
|
|
||||||
| Beispiel | Zeigt |
|
| Beispiel | Zeigt |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **▶ [0 · Online-Shop-Relaunch](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-0.werkbaum)** | ein Softwareprojekt mit allen acht Status |
|
| **▶ [0 · Online-Shop-Relaunch](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-0.werkbaum)** | ein Softwareprojekt mit allen acht Status |
|
||||||
| **▶ [1 · Neue Küche](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-1.werkbaum)** | ein Plan ohne Software, viele Alternativen — gut für den Günstigster-Pfad-Schalter |
|
| **▶ [1 · Neue Küche](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-1.werkbaum)** | ein Plan ohne Software, viele Alternativen — gut für den Günstigster-Pfad-Schalter |
|
||||||
| **▶ [2 · Community-Konferenz](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-2.werkbaum)** | ein breiter Plan mit vielen Beteiligten; horizontal vs. kompakt vergleichen |
|
| **▶ [2 · Community-Konferenz](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-2.werkbaum)** | ein breiter Plan mit vielen Beteiligten; horizontal vs. kompakt vergleichen |
|
||||||
| **▶ [3 · Drei Arbeitsstränge](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-3.werkbaum)** | mehrere Wurzeln = mehrere Bäume nebeneinander |
|
| **▶ [3 · Drei Arbeitsstränge](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-3.werkbaum)** | mehrere Wurzeln = mehrere Bäume nebeneinander |
|
||||||
| **▶ [Werkbaum selbst](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-werkbaum.werkbaum)** | Bestand und mögliche Weiterentwicklung |
|
| **▶ [Werkbaum selbst](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/werkbaum.werkbaum)** | Bestand und mögliche Weiterentwicklung |
|
||||||
|
|
||||||
Der geladene Text wird als **eigenes Dokument** geführt, dessen **Name die URL**
|
Der geladene Text wird als **eigenes Dokument** geführt, dessen **Name die URL**
|
||||||
ist — eigene Dokumente bleiben unberührt, und derselbe Link aktualisiert dieses
|
ist — eigene Dokumente bleiben unberührt, und derselbe Link aktualisiert dieses
|
||||||
@@ -83,10 +83,10 @@ Notationsdateien tragen die Endung **`.werkbaum`** (UTF-8; siehe `docs/SPEC.md`
|
|||||||
erreichbare Textdatei, unabhängig von Endung und Content-Type.
|
erreichbare Textdatei, unabhängig von Endung und Content-Type.
|
||||||
|
|
||||||
**Einschränkung — CORS:** Der Browser lädt fremde Hosts nur, wenn sie
|
**Einschränkung — CORS:** Der Browser lädt fremde Hosts nur, wenn sie
|
||||||
`Access-Control-Allow-Origin` senden. `raw.githubusercontent.com` und
|
`Access-Control-Allow-Origin` senden. `raw.githubusercontent.com`,
|
||||||
GitLab-Raw-Links tun das; ein beliebiger Webserver oft nicht. Scheitert das
|
GitLab-Raw-Links und `git.javagil.de` tun das (D96); ein beliebiger Webserver
|
||||||
Laden, bleibt der bisherige Stand stehen und eine Warnung nennt die Ursache.
|
oft nicht. Scheitert das Laden, bleibt der bisherige Stand stehen und eine
|
||||||
Zugelassen sind nur `http`/`https`.
|
Warnung nennt die Ursache. Zugelassen sind nur `http`/`https`.
|
||||||
|
|
||||||
### Zusammen an einem Plan arbeiten (`?live=`)
|
### Zusammen an einem Plan arbeiten (`?live=`)
|
||||||
|
|
||||||
@@ -152,11 +152,11 @@ git clone mih09-git@git.javagil.de:mi/werkbaum.git # oder https://git.javag
|
|||||||
```
|
```
|
||||||
|
|
||||||
**GitHub bleibt ein Klon.** `main` wird dorthin von Hand gespiegelt
|
**GitHub bleibt ein Klon.** `main` wird dorthin von Hand gespiegelt
|
||||||
(`scripts/push-github.sh`), denn zwei Dinge hängen daran: die
|
(`scripts/push-github.sh`), denn die GitHub-Pages-Instanz hängt daran — der
|
||||||
GitHub-Pages-Instanz (der 🚧 *latest build* ganz oben) und die Beispiel-Links
|
🚧 *latest build* ganz oben. Die Beispiel-Links waren ein zweiter Grund und sind
|
||||||
weiter oben, die ihre Pläne per `?sourceUrl=` von `raw.githubusercontent.com`
|
es nicht mehr: `git.javagil.de` liefert `raw`-Dateien inzwischen mit
|
||||||
laden. Gitea liefert `raw`-Dateien **ohne** `Access-Control-Allow-Origin` aus —
|
`Access-Control-Allow-Origin`, sie zeigen deshalb auf Gitea
|
||||||
dort blockte der Browser sie (`docs/DECISIONS.md` D23, D95).
|
(`docs/DECISIONS.md` D96, revidiert D95).
|
||||||
|
|
||||||
### Lokal ausführen
|
### Lokal ausführen
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ The editor can pull its notation text from an external text file via the
|
|||||||
Git or a wiki:
|
Git or a wiki:
|
||||||
|
|
||||||
```
|
```
|
||||||
https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-0.werkbaum
|
https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-0.werkbaum
|
||||||
```
|
```
|
||||||
|
|
||||||
Ready-made examples in [`docs/examples/`](docs/examples/) — **open them one
|
Ready-made examples in [`docs/examples/`](docs/examples/) — **open them one
|
||||||
@@ -63,11 +63,11 @@ between all of them in the editor title bar:
|
|||||||
|
|
||||||
| Example | Shows |
|
| Example | Shows |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **▶ [0 · Online shop relaunch](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-0.werkbaum)** | a software project with all eight states |
|
| **▶ [0 · Online shop relaunch](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-0.werkbaum)** | a software project with all eight states |
|
||||||
| **▶ [1 · New kitchen](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-1.werkbaum)** | a non-software plan, lots of alternatives — good for the cheapest-path toggle |
|
| **▶ [1 · New kitchen](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-1.werkbaum)** | a non-software plan, lots of alternatives — good for the cheapest-path toggle |
|
||||||
| **▶ [2 · Community conference](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-2.werkbaum)** | a wide plan with many people; compare horizontal vs. compact |
|
| **▶ [2 · Community conference](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-2.werkbaum)** | a wide plan with many people; compare horizontal vs. compact |
|
||||||
| **▶ [3 · Three workstreams](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-3.werkbaum)** | several roots = several trees side by side |
|
| **▶ [3 · Three workstreams](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/example-plan-3.werkbaum)** | several roots = several trees side by side |
|
||||||
| **▶ [Werkbaum itself](https://werkbaum.javagil.de/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-werkbaum.werkbaum)** | what exists today and where it could go |
|
| **▶ [Werkbaum itself](https://werkbaum.javagil.de/?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/docs/examples/werkbaum.werkbaum)** | what exists today and where it could go |
|
||||||
|
|
||||||
The loaded text becomes its own document whose **name is the URL**, so your own
|
The loaded text becomes its own document whose **name is the URL**, so your own
|
||||||
documents stay untouched; the same link updates that one document instead of
|
documents stay untouched; the same link updates that one document instead of
|
||||||
@@ -79,9 +79,10 @@ and D24) — a convention, not a contract: `sourceUrl` reads any text file over
|
|||||||
http(s) regardless of extension or content type.
|
http(s) regardless of extension or content type.
|
||||||
|
|
||||||
**Caveat — CORS:** the browser only fetches a foreign host if it sends
|
**Caveat — CORS:** the browser only fetches a foreign host if it sends
|
||||||
`Access-Control-Allow-Origin`. `raw.githubusercontent.com` and GitLab raw links
|
`Access-Control-Allow-Origin`. `raw.githubusercontent.com`, GitLab raw links and
|
||||||
do; an arbitrary web server often does not. If loading fails the previous
|
`git.javagil.de` do (D96); an arbitrary web server often does not. If loading
|
||||||
content stays and a warning explains why. Only `http`/`https` are allowed.
|
fails the previous content stays and a warning explains why. Only `http`/`https`
|
||||||
|
are allowed.
|
||||||
|
|
||||||
### Working on one plan together (`?live=`)
|
### Working on one plan together (`?live=`)
|
||||||
|
|
||||||
@@ -146,11 +147,11 @@ git clone mih09-git@git.javagil.de:mi/werkbaum.git # or https://git.javagil
|
|||||||
```
|
```
|
||||||
|
|
||||||
**GitHub stays a clone.** `main` is mirrored there by hand
|
**GitHub stays a clone.** `main` is mirrored there by hand
|
||||||
(`scripts/push-github.sh`), because two things hang off it: the GitHub Pages
|
(`scripts/push-github.sh`), because the GitHub Pages instance hangs off it — the
|
||||||
instance (the 🚧 *latest build* linked at the top) and the example links above,
|
🚧 *latest build* linked at the top. The example links above used to be a second
|
||||||
which load plan files from `raw.githubusercontent.com` via `?sourceUrl=`. Gitea
|
reason and are not any more: `git.javagil.de` now serves raw files with an
|
||||||
serves raw files **without** an `Access-Control-Allow-Origin` header, so the
|
`Access-Control-Allow-Origin` header, so they point at Gitea
|
||||||
browser would block them there (`docs/DECISIONS.md` D23, D95).
|
(`docs/DECISIONS.md` D96, revising D95).
|
||||||
|
|
||||||
### Running it locally
|
### Running it locally
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ reverse.
|
|||||||
|
|
||||||
- The project moved to its own Gitea at git.javagil.de — the footer's repository and version links point there now, and GitHub stays a clone carrying the very same commits
|
- The project moved to its own Gitea at git.javagil.de — the footer's repository and version links point there now, and GitHub stays a clone carrying the very same commits
|
||||||
- Every push is built by Werkator, the project's own CI, alongside the GitHub Pages build: backend and frontend as two named builds
|
- Every push is built by Werkator, the project's own CI, alongside the GitHub Pages build: backend and frontend as two named builds
|
||||||
|
- The example plan links now load from git.javagil.de instead of the GitHub clone, and the "Werkbaum itself" link works again — it pointed at a file name that does not exist
|
||||||
|
|
||||||
## 2026-09-02
|
## 2026-09-02
|
||||||
|
|
||||||
|
|||||||
+61
-2
@@ -635,8 +635,8 @@ mögliche Erweiterung.)
|
|||||||
|
|
||||||
**CORS ist die eigentliche Einschränkung.** Der Browser lädt fremde Hosts nur,
|
**CORS ist die eigentliche Einschränkung.** Der Browser lädt fremde Hosts nur,
|
||||||
wenn die Zielseite `Access-Control-Allow-Origin` sendet. Das tun u. a.
|
wenn die Zielseite `Access-Control-Allow-Origin` sendet. Das tun u. a.
|
||||||
`raw.githubusercontent.com` und GitLab-Raw-Links; ein beliebiger Webserver
|
`raw.githubusercontent.com`, GitLab-Raw-Links und — seit D96 — das eigene
|
||||||
oft **nicht**. Scheitert das Laden (CORS, 404, Netz), bleibt der bisherige Stand
|
`git.javagil.de`; ein beliebiger Webserver oft **nicht**. Scheitert das Laden (CORS, 404, Netz), bleibt der bisherige Stand
|
||||||
stehen und es erscheint eine **Warnung** im Warnbereich (Typ `sourceLoad`,
|
stehen und es erscheint eine **Warnung** im Warnbereich (Typ `sourceLoad`,
|
||||||
zeilenlos ⇒ zuoberst), die CORS ausdrücklich als wahrscheinliche Ursache nennt.
|
zeilenlos ⇒ zuoberst), die CORS ausdrücklich als wahrscheinliche Ursache nennt.
|
||||||
Bewusst kein Proxy-Dienst als Ausweg: das würde fremde Inhalte über einen
|
Bewusst kein Proxy-Dienst als Ausweg: das würde fremde Inhalte über einen
|
||||||
@@ -9144,3 +9144,62 @@ beobachtete Klon `~/werkbaum` auf mih09 bekommt Gitea als `origin` — sonst
|
|||||||
sähe der Watcher neue Commits erst nach dem Spiegeln. **Status-Checks werden
|
sähe der Watcher neue Commits erst nach dem Spiegeln. **Status-Checks werden
|
||||||
weiterhin nicht gepostet**, solange auf der Instanz kein Gitea-Token liegt;
|
weiterhin nicht gepostet**, solange auf der Instanz kein Gitea-Token liegt;
|
||||||
die Sektion ist bis dahin eine Beschriftung.
|
die Sektion ist bis dahin eine Beschriftung.
|
||||||
|
|
||||||
|
**Nachtrag zu D95 — der CORS-Zwang ist weg (2026-09-03).** Von den zwei
|
||||||
|
gemessenen Gründen für den Klon hält nur noch einer: `git.javagil.de` liefert
|
||||||
|
`raw`-Dateien inzwischen mit `Access-Control-Allow-Origin` (D96), die
|
||||||
|
Beispiel-Links zeigen deshalb auf Gitea. **GitHub Pages bleibt** — der
|
||||||
|
Actions-Workflow der „latest build“-Instanz (D16) lässt sich nicht mitnehmen,
|
||||||
|
und daran hängt das Spiegeln weiterhin.
|
||||||
|
|
||||||
|
## D96 — `git.javagil.de` liefert `raw`-Dateien mit `Access-Control-Allow-Origin` (2026-09-03)
|
||||||
|
D95 hielt fest, dass die Beispiel-Links auf `raw.githubusercontent.com` bleiben
|
||||||
|
müssen, weil Gitea den CORS-Header nicht sendet. Das war eine
|
||||||
|
Server-Konfiguration, keine Eigenschaft von Gitea — sie ist jetzt gesetzt, und
|
||||||
|
die Links zeigen auf `origin`.
|
||||||
|
|
||||||
|
**Gemessen, nicht vermutet.** Giteas eigener `[cors]`-Abschnitt allein reicht
|
||||||
|
nicht: mit `ENABLED = true` / `ALLOW_DOMAIN = *` / `METHODS = GET,HEAD` in
|
||||||
|
`app.ini` trägt `/api/v1/repos/mi/werkdock/raw/README.md` den Header, die
|
||||||
|
**Web**-Route `/mi/werkdock/raw/branch/main/README.md` aber weiterhin nicht —
|
||||||
|
Gitea 1.27 legt die CORS-Middleware nur auf `/api/v1`. Die Beispiel-Links
|
||||||
|
benutzen die Web-Route.
|
||||||
|
|
||||||
|
**Also beides, mit klarer Aufteilung.** Der `[cors]`-Abschnitt bleibt für die
|
||||||
|
API-Route; die Web-Route bekommt den Header im Apache davor, in der
|
||||||
|
`.htaccess` der Domain:
|
||||||
|
|
||||||
|
```apache
|
||||||
|
SetEnvIf Request_URI "^/[^/]+/[^/]+/(raw|media)/" GITEA_RAW_CORS
|
||||||
|
Header always set Access-Control-Allow-Origin "*" env=GITEA_RAW_CORS
|
||||||
|
```
|
||||||
|
|
||||||
|
Zwei Fallen, beide beim Umsetzen aufgelaufen: `<LocationMatch>` ist in einer
|
||||||
|
`.htaccess` **nicht erlaubt** (nur Server-Config/VHost) — auf einem Managed
|
||||||
|
Webspace gibt es aber nur `.htaccess`, daher `SetEnvIf`. Und die Regel darf
|
||||||
|
`/api/v1` **nicht** mitfassen: `Header always` schreibt in `err_headers_out`
|
||||||
|
und *ergänzt* dort, statt zu ersetzen — zusammen mit Giteas eigenem Header
|
||||||
|
standen zwei `Access-Control-Allow-Origin: *` in der Antwort, was Browser als
|
||||||
|
ungültig verwerfen. Gemessen: je genau ein Header auf beiden raw-Routen, keiner
|
||||||
|
auf gewöhnlichen Repo-Seiten.
|
||||||
|
|
||||||
|
**`*` ohne Credentials ist hier die harmlose Variante.** Unter einem
|
||||||
|
Wildcard-Ursprung sendet der Browser grundsätzlich keine Cookies; ein fremder
|
||||||
|
Ursprung liest also nur, was ohnehin anonym abrufbar ist. Private Repositories
|
||||||
|
brauchen die Sitzung und antworten weiter mit 404/403 (nachgemessen: 404 auf
|
||||||
|
einen nicht existierenden Pfad). Ausdrücklich **nicht** getan: kein
|
||||||
|
`Access-Control-Allow-Credentials: true` (damit könnten fremde Seiten private
|
||||||
|
Repositories im Namen des angemeldeten Benutzers lesen), kein Zurückspiegeln
|
||||||
|
des `Origin` (dasselbe Risiko, sobald jemand später Credentials ergänzt), und
|
||||||
|
der Header steht nicht site-weit, sondern nur auf den raw-Pfaden.
|
||||||
|
|
||||||
|
**Kein Preflight nötig.** `OPTIONS` auf die Web-raw-Route antwortet weiterhin
|
||||||
|
`405`. Das ist folgenlos: der Abruf aus D23 ist ein *simple request* —
|
||||||
|
schlichtes `GET`, `credentials:'omit'`, keine eigenen Header —, und dafür
|
||||||
|
schickt der Browser keinen Preflight.
|
||||||
|
|
||||||
|
**Die Konfiguration liegt in keinem Repository.** Sie gehört dem Unix-Benutzer
|
||||||
|
`mih09-git` auf mih09 (`gitea/custom/conf/app.ini` und
|
||||||
|
`doms/git.javagil.de/htdocs-ssl/.htaccess`, beide mit Zeitstempel-Sicherung
|
||||||
|
daneben) — deshalb steht sie hier im Wortlaut, damit sie nach einem Neuaufsetzen
|
||||||
|
wiederherstellbar ist.
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
> **Hinweis:** Dieses Dokument beschreibt nur die Änderung dieses PR.
|
||||||
|
> Es kann veraltet sein, sobald der nächste PR gemergt ist.
|
||||||
|
> Historische PR-Dokumentation wird nicht nachgepflegt — sie ist eine Momentaufnahme, keine aktuelle Doku.
|
||||||
|
|
||||||
|
## Das Problem
|
||||||
|
|
||||||
|
Die Beispiel-Links beider READMEs laden ihren Plan per `?sourceUrl=` aus einer Textdatei im Netz (D23).
|
||||||
|
Der Browser holt eine fremde Herkunft nur, wenn die Antwort `Access-Control-Allow-Origin` trägt.
|
||||||
|
`raw.githubusercontent.com` sendet den Header, `git.javagil.de` sendete ihn nicht.
|
||||||
|
Deshalb mussten die Links nach dem Umzug nach Gitea (D95) weiterhin auf den GitHub-Klon zeigen, obwohl das Repository dort gar nicht mehr zuhause ist.
|
||||||
|
|
||||||
|
Gemessen am 2026-09-03, mit `Origin:`-Header: HTTP 200, `Access-Control-Expose-Headers: Content-Disposition`, `Content-Type: text/plain; charset=utf-8` — aber kein `Access-Control-Allow-Origin`.
|
||||||
|
Die Datei selbst war also einwandfrei erreichbar; es fehlte genau ein Header.
|
||||||
|
|
||||||
|
## Nicht das Ziel
|
||||||
|
|
||||||
|
- Der GitHub-Klon verschwindet nicht: die GitHub-Pages-Instanz (D16) hängt weiter daran, sie ist ein Actions-Workflow und lässt sich nicht mitnehmen.
|
||||||
|
- Kein Proxy-Dienst als Ausweg — D23 verwirft ihn ausdrücklich, weil er fremde Inhalte über einen Dritt-Host leiten würde.
|
||||||
|
- Keine Änderung am Frontend: `sourceUrl` bleibt, wie es ist; der Fehler lag ausschließlich auf der Serverseite.
|
||||||
|
|
||||||
|
## Die Szenarien
|
||||||
|
|
||||||
|
### Feature: Beispiel-Pläne laden aus dem eigenen Gitea
|
||||||
|
|
||||||
|
#### Hintergrund
|
||||||
|
|
||||||
|
- Die Konfiguration liegt beim Unix-Benutzer `mih09-git` auf mih09 und in **keinem** Repository; sie ist im Wortlaut in D96 festgehalten.
|
||||||
|
- Giteas eigener `[cors]`-Abschnitt und die `.htaccess` der Domain teilen sich die Arbeit: die API-Route deckt Gitea ab, die Web-Route der Apache davor.
|
||||||
|
|
||||||
|
#### Szenario#1.01: Ein Beispiel-Link öffnet den Plan statt eines CORS-Fehlers
|
||||||
|
|
||||||
|
Damit die Links auf `origin` zeigen können und nicht auf einen Klon.
|
||||||
|
|
||||||
|
- **Gegeben** ein Beispiel-Link mit `?sourceUrl=https://git.javagil.de/mi/werkbaum/raw/branch/main/…`
|
||||||
|
- **Wenn** der Browser die Datei aus der fremden Herkunft holt
|
||||||
|
- **Dann** trägt die Antwort `Access-Control-Allow-Origin: *` und der Plan wird geöffnet
|
||||||
|
|
||||||
|
##### Nachgewiesen durch
|
||||||
|
|
||||||
|
- Messung 2026-09-03 auf allen fünf Beispieldateien: je HTTP 200 mit genau einem `Access-Control-Allow-Origin: *`.
|
||||||
|
|
||||||
|
#### Szenario#1.02: Die API-Route trägt den Header genau einmal
|
||||||
|
|
||||||
|
Damit die Antwort gültig bleibt — zwei `Access-Control-Allow-Origin`-Header verwirft der Browser als ungültig.
|
||||||
|
|
||||||
|
- **Gegeben** Gitea setzt den Header auf `/api/v1/…` bereits selbst
|
||||||
|
- **Wenn** die `.htaccess` diese Route nicht mitfasst
|
||||||
|
- **Dann** steht in der Antwort genau ein `Access-Control-Allow-Origin: *`
|
||||||
|
|
||||||
|
##### Nachgewiesen durch
|
||||||
|
|
||||||
|
- Messung 2026-09-03: `/api/v1/repos/mi/werkdock/raw/README.md` → ein Header (zuvor, mit der ersten Fassung der `.htaccess`, waren es zwei).
|
||||||
|
|
||||||
|
#### Szenario#1.03: Gewöhnliche Repo-Seiten bleiben unberührt
|
||||||
|
|
||||||
|
Damit der Header nur dort steht, wo er gebraucht wird, und nicht site-weit.
|
||||||
|
|
||||||
|
- **Gegeben** eine gewöhnliche Seite wie `/mi/werkdock`
|
||||||
|
- **Wenn** sie abgerufen wird
|
||||||
|
- **Dann** trägt die Antwort keinen `Access-Control-Allow-Origin`
|
||||||
|
|
||||||
|
##### Nachgewiesen durch
|
||||||
|
|
||||||
|
- Messung 2026-09-03: `/mi/werkdock` → HTTP 200, null `Access-Control-Allow-Origin`-Header.
|
||||||
|
|
||||||
|
## Die Lösung
|
||||||
|
|
||||||
|
Auf mih09, beim Benutzer `mih09-git` (Sicherungskopien mit Zeitstempel liegen jeweils daneben):
|
||||||
|
|
||||||
|
- `gitea/custom/conf/app.ini` bekommt einen `[cors]`-Abschnitt (`ENABLED = true`, `ALLOW_DOMAIN = *`, `METHODS = GET,HEAD`); Gitea neu gestartet.
|
||||||
|
- `doms/git.javagil.de/htdocs-ssl/.htaccess` bekommt `SetEnvIf Request_URI "^/[^/]+/[^/]+/(raw|media)/"` plus `Header always set Access-Control-Allow-Origin "*" env=…`, vor den vorhandenen Proxy-Regeln.
|
||||||
|
|
||||||
|
Im Repository:
|
||||||
|
|
||||||
|
- Die Beispiel-Links beider READMEs zeigen auf `git.javagil.de/mi/werkbaum/raw/branch/main/…`.
|
||||||
|
- Die CORS-Einschränkung in beiden READMEs und in D23 nennt `git.javagil.de` jetzt unter den Hosts, die den Header senden.
|
||||||
|
- Der Absatz „GitHub bleibt ein Klon“ nennt nur noch GitHub Pages als Grund; D95 bekommt einen Nachtrag, D96 hält die Konfiguration im Wortlaut fest.
|
||||||
|
|
||||||
|
Warum die Aufteilung auf zwei Stellen: Gitea 1.27 legt die CORS-Middleware nur auf `/api/v1`, nicht auf die Web-raw-Route — und genau die benutzen die Links.
|
||||||
|
Warum `SetEnvIf` statt `<LocationMatch>`: Location-Direktiven sind in einer `.htaccess` nicht erlaubt, und auf einem Managed Webspace gibt es nur `.htaccess`.
|
||||||
|
Warum `*` ohne Credentials: unter einem Wildcard-Ursprung sendet der Browser keine Cookies, ein fremder Ursprung liest also nur, was ohnehin anonym abrufbar ist; private Repositories antworten weiter mit 404/403.
|
||||||
|
|
||||||
|
## Offene Fragen
|
||||||
|
|
||||||
|
- Keine. Beide Fallen (verbotenes `<LocationMatch>`, doppelter Header) sind beim Umsetzen aufgetreten und behoben; die Messungen decken Web-raw, API-raw und eine gewöhnliche Seite ab.
|
||||||
|
|
||||||
|
## Weitere Änderungen
|
||||||
|
|
||||||
|
- Der Link „Werkbaum selbst“ war schon vorher tot: er zeigte auf `example-werkbaum.werkbaum`, die Datei heißt `werkbaum.werkbaum` — auch auf GitHub lieferte er 404. Beim Umstellen mit korrigiert.
|
||||||
|
- `docs/prs/` samt Konvention neu eingeführt; `CLAUDE.md` verweist darauf.
|
||||||
|
|
||||||
|
## Vorausgesetzte PRs
|
||||||
|
|
||||||
|
- Keine; setzt den Umzug nach Gitea (D95) voraus, der bereits auf `main` liegt.
|
||||||
|
|
||||||
|
## Folge-PRs
|
||||||
|
|
||||||
|
- Keine geplant.
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# PR-Dokumentation
|
||||||
|
|
||||||
|
Jeder Pull Request bekommt hier **eine** Datei.
|
||||||
|
|
||||||
|
## Dateiname
|
||||||
|
|
||||||
|
`JJJJ-MM-TT-PR#<nummer>-kurze-beschreibung.md`
|
||||||
|
|
||||||
|
Die Nummer ist die des Gitea-PR auf <https://git.javagil.de/mi/werkbaum>.
|
||||||
|
Steht sie noch nicht fest, gilt `PR#000` als Platzhalter — im Dateinamen wie in
|
||||||
|
den Szenario-IDs — und wird nachgezogen, sobald der PR offen ist.
|
||||||
|
|
||||||
|
## Aufbau
|
||||||
|
|
||||||
|
Die `##`-Abschnitte in genau dieser Reihenfolge, nicht Zutreffendes weglassen:
|
||||||
|
|
||||||
|
1. Das Problem
|
||||||
|
2. Nicht das Ziel
|
||||||
|
3. Die Szenarien
|
||||||
|
4. Die Lösung
|
||||||
|
5. Offene Fragen
|
||||||
|
6. Weitere Änderungen
|
||||||
|
7. Vorausgesetzte PRs
|
||||||
|
8. Folge-PRs
|
||||||
|
|
||||||
|
## Regeln
|
||||||
|
|
||||||
|
- Deutsch (CLAUDE.md), Markdown, ein Satz je Zeile, kurz halten.
|
||||||
|
- Das „Warum“ erklären, nicht nur das „Was“.
|
||||||
|
- Szenarien in Markdown-eigenem Pseudo-Gherkin mit IDs `Szenario#<pr-nummer>.<nn>`,
|
||||||
|
jedes mit einer Liste `##### Nachgewiesen durch`.
|
||||||
|
- Ein PR-doc beschreibt den Stand **dieses** PR. Ältere PR-docs werden nicht
|
||||||
|
nachgepflegt, wenn spätere PRs das Verhalten ändern — dauerhafte Begründungen
|
||||||
|
gehören nach `docs/DECISIONS.md`.
|
||||||
Reference in New Issue
Block a user