secureAction
A wrapper for Server Actions: required authorization, rate limit, size limit and schema inside the action, and a typed result without error messages.
export const renameAgent = secureAction({ authorize: currentUser, schema: z.object({ id: z.string().uuid(), name: z.string().max(80) }), handler: ({ id, name }, user) => db.agents.rename(user.tenantId, id, name),});const result = await renameAgent({ id, name }); // { ok: true, data } | { ok: false, code }Installation
Once per app, set up Aedis UI. The CLI verifies the signed release before writing anything and pins every dependency:
npx @aedis/cli@0.1.0 initImport the theme once in your global CSS, after Tailwind:
app/globals.css
@import "tailwindcss";@import "./styles/aedis-theme.css";Then add the component:
npx @aedis/cli@0.1.0 add secure-action# pnpm dlx @aedis/cli@0.1.0 add secure-action · yarn dlx @aedis/cli@0.1.0 add secure-action · bunx @aedis/cli@0.1.0 add secure-actionProps
| Prop | Type | Default | Description |
|---|---|---|---|
| authorize | () => Ctx | null | — | Required; runs on every call. null answers "unauthorized"; throw ActionError("forbidden") for a caller without the right. |
| schema | StandardSchemaV1 | — | Any Standard Schema validator; the handler only sees its output. Invalid input returns the failing field paths. |
| maxInputBytes | number | 65536 | Serialized size limit, files included, checked before validation. |
| rateLimit | (ctx) => boolean | — | Return false to answer "rate-limited". |
| handler | (input, ctx) => T | — | Throw ActionError("not-found" | "conflict" | …) for an expected failure. |
| taintSecret(message, lifetime, value) | boolean | — | React taint for a token (needs experimental.taint); false when unavailable. |
Security
- Every Server Action is a public POST endpoint: authorization is a required argument and runs inside the action.
- Order: authorize, rate limit, size limit, schema, handler. An anonymous call is never parsed.
- The client gets a code, never an error message; details go to the server log.
- server-only import; see the Server Actions guide for allowedOrigins, bodySizeLimit, the Origin check and secrets in closures.