"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("../index-DEZRGktf.js"),t=require("lucide-react");require("react-router-dom");require("react");require("react-dom");const s=()=>e.jsxs("div",{className:"flex flex-col gap-8",children:[e.jsx(r.HeroCard,{title:"Security",description:"Authentication, rate limiting, and hardening measures for production deployments.",icon:e.jsx("div",{className:"w-16 h-16 sm:w-20 sm:h-20 bg-linear-to-br from-red-500 to-rose-600 rounded-full flex items-center justify-center shadow-lg",children:e.jsx(t.Shield,{className:"w-8 h-8 sm:w-10 sm:h-10 text-white"})})}),e.jsx(r.CardContainer,{children:e.jsxs(r.CardTitle,{title:"Bearer Token Authentication",children:[e.jsxs(r.Typography,{className:"text-sm text-foreground/70 mb-3",children:["The HTTP transport requires a Bearer token when"," ",e.jsx("code",{className:"px-1.5 py-0.5 bg-muted rounded text-xs font-mono",children:"MCP_API_KEY"})," ","is set. All requests must include the Authorization header:"]}),e.jsx(r.CodeBlock,{code:`# Set the API key on the server
export MCP_API_KEY="your-secure-random-string"

# Clients must send:
Authorization: Bearer your-secure-random-string

# Generate a secure key:
openssl rand -base64 32`}),e.jsx("div",{className:"mt-3 p-3 rounded-lg border border-amber-500/20 bg-amber-500/5",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(t.AlertTriangle,{className:"w-4 h-4 text-amber-500 mt-0.5"}),e.jsxs(r.Typography,{className:"text-xs text-amber-600 dark:text-amber-400",children:["If ",e.jsx("code",{className:"font-mono",children:"MCP_API_KEY"})," is not set, the server runs without auth — only suitable for local/stdio usage."]})]})})]})}),e.jsx(r.CardContainer,{children:e.jsxs(r.CardTitle,{title:"Rate Limiting",children:[e.jsx(r.Typography,{className:"text-sm text-foreground/70 mb-3",children:"Built-in rate limiting protects the server from abuse:"}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[e.jsxs("div",{className:"p-3 rounded-lg border border-border bg-muted/30 text-center",children:[e.jsx(r.Typography,{className:"text-2xl font-bold text-foreground",children:"100"}),e.jsx(r.Typography,{className:"text-xs text-foreground/50",children:"requests/min per IP"})]}),e.jsxs("div",{className:"p-3 rounded-lg border border-border bg-muted/30 text-center",children:[e.jsx(r.Typography,{className:"text-2xl font-bold text-foreground",children:"429"}),e.jsx(r.Typography,{className:"text-xs text-foreground/50",children:"status when exceeded"})]}),e.jsxs("div",{className:"p-3 rounded-lg border border-border bg-muted/30 text-center",children:[e.jsx(r.Typography,{className:"text-2xl font-bold text-foreground",children:"60s"}),e.jsx(r.Typography,{className:"text-xs text-foreground/50",children:"window reset"})]})]}),e.jsx(r.CodeBlock,{code:`// Rate limit response when exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{ "error": "Rate limit exceeded. Try again in 60 seconds." }`})]})}),e.jsx(r.CardContainer,{children:e.jsxs(r.CardTitle,{title:"Timing-Safe Comparison",children:[e.jsx(r.Typography,{className:"text-sm text-foreground/70 mb-3",children:"Token validation uses constant-time comparison to prevent timing attacks:"}),e.jsx(r.CodeBlock,{code:`import { timingSafeEqual } from 'node:crypto';

function verifyToken(provided: string, expected: string): boolean {
  const a = Buffer.from(provided);
  const b = Buffer.from(expected);
  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}`})]})}),e.jsxs("section",{className:"space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx(r.Typography,{tag:"h2",className:"mb-2",children:"Infrastructure Security"}),e.jsx(r.Typography,{tag:"p",className:"text-gray-500 dark:text-gray-400 max-w-2xl mx-auto",children:"Docker hardening and HTTPS enforcement for production deployments"})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4",children:[e.jsx(r.FeatureCard,{layout:"vertical",icon:e.jsx(t.User,{className:"w-6 h-6 text-white filter drop-shadow-sm"}),title:"Non-Root User",description:"Runs as node user (UID 1000) — never as root",iconBgClassName:"from-blue-500 to-indigo-500"}),e.jsx(r.FeatureCard,{layout:"vertical",icon:e.jsx(t.Layers,{className:"w-6 h-6 text-white filter drop-shadow-sm"}),title:"Multi-Stage Build",description:"Only production deps in final Alpine-based image",iconBgClassName:"from-emerald-500 to-teal-500"}),e.jsx(r.FeatureCard,{layout:"vertical",icon:e.jsx(t.Lock,{className:"w-6 h-6 text-white filter drop-shadow-sm"}),title:"Auto TLS",description:"Automatic certificate provisioning and HTTP→HTTPS redirect",iconBgClassName:"from-violet-500 to-purple-500"}),e.jsx(r.FeatureCard,{layout:"vertical",icon:e.jsx(t.KeyRound,{className:"w-6 h-6 text-white filter drop-shadow-sm"}),title:"Encrypted Secrets",description:"Secrets stored encrypted at rest with fly secrets",iconBgClassName:"from-rose-500 to-red-500"})]})]}),e.jsx(r.CardContainer,{children:e.jsxs(r.CardTitle,{title:"Security Checklist",children:[e.jsx(r.Typography,{className:"text-sm text-foreground/70 mb-3",children:"Before deploying to production, ensure:"}),e.jsx(r.CodeBlock,{code:`✓ MCP_API_KEY is set to a strong random value (32+ chars)
✓ HTTPS is enforced (automatic on Fly.io)
✓ Rate limiting is enabled (default: 100 req/min)
✓ Docker runs as non-root user
✓ No secrets in source code or Docker image layers
✓ Fly.io secrets set via 'fly secrets set' (not env files)
✓ Health endpoint (/health) does not expose internals
✓ CORS restricted to known origins in production`})]})})]});exports.default=s;
