diff --git a/docs/architecture.md b/docs/architecture.md index 8fb0c72..a0d22df 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,4 +1,7 @@ -# Architecture +--- +title: "Architecture" +description: "Follow the append-only pipeline from scan to process, revalidate, enrich, report, and export." +--- ## Pipeline diff --git a/docs/configuration.md b/docs/configuration.md index 1cf54fd..15e24e0 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,4 +1,7 @@ -# Configuration reference +--- +title: "Configuration reference" +description: "Configure projects, matchers, agents, ownership, and runtime environment values in deepsec.config.ts." +--- deepsec reads `deepsec.config.{ts,mjs,js,cjs}` from the current working directory, walking up. The CLI inherits whatever the file declares. diff --git a/docs/data-layout.md b/docs/data-layout.md index 421771c..1eb2b20 100644 --- a/docs/data-layout.md +++ b/docs/data-layout.md @@ -1,4 +1,7 @@ -# Data layout +--- +title: "Data layout" +description: "The on-disk state deepsec writes for projects, files, runs, findings, and exports." +--- `data/` is deepsec's on-disk state. Each project owns a subdirectory; the files inside are append-only across runs. @@ -50,7 +53,7 @@ Free-form markdown injected into the AI prompt for `process`, [getting-started.md](getting-started.md) for the agent prompt that writes a good one. -## files/.json — `FileRecord` +## `files/.json` — FileRecord The core per-file accumulator. Every stage *adds to* this record; nothing is overwritten. Re-scanning merges new candidates. @@ -174,7 +177,7 @@ analyzed -- AnalysisEntry appended; findings updated `error` is set if the agent crashed mid-investigation. Re-running `process` will retry `error` and `pending` files. -## runs/.json — `RunMeta` +## `runs/.json` — RunMeta One per `scan` / `process` / `revalidate` invocation. Used for status reporting (`deepsec status`) and for filtering exports by run. diff --git a/docs/faq.md b/docs/faq.md index bfd88ec..4fbd4bb 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,4 +1,7 @@ -# FAQ +--- +title: "FAQ" +description: "Installation, credentials, costs, CI, state handling, and common operating questions." +--- ## How should I install deepsec? diff --git a/docs/getting-started.md b/docs/getting-started.md index bf27969..d46203e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,4 +1,7 @@ -# Getting started +--- +title: "Getting started" +description: "Install deepsec in a .deepsec workspace, fill in INFO.md, and run a limited scan before a full review." +--- ## Install diff --git a/docs/meta.json b/docs/meta.json new file mode 100644 index 0000000..b52fc9d --- /dev/null +++ b/docs/meta.json @@ -0,0 +1,15 @@ +{ + "pages": [ + "getting-started", + "reviewing-changes", + "supported-tech", + "writing-matchers", + "models", + "vercel-setup", + "configuration", + "architecture", + "data-layout", + "plugins", + "faq" + ] +} diff --git a/docs/models.md b/docs/models.md index 742e4e4..da746ba 100644 --- a/docs/models.md +++ b/docs/models.md @@ -1,4 +1,7 @@ -# Models +--- +title: "Models" +description: "Choose Codex, Claude, or Pi for process and revalidate runs, and compare models under the same workload." +--- deepsec talks to LLMs through interchangeable agent backends: diff --git a/docs/plugins.md b/docs/plugins.md index 6629954..330ea62 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -1,4 +1,7 @@ -# Plugins +--- +title: "Plugins" +description: "Extend deepsec with matchers, ownership providers, notifiers, agents, and remote executors." +--- A deepsec plugin can fill any of five slots: diff --git a/docs/reviewing-changes.md b/docs/reviewing-changes.md index 55b0e86..d326cb4 100644 --- a/docs/reviewing-changes.md +++ b/docs/reviewing-changes.md @@ -1,4 +1,7 @@ -# Reviewing changes (PR mode) +--- +title: "Reviewing changes (PR mode)" +description: "Use PR mode to investigate only changed files and fail CI when new findings appear." +--- `deepsec process` has a direct-invocation mode for reviewing a specific set of files — typically the files changed in a pull request. This is diff --git a/docs/supported-tech.md b/docs/supported-tech.md index 58bc428..ca9bbec 100644 --- a/docs/supported-tech.md +++ b/docs/supported-tech.md @@ -1,4 +1,7 @@ -# Supported tech +--- +title: "Supported tech" +description: "The frameworks, languages, infrastructure files, and prompt highlights deepsec recognizes out of the box." +--- Canonical list of frameworks and ecosystems deepsec recognizes out of the box. Each entry tells you three things: diff --git a/docs/vercel-setup.md b/docs/vercel-setup.md index 8ee8d96..817b55a 100644 --- a/docs/vercel-setup.md +++ b/docs/vercel-setup.md @@ -1,4 +1,7 @@ -# Setting up AI Gateway and Vercel Sandbox +--- +title: "Setting up AI Gateway and Vercel Sandbox" +description: "Use AI Gateway for model access and Vercel Sandbox for distributed scans across microVMs." +--- deepsec uses two Vercel products. Most people only need the first. diff --git a/docs/writing-matchers.md b/docs/writing-matchers.md index b2fefcd..701aa47 100644 --- a/docs/writing-matchers.md +++ b/docs/writing-matchers.md @@ -1,4 +1,7 @@ -# Writing matchers with your coding agent +--- +title: "Writing matchers with your coding agent" +description: "Add project-specific matchers for routes, RPC surfaces, auth helpers, webhooks, and internal frameworks." +--- This doc is for users running deepsec inside a `.deepsec/` workspace — i.e. you ran `npx deepsec init`, deepsec is installed in diff --git a/package.json b/package.json index 0a0741e..9e7ce47 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "url": "https://github.com/vercel-labs/deepsec" }, "scripts": { - "build": "tsc --build", + "build": "pnpm -r build", "bundle": "pnpm --filter deepsec bundle", "deepsec": "tsx packages/deepsec/src/cli.ts", "test": "vitest run", diff --git a/packages/website/.gitignore b/packages/website/.gitignore new file mode 100644 index 0000000..cc88c81 --- /dev/null +++ b/packages/website/.gitignore @@ -0,0 +1,44 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# fumadocs-mdx generated source +/.source/ diff --git a/packages/website/README.md b/packages/website/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/packages/website/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/packages/website/app/api/search/route.ts b/packages/website/app/api/search/route.ts new file mode 100644 index 0000000..be1b15d --- /dev/null +++ b/packages/website/app/api/search/route.ts @@ -0,0 +1,5 @@ +import { createSearchRoute } from "@vercel/geistdocs/routes/search"; +import { config } from "@/lib/geistdocs/config"; +import { geistdocsSource } from "@/lib/geistdocs/source"; + +export const GET = createSearchRoute({ config, sources: [geistdocsSource] }); diff --git a/packages/website/app/docs/[...slug]/page.tsx b/packages/website/app/docs/[...slug]/page.tsx new file mode 100644 index 0000000..16f3171 --- /dev/null +++ b/packages/website/app/docs/[...slug]/page.tsx @@ -0,0 +1,62 @@ +import { MobileDocsBar } from "@vercel/geistdocs/mobile-docs-bar"; +import { createDocsPage } from "@vercel/geistdocs/pages/docs"; +import type { ComponentProps, ElementType } from "react"; +import { getMDXComponents } from "@/components/geistdocs/mdx-components"; +import { config, github } from "@/lib/geistdocs/config"; +import { geistdocsSource } from "@/lib/geistdocs/source"; + +// The docs are plain markdown that also gets read on GitHub, so they +// cross-link with relative `.md` paths. Rewrite sibling links to doc routes +// and links that escape docs/ (e.g. ../SECURITY.md) to the GitHub blob view. +function resolveDocHref(href: string | undefined) { + if (!href || !/\.md(#|$)/.test(href) || /^[a-z]+:/.test(href)) { + return href; + } + + const [path, hash] = href.split("#"); + const suffix = hash ? `#${hash}` : ""; + + if (path.startsWith("../")) { + return `https://github.com/${github.owner}/${github.repo}/blob/main/${path.replace(/^(\.\.\/)+/, "")}${suffix}`; + } + + return `/docs/${path.replace(/^\.\//, "").replace(/\.md$/, "")}${suffix}`; +} + +const docsPage = createDocsPage({ + config, + mdx: ({ link }) => { + const DocsLink = (link ?? "a") as ElementType; + return getMDXComponents({ + a: (props: ComponentProps<"a">) => , + }); + }, + source: geistdocsSource, + tableOfContentPopover: { + enabled: false, + }, + renderTop: ({ data }) => , +}); + +// The site is English-only and serves docs at /docs/ without a locale +// segment (hideLocale: "default-locale"), so pin lang instead of routing it. +type PageParams = { slug: string[] }; + +export default function Page({ params }: { params: Promise }) { + return docsPage.Page({ + params: params.then(({ slug }) => ({ lang: "en", slug })), + }); +} + +export function generateStaticParams() { + return docsPage + .generateStaticParams() + .filter((param) => param.lang === "en" && param.slug?.length) + .map(({ slug }) => ({ slug: slug as string[] })); +} + +export function generateMetadata({ params }: { params: Promise }) { + return docsPage.generateMetadata({ + params: params.then(({ slug }) => ({ lang: "en", slug })), + }); +} diff --git a/packages/website/app/docs/layout.tsx b/packages/website/app/docs/layout.tsx new file mode 100644 index 0000000..5995fe3 --- /dev/null +++ b/packages/website/app/docs/layout.tsx @@ -0,0 +1,20 @@ +import { GeistdocsDocsLayout } from "@vercel/geistdocs/layout"; +import type { ReactNode } from "react"; +import { config } from "@/lib/geistdocs/config"; +import { source } from "@/lib/geistdocs/source"; + +export default function Layout({ children }: { children: ReactNode }) { + return ( +
+ + {children} + +
+ ); +} diff --git a/packages/website/app/docs/page.tsx b/packages/website/app/docs/page.tsx new file mode 100644 index 0000000..7feca77 --- /dev/null +++ b/packages/website/app/docs/page.tsx @@ -0,0 +1,5 @@ +import { redirect } from "next/navigation"; + +export default function DocsIndex() { + redirect("/docs/getting-started"); +} diff --git a/packages/website/app/favicon.ico b/packages/website/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/packages/website/app/favicon.ico differ diff --git a/packages/website/app/globals.css b/packages/website/app/globals.css new file mode 100644 index 0000000..aa8aff7 --- /dev/null +++ b/packages/website/app/globals.css @@ -0,0 +1,29 @@ +@import "@vercel/geistdocs/styles.css"; +@source "../node_modules/@vercel/geistdocs/dist/**/*.js"; + +body { + font-family: var(--font-sans); +} + +a { + text-underline-offset: 4px; +} + +::selection { + background: var(--ds-gray-1000); + color: var(--ds-background-100); +} + +.hero-grid { + background-image: + linear-gradient(to right, var(--ds-gray-alpha-200) 1px, transparent 1px), + linear-gradient(to bottom, var(--ds-gray-alpha-200) 1px, transparent 1px); + background-size: 48px 48px; + background-position: center top; +} + +@media (max-width: 640px) { + .hero-grid { + background-size: 32px 32px; + } +} diff --git a/packages/website/app/layout.tsx b/packages/website/app/layout.tsx new file mode 100644 index 0000000..02106f1 --- /dev/null +++ b/packages/website/app/layout.tsx @@ -0,0 +1,39 @@ +import { Analytics } from "@vercel/analytics/next"; +import { Footer } from "@vercel/geistdocs/footer"; +import { Navbar } from "@vercel/geistdocs/navbar"; +import { SpeedInsights } from "@vercel/speed-insights/next"; +import type { Metadata } from "next"; +import { GeistdocsProvider } from "@/components/geistdocs/provider"; +import { config } from "@/lib/geistdocs/config"; +import { mono, sans } from "@/lib/geistdocs/fonts"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "deepsec - Full-repository security review", + description: + "deepsec is an open source vulnerability scanner that runs coding agents over entire repositories, in your own infrastructure, to find bugs that pull request review never revisits.", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + + + {children} +