mcpField
A
alibabacloud-waf-security-monitor

alibabacloud-waf-security-monitor

github.com/aliyunセキュリティ28161 回インストール1 日前に更新
リポジトリ

alibabacloud-waf-security-monitor について

cn-hangzhouとap-southeast-1のAlibaba Cloud WAF 3.0を点検するセキュリティ監視スキルです。資産、攻撃イベント、トラフィック、HTTPステータス、防御状態を集約し、構造化レポートを作成します。

主な機能

  1. 012リージョンのWAFインスタンス点検
  2. 02攻撃イベントとトラフィックの分析
  3. 03HTTPステータスコード異常の検出
  4. 04アラーム、DDoS、防御状態の確認
  5. 05構造化された点検レポートの作成

活用シーン

  1. 01WAF資産と証明書の定期確認
  2. 02期間ごとのトラフィック変化の比較
  3. 034xxまたは5xx異常の調査
  4. 04アラームと防御停止状態の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/aliyun/alibabacloud-aiops-skills --skill alibabacloud-waf-security-monitor

インストール後、Claude Code で/alibabacloud-waf-security-monitorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
acceptance-criteria.md
api-reference.md
cli-installation-guide.md
cli-setup.md
defense-templates.md
ram-policies.md
related-commands.md
report-template.md
verification-method.md
scripts/
detect_region_mismatch.py
extract_bot_template.py
requirements.txt
verify_output.py

詳細

WAF セキュリティ製品の検査と監視

このスキルは、Alibaba Cloud WAF 3.0 のインスタンスを対象に、2 つの業務リージョン(cn-hangzhou と ap-southeast-1)で包括的なセキュリティ検査を実施します。資産インベントリ(CNAME ドメイン、クラウド製品のアクセス、SSL 証明書)、攻撃イベントの統計(bot_manager テンプレートを使用した Bot/CC)、トラフィック分析(期間比較による QPS/帯域幅)、HTTP ステータスコードの異常検出(4xx/5xx)、保護ステータスの確認(アラーム、DDoS、一時停止ステータス)を対象とします。標準テンプレートに沿った構造化された検査レポートを出力します。

アーキテクチャ:waf-openapi (WAF 3.0) -> aliyun CLI plugin mode (kebab-case) -> Dual-Region Inspection -> Structured Report

事前確認

事前確認:Aliyun CLI 3.3.3 以降が必要です

aliyun version を実行して、バージョンが 3.3.3 以降であることを確認してください。インストールされていない場合、またはバージョンが古い場合は、 curl -fsSL https://aliyuncli.alicdn.com/setup.sh | bash を実行してインストールまたは更新してください。 または、インストール手順について references/cli-installation-guide.md を参照してください。

事前確認:Aliyun CLI プラグインの更新が必要です

[MUST] aliyun configure set --auto-plugin-install true を実行して、自動プラグインインストールを有効にしてください。 [MUST] aliyun plugin update を実行して、既存のプラグインを常に最新の状態にしてください。

事前確認:スクリプトの依存関係

scripts/ 内のスクリプトには Python 3 が必要です(標準ライブラリのみを使用し、サードパーティーパッケージは不要です)。 詳細は scripts/requirements.txt を参照してください。

オブザーバビリティの初期化(すべてのコマンドの実行前に必ず実行)

if [ -z "$SKILL_SESSION_ID" ]; then
  export SKILL_SESSION_ID="$(cat /proc/sys/kernel/random/uuid 2>/dev/null | tr -d '-' || uuidgen | tr -d '-' | tr 'A-F' 'a-f')"
fi
export ALIBABA_CLOUD_USER_AGENT="AlibabaCloud-Agent-Skills/alibabacloud-waf-security-monitor/${SKILL_SESSION_ID}"
export ALIBABA_CLOUD_OTEL_TRACEPARENT="00-${SKILL_SESSION_ID}-01"
export ALIBABA_CLOUD_OTEL_BAGGAGE="skill=alibabacloud-waf-security-monitor,source=agent-skills"

省略したり、形式を変更したり、baggage に PII を含めたりしないでください。

認証

事前確認:Alibaba Cloud の認証情報が必要です

セキュリティルール:

  • 絶対に AK/SK の値を読み取ったり、エコーしたり、表示したりしないでください(例:echo $ALIBABA_CLOUD_ACCESS_KEY_ID は禁止です)
  • 絶対に会話やコマンドラインで AK/SK を直接入力するようユーザーに求めないでください
  • 絶対にリテラルな認証情報の値を指定して aliyun configure set を使用しないでください
  • 認証情報の状態を確認する場合は、aliyun configure list のみを使用してください
aliyun configure list

出力を確認して、有効なプロファイル(AK、STS、または OAuth ID)があることを確かめてください。

有効なプロファイルがない場合は、ここで中止してください。

  1. Alibaba Cloud Console から認証情報を取得します
  2. このセッションの外で認証情報を設定します(ターミナルで aliyun configure を実行するか、シェルプロファイルで環境変数を設定します)
  3. aliyun configure list で有効なプロファイルが表示されることを確認してから、戻って再実行します

RAM ポリシー

すべての権限は読み取り専用です(Describe/List のみ)。ポリシーの JSON 全体については、references/ram-policies.md を参照してください。

カテゴリAPI アクション種類
資産管理DescribeInstance, DescribeDomains, DescribeCloudResourceList読み取り専用
攻撃イベントDescribeDefenseRuleStatistics, DescribeApisecEvents読み取り専用
トラフィック分析DescribeFlowChart, DescribePeakTrend, DescribeFlowTopResource, DescribeFlowTopUrl読み取り専用
ステータスコードDescribeResponseCodeTrendGraph読み取り専用
保護ステータスDescribePauseProtectionStatus, DescribeAlarmList, DescribeDDoSStatus読み取り専用
証明書DescribeCerts読み取り専用
防御DescribeDefenseTemplates, DescribeMajorProtectionBlackIps読み取り専用

[MUST] 権限エラーの対応: 実行中のいずれかの時点で、権限エラーによりコマンドまたは API 呼び出しが失敗した場合は、次の手順に従ってください。

  1. references/ram-policies.md を読み、この SKILL に必要な権限の一覧を確認します
  2. ram-permission-diagnose スキルを使用して、必要な権限をユーザーが申請できるよう案内します
  3. 必要な権限が付与されたことをユーザーが確認するまで待機します

パラメーターの確認

重要:パラメーターの確認 -- コマンドまたは API 呼び出しを実行する前に、 ユーザーがカスタマイズできるすべてのパラメーター(例:RegionId、インスタンス名、CIDR ブロック、 パスワード、ドメイン名、リソース仕様など)を必ずユーザーに確認してください。 明示的な承認なしに、既定値を推測したり使用したりしないでください。

パラメーター必須/任意説明既定値
時間範囲任意検査対象の時間枠過去 24 時間
比較モード任意期間ごとの比較基準前日比
リージョンの範囲任意検査する WAF リージョンcn-hangzhou と ap-southeast-1 の両方

注:InstanceId は自動検出されるため、ユーザー入力は不要です。 フェーズ 1 では、各リージョンで describe-instance を呼び出し、WAF InstanceId を自動的に取得します。それ以降の API 呼び出しでは、検出した値を使用します。ユーザーが --instance-id を手動で指定する必要はありません。

コア検査ワークフロー

実行ガイダンス:

  • リージョンのルール:WAF 3.0 のビジネスリージョンは cn-hangzhou と ap-southeast-1 の 2 つだけです。それぞれに独自の InstanceId があるため、両方を個別にクエリしてください。--region フラグのみを使用してください(--region-id は「unknown flag」エラーを発生させ、--biz-region-id では正しくルーティングされません)。API リファレンスを参照してください。
  • コマンドごとの User-Agent:すべての aliyun waf-openapi CLI 呼び出しに、--user-agent "$ALIBABA_CLOUD_USER_AGENT" フラグを必ず含めてください(Observability Initialization 中に設定します)。
  • フェーズ 1~2~3~4 は同じシェルセッションで実行:REGION_INSTANCES、BASE_START、EFFECTIVE_BOT_ID などの変数は各フェーズで共有されます。シェルを分けると値が失われ、未定義変数エラーが発生します。
  • 各コードブロックは bash で実行してください。説明や計画だけで済ませないでください。
  • API 呼び出しの出力には RESULT という変数名を使用してください。検証スクリプト(scripts/verify_output.py)とログ集約のパターンでは、一貫した変数名が必要です。
  • すべての aliyun waf-openapi の出力を /tmp/waf_skill_output.log に追記してください。フェーズ 4 の検証スクリプトは、完全性のチェックのためにこのファイルを解析します。
  • エラーが発生した場合はユーザーに報告して続行してください。結果が空の場合は「0」と報告し、そのセクションを省略しないでください。
フェーズ 1~2~3:環境、アセット、タイムスタンプ(一括ブロック)
# === Phase 1: Heartbeat ===
HEARTBEAT_CN=$(aliyun waf-openapi describe-instance \
  --region cn-hangzhou --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$HEARTBEAT_CN" > /tmp/waf_skill_output.log
HEARTBEAT_INTL=$(aliyun waf-openapi describe-instance \
  --region ap-southeast-1 --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$HEARTBEAT_INTL" >> /tmp/waf_skill_output.log

# Setup
aliyun version
aliyun configure set --auto-plugin-install true --connect-timeout 10 --read-timeout 30 2>/dev/null || true
aliyun plugin update 2>/dev/null || true

# === Phase 2.1: Instance discovery (from heartbeat, no redundant calls) ===
declare -A REGION_INSTANCES
for region in cn-hangzhou ap-southeast-1; do
  if [ "$region" = "cn-hangzhou" ]; then RAW="$HEARTBEAT_CN"; else RAW="$HEARTBEAT_INTL"; fi
  IDS=$(echo "$RAW" | python3 -c "
import sys,json,re
raw=sys.stdin.read()
raw=re.sub(r'[\x00-\x1f\x7f]','',raw)
try:
  d=json.loads(raw)
  if 'InstanceId' in d: print(d['InstanceId'])
except:
  for line in raw.splitlines():
    if '\"InstanceId\"' in line and 'waf_' in line:
      print(line.split('\"InstanceId\"')[1].split('\"')[1]); break
" 2>/dev/null)
  REGION_INSTANCES[$region]="$IDS"
  echo "[MAPPING] $region -> $IDS"
done
echo "[CHECK] cn-hangzhou=${REGION_INSTANCES[cn-hangzhou]} | ap-southeast-1=${REGION_INSTANCES[ap-southeast-1]}"

# DEGRADED FALLBACK
[ -z "${REGION_INSTANCES[cn-hangzhou]}" ] && REGION_INSTANCES[cn-hangzhou]="UNKNOWN" && echo "[DEGRADED] cn-hangzhou=UNKNOWN"
[ -z "${REGION_INSTANCES[ap-southeast-1]}" ] && REGION_INSTANCES[ap-southeast-1]="UNKNOWN" && echo "[DEGRADED] ap-southeast-1=UNKNOWN"

# === Phase 2.2: Domains (use page-size 10 -- larger values like 100 trigger API parameter errors) ===
for region in cn-hangzhou ap-southeast-1; do
  for instance_id in ${REGION_INSTANCES[$region]}; do
    RESULT=$(aliyun waf-openapi describe-domains \
      --instance-id $instance_id --region $region \
      --page-number 1 --page-size 10 \
      --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
    echo "$RESULT" >> /tmp/waf_skill_output.log
  done
done

# === Phase 2.3: Cloud resources + Certificates ===
for region in cn-hangzhou ap-southeast-1; do
  for instance_id in ${REGION_INSTANCES[$region]}; do
    RESULT=$(aliyun waf-openapi describe-cloud-resource-list \
      --instance-id $instance_id --region $region \
      --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
    echo "$RESULT" >> /tmp/waf_skill_output.log
    # Cross-region mismatch detection: flag resources whose ResourceRegionId != WAF instance region
    echo "$RESULT" | python3 scripts/detect_region_mismatch.py \
      --region "$region" --instance-id "$instance_id" >> /tmp/waf_skill_output.log
    RESULT=$(aliyun waf-openapi describe-certs \
      --instance-id $instance_id --region $region \
      --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
    echo "$RESULT" >> /tmp/waf_skill_output.log
  done
done

# === Phase 3: Timestamps ===
if [ -n "$BASE_END" ] && ! echo "$BASE_END" | grep -qE '^[0-9]+$'; then
  echo "[ERROR] BASE_END is not a valid integer: $BASE_END"; exit 1
fi
if [ -n "$BASE_START" ] && ! echo "$BASE_START" | grep -qE '^[0-9]+$'; then
  echo "[ERROR] BASE_START is not a valid integer: $BASE_START"; exit 1
fi
BASE_END=${BASE_END:-$(date +%s)}; BASE_START=${BASE_START:-$((BASE_END - 86400))}
COMPARE_END=$((BASE_START)); COMPARE_START=$((COMPARE_END - (BASE_END - BASE_START)))
echo "[TIMESTAMP] BASE=$BASE_START~$BASE_END COMPARE=$COMPARE_START~$COMPARE_END"
echo "[PHASE 1-2-3 DONE] Instances: cn-hangzhou=${REGION_INSTANCES[cn-hangzhou]} ap-southeast-1=${REGION_INSTANCES[ap-southeast-1]}"

中止ルール:リージョンごとに個別に処理します。cn-hangzhou が失敗しても、ap-southeast-1 をスキップしてはいけません。 InvalidAccessKeyId(認証情報の問題がすべてのリージョンに影響する場合)に限り処理を終了してください。それ以外の場合は、UNKNOWN プレースホルダーを使用して縮退モードで続行してください。

フェーズ 4:検査(リージョンごと、インスタンスごと)

コードブロック 4.1~4.5 は、前の結果にかかわらずすべて実行してください。各検査項目は独立しています。

  • 呼び出し N でエラーが発生した場合は、エラーを記録して直ちに呼び出し N+1 を実行してください。
  • すべての呼び出しに --user-agent "$ALIBABA_CLOUD_USER_AGENT" フラグを含めてください。
  • すべての呼び出しで、RESULT=$(aliyun waf-openapi <cmd> --region $region --user-agent "$ALIBABA_CLOUD_USER_AGENT" ... 2>&1); echo "$RESULT" >> /tmp/waf_skill_output.log を使用してください。
  • ループ:for region in cn-hangzhou ap-southeast-1; do for instance_id in ${REGION_INSTANCES[$region]}; do
  • 各リージョンで 4.1~4.5 が完了した後、echo "[CHECKPOINT] region=$region ALL phases done" を出力してください。
  • リージョンのループ内で break/continue/return を使用しないでください。
4.1 防御テンプレート

JSON の抽出には python3 を使用してください(grep/sed/awk/bash の文字列操作は使用しないでください)。防御テンプレートガイドを参照してください。

RESULT=$(aliyun waf-openapi describe-defense-templates \
  --instance-id $instance_id --region $region \
  --page-number 1 --page-size 50 \
  --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$RESULT" >> /tmp/waf_skill_output.log

BOT_TEMPLATE_ID=$(echo "$RESULT" | python3 scripts/extract_bot_template.py 2>/dev/null)
if ! echo "$BOT_TEMPLATE_ID" | grep -qE '^[0-9]+$'; then BOT_TEMPLATE_ID=""; fi
EFFECTIVE_BOT_ID="${BOT_TEMPLATE_ID:-0}"
echo "[TEMPLATE] BOT=$EFFECTIVE_BOT_ID region=$region"
  • describe-defense-rule-statistics がサポートするのは bot_manager のみです。他のシーンでは DefenseSceneNotSupported が返されます。
  • template-id が空の場合は、フォールバックとして 0 を使用してください(これにより呼び出しがサーバーに到達し、「template not found」が返されてログに記録されます)。
4.2 攻撃イベント(インスタンスごとに3回呼び出し)

CC 検出の対応付け:CC 攻撃データは describe-defense-rule-statistics(primary-key=scene/action/status)から取得します。 API の応答が空の場合は、「CC/Bot attacks: 0 (no block records in this period)」と記載してください。実際に検出が行われたことを示唆する「not detected」という表現は避けてください。

for key in scene action status; do
  RESULT=$(aliyun waf-openapi describe-defense-rule-statistics \
    --instance-id $instance_id --primary-key $key \
    --template-id $EFFECTIVE_BOT_ID --region $region \
    --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
  echo "$RESULT" >> /tmp/waf_skill_output.log
done
RESULT=$(aliyun waf-openapi describe-apisec-events \
  --instance-id $instance_id --region $region \
  --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$RESULT" >> /tmp/waf_skill_output.log
RESULT=$(aliyun waf-openapi describe-major-protection-black-ips \
  --instance-id $instance_id --region $region \
  --page-number 1 --page-size 50 \
  --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$RESULT" >> /tmp/waf_skill_output.log
4.3 トラフィック(ベース期間と比較期間の両方が必須)
for api in describe-flow-chart describe-peak-trend; do
  RESULT=$(aliyun waf-openapi $api \
    --instance-id $instance_id --region $region \
    --start-timestamp $BASE_START --end-timestamp $BASE_END --interval 300 \
    --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
  echo "$RESULT" >> /tmp/waf_skill_output.log
done
# COMPARE period (execute even if base returned empty)
for api in describe-flow-chart describe-peak-trend; do
  RESULT=$(aliyun waf-openapi $api \
    --instance-id $instance_id --region $region \
    --start-timestamp $COMPARE_START --end-timestamp $COMPARE_END --interval 300 \
    --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
  echo "$RESULT" >> /tmp/waf_skill_output.log
done
RESULT=$(aliyun waf-openapi describe-flow-top-resource \
  --instance-id $instance_id --region $region \
  --start-timestamp $BASE_START --end-timestamp $BASE_END \
  --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$RESULT" >> /tmp/waf_skill_output.log
RESULT=$(aliyun waf-openapi describe-flow-top-url \
  --instance-id $instance_id --region $region \
  --start-timestamp $BASE_START --end-timestamp $BASE_END \
  --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
echo "$RESULT" >> /tmp/waf_skill_output.log
echo "[SELF-CHECK-4.3] region=$region BASE+COMPARE flow calls done."
4.4 HTTP ステータスコード(リージョンごとに4回呼び出し:2種類 × 2期間)
for type_val in waf upstream; do
  for start_ts end_ts in $BASE_START $BASE_END $COMPARE_START $COMPARE_END; do
    RESULT=$(aliyun waf-openapi describe-response-code-trend-graph \
      --instance-id $instance_id --region $region \
      --start-timestamp $start_ts --end-timestamp $end_ts \
      --interval 300 --type $type_val \
      --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
    echo "$RESULT" >> /tmp/waf_skill_output.log
  done
done
echo "[CHECKPOINT-4.4] region=$region status_code_calls=4."
4.5 保護ステータス
for api in describe-pause-protection-status describe-alarm-list describe-ddos-status; do
  RESULT=$(aliyun waf-openapi $api \
    --instance-id $instance_id --region $region \
    --user-agent "$ALIBABA_CLOUD_USER_AGENT" 2>&1)
  echo "$RESULT" >> /tmp/waf_skill_output.log
done
echo "[CHECKPOINT] region=$region ALL phases done"

証明書のしきい値:<7d=Critical、<30d=Warning、>=30d=Normal。データはフェーズ2.3の describe-certs から取得します(再度呼び出さないでください)。

4.6 期間ごとの比較

変化率 =(ベース期間 - 比較期間)/ 比較期間 x 100%。しきい値:+/-50-100%=要注意、>+/-100%=異常。

4.7 レポートと検証

レポート:レポートテンプレートに従ってください。リージョンごとにまとめてください。

リージョン間の不一致:検証後、ログに [REGION_MISMATCH_SUMMARY] の行が含まれているか確認してください。含まれている場合は、レポートに「リージョン間のリソースリスク」セクションを追加し、不一致のある各リソースを列挙してください。結論では、設定リスク項目として扱ってください。

エラーと空の区別 -- これらを区別することで、API の失敗を「インシデントゼロ」と誤って表現するのを防げます:

  • API 200 + [] -> 0 (API returned empty)
  • API エラー -> [QUERY FAILED (ErrorCode: XXX)]
  • API がエラーを返した場合は 0 と記載しないでください。

検証 -- データの欠落を見つけるため、レポート作成前に実行してください:

python3 scripts/verify_output.py /tmp/waf_skill_output.log

レポートの整合性ルール:

  • レポート内のすべての数値は、ログの解析結果に基づいてください。API の出典がないハードコード値は捏造です。
  • リージョンをまたいでドメインを割り当てないでください。
  • ブロック数が0の場合、「攻撃を検出」と記載しないでください。
  • API の応答にない具体的なパスやエンドポイントを推測しないでください。
  • QUERY FAILED がセクションの50%を超える場合、結論に「評価は不完全」と記載してください。
  • すべてのデータポイントに、出典となる API を明記してください。

データが空の場合のレポートルール:

  • API が空の配列または0を返した場合:「この期間のデータは返されませんでした(API の応答が空)」と記載してください。
  • 「重大な攻撃は検出されませんでした」「トラフィックは安定していました」など、推測に基づく説明は記載しないでください。
  • 期間ごとの比較:ベース期間と比較期間がともに0の場合は、「両期間ともデータがなく、計算できません」と記載してください。
  • 期間ごとの比較:比較期間が0でベース期間が0より大きい場合は、「比較期間にデータがなく、基準値がありません」と記載してください。

証明書とタイムスタンプのルール:

  • 証明書の有効期限までの日数は、scripts/verify_output.py が出力する [CERT] 行を参照してください。bash の算術演算で有効期限までの日数を計算しないでください。
  • タイムスタンプから日付への変換には python3 datetime または date -d @ts を使用してください。
  • レポートを生成する前に、相互確認してください:検証スクリプトの [VERIFY] Domains とレポートのドメイン一覧、[CERT] の件数とレポートの証明書数が一致していることを確認してください。

成功の検証

実行の証拠、パラメーターの正確性、結果の処理、捏造防止ルールを対象とする詳細な評価レイヤーと合格/不合格の基準については、references/verification-method.md を参照してください。

クリーンアップ

明示的なクリーンアップは不要です。すべての操作は読み取り専用で、リソースはプロビジョニングされません。

ベストプラクティス

  1. WAF の両方のビジネスリージョン(cn-hangzhou、ap-southeast-1)に必ず個別にクエリを実行します
  2. --region のみを使用し、--region-id や --biz-region-id は使用しません
  3. すべての aliyun waf-openapi コマンドに --user-agent "$ALIBABA_CLOUD_USER_AGENT" を含めます
  4. JSON の抽出には python3 を使用し、API レスポンスに対して grep/sed/awk は使用しません
  5. 防御テンプレートは DefenseScene=bot_manager のみでフィルタリングします。それ以外のシーンではエラーが返されます
  6. 先行するエラーの有無にかかわらず、すべての検査フェーズを実行します。各項目は独立しています
  7. レポートでは、API エラーと結果が空の場合を区別します
  8. レポートを作成する前に、scripts/verify_output.py を使用してデータの完全性を検証します
  9. データを捏造しません。すべての数値は、ログファイル内の API レスポンスにたどれる必要があります
  10. 先行するエラーの有無にかかわらず、すべての検査フェーズを実行します。各項目は独立しています
  11. describe-domains では --page-size 10 を使用します(より大きな値を指定すると、API パラメーターエラーが発生します)

参考資料

リソースパス
CLI インストールガイドreferences/cli-installation-guide.md
CLI のセットアップreferences/cli-setup.md
RAM ポリシーreferences/ram-policies.md
API リファレンスreferences/api-reference.md
防御テンプレートreferences/defense-templates.md
レポートテンプレートreferences/report-template.md
CLI コマンドreferences/related-commands.md
検証方法references/verification-method.md
受け入れ基準references/acceptance-criteria.md

コメント