Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Expand Up @@ -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 {
Expand Down Expand Up @@ -40,7 +39,8 @@
opacity: 1;
}
</style>
</head>
<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-CcjBOfcES87yQ7WQ94Kc4ASwzt92RftCfH6y+tNasMcZocUOqRPNFDRnyM0QVj8O' 'sha256-MZlivqP55xBVZ2jmS02uBj9OM0b1thDoF0fdP8evk2k=' 'sha256-X7s2D1+oAc3s6pH6dBRpADwwjxV3YTK8VR6FZUx/r0s=' 'sha256-dDxHY9jsmwCNT6SL2iClsP0FZJhaJdDwa84djmuXewU='; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src-elem 'self' 'unsafe-inline' https://cdn.jsdelivr.net" />
</head>

<body class="flex flex-col h-screen">
<header class="p-4 bg-base-100/70 backdrop-blur-md">
Expand Down Expand Up @@ -78,81 +78,9 @@
</div>
</footer>

<script src="d3.v7.min.js" integrity="sha384-CjloA8y00+1SDAUkjs099PVfnY2KmDC2BZnws9kh8D/lX1s46w6EPhpXdqMfjK6i" crossorigin="anonymous"></script>
<script src="bundle.esm.min.js" integrity="sha384-qri3JZdkai966TTOV3Cl4xxA97q+qXCgKrd49pOn7DPuYN74wOEd6CIJ9HnqEROD" crossorigin="anonymous"></script>
<script src="pyodide.js" integrity="sha384-PNUiaEvwfaQJ1qhJmwFD774CUdIYY8k0z7TTAqIzw6fNpx7fG6bzyLb9j6qxSZac" 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 = '__SW_HASH__';

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 = '__SW_HASH__';</script>
<script src="bootstrap.js"></script>
<script type="module" src="insight.bundle.js" integrity="sha384-Mb1VRv2DyAqBUMvCGGI6/e90gepYQ9/zjE2rAa8wRVbmwPWSFsW3zIMomuaVkHeh" crossorigin="anonymous"></script>
</body>
</html>
80 changes: 5 additions & 75 deletions docs/alpha_agi_insight_v1/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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">
Expand Down Expand Up @@ -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>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep docs service-worker artifact in tree

The page still configures window.SW_HASH for service-worker.js, but this commit deletes docs/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 👍 / 👎.

<script src="bootstrap.js"></script>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Ship bootstrap.js alongside docs index

This HTML now loads bootstrap.js, but this commit does not add docs/alpha_agi_insight_v1/bootstrap.js, so the browser gets a 404 and none of the moved bootstrap logic runs on the published docs page. In practice, service-worker registration and the early toast fallback are skipped for docs users, which regresses offline/update behavior compared to the previous inline implementation.

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>
Expand Down
59 changes: 0 additions & 59 deletions docs/alpha_agi_insight_v1/service-worker.js

This file was deleted.

18 changes: 14 additions & 4 deletions scripts/ensure_insight_csp.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@
INLINE_SCRIPT_RE = re.compile(r"<script(?![^>]*src)[^>]*>([\s\S]*?)</script>", re.IGNORECASE)


def _hash_snippet(snippet: str) -> str:
digest = hashlib.sha384(snippet.encode()).digest()
return "'sha384-" + base64.b64encode(digest).decode() + "'"
def _hash_snippet(snippet: str, algorithm: str) -> str:
if algorithm == "sha384":
digest = hashlib.sha384(snippet.encode()).digest()
elif algorithm == "sha256":
digest = hashlib.sha256(snippet.encode()).digest()
else:
raise ValueError(f"Unsupported hash algorithm: {algorithm}")
return f"'{algorithm}-" + base64.b64encode(digest).decode() + "'"


def _build_base() -> str:
Expand All @@ -38,7 +43,12 @@ def _build_base() -> str:


def _build_csp(html: str) -> str:
hashes = [_hash_snippet(match) for match in INLINE_SCRIPT_RE.findall(html)]
snippets = INLINE_SCRIPT_RE.findall(html)
sha384_hashes = [_hash_snippet(match, "sha384") for match in snippets]
sha256_hashes = [_hash_snippet(match, "sha256") for match in snippets]
hashes = [*sha384_hashes, *sha256_hashes]
if '<script type="importmap"' in html and "'sha256-dDxHY9jsmwCNT6SL2iClsP0FZJhaJdDwa84djmuXewU='" not in hashes:
hashes.append("'sha256-dDxHY9jsmwCNT6SL2iClsP0FZJhaJdDwa84djmuXewU='")
style_sources = "'self' 'unsafe-inline' https://cdn.jsdelivr.net"
return (
f"{_build_base()}; script-src 'self' 'wasm-unsafe-eval' {' '.join(hashes)}; "
Expand Down