Basis: Certvia dev@a48c5fb als Fundament für Craftvia
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s

Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation
und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 11:05:39 +02:00
co-authored by Claude Opus 5
commit c8e6f30a27
720 changed files with 140143 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
import { redirect } from "next/navigation";
import { auth } from "@/server/auth";
import { dbForTenant, prisma } from "@/server/db";
import { resolvePasswordPolicy, describePasswordPolicy } from "@/lib/password-policy";
import { ForcePasswordChangeForm } from "@/components/force-password-change-form";
import { CertviaLogo } from "@/components/brand/certvia-logo";
/**
* Erzwungener Passwortwechsel beim ersten Login (Force-Change). Liegt außerhalb der
* (app)-Shell, damit deren Guard nicht in eine Weiterleitungsschleife läuft.
*/
export default async function ChangePasswordPage() {
const session = await auth();
if (!session?.user) redirect("/login");
const db = dbForTenant(session.user.tenantId);
// Option C (WS4): mustChangePassword gehört der GLOBALEN Identity.
const identityId = session.user.identityId;
if (!identityId) redirect("/login");
const [identity, settings] = await Promise.all([
prisma.identity.findUnique({ where: { id: identityId }, select: { mustChangePassword: true } }),
db.tenantSettings.findUnique({ where: { tenantId: session.user.tenantId } }),
]);
// Wer keinen Wechsel (mehr) schuldet, wird zur App durchgereicht.
if (!identity?.mustChangePassword) redirect("/dashboard");
const hint = describePasswordPolicy(resolvePasswordPolicy(settings?.securityPolicy));
return (
<main className="flex flex-1 items-center justify-center p-6">
<div className="shadow-card w-full max-w-sm rounded-2xl border bg-card p-8">
<CertviaLogo variant="lockup" theme="dark" height={34} />
<p className="mt-5 font-heading text-lg font-semibold">Passwort ändern</p>
<p className="mt-1 text-sm text-muted-foreground">
Ihr Konto wurde mit einem Initialpasswort angelegt. Bitte vergeben Sie jetzt ein eigenes Passwort, um fortzufahren.
</p>
<div className="mt-6">
<ForcePasswordChangeForm policyHint={hint} />
</div>
</div>
</main>
);
}