api-security-best-practices
認証・認可・入力バリデーション・レート制限・一般的なAPIの脆弱性対策など、セキュアなAPI設計パターンを実装します。APIのセキュリティ強化が必要な場面や、設計段階からセキュリティを組み込みたい場合に活用できます。
description の原文を見る
Implement secure API design patterns including authentication, authorization, input validation, rate limiting, and protection against common API vulnerabilities
SKILL.md 本文
API セキュリティ ベストプラクティス
概要
認証、認可、入力検証、レート制限、および一般的な脆弱性からの保護を実装することにより、開発者がセキュアなAPIを構築するためのガイドです。このスキルは REST、GraphQL、および WebSocket API のセキュリティパターンをカバーしています。
このスキルを使用する場合
- 新しい API エンドポイントを設計する際に使用
- 既存の API をセキュアにする際に使用
- 認証と認可を実装する際に使用
- API 攻撃(インジェクション、DDoS など)から保護する際に使用
- API セキュリティレビューを実施する際に使用
- セキュリティ監査に向けて準備する際に使用
- レート制限とスロットリングを実装する際に使用
- API で機密データを処理する際に使用
動作方法
ステップ 1: 認証と認可
セキュアな認証の実装をサポートします:
- 認証方法を選択(JWT、OAuth 2.0、API キー)
- トークンベースの認証を実装
- ロールベースアクセス制御(RBAC)を設定
- セキュアなセッション管理
- 多要素認証(MFA)を実装
ステップ 2: 入力検証とサニタイズ
インジェクション攻撃から保護:
- すべての入力データを検証
- ユーザー入力をサニタイズ
- パラメータ化されたクエリを使用
- リクエストスキーマ検証を実装
- SQL インジェクション、XSS、コマンドインジェクションを防止
ステップ 3: レート制限とスロットリング
悪用と DDoS 攻撃を防止:
- ユーザー/IP ごとのレート制限を実装
- API スロットリングを設定
- リクエストクォータを設定
- レート制限エラーを適切に処理
- 疑わしいアクティビティを監視
ステップ 4: データ保護
機密データをセキュアに:
- 転送中のデータを暗号化(HTTPS/TLS)
- 保存時に機密データを暗号化
- 適切なエラーハンドリングを実装(データ漏洩なし)
- エラーメッセージをサニタイズ
- セキュアなヘッダーを使用
ステップ 5: API セキュリティテスト
セキュリティ実装を検証:
- 認証と認可をテスト
- ペネトレーションテストを実施
- 一般的な脆弱性(OWASP API Top 10)をチェック
- 入力処理を検証
- レート制限をテスト
例
例 1: JWT 認証の実装
## セキュアな JWT 認証実装
### 認証フロー
1. ユーザーが認証情報でログイン
2. サーバーが認証情報を検証
3. サーバーが JWT トークンを生成
4. クライアントがトークンを安全に保存
5. クライアントが各リクエストでトークンを送信
6. サーバーがトークンを検証
### 実装
#### 1. セキュアな JWT トークンを生成
\`\`\`javascript
// auth.js
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
// ログインエンドポイント
app.post('/api/auth/login', async (req, res) => {
try {
const { email, password } = req.body;
// 入力を検証
if (!email || !password) {
return res.status(400).json({
error: 'メールアドレスとパスワードは必須です'
});
}
// ユーザーを検索
const user = await db.user.findUnique({
where: { email }
});
if (!user) {
// ユーザーが存在するかを明かさない
return res.status(401).json({
error: '認証情報が無効です'
});
}
// パスワードを検証
const validPassword = await bcrypt.compare(
password,
user.passwordHash
);
if (!validPassword) {
return res.status(401).json({
error: '認証情報が無効です'
});
}
// JWT トークンを生成
const token = jwt.sign(
{
userId: user.id,
email: user.email,
role: user.role
},
process.env.JWT_SECRET,
{
expiresIn: '1h',
issuer: 'your-app',
audience: 'your-app-users'
}
);
// リフレッシュトークンを生成
const refreshToken = jwt.sign(
{ userId: user.id },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: '7d' }
);
// リフレッシュトークンをデータベースに保存
await db.refreshToken.create({
data: {
token: refreshToken,
userId: user.id,
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
}
});
res.json({
token,
refreshToken,
expiresIn: 3600
});
} catch (error) {
console.error('ログインエラー:', error);
res.status(500).json({
error: 'ログイン中にエラーが発生しました'
});
}
});
\`\`\`
#### 2. JWT トークンを検証(ミドルウェア)
\`\`\`javascript
// middleware/auth.js
const jwt = require('jsonwebtoken');
function authenticateToken(req, res, next) {
// ヘッダーからトークンを取得
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({
error: 'アクセストークンが必要です'
});
}
// トークンを検証
jwt.verify(
token,
process.env.JWT_SECRET,
{
issuer: 'your-app',
audience: 'your-app-users'
},
(err, user) => {
if (err) {
if (err.name === 'TokenExpiredError') {
return res.status(401).json({
error: 'トークンの有効期限が切れています'
});
}
return res.status(403).json({
error: 'トークンが無効です'
});
}
// ユーザーをリクエストに追加
req.user = user;
next();
}
);
}
module.exports = { authenticateToken };
\`\`\`
#### 3. ルートを保護
\`\`\`javascript
const { authenticateToken } = require('./middleware/auth');
// 保護されたルート
app.get('/api/user/profile', authenticateToken, async (req, res) => {
try {
const user = await db.user.findUnique({
where: { id: req.user.userId },
select: {
id: true,
email: true,
name: true,
// passwordHash は返さない
}
});
res.json(user);
} catch (error) {
res.status(500).json({ error: 'サーバーエラー' });
}
});
\`\`\`
#### 4. トークンリフレッシュを実装
\`\`\`javascript
app.post('/api/auth/refresh', async (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(401).json({
error: 'リフレッシュトークンが必要です'
});
}
try {
// リフレッシュトークンを検証
const decoded = jwt.verify(
refreshToken,
process.env.JWT_REFRESH_SECRET
);
// リフレッシュトークンがデータベースに存在するかを確認
const storedToken = await db.refreshToken.findFirst({
where: {
token: refreshToken,
userId: decoded.userId,
expiresAt: { gt: new Date() }
}
});
if (!storedToken) {
return res.status(403).json({
error: 'リフレッシュトークンが無効です'
});
}
// 新しいアクセストークンを生成
const user = await db.user.findUnique({
where: { id: decoded.userId }
});
const newToken = jwt.sign(
{
userId: user.id,
email: user.email,
role: user.role
},
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
res.json({
token: newToken,
expiresIn: 3600
});
} catch (error) {
res.status(403).json({
error: 'リフレッシュトークンが無効です'
});
}
});
\`\`\`
### セキュリティ ベストプラクティス
- ✅ 強力な JWT シークレットを使用(最小256ビット)
- ✅ 短い有効期限を設定(アクセストークンは1時間)
- ✅ 長い有効期間のセッション用にリフレッシュトークンを実装
- ✅ リフレッシュトークンをデータベースに保存(失効可能)
- ✅ HTTPS のみを使用
- ✅ 機密データを JWT ペイロードに保存しない
- ✅ トークン発行者とオーディエンスを検証
- ✅ ログアウト用のトークンブラックリストを実装
例 2: 入力検証と SQL インジェクション防止
## SQL インジェクション防止と入力検証
### 問題
**❌ 脆弱なコード:**
\`\`\`javascript
// 絶対にしないでください - SQL インジェクション脆弱性
app.get('/api/users/:id', async (req, res) => {
const userId = req.params.id;
// 危険:ユーザー入力がクエリに直接含まれている
const query = \`SELECT * FROM users WHERE id = '\${userId}'\`;
const user = await db.query(query);
res.json(user);
});
// 攻撃例:
// GET /api/users/1' OR '1'='1
// すべてのユーザーが返される!
\`\`\`
### 解決法
#### 1. パラメータ化されたクエリを使用
\`\`\`javascript
// ✅ 安全:パラメータ化クエリ
app.get('/api/users/:id', async (req, res) => {
const userId = req.params.id;
// 最初に入力を検証
if (!userId || !/^\d+$/.test(userId)) {
return res.status(400).json({
error: 'ユーザー ID が無効です'
});
}
// パラメータ化されたクエリを使用
const user = await db.query(
'SELECT id, email, name FROM users WHERE id = $1',
[userId]
);
if (!user) {
return res.status(404).json({
error: 'ユーザーが見つかりません'
});
}
res.json(user);
});
\`\`\`
#### 2. ORM で適切なエスケープを使用
\`\`\`javascript
// ✅ 安全:Prisma ORM を使用
app.get('/api/users/:id', async (req, res) => {
const userId = parseInt(req.params.id);
if (isNaN(userId)) {
return res.status(400).json({
error: 'ユーザー ID が無効です'
});
}
const user = await prisma.user.findUnique({
where: { id: userId },
select: {
id: true,
email: true,
name: true,
// 機密フィールドは選択しない
}
});
if (!user) {
return res.status(404).json({
error: 'ユーザーが見つかりません'
});
}
res.json(user);
});
\`\`\`
#### 3. Zod で リクエスト検証を実装
\`\`\`javascript
const { z } = require('zod');
// 検証スキーマを定義
const createUserSchema = z.object({
email: z.string().email('メールアドレスの形式が無効です'),
password: z.string()
.min(8, 'パスワードは最低8文字です')
.regex(/[A-Z]/, 'パスワードに大文字を含む必要があります')
.regex(/[a-z]/, 'パスワードに小文字を含む必要があります')
.regex(/[0-9]/, 'パスワードに数字を含む必要があります'),
name: z.string()
.min(2, '名前は最低2文字です')
.max(100, '名前が長すぎます'),
age: z.number()
.int('年齢は整数である必要があります')
.min(18, '18歳以上である必要があります')
.max(120, '無効な年齢です')
.optional()
});
// 検証ミドルウェア
function validateRequest(schema) {
return (req, res, next) => {
try {
schema.parse(req.body);
next();
} catch (error) {
res.status(400).json({
error: '検証に失敗しました',
details: error.errors
});
}
};
}
// 検証を使用
app.post('/api/users',
validateRequest(createUserSchema),
async (req, res) => {
// この時点で入力は検証されています
const { email, password, name, age } = req.body;
// パスワードをハッシュ化
const passwordHash = await bcrypt.hash(password, 10);
// ユーザーを作成
const user = await prisma.user.create({
data: {
email,
passwordHash,
name,
age
}
});
// パスワードハッシュを返さない
const { passwordHash: _, ...userWithoutPassword } = user;
res.status(201).json(userWithoutPassword);
}
);
\`\`\`
#### 4. XSS 防止のために出力をサニタイズ
\`\`\`javascript
const DOMPurify = require('isomorphic-dompurify');
app.post('/api/comments', authenticateToken, async (req, res) => {
const { content } = req.body;
// 検証
if (!content || content.length > 1000) {
return res.status(400).json({
error: 'コメント内容が無効です'
});
}
// XSS を防止するため HTML をサニタイズ
const sanitizedContent = DOMPurify.sanitize(content, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href']
});
const comment = await prisma.comment.create({
data: {
content: sanitizedContent,
userId: req.user.userId
}
});
res.status(201).json(comment);
});
\`\`\`
### 検証チェックリスト
- [ ] すべてのユーザー入力を検証
- [ ] パラメータ化クエリまたは ORM を使用
- [ ] データ型を検証(文字列、数字、メール等)
- [ ] データ範囲を検証(最小/最大長、値の範囲)
- [ ] HTML コンテンツをサニタイズ
- [ ] 特殊文字をエスケープ
- [ ] ファイルアップロードを検証(タイプ、サイズ、内容)
- [ ] ブロックリストではなくホワイトリストを使用
例 3: レート制限と DDoS 保護
## レート制限の実装
### レート制限が必要な理由
- ブルートフォース攻撃を防止
- DDoS から保護
- API の悪用を防止
- 公平な使用を確保
- サーバーコストを削減
### Express Rate Limit での実装
\`\`\`javascript
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');
// Redis クライアントを作成
const redis = new Redis({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT
});
// 一般的な API レート制限
const apiLimiter = rateLimit({
store: new RedisStore({
client: redis,
prefix: 'rl:api:'
}),
windowMs: 15 * 60 * 1000, // 15分
max: 100, // ウィンドウあたり100リクエスト
message: {
error: '多くのリクエストがあります。後でやり直してください',
retryAfter: 900 // 秒
},
standardHeaders: true, // ヘッダーにレート制限情報を返す
legacyHeaders: false,
// カスタムキージェネレータ(ユーザー ID または IP)
keyGenerator: (req) => {
return req.user?.userId || req.ip;
}
});
// 認証エンドポイント用の厳しいレート制限
const authLimiter = rateLimit({
store: new RedisStore({
client: redis,
prefix: 'rl:auth:'
}),
windowMs: 15 * 60 * 1000, // 15分
max: 5, // 15分あたり5回のログイン試行のみ
skipSuccessfulRequests: true, // 成功したログインはカウントしない
message: {
error: 'ログイン試行が多すぎます。後でやり直してください',
retryAfter: 900
}
});
// レート制限を適用
app.use('/api/', apiLimiter);
app.use('/api/auth/login', authLimiter);
app.use('/api/auth/register', authLimiter);
// 高負荷操作用のカスタムレート制限
const expensiveLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1時間
max: 10, // 1時間あたり10リクエスト
message: {
error: 'この操作のレート制限に達しました'
}
});
app.post('/api/reports/generate',
authenticateToken,
expensiveLimiter,
async (req, res) => {
// 高負荷操作
}
);
\`\`\`
### 高度:ユーザーごとのレート制限
\`\`\`javascript
// ユーザー層に基づいて異なる制限
function createTieredRateLimiter() {
const limits = {
free: { windowMs: 60 * 60 * 1000, max: 100 },
pro: { windowMs: 60 * 60 * 1000, max: 1000 },
enterprise: { windowMs: 60 * 60 * 1000, max: 10000 }
};
return async (req, res, next) => {
const user = req.user;
const tier = user?.tier || 'free';
const limit = limits[tier];
const key = \`rl:user:\${user.userId}\`;
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, limit.windowMs / 1000);
}
if (current > limit.max) {
return res.status(429).json({
error: 'レート制限に達しました',
limit: limit.max,
remaining: 0,
reset: await redis.ttl(key)
});
}
// レート制限ヘッダーを設定
res.set({
'X-RateLimit-Limit': limit.max,
'X-RateLimit-Remaining': limit.max - current,
'X-RateLimit-Reset': await redis.ttl(key)
});
next();
};
}
app.use('/api/', authenticateToken, createTieredRateLimiter());
\`\`\`
### Helmet での DDoS 保護
\`\`\`javascript
const helmet = require('helmet');
app.use(helmet({
// コンテンツセキュリティポリシー
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", 'data:', 'https:']
}
},
// クリックジャッキングを防止
frameguard: { action: 'deny' },
// X-Powered-By ヘッダーを非表示
hidePoweredBy: true,
// MIME タイプ嗅覚を防止
noSniff: true,
// HSTS を有効化
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
\`\`\`
### レート制限レスポンスヘッダー
\`\`\`
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1640000000
Retry-After: 900
\`\`\`
ベストプラクティス
✅ これをしましょう
- HTTPS を常に使用 - HTTP で機密データを送信しない
- 認証を実装 - 保護されたエンドポイントに認証を要求
- すべての入力を検証 - ユーザー入力を決して信頼しない
- パラメータ化されたクエリを使用 - SQL インジェクションを防止
- レート制限を実装 - ブルートフォースと DDoS から保護
- パスワードをハッシュ化 - bcrypt を塩ラウンド >= 10 で使用
- 短時間有効なトークンを使用 - JWT アクセストークンは素早く失効
- CORS を適切に実装 - 信頼できるオリジンのみを許可
- セキュリティイベントをログ - 疑わしいアクティビティを監視
- 依存関係を常に更新 - 定期的にパッケージを更新
- セキュリティヘッダーを使用 - Helmet.js を実装
- エラーメッセージをサニタイズ - 機密情報を漏らさない
❌ これをしてはいけません
- パスワードを平文で保存しない - 常にパスワードをハッシュ化
- 弱いシークレットを使用しない - 強力でランダムな JWT シークレットを使用
- ユーザー入力を信頼しない - 常に検証とサニタイズを実施
- スタックトレースを公開しない - プロダクションではエラー詳細を非表示
- SQL に文字列連結を使用しない - パラメータ化クエリを使用
- 機密データを JWT に保存しない - JWT は暗号化されていない
- セキュリティ更新を無視しない - 依存関係を定期的に更新
- デフォルト認証情報を使用しない - すべてのデフォルトパスワードを変更
- CORS を完全に無効にしない - 代わりに適切に設定
- 機密データをログに出力しない - ログをサニタイズ
一般的な落とし穴
問題:JWT シークレットがコードに露出
症状: JWT シークレットがハードコードされているか Git にコミットされている 解決法: ```javascript // ❌ 悪い例 const JWT_SECRET = 'my-secret-key';
// ✅ 良い例 const JWT_SECRET = process.env.JWT_SECRET; if (!JWT_SECRET) { throw new Error('JWT_SECRET 環境変数が必要です'); }
// 強力なシークレットを生成 // node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" ```
問題:弱いパスワード要件
症状: ユーザーが「password123」などの弱いパスワードを設定可能 解決法: ```javascript const passwordSchema = z.string() .min(12, 'パスワードは最低12文字です') .regex(/[A-Z]/, '大文字を含む必要があります') .regex(/[a-z]/, '小文字を含む必要があります') .regex(/[0-9]/, '数字を含む必要があります') .regex(/[^A-Za-z0-9]/, '特殊文字を含む必要があります');
// または パスワード強度ライブラリを使用 const zxcvbn = require('zxcvbn'); const result = zxcvbn(password); if (result.score < 3) { return res.status(400).json({ error: 'パスワードが弱すぎます', suggestions: result.feedback.suggestions }); } ```
問題:認可チェックが欠落
症状: ユーザーが本来アクセスできないリソースにアクセス可能 解決法: ```javascript // ❌ 悪い例:認証のみをチェック app.delete('/api/posts/:id', authenticateToken, async (req, res) => { await prisma.post.delete({ where: { id: req.params.id } }); res.json({ success: true }); });
// ✅ 良い例:認証と認可の両方をチェック app.delete('/api/posts/:id', authenticateToken, async (req, res) => { const post = await prisma.post.findUnique({ where: { id: req.params.id } });
if (!post) { return res.status(404).json({ error: 'ポストが見つかりません' }); }
// ユーザーがポストを所有しているか、または管理者であるかを確認 if (post.userId !== req.user.userId && req.user.role !== 'admin') { return res.status(403).json({ error: 'このポストを削除する権限がありません' }); }
await prisma.post.delete({ where: { id: req.params.id } }); res.json({ success: true }); }); ```
問題:詳細なエラーメッセージ
症状: エラーメッセージがシステム詳細を明かす
解決法:
```javascript
// ❌ 悪い例:データベース詳細を公開
app.post('/api/users', async (req, res) => {
try {
const user = await prisma.user.create({ data: req.body });
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
// エラー: "Unique constraint failed on the fields: (email)"
}
});
// ✅ 良い例:一般的なエラーメッセージ app.post('/api/users', async (req, res) => { try { const user = await prisma.user.create({ data: req.body }); res.json(user); } catch (error) { console.error('ユーザー作成エラー:', error); // 完全なエラーをログ
if (error.code === 'P2002') {
return res.status(400).json({
error: 'メールアドレスは既に存在します'
});
}
res.status(500).json({
error: 'ユーザー作成中にエラーが発生しました'
});
} }); ```
セキュリティチェックリスト
認証と認可
- 強力な認証を実装(JWT、OAuth 2.0)
- すべてのエンドポイントで HTTPS を使用
- bcrypt でパスワードをハッシュ化(塩ラウンド >= 10)
- トークンの有効期限を実装
- リフレッシュトークンメカニズムを追加
- 各リクエストでユーザー認可を検証
- ロールベースアクセス制御(RBAC)を実装
入力検証
- すべてのユーザー入力を検証
- パラメータ化クエリまたは ORM を使用
- HTML コンテンツをサニタイズ
- ファイルアップロードを検証
- リクエストスキーマ検証を実装
- ホワイトリストを使用(ブロックリストではなく)
レート制限と DDoS 保護
- ユーザー/IP ごとのレート制限を実装
- 認証エンドポイント用の厳しい制限を追加
- 分散レート制限用に Redis を使用
- 適切なレート制限ヘッダーを返す
- リクエストスロットリングを実装
データ保護
- すべてのトラフィックに HTTPS/TLS を使用
- 保存時に機密データを暗号化
- 機密データを JWT に保存しない
- エラーメッセージをサニタイズ
- 適切な CORS 設定を実装
- セキュリティヘッダーを使用(Helmet.js)
監視とログ
- セキュリティイベントをログ
- 疑わしいアクティビティを監視
- 失敗した認証試行に対するアラートを設定
- API 使用パターンを追跡
- 機密データをログに出力しない
OWASP API セキュリティ Top 10
- 不十分なオブジェクトレベル認可 - ユーザーがリソースにアクセスできることを常に確認
- 不十分な認証 - 強力な認証メカニズムを実装
- 不十分なオブジェクトプロパティレベル認可 - ユーザーがアクセス可能なプロパティを検証
- 無制限のリソース消費 - レート制限とクォータを実装
- 不十分な関数レベル認可 - 各関数のユーザーロールを検証
- 重要なビジネスフローへのアクセス制限がない - 重要なワークフローを保護
- サーバー側リクエストフォージェリ(SSRF) - URL を検証とサニタイズ
- セキュリティ設定不備 - セキュリティ ベストプラクティスとヘッダーを使用
- 不十分なインベントリ管理 - すべての API エンドポイントを文書化とセキュア化
- API の不安全な使用 - サードパーティ API のデータを検証
関連スキル
@ethical-hacking-methodology- セキュリティテストの観点@sql-injection-testing- SQL インジェクション用のテスト@xss-html-injection- XSS 脆弱性用のテスト@broken-authentication- 認証脆弱性@backend-dev-guidelines- バックエンド開発標準@systematic-debugging- セキュリティ問題をデバッグ
追加リソース
- OWASP API セキュリティ Top 10
- JWT ベストプラクティス
- Express セキュリティ ベストプラクティス
- Node.js セキュリティチェックリスト
- API セキュリティチェックリスト
プロのヒント: セキュリティは1回限りのタスクではありません。API を定期的に監査し、依存関係を最新に保ち、新しい脆弱性について情報を得てください!
制限事項
- このスキルは、上記で説明されているスコープに明確に一致するタスクの場合にのみ使用してください。
- 出力を環境固有の検証、テスト、またはエキスパートレビューの代替品として扱わないでください。
- 必要な入力、権限、安全性の境界、または成功基準が不足している場合は、中断して説明を求めてください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- sickn33
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/sickn33/antigravity-awesome-skills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。