-
Notifications
You must be signed in to change notification settings - Fork 64
Centralize bootstrapping into bootstrap.js and strengthen CSP hash generation #4635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| // Bootstrap globals and service worker wiring for the Insight demo. | ||
|
|
||
| window.PINNER_TOKEN = ""; | ||
| window.OTEL_ENDPOINT = ""; | ||
| window.IPFS_GATEWAY = ""; | ||
|
|
||
| if (typeof window.toast !== "function") { | ||
| window.toast = (msg) => { | ||
| const toastNode = document.getElementById("toast"); | ||
| if (!toastNode) { | ||
| console.warn(msg); | ||
| return; | ||
| } | ||
|
|
||
| toastNode.textContent = String(msg); | ||
| toastNode.classList.add("show"); | ||
| const toastFn = window.toast; | ||
| if (typeof toastFn.id === "number") { | ||
| window.clearTimeout(toastFn.id); | ||
| } | ||
| toastFn.id = window.setTimeout(() => toastNode.classList.remove("show"), 2000); | ||
| }; | ||
| } | ||
|
|
||
| const SW_URL = "service-worker.js"; | ||
|
|
||
| const supportsServiceWorker = (() => { | ||
| try { | ||
| return Boolean(navigator.serviceWorker); | ||
| } catch { | ||
| return false; | ||
| } | ||
| })(); | ||
|
|
||
| if (supportsServiceWorker && !navigator.webdriver) { | ||
| window.addEventListener("load", async () => { | ||
| try { | ||
| const response = await fetch(SW_URL); | ||
| const buffer = await response.arrayBuffer(); | ||
| const digest = await crypto.subtle.digest("SHA-384", buffer); | ||
| const digestB64 = btoa(String.fromCharCode(...new Uint8Array(digest))); | ||
| const swHash = typeof window.SW_HASH === "string" ? window.SW_HASH : ""; | ||
| if (!swHash || `sha384-${digestB64}` !== swHash) { | ||
| throw new Error("Service worker hash mismatch"); | ||
| } | ||
|
|
||
| const registration = await navigator.serviceWorker.register(SW_URL); | ||
| await navigator.serviceWorker.ready; | ||
| registration.addEventListener("updatefound", () => { | ||
| const installingWorker = registration.installing; | ||
| if (!installingWorker) { | ||
| return; | ||
| } | ||
|
|
||
| installingWorker.addEventListener("statechange", () => { | ||
| if (installingWorker.state === "installed") { | ||
| window.toast("Update available — reload to use the latest version."); | ||
| } | ||
| }); | ||
| }); | ||
| } catch (err) { | ||
| const message = err instanceof Error ? err.message : String(err); | ||
| console.error(err); | ||
| window.toast(`Service worker failed: ${message}`); | ||
| } | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,8 +5,7 @@ | |
| <title>α-AGI Insight</title> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
|
|
||
| <link href="https://cdn.jsdelivr.net/npm/daisyui@4.10.2/dist/full.min.css" rel="stylesheet" type="text/css" /> | ||
| <script src="https://cdn.tailwindcss.com"></script> | ||
| <link href="style.css" rel="stylesheet" type="text/css" /> | ||
|
|
||
| <style> | ||
| @keyframes gradient { | ||
|
|
@@ -40,7 +39,7 @@ | |
| opacity: 1; | ||
| } | ||
| </style> | ||
| <meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src 'self' https://api.openai.com; frame-src 'self' blob:; worker-src 'self' blob:; script-src 'self' 'wasm-unsafe-eval' 'sha384-177zXf5eB3dnF9pKwGvc3ITN0EN04yL+Lju+41FYl59Rk/ooEBgXYv3+I8s/0zR0' 'sha384-79nEfECpiwNfTKeXO3LCt0sLutpd3k4stwrBgGfcJBKvwd9SsNd9wIP34JDO4M50' 'sha384-S/HpIy5nMSwGRdVif2eZ3cvGREvSWay48Hf5S44wcCUQ0HW9qYkQDrwyKoG6dSj5' 'sha384-eR8sYzoSk2xJcnjk7RVrsGWKil+DbPgMionlm2xuFpCTJRuyTQ/l6jHF2OY7ZnIL'; style-src 'self' 'unsafe-inline'" /> | ||
| <meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src 'self' https://api.openai.com; frame-src 'self' blob:; worker-src 'self' blob:; script-src 'self' 'wasm-unsafe-eval' 'sha384-E8swqB1rgmKfkntp22RjfBap5YfJMvGbUVw5y2+djoHjwuDrALqWEe1kasdDBmTm' 'sha384-8EzrlAris6MLirPYFKRY4ewS/HYnCKoXFJnB/3zX+XSQ8buVADrMBB6qPBUFs77f' 'sha384-eR8sYzoSk2xJcnjk7RVrsGWKil+DbPgMionlm2xuFpCTJRuyTQ/l6jHF2OY7ZnIL'; style-src 'self' 'unsafe-inline'" /> | ||
| </head> | ||
|
|
||
| <body class="flex flex-col h-screen"> | ||
|
|
@@ -79,78 +78,9 @@ | |
| </div> | ||
| </footer> | ||
|
|
||
| <script src="d3.v7.min.js" integrity="sha384-CjloA8y00+1SDAUkjs099PVfnY2KmDC2BZnws9kh8D/lX1s46w6EPhpXdqMfjK6i" crossorigin="anonymous"></script> | ||
| <script type="importmap"> | ||
| { | ||
| "imports": { | ||
| "d3": "./d3.exports.js" | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <script> | ||
| // Provide a resilient toast implementation before deferred modules load. | ||
| // The Playwright offline checks rely on these calls not throwing. | ||
| if (typeof window.toast !== 'function') { | ||
| window.toast = (msg) => { | ||
| const t = document.getElementById('toast'); | ||
| if (t) { | ||
| t.textContent = msg; | ||
| t.classList.add('show'); | ||
| clearTimeout((window.toast).id); | ||
| (window.toast).id = window.setTimeout(() => t.classList.remove('show'), 2000); | ||
| return; | ||
| } | ||
| console.warn(msg); | ||
| }; | ||
| } | ||
| </script> | ||
|
|
||
| <script> | ||
| const SW_URL = 'service-worker.js'; | ||
| const SW_HASH = 'sha384-jNrRb0RaME0Q+lz0/ITUhfnQBDj97uJPtmPXPc9rSfGvo79YnRebfKvL0rUyytDQ'; | ||
|
|
||
| const serviceWorkerSupported = (() => { | ||
| try { | ||
| return Boolean(navigator.serviceWorker); | ||
| } catch (_err) { | ||
| return false; | ||
| } | ||
| })(); | ||
|
|
||
| if (serviceWorkerSupported && !navigator.webdriver) { | ||
| window.addEventListener('load', async () => { | ||
| try { | ||
| const res = await fetch(SW_URL); | ||
| const buf = await res.arrayBuffer(); | ||
| const digest = await crypto.subtle.digest('SHA-384', buf); | ||
| const b64 = btoa(String.fromCharCode(...new Uint8Array(digest))); | ||
| if (`sha384-${b64}` !== SW_HASH) { | ||
| throw new Error('Service worker hash mismatch'); | ||
| } | ||
|
|
||
| navigator.serviceWorker.register(SW_URL).then((registration) => { | ||
| navigator.serviceWorker.ready.then(() => { | ||
| registration.addEventListener('updatefound', () => { | ||
| const newWorker = registration.installing; | ||
| if (!newWorker) return; | ||
|
|
||
| newWorker.addEventListener('statechange', () => { | ||
| if (newWorker.state === 'installed') { | ||
| window.toast('Update available — reload to use the latest version.'); | ||
| } | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
| } catch (err) { | ||
| console.error(err); | ||
| window.toast('Service worker failed: ' + err.message); | ||
| } | ||
| }); | ||
| } | ||
| </script> | ||
|
|
||
| <script type="importmap">{"imports":{"d3":"./d3.exports.js"}}</script> | ||
| <script>window.SW_HASH = 'sha384-jNrRb0RaME0Q+lz0/ITUhfnQBDj97uJPtmPXPc9rSfGvo79YnRebfKvL0rUyytDQ';</script> | ||
| <script src="bootstrap.js"></script> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This HTML now loads Useful? React with 👍 / 👎. |
||
| <script type="module" src="insight.bundle.js" integrity="sha384-Mb1VRv2DyAqBUMvCGGI6/e90gepYQ9/zjE2rAa8wRVbmwPWSFsW3zIMomuaVkHeh" crossorigin="anonymous"></script> | ||
| <script>window.PINNER_TOKEN=atob('');window.OTEL_ENDPOINT=atob('');window.IPFS_GATEWAY=atob('');</script> | ||
| </body> | ||
|
|
||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The page still configures
window.SW_HASHforservice-worker.js, but this commit deletesdocs/alpha_agi_insight_v1/service-worker.js, so the docs build no longer ships the worker it is wired to verify/register. That breaks service-worker-based caching in docs deployments and conflicts with existing docs checks that expect this file to exist.Useful? React with 👍 / 👎.