diff --git a/apps/sim/app/(home)/components/enterprise/enterprise.tsx b/apps/sim/app/(home)/components/enterprise/enterprise.tsx index 1d07bd58a38..ca967b13b2c 100644 --- a/apps/sim/app/(home)/components/enterprise/enterprise.tsx +++ b/apps/sim/app/(home)/components/enterprise/enterprise.tsx @@ -4,14 +4,484 @@ * SEO: * - `
`. * - `

` for the section title. - * - Compliance certs (SOC2, HIPAA) as visible `` text. + * - Compliance certs (SOC 2, HIPAA) as visible `` text. * - Enterprise CTA links to contact form via `` with `rel="noopener noreferrer"`. * * GEO: - * - Entity-rich: "Sim is SOC2 and HIPAA compliant" — not "We are compliant." + * - Entity-rich: "Sim is SOC 2 and HIPAA compliant" — not "We are compliant." * - `
    ` checklist of features (SSO, RBAC, audit logs, SLA, on-premise deployment) * as an atomic answer block for "What enterprise features does Sim offer?". */ +'use client' + +import { useEffect, useRef, useState } from 'react' +import { AnimatePresence, motion } from 'framer-motion' +import Image from 'next/image' +import Link from 'next/link' +import { Badge, ChevronDown } from '@/components/emcn' +import { Lock } from '@/components/emcn/icons' +import { GithubIcon } from '@/components/icons' + +/** Consistent color per actor — same pattern as Collaboration section cursors. */ +const ACTOR_COLORS: Record = { + 'Sarah K.': '#2ABBF8', + 'Sid G.': '#33C482', + 'Theo L.': '#FA4EDF', + 'Abhay K.': '#FFCC02', + 'Danny S.': '#FF6B35', +} + +/** Left accent bar opacity by recency — newest is brightest. */ +const ACCENT_OPACITIES = [0.75, 0.45, 0.28, 0.15, 0.07] as const + +/** Human-readable label per resource type. */ +const RESOURCE_TYPE_LABEL: Record = { + workflow: 'Workflow', + member: 'Member', + byok_key: 'BYOK Key', + api_key: 'API Key', + permission_group: 'Permission Group', + credential_set: 'Credential Set', + knowledge_base: 'Knowledge Base', + environment: 'Environment', + mcp_server: 'MCP Server', + file: 'File', + webhook: 'Webhook', + chat: 'Chat', + table: 'Table', + folder: 'Folder', + document: 'Document', +} + +interface LogEntry { + id: number + actor: string + /** Matches the `description` field stored by recordAudit() */ + description: string + resourceType: string + /** Unix ms timestamp of when this entry was "received" */ + insertedAt: number +} + +function formatTimeAgo(insertedAt: number): string { + const elapsed = Date.now() - insertedAt + if (elapsed < 8_000) return 'just now' + if (elapsed < 60_000) return `${Math.floor(elapsed / 1000)}s ago` + return `${Math.floor(elapsed / 60_000)}m ago` +} + +/** + * Entry templates using real description strings from the actual recordAudit() + * calls across the codebase (e.g. `Added BYOK key for openai`, + * `Invited alex@acme.com to workspace as member`). + */ +const ENTRY_TEMPLATES: Omit[] = [ + { actor: 'Sarah K.', description: 'Deployed workflow "Email Triage"', resourceType: 'workflow' }, + { + actor: 'Sid G.', + description: 'Invited alex@acme.com to workspace as member', + resourceType: 'member', + }, + { actor: 'Theo L.', description: 'Added BYOK key for openai', resourceType: 'byok_key' }, + { actor: 'Sarah K.', description: 'Created workflow "Invoice Parser"', resourceType: 'workflow' }, + { + actor: 'Abhay K.', + description: 'Created permission group "Engineering"', + resourceType: 'permission_group', + }, + { actor: 'Danny S.', description: 'Created API key "Production Key"', resourceType: 'api_key' }, + { + actor: 'Theo L.', + description: 'Changed permissions for sam@acme.com to editor', + resourceType: 'member', + }, + { actor: 'Sarah K.', description: 'Uploaded file "Q3_Report.pdf"', resourceType: 'file' }, + { + actor: 'Sid G.', + description: 'Created credential set "Prod Keys"', + resourceType: 'credential_set', + }, + { + actor: 'Abhay K.', + description: 'Created knowledge base "Internal Docs"', + resourceType: 'knowledge_base', + }, + { actor: 'Danny S.', description: 'Updated environment variables', resourceType: 'environment' }, + { + actor: 'Sarah K.', + description: 'Added tool "search_web" to MCP server', + resourceType: 'mcp_server', + }, + { actor: 'Sid G.', description: 'Created webhook "Stripe Payment"', resourceType: 'webhook' }, + { actor: 'Theo L.', description: 'Deployed chat "Support Assistant"', resourceType: 'chat' }, + { actor: 'Abhay K.', description: 'Created table "Lead Tracker"', resourceType: 'table' }, + { actor: 'Danny S.', description: 'Revoked API key "Staging Key"', resourceType: 'api_key' }, + { + actor: 'Sarah K.', + description: 'Duplicated workflow "Data Enrichment"', + resourceType: 'workflow', + }, + { + actor: 'Sid G.', + description: 'Removed member theo@acme.com from workspace', + resourceType: 'member', + }, + { + actor: 'Theo L.', + description: 'Updated knowledge base "Product Docs"', + resourceType: 'knowledge_base', + }, + { actor: 'Abhay K.', description: 'Created folder "Finance Workflows"', resourceType: 'folder' }, + { + actor: 'Danny S.', + description: 'Uploaded document "onboarding-guide.pdf"', + resourceType: 'document', + }, + { + actor: 'Sarah K.', + description: 'Updated credential set "Prod Keys"', + resourceType: 'credential_set', + }, + { + actor: 'Sid G.', + description: 'Added member abhay@acme.com to permission group "Engineering"', + resourceType: 'permission_group', + }, + { actor: 'Theo L.', description: 'Locked workflow "Customer Sync"', resourceType: 'workflow' }, +] + +const INITIAL_OFFSETS_MS = [0, 20_000, 75_000, 240_000, 540_000] + +const MARQUEE_KEYFRAMES = ` + @keyframes marquee { + 0% { transform: translateX(0); } + 100% { transform: translateX(-25%); } + } + @media (prefers-reduced-motion: reduce) { + @keyframes marquee { 0%, 100% { transform: none; } } + } +` + +const FEATURE_TAGS = [ + 'Access Control', + 'Self-Hosting', + 'Bring Your Own Key', + 'Credential Sharing', + 'Custom Limits', + 'Admin API', + 'White Labeling', + 'Dedicated Support', + '99.99% Uptime SLA', + 'Workflow Versioning', + 'On-Premise', + 'Organizations', + 'Workspace Export', + 'Audit Logs', +] as const + +interface AuditRowProps { + entry: LogEntry + index: number +} + +function AuditRow({ entry, index }: AuditRowProps) { + const color = ACTOR_COLORS[entry.actor] ?? '#F6F6F6' + const accentOpacity = ACCENT_OPACITIES[index] ?? 0.04 + const timeAgo = formatTimeAgo(entry.insertedAt) + const resourceLabel = RESOURCE_TYPE_LABEL[entry.resourceType] + + return ( +
    + {/* Left accent bar — brightness encodes recency */} + + ) +} + +function AuditLogPreview() { + const counterRef = useRef(ENTRY_TEMPLATES.length) + const templateIndexRef = useRef(5 % ENTRY_TEMPLATES.length) + + const now = Date.now() + const [entries, setEntries] = useState(() => + ENTRY_TEMPLATES.slice(0, 5).map((t, i) => ({ + ...t, + id: i, + insertedAt: now - INITIAL_OFFSETS_MS[i], + })) + ) + const [, tick] = useState(0) + + useEffect(() => { + const addInterval = setInterval(() => { + const template = ENTRY_TEMPLATES[templateIndexRef.current] + templateIndexRef.current = (templateIndexRef.current + 1) % ENTRY_TEMPLATES.length + + setEntries((prev) => [ + { ...template, id: counterRef.current++, insertedAt: Date.now() }, + ...prev.slice(0, 4), + ]) + }, 2600) + + // Refresh time labels every 5s so "just now" ages to "Xs ago" + const tickInterval = setInterval(() => tick((n) => n + 1), 5_000) + + return () => { + clearInterval(addInterval) + clearInterval(tickInterval) + } + }, []) + + return ( +
    + {/* Header */} +
    +
    + {/* Pulsing live indicator */} + + + + + + Audit Log + +
    +
    + + Export + + + Filter + +
    +
    + + {/* Log entries — new items push existing ones down */} +
    + + {entries.map((entry, index) => ( + + + + ))} + +
    +
    + ) +} + +function TrustStrip() { + return ( +
    + {/* SOC 2 + HIPAA combined */} + + SOC 2 Type II +
    + + SOC 2 & HIPAA + + + Type II · PHI protected → + +
    + + + {/* Open Source — center */} + +
    + +
    +
    + + Open Source + + + View on GitHub → + +
    + + + {/* SSO */} +
    +
    + +
    +
    + + SSO & SCIM + + + Okta, Azure AD, Google + +
    +
    +
    + ) +} + export default function Enterprise() { - return null + return ( +
    +
    +
    + + Enterprise + + +

    + Enterprise features for +
    + fast, scalable workflows +

    +
    + +
    + + + + {/* Scrolling feature ticker */} +
    +