Release v1.7.18: fix Alpine.js SRI + CSP, add frontend modernization roadmap
Release / build-and-push (push) Successful in 1m23s
CI / lint-and-test (push) Successful in 1m22s

- Revert @alpinejs/csp (CSP build has no support for template literals,
  optional chaining, or x-html — all used in the app template); switch
  back to the regular alpinejs build
- Pin Alpine.js to 3.15.12 with a verified SRI hash (replaces the
  floating @3.x.x tag that caused the integrity check failure)
- Restore 'unsafe-eval' to script-src (required by Alpine.js's
  new Function() expression evaluator; inline script was already
  eliminated in v1.7.17 so 'unsafe-inline' stays removed)
- Add Phase 7.5 Frontend Modernization to ROADMAP: Vue 3 + Vite
  migration plan that will allow a clean CSP without unsafe-eval

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 08:01:57 +02:00
parent 79647d8962
commit 7639f5f69d
4 changed files with 33 additions and 3 deletions
+30
View File
@@ -95,6 +95,36 @@ Goal: address penetration test findings and threat model gaps.
---
## Phase 7.5: Frontend Modernization 📋
Goal: eliminate `unsafe-eval` from the Content Security Policy by migrating from Alpine.js to a compiled frontend framework.
Status: **Planned**. Current Alpine.js requires `unsafe-eval` because it uses `new Function()` to evaluate attribute expressions at runtime. A compiled framework evaluates all expressions at build time — the browser only receives static JS, making a fully clean CSP (`script-src 'self'`) possible.
### Recommended approach: Vue 3 + Vite
Alpine.js was inspired by Vue, so the migration is largely mechanical:
| Alpine.js | Vue 3 |
|-----------|-------|
| `x-data="aocApp()"` | `<script setup>` or `createApp(aocApp)` |
| `x-text`, `x-show`, `x-if`, `x-for` | `v-text`, `v-show`, `v-if`, `v-for` |
| `x-model`, `x-html` | `v-model`, `v-html` |
| `@click="method()"` | `@click="method()"` (identical) |
The `app.js` logic (`aocApp()` function body, ~820 lines) translates almost directly.
The CDN dependencies on `cdn.jsdelivr.net` and `alcdn.msauth.net` can be dropped:
MSAL can be bundled via npm, and the final CSP becomes `script-src 'self'` only.
### Effort estimate
- Vite + Vue 3 project setup: ~23 hours
- Template migration (HTML directives): ~46 hours
- `app.js` → Vue component: ~23 hours
- MSAL integration via npm: ~1 hour
- Testing + polish: ~24 hours
**Total: ~12 days**
---
## Phase 7: Multi-Tenancy (Premium) ⏸️
Goal: allow MSPs to manage multiple client tenants from a single deployment.
+1 -1
View File
@@ -1 +1 @@
1.7.17
1.7.18
+1 -1
View File
@@ -6,7 +6,7 @@
<title>Admin Operations Center</title>
<link rel="stylesheet" href="/style.css?v=15" />
<script src="/app.js?v=1"></script>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.15.12/dist/cdn.min.js" integrity="sha384-MKLWq9B+VC0W3U8kDIBEsSu8uCnQ1B0UQpRaB+F7uR5ocXFbymMUKuLRntu5LLdu" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.15.12/dist/cdn.min.js" integrity="sha384-pb6hrQvo4s23cEUFtj0CZkzGE3jyK3pj26RIupXXxhSrrcUA/Cn0lZgcCrGH0t6L" crossorigin="anonymous"></script>
<script src="https://alcdn.msauth.net/browser/2.37.0/js/msal-browser.min.js" integrity="sha384-DUSOaqAzlZRiZxkDi8hL7hXJDZ+X39ZOAYV9ZDx44gUv9pozmcunJH02tjSFLPnW" crossorigin="anonymous"></script>
</head>
<body>
+1 -1
View File
@@ -112,7 +112,7 @@ async def security_headers_middleware(request: Request, call_next):
if request.url.path.startswith("/api/") or request.url.path in ("/", "/index.html"):
response.headers["Content-Security-Policy"] = (
"default-src 'self'; "
"script-src 'self' cdn.jsdelivr.net alcdn.msauth.net; "
"script-src 'self' 'unsafe-eval' cdn.jsdelivr.net alcdn.msauth.net; "
"style-src 'self' 'unsafe-inline'; "
"connect-src 'self' https://login.microsoftonline.com; "
"frame-src 'self' https://login.microsoftonline.com; "