Compare commits
base: stwaidele:a327126fac36884ef8f158f16daab7d12419d854
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:90748b743edca00680e5b572398595eeaaec49d2
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
a327126fac
...
90748b743e
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 90748b743e |
#307: pond-level branding overrides the instance logo and favicon
Built on #306's storage, serving and crop control — a layer, not a parallel implementation. `resolveBranding` in shared is the ONE place that answers "which asset applies here?", and both the sidebar logo and the favicon swap read it. The decision most likely to be "fixed" by accident, so it is pinned by name in `branding.test.ts`: **a logo set belongs to one level and variants are never mixed across levels.** A pond that uploaded only a light logo shows THAT logo in dark mode; it does not borrow the instance's dark variant. Decided 2026-08-01 — a logo silently swapping to a different image when the viewer switches theme is a change nobody ordered, and a design that looks wrong is more honest than one that is quietly substituted. Only a pond with no logo at all inherits the instance's set, again as a set. The settings screen warns about a missing dark variant; it never blocks. Consequences that fall out of that rule and are easy to get wrong: - The serving route does NOT fall back when given a pond scope. The caller already decided which level applies; a "helpful" fallback in the route would mix variants across levels behind the resolver's back. - The logo link's accessible name follows the LEVEL: a pond logo is named by the pond, an instance logo by the instance. It is the link home, and a link's name has to say where it goes. - **Charged to the pond's storage quota**, before the write, like attachments. Without it branding would be a way around the quota, and replacing a logo repeatedly would consume disk with no ceiling. The replaced asset's bytes are released FIRST, so re-uploading the same logo costs nothing — and a refused upload puts the released reservation back, so a rejection cannot leave the pond with more room than it had. - **Purge removes the branding files.** The purge standard is absolute: after it nothing referencing the pond survives, rows or files. Asserted against the real purge path, not the new code alone. - Security unchanged from #306 and not relaxed because the uploader is now an ordinary Pond Admin: SVG refused, magic bytes and IHDR checked server-side, size caps, content type pinned, no image parsing. - The favicon swap is driven by the RESOLVED pond, never the raw route parameter — an unreadable or unknown slug must not leave a stale icon in the tab. That it happens after first paint is accepted and stated in the code and the UI: avoiding it would mean server-rendering index.html, which is #179's territory. Same audit id as #306 (`branding.changed`) with `scope: 'pond'` — the catalogue already carries the field, so no version bump. Verified: api suite 105 files / 592 tests green; 5 pond-branding e2e tests (pond scope serves the pond's bytes while the instance level still 404s, the quota is charged and released exactly, SVG refused at pond level, a reader may read but not change, purge deletes the files); 9 shared unit tests on the resolution order including both mixing directions. |