Token导航 LogoToken导航

Agent Skill · 开发规范

better-auth-best-practices(更好的身份验证最佳实践)

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

better-auth-best-practices 是开发规范类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为接触敏感数据;许可证信息还不明确,第三方扫描已通过,按安装量在开发规范类的 1,265 个 Skill 里排第 638。

总安装 679周安装 28GitHub Stars 4下载 222核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:better-auth-best-practices(更好的身份验证最佳实践)
来源仓库:https://github.com/autumnsgrove/groveengine
仓库路径:skills/better-auth-best-practices
安装命令:
npx skills add https://github.com/autumnsgrove/groveengine --skill better-auth-best-practices
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/autumnsgrove/groveengine --skill better-auth-best-practices

这个 Skill 是做什么的

开发规范类 Skill 用来统一代码风格、目录结构和评审口径,产出多为检查清单或改写建议。

better-auth-best-practices 用于辅助安全审计、权限检查和认证流程漏洞排查,提供 Better Auth 框架的最佳实践参考。涵盖配置加固、速率限制、会话管理、插件集成和生产部署模式,强化身份验证安全性。可协助设置二次验证、邮箱验证、OAuth 集成和 Cookie 安全策略,降低账户风险。

使用时不能将工具输出直接当作最终结论,需结合人工复核敏感配置和操作边界。涉及用户数据或生产系统时,应先确认最小权限原则和脱敏处理,避免越权访问。

来源仓库内路径:skills/better-auth-best-practices

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/autumnsgrove/groveengine --skill better-auth-b…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

better-auth-best-practices 怎么安装?

在终端执行 npx skills add https://github.com/autumnsgrove/groveengine --skill better-auth-best-practi…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

better-auth-best-practices 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

better-auth-best-practices 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

better-auth-best-practices 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

better-auth-best-practices 用的人多吗?

公开数据是累计安装 679 次,近一周安装 28 次,下载 222 次,GitHub 4 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

better-auth-best-practices 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发规范类任务、又不想每次都手写提示词的人。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发规范类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
vercel-react-best-practices

Vercel React 最佳实践 · Codex、Claude

8,490,72025,918操作浏览器MIT通过
web-design-guidelines

网页设计指南 · Codex、Claude

6,686,01625,885需要联网MIT有提醒
remotion-best-practices

Remotion 最佳实践 · Codex、Claude

6,505,6323,027操作浏览器MIT有提醒
supabase-postgres-best-practices

Supabase Postgres 最佳实践 · Codex、Claude

3,175,5232,030需要联网MIT通过
next-best-practices

Next.js 最佳实践 · Codex、Claude

1,848,240841操作浏览器MIT通过
better-auth-best-practices

更好的身份验证最佳实践 · 本页

6794接触敏感数据未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Better Auth Best Practices

Comprehensive reference for the Better Auth framework. Covers configuration, security hardening, rate limiting, session management, plugins, and production deployment patterns.

Canonical docs: better-auth.com/docs Source: Synthesized from better-auth/skills (official upstream) + Grove production experience.

When to Activate

  • Configuring or modifying Better Auth server/client setup
  • Auditing auth security (pair with raccoon-audit, turtle-harden)
  • Adding or configuring rate limiting
  • Setting up session management, cookie caching, or secondary storage
  • Adding plugins (2FA, organizations, passkeys, etc.)
  • Troubleshooting auth issues on Heartwood or any Better Auth deployment
  • Reviewing security posture before production deploy

Pair with: heartwood-auth (Grove-specific integration), spider-weave (auth architecture), turtle-harden (deep security)


Grove Context: Heartwood

Heartwood is Grove's auth service, powered by Better Auth on Cloudflare Workers.

ComponentDetail
Frontendheartwood.grove.place
APIauth-api.grove.place
DatabaseCloudflare D1 (SQLite)
Session cacheCloudflare KV (SESSION_KV)
ProvidersGoogle OAuth, Magic Links, Passkeys
Cookie domain.grove.place (cross-subdomain SSO)

Everything in this skill applies directly to Heartwood. The heartwood-auth skill covers Grove-specific integration patterns (client setup, route protection, error codes). This skill covers the framework itself.


Quick Reference

Environment Variables

VariablePurpose
BETTER_AUTH_SECRETEncryption secret (min 32 chars). Generate: openssl rand -base64 32
BETTER_AUTH_URLBase URL (e.g., https://auth-api.grove.place)
BETTER_AUTH_TRUSTED_ORIGINSComma-separated trusted origins

Only define baseURL/secret in config if env vars are NOT set.

File Location

CLI looks for auth.ts in: ./, ./lib, ./utils, or under ./src. Use --config for custom path.

CLI Commands

npx @better-auth/cli@latest migrate    # Apply schema (built-in adapter)
npx @better-auth/cli@latest generate   # Generate schema for Prisma/Drizzle

Re-run after adding/changing plugins.


Core Configuration

OptionNotes
appNameDisplay name (used in 2FA issuer, emails)
baseURLOnly if BETTER_AUTH_URL not set
basePathDefault /api/auth. Set / for root
secretOnly if BETTER_AUTH_SECRET not set
databaseRequired. Connection or adapter instance
secondaryStorageRedis/KV for sessions & rate limits
emailAndPassword{enabled: true} to activate
socialProviders{google: {clientId, clientSecret},...}
pluginsArray of plugins
trustedOriginsCSRF whitelist (baseURL auto-trusted)

Database

Direct connections: Pass pg.Pool, mysql2 pool, better-sqlite3, or bun:sqlite instance.

ORM adapters: Import from better-auth/adapters/drizzle, better-auth/adapters/prisma, better-auth/adapters/mongodb.

Critical gotcha: Better Auth uses adapter model names, NOT underlying table names. If Prisma model is User mapping to table users, use modelName: "user" (Prisma reference), not "users".


Rate Limiting

Better Auth has built-in rate limiting — enabled by default in production, disabled in development.

Why This Matters for Grove

Better Auth's rate limiter can replace custom threshold SDKs for auth endpoints. It's battle-tested, configurable per-endpoint, and integrates directly with the auth layer where it matters most.

Default Configuration

import { betterAuth } from "better-auth";

export const auth = betterAuth({
  rateLimit: {
    enabled: true,       // Default: true in production
    window: 10,          // Time window in seconds (default: 10)
    max: 100,            // Max requests per window (default: 100)
  },
});

Storage Options

rateLimit: {
  storage: "secondary-storage", // Best for production
}
StorageBehavior
"memory"Fast, resets on restart. Not recommended for serverless.
"database"Persistent, adds DB load
"secondary-storage"Uses configured KV/Redis. Default when available.

For Heartwood: Use "secondary-storage" backed by Cloudflare KV.

Per-Endpoint Rules

Better Auth applies stricter defaults to sensitive endpoints:

  • /sign-in, /sign-up, /change-password, /change-email: 3 requests per 10 seconds

Override for specific paths:

rateLimit: {
  customRules: {
    "/api/auth/sign-in/email": {
      window: 60,  // 1 minute
      max: 5,      // 5 attempts
    },
    "/api/auth/sign-up/email": {
      window: 60,
      max: 3,      // Very strict for registration
    },
    "/api/auth/some-safe-endpoint": false, // Disable rate limiting
  },
}

Custom Storage

For non-standard backends:

rateLimit: {
  customStorage: {
    get: async (key) => {
      // Return { count: number, expiresAt: number } or null
    },
    set: async (key, data) => {
      // Store the rate limit data
    },
  },
}

Each plugin can optionally define its own rate-limit rules per endpoint.


Session Management

Storage Priority

  1. If secondaryStorage defined → sessions go there (not DB)
  2. Set session.storeSessionInDatabase: true to also persist to DB
  3. No database + cookieCache → fully stateless mode

Key Options

session: {
  expiresIn: 60 * 60 * 24 * 7,   // 7 days (default)
  updateAge: 60 * 60 * 24,        // Refresh every 24 hours (default)
  freshAge: 60 * 60 * 24,         // 24 hours for sensitive actions (default)
}

freshAge — defines how recently a user must have authenticated to perform sensitive operations. Use to require re-auth for password changes, viewing sensitive data, etc.

Cookie Cache Strategies

Cache session data in cookies to reduce DB/KV queries:

session: {
  cookieCache: {
    enabled: true,
    maxAge: 60 * 5,        // 5 minutes
    strategy: "compact",   // Options: "compact", "jwt", "jwe"
    version: 1,            // Change to invalidate all sessions
  },
}
StrategyDescription
compactBase64url + HMAC. Smallest size. Default.
jwtStandard HS256 JWT. Readable but signed.
jweA256CBC-HS512 encrypted. Maximum security.

Gotcha: Custom session fields are NOT cached — they're always re-fetched from storage.


Security Configuration

Secret Management

Better Auth looks for secrets in order:

  1. options.secret in config
  2. BETTER_AUTH_SECRET env var
  3. AUTH_SECRET env var

Requirements:

  • Rejects default/placeholder secrets in production
  • Warns if shorter than 32 characters
  • Warns if entropy below 120 bits

CSRF Protection

Multi-layered by default:

  1. Origin header validation — Origin/Referer must match trusted origins
  2. Fetch metadata — Uses Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest headers
  3. First-login protection — Validates origin even without cookies
advanced: {
  disableCSRFCheck: false,  // KEEP THIS FALSE
}

Trusted Origins

trustedOrigins: [
  "https://app.grove.place",
  "https://*.grove.place",          // Wildcard subdomain
  "exp://192.168.*.*:*/*",          // Custom schemes (Expo)
]

Dynamic computation:

trustedOrigins: async (request) => {
  const tenant = getTenantFromRequest(request);
  return [`https://${tenant}.grove.place`];
}

Validated parameters: callbackURL, redirectTo, errorCallbackURL, newUserCallbackURL, origin, and more. Invalid URLs get 403.

Cookie Security

Defaults are secure:

  • secure: true when baseURL uses HTTPS or in production
  • sameSite: "lax" (CSRF prevention while allowing navigation)
  • httpOnly: true (no JavaScript access)
  • __Secure- prefix when secure is enabled
advanced: {
  useSecureCookies: true,
  cookiePrefix: "better-auth",
  defaultCookieAttributes: {
    sameSite: "lax",
  },
  crossSubDomainCookies: {
    enabled: true,
    domain: ".grove.place",  // Note the leading dot
    additionalCookies: ["session_token", "session_data"],
  },
}

Warning: Cross-subdomain cookies expand attack surface. Only enable if you trust all subdomains.

IP-Based Security

advanced: {
  ipAddress: {
    ipAddressHeaders: ["x-forwarded-for", "x-real-ip"],
    ipv6Subnet: 64,            // Group IPv6 by /64
    disableIpTracking: false,  // Keep enabled for rate limiting
  },
  trustedProxyHeaders: true,   // Only if behind a trusted proxy
}

Background Tasks (Timing Attack Prevention)

Sensitive operations should complete in constant time. The handler callback receives a promise that must outlive the response — on serverless platforms, you need the platform's waitUntil to keep it alive.

Cloudflare Workers: Capture ExecutionContext from the fetch handler and close over it:

// In your Worker fetch handler:
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    // Create auth with ctx in scope
    const auth = createAuth(env, ctx);
    return auth.handler(request);
  },
};

// In your auth config factory:
function createAuth(env: Env, ctx: ExecutionContext) {
  return betterAuth({
    // ...
    advanced: {
      backgroundTasks: {
        handler: (promise) => ctx.waitUntil(promise),
      },
    },
  });
}

Vercel/Next.js: Use the waitUntil export from @vercel/functions:

import { waitUntil } from "@vercel/functions";

advanced: {
  backgroundTasks: {
    handler: (promise) => waitUntil(promise),
  },
}

Ensures email sending doesn't leak information about whether a user exists.

Account Enumeration Prevention

Built-in protections:

  1. Consistent response messages — Password reset always returns generic message
  2. Dummy operations — When user isn't found, still performs token generation + DB lookups
  3. Background email sending — Async to prevent timing differences

OAuth / Social Provider Security

PKCE (Automatic)

Better Auth automatically uses PKCE for all OAuth flows:

  1. Generates 128-character random code_verifier
  2. Creates code_challenge using S256 (SHA-256)
  3. Validates code exchange with original verifier

State Parameter

account: {
  storeStateStrategy: "cookie",  // "cookie" (default) or "database"
}

State tokens: 32-character random strings, expire after 10 minutes, contain encrypted callback URLs + PKCE verifier.

Encrypt Stored OAuth Tokens

account: {
  encryptOAuthTokens: true,  // AES-256-GCM
}

Enable if you store OAuth tokens for API access on behalf of users.


Email & Password

Email Verification

emailVerification: {
  sendVerificationEmail: async ({ user, url }) => {
    await sendEmail({ to: user.email, subject: "Verify your email", url });
  },
  sendOnSignUp: true,
  requireEmailVerification: true,  // Blocks sign-in until verified
}

Password Reset

emailAndPassword: {
  sendResetPassword: async ({ user, url }) => {
    await sendEmail({ to: user.email, subject: "Reset your password", url });
  },
  password: {
    minLength: 8,   // Default
    maxLength: 128,  // Default
  },
  revokeSessionsOnPasswordReset: true,  // Log out all sessions
}

Security: Reset tokens are 24-character alphanumeric strings, expire after 1 hour, single-use.

Password Hashing

Default: scrypt. For Argon2id, provide custom hash and verify functions.


Two-Factor Authentication

Setup

import { twoFactor } from "better-auth/plugins";

// Server
plugins: [
  twoFactor({
    issuer: "Grove",  // Shown in authenticator apps
    totpOptions: { digits: 6, period: 30 },
    backupCodeOptions: { amount: 10, length: 10, storeBackupCodes: "encrypted" },
  }),
]

// Client
plugins: [
  twoFactorClient({
    onTwoFactorRedirect() {
      window.location.href = "/2fa";
    },
  }),
]

Run migrations after adding. The twoFactorEnabled flag only activates after successful TOTP verification.

Sign-In Flow with 2FA

  1. User signs in with credentials
  2. Response includes twoFactorRedirect: true
  3. Session cookie removed temporarily
  4. Two-factor cookie set (10-minute expiration)
  5. User verifies via TOTP/OTP/backup code
  6. Session cookie restored

Trusted Devices

Skip 2FA on subsequent sign-ins:

twoFactor({
  trustDeviceMaxAge: 30 * 24 * 60 * 60,  // 30 days
})

// During verification:
await authClient.twoFactor.verifyTotp({ code, trustDevice: true });

OTP (Email/SMS)

twoFactor({
  otpOptions: {
    sendOTP: async ({ user, otp }) => {
      await sendEmail({ to: user.email, subject: "Your code", text: `Code: ${otp}` });
    },
    period: 5,            // Minutes
    digits: 6,
    allowedAttempts: 5,
    storeOTP: "encrypted",
  },
})

Built-in 2FA Protections

  • Rate limiting: 3 requests per 10 seconds on 2FA endpoints
  • OTP attempt limiting: configurable max attempts
  • Constant-time comparison prevents timing attacks
  • TOTP secrets encrypted with symmetric encryption
  • Backup codes encrypted by default
  • Limitation: 2FA requires credential accounts — social-only accounts can't enable it

Organizations Plugin

Multi-tenant organization support:

import { organization } from "better-auth/plugins";

plugins: [
  organization({
    // Limit who can create orgs
    allowUserToCreateOrganization: async (user) => {
      return user.emailVerified;
    },
  }),
]

Key Concepts

  • Active organization stored in session — scopes API calls after setActive()
  • Default roles: owner (full), admin (management), member (basic)
  • Dynamic access control for custom runtime permissions
  • Teams group members within organizations
  • Invitations expire after 48 hours (configurable), email-specific
  • Safety: Last owner cannot be removed or leave

Plugins Reference

import { twoFactor, organization } from "better-auth/plugins";
PluginPurposeScoped Package?
twoFactorTOTP/OTP/backup codesNo
organizationTeams & multi-tenantNo
passkeyWebAuthn@better-auth/passkey
magicLinkPasswordless emailNo
emailOtpEmail-based OTPNo
usernameUsername authNo
phoneNumberPhone authNo
adminUser managementNo
apiKeyAPI key authNo
bearerBearer token authNo
jwtJWT tokensNo
multiSessionMultiple sessionsNo
ssoSAML/OIDC enterprise@better-auth/sso
oauthProviderBe an OAuth providerNo
oidcProviderBe an OIDC providerNo
openAPIAPI documentationNo
genericOAuthCustom OAuth providerNo

Client plugins go in createAuthClient({plugins: [...]}).

Always run migrations after adding plugins.


Client Setup

Import by framework:

FrameworkImport
React/Next.jsbetter-auth/react
Svelte/SvelteKitbetter-auth/svelte
Vue/Nuxtbetter-auth/vue
Solidbetter-auth/solid
Vanilla JSbetter-auth/client

Key methods: signUp.email(), signIn.email(), signIn.social(), signOut(), useSession(), getSession(), revokeSession(), revokeSessions().

Type Safety

// Infer types from server config
type Session = typeof auth.$Infer.Session;
type User = typeof auth.$Infer.Session.user;

// For separate client/server projects
createAuthClient<typeof auth>();

Hooks

Endpoint Hooks

hooks: {
  before: [
    {
      matcher: (ctx) => ctx.path === "/sign-in/email",
      handler: createAuthMiddleware(async (ctx) => {
        // Access: ctx.path, ctx.context.session, ctx.context.secret
        // Return modified context or void
      }),
    },
  ],
  after: [
    {
      matcher: (ctx) => true,
      handler: createAuthMiddleware(async (ctx) => {
        // Access: ctx.context.returned (response data)
      }),
    },
  ],
}

Database Hooks

databaseHooks: {
  user: {
    create: {
      before: async ({ data }) => { /* add defaults, return false to block */ },
      after: async ({ data }) => { /* audit log, send welcome email */ },
    },
  },
  session: {
    create: {
      after: async ({ data, ctx }) => {
        await auditLog("session.created", {
          userId: data.userId,
          ip: ctx?.request?.headers.get("x-forwarded-for"),
        });
      },
    },
  },
}

Hook context (ctx.context): session, secret, authCookies, password.hash()/verify(), adapter, internalAdapter, generateId(), tables, baseURL.


Common Gotchas

  1. Model vs table name — Config uses ORM model name, not DB table name
  2. Plugin schema — Re-run CLI after adding plugins (always!)
  3. Secondary storage — Sessions go there by default, not DB
  4. Cookie cache — Custom session fields NOT cached, always re-fetched
  5. Stateless mode — No DB = session in cookie only, logout on cache expiry
  6. Change email flow — Sends to current email first, then new email
  7. 2FA + social — 2FA only works on credential accounts, not social-only
  8. Last owner — Cannot be removed from or leave an organization
  9. Rate limit memory — Memory storage resets on restart, bad for serverless

Production Security Checklist

  • BETTER_AUTH_SECRET set (32+ chars, high entropy)
  • BETTER_AUTH_URL uses HTTPS
  • trustedOrigins configured for all valid origins
  • Rate limiting enabled with appropriate per-endpoint limits
  • Rate limit storage set to "secondary-storage" or "database" (not memory)
  • CSRF protection enabled (disableCSRFCheck: false)
  • Secure cookies enabled (automatic with HTTPS)
  • account.encryptOAuthTokens: true if storing tokens
  • Background tasks configured for serverless (capture ExecutionContext from fetch handler)
  • Audit logging via databaseHooks or hooks
  • IP tracking headers configured if behind proxy
  • Email verification enabled
  • Password reset implemented
  • 2FA available for sensitive apps
  • Session expiry and refresh intervals reviewed
  • Cookie cache strategy chosen (jwe for sensitive session data)
  • account.accountLinking reviewed

Complete Production Config Example

import { betterAuth } from "better-auth";
import { twoFactor, organization } from "better-auth/plugins";

// Factory pattern — ctx comes from the Worker fetch handler
export function createAuth(env: Env, ctx: ExecutionContext) {
  return betterAuth({
    appName: "Grove",
    secret: env.BETTER_AUTH_SECRET,
    baseURL: "https://auth-api.grove.place",
    trustedOrigins: [
      "https://heartwood.grove.place",
      "https://*.grove.place",
    ],

    database: d1Adapter(env),
    secondaryStorage: kvAdapter(env),

    // Rate limiting (replaces custom threshold SDK for auth)
    rateLimit: {
      enabled: true,
      storage: "secondary-storage",
      customRules: {
        "/api/auth/sign-in/email": { window: 60, max: 5 },
        "/api/auth/sign-up/email": { window: 60, max: 3 },
        "/api/auth/change-password": { window: 60, max: 3 },
      },
    },

    // Sessions
    session: {
      expiresIn: 60 * 60 * 24 * 7,    // 7 days
      updateAge: 60 * 60 * 24,         // 24 hours
      freshAge: 60 * 60,               // 1 hour for sensitive actions
      cookieCache: {
        enabled: true,
        maxAge: 300,
        strategy: "jwe",
      },
    },

    // OAuth
    account: {
      encryptOAuthTokens: true,
      storeStateStrategy: "cookie",
    },

    // Security
    advanced: {
      useSecureCookies: true,
      crossSubDomainCookies: {
        enabled: true,
        domain: ".grove.place",
      },
      ipAddress: {
        ipAddressHeaders: ["x-forwarded-for"],
        ipv6Subnet: 64,
      },
      backgroundTasks: {
        handler: (promise) => ctx.waitUntil(promise),  // ctx captured from fetch handler
      },
    },

    // Plugins
    plugins: [
      twoFactor({
        issuer: "Grove",
        backupCodeOptions: { storeBackupCodes: "encrypted" },
      }),
      organization(),
    ],

    // Audit hooks
    databaseHooks: {
      session: {
        create: {
          after: async ({ data, ctx: hookCtx }) => {
            console.log(`[audit] session created: user=${data.userId}`);
          },
        },
      },
    },
  });
}

Resources

平台分布

Codex

37.18%
按下载量换算83

Claude

28%
按下载量换算62

Cursor

18.54%
按下载量换算41

Gemini CLI

8.07%
按下载量换算18

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills