feat: partner enrichment, mutations, settings & branding + operator quick-wins

Backend (platform-api): computed tenant health plus industry/brandColor; partner-scoped tenant update/suspend/resume guarded by assertPartnerOwnsTenant; enriched partner users (MFA + access level) with invite/remove; partner settings and whitelabel branding persistence; Authentik authenticator counting and group removal. Audit on every mutation.

Frontend (portal): all five partner pages on real data — dashboard alerts, customers edit/suspend, team MFA/access with invite/remove, editable settings, branding fetch/save.

Operator: dashboard and infrastructure service health driven by real liveness probes; fabricated uptime/p95/error-rate removed.
This commit is contained in:
Ronni Baslund
2026-05-30 08:03:07 +02:00
parent a51dc9a732
commit 89691626f4
33 changed files with 1753 additions and 198 deletions
+4 -5
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { INCIDENT, PLANNED_SERVICES } from '~/data/fixtures'
import { PLANNED_SERVICES } from '~/data/fixtures'
// Shape returned by /api/health/platform on platform-api.
interface ProbeResult {
@@ -72,13 +72,12 @@ function label(p: ProbeResult) {
<div v-if="incidentActive" class="incident">
<span class="pill">
<span class="dot" />
{{ INCIDENT.severity }} · ACTIVE
DEGRADED
</span>
<div class="body">
<div class="title">{{ INCIDENT.title }}</div>
<div class="sub">{{ degradedCount }} service(s) reporting non-ok status · IC: {{ INCIDENT.ic }}</div>
<div class="title">{{ degradedCount }} service(s) reporting non-ok status</div>
<div class="sub">{{ (probes ?? []).filter((p) => p.status !== 'ok').map((p) => p.name).join(', ') }}</div>
</div>
<UiButton variant="primary" disabled>Open incident</UiButton>
</div>
<Eyebrow class="section-head">Live · {{ totalCount }} services</Eyebrow>