A drawing of a desk from above at eight in the morning: a cup of coffee, a closed notebook and a phone lying face up. The phone shows one small card: Checked overnight. Nothing affects you.

Most mornings look like this. The check ran overnight and there was nothing to do.

This site is small. It is Next.js on Vercel, and most of it is static pages. School Governance Assurance Framework (SGAF) is not small. It is a live platform that schools and trusts sign in to every day. Neither is safe by default. Both run on frameworks, runtimes and libraries, and every one of them gets security fixes on its own schedule.

I do not have time to read every advisory. So I do not. One of my AI assistants does it for me, and this week gave it two chances to show how it works.

The security assistant

I run a small team of AI assistants. One of them has a single job: watch reputable security advisories and check each one against what my products actually run. Not what I think they run. The exact versions in production. It watches SGAF as well as this site.

That last part matters. Most advisories do not apply to you. The useful question is never "is this bad?" It is "are we in range, and does the vulnerable code actually get used here?"

Triage with Jev

Spotting an advisory is the easy part. Deciding how much it matters, and who should deal with it, is where I use Jev. Jev is a small, fast classification model. It does not write fixes or touch code. It reads the facts and picks from a short, fixed list of labels, with a confidence score for each.

When an advisory matches something I run, the assistant gives Jev the advisory, the product and the exact version in production. Jev answers two questions.

How urgent is it? "Alert now" means exploitable today on something I own. "Next sweep" means real but not urgent, or exposure not yet confirmed. "Ignore" means it does not apply to anything I run.

Who owns it? SGAF, this site, or me, when ownership is unclear, like an old project only I know the status of.

On Friday, Jev labelled this site "alert now" at 0.98 and SGAF "alert now" at 0.89. An old side project came back "next sweep", but only at 0.34. A low score is not an answer, so that one came to me to decide.

Jev's labels only route work. A label never ships anything on its own. Production changes still wait for my yes.

Wednesday: Node.js

On 21 October, Node.js put out security releases. The assistant checked which Node version the site builds on.

The answer was that there was nothing to change in my code. The site uses whatever patched runtime Vercel provides, so the fix arrives when Vercel rolls it out. Redeploying before then would have rebuilt the site on the same old runtime and achieved nothing except a feeling of having done something.

So instead there is a daily check. When Vercel confirms the patched runtime is live, the site gets one redeploy. Not a panic redeploy now, and not a forgotten one later.

Friday: Next.js

This morning the assistant flagged something that did apply.

Production was on Next.js 16.3.4 with sharp 0.35.4. That put it in range of two things. The first was a critical remote code execution issue in next/og, the part of Next.js that generates images on the fly, published as GHSA-vcvr-r3jv-pc5j and fixed in 16.3.6. The second was the Next.js October security update: two more critical remote code execution issues and a high severity denial of service, fixed in 16.4.1.

A table of the two packages that changed. Next.js went from 16.3.4 to 16.4.1. sharp went from 0.35.4 to 0.35.5.

The whole change. Two versions, one pull request.

This site uses next/og. It draws the preview card you see when someone shares a link to a page. So this was not theoretical.

What happened next

The assistant prepared a pull request. One change: Next.js to 16.4.1, with the matching lint config, and the lockfile resolving sharp to 0.35.5. It ran lint and the build. It checked every route that generates a link-preview image and confirmed each one came back with a 200. Vercel built a preview of the branch and it went green.

Then it stopped and asked me.

Nothing reached production until I said yes myself. When I did, it merged the change, ran the production deploy, and pointed my domains at the new deploy explicitly. That step sounds redundant. It is not. I have had custom domains stay attached to an old deploy after a release, which means the fix is "live" and nobody visiting the site is getting it. So the domains get re-pointed every time, on purpose.

Then it checked the live site: the homepage, the www address and a preview image, all served by the new deploy.

Flagged in the morning. Live by about two in the afternoon.

A vertical timeline. Advisory published. Versions checked in production. Not affected, which is where most mornings end. Then the rarer branch: fix prepared, approved by me, live check passed.

Most advisories stop at the third row. When one does not, nothing reaches production until I say yes, and the last check is against the live site.

The rules behind it

None of this is clever. It is a handful of rules I keep.

Agents prepare, a person approves production. The assistant can do everything up to the point where real visitors are affected. That last step is mine. Not because the assistant would get it wrong, but because I am the one who answers for it.

One change per fix. A security pull request does a security fix. No tidying, no "while I was in there". If something breaks, I want to know exactly what caused it, and I want rolling back to undo one thing.

Verify live, not just green. A passing build tells you the code compiled. It does not tell you the domain is serving it. The check that counts is the one against the real address.

Keep the surface small. The less there is to attack, the less there is to patch. My email address is not in the page source. It is put together when you click it, so scrapers do not get it for free. Secrets never go in chat with an assistant. Tokens live in environment settings and nowhere else.

If you run your own site

You do not need a team of assistants for this. You need three things. Something that tells you when an advisory applies to the versions you actually run. A rule that a person signs off production. And a check against the live address after every release.

The advisories will keep coming. The aim is not to panic at each one. It is to have a routine that already knows what to do.

  • security
  • agents
  • operations