ADR-0218 週次観測ログ
ADR-0218 (legal_holds schema と保全解除運用 · 2026-07-06 受理) の Confirmation 5 KPI の観測結果を時系列で記録する。SQL 骨格は本ファイル各節 · SSoT は ADR-0218 §9 Confirmation。実 SQL の実行は Phase 0 dogfood 開始 (vlt/terraform/ の legal-hold-placement / legal-hold-release Cloud Tasks queue と Cloud Audit Logs Data Access log 有効化 + ${project} / ${dataset} 確定) 後に開始する。
Week 0 (2026-07-06 · Phase 0 dogfood 前 · 準備段階)
Phase 0 dogfood 未着手のため実測データなし。5 KPI の SQL 骨格 + SLO + 実施頻度 + 撤退条件連動を先出しで整理する。dogfood 開始時点で本節を Week 1 として実測数値に置き換える。
KPI 1: 保全対象の誤廃棄件数 (日次 · 目標 = 0 件)
- SLO: 日次 0 件。ADR-0208 §Confirmation #3「保全対象の誤廃棄 = 0 件」と統合
- 実施頻度: 日次 (BQ scheduled query)
- 撤退条件連動: 1 件でも hit で日次廃棄バッチ即停止 (ADR-0218 §8-1 発火) +
legal_holds表と GCStemporaryHold状態の bit 一致検証を全 receipt 対象で再走 · 差異解消まで復旧手順発動
BigQuery SQL 骨格:
SELECT COUNT(*) AS wrongful_deletion_count
FROM `${project}.${dataset}.retention_batch_log` AS rbl
WHERE rbl.executed_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
AND rbl.deletion_action = 'PHYSICAL_DELETE'
AND EXISTS (
SELECT 1 FROM `${project}.${dataset}.legal_holds` AS lh
WHERE lh.released_at IS NULL
AND (
lh.scope = 'ALL'
OR (lh.scope = 'RECEIPT' AND lh.receipt_id = rbl.receipt_id)
OR (lh.scope = 'PREFIX' AND STARTS_WITH(rbl.storage_uri, lh.scope_prefix))
)
);
-- 期待値: 0 · >0 で撤退条件 1 発火
E2E テスト必達: 同一 receipt に scope=RECEIPT + scope=ALL 同時 active → scope=RECEIPT 解除 → 廃棄拒否 (残存 hold 見落とし検証)。
KPI 2: 保全中証憑への期限短縮試行件数 (日次 · 目標 = 0 件)
- SLO: 日次 0 件
- 実施頻度: 日次 (BQ scheduled query on Cloud Logging sink)
- 撤退条件連動: 1 件でも hit で gate 節ログ調査 + 呼び出し元の権限見直し (§8-1 準拠)
BigQuery SQL 骨格 (Cloud Logging sink 経由):
SELECT COUNT(*) AS retention_shorten_attempt_count
FROM `${project}.audit_logs.cloudaudit_googleapis_com_data_access_*`
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
AND protoPayload.methodName = 'storage.objects.overrideUnlockedRetention'
AND resource.labels.bucket_name LIKE '${bucket_prefix}%'
AND JSON_EXTRACT_SCALAR(protoPayload.status.code, '$') != '0' -- gate 節が拒否した call
;
-- 期待値: 0
KPI 3: hold placement/release 冪等性 + API レイヤーの 2 段階承認強制 (週次)
- SLO: 冪等性違反 週次 < 5 件 · API レイヤーで
placed_by = authorized_byの Phase 1 GAscope=ALL拒否件数を月次観測 (件数は記録のみ · 目標値なし) - 実施頻度: 週次
- 撤退条件連動: 冪等性違反が 6 ヶ月観測で累積 5 件超で ADR-0218 §8-5 発火 (冪等キー unique constraint と Cloud Tasks worker early-return 実装 review)
BigQuery SQL 骨格 (Cloud Tasks worker log · Cloud Logging sink):
-- 冪等キー衝突による early-return 件数
SELECT
COUNT(*) AS idempotent_early_return_count,
APPROX_QUANTILES(
TIMESTAMP_DIFF(response_at, request_at, MILLISECOND), 100
)[OFFSET(95)] AS latency_p95_ms
FROM `${project}.${dataset}.cloud_tasks_worker_log`
WHERE queue_name IN ('legal-hold-placement', 'legal-hold-release')
AND processed_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
AND early_return_reason = 'IDEMPOTENT_KEY_COLLISION';
-- 期待値: idempotent_early_return_count < 5
-- API レイヤー 2 段階承認強制の拒否件数 (Phase 1 GA · scope=ALL のみ)
SELECT
COUNT(*) AS scope_all_two_stage_reject_count,
DATE_TRUNC(request_at, MONTH) AS month
FROM `${project}.${dataset}.legal_holds_api_log`
WHERE request_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND requested_scope = 'ALL'
AND rejection_reason = 'PLACED_BY_EQUALS_AUTHORIZED_BY'
GROUP BY month;
-- 期待値: 記録のみ (SLO 未設定)
KPI 4: Cloud Audit Logs Data Access log 網羅性 (日次軽量 + 月次全件 · 目標 差異率 < 1%)
- SLO: 差異率 < 1%
- 実施頻度: 日次 (軽量突合) + 月次 (全件詳細突合)
- 撤退条件連動: 差異率 > 1% で IntegrityGuard 発報 + Terraform drift 検知 (ADR-0218 §8-3 発火)
BigQuery SQL 骨格 (日次軽量突合):
WITH primary_count AS (
SELECT COUNT(*) AS n
FROM `${project}.${dataset}.legal_hold_placements`
WHERE created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
),
secondary_count AS (
SELECT COUNT(*) AS n
FROM `${project}.audit_logs.cloudaudit_googleapis_com_data_access_*`
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
AND protoPayload.methodName = 'storage.objects.patch'
AND JSON_EXTRACT_SCALAR(protoPayload.request.temporaryHold, '$') = 'true'
AND resource.labels.bucket_name LIKE '${bucket_prefix}%'
)
SELECT
primary_count.n AS primary_count,
secondary_count.n AS secondary_count,
ABS(primary_count.n - secondary_count.n)
/ GREATEST(primary_count.n, secondary_count.n, 1) AS diff_ratio
FROM primary_count, secondary_count;
-- 期待値: diff_ratio < 0.01
月次全件突合 SQL は placement/release 各行の timestamp を primary/secondary で JOIN し 5 分許容差以内の一致率で判定する (詳細 SQL は Phase 0 dogfood 開始時に確定 · 骨格上は上記日次と同 pattern)。
KPI 5: Cloud Audit Logs 月次コスト (月次 · 目標 Phase 1 < $0.25/月 · GA < $5/月)
- SLO: Phase 1 (tenant 1 = 自社 dogfood) で月 $0.25 未満 · Phase 1 GA 一般提供時 (tenant 1000) で月 $5 未満
- 実施頻度: 月次
- 撤退条件連動: 月 $5 超過で Exclusion filter 設定確認 (hold 関連リソースパス以外を除外) + ADR-0218 §8-9 発火
BigQuery SQL 骨格 (Cloud Billing export):
SELECT
invoice.month,
SUM(cost) AS cloud_logging_hold_cost_usd,
SUM(usage.amount) AS log_bytes
FROM `${project}.billing_export.gcp_billing_export_v1_*`
WHERE service.description = 'Cloud Logging'
AND (
labels.log_name LIKE '%data_access%'
OR labels.resource_type = 'gcs_bucket'
)
AND invoice.month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH))
GROUP BY invoice.month;
-- 期待値: cloud_logging_hold_cost_usd < 0.25 (Phase 1) / < 5.00 (GA)
Phase 0 dogfood 開始時の確定タスク
Phase 0 dogfood 開始 (vlt/terraform/ shipping + ${project} / ${dataset} 確定) の時点で以下を確定する:
- table 名の確定:
${project}/${dataset}/${bucket_prefix}の実値を SQL 骨格に埋め込む - BQ scheduled query 登録: KPI 1/2 は日次 · KPI 3/4 (日次軽量) は日次 · KPI 4 (月次全件) と KPI 5 は月次 · Cloud Monitoring alert 連携先を確認
- E2E テスト整備: KPI 1 の残存 hold 見落とし検証 (
scope=RECEIPT+scope=ALL同時 active) を統合テストへ追加 - 本ページ Week 1 更新: dogfood 1 週間後に本節を Week 1 として実測値へ置き換え
関連 SSoT
- ADR-0218 (legal_holds schema と保全解除運用):
docs/adr/0218-finalize-legal-holds-schema-and-unhold-operation.md(§9 Confirmation が本 SQL 骨格の SSoT) - 親決定 ADR-0208 (保存年限管理と期限後廃棄):
docs/adr/0208-*.md(Confirmation #3 と統合) - 起案 draft (archive 済):
tasks/prompts/archive/draft_adr_jtbd012-legal-holds-schema.md - 観測手順 pattern の先例:
docs/_internal/06_ops/adr-0212-observation-log.md(drp domain · 週次観測ログ) - SQL 実行環境: Phase 0 dogfood 開始後に BigQuery scheduled query として登録 (実行環境の SSoT は
vlt/terraform/の locked module + Cloud Audit Logs Data Access log 有効化 sink)