CI & Build / Build now, or wait for Android? (push) Successful in 2s
CI & Build / Python lint (push) Successful in 3s
Android / Build, or is the channel already serving this? (push) Successful in 3s
Android / Core and FFI clippy and tests (push) Skipped
Android / Kotlin + Rust (APK) (push) Skipped
Android / Build the server image (push) Skipped
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
CI & Build / Web typecheck and unit tests (push) Successful in 10s
CI & Build / Python tests (push) Successful in 12s
CI & Build / integration (push) Successful in 1m40s
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Successful in 1m44s
CI & Build / Build & push image (push) Successful in 38s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m18s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 3m9s
Desktop (Tauri) / Update manifest (push) Successful in 4s
#5927 "Adopt the family idea secret.Box": the SMTP password and the backup bucket's secret key were kept as plain text in the settings table, so a copy of the database alone could read them. - New sealing.py: AES-GCM under an HKDF-derived key, each value bound to its setting's name. The key is a random file, /var/inkwell/sealing.key (0600), made on first use. It lives on the data volume, not in the database, which is where the signing secret sits by default. - set_settings seals a secret before storing it; get_setting opens it. A value that no longer opens (key file lost) reads as not set, so Settings asks for it again. - At startup, credentials stored before this are sealed in place, so nothing has to be re-entered. A data folder that can't be written never stops the server; saving a password then answers with the reason. - New dependency: cryptography (approved by the operator). Also #1919 "Deprecate / remove the PWA": kept. Its service worker caches only the offline page, so an installed copy always runs the live build. One stale comment in sw.js is corrected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
38 lines
1.4 KiB
JavaScript
38 lines
1.4 KiB
JavaScript
// Inkwell service worker — installable shell, deliberately NOT offline-first.
|
|
//
|
|
// This exists so the web app satisfies the PWA install criteria ("Add to Home
|
|
// Screen") and shows a friendly page when a navigation happens with no network.
|
|
// The offline clients are the desktop and Android apps; to stay always-fresh
|
|
// and avoid deploy staleness, this SW does NOT cache the app shell, hashed build
|
|
// assets, or any /api response — everything but the offline fallback goes
|
|
// straight to the network. So an installed copy is the live web app, never an
|
|
// older one (#1919).
|
|
const CACHE = "inkwell-shell-v1";
|
|
const OFFLINE_URL = "/offline.html";
|
|
|
|
self.addEventListener("install", (event) => {
|
|
event.waitUntil(
|
|
caches
|
|
.open(CACHE)
|
|
.then((cache) => cache.add(OFFLINE_URL))
|
|
.then(() => self.skipWaiting()),
|
|
);
|
|
});
|
|
|
|
self.addEventListener("activate", (event) => {
|
|
event.waitUntil(
|
|
caches
|
|
.keys()
|
|
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
|
.then(() => self.clients.claim()),
|
|
);
|
|
});
|
|
|
|
// Only intercept page navigations: try the network, fall back to the cached
|
|
// offline page when the server is unreachable. All other requests (hashed
|
|
// assets, /api/*) are left untouched and hit the network normally.
|
|
self.addEventListener("fetch", (event) => {
|
|
if (event.request.mode !== "navigate") return;
|
|
event.respondWith(fetch(event.request).catch(() => caches.match(OFFLINE_URL)));
|
|
});
|