Daoyou Hono API、认证、授权、Better Auth、Turnstile、admin、internal cron、LLM header 安全和服务端输入校验指南。Use when adding or modifying src/server routes, middleware, auth, admin endpoints, cron/internal endpoints, shared contracts, LLM provider handling, API validation, or security-relevant frontend auth/admin loaders in this repo. For ordinary admin pages, navigation, and UI state, use daoyou-frontend-routing-state.
Installation
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Daoyou Hono API、认证、授权、Better Auth、Turnstile、admin、internal cron、LLM header 安全和服务端输入校验指南。Use when adding or modifying src/server routes, middleware, auth, admin endpoints, cron/internal endpoints, shared contracts, LLM provider handling, API validation, or security-relevant frontend auth/admin loaders in this repo. For ordinary admin pages, navigation, and UI state, use daoyou-frontend-routing-state.
Daoyou Backend API Security
Read First
src/server/app.ts
src/server/routes/api/index.ts
src/server/routes/internal/cron.router.ts
src/server/lib/hono/middleware.ts
src/server/lib/auth/auth.ts
src/server/lib/auth/hono.ts
src/server/lib/llm/allowedHosts.ts
src/shared/config/llmProviders.ts
src/shared/contracts
Existing route/service tests near the target endpoint
API Boundary Facts
API server is Hono.
/api/auth/* is handled by Better Auth through src/server/lib/auth/hono.ts.
jsonError() handles Zod errors and uncaught API errors for /api/* and /internal/*, but auth is registered before that middleware.
Frontend route loaders are UX guards only. Backend handlers are the security boundary.
Existing auth middleware:
requireUser() for logged-in users.
requireActiveCultivator() for logged-in users with an active cultivator; it sets user, cultivator, and executor.
requireAdmin() for ADMIN_EMAILS allowlist.
validateJson() and validateQuery() for Zod parsing.
Admin subroutes currently apply requireAdmin() explicitly inside handlers.
/internal/cron/* uses Authorization: Bearer ${CRON_SECRET}, not user sessions. In production, missing CRON_SECRET returns 500.
LLM Security Facts
The browser patches window.fetch in src/react-app/main.tsx to add x-llm-* headers for /api/ requests.
Server LLM calls should use src/server/utils/aiClient.ts (text, stream_text, object, objectArray, tool) so provider resolution, metrics, schema prompt injection, retry, and jsonrepair stay in one path.
Server accepts user LLM config only when provider, apiKey, model, and fastModel are present.
Non-empty x-llm-base-url must pass HTTPS and hostname whitelist validation in src/server/lib/llm/allowedHosts.ts.
The whitelist source of truth is src/shared/config/llmProviders.ts; do not add a second server-only allowlist.
LLM metrics use in-memory fallback plus Redis key admin:llm-metrics:events:v1; do not add a parallel metrics store.
Prompt files under src/server/prompts/*.md have id: headers. New prompt scenes usually also need LlmSceneId, caller sceneId, schema/constraint, and tests.
Treat LLM output as untrusted input. Numeric state changes need Zod bounds and service/resource-layer guards.
docs/llm-security-defense.md contains useful historical risk analysis, but parts are stale relative to current code.
External Service Facts
Redis access must go through src/server/lib/redis; do not instantiate new Redis() in feature code.
Redis is not optional for many runtime paths even though health-check reports disabled when REDIS_URL is absent.
SMTP mail uses src/server/lib/admin/smtp.ts; required env includes SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, and MAIL_FROM.
Workflow
Classify the endpoint: public, logged-in, active-cultivator, admin, or internal cron.
Reuse the existing middleware. Do not hand-roll session parsing.
Add or reuse Zod schemas for request bodies and query strings.
Register new API routes in src/server/routes/api/index.ts; register internal jobs in src/server/routes/internal.
If the route changes shared request/response shape, update src/shared/contracts or src/shared/types.
If the route calls LLM or consumes LLM output, check prompt/schema bounds and service-layer guards.
If adding a prompt scene, update prompt id, LlmSceneId, caller sceneId, schema/constraint, and tests together.
Add focused route/service tests.
Do Not
Do not rely on React loaders for authorization.
Do not bypass src/server/lib/auth/hono.ts for login, signup, reset, OTP, or Turnstile-protected flows.
Do not add admin files under /api/admin without explicit admin authorization.
Do not read x-llm-base-url directly in business code; use the validated context config.
Do not make public list/ranking/community endpoints private without checking frontend/product usage.
Do not assume src/shared/api exists; shared contracts live under src/shared/contracts.
Do not bypass aiClient.ts for LLM calls.
Do not create feature-local Redis clients or SMTP transports.
Verify
Route/middleware changes: run the nearest route test.
Auth changes: run auth-related tests and manually check cookie/header behavior when relevant.
LLM provider changes: run src/server/lib/llm/allowedHosts.test.ts.
Cron changes: test the route and verify secret behavior for production and non-production assumptions.