---
title: "Lock the Doors"
description: "Make the dispatcher production-safe: understand the fail-closed auth guarantee, keep the model credential and secrets in env, and confirm an unknown caller gets shut out."
canonical_url: "https://vercel.com/academy/building-agents-with-eve/lock-the-doors"
md_url: "https://vercel.com/academy/building-agents-with-eve/lock-the-doors.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-08-29T02:28:26.270Z"
content_type: "lesson"
course: "building-agents-with-eve"
course_title: "Building Agents with eve"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Lock the Doors

# Lock the Doors

The dispatcher is about to move from your laptop to the public internet. Before deploying, we'll confirm that only recognized callers can reach it.

The auth walk from 4.3 already decides who gets in. This lesson checks what happens to unrecognized callers and confirms that credentials stay out of source code.

## Outcome

You can state exactly what an unauthenticated request to the deployed dispatcher gets, and your model credential and any secrets live in environment variables, not in the repo.

## Hands-on exercise

**Understand fail-closed.** Your `auth` list is `[appAuth, vercelOidc(), localDev()]`. Walk through what each does to a *public production* request from a stranger's browser:

- `appAuth` calls `getCustomer` and finds no valid session → returns `null`, falls through.
- `vercelOidc()` wants a valid Vercel OIDC token the stranger doesn't have → falls through.
- `localDev()` only grants its synthetic principal inside an `eve dev` or `vercel dev` process. Production isn't a dev process → falls through.

Every entry falls through, so eve returns a `401`. Routes reject any request that no authenticator explicitly accepts. Unrecognized traffic is denied by default.

\*\*Warning: Why localDev() is safe to leave in production\*\*

`localDev()` keys off the running process, not the request hostname. `eve dev` sets the local-development context; `eve start` and deployed production do not. A forged `Host` header cannot turn production into local development. Keep `vercelOidc()` before `localDev()` so local requests carrying real Vercel identity are not replaced by the synthetic dev principal.

\*\*Note: The scaffold ships placeholderAuth() for this reason\*\*

A fresh eve project starts with `placeholderAuth()` in the walk. In production, it returns a clear "auth isn't configured yet" `401` so a half-built app fails closed. You replaced it with real auth in 4.3.

**Keep secrets in env.** The dispatcher needs exactly one credential to run: a model key. The easy, secret-free path is the Vercel AI Gateway, link a Vercel project and a gateway id like `anthropic/claude-opus-4.8` authenticates through OIDC, with no provider key to store anywhere:

```bash
npx eve link   # links this directory to a Vercel project and pulls Gateway creds
```

Anything sensitive your real `getCustomer` would use (a session-signing secret, a JWT key) belongs in Vercel's environment variables, never in source. Route-auth secrets are re-materialized from env at boot and never baked into the build artifacts.

## Try It

Confirm the production policy before you deploy: `appAuth` is first, authenticated Vercel identity comes next, and the process-only development fallback is last. Do not try to prove this by changing the `Host` header under `eve dev`: that process deliberately enables `localDev()`, regardless of hostname. You'll exercise the real `401` and authenticated `202` against the deployment in 5.2.

Now sweep for secrets you don't want in git:

```bash
git grep -nEi '(sk-[a-z0-9]{16,}|(api[_-]?key|secret)[[:space:]]*=[[:space:]]*[^[:space:]]{8,})' \
  -- . ':!package-lock.json' || echo "clean"
```

\*\*Note: Production-safe is mostly verifying, not adding\*\*

Notice you barely wrote code here. eve's defaults, fail-closed routes, secrets re-materialized from env, OIDC model auth, do the heavy lifting. "Hardening for production" is largely confirming the framework's safe defaults are still in force and that you didn't paste a key somewhere.

If the sweep finds a real value, remove it from source, rotate it, and put the replacement in Vercel environment variables. If you can't reach a model after linking, run `eve link` again and confirm the project has AI Gateway access.

## Done-When

- [ ] You can explain why an unknown production caller falls through every authenticator to `401`.
- [ ] The auth order is `[appAuth, vercelOidc(), localDev()]`.
- [ ] The model credential comes from a linked Vercel project / env, not source.
- [ ] `git grep` for secrets comes back clean.

## Solution

There's no new file here. The solution is the auth walk you wrote in 4.3, now verified as the production lock:

```ts title="agent/channels/eve.ts (unchanged from 4.3)"
export default eveChannel({
  auth: [appAuth, vercelOidc(), localDev()],
});
```

`appAuth` admits customers. `vercelOidc()` covers authenticated Vercel traffic, and `localDev()` only activates in the dev process. Everything else receives the fail-closed `401`. With credentials in the environment, the dispatcher is ready to deploy.


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
