Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ This is a **security-focused project**. Follow these rules strictly:

## Versioning

The agentsec version is stamped in **seven** files plus regenerated sample reports. **Never edit them by hand** — always use the bump script. The list lives in [scripts/version-stamps.ts](scripts/version-stamps.ts); the source of truth is `packages/cli/package.json`.
The agentsec version is stamped in **four** files plus regenerated sample reports. **Never edit them by hand** — always use the bump script. The list lives in [scripts/version-stamps.ts](scripts/version-stamps.ts); the source of truth is `packages/cli/package.json`.

```bash
# Bump to a new version (also regenerates examples)
Expand All @@ -125,9 +125,10 @@ What the bump script touches:
- `packages/shared/src/constants.ts` — `AUDIT_VERSION` (used by `--version` and SARIF driver)
- `skills/agentsec/SKILL.md` — GitHub-canonical SKILL.md
- `apps/landing/public/skill.md` — landing site mirror (re-mirrored from SKILL.md every bump)
- `apps/landing/components/{Hero,Header,Footer}.tsx` — UI version chips
- `examples/audit-report.{txt,json,html,sarif}` and the same files in `apps/landing/public/examples/` — regenerated by running the CLI against `e2e/fixtures`

The landing site's UI version chips (Hero, Header, Footer) are **not** stamped — they fetch the latest published version from `https://registry.npmjs.org/agentsec/latest` at request time via [apps/landing/lib/version.ts](apps/landing/lib/version.ts) (Next.js ISR, 1-hour revalidation). If the npm registry is unreachable they fall back to the version imported from `packages/cli/package.json`, so the chips still match the in-repo canonical version even offline.

If you add a new place where the version needs to appear, add an entry to `STAMPS` in `scripts/version-stamps.ts` and the bump + check scripts pick it up automatically.

After bumping: review the diff, commit, then push `main` and the `vX.Y.Z` tag in **separate** pushes (GitHub Actions silently drops the tag-push event when bundled with a branch push, so don't `git push --tags` together with main). The release workflow runs three jobs:
Expand Down
6 changes: 4 additions & 2 deletions apps/landing/app/examples/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Metadata } from "next";
import Link from "next/link";
import { Footer } from "@/components/Footer";
import { Header } from "@/components/Header";
import { getAgentsecVersion } from "@/lib/version";
import { SITE_NAME } from "../_brand/constants";

export const metadata: Metadata = {
Expand Down Expand Up @@ -190,7 +191,8 @@ const ICONS: Record<ArtifactIcon, React.ReactNode> = {
),
};

export default function ExamplesPage(): React.ReactNode {
export default async function ExamplesPage(): Promise<React.ReactNode> {
const version = await getAgentsecVersion();
return (
<>
<a
Expand All @@ -199,7 +201,7 @@ export default function ExamplesPage(): React.ReactNode {
>
Skip to main content
</a>
<Header />
<Header version={version} />
<main id="examples-main">
<ExamplesHero />
<ReportsSection />
Expand Down
8 changes: 5 additions & 3 deletions apps/landing/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { HowItWorks } from "@/components/HowItWorks";
import { Install } from "@/components/Install";
import { Policy } from "@/components/Policy";
import { TenCommandments } from "@/components/TenCommandments";
import { getAgentsecVersion } from "@/lib/version";

export default function Home(): React.ReactNode {
export default async function Home(): Promise<React.ReactNode> {
const version = await getAgentsecVersion();
return (
<>
<a
Expand All @@ -19,10 +21,10 @@ export default function Home(): React.ReactNode {
>
Skip to main content
</a>
<Header />
<Header version={version} />
<HashScroll />
<main id="main">
<Hero />
<Hero version={version} />
<AnimatedTerminal />
<HowItWorks />
<TenCommandments />
Expand Down
5 changes: 3 additions & 2 deletions apps/landing/app/skill-watch/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Metadata } from "next";
import Link from "next/link";
import { Footer } from "@/components/Footer";
import { Header } from "@/components/Header";
import { getAgentsecVersion } from "@/lib/version";
import { SITE_NAME } from "../_brand/constants";
import { OwaspBars } from "./OwaspBars";
import { SkillWatchTable } from "./SkillWatchTable";
Expand Down Expand Up @@ -145,7 +146,7 @@ function slimEntity(e: SkillWatchEntity): SkillWatchEntity {
}

export default async function SkillWatchPage(): Promise<React.ReactNode> {
const skills = await fetchSkillWatch();
const [skills, version] = await Promise.all([fetchSkillWatch(), getAgentsecVersion()]);
const agg = aggregate(skills);
const slimSkills = skills.map(slimEntity);

Expand All @@ -157,7 +158,7 @@ export default async function SkillWatchPage(): Promise<React.ReactNode> {
>
Skip to main content
</a>
<Header />
<Header version={version} />
<main id="skill-watch-main">
<SkillWatchHero count={agg.total} lastScan={agg.mostRecentScan} />
{skills.length === 0 ? (
Expand Down
6 changes: 4 additions & 2 deletions apps/landing/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getAgentsecVersion } from "@/lib/version";
import { Logo } from "./Logo";

type FooterCol = {
Expand Down Expand Up @@ -58,7 +59,8 @@ const COLS: readonly FooterCol[] = [
},
];

export function Footer(): React.ReactNode {
export async function Footer(): Promise<React.ReactNode> {
const version = await getAgentsecVersion();
return (
<footer className="bg-brand-darker border-t border-brand-border pt-16 pb-8">
<div className="max-w-[1200px] mx-auto px-6">
Expand Down Expand Up @@ -111,7 +113,7 @@ export function Footer(): React.ReactNode {
© 2026 AgentSec · Built by Semiotic Labs · MIT licensed
</span>
<span className="text-[13px] font-mono text-brand-dim">
v0.3.2 · <span className="text-brand-green">● operational</span>
v{version} · <span className="text-brand-green">● operational</span>
</span>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions apps/landing/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const NAV_LINKS: readonly NavLink[] = [

const GITHUB_URL = "https://github.com/semiotic-ai/agentsec";

export function Header(): React.ReactNode {
export function Header({ version }: { version: string }): React.ReactNode {
const [isScrolled, setIsScrolled] = useState(false);
const [mobileOpen, setMobileOpen] = useState(false);

Expand Down Expand Up @@ -60,7 +60,7 @@ export function Header(): React.ReactNode {
</span>
<span className="font-semibold text-base tracking-[-0.01em]">AgentSec</span>
<span className="ml-1 inline-flex items-center font-mono text-[11px] tracking-[0.04em] uppercase px-2 py-[3px] rounded-full border border-brand-border bg-brand-secondary text-brand-muted">
v0.3.2
v{version}
</span>
</a>

Expand Down
4 changes: 2 additions & 2 deletions apps/landing/components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const SKILLS: readonly Skill[] = [
{ name: "note-taker", version: "2.0.0", score: 88, grade: "B" },
];

export function Hero(): React.ReactNode {
export function Hero({ version }: { version: string }): React.ReactNode {
return (
<section className="relative overflow-hidden pt-[140px] pb-20">
<div className="bg-grid pointer-events-none absolute inset-0" aria-hidden="true" />
Expand All @@ -43,7 +43,7 @@ export function Hero(): React.ReactNode {
/>
OWASP AST-10 + Web3 Annex
</span>
<span className="text-[13px] text-brand-dim">v0.3.2 · MIT</span>
<span className="text-[13px] text-brand-dim">v{version} · MIT</span>
</div>

<h1 className="font-display mb-6 text-brand-text">
Expand Down
20 changes: 20 additions & 0 deletions apps/landing/lib/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import cliPackageJson from "../../../packages/cli/package.json";

const NPM_REGISTRY_URL = "https://registry.npmjs.org/agentsec/latest";
const REVALIDATE_SECONDS = 3600;
const FALLBACK_VERSION = cliPackageJson.version;

type NpmRegistryResponse = { version?: string };

export async function getAgentsecVersion(): Promise<string> {
try {
const res = await fetch(NPM_REGISTRY_URL, {
next: { revalidate: REVALIDATE_SECONDS },
});
if (!res.ok) return FALLBACK_VERSION;
const data = (await res.json()) as NpmRegistryResponse;
return data.version ?? FALLBACK_VERSION;
} catch {
return FALLBACK_VERSION;
}
}
15 changes: 0 additions & 15 deletions scripts/version-stamps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,6 @@ export const STAMPS: VersionStamp[] = [
description: "Landing site mirror of SKILL.md (served at /skill.md, indexed by ClawHub)",
pattern: "\nversion: {VERSION}\nlicense: MIT\nhomepage:",
},
{
file: "apps/landing/components/Hero.tsx",
description: "Landing hero version chip",
pattern: "v{VERSION} · MIT",
},
{
file: "apps/landing/components/Header.tsx",
description: "Landing header version pill",
pattern: " v{VERSION}\n </span>",
},
{
file: "apps/landing/components/Footer.tsx",
description: "Landing footer version chip",
pattern: "v{VERSION} · <span",
},
];

export function fillPattern(pattern: string, version: string): string {
Expand Down