Compare commits

..

5 Commits

Author SHA1 Message Date
will.anderson d2ae0b4b60 Fix SyntaxError in account-dashboard and expand CSP
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m37s
Replace ternary operator in native_js block with explicit if-else —
El's parser chokes on '?' adjacent to single-quoted strings inside
native_js(), causing an Uncaught SyntaxError that prevents the entire
IIFE from running and leaves signInWith undefined.

Add missing CSP entries to all three header functions:
- js.stripe.com → script-src and frame-src (Stripe JS and Elements iframe)
- fonts.googleapis.com → style-src (Google Fonts CSS)
- fonts.gstatic.com → font-src (Google Fonts files)
- static.cloudflareinsights.com → script-src (Cloudflare beacon)
2026-05-19 12:13:05 -05:00
will.anderson bfcb325352 Clear hardcoded device count — JS sets it from plan data
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m54s
2026-05-14 11:38:05 -05:00
will.anderson 57e9cafc95 Merge pull request 'Fix device count: 1 for free, 2 for professional/founding' (#148) from fix/devices-count into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m13s
2026-05-14 16:36:20 +00:00
will.anderson 632d95000c Fix device count: show 1 for free plan, 2 for professional/founding
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m38s
2026-05-14 11:36:02 -05:00
will.anderson 77807d30af Merge pull request 'Fix account SIGSEGV: el_meta 1-arg → 2-arg' (#146) from fix/account-el-meta into dev
Dev — Build & local smoke test / build-smoke (push) Successful in 2m13s
2026-05-13 17:41:53 +00:00
3 changed files with 11 additions and 4 deletions
+1 -1
View File
@@ -818,7 +818,7 @@ fn account_devices_card() -> String {
el_div("class=\"device-icon\"", account_signin_svg_device()) +
el_div(
"",
el_p("class=\"devices-count\"", "2 devices included with your plan") +
el_p("class=\"devices-count\" id=\"devices-count-el\"", "") +
el_p("class=\"devices-sub\"", "Currently: Setup at launch")
)
) +
+7
View File
@@ -103,6 +103,13 @@ fn main() -> Void {
}
setHtml('plan-billing-note-el', billingNote);
var devicesEl = document.getElementById('devices-count-el');
if (devicesEl) {
var deviceText = '2 devices included with your plan';
if (plan === 'free') { deviceText = '1 device included with your plan'; }
devicesEl.textContent = deviceText;
}
var meta = '';
if (createdAt) {
var d = new Date(createdAt);
+3 -3
View File
@@ -2317,7 +2317,7 @@ fn sec_headers_json() -> String {
+ "\"X-Frame-Options\":\"SAMEORIGIN\","
+ "\"Referrer-Policy\":\"strict-origin-when-cross-origin\","
+ "\"Permissions-Policy\":\"geolocation=(), microphone=(), camera=()\","
+ "\"Content-Security-Policy\":\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; frame-src https://challenges.cloudflare.com; connect-src 'self' https://api.stripe.com https://*.supabase.co; img-src 'self' data: https:; font-src 'self' data:\"}"
+ "\"Content-Security-Policy\":\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://js.stripe.com https://static.cloudflareinsights.com https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; frame-src https://challenges.cloudflare.com https://js.stripe.com; connect-src 'self' https://api.stripe.com https://*.supabase.co; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com\"}"
}
// Headers for compiled JS assets. Explicitly sets Content-Type so the browser
@@ -2333,7 +2333,7 @@ fn js_headers_json() -> String {
+ "\"X-Frame-Options\":\"SAMEORIGIN\","
+ "\"Referrer-Policy\":\"strict-origin-when-cross-origin\","
+ "\"Permissions-Policy\":\"geolocation=(), microphone=(), camera=()\","
+ "\"Content-Security-Policy\":\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; frame-src https://challenges.cloudflare.com; connect-src 'self' https://api.stripe.com https://*.supabase.co; img-src 'self' data: https:; font-src 'self' data:\"}"
+ "\"Content-Security-Policy\":\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://js.stripe.com https://static.cloudflareinsights.com https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; frame-src https://challenges.cloudflare.com https://js.stripe.com; connect-src 'self' https://api.stripe.com https://*.supabase.co; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com\"}"
}
// Headers for static assets under /assets/ and /brand/.
@@ -2349,7 +2349,7 @@ fn static_asset_headers_json() -> String {
+ "\"X-Frame-Options\":\"SAMEORIGIN\","
+ "\"Referrer-Policy\":\"strict-origin-when-cross-origin\","
+ "\"Permissions-Policy\":\"geolocation=(), microphone=(), camera=()\","
+ "\"Content-Security-Policy\":\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; frame-src https://challenges.cloudflare.com; connect-src 'self' https://api.stripe.com https://*.supabase.co; img-src 'self' data: https:; font-src 'self' data:\"}"
+ "\"Content-Security-Policy\":\"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://cdn.jsdelivr.net https://js.stripe.com https://static.cloudflareinsights.com https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; frame-src https://challenges.cloudflare.com https://js.stripe.com; connect-src 'self' https://api.stripe.com https://*.supabase.co; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com\"}"
}
fn handle_request(method: String, path: String, headers: Map, body: String) -> String {