feat: Passwordless cross-device authentication

- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
This commit is contained in:
Bernt
2026-07-07 07:11:50 +00:00
parent 4aa984ad74
commit 6989a98d75
61843 changed files with 5491611 additions and 872231 deletions
+32 -32
View File
@@ -65,7 +65,7 @@
a { color: inherit; text-decoration: none; }
/* ── NAV ── */
/* NAV */
nav {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
display: flex; align-items: center; justify-content: space-between;
@@ -117,7 +117,7 @@
.btn-outline:hover { background: rgba(0,0,0,0.04); transform: translateY(-1px); }
.btn-lg { padding: 14px 30px; font-size: 16px; border-radius: var(--radius-md); }
/* ── HERO ── */
/* HERO */
.hero {
min-height: 60vh;
display: flex; flex-direction: column; align-items: center; justify-content: center;
@@ -168,7 +168,7 @@
margin-bottom: 40px;
}
/* ── TRUST BADGES ── */
/* TRUST BADGES */
.trust-bar {
display: flex; gap: 32px; flex-wrap: wrap; justify-content: center;
padding: 40px 24px;
@@ -192,7 +192,7 @@
flex-shrink: 0;
}
/* ── SECTION COMMON ── */
/* SECTION COMMON */
section { padding: 88px 24px; }
.container { max-width: 1100px; margin: 0 auto; }
@@ -218,7 +218,7 @@
line-height: 1.7;
}
/* ── SECURITY GRID ── */
/* SECURITY GRID */
.security-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
@@ -275,7 +275,7 @@
}
.security-items li::before {
content: '';
content: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
color: var(--green);
font-weight: 800;
font-size: 14px;
@@ -283,7 +283,7 @@
flex-shrink: 0;
}
/* ── ENTERPRISE CTA ── */
/* ENTERPRISE CTA */
.enterprise-block {
background: var(--surface);
border: 1px solid var(--border);
@@ -318,7 +318,7 @@
.enterprise-block .contact-item strong { color: #1d1d1f; }
/* ── COMPLIANCE STRIP ── */
/* COMPLIANCE STRIP */
.compliance-strip {
background: rgba(0,102,255,0.04);
border: 1px solid rgba(0,102,255,0.12);
@@ -334,7 +334,7 @@
.compliance-badge .dot {
width: 8px; height: 8px;
background: var(--green);
border-radius: 50%;
border-radius: var(--radius-full);
box-shadow: 0 0 6px rgba(34,197,94,0.6);
flex-shrink: 0;
}
@@ -349,7 +349,7 @@
flex-shrink: 0;
}
/* ── FOOTER ── */
/* FOOTER */
footer {
border-top: 1px solid var(--border);
padding: 40px 40px;
@@ -372,13 +372,13 @@
.footer-social {
width: 32px; height: 32px;
border: 1px solid var(--border);
border-radius: 8px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
transition: border-color 0.2s, background 0.2s;
}
.footer-social:hover { border-color: rgba(0,0,0,0.25); background: rgba(0,0,0,0.04); }
/* ── RESPONSIVE ── */
/* RESPONSIVE */
@media (max-width: 900px) {
nav { padding: 0 20px; }
.nav-links { display: none; }
@@ -451,7 +451,7 @@
<!-- HERO -->
<section class="hero">
<div class="hero-eyebrow">🔒 Enterprise Security</div>
<div class="hero-eyebrow"> Enterprise Security</div>
<h1>Built secure<br>from the ground up.</h1>
<p class="hero-sub">LandveX runs on AWS infrastructure in Stockholm, with end-to-end encryption, verified identity chains, and GDPR-compliant data handling — designed for organisations that demand it.</p>
<div style="display:flex;gap:14px;flex-wrap:wrap;justify-content:center">
@@ -463,15 +463,15 @@
<!-- TRUST BAR -->
<div class="trust-bar">
<div class="trust-item">
<div class="icon">🔐</div>
<div class="icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="7" width="10" height="7" rx="1" stroke="#666" stroke-width="1.5"/><path d="M5 7V5C5 3.3 6.3 2 8 2C9.7 2 11 3.3 11 5V7" stroke="#666" stroke-width="1.5"/><circle cx="8" cy="10.5" r="1" fill="#666"/></svg></div>
AES-256 at rest
</div>
<div class="trust-item">
<div class="icon">🔒</div>
<div class="icon"></div>
TLS 1.2+ in transit
</div>
<div class="trust-item">
<div class="icon">🇪🇺</div>
<div class="icon"></div>
EU data residency
</div>
<div class="trust-item">
@@ -479,11 +479,11 @@
GDPR compliant
</div>
<div class="trust-item">
<div class="icon">🏛️</div>
<div class="icon"></div>
Hosted on AWS SOC 2 Type II infrastructure
</div>
<div class="trust-item">
<div class="icon">🛡️</div>
<div class="icon"></div>
ISO 27001-certified infrastructure (AWS)
</div>
</div>
@@ -502,7 +502,7 @@
<!-- Data Security -->
<div class="security-card" style="cursor:pointer;" onclick="location.href='#contact'" role="button" tabindex="0">
<div class="card-header">
<div class="card-icon">🔐</div>
<div class="card-icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="7" width="10" height="7" rx="1" stroke="#666" stroke-width="1.5"/><path d="M5 7V5C5 3.3 6.3 2 8 2C9.7 2 11 3.3 11 5V7" stroke="#666" stroke-width="1.5"/><circle cx="8" cy="10.5" r="1" fill="#666"/></svg></div>
<div class="card-title-wrap">
<h2>Data Security</h2>
<p>Encryption end-to-end, always</p>
@@ -520,7 +520,7 @@
<!-- Identity & Access -->
<div class="security-card" style="cursor:pointer;" onclick="location.href='#contact'" role="button" tabindex="0">
<div class="card-header">
<div class="card-icon">🪪</div>
<div class="card-icon"></div>
<div class="card-title-wrap">
<h2>Identity &amp; Access</h2>
<p>Verified identities, least-privilege access</p>
@@ -537,7 +537,7 @@
<!-- Data Integrity -->
<div class="security-card" style="cursor:pointer;" onclick="location.href='#contact'" role="button" tabindex="0">
<div class="card-header">
<div class="card-icon">🔗</div>
<div class="card-icon"></div>
<div class="card-title-wrap">
<h2>Data Integrity</h2>
<p>Tamper-evident submission chain</p>
@@ -553,7 +553,7 @@
<!-- Privacy & Compliance -->
<div class="security-card" style="cursor:pointer;" onclick="location.href='#contact'" role="button" tabindex="0">
<div class="card-header">
<div class="card-icon">🇪🇺</div>
<div class="card-icon"></div>
<div class="card-title-wrap">
<h2>Privacy &amp; Compliance</h2>
<p>GDPR by design, not as an afterthought</p>
@@ -570,7 +570,7 @@
<!-- Operational Security -->
<div class="security-card" style="cursor:pointer;" onclick="location.href='#contact'" role="button" tabindex="0">
<div class="card-header">
<div class="card-icon">⚙️</div>
<div class="card-icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" stroke="#666" stroke-width="1.5"/><path d="M8 2V4M8 12V14M2 8H4M12 8H14M4.3 4.3L5.7 5.7M10.3 10.3L11.7 11.7M4.3 11.7L5.7 10.3M10.3 5.7L11.7 4.3" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg></div>
<div class="card-title-wrap">
<h2>Operational Security</h2>
<p>Hardened, monitored, incident-ready</p>
@@ -586,7 +586,7 @@
<!-- Enterprise -->
<div class="security-card" style="cursor:pointer;border-color:rgba(0,102,255,0.18);background:rgba(0,102,255,0.04)" onclick="location.href='#contact'" role="button" tabindex="0">
<div class="card-header">
<div class="card-icon" style="background:var(--blue-glow);border-color:rgba(0,102,255,0.25)">🏢</div>
<div class="card-icon" style="background:var(--blue-glow);border-color:rgba(0,102,255,0.25)"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="2" width="10" height="12" rx="1" stroke="#666" stroke-width="1.5"/><path d="M6 5H7M6 8H7M6 11H7M9 5H10M9 8H10M9 11H10" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg></div>
<div class="card-title-wrap">
<h2>Enterprise</h2>
<p>Agreements, questionnaires, direct contact</p>
@@ -648,15 +648,15 @@
<p>Procurement, legal, or IT security teams with questions about the Landvex platform can contact our security team directly. We respond to all questionnaires within 5 business days.</p>
<div style="margin-top:28px;display:flex;flex-direction:column;gap:10px">
<div class="contact-item">
<span style="font-size:16px">📧</span>
<span style="font-size:16px"></span>
<span>Security team: <strong><a href="mailto:security@landvex.com" style="color:#5599ff">security@landvex.com</a></strong></span>
</div>
<div class="contact-item">
<span style="font-size:16px">📄</span>
<span style="font-size:16px"></span>
<span>DPA available on request</span>
</div>
<div class="contact-item">
<span style="font-size:16px"></span>
<span style="font-size:16px"></span>
<span>Questionnaire SLA: <strong>5 business days</strong></span>
</div>
</div>
@@ -678,25 +678,25 @@
We respond within one business day.
</p>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px">
<div style="border:1px solid #e5e7eb;border-radius:8px;padding:14px 16px">
<div style="border:1px solid #e5e7eb;border-radius: var(--radius-md);padding:14px 16px">
<div style="font-weight:700;font-size:.875rem;margin-bottom:4px">Penetration test summary</div>
<div style="font-size:.8rem;color:#aaa">Most recent external pen test — under NDA</div>
</div>
<div style="border:1px solid #e5e7eb;border-radius:8px;padding:14px 16px">
<div style="border:1px solid #e5e7eb;border-radius: var(--radius-md);padding:14px 16px">
<div style="font-weight:700;font-size:.875rem;margin-bottom:4px">AWS compliance reports</div>
<div style="font-size:.8rem;color:#aaa">SOC 2 Type II + ISO 27001 (AWS infrastructure)</div>
</div>
<div style="border:1px solid #e5e7eb;border-radius:8px;padding:14px 16px">
<div style="border:1px solid #e5e7eb;border-radius: var(--radius-md);padding:14px 16px">
<div style="font-weight:700;font-size:.875rem;margin-bottom:4px">CAIQ / SIG questionnaire</div>
<div style="font-size:.8rem;color:#aaa">Pre-filled security assessment on request</div>
</div>
<div style="border:1px solid #e5e7eb;border-radius:8px;padding:14px 16px">
<div style="border:1px solid #e5e7eb;border-radius: var(--radius-md);padding:14px 16px">
<div style="font-weight:700;font-size:.875rem;margin-bottom:4px">Data Processing Agreement</div>
<div style="font-size:.8rem;color:#aaa"><a href="/dpa" style="color:#2563eb">View DPA →</a></div>
</div>
</div>
<a href="mailto:security@landvex.com?subject=Security%20documentation%20request"
style="display:inline-block;background:#0a1628;color: #1d1d1f;padding:10px 20px;border-radius:8px;font-size:.875rem;font-weight:700;text-decoration:none">
style="display:inline-block;background:#0a1628;color: #1d1d1f;padding:10px 20px;border-radius: var(--radius-md);font-size:.875rem;font-weight:700;text-decoration:none">
Request documentation →
</a>
<p style="font-size:.75rem;color:#aaa;margin-top:10px">