Chore: Rebranding Gatehouse to Secuird (UI)

This commit is contained in:
2026-03-06 00:22:57 +05:45
parent 7be6415db1
commit 979b5a918e
27 changed files with 76 additions and 76 deletions

Before

Width:  |  Height:  |  Size: 661 B

After

Width:  |  Height:  |  Size: 661 B

@@ -1,21 +1,21 @@
import { cn } from "@/lib/utils";
interface GatehouseLogoProps {
interface SecuirdLogoProps {
size?: "sm" | "md" | "lg";
variant?: "default" | "light";
className?: string;
}
/**
* Gatehouse Logo - Abstract gate/doorway mark
* Secuird Logo - Abstract gate/doorway mark
* Represents controlled entry and policy enforcement
* Two vertical pillars forming a gateway with negative space
*/
export function GatehouseLogo({
export function SecuirdLogo({
size = "md",
variant = "default",
className
}: GatehouseLogoProps) {
}: SecuirdLogoProps) {
const sizeClasses = {
sm: "w-8 h-8",
md: "w-9 h-9",
+6 -6
View File
@@ -65,9 +65,9 @@ const isDev = import.meta.env.DEV;
const originalFetch = window.fetch;
// Avoid patching multiple times during HMR
const globalAny = window as unknown as { __gatehouseFetchPatched?: boolean };
if (isDev && !globalAny.__gatehouseFetchPatched) {
globalAny.__gatehouseFetchPatched = true;
const globalAny = window as unknown as { __secuirdFetchPatched?: boolean };
if (isDev && !globalAny.__secuirdFetchPatched) {
globalAny.__secuirdFetchPatched = true;
try {
window.fetch = async function (input, init) {
@@ -165,9 +165,9 @@ if (isDev && !globalAny.__gatehouseFetchPatched) {
};
} catch (patchError) {
// Log any errors during fetch patching with full stack trace
console.error("[Gatehouse DevTools] Failed to patch fetch:", patchError);
console.error("[Secuird DevTools] Failed to patch fetch:", patchError);
if (patchError instanceof Error) {
console.error("[Gatehouse DevTools] Stack trace:", patchError.stack);
console.error("[Secuird DevTools] Stack trace:", patchError.stack);
}
}
}
@@ -220,7 +220,7 @@ export default function ApiDevTools() {
{/* Header */}
<div className="flex items-center justify-between px-4 py-2 border-b border-slate-700 bg-slate-800">
<div className="flex items-center gap-3">
<span className="font-semibold text-sm">Gatehouse API DevTools</span>
<span className="font-semibold text-sm">Secuird API DevTools</span>
<Badge variant="outline" className="text-xs border-slate-600">
{logs.length} requests
</Badge>
@@ -97,7 +97,7 @@ export default function MfaEnforcementLayout() {
<header className="h-14 border-b border-border bg-card flex items-center justify-between px-4 flex-shrink-0">
<div className="flex items-center gap-3">
<Shield className="w-5 h-5 text-primary" />
<span className="font-semibold text-foreground">Gatehouse</span>
<span className="font-semibold text-foreground">Secuird</span>
</div>
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground">
+4 -4
View File
@@ -1,5 +1,5 @@
import { Outlet, Link } from "react-router-dom";
import { GatehouseLogo } from "@/components/branding/GatehouseLogo";
import { SecuirdLogo } from "@/components/branding/SecuirdLogo";
export default function PublicLayout() {
return (
@@ -11,8 +11,8 @@ export default function PublicLayout() {
<header className="relative z-10 w-full py-6 px-4">
<div className="max-w-md mx-auto">
<Link to="/" className="flex items-center gap-2.5 justify-center">
<GatehouseLogo size="md" />
<span className="text-xl font-semibold text-foreground tracking-tight">Gatehouse</span>
<SecuirdLogo size="md" />
<span className="text-xl font-semibold text-foreground tracking-tight">Secuird</span>
</Link>
</div>
</header>
@@ -28,7 +28,7 @@ export default function PublicLayout() {
<footer className="relative z-10 py-6 px-4">
<div className="max-w-md mx-auto text-center">
<p className="text-sm text-muted-foreground">
© {new Date().getFullYear()} Gatehouse. Identity & Access.
© {new Date().getFullYear()} Secuird. Identity & Access.
</p>
</div>
</footer>
+3 -3
View File
@@ -18,7 +18,7 @@ import {
Monitor,
ShieldAlert,
} from "lucide-react";
import { GatehouseLogo } from "@/components/branding/GatehouseLogo";
import { SecuirdLogo } from "@/components/branding/SecuirdLogo";
import { NavLink } from "@/components/NavLink";
import { useAuth } from "@/contexts/AuthContext";
import {
@@ -90,10 +90,10 @@ export function AppSidebar() {
{/* Logo */}
<SidebarHeader className="p-4 border-b border-sidebar-border">
<div className="flex items-center gap-3">
<GatehouseLogo size="sm" variant="light" />
<SecuirdLogo size="sm" variant="light" />
{!collapsed && (
<span className="text-lg font-semibold text-sidebar-foreground tracking-tight">
Gatehouse
Secuird
</span>
)}
</div>
@@ -275,7 +275,7 @@ export function TotpEnrollmentWizard({
</div>
<p className="text-xs text-muted-foreground">
Open your authenticator app and enter the 6-digit code shown for Gatehouse.
Open your authenticator app and enter the 6-digit code shown for Secuird.
</p>
<div className="flex justify-end gap-2 pt-2">
+2 -2
View File
@@ -1,4 +1,4 @@
// Gatehouse Configuration
// Secuird Configuration
// Environment-specific settings for the application
export const config = {
@@ -9,7 +9,7 @@ export const config = {
// App metadata
app: {
name: "Gatehouse",
name: "Secuird",
description: "Identity & Access Platform",
},
+1 -1
View File
@@ -32,7 +32,7 @@ interface AuthContextType {
const AuthContext = createContext<AuthContextType | null>(null);
// LocalStorage key for MFA compliance persistence
const MFA_COMPLIANCE_KEY = 'gatehouse_mfa_compliance';
const MFA_COMPLIANCE_KEY = 'secuird_mfa_compliance';
// Helper to persist MFA compliance to localStorage
function persistMfaCompliance(compliance: MfaComplianceSummary | null): void {
+1 -1
View File
@@ -4,7 +4,7 @@
@tailwind components;
@tailwind utilities;
/* Gatehouse Design System - Enterprise Identity & Access Platform
/* Secuird Design System - Enterprise Identity & Access Platform
Authoritative, infrastructure-grade aesthetic with slate/charcoal/muted blue palette
Colors are HSL for theming flexibility
*/
+3 -3
View File
@@ -1,4 +1,4 @@
// API Client for Gatehouse Backend
// API Client for Secuird Backend
// Uses Bearer token authentication
import { config } from '@/config';
@@ -259,8 +259,8 @@ class ApiError extends Error {
}
// Token storage keys
const TOKEN_KEY = 'gatehouse_token';
const TOKEN_EXPIRY_KEY = 'gatehouse_token_expiry';
const TOKEN_KEY = 'secuird_token';
const TOKEN_EXPIRY_KEY = 'secuird_token_expiry';
// Token management
export const tokenManager = {
+2 -2
View File
@@ -3,7 +3,7 @@ import { useSearchParams, useNavigate } from "react-router-dom";
import { CheckCircle, XCircle, Loader2, Mail } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { GatehouseLogo } from "@/components/branding/GatehouseLogo";
import { SecuirdLogo } from "@/components/branding/SecuirdLogo";
import { api, ApiError } from "@/lib/api";
type Status = "loading" | "success" | "error" | "missing";
@@ -42,7 +42,7 @@ export default function ActivatePage() {
<div className="w-full max-w-md space-y-6">
{/* Logo */}
<div className="flex justify-center">
<GatehouseLogo size="md" />
<SecuirdLogo size="md" />
</div>
<Card>
+2 -2
View File
@@ -61,7 +61,7 @@ export default function InviteAcceptPage() {
const result = await api.invites.accept(token, name || undefined, inviteData?.user_exists ? undefined : password);
if (result.token) {
// Store the token manually since we're not using the normal login flow
localStorage.setItem("gatehouse_token", result.token);
localStorage.setItem("secuird_token", result.token);
}
navigate("/profile");
} catch (err: unknown) {
@@ -127,7 +127,7 @@ export default function InviteAcceptPage() {
<CheckCircle className="w-5 h-5 text-accent flex-shrink-0 mt-0.5" />
<div className="text-sm">
<p className="font-medium text-foreground">Account found</p>
<p className="text-muted-foreground">You already have a Gatehouse account. Click below to join the organization.</p>
<p className="text-muted-foreground">You already have a Secuird account. Click below to join the organization.</p>
</div>
</div>
) : (
+14 -14
View File
@@ -27,8 +27,8 @@ import { OAuthProvider } from "@/lib/oauth";
type LoginStep = 'credentials' | 'totp' | 'webauthn' | 'passkey-email' | 'mfa-enrollment' | 'mfa';
const GATEHOUSE_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
const SECUIRD_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
const SECUIRD_OIDC = SECUIRD_API.replace(/\/api\/v1\/?$/, '');
/**
* Complete an OIDC authorization flow after the user has authenticated.
@@ -36,7 +36,7 @@ const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
* the auth code and returns the redirect URL for the calling application.
*/
async function completeOidcFlow(oidcSessionId: string, token: string): Promise<string> {
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
@@ -64,13 +64,13 @@ export default function LoginPage() {
const [mfaToken, setMfaToken] = useState<string | null>(null);
// OIDC bridge: if oidc_session_id is in the URL, we're acting as the
// login UI for an OIDC authorization flow (e.g. SecuIRD → Gatehouse).
// login UI for an OIDC authorization flow (e.g. SecuIRD → Secuird).
// After successful login, call /oidc/complete and redirect to the client app.
const oidcSessionId = searchParams.get('oidc_session_id');
const oidcError = searchParams.get('error');
// CLI bridge: if cli_token or cli_redirect is present the login was triggered
// by the Gatehouse CLI tool. After successful auth the token is delivered
// by the Secuird CLI tool. After successful auth the token is delivered
// directly to the CLI's local callback server.
const cliToken = searchParams.get('cli_token');
const cliRedirectParam = searchParams.get('cli_redirect');
@@ -81,7 +81,7 @@ export default function LoginPage() {
useEffect(() => {
if (!cliToken || cliFetchedRef.current) return;
cliFetchedRef.current = true;
fetch(`${GATEHOUSE_API}/cli/redirect-url?token=${encodeURIComponent(cliToken)}`)
fetch(`${SECUIRD_API}/cli/redirect-url?token=${encodeURIComponent(cliToken)}`)
.then((r) => r.json())
.then((body) => {
if (body?.data?.redirect_url) {
@@ -165,7 +165,7 @@ export default function LoginPage() {
// MFA enrollment required - will be handled by ProtectedLayout
// Navigation happens in AuthContext (MFA path always navigates)
} else if (oidcSessionId) {
// OIDC bridge: send token back to the Gatehouse backend to complete the flow
// OIDC bridge: send token back to the Secuird backend to complete the flow
const token = tokenManager.getToken();
if (token) await finishOidcFlow(token);
} else if (cliRedirectUrl) {
@@ -176,7 +176,7 @@ export default function LoginPage() {
// Normal login: navigation already handled by AuthContext (skipNavigate=false)
} catch (error) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] Login failed:", error);
console.error("[Secuird] Login failed:", error);
}
const message = error instanceof ApiError
@@ -246,7 +246,7 @@ export default function LoginPage() {
}
} catch (error) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] MFA verification failed:", error);
console.error("[Secuird] MFA verification failed:", error);
}
const message = error instanceof ApiError
@@ -294,7 +294,7 @@ export default function LoginPage() {
// Normal login: navigation already handled by AuthContext (skipNavigate=false)
} catch (error) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] TOTP verification failed:", error);
console.error("[Secuird] TOTP verification failed:", error);
}
const message = error instanceof ApiError
@@ -363,7 +363,7 @@ export default function LoginPage() {
});
} catch (error) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] Passkey login failed:", error);
console.error("[Secuird] Passkey login failed:", error);
}
let message = "Failed to sign in with passkey";
@@ -438,7 +438,7 @@ export default function LoginPage() {
}
} catch (error) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] WebAuthn verification failed:", error);
console.error("[Secuird] WebAuthn verification failed:", error);
}
let message = "Failed to verify passkey";
@@ -518,7 +518,7 @@ export default function LoginPage() {
} catch (error) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] OAuth login failed:", error);
console.error("[Secuird] OAuth login failed:", error);
}
let message = `Failed to initiate ${provider} sign in`;
@@ -939,7 +939,7 @@ export default function LoginPage() {
</h1>
<p className="text-muted-foreground mt-2">
{cliRedirectUrl
? "Sign in to grant the Gatehouse CLI access to your account"
? "Sign in to grant the Secuird CLI access to your account"
: oidcSessionId
? "An application is requesting access to your account"
: "Sign in to your account to continue"}
+6 -6
View File
@@ -9,11 +9,11 @@ import { useToast } from "@/hooks/use-toast";
type CallbackState = 'loading' | 'success' | 'error';
const GATEHOUSE_API = (import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1') as string;
const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
const SECUIRD_API = (import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1') as string;
const SECUIRD_OIDC = SECUIRD_API.replace(/\/api\/v1\/?$/, '');
async function completeOidcFlow(oidcSessionId: string, token: string): Promise<string> {
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
@@ -24,7 +24,7 @@ async function completeOidcFlow(oidcSessionId: string, token: string): Promise<s
}
/**
* OAuth callback page that handles the redirect from the Gatehouse backend
* OAuth callback page that handles the redirect from the Secuird backend
* after a successful (or failed) OAuth provider authentication.
*
* The backend exchanges the provider code for a session token and then
@@ -134,7 +134,7 @@ export default function OAuthCallbackPage() {
return;
} catch (oidcErr) {
if (import.meta.env.DEV) {
console.error("[Gatehouse] OIDC completion failed after OAuth:", oidcErr);
console.error("[Secuird] OIDC completion failed after OAuth:", oidcErr);
}
// Fall through to normal flow on failure — user is still logged in
}
@@ -163,7 +163,7 @@ export default function OAuthCallbackPage() {
setStatus('error');
setError("Failed to load your profile. Please try signing in again.");
if (import.meta.env.DEV) {
console.error("[Gatehouse] OAuth callback refreshUser failed:", err);
console.error("[Secuird] OAuth callback refreshUser failed:", err);
}
}
};
+4 -4
View File
@@ -6,8 +6,8 @@ import { Card } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { tokenManager } from "@/lib/api";
const GATEHOUSE_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
const SECUIRD_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
const SECUIRD_OIDC = SECUIRD_API.replace(/\/api\/v1\/?$/, '');
const SCOPE_META: Record<string, { icon: typeof Shield; label: string; description: string }> = {
openid: { icon: Shield, label: "OpenID", description: "Verify your identity" },
@@ -41,7 +41,7 @@ export default function OIDCConsentPage() {
(async () => {
try {
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/begin`, {
const res = await fetch(`${SECUIRD_OIDC}/oidc/begin`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ oidc_session_id: oidcSessionId }),
@@ -67,7 +67,7 @@ export default function OIDCConsentPage() {
navigate(`/login?oidc_session_id=${context.oidc_session_id}`);
return;
}
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ oidc_session_id: context.oidc_session_id, token }),
+5 -5
View File
@@ -1,7 +1,7 @@
/**
* OIDCLoginPage — Standalone OIDC proxy login UI
*
* Unified entry point for OIDC authorization flows via the Gatehouse OIDC bridge.
* Unified entry point for OIDC authorization flows via the Secuird OIDC bridge.
* Handles:
* 1. Unauthenticated users → shows an email/password login form
* 2. Already-authenticated users → shows a consent/approval screen directly
@@ -9,7 +9,7 @@
* Route: /oidc-login?oidc_session_id=<id>
*
* Configure your oauth2-proxy / OIDC client's login_url to:
* https://<gatehouse-ui>/oidc-login
* https://<secuird-ui>/oidc-login
*/
import { useState, useEffect, useCallback } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
@@ -37,7 +37,7 @@ import { useAuth } from "@/contexts/AuthContext";
import { ApiError, tokenManager } from "@/lib/api";
// ── Configuration ─────────────────────────────────────────────────────────────
const GATEHOUSE_OIDC = (import.meta.env.VITE_API_BASE_URL ?? "http://localhost:5000/api/v1")
const SECUIRD_OIDC = (import.meta.env.VITE_API_BASE_URL ?? "http://localhost:5000/api/v1")
.replace(/\/api\/v1\/?$/, "");
// ── Scope display metadata ────────────────────────────────────────────────────
@@ -62,7 +62,7 @@ type PageStep = "loading" | "login" | "consent" | "error";
// ── API helpers ───────────────────────────────────────────────────────────────
async function fetchOIDCContext(oidcSessionId: string): Promise<OIDCContext> {
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/begin`, {
const res = await fetch(`${SECUIRD_OIDC}/oidc/begin`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ oidc_session_id: oidcSessionId }),
@@ -75,7 +75,7 @@ async function fetchOIDCContext(oidcSessionId: string): Promise<OIDCContext> {
}
async function completeOIDCFlow(oidcSessionId: string, token: string): Promise<string> {
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
+1 -1
View File
@@ -108,7 +108,7 @@ export default function RegisterPage() {
Create your account
</h1>
<p className="text-muted-foreground mt-2">
Get started with Gatehouse in seconds
Get started with Secuird in seconds
</p>
</div>
+1 -1
View File
@@ -261,7 +261,7 @@ export default function CAsPage() {
<div>
<h1 className="page-title">Certificate Authorities</h1>
<p className="page-description">
Manage your organization's SSH CAs with <code>Gatehouse</code>
Manage your organization's SSH CAs with <code>Secuird</code>
</p>
</div>
</div>
+3 -3
View File
@@ -160,7 +160,7 @@ export default function OIDCClientsPage() {
<div className="page-header flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div>
<h1 className="page-title">OIDC Clients</h1>
<p className="page-description">Applications that authenticate via Gatehouse</p>
<p className="page-description">Applications that authenticate via Secuird</p>
</div>
<Button onClick={() => setDialogMode("generic")}>
<Plus className="w-4 h-4 mr-2" />
@@ -235,7 +235,7 @@ export default function OIDCClientsPage() {
<Network className="w-10 h-10 text-muted-foreground/40" />
<div>
<p className="font-medium text-muted-foreground">No OIDC clients yet</p>
<p className="text-sm text-muted-foreground/70">Register an app to let it authenticate via Gatehouse</p>
<p className="text-sm text-muted-foreground/70">Register an app to let it authenticate via Secuird</p>
</div>
<div className="flex gap-2 flex-wrap justify-center">
<Button variant="outline" onClick={() => setDialogMode("generic")}>
@@ -320,7 +320,7 @@ export default function OIDCClientsPage() {
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle>Add OIDC Client</DialogTitle>
<DialogDescription>Register an application to authenticate via Gatehouse</DialogDescription>
<DialogDescription>Register an application to authenticate via Secuird</DialogDescription>
</DialogHeader>
<Tabs
+5 -5
View File
@@ -47,7 +47,7 @@ export function CADetailCard({ ca, onEdit, onRotate, onDelete }: CADetailCardPro
const isSystem = !!ca.is_system;
// ── User CA: server trusts this public key so it accepts user certs ──────
const userCaServerSnippet = `# On each SSH server — trust Gatehouse-issued user certificates:
const userCaServerSnippet = `# On each SSH server — trust Secuird-issued user certificates:
echo '${ca.public_key.trim()}' >> /etc/ssh/trusted_user_ca_keys
# /etc/ssh/sshd_config (add once, then reload sshd):
@@ -63,7 +63,7 @@ AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
# ─── Server side (separate step) ────────────────────────────────────────────
# 1. Collect the server's HOST public key:
# cat /etc/ssh/ssh_host_ed25519_key.pub
# 2. Submit it to Gatehouse → "Issue Host Certificate" to get a signed cert.
# 2. Submit it to Secuird → "Issue Host Certificate" to get a signed cert.
# 3. Install the cert on the server:
# /etc/ssh/sshd_config:
# HostKey /etc/ssh/ssh_host_ed25519_key
@@ -200,8 +200,8 @@ AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
<span className="flex items-center gap-1.5">
<Terminal className="w-3.5 h-3.5" />
{isUser
? "Server setup — trust Gatehouse user certificates"
: "Client setup — trust Gatehouse host certificates"}
? "Server setup — trust Secuird user certificates"
: "Client setup — trust Secuird host certificates"}
</span>
</AccordionTrigger>
<AccordionContent className="pb-3">
@@ -209,7 +209,7 @@ AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
<div className="mb-2 rounded border border-amber-300 dark:border-amber-700 bg-amber-50 dark:bg-amber-950/40 px-2 py-1.5 text-xs text-amber-800 dark:text-amber-300">
<strong>Two separate steps:</strong> (1) Put this CA public key in client{" "}
<code className="font-mono">known_hosts</code>. (2) Issue a host certificate
for each server via Gatehouse and install it as{" "}
for each server via Secuird and install it as{" "}
<code className="font-mono">HostCertificate</code>.
</div>
)}
+1 -1
View File
@@ -127,7 +127,7 @@ export function CASection({
<p>
Certificates are being signed by a CA key loaded from the server
configuration, not managed through this UI. Generate a managed key below to
take full control of certificate issuance from Gatehouse.
take full control of certificate issuance from Secuird.
</p>
</div>
<Button
+1 -1
View File
@@ -176,7 +176,7 @@ ssh-keygen -L -f /etc/ssh/ssh_host_ed25519_key-cert.pub`
</p>
<p>
<strong>Step 2 (here):</strong> For each server, collect its host public key,
paste it below, and Gatehouse will sign it. Install the resulting certificate
paste it below, and Secuird will sign it. Install the resulting certificate
as <code className="font-mono">HostCertificate</code> in{" "}
<code className="font-mono">sshd_config</code>.
</p>
+1 -1
View File
@@ -172,7 +172,7 @@ export default function LinkedAccountsPage() {
<Alert className="mb-6">
<AlertCircle className="w-4 h-4" />
<AlertDescription>
Linked accounts can only be used to sign in to an existing Gatehouse account.
Linked accounts can only be used to sign in to an existing Secuird account.
They cannot be used to create new accounts.
</AlertDescription>
</Alert>
+2 -2
View File
@@ -658,7 +658,7 @@ export default function SSHKeysPage() {
CA Public Key
</CardTitle>
<CardDescription>
Add this key to <code>TrustedUserCAKeys</code> on your servers so they accept certificates issued by Gatehouse.
Add this key to <code>TrustedUserCAKeys</code> on your servers so they accept certificates issued by Secuird.
</CardDescription>
</CardHeader>
<CardContent>
@@ -821,7 +821,7 @@ TrustedUserCAKeys /etc/ssh/trusted_user_ca_keys`}
{`echo '<challenge_text>' > /tmp/challenge.txt
ssh-keygen -Y sign \\
-f ~/.ssh/id_ed25519 \\
-n gatehouse \\
-n secuird \\
/tmp/challenge.txt
cat /tmp/challenge.txt.sig | base64 -w0`}
</pre>
+1 -1
View File
@@ -1 +1 @@
{"root":["./src/App.tsx","./src/config.ts","./src/main.tsx","./src/vite-env.d.ts","./src/components/NavLink.tsx","./src/components/auth/BannerAlert.tsx","./src/components/auth/ComplianceBanner.tsx","./src/components/auth/PasswordStrengthMeter.tsx","./src/components/branding/GatehouseLogo.tsx","./src/components/dev/ApiDevTools.tsx","./src/components/layouts/AuthenticatedLayout.tsx","./src/components/layouts/MfaEnforcementLayout.tsx","./src/components/layouts/ProtectedLayout.tsx","./src/components/layouts/PublicLayout.tsx","./src/components/navigation/AppSidebar.tsx","./src/components/navigation/TopBar.tsx","./src/components/security/AddPasskeyWizard.tsx","./src/components/security/TotpEnrollmentWizard.tsx","./src/components/security/TotpRemoveDialog.tsx","./src/components/ui/accordion.tsx","./src/components/ui/alert-dialog.tsx","./src/components/ui/alert.tsx","./src/components/ui/aspect-ratio.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/carousel.tsx","./src/components/ui/chart.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/command.tsx","./src/components/ui/context-menu.tsx","./src/components/ui/dialog.tsx","./src/components/ui/drawer.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/form.tsx","./src/components/ui/hover-card.tsx","./src/components/ui/input-otp.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/menubar.tsx","./src/components/ui/navigation-menu.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/progress.tsx","./src/components/ui/radio-group.tsx","./src/components/ui/resizable.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/sheet.tsx","./src/components/ui/sidebar.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/slider.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/toast.tsx","./src/components/ui/toaster.tsx","./src/components/ui/toggle-group.tsx","./src/components/ui/toggle.tsx","./src/components/ui/tooltip.tsx","./src/components/ui/use-toast.ts","./src/contexts/AuthContext.tsx","./src/hooks/use-mobile.tsx","./src/hooks/use-toast.ts","./src/hooks/useOrganizations.ts","./src/lib/api.ts","./src/lib/encoding.ts","./src/lib/oauth.ts","./src/lib/utils.ts","./src/lib/webauthn.ts","./src/pages/Index.tsx","./src/pages/NotFound.tsx","./src/pages/auth/ForgotPasswordPage.tsx","./src/pages/auth/InviteAcceptPage.tsx","./src/pages/auth/LoginPage.tsx","./src/pages/auth/OAuthCallbackPage.tsx","./src/pages/auth/OIDCConsentPage.tsx","./src/pages/auth/OIDCErrorPage.tsx","./src/pages/auth/RegisterPage.tsx","./src/pages/auth/ResetPasswordPage.tsx","./src/pages/auth/VerifyEmailPage.tsx","./src/pages/org/CompliancePage.tsx","./src/pages/org/MembersPage.tsx","./src/pages/org/OIDCClientsPage.tsx","./src/pages/org/OrgAuditPage.tsx","./src/pages/org/OrgOverviewPage.tsx","./src/pages/org/PoliciesPage.tsx","./src/pages/user/ActivityPage.tsx","./src/pages/user/LinkedAccountsPage.tsx","./src/pages/user/ProfilePage.tsx","./src/pages/user/SecurityPage.tsx"],"errors":true,"version":"5.8.3"}
{"root":["./src/App.tsx","./src/config.ts","./src/main.tsx","./src/vite-env.d.ts","./src/components/NavLink.tsx","./src/components/auth/BannerAlert.tsx","./src/components/auth/ComplianceBanner.tsx","./src/components/auth/PasswordStrengthMeter.tsx","./src/components/branding/SecuirdLogo.tsx","./src/components/dev/ApiDevTools.tsx","./src/components/layouts/AuthenticatedLayout.tsx","./src/components/layouts/MfaEnforcementLayout.tsx","./src/components/layouts/ProtectedLayout.tsx","./src/components/layouts/PublicLayout.tsx","./src/components/navigation/AppSidebar.tsx","./src/components/navigation/TopBar.tsx","./src/components/security/AddPasskeyWizard.tsx","./src/components/security/TotpEnrollmentWizard.tsx","./src/components/security/TotpRemoveDialog.tsx","./src/components/ui/accordion.tsx","./src/components/ui/alert-dialog.tsx","./src/components/ui/alert.tsx","./src/components/ui/aspect-ratio.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/carousel.tsx","./src/components/ui/chart.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/command.tsx","./src/components/ui/context-menu.tsx","./src/components/ui/dialog.tsx","./src/components/ui/drawer.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/form.tsx","./src/components/ui/hover-card.tsx","./src/components/ui/input-otp.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/menubar.tsx","./src/components/ui/navigation-menu.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/progress.tsx","./src/components/ui/radio-group.tsx","./src/components/ui/resizable.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/sheet.tsx","./src/components/ui/sidebar.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/slider.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/toast.tsx","./src/components/ui/toaster.tsx","./src/components/ui/toggle-group.tsx","./src/components/ui/toggle.tsx","./src/components/ui/tooltip.tsx","./src/components/ui/use-toast.ts","./src/contexts/AuthContext.tsx","./src/hooks/use-mobile.tsx","./src/hooks/use-toast.ts","./src/hooks/useOrganizations.ts","./src/lib/api.ts","./src/lib/encoding.ts","./src/lib/oauth.ts","./src/lib/utils.ts","./src/lib/webauthn.ts","./src/pages/Index.tsx","./src/pages/NotFound.tsx","./src/pages/auth/ForgotPasswordPage.tsx","./src/pages/auth/InviteAcceptPage.tsx","./src/pages/auth/LoginPage.tsx","./src/pages/auth/OAuthCallbackPage.tsx","./src/pages/auth/OIDCConsentPage.tsx","./src/pages/auth/OIDCErrorPage.tsx","./src/pages/auth/RegisterPage.tsx","./src/pages/auth/ResetPasswordPage.tsx","./src/pages/auth/VerifyEmailPage.tsx","./src/pages/org/CompliancePage.tsx","./src/pages/org/MembersPage.tsx","./src/pages/org/OIDCClientsPage.tsx","./src/pages/org/OrgAuditPage.tsx","./src/pages/org/OrgOverviewPage.tsx","./src/pages/org/PoliciesPage.tsx","./src/pages/user/ActivityPage.tsx","./src/pages/user/LinkedAccountsPage.tsx","./src/pages/user/ProfilePage.tsx","./src/pages/user/SecurityPage.tsx"],"errors":true,"version":"5.8.3"}
+1 -1
View File
@@ -8,7 +8,7 @@ export default defineConfig(({ mode }) => ({
server: {
host: "::",
port: 8080,
allowedHosts: process.env.VITE_ALLOWED_HOSTS?.split(",") || ["ui.webauthn.local","gatehouse-ui.hawkvelt.tech"],
allowedHosts: process.env.VITE_ALLOWED_HOSTS?.split(",") || ["ui.webauthn.local","secuird-ui.hawkvelt.tech"],
},
plugins: [react(), mode === "development" && componentTagger()].filter(Boolean),
resolve: {