From 015f9c3ad475f0daaa5c7e79cdb44894a013bffe Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sun, 9 Aug 2026 20:32:16 -0400 Subject: [PATCH] fix(site): move the demo module out of the page to satisfy CSP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit script-src 'self' with no 'unsafe-inline' blocks inline module scripts, so the demo initialized nothing on the deployed site while working perfectly locally — the dev server sends no CSP, so only the real deployment showed it. Extracted to assets/demo.js rather than relaxing the policy. Loosening CSP for a page that renders moderation decisions would be the wrong trade. --- .gitignore | 2 + packages/site/public/assets/demo.js | 152 +++++++++++++++++++++++++++ packages/site/public/demo.html | 155 +--------------------------- 3 files changed, 155 insertions(+), 154 deletions(-) create mode 100644 packages/site/public/assets/demo.js diff --git a/.gitignore b/.gitignore index 0bc3d78..92202c2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ coverage/ # Built site output (Vercel builds it) packages/site/dist/ +.vercel +.env* diff --git a/packages/site/public/assets/demo.js b/packages/site/public/assets/demo.js new file mode 100644 index 0000000..0bed273 --- /dev/null +++ b/packages/site/public/assets/demo.js @@ -0,0 +1,152 @@ +import { + createBitGate, + createMemoryTransport, + defineBitGateElements, + COMMERCE_POLICY, + } from "../vendor/bitgate/bitgate.js"; + + defineBitGateElements(); + + const key = (seed) => seed.repeat(64).slice(0, 64); + const ROOT = key("a1"); + const LISTING_MOD = key("b2"); + const SELLER_MOD = key("c3"); + const SELLER = key("d4"); + const SHOPPER = key("e5"); + const NOW = Math.floor(Date.now() / 1000); + const trusted = (index) => key(index.toString(16).padStart(2, "0")); + + const TARGET = { type: "address", kind: "30078", pubkey: SELLER, identifier: "sku-001" }; + const TARGET_KEY = `address:30078:${SELLER}:sku-001`; + const PROFILES = ["browse", "detail", "checkout", "seller-dashboard"]; + const VIEWERS = { shopper: SHOPPER, listing: LISTING_MOD, seller: SELLER_MOD }; + + // An in-memory transport keeps the demo deterministic: nothing is fetched and + // nothing is published, so it works offline and cannot touch real relays. + const runtime = createBitGate({ + applicationId: "bitgate-demo", + namespace: "demo", + root: ROOT, + transport: createMemoryTransport(), + policy: COMMERCE_POLICY, + now: () => NOW, + }); + + const COMMERCE_ROLES = { + listing_moderator: ["contribute-event-deny", "contribute-address-deny", "review-evidence"], + seller_moderator: ["contribute-user-deny", "review-evidence"], + super_admin: [ + "manage-roles", "manage-policy", "manage-community-sources", + "contribute-user-allow", "contribute-user-deny", "contribute-event-deny", + "contribute-address-deny", "contribute-trust-seed", "review-evidence", + ], + }; + + let reportCount = 0; + let muteCount = 0; + + function seedRoster() { + runtime.admin.setRoles({ + root: ROOT, + roles: COMMERCE_ROLES, + actors: { + [ROOT]: ["super_admin"], + [LISTING_MOD]: ["listing_moderator"], + [SELLER_MOD]: ["seller_moderator"], + }, + }); + } + + function setViewer(name) { + runtime.setViewer(VIEWERS[name]); + // Viewer switching clears viewer-scoped state by design, so trust is + // re-seeded afterwards — the same order a real integration must use. + runtime.trust.setContacts(Array.from({ length: 24 }, (_, i) => trusted(i + 1))); + } + + function reset() { + reportCount = 0; + muteCount = 0; + runtime.reports.clearTarget(TARGET_KEY); + runtime.mutes.lists.clear(); + runtime.admin.setContributions([]); + seedRoster(); + setViewer("shopper"); + runtime.invalidateDecisions(); + render(); + } + + const veil = document.getElementById("veil"); + const caps = document.getElementById("caps"); + veil.runtime = runtime; + veil.target = TARGET; + caps.runtime = runtime; + + function render() { + const body = document.querySelector("#surfaces tbody"); + body.innerHTML = PROFILES.map((profile) => { + const decision = runtime.evaluate(TARGET, { profile }); + const transaction = decision.transaction?.effect ?? "allow"; + return `
${profile}${id}