feat: seo optimization p1
This commit is contained in:
@@ -49,8 +49,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
--font-sans: var(--font-inter), 'Inter', ui-sans-serif, system-ui, sans-serif;
|
||||||
--font-serif: 'Source Serif 4', 'Source Serif Pro', Georgia, serif;
|
--font-serif: var(--font-source-serif), 'Source Serif 4', 'Source Serif Pro', Georgia, serif;
|
||||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
|
|
||||||
--color-background: rgb(var(--background));
|
--color-background: rgb(var(--background));
|
||||||
|
|||||||
@@ -3,8 +3,35 @@ import type { Metadata } from 'next'
|
|||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Greyscan | Greywall',
|
title: 'Greyscan | Greywall',
|
||||||
description: 'Scan your repo and see what an unrestricted AI agent would attempt. Powered by Greywall.',
|
description: 'Scan your repo and see what an unrestricted AI agent would attempt. Powered by Greywall.',
|
||||||
|
alternates: {
|
||||||
|
canonical: 'https://greywall.io/greyscan',
|
||||||
|
},
|
||||||
|
openGraph: {
|
||||||
|
title: 'Greyscan | Greywall',
|
||||||
|
description: 'Scan your repo and see what an unrestricted AI agent would attempt. Powered by Greywall.',
|
||||||
|
url: 'https://greywall.io/greyscan',
|
||||||
|
siteName: 'Greywall',
|
||||||
|
type: 'website',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const breadcrumbJsonLd = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'BreadcrumbList',
|
||||||
|
itemListElement: [
|
||||||
|
{ '@type': 'ListItem', position: 1, name: 'Greywall', item: 'https://greywall.io' },
|
||||||
|
{ '@type': 'ListItem', position: 2, name: 'Greyscan', item: 'https://greywall.io/greyscan' },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ExposureLayout({ children }: { children: React.ReactNode }) {
|
export default function ExposureLayout({ children }: { children: React.ReactNode }) {
|
||||||
return children
|
return (
|
||||||
|
<>
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,26 @@
|
|||||||
import type { Metadata } from 'next'
|
import type { Metadata } from 'next'
|
||||||
|
import { Inter, Source_Serif_4 } from 'next/font/google'
|
||||||
import './globals.css'
|
import './globals.css'
|
||||||
|
|
||||||
|
const inter = Inter({
|
||||||
|
subsets: ['latin'],
|
||||||
|
display: 'swap',
|
||||||
|
variable: '--font-inter',
|
||||||
|
})
|
||||||
|
|
||||||
|
const sourceSerif = Source_Serif_4({
|
||||||
|
subsets: ['latin'],
|
||||||
|
display: 'swap',
|
||||||
|
variable: '--font-source-serif',
|
||||||
|
style: ['normal', 'italic'],
|
||||||
|
axes: ['opsz'],
|
||||||
|
})
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
metadataBase: new URL('https://greywall.io'),
|
||||||
title: 'Greywall: Sandbox for AI Agents',
|
title: 'Greywall: Sandbox for AI Agents',
|
||||||
description:
|
description:
|
||||||
'Container-free, default-deny sandboxing with observability for AI agents. Five layers of defense in one command.',
|
'Container-free, default-deny sandboxing with real-time observability for AI agents on Linux and macOS. Five kernel-enforced security layers in one command. Open source.',
|
||||||
icons: {
|
icons: {
|
||||||
icon: [
|
icon: [
|
||||||
{ url: '/icon.svg', type: 'image/svg+xml' },
|
{ url: '/icon.svg', type: 'image/svg+xml' },
|
||||||
@@ -13,6 +29,74 @@ export const metadata: Metadata = {
|
|||||||
],
|
],
|
||||||
apple: '/apple-icon.png',
|
apple: '/apple-icon.png',
|
||||||
},
|
},
|
||||||
|
openGraph: {
|
||||||
|
title: 'Greywall: Sandbox for AI Agents',
|
||||||
|
description: 'Container-free, default-deny sandboxing with real-time observability for AI agents. Five kernel-enforced security layers in one command.',
|
||||||
|
url: 'https://greywall.io',
|
||||||
|
siteName: 'Greywall',
|
||||||
|
type: 'website',
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: 'summary',
|
||||||
|
title: 'Greywall: Sandbox for AI Agents',
|
||||||
|
description: 'Container-free, default-deny sandboxing with real-time observability for AI agents. Five kernel-enforced security layers in one command.',
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: 'https://greywall.io',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonLd = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@graph': [
|
||||||
|
{
|
||||||
|
'@type': 'Organization',
|
||||||
|
'@id': 'https://greyhaven.co/#organization',
|
||||||
|
name: 'Greyhaven',
|
||||||
|
url: 'https://greyhaven.co',
|
||||||
|
logo: { '@type': 'ImageObject', url: 'https://greywall.io/icon.svg' },
|
||||||
|
sameAs: ['https://github.com/GreyhavenHQ'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'WebSite',
|
||||||
|
'@id': 'https://greywall.io/#website',
|
||||||
|
name: 'Greywall',
|
||||||
|
url: 'https://greywall.io',
|
||||||
|
publisher: { '@id': 'https://greyhaven.co/#organization' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'SoftwareApplication',
|
||||||
|
'@id': 'https://greywall.io/#software',
|
||||||
|
name: 'Greywall',
|
||||||
|
description:
|
||||||
|
'Container-free, default-deny sandboxing with real-time observability and dynamic controls for AI agents on Linux and macOS.',
|
||||||
|
applicationCategory: 'SecurityApplication',
|
||||||
|
operatingSystem: 'Linux, macOS',
|
||||||
|
url: 'https://greywall.io',
|
||||||
|
downloadUrl: 'https://github.com/GreyhavenHQ/greywall',
|
||||||
|
license: 'https://opensource.org/licenses/Apache-2.0',
|
||||||
|
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
||||||
|
author: { '@id': 'https://greyhaven.co/#organization' },
|
||||||
|
featureList: [
|
||||||
|
'Filesystem isolation',
|
||||||
|
'Network isolation',
|
||||||
|
'Command blocking',
|
||||||
|
'Real-time violation monitoring',
|
||||||
|
'Learning mode',
|
||||||
|
'Syscall filtering',
|
||||||
|
'Dynamic allow/deny controls',
|
||||||
|
],
|
||||||
|
isAccessibleForFree: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'SoftwareSourceCode',
|
||||||
|
name: 'Greywall',
|
||||||
|
codeRepository: 'https://github.com/GreyhavenHQ/greywall',
|
||||||
|
programmingLanguage: 'Go',
|
||||||
|
license: 'https://opensource.org/licenses/Apache-2.0',
|
||||||
|
targetProduct: { '@id': 'https://greywall.io/#software' },
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
@@ -21,13 +105,11 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className="dark">
|
<html lang="en" className={`dark ${inter.variable} ${sourceSerif.variable}`}>
|
||||||
<head>
|
<head>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<script
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
type="application/ld+json"
|
||||||
<link
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,500;0,8..60,600;0,8..60,700;1,8..60,400;1,8..60,600;1,8..60,700&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body className="font-sans antialiased bg-background text-foreground">
|
<body className="font-sans antialiased bg-background text-foreground">
|
||||||
|
|||||||
118
app/privacy/page.tsx
Normal file
118
app/privacy/page.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import type { Metadata } from 'next'
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Privacy Policy | Greywall',
|
||||||
|
description: 'How Greywall handles your data.',
|
||||||
|
alternates: {
|
||||||
|
canonical: 'https://greywall.io/privacy',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PrivacyPage() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen pt-24 pb-16 px-4 sm:px-6">
|
||||||
|
<article className="mx-auto max-w-2xl">
|
||||||
|
<h1 className="font-serif text-3xl sm:text-4xl font-semibold tracking-tight mb-2">
|
||||||
|
Privacy Policy
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm text-muted-foreground font-sans mb-12">
|
||||||
|
Last updated: March 19, 2026
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-10 text-muted-foreground font-serif text-base leading-relaxed">
|
||||||
|
<section>
|
||||||
|
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Greywall (the CLI tool)</h2>
|
||||||
|
<p>
|
||||||
|
Greywall runs entirely on your machine. It does not phone home, collect telemetry,
|
||||||
|
or transmit any data. No analytics, no crash reports, no usage tracking. The source
|
||||||
|
code is open and auditable
|
||||||
|
at <a href="https://github.com/GreyhavenHQ/greywall" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">github.com/GreyhavenHQ/greywall</a>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">This website (greywall.io)</h2>
|
||||||
|
<p className="mb-4">
|
||||||
|
The Greywall landing page is a static site hosted on Vercel. We do not use cookies,
|
||||||
|
analytics scripts, or tracking pixels. Vercel may collect minimal server logs
|
||||||
|
(IP address, user agent, timestamp) as part of standard web hosting.
|
||||||
|
See <a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">Vercel's privacy policy</a> for
|
||||||
|
details.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Greyscan</h2>
|
||||||
|
<p className="mb-4">
|
||||||
|
When you use Greyscan at <a href="/greyscan" className="text-primary hover:text-primary/80 transition-colors">/greyscan</a>,
|
||||||
|
the following happens:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
Your browser fetches the public file tree, dependency list, and README from GitHub's
|
||||||
|
API directly. This data never passes through our servers during collection.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
To generate the threat report, a summary of the repo structure (file names,
|
||||||
|
detected stack, dependency names, and up to 8,000 characters of the README) is
|
||||||
|
sent to our server and forwarded to a third-party LLM provider for analysis.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Results are cached in server memory for up to 24 hours to avoid redundant
|
||||||
|
LLM calls for the same repository, then discarded. We do not persist scan
|
||||||
|
results to disk or a database.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
No repository source code is read or transmitted. Only file paths, dependency
|
||||||
|
names, and the public README are included.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Third-party services</h2>
|
||||||
|
<ul className="list-disc pl-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
<span className="text-foreground font-medium">GitHub API</span> — Greyscan
|
||||||
|
calls the GitHub REST API from your browser to fetch public repository metadata.
|
||||||
|
Subject to <a href="https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">GitHub's privacy statement</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-foreground font-medium">LLM provider</span> — Repo
|
||||||
|
summaries sent through Greyscan are processed by a third-party LLM to generate
|
||||||
|
threat reports. The provider may retain data per their own policies.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-foreground font-medium">Vercel</span> — Hosting
|
||||||
|
infrastructure. See <a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">Vercel's privacy policy</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Security</h2>
|
||||||
|
<p>
|
||||||
|
If you discover a security issue in Greywall or this website, please report it
|
||||||
|
via <a href="https://github.com/GreyhavenHQ/greywall/security" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">GitHub Security Advisories</a>.
|
||||||
|
We will respond promptly.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2 className="font-serif text-xl font-semibold text-foreground mb-3">Contact</h2>
|
||||||
|
<p>
|
||||||
|
For questions about this policy,
|
||||||
|
reach us at <a href="https://greyhaven.co/contact" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80 transition-colors">greyhaven.co/contact</a>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-16 pt-8 border-t border-border/30">
|
||||||
|
<a href="/" className="text-sm text-muted-foreground hover:text-foreground transition-colors font-sans">
|
||||||
|
← Back to Greywall
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
9
app/sitemap.ts
Normal file
9
app/sitemap.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import type { MetadataRoute } from 'next'
|
||||||
|
|
||||||
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
|
return [
|
||||||
|
{ url: 'https://greywall.io', lastModified: new Date(), changeFrequency: 'weekly', priority: 1 },
|
||||||
|
{ url: 'https://greywall.io/greyscan', lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
|
||||||
|
{ url: 'https://greywall.io/privacy', lastModified: new Date(), changeFrequency: 'yearly', priority: 0.3 },
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import Image from 'next/image'
|
||||||
import { CheckCircle2 } from 'lucide-react'
|
import { CheckCircle2 } from 'lucide-react'
|
||||||
|
|
||||||
const agents = [
|
const agents = [
|
||||||
@@ -42,7 +43,7 @@ export function Agents() {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="group flex items-center gap-2.5 sm:gap-3 p-3 sm:p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 hover:bg-card/50 transition-all cursor-pointer"
|
className="group flex items-center gap-2.5 sm:gap-3 p-3 sm:p-4 rounded-lg border border-border/40 bg-card/30 hover:border-primary/20 hover:bg-card/50 transition-all cursor-pointer"
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
src={`https://github.com/${agent.org}.png?size=64`}
|
src={`https://github.com/${agent.org}.png?size=64`}
|
||||||
alt={agent.name}
|
alt={agent.name}
|
||||||
width={28}
|
width={28}
|
||||||
|
|||||||
@@ -109,22 +109,22 @@ const rows: Row[] = [
|
|||||||
function CellIcon({ value }: { value: CellValue }) {
|
function CellIcon({ value }: { value: CellValue }) {
|
||||||
if (value === 'yes') {
|
if (value === 'yes') {
|
||||||
return (
|
return (
|
||||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10">
|
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10" aria-label="Supported">
|
||||||
<Check className="h-3 w-3 text-green-400" />
|
<Check className="h-3 w-3 text-green-400" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (value === 'no') {
|
if (value === 'no') {
|
||||||
return (
|
return (
|
||||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10">
|
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10" aria-label="Not supported">
|
||||||
<X className="h-3 w-3 text-red-400/70" />
|
<X className="h-3 w-3 text-red-400/70" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (value === 'partial') {
|
if (value === 'partial') {
|
||||||
return (
|
return (
|
||||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10">
|
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10" aria-label="Partial support">
|
||||||
<Minus className="h-3 w-3 text-yellow-400/70" />
|
<Minus className="h-3 w-3 text-yellow-400/70" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -214,19 +214,19 @@ export function Comparison() {
|
|||||||
<div className="mt-6 flex flex-wrap items-center gap-5 text-xs font-sans text-muted-foreground">
|
<div className="mt-6 flex flex-wrap items-center gap-5 text-xs font-sans text-muted-foreground">
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10">
|
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-400/10">
|
||||||
<Check className="h-3 w-3 text-green-400" />
|
<Check className="h-3 w-3 text-green-400" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
Supported
|
Supported
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10">
|
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-400/10">
|
||||||
<Minus className="h-3 w-3 text-yellow-400/70" />
|
<Minus className="h-3 w-3 text-yellow-400/70" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
Partial
|
Partial
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10">
|
<span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-400/10">
|
||||||
<X className="h-3 w-3 text-red-400/70" />
|
<X className="h-3 w-3 text-red-400/70" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
Not supported
|
Not supported
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ export function Footer() {
|
|||||||
>
|
>
|
||||||
greyhaven.co
|
greyhaven.co
|
||||||
</a>
|
</a>
|
||||||
|
<a
|
||||||
|
href="/privacy"
|
||||||
|
className="hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
Privacy
|
||||||
|
</a>
|
||||||
<span>Apache 2.0</span>
|
<span>Apache 2.0</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState, useEffect, useRef } from 'react'
|
import { useState, useEffect, useRef } from 'react'
|
||||||
|
import Image from 'next/image'
|
||||||
import { Eye } from 'lucide-react'
|
import { Eye } from 'lucide-react'
|
||||||
|
|
||||||
const slides = [
|
const slides = [
|
||||||
@@ -97,20 +98,26 @@ export function Observability() {
|
|||||||
{/* Screenshot with crossfade */}
|
{/* Screenshot with crossfade */}
|
||||||
<div className="relative rounded-lg border border-border/40 overflow-hidden bg-white">
|
<div className="relative rounded-lg border border-border/40 overflow-hidden bg-white">
|
||||||
{/* Hidden reference image to lock container height */}
|
{/* Hidden reference image to lock container height */}
|
||||||
<img
|
<Image
|
||||||
src={slides[0].src}
|
src={slides[0].src}
|
||||||
alt=""
|
alt=""
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
width={1977}
|
||||||
|
height={1444}
|
||||||
className="w-full h-auto invisible"
|
className="w-full h-auto invisible"
|
||||||
|
priority
|
||||||
/>
|
/>
|
||||||
{slides.map((slide, i) => (
|
{slides.map((slide, i) => (
|
||||||
<img
|
<Image
|
||||||
key={slide.label}
|
key={slide.label}
|
||||||
src={slide.src}
|
src={slide.src}
|
||||||
alt={slide.alt}
|
alt={slide.alt}
|
||||||
|
width={slide.src === '/pending_requests.png' ? 1752 : 1977}
|
||||||
|
height={slide.src === '/pending_requests.png' ? 1216 : 1444}
|
||||||
className={`absolute inset-0 w-full h-full object-contain object-top transition-opacity duration-700 ${
|
className={`absolute inset-0 w-full h-full object-contain object-top transition-opacity duration-700 ${
|
||||||
i === active ? 'opacity-100' : 'opacity-0'
|
i === active ? 'opacity-100' : 'opacity-0'
|
||||||
}`}
|
}`}
|
||||||
|
priority={i === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const nextConfig = {
|
|||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
},
|
},
|
||||||
images: {
|
images: {
|
||||||
unoptimized: true,
|
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
@@ -12,6 +11,19 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/(.*)',
|
||||||
|
headers: [
|
||||||
|
{ key: 'X-Frame-Options', value: 'DENY' },
|
||||||
|
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
||||||
|
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
||||||
|
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default nextConfig
|
export default nextConfig
|
||||||
|
|||||||
30
public/llms.txt
Normal file
30
public/llms.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Greywall
|
||||||
|
|
||||||
|
> Container-free, default-deny sandboxing with real-time observability for AI agents on Linux and macOS.
|
||||||
|
|
||||||
|
Greywall is an open-source CLI tool that wraps any AI agent (Claude Code, Codex, Cursor, Aider, and others) in a kernel-enforced sandbox. It uses five security layers on Linux (Bubblewrap namespaces, Landlock filesystem, Seccomp BPF syscall filtering, eBPF monitoring, and TUN+SOCKS5 network proxy) and four on macOS (Seatbelt sandbox, filesystem policy, log stream monitor, and proxy-based network control). Default-deny policy means nothing is accessible unless explicitly granted. Built by Greyhaven, licensed Apache 2.0.
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
- Filesystem isolation (kernel-enforced read/write/deny per path)
|
||||||
|
- Network isolation (all traffic routed through GreyProxy)
|
||||||
|
- Command blocking (detects blocked commands in pipes, chains, nested shells)
|
||||||
|
- Real-time violation monitoring (every denial captured with full context)
|
||||||
|
- Learning mode (auto-generates least-privilege templates from observed access)
|
||||||
|
- Syscall filtering (blocks 27+ dangerous system calls via Seccomp BPF)
|
||||||
|
- Dynamic allow/deny controls (adjust policies live without restarting)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
- [Homepage](https://greywall.io)
|
||||||
|
- [Documentation](https://docs.greywall.io/)
|
||||||
|
- [GitHub](https://github.com/GreyhavenHQ/greywall)
|
||||||
|
- [Greyhaven (parent company)](https://greyhaven.co)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
- Homebrew: `brew tap greyhavenhq/tap && brew install greywall`
|
||||||
|
- Curl: `curl -fsSL https://raw.githubusercontent.com/GreyhavenHQ/greywall/main/install.sh | sh`
|
||||||
|
- Go: `go install github.com/GreyhavenHQ/greywall/cmd/greywall@latest`
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
Works with: Claude Code, Codex, Cursor, Aider, Goose, Amp, Gemini CLI, Cline, OpenCode, Copilot.
|
||||||
|
Platforms: Linux (3.8+), macOS.
|
||||||
|
License: Apache 2.0.
|
||||||
26
public/robots.txt
Normal file
26
public/robots.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
Disallow: /api/
|
||||||
|
|
||||||
|
User-agent: GPTBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: OAI-SearchBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: PerplexityBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: CCBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: cohere-ai
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
Sitemap: https://greywall.io/sitemap.xml
|
||||||
Reference in New Issue
Block a user