The overrideWarnings escape hatch added alongside the bundle scan was
API-only: an admin uploading a crypto plugin through the web form hit a
400 with canOverride and had no way to act on it, which left S/MIME and
PGP bundles uninstallable through the UI.
Hold the rejected file client-side and show the findings — pattern per
file — with "Install anyway" and "Cancel". Proceeding re-posts the same
file with overrideWarnings, so the decision stays explicit and lands in
the audit log. The route now echoes accepted findings back on success so
the confirmation says how many were waved through rather than reporting a
bare install.
Also replaces a dead `data.warnings` read with the live `findings` field;
the route never returned `warnings` on success, so that branch never ran.
Completes B-01.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two problems with the upload scanner, pulling in opposite directions.
It only scanned the entrypoint, so a bundle with `eval()` in a second
file passed outright — verified against a synthetic bundle whose
vendor/openpgp.js tripped three patterns while index.js stayed clean.
At the same time, a hard 400 on eval()/new Function()/innerHTML= makes
every crypto plugin uninstallable: minified openpgp.js and pkijs
legitimately contain all three. That blocks S/MIME and PGP entirely.
Scan every .js/.mjs in the bundle and return structured findings
({file, patterns[]}) plus canOverride, so the admin can see exactly what
tripped and where. An explicit overrideWarnings=true proceeds and writes
a plugin.install.scan_override audit entry recording which patterns in
which files were accepted — not merely that an override happened.
This route is already admin-authenticated, so the scan is defence in
depth against an accidental or compromised upload, not a trust boundary.
Treating it as the latter is what made crypto plugins uninstallable.
Also log the B-04 and B-01 divergences in vnc/VNC-CHANGES.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add optional logoLightUrl/logoDarkUrl to InstalledTheme + resolveThemeLogo()
helper; set logos on vnclagoon + src themes; login page and nav-rail prefer the
active theme's logo, falling back to the global config logo. So switching theme
switches the whole brand. 0 type errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add builtin-vnclagoon theme (cyan #00D4FF accent on navy #0A0E1A, DM Sans body
+ Syne headings, self-hosted OFL fonts); set as default theme policy; default
mode dark. Add VNCmail wordmark SVGs (on-dark/on-light) + wire logo/company via
k8s secret template. Placeholder wordmark — swap official styleguide SVG.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bulwark is stateful (local /app/data) — Vercel serverless (read-only fs)
crashes it. Deploy as a container with 4 persistent volumes on microk8s,
alongside bulwark.sandbox.vnc.de. Adds deploy/k8s/ (namespace, pvc, deployment,
service, ingress, secret template, runbook) + rewrites setup doc off Vercel.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove withMicrofrontends wrap + @vercel/microfrontends dep. Grouping is
organizational (separate Vercel team), not a microfrontends group. App
serves at its own root again (NEXT_PUBLIC_BASE_PATH removed on Vercel).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wrap next.config with withMicrofrontends; add @vercel/microfrontends.
Served at /mail under the suite shell (via NEXT_PUBLIC_BASE_PATH set on the
Vercel project). Logged in vnc/VNC-CHANGES.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fork of bulwarkmail/webmail for deploy on Vercel as project vncmail-plus.
Adds vnc/ customization layer (branding, overrides, VNC-CHANGES log),
Vercel env template, and VNCMAIL-SETUP.md runbook. No upstream files touched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>