1. Executive Summary
- 文脈: JTBD-012 (帳票・証憑管理 SaaS) の Phase 0-2 で電帳法施行規則 4 条の 3 要素 (取引年月日 · 取引金額 · 取引先) 検索索引 stack を確定する必要がある
- 課題: BigQuery search index は base table 10 GB 未満で index が populate されず全表スキャンに劣化し、Phase 0 の 1 tenant 数百 MB · Phase 1 GA の 100 tenant 10-100K 件でも tenant 別 payload が 10 GB に届かない
- 対策: Cloud SQL (Postgres) を primary 検索 stack に採択し pg_trgm を Phase 0 default · pg_bigm を Phase 1 で追加する
- 効果: Phase 0 は ~$40/月 · Phase 1 GA は ~$1,250/月で 100 tenant を余裕でカバーし検索 P95 500ms 未満を達成する (NEC 実測 1300 万件 6 GB を 0.3 秒)
- 代償: Phase 2 拡大時の BigQuery mirror + Datastream + date-hash routing は別 ADR で決定し起票着手トリガーは予兆閾値 (400 tenant or 800K 件) 到達 · 起票完了 hard deadline は §8 撤退条件 1 (検索 P95 500ms 2 週連続超過) 発火時点 · analytics 用途 (BigQuery) は Phase 2 別 ADR とは独立に別途起票し起票着手トリガーは Phase 1 GA 到達 (~2026-10-31) · 起票完了 hard deadline は GA + 1 か月 (= §8 撤退条件 4 発火時点)
2. 何を解決するか
2.1 直面していること
適合性:
- 電帳法施行規則 4 条は「完全一致 + 範囲 + 複合条件」の 3 要素検索を骨格として要求している
- OCR 抽出精度は 95-99% で「株式会社サンプル」→「株式会杜サンプル」誤読が発生し部分一致 or 前方一致検索が事実上必達となる (法令上は明示要件ではないが運用リスク)
- ADR-0229 (audit_log 追記専用性 DB REVOKE + FORCE RLS) の 2 層防御は documents 表にも適用が必要で tenant_id 索引と RLS policy 述語の整合が要求される
効率性:
- BigQuery search index は base table 10 GB 未満で index が populate されず全表スキャンに劣化する (Google Cloud 公式 doc SoT)
- Phase 0 の 1 tenant 数千件 (数百 MB) では絶対に閾値未満 · Phase 1 GA の 100 tenant × 100K 件でも tenant 別 payload はしばらく 10 GB に届かない
運用性:
- JTBD-012 SaaS は AWS 可搬性を担保する要件がある (ADR-0179 (SaaS GCP 単一基盤) の下流条項)
- Vertex AI Search は GCP lock-in で AWS 移植不可 · OpenSearch は self-hosted GKE で PoC からやり直しコスト発生
2.2 放置すると起こること
信頼性:
- stack 選定を先延ばしすると Phase 0 dogfood 開始 (
2026-08 中旬) に間に合わず検索機能を欠いた α運用が確定し JIIMA 事前照会 (2026-08-06) の実装確認項目 5 種が回答不能となる
- 誤った stack (BigQuery 単独) を採用すると Phase 1 GA (~2026-10-31) で全表スキャン化して P95 500ms 未達 · cutover reindex 数週間の rework が発生する
2.3 潜在リスク (実害未発生 · 発生確率不明)
適合性:
- JIIMA 事前照会回答 (~2026-08-06 目安) で pg_trgm/pg_bigm の similarity ベース fuzzy match が「機能要件 15 の記載が不明瞭で認証審査上マイナス」と示される可能性 (発生確率低 · 競合 3 社は全て Postgres 系で JIIMA 認証取得済み)
- similarity 閾値を緩めに設定すると税務調査で「関係のない取引先の証憑が検索される」と指摘され施行規則 4 条の検索精度要件違反とみなされる可能性 (実害未発生 · JIIMA 事前照会で許容範囲を確認予定)
- counterparty_name の正規化が「空白除去 + lower」のみに留まると OCR 出力の全角スペース · 半角カナ · 旧字体 · Unicode 合成揺れが吸収されず税務調査時の取引先名検索で該当証憑が 0 件返却される可能性 (実害未発生 · Phase 0 dogfood で発生確率を測定予定)
- 施行規則 4 条 1 項 6 号のダウンロード出力要件 (国税庁取扱通達 4-24 が CSV 等の整然とした形式を規定) が本 ADR の索引設計に未定義で JIIMA 照会回答後に追加要件が発覚する可能性 (実害未発生 · §3.3 仕様に出力形式を追記して吸収)
3. 採用したい方針
3.1 対策方針
Cloud SQL (Postgres) を primary 検索 stack として採択し、電帳法 3 要素の複合検索と OCR 誤読補正の部分一致検索を pg_trgm/pg_bigm で満たす。Phase 0 は pg_trgm のみで dev cost 追加 SaaS ゼロ · Phase 1 で pg_bigm を無停止で追加する。Phase 2 拡大時の BigQuery mirror + Datastream + date-hash routing と analytics 用途はそれぞれ独立の別 ADR で決定する (2 本立て)。前者は起票着手トリガーが予兆閾値 (400 tenant or 800K 件) 到達 · 起票完了 hard deadline が §8 撤退条件 1 発火時点。後者は起票着手トリガーが Phase 1 GA 到達 (~2026-10-31) · 起票完了 hard deadline が GA + 1 か月 (= §8 撤退条件 4 発火時点)。
- 適合性: 電帳法 3 要素 (取引年月日 · 取引金額 · 取引先) の複合検索を documents 表の btree + GIN 索引で満たし OCR 誤読を pg_trgm similarity threshold で許容する
- 適合性: Phase 2 拡大時の BQ mirror 別 ADR は「Postgres (90 日以内) と BQ (90 日超) にまたがる複合条件検索の federated join 戦略 or BQ 単一経路への完全移行タイミング」を前提条件として含める (施行規則 4 条の全期間検索要件 = 保存期間 7 年 · 欠損金繰越時 10 年 · 法人税法施行規則 59 条 / 67 条準拠)
- 効率性: Phase 0 は pg_trgm のみ (Cloud SQL default 利用可) で追加 SaaS ゼロ · Phase 1 で pg_bigm を 2 手順 (Cloud SQL flag 有効化 +
CREATE EXTENSION) + 無停止 CREATE INDEX CONCURRENTLY で追加する
- 運用性: Phase 2 拡大時の BigQuery mirror + Datastream + date-hash routing は Phase 2 別 ADR で決定 · 起票着手トリガーは §9 Confirmation 先行監視での予兆閾値 (400 tenant or 800K 件) 到達 · 起票完了 hard deadline は §8 撤退条件 1 (検索 P95 500ms 2 週連続超過) 発火時点 · 未起票のまま発火した場合は Phase 1 GA の新規 tenant 受入停止で対応
- 運用性: analytics 用途 (BigQuery) は Phase 2 別 ADR とは独立に別途起票 · 起票着手トリガーは Phase 1 GA 到達 (~2026-10-31) · 起票完了 hard deadline は GA + 1 か月 (= §8 撤退条件 4 発火時点) · 未起票のまま deadline 超過時は Cloud SQL read-only + ad-hoc SQL で凌ぐ
- 信頼性: Phase 1 GA は HA (regional standby) + Read replica × 1 で検索負荷を replica に振り P95 500ms 目標を達成する
3.2 守るべき設計制約
- 適合性: documents 表の 3 要素列は
(tenant_id, transaction_date DESC) · (tenant_id, amount) · (tenant_id, counterparty_name) の btree 索引と GIN (pg_trgm) 索引を持ち電帳法施行規則 4 条の複合条件検索を満たす
- 適合性:
normalize_counterparty(text) は immutable 関数として定義し generated column から参照する · 正規化ロジックの変更 (mapping table 追加等) 時は generated column の REINDEX を運用 runbook に含める · mapping table を外部 table 参照する代替設計 (generated column 再定義を不要にする) を Phase 0 dogfood で PoC 実施し所要時間実測と併記
- 適合性: ADR-0229 (audit_log 追記専用性 DB REVOKE + FORCE RLS) 準拠で ENABLE ROW LEVEL SECURITY + FORCE ROW LEVEL SECURITY + REVOKE ALL FROM PUBLIC + GRANT app_user の 2 層防御を documents 表にも適用する
- 運用性: Postgres primary で AWS 可搬性 (Amazon RDS/Aurora + pg_trgm/pg_bigm) を担保し BigQuery は analytics 補助用途に限定する
3.3 仕様
- 適合性: counterparty_name の正規化 (Unicode NFKC 正規化 + 空白除去 + lower + 半角/全角カナ統一 + 旧字体→新字体 mapping) は generated column
counterparty_name_normalized として DB 側に押し込み GIN (pg_trgm) 索引を同列に設定する
- 適合性: 正規化関数は immutable な PL/pgSQL 関数
normalize_counterparty(text) として定義し NFKC で全角スペース · 半角カナ · 記号幅を吸収 · 旧字体は translate() ベースの mapping table (JIS X 0208 旧字体→新字体の 300 字程度) で変換する · mapping table 追加時は generated column の REINDEX が必要
- 適合性: 施行規則 4 条 1 項 6 号のダウンロード出力要件を満たすため検索結果 CSV 出力エンドポイントを実装 · 出力列は (transaction_date / amount / counterparty_name / document_id / created_at) 固定 · CSV RFC 4180 準拠の整然とした形式 · 出力実行ログを audit_log に記録し証跡保全する
- 適合性: pg_trgm similarity 閾値のデフォルトは 0.3 · 下限 0.2 · 上限 0.5 の範囲で運用し JIIMA 事前照会で fuzzy match 誤ヒット率の認証審査上許容範囲を確認する
- 効率性: Phase 0 は
db-custom-1-3840 (1 vCPU / 3.75 GB) non-HA + SSD 20 GB で ~$40/月 · Phase 1 GA は db-custom-4-15360 HA (regional) + Read replica × 1 で ~$1,250/月 (on-demand)
- 信頼性: pg_trgm similarity threshold (
% 'foo') で OCR 誤読許容 · pg_bigm は 2 文字社名 (「日本」「東京」「三菱」等) の LIKE 索引高速化用 · pg_bigm max column size は 107,374,180 bytes (~102 MB) 制約あり (取引先名では余裕)
- 運用性: PgBouncer は session mode 限定 · transaction mode 禁止 · prepared statement は DEALLOCATE ALL or simple query protocol 強制 · Terraform 設定で pooling mode を強制し tenant コンテキストリーク (SET LOCAL 残留 · planner cache 経由 RLS bypass) を防止する
- 運用性: per-request Postgres session に
SET LOCAL app.current_tenant = ? を注入しトランザクション終了で自動解除する (connection pool 経由の tenant コンテキストリーク防止)
4. 判断基準
4.1 評価軸
| # | 軸 (Q42) | 日本語軸名 | 重要度 (係数) | 案件特有の解釈 |
|---|
| 1 | #suitable | 適合性 | Must (×2.0) | 電帳法施行規則 4 条 3 要素検索 + JIIMA 機能要件 15 + ADR-0229 2 層防御と整合 |
| 2 | #efficient | 効率性 | Must (×2.0) | Phase 0 dev ≤ $50/月 · Phase 1 GA on-demand ≤ $1,500/月 · dev 工数最小 (追加 SaaS ゼロ or 最小) |
| 3 | #operable | 運用性 | High (×1.0) | Phase 0 → 1 → 2 の段階昇格経路が確立 · AWS 可搬性 (Postgres レイヤ無改修移植可能) · rollback 経路明確 |
| 4 | #reliable | 信頼性 | High (×1.0) | Phase 1 GA 100 tenant × 100K 件で検索 P95 500ms 未達なし · pg_bigm 実測 SoT あり |
K.O. criterion: 3 要素複合検索を満たさない stack は K.O. · Phase 1 GA cost が $1,500/月を上回れば K.O. · 段階昇格に stack 総取替を要すれば K.O. · 実運用実績 SoT を提示できない stack は K.O.
4.2 評価軸 × 案スコア表
| 軸 | 係数 | 採択案 (Cloud SQL Postgres) | 案 A (BQ search index 単独) | 案 B (OpenSearch/Elastic) | 案 C (Vertex AI Search) | 案 D (Firestore/Bigtable/Spanner) |
|---|
| 適合性 | ×2.0 | 5 | 2 | 4 | 2 | 2 |
| 効率性 | ×2.0 | 5 | 1 | 2 | 2 | 2 |
| 運用性 | ×1.0 | 5 | 3 | 2 | 2 | 3 |
| 信頼性 | ×1.0 | 5 | 2 | 4 | 3 | 3 |
| 加重和 (正規化) | | 1.000 | 0.300 | 0.533 | 0.367 | 0.400 |
| K.O. 通過 (Must ≥3) | | ✓ | ❌ | ❌ | ❌ | ❌ |
5. 検討した代替案
5.1 案 1 (採用): Cloud SQL (Postgres) primary + BigQuery mirror Phase 2 追加
採用案。詳細は §3.1 対策方針 参照。競合 3 社 (freee 会計 · マネーフォワードクラウド会計 · 弥生会計) は全て Postgres/Aurora 系で JIIMA 認証取得済み (freee 認証番号 009000-00 · 607100-00) で Postgres 選択が cert 障壁になる根拠なし。
5.2 案 2 (不採用): BigQuery search index 単独
- 効率性: base table 10 GB 未満で index が populate されず全表スキャンに劣化する (Google Cloud 公式 doc SoT) · Phase 0/1 の payload size では絶対に閾値未満
- 適合性: 日本語 native tokenize なし +
= / IN / LIKE / STARTS_WITH のみで pg_bigm 相当の 2 文字部分一致高速化ができない
- 運用性: SEARCH function は BQ BI Engine で加速されないため pg_trgm 相当のランク付け機能が欠落する
5.3 案 3 (不採用): OpenSearch/Elastic 前倒し
- 効率性: self-hosted GKE OpenSearch は最小構成でも ~$500-1,500/月 (Elastic Cloud GCP Iowa 1 GB RAM は $40.25/月だが Phase 1 GA では PoC 未達スペック)
- 運用性: 新 stack 導入で PoC からやり直し工数が発生し JIIMA 認証事前照会期限 (~2026-08-06) を考えると risk 受容不可
- 適合性: NEC 実測 (1300 万件 6 GB の日本語 2 文字検索を 0.3 秒) から Phase 1 の 10M 件 × 30 文字取引先名 = 300 MB 相当は pg_bigm/pg_trgm で余裕であり Elastic 導入必要性なし
5.4 案 4 (不採用): Vertex AI Search
- 適合性: 「意味的関連まで返す」設計で電帳法「該当を全件返却」用途と真逆であり JIIMA 機能要件 15 のマニュアル記述が難
- 効率性: $1.50-6.00/1,000 queries × 100 tenant × 検索 20 回/日 × 30 日 = 60K queries/月 → ~$90-360/月の追加 cost が Phase 1 予算過大
- 運用性: GCP lock-in で AWS 移植不可であり Postgres primary の可搬性メリットを毀損する
5.5 案 5 (不採用): Firestore/Bigtable/Spanner
- 適合性: 3 要素複合検索を効率よく満たせない (Firestore は combining index の設計が複雑 · Bigtable は SQL 複合条件不可 · Spanner は full-text search 弱い)
- 効率性: Spanner は最小構成でも高価 · Bigtable は開発工数増大で Phase 0-1 予算超過
6. 影響
6.1 正の影響
- 効率性: Phase 0 dogfood 開始が ~$40/月で始まり dev cost 追加 SaaS ゼロ · Phase 1 GA も ~$1,250/月 (100 tenant で tenant 単価 ~$12.5/月)
- 適合性: 競合 3 社と同じ Postgres 系 stack で JIIMA cert 取得済み precedent がある (freee 会計 認証番号 009000-00 · 607100-00) · cert 障壁になる根拠なし
- 適合性: counterparty_name 正規化を NFKC + カナ統一 + 旧字体 mapping まで拡張し全角スペース · 半角カナ · 旧字体 · Unicode 合成揺れを吸収することで税務調査時の取引先名検索 recall を担保する
- 運用性: Postgres primary で AWS 可搬性を担保 (RDS/Aurora + pg_trgm/pg_bigm 拡張) · 移植時は Postgres レイヤ無改修
- 信頼性: Phase 1 GA 100 tenant × 100K 件は pg_bigm 実測 SoT (NEC 1300 万件 6 GB を 0.3 秒) と比較して余裕であり P95 500ms 目標達成の技術的根拠が確立する
6.2 負の影響 / リスク
- 効率性: Phase 2 拡大時に BigQuery mirror + Datastream + date-hash routing の実装追加コストが発生する · 起票着手トリガーは §9 Confirmation 先行監視での予兆閾値 (400 tenant or 800K 件) 到達 · 起票完了 hard deadline は §8 撤退条件 1 (検索 P95 500ms 2 週連続超過) 発火時点 · 未起票のまま発火した場合は Phase 1 GA の新規 tenant 受入停止 (受入を止めて P95 を戻す)
- 効率性: analytics 用途 (BigQuery) は Phase 2 別 ADR とは独立に別途起票が必要 · 起票着手トリガーは Phase 1 GA 到達 (~2026-10-31) · 起票完了 hard deadline は GA + 1 か月 (= §8 撤退条件 4 発火時点) · 未起票のまま deadline 超過時は Cloud SQL read-only + ad-hoc SQL で凌ぐ (BI 要求への一時対応)
- 保守性:
normalize_counterparty(text) の旧字体 mapping table を追加・更新する度に generated column の REINDEX が必要となり Phase 1 GA 以降は index 再構築時間 (100 tenant × 10M 件想定で数十分〜数時間規模) と読み取り影響を運用 runbook で管理する必要がある · generated column の再定義 (ALTER TABLE ALTER COLUMN による再定義) はテーブル全体の書き換えロックを取得するため CREATE INDEX CONCURRENTLY では回避できず · Phase 0 dogfood 環境で所要時間と lock 影響を実測し P95 500ms SLA への影響を定量化する
- 適合性: JIIMA 事前照会 (~2026-08-06) 回答で pg_trgm/pg_bigm similarity ベース fuzzy match が「機能要件 15 の記載が不明瞭で認証審査上マイナス」と示された場合マニュアル記述を完全一致 + 前方一致 + 部分一致 (LIKE) に限定し fuzzy はオプション表示に降格が必要となる (§8 撤退条件 3 で対応)
- 適合性: Phase 2 で 90 日超データを BigQuery にルーティングする際 Postgres (90 日以内) と BQ (90 日超) にまたがる保存期間 (最長 10 年) 全期間の複合条件検索が federated join 未設計だと pagination · 件数カウント · ソート順の整合性が崩れ税務調査官の「全件提示」要求に応答不能となる · Phase 2 別 ADR の前提条件として §3.1 対策方針で明記済み
7. コスト試算
7.1 前提条件
| 項目 | 値 | 根拠 |
|---|
| Phase 0 tenant 数 | 1 (自社 dogfood) | vlt Phase 0 α経路 (ADR-0125 (JTBD-012 dogfood 先行)) |
| Phase 1 GA tenant 数 | 100 | ADR-0179 SaaS Phase 1 GA 想定 |
| Phase 1 tenant 当たり件数 | 10-100K | 中堅企業の年間帳票量から推定 |
| region | asia-northeast1 | ADR-0200 (asia-northeast1 primary region) |
| 課金モデル | on-demand + 1yr CUD | Cloud SQL 標準 |
7.2 月コスト試算
Phase 0 dogfood (1 tenant · dev のみ · prod 無課金)
| 項目 | 数量 | 月額 |
|---|
| Cloud SQL Postgres db-custom-1-3840 non-HA | 730h | ~$30 |
| Cloud SQL SSD 20 GB | | ~$4.4 |
| Backup (7 日) | 5 GB | ~$0.6 |
| GCS Standard (書類) | ~1 GB | ~$0.02 |
| Cloud Run min-instance = 0 (mandatory) + Cloud SQL Auth Proxy on-demand 起動 | | ~$5 |
| VPC Service Controls (default policy · 追加 policy なし) | | ~$5 |
| Logging + Monitoring | | ~$3 |
| 合計 (min-instance=0 mandatory 前提) | | ~$48/月 (上限 $50 未満) |
⚠️ Phase 0 dogfood 開始 gate 必達条件: Cloud Run min-instance = 0 + Cloud SQL Auth Proxy on-demand 起動 + VPC-SC default policy (追加 policy なし) を mandatory 化し圧縮後実測 ~$48/月 (上限 $50 未満) を厳守する。逸脱時は Phase 0 dogfood 中断 (§9 Confirmation cost 実測で monthly monitor · 逸脱検出時に GO/NO-GO 再判定)。always-on Proxy · min-instance ≥ 1 · 追加 VPC-SC policy を採用したい場合は本 ADR の amend PR で予算計算を再開示し代表取締役承認を得る。
Phase 1 GA (~100 tenant · 10-100K 件/tenant · HA)
| 項目 | 数量 | 月額 |
|---|
| Cloud SQL db-custom-4-15360 + HA (regional) | 730h × 2 | ~$565 |
| Cloud SQL SSD 500 GB × 2 (HA) | 1000 GB | ~$220 |
| Backup (30 日) | ~300 GB | ~$33 |
| Read replica × 1 | 730h | ~$282 |
| GCS Standard (書類 ~5 TB) | 5000 GB | ~$100 |
| Cloud Run + Logging + Monitoring | | ~$50 |
| 合計 (on-demand) | | ~$1,250/月 |
| 1yr CUD 適用時 | | ~$950/月 |
| tenant あたり単価 | | ~$12.5/月/tenant |
実装工数試算
- Phase 0 (DDL + RLS policy +
normalize_counterparty 関数 + 3 要素検索 endpoint + CSV 出力 endpoint 実装): ~6 人日 (vlt/src/db/schema.sql に documents 追加 + withTenantContext wrapper + 検索 API endpoint + CSV 出力 endpoint + 正規化関数 + 旧字体 mapping table)
- Phase 1 pg_bigm 追加 (flag +
CREATE EXTENSION + CREATE INDEX CONCURRENTLY): ~1 人日 (Terraform Cloud SQL flag 追加 + migration script)
- Phase 2 BQ mirror 実装 (Datastream + BQ SEARCH INDEX + アプリ側 federated routing): ~10-15 人日 (別 ADR で決定 · 予算計上のみ · リードタイム短くとも 60 日 · 長くて 90 日)
- analytics 用途 (BigQuery) 実装: ~5-10 人日 (別 ADR で決定 · 予算計上のみ)
8. 撤退条件
- Phase 2 拡大時の BigQuery mirror + Datastream + date-hash routing 別 ADR の起票完了 hard deadline 発火: 検索 P95 latency が 500ms を持続的に (2 週連続で日次 P95) 超過し Cloud SQL スケールアップ (vCPU/RAM 2 倍) + partitioning でも改善しない場合 → Datastream で BigQuery mirror 開始 · BQ 側
CREATE SEARCH INDEX · アプリ側 read path に BQ route 追加 · 90 日超データを BQ ルーティング · pg_partman 月次パーティション化 · 本条件の発火は「Phase 2 拡大時の BigQuery mirror + Datastream + date-hash routing」を扱う別 ADR の起票完了 hard deadline を兼ねる (発火時点で別 ADR 起票完了必須 · 起票着手トリガーは予兆閾値 400 tenant or 800K 件到達 · 未起票のまま発火した場合は Phase 1 GA の新規 tenant 受入停止で P95 を戻す · analytics 用途は本条件と独立に §8 撤退条件 4 で扱う)
- OCR fuzzy 補正の再現率 (recall) が 90% を下回り 税務調査対応時の「取引先で検索して該当証憑を提示」の運用に破綻する場合 → 正規化ロジック見直し (NFKC + カナ統一 + 旧字体 mapping の拡張 or
normalize_counterparty 関数の再定義 + generated column REINDEX) · 取引先マスタ table 導入 · OpenSearch 追加 (self-hosted GKE)
- JIIMA 事前照会 (~2026-08-06) 回答で pg_trgm/pg_bigm の similarity ベース fuzzy match が「機能要件 15 の記載が不明瞭で認証審査上マイナス」と示された場合 → マニュアル記述を完全一致 + 前方一致 + 部分一致 (LIKE) に限定 · UX 上の fuzzy はオプション表示に降格 · pg_bigm による LIKE 高速化のみ残置
- analytics 用途 (BigQuery) の別 ADR 起票完了 hard deadline 発火: Phase 1 GA 到達 (~2026-10-31) から 1 か月経過時点で analytics 用途別 ADR が未起票の場合 → Cloud SQL read-only + ad-hoc SQL で BI 要求を一時対応 · tenant 向け analytics dashboard 提供は別 ADR 起票まで保留 · 本条件の発火は「analytics 用途 (BigQuery)」を扱う別 ADR の起票完了 hard deadline を兼ねる (発火時点で別 ADR 起票完了必須 · 起票着手トリガーは Phase 1 GA 到達 · 未起票のまま 1 か月経過した場合は上記一時対応で凌ぐ · Phase 2 拡大は本条件と独立に §8 撤退条件 1 で扱う)
9. Confirmation
| 検証手段 | 実行頻度 | 目標値 | 違反時対応 |
|---|
| 検索 P95 latency 実測 (Cloud SQL slow query log + Prometheus) | 日次 | ≤ 500ms (Phase 1 GA · 100 tenant · 100K 件) | §8 撤退条件 1 発火 (Phase 2 BQ mirror 別 ADR 起票完了 hard deadline を兼ねる) |
| Phase 2 先行監視指標 (tenant 数 · 総件数) 実測 (Cloud SQL metadata + BigQuery billing export) | 月次 | 中間アラート = 200 tenant or 40 万件到達で Phase 2 別 ADR draft 着手義務 · 予兆閾値 400 tenant or 800K 件到達で起票着手 · 500 tenant or 1M 件到達は §8 撤退条件 1 前倒し監視対象化 | 中間アラート到達で draft 着手 (Phase 2 実装リードタイム 60-90 日を撤退条件 1 発火時期から逆算) · 予兆閾値到達で起票着手 (P95 未超過でも起票判断) |
| analytics 別 ADR 起票 milestone (Phase 1 GA 到達確認 + 起票完了確認) | 1 回 (Phase 1 GA 到達時 + GA + 1 か月時点) | Phase 1 GA (~2026-10-31) から 1 か月以内に analytics 用途別 ADR を起票完了 | §8 撤退条件 4 発火 (analytics 別 ADR 起票完了 hard deadline を兼ねる · Cloud SQL read-only + ad-hoc SQL で一時対応) |
| OCR fuzzy match recall 実測 (integration test で誤読 pattern 20 種 + 正規化 4 クラス pattern 20 種を検証 · 誤読 = OCR 字形誤り · 正規化 4 クラス = 全角スペース / 半角カナ / 旧字体 / Unicode 合成揺れ) | 週次 | ≥ 90% (誤読カテゴリ · 正規化カテゴリで個別に達成) | §8 撤退条件 2 発火 |
| JIIMA 事前照会回答検証 (~2026-08-06 目安) | 1 回 (回答受領時) | pg_trgm/pg_bigm 適合と明示回答 or マニュアル記述で満たせる回答 · 追加確認項目 = fuzzy match 誤ヒット率の認証審査上許容範囲 + ダウンロード出力形式 (施行規則 4 条 1 項 6 号 · 国税庁取扱通達 4-24) の CSV 整然形式該当性 | §8 撤退条件 3 発火 |
PgBouncer pooling mode + tenant コンテキストリーク検証 (vlt/tests/db/documents_rls.test.ts で接続再利用の連続リクエストが異なる tenant を 0 件返却することを複数コネクション同時実行で検証) | PR 毎 CI + 月次 | 全ケース 0 件返却 (SET LOCAL 残留 · planner cache 経由 RLS bypass なし) | Terraform 設定で PgBouncer session mode 強制の再確認 · prepared statement DEALLOCATE ALL 挙動確認 |
| Cloud SQL cost 実測 (BigQuery billing export + Looker Studio) | 月次 | Phase 0 ≤ $50/月 (mandatory) · Phase 1 GA ≤ $1,500/月 | Phase 0 逸脱時は Cloud Run min-instance = 0 + on-demand Proxy · VPC-SC default policy を verify · 逸脱継続 2 週で Phase 0 dogfood 中断 · always-on 化採用は本 ADR amend PR で代表取締役承認 |
| JIIMA 照会項目 5 種の回答マッピング verify (機能要件 15 適合の照会 5 項目 · ダウンロード形式確認を含む) | 1 回 (回答受領時) | 全 5 項目が Postgres pg_trgm/pg_bigm で満たせる | §8 撤退条件 3 発火 or マニュアル追記 |
10. 参照
10.1 関連 ADR
- Depends On: ADR-0203 (
docs/adr/0203-establish-receipts-audit-log-base-schema-amend-retention.md = receipts + audit_log base schema) — documents 表は本 ADR で追加する新規 table · receipts と同じ 4 列 retention 規約 + audit_log 経路を継承
- Depends On: ADR-0229 (
docs/adr/0229-enforce-audit-log-append-only-db-revoke-force-rls.md = audit_log 追記専用性 DB REVOKE + FORCE RLS) — documents 表にも同 2 層防御 (ENABLE RLS + FORCE RLS + REVOKE ALL + GRANT app_user) を適用
- Depends On: ADR-0200 (
docs/adr/0200-confirm-gcp-region-tokyo.md = asia-northeast1 primary region) — Cloud SQL Postgres 配置 region の前提
- Relates To: ADR-0206 (
docs/adr/0206-parallel-jiima-cert-for-scanner-and-e-transaction.md = JIIMA 認証取得ロードマップ) — 機能要件 15 の照会項目 5 種を確定 · 事前照会回答は本 ADR §9 Confirmation に紐付く
- Relates To: ADR-0179 (
docs/adr/0179-jtbd-012-saas-gcp-aws-migration-no-cloudflare.md = SaaS GCP 単一基盤) — Cloud SQL for PostgreSQL の基盤選定起点 · AWS 可搬性要件の下流
- Relates To: ADR-0181 (
docs/adr/0181-establish-vlt-clone-for-jtbd-012-saas.md = vlt clone 設立) — 本 ADR の実装 code path は vlt/src/ 配下
10.2 関連 PR/Issue
- 関連 RQ: RQ-129 (電帳法 3 要素検索索引 3 モデル Deep Research · 2026-07-13 完遂 · $10.17 · Claude + Gemini + OpenAI)
- synthesis:
docs/research/rq-129-three-element-search-index-synthesis.md (= 3 モデル DR の統合成果物)
- 3 モデル result:
docs/research/rq-129-result-{claude,gemini,openai}.md
- 起源 PR: #5824 → #5831 (Wave 1 Level 1 の H1/O1/O4 3 モデル DR 完遂)
10.3 外部資料
- 国税庁「電子帳簿保存法取扱通達解説 (趣旨説明)」 — https://www.nta.go.jp/law/joho-zeikaishaku/sonota/030628/pdf/02.pdf
- JIIMA 電子取引ソフト法的要件認証 FAQ — https://www.jiima.or.jp/certification/denshitorihiki/faq/
- freee プレスリリース (JIIMA 認証取得) — https://corp.freee.co.jp/news/20220829freee_jiima.html
- Google Cloud「BigQuery search index の紹介」 — https://cloud.google.com/bigquery/docs/search-intro
- Google Cloud「Cloud SQL PostgreSQL 拡張機能」 — https://cloud.google.com/sql/docs/postgres/extensions
- NEC「pg_bigm 機能概要」 — https://jpn.nec.com/postgresql/oss_tool/pg_bigm.html
- NEC「pg_bigm を用いた日本語全文検索」 — https://jpn.nec.com/postgresql/technical_info/pg_bigm_v2.html
- AWS Blog「PostgreSQL 拡張 (pg_trgm, pg_bigm)」 — https://aws.amazon.com/blogs/database/index-types-supported-in-amazon-aurora-postgresql-and-amazon-rds-for-postgresql-using-extensions-bloom-pg_trgm-and-pg_bigm/
- Crunchy Data「Row Level Security for Tenants in Postgres」 — https://www.crunchydata.com/blog/row-level-security-for-tenants-in-postgres
11. 実装配線
- lint 配線:
scripts/vlt-schema-lint.mjs (= vlt/src/db/schema.sql の SCHEMA_RULES SoT) に documents 表用の 7 rule (tenant_id NOT NULL / FORCE RLS 宣言 / REVOKE ALL FROM PUBLIC / (tenant_id, X) 複合 index / GIN pg_trgm 索引存在 / normalize_counterparty 関数 immutable 宣言 / CSV 出力 endpoint audit_log 記録) を追加し vlt/tests/db/documents_rls.test.ts に integration test を新設して pg_trgm/pg_bigm 検索 · 正規化 4 クラス (全角スペース / 半角カナ / 旧字体 / Unicode 合成揺れ) recall · FORCE RLS bypass 不可 · PgBouncer 接続再利用連続リクエストで別 tenant 0 件返却を複数コネクション同時実行で検証する
- 起案フロー配線: 本 draft は Pipeline 投入前段階 (
tasks/prompts/draft_adr_*) に配置し JIIMA 事前照会 (~2026-08-06) 回答受領後に §9 Confirmation を amend して scripts/draft_push.sh で正式起案する · docs/architecture/arch_jtbd012_decision_inventory.md の H1 論点行を「draft ADR 起案済 (2026-07-14 · JIIMA 回答後 pipeline 投入)」に更新
- docs SSoT 同期:
.claude/rules/vlt-schema.md (= vlt schema 規約) に documents 表 7 rule (tenant_id NOT NULL + FORCE RLS + REVOKE ALL + 3 要素 btree 索引 + GIN pg_trgm + normalize_counterparty immutable 関数 + CSV 出力 audit_log 記録) を追記 · docs/_internal/06_ops/vlt_runbook.md に「normalize_counterparty mapping table 更新時の generated column REINDEX 手順」および「PgBouncer session mode 強制 + prepared statement DEALLOCATE ALL 手順」を追記 · ADR-0203 の refined_by に本 ADR を追記 (受理時)