Compare commits
base: stwaidele:76a5e92f2ee7e6fac4da05b83072661758eeeed4
stwaidele:main
stwaidele:345-plugin-zip-license-texts
stwaidele:issue-339-markdown-table-paste
stwaidele:issue-338-tab-navigation
stwaidele:issue-337-merge-split
stwaidele:issue-336-delete-icons
stwaidele:issue-335-gap-cursor
stwaidele:feat/332-invitations
stwaidele:feat/331-admin-create-user
stwaidele:329-quota-override-cell-table-layout
stwaidele:324-325-self-hosting-guide-findings
stwaidele:323-document-title-instance-name
stwaidele:322-admin-settings-form-flat-keys
stwaidele:320-refresh-self-hosting-guide
stwaidele:fix/sort-key-test-timeout
stwaidele:issue-307-pond-branding
stwaidele:issue-305-pond-archive
stwaidele:issue-179-spa-lang
stwaidele:issue-306-instance-branding
stwaidele:issue-304-custom-font-ui
stwaidele:issue-303-fonts-dir-ownership
stwaidele:issue-303-custom-fonts
stwaidele:issue-301-settings-reflow
stwaidele:issue-302-pond-start-page
stwaidele:issue-300-icon-buttons
stwaidele:issue-296-remove-legacy-verify
stwaidele:issue-232-plugin-hash-pinning
stwaidele:adr-0019-0027-accepted
stwaidele:issue-246-vs-nfd-enforced
stwaidele:issue-245-vs-nfd-hidden
stwaidele:issue-244-vs-nfd-marked
stwaidele:issue-243-vs-nfd-mode
stwaidele:issue-221-offline-update
stwaidele:issue-220-isolated-run
stwaidele:issue-288-restore-partitioned
stwaidele:issue-219-offline-build
stwaidele:issue-218-registry-mirror
stwaidele:issue-217-claim-mapping
stwaidele:issue-216-local-auth-switch
stwaidele:issue-215-proxy-auth
stwaidele:issue-214-oidc
stwaidele:issue-225-read-trail-switch
stwaidele:issue-224-read-trail-storage
stwaidele:issue-223-read-trail-dedup
stwaidele:issue-222-read-trail
stwaidele:issue-227-hardening-guide
stwaidele:issue-228-security-documentation
stwaidele:issue-229-operations-manual
stwaidele:issue-230-grundschutz-mapping
stwaidele:issue-231-residual-risks
stwaidele:issue-213-upload-warning
stwaidele:issue-212-attachment-marking
stwaidele:issue-211-channel-marking
stwaidele:issue-210-zip-marking
stwaidele:issue-209-office-marking
stwaidele:issue-208-pdf-marking
stwaidele:issue-207-print-css
stwaidele:issue-206-web-classification-marking
stwaidele:issue-205-classification-inheritance
stwaidele:issue-204-page-classification
stwaidele:feat/203-image-digest-pinning
stwaidele:feat/201-audit-event-catalogue
stwaidele:feat/200-plugins-kill-switch
stwaidele:feat/199-attachment-integrity-hashes
stwaidele:feat/202-sbom-license-report
stwaidele:feat/236-pin-node-version
stwaidele:feat/235-page-links-purge-decision
stwaidele:feat/234-mail-outbox-retention
stwaidele:feat/233-conversion-job-payload-pruning
stwaidele:feat/198-env-verification
stwaidele:feat/197-security-headers
stwaidele:feat/196-audit-retention
stwaidele:feat/195-search-index-trash
stwaidele:feat/194-orphan-sweep
stwaidele:feat/193-pond-purge
stwaidele:feat/192-backup-allowlist
stwaidele:feat/191-feeds-switch
stwaidele:feat/190-session-timeouts
stwaidele:feat/189-csrf-fail-closed
stwaidele:feat/188-token-key-separation
stwaidele:docs/226-delimitation-statement
stwaidele:docs/vs-nfd-planning
stwaidele:feat/186-pond-accent
stwaidele:feat/184-theme-engine
stwaidele:feat/182-theme-toggle
stwaidele:feat/180-dark-mode
stwaidele:admin-actions-cell-align
stwaidele:admin-user-action-icons
stwaidele:a11y-mittel
stwaidele:a11y-aria
stwaidele:a11y-focus-lang
stwaidele:fix-160-plugin-block-editable
stwaidele:m23-chordpro
stwaidele:m22-aufgaben
stwaidele:m21-api-feeds
stwaidele:m20-ui-einbettung
stwaidele:k19-screenshot-svgfit
stwaidele:excalidraw-demo-docs
stwaidele:fix-137-3px
stwaidele:fix-137-nodeview
stwaidele:editor-autofocus
stwaidele:fix-137-checkbox
stwaidele:m17-m19-issues
stwaidele:prod-v0.16.0-initial
stwaidele:v0.16.0
stwaidele:prod-v0.15.0-initial
stwaidele:v0.15.0
stwaidele:prod-v0.14.0-initial
stwaidele:v0.14.0
stwaidele:prod-v0.13.0-initial
stwaidele:v0.13.0
stwaidele:prod-v0.12.0-initial
stwaidele:v0.12.0
stwaidele:prod-v0.11.1-initial
stwaidele:v0.11.1
stwaidele:v0.11.0
stwaidele:prod-v0.11.0-initial
stwaidele:prod-v0.10.1-initial
stwaidele:v0.10.1
stwaidele:prod-v0.10.0-initial
stwaidele:v0.10.0
stwaidele:prod-v0.9.2-initial
stwaidele:v0.9.2
stwaidele:prod-v0.9.1-initial
stwaidele:v0.9.1
stwaidele:prod-v0.9.0-initial
stwaidele:v0.9.0
stwaidele:prod-v0.8.0-initial
stwaidele:v0.8.0
stwaidele:prod-v0.7.0-initial
stwaidele:v0.7.0
stwaidele:prod-v0.6.0-initial
stwaidele:v0.6.0
stwaidele:prod-v0.5.0-initial
stwaidele:v0.5.0
stwaidele:prod-v0.4.0-keycheck
stwaidele:prod-v0.4.0-initial
stwaidele:v0.4.0
stwaidele:prod-v0.3.0-initial
stwaidele:v0.3.0
stwaidele:drill-prod-1783881455
stwaidele:drill-prod-1783879107
stwaidele:prod-v0.2.0-initial
stwaidele:v0.2.0
stwaidele:prod-v0.1.2-initial
stwaidele:v0.1.2
stwaidele:prod-v0.1.1-final
stwaidele:prod-v0.1.0-rollback1
stwaidele:prod-v0.1.1-upgrade
stwaidele:v0.1.1
stwaidele:prod-v0.1.0-initial
stwaidele:v0.1.0
stwaidele:drill-verify-87
..
compare: stwaidele:6377faf332eb7b814ea79491e2d9329b8f29524b
stwaidele:345-plugin-zip-license-texts
stwaidele:main
stwaidele:issue-339-markdown-table-paste
stwaidele:issue-338-tab-navigation
stwaidele:issue-337-merge-split
stwaidele:issue-336-delete-icons
stwaidele:issue-335-gap-cursor
stwaidele:feat/332-invitations
stwaidele:feat/331-admin-create-user
stwaidele:329-quota-override-cell-table-layout
stwaidele:324-325-self-hosting-guide-findings
stwaidele:323-document-title-instance-name
stwaidele:322-admin-settings-form-flat-keys
stwaidele:320-refresh-self-hosting-guide
stwaidele:fix/sort-key-test-timeout
stwaidele:issue-307-pond-branding
stwaidele:issue-305-pond-archive
stwaidele:issue-179-spa-lang
stwaidele:issue-306-instance-branding
stwaidele:issue-304-custom-font-ui
stwaidele:issue-303-fonts-dir-ownership
stwaidele:issue-303-custom-fonts
stwaidele:issue-301-settings-reflow
stwaidele:issue-302-pond-start-page
stwaidele:issue-300-icon-buttons
stwaidele:issue-296-remove-legacy-verify
stwaidele:issue-232-plugin-hash-pinning
stwaidele:adr-0019-0027-accepted
stwaidele:issue-246-vs-nfd-enforced
stwaidele:issue-245-vs-nfd-hidden
stwaidele:issue-244-vs-nfd-marked
stwaidele:issue-243-vs-nfd-mode
stwaidele:issue-221-offline-update
stwaidele:issue-220-isolated-run
stwaidele:issue-288-restore-partitioned
stwaidele:issue-219-offline-build
stwaidele:issue-218-registry-mirror
stwaidele:issue-217-claim-mapping
stwaidele:issue-216-local-auth-switch
stwaidele:issue-215-proxy-auth
stwaidele:issue-214-oidc
stwaidele:issue-225-read-trail-switch
stwaidele:issue-224-read-trail-storage
stwaidele:issue-223-read-trail-dedup
stwaidele:issue-222-read-trail
stwaidele:issue-227-hardening-guide
stwaidele:issue-228-security-documentation
stwaidele:issue-229-operations-manual
stwaidele:issue-230-grundschutz-mapping
stwaidele:issue-231-residual-risks
stwaidele:issue-213-upload-warning
stwaidele:issue-212-attachment-marking
stwaidele:issue-211-channel-marking
stwaidele:issue-210-zip-marking
stwaidele:issue-209-office-marking
stwaidele:issue-208-pdf-marking
stwaidele:issue-207-print-css
stwaidele:issue-206-web-classification-marking
stwaidele:issue-205-classification-inheritance
stwaidele:issue-204-page-classification
stwaidele:feat/203-image-digest-pinning
stwaidele:feat/201-audit-event-catalogue
stwaidele:feat/200-plugins-kill-switch
stwaidele:feat/199-attachment-integrity-hashes
stwaidele:feat/202-sbom-license-report
stwaidele:feat/236-pin-node-version
stwaidele:feat/235-page-links-purge-decision
stwaidele:feat/234-mail-outbox-retention
stwaidele:feat/233-conversion-job-payload-pruning
stwaidele:feat/198-env-verification
stwaidele:feat/197-security-headers
stwaidele:feat/196-audit-retention
stwaidele:feat/195-search-index-trash
stwaidele:feat/194-orphan-sweep
stwaidele:feat/193-pond-purge
stwaidele:feat/192-backup-allowlist
stwaidele:feat/191-feeds-switch
stwaidele:feat/190-session-timeouts
stwaidele:feat/189-csrf-fail-closed
stwaidele:feat/188-token-key-separation
stwaidele:docs/226-delimitation-statement
stwaidele:docs/vs-nfd-planning
stwaidele:feat/186-pond-accent
stwaidele:feat/184-theme-engine
stwaidele:feat/182-theme-toggle
stwaidele:feat/180-dark-mode
stwaidele:admin-actions-cell-align
stwaidele:admin-user-action-icons
stwaidele:a11y-mittel
stwaidele:a11y-aria
stwaidele:a11y-focus-lang
stwaidele:fix-160-plugin-block-editable
stwaidele:m23-chordpro
stwaidele:m22-aufgaben
stwaidele:m21-api-feeds
stwaidele:m20-ui-einbettung
stwaidele:k19-screenshot-svgfit
stwaidele:excalidraw-demo-docs
stwaidele:fix-137-3px
stwaidele:fix-137-nodeview
stwaidele:editor-autofocus
stwaidele:fix-137-checkbox
stwaidele:m17-m19-issues
stwaidele:prod-v0.16.0-initial
stwaidele:v0.16.0
stwaidele:prod-v0.15.0-initial
stwaidele:v0.15.0
stwaidele:prod-v0.14.0-initial
stwaidele:v0.14.0
stwaidele:prod-v0.13.0-initial
stwaidele:v0.13.0
stwaidele:prod-v0.12.0-initial
stwaidele:v0.12.0
stwaidele:prod-v0.11.1-initial
stwaidele:v0.11.1
stwaidele:v0.11.0
stwaidele:prod-v0.11.0-initial
stwaidele:prod-v0.10.1-initial
stwaidele:v0.10.1
stwaidele:prod-v0.10.0-initial
stwaidele:v0.10.0
stwaidele:prod-v0.9.2-initial
stwaidele:v0.9.2
stwaidele:prod-v0.9.1-initial
stwaidele:v0.9.1
stwaidele:prod-v0.9.0-initial
stwaidele:v0.9.0
stwaidele:prod-v0.8.0-initial
stwaidele:v0.8.0
stwaidele:prod-v0.7.0-initial
stwaidele:v0.7.0
stwaidele:prod-v0.6.0-initial
stwaidele:v0.6.0
stwaidele:prod-v0.5.0-initial
stwaidele:v0.5.0
stwaidele:prod-v0.4.0-keycheck
stwaidele:prod-v0.4.0-initial
stwaidele:v0.4.0
stwaidele:prod-v0.3.0-initial
stwaidele:v0.3.0
stwaidele:drill-prod-1783881455
stwaidele:drill-prod-1783879107
stwaidele:prod-v0.2.0-initial
stwaidele:v0.2.0
stwaidele:prod-v0.1.2-initial
stwaidele:v0.1.2
stwaidele:prod-v0.1.1-final
stwaidele:prod-v0.1.0-rollback1
stwaidele:prod-v0.1.1-upgrade
stwaidele:v0.1.1
stwaidele:prod-v0.1.0-initial
stwaidele:v0.1.0
stwaidele:drill-verify-87
1 Commits
76a5e92f2e
...
6377faf332
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 6377faf332 |
#306: instance branding — logo and favicon, cropped in the browser
All checks were successful
CI / Lint, typecheck, test (pull_request) Successful in 7m28s
CI / Build container images (pull_request) Successful in 2m7s
CI / Auth e2e pack (pull_request) Successful in 9m37s
CI / Import/export fidelity gate (pull_request) Successful in 1m7s
CD / Build and push images (push) Successful in 23s
CD / Deploy to Test (push) Successful in 12s
CD / Smoke tests against Test (push) Successful in 1m47s
CD / Promote to Int (push) Successful in 16s
CI / Lint, typecheck, test (push) Successful in 7m25s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 9m41s
CI / Import/export fidelity gate (push) Successful in 1m12s
An instance had no way to look like itself: the top bar said "Dorfteich" whatever the operator called their instance, `instance.name` was never rendered in the running app at all, and there was no favicon anywhere — `index.html` had no `<link rel="icon">` and `public/` held only fonts and theme-init.js. Where the line is drawn, and why: - **The api never decodes an image.** Cropping, scaling and the conversion to PNG happen on a canvas in the browser; the api checks the PNG signature, reads the IHDR dimensions at their fixed offsets and enforces the caps. An image library would put a decoder in front of attacker-supplied bytes AND would have to be carried through the `--network none` offline build. Reading two big-endian integers is not decoding. - **SVG is refused**, with its own error message rather than a generic "not a PNG": it can carry script, and serving it from our own origin would be a cross-site-scripting vector. An operator who tried one should learn that it is deliberate. - **The crop is driven by number inputs, not by dragging.** A drag-only cropper excludes keyboard and switch users outright; a number input is arrow-key operable and screen-reader readable without any custom aria. The resulting pixel size is stated in text, not only drawn as a frame. - **The variant is chosen by CSS, not JavaScript.** `theme-init.js` has already resolved `data-theme` before first paint, so the correct logo is the one painted rather than the one that appears after a flash. Without a dark variant the LIGHT logo carries both themes — the operator's own asset shown unchanged beats one they did not choose (the rule #307 extends to ponds). The settings screen warns; it never blocks. - **The favicon link is static, its resource dynamic.** index.html stays a static file and the api answers with the uploaded icon or a shipped default — that route must never 404, or the browser keeps its generic icon for good. The default is generated by a script from Node's own zlib (`gen-default-favicon.mjs`), for the same offline-build reason. - Both favicon sizes are uploaded together: one source, one crop, so the tab icon and the home-screen icon can never disagree. - Branding is served WITHOUT a session, because the login screen carries it and the browser fetches the favicon before anyone signs in. The admin screen says so — an operator may not expect their logo to be public. - The metadata is not writable through the settings endpoint: it describes bytes on disk, and hand-writing it would claim an asset that is not there. `./data/branding` follows the three-step rule #303 paid for: env default + `data-dirs.ts` entry, compose volume (repo AND the stages on ONE), and the `mkdir`/`chown` line in the api Dockerfile. `data-dirs.test.ts` is new and closes the hole that made #303's variant invisible: the nightly archive skips a missing directory WORDLESSLY, so the fence now demands that every `*_DIR` the backup env declares actually travels in the archive. Verified against the real defect — removing the line fails it by name. Audit catalogue v1.7 (`branding.changed`), carrying `scope` from the start so #307 is the same event with a different scope, not a second id. Verified: api suite 103 files green (a lone `public-api` ECONNRESET under local parallel load, green in isolation — the documented local flake); branding suite 12 tests against a real directory; crop arithmetic unit tests; a11y pack 11/11 in both schemes; /admin measured at 320px with the new section (overflow 0); and the whole flow walked in the browser: upload → crop 780×180 → stored as 512×118 → logo in the sidebar linking home with the instance name as its accessible name → topbar wordmark following `instance.name` → light logo still shown under `data-theme="dark"`. |