経済産業大臣賞受賞 | 木材流通業界のDXを実現したB2BサブスクリプションSaaS
電話・FAX・Excelによるアナログ取引を、Web上で一元管理するSaaS化に成功
クライアント
某木材流通関連企業(本プロダクトにて経済産業大臣賞を受賞) | 業界: 木材サプライチェーン(林業・市場・製材所・プレカット・工務店・メーカーをまたぐB2B流通) | モデル: 招待制 B2B サブスクリプション SaaS(Stripe Connect によるマーケットプレイス決済)
私の役割
テクニカル・アーキテクト 兼 フルスタック・デベロッパー(要件定義・基本設計からフロントエンド・バックエンド・インフラ構築・セキュリティ監査対応・運用保守まで、プロダクト開発の全工程を一人で担当)
課題(Situation & Task)
木材業界は、電話・メール・FAX・Excelでの受発注が主流の、極めてアナログな業界でした。流通には「林業」「市場」「製材所」「プレカット」「工務店」「メーカー」といった多様な業種が多段でつながり、商流や利害関係が複雑に絡み合っていました(業界のしがらみ)。各業種で実行できる操作や閲覧できる情報が異なるうえ、企業をまたいで取引するため、テナント間のデータ分離と決済の正当性を同時に担保する必要がありました。従来は関係性のある既存の取引先としか取引できず、情報も閉鎖的でした。
木材サプライチェーン特有の複雑な課題として、以下の4点が存在していました。
-
業界の根本課題: 電話・FAX・Excelでの受発注が主流で、デジタル化が大幅に遅れていました。在庫情報はExcelで管理され常に最新が不明。FAXでの発注は記録が残らず、電話での確認作業に毎日数時間を要していました。
-
多段商流と業種ベースの認可: 「林業 → 市場 → 製材所 → プレカット → 工務店 → メーカー」と多様な業種(さらに『製材所兼プレカット』のような複合属性、閲覧・管理ロール)がつながり、業種ごとに実行可能な機能・閲覧範囲が異なります。そのため、API単位での厳格な業種ベース認可が必須でした。
-
企業横断のデータ分離(マルチテナント): 企業をまたいで相手を探し取引するため、企業横断の検索・閲覧で相手企業のPII(メール・電話・法人番号など)が漏れないテナント分離が要件でした。
-
決済の正当性と冪等性: 継続課金に加えて取引ごとの精算が発生するマーケットプレイス決済(Stripe Connect)では、金額改ざん・二重課金・Webhookの重複処理が許されず、冪等性と整合性の担保が必須でした。
技術選定の理由(Rationale)
Python 3.11 / Flask / SQLAlchemy 2.0 / Marshmallow 3 / PostgreSQL 16: 帳票生成・Excel取り込み・複雑な多段商流のロジックに最適。Router → UseCase → Repository → Model の厳格な層分離で、変更容易性(ETC)と単一責任(SRP)を担保
React 18 / TypeScript 5.9 / Vite 7 / MUI 7 / TanStack Query 5: 業種ごとに異なる複雑なUI制御と大量データ操作のため採用。
any/letを禁止し Zod で境界検証する型安全規律と、107ルートの遅延ロードで初期バンドルを最小化AWS(ECS Fargate / RDS / Cognito / Lambda / CloudFront / S3 / SQS / EventBridge / DynamoDB): スケーラブルなSaaS基盤。Webhook・帳票・Excel取り込みなど重い/非同期処理は Lambda へ分離しイベント駆動化
Terraform(IaC 100%): VPC〜Cognito〜ECS〜RDS〜CloudFront〜12 の Lambda までを17モジュールでコード化。再現性・レビュー可能性・コスト制御・無停止移行を担保し、S3 ネイティブロックで state を管理
AWS Cognito(JWT RS256): 7業種+閲覧/管理ロールの認証基盤。API Gateway のオーソライザーで全エンドポイントを保護し、業種ベース認可はルーター層で厳格化
Stripe Connect: 継続課金+取引精算+銀行振込に対応するマーケットプレイス決済。金額はサーバ側で解決し、Webhook は冪等化、課金調整はトランザクショナル・アウトボックスで確実に反映
実施したこと(Action)
【業種ベースのマルチテナント認可】 業種コードを機能ごとの
frozensetホワイトリストで定義し、認可判定はルーター層に一元化(不一致は 403、IDの列挙攻撃を抑止)。企業横断の検索・閲覧ではPIIを除外した公開スキーマ(UserPublicSchema)に限定し、相手企業のメール・電話・法人番号が漏れない二層スキーマ境界を実装【認証基盤 Cognito RS256 + JWKS】 API Gateway のオーソライザーで全 221 エンドポイントを保護。バックエンドは RS256 で JWT を検証し
exp/iat/iss/aud/token_useを必須化、token_use==id以外を拒否。JWKS は二重チェックロックのシングルトンでキャッシュし、6時間間隔で更新(起動時プリウォーム)【冪等な決済 Stripe Connect】 サブスク状態は
Userに保持し、Stripe ID 形式を DB の CHECK 制約で検証(cus_/sub_/acct_)。金額はサーバ側で解決して改ざんを排除。Webhook は 3 つの Lambda に分離し、DynamoDB の条件付き書き込み(attribute_not_exists・30日TTL)で重複排除。課金調整はトランザクショナル・アウトボックス+整合化 Lambda(EventBridge 定期実行)で確実に反映【重い処理の並列化】 注文書・納品書・請求書の Excel/PDF を
ThreadPoolExecutorで同時生成(各スレッドに専用アプリコンテキスト、selectinloadで N+1 回避、with_for_updateで競合防止)。Excel→DB 取り込みは S3 イベント駆動の Lambda で一括投入し、50MB 上限・数式インジェクション無害化(CWE-1236)を実装。フロントは指数バックオフ+Page Visibility 対応のポーリングで背面タブの API 浪費を抑制【DBの効率と信頼性】 不足していた 48 本の FK インデックスを
CREATE INDEX CONCURRENTLYで無停止追加。コネクションプールは(5+5)×8タスク < RDS上限で枯渇を予防。日報の N+1(サイト数に比例する flush)を定数化。テストはセーブポイント分離で全件を約 11 秒で実行【セキュリティ監査 4ラウンド】 静的監査 → ライブ診断 → ブラックボックス+ホワイトボックス・ペネトレを実施。実在 15 ロールでの第三者ペネトレ(R4)で全 221 エンドポイントの認証欠落 0 件を実証。クロステナント PII 漏洩・決済金額改ざん・平文資格情報(→ Secrets Manager 移行)・Webhook 冪等性の fail-open(→ fail-closed)等の Critical/High 指摘を全て Close。HSTS/CSP/X-Frame-Options 等のセキュリティヘッダも整備
【可観測性と回復性】 構造化ログ+ERROR の Slack 通知(恒久/一時失敗を分類し指数バックオフでリトライ)。Slack 配信失敗は単一行 JSON マーカーで検知してログインジェクションによるアラーム偽装を防止し、CloudWatch メトリクスフィルタ → SNS メールで Slack 非依存の経路にエスカレーション。マーカー契約はバックエンド/Lambda/Terraform 間で契約テストにより機械的に同期
【IaC・CI/CD・品質ゲート】 GitHub Actions OIDC(長期キーなし)で ECR → ECS 強制デプロイ、S3 同期+CloudFront 無効化。Terraform は plan(PRで tfsec)/apply(権限境界付きロール)/drift 検知(定期 cron → Issue 起票)を自動化。pre-commit/pre-push の二段ゲートで ruff・mypy・Bandit・Vulture・deptry・pip-audit・ESLint・Prettier・tsc・npm audit・Trivy・gitleaks を実行し、Dependabot で 6 エコシステムを継続更新
本プロダクトは B2B・決済・複数企業のデータが交差するため、セキュリティと整合性を最優先に設計しました。
テナント分離とPII保護: 取引相手の情報は、相互に取引関係がある場合のみ詳細スキーマで返し、企業横断の検索・閲覧ではPIIを除外した公開スキーマに限定しました。第三者ペネトレでクロステナントPII漏洩(B-1, HIGH)を検出した際は、即日修正・再診断で0件を確認しています。
決済の冪等性: 金額はサーバ側で解決し、Stripe へのリクエストはコンテンツアドレス方式の冪等キー、Webhook は別 Lambda + DynamoDB の条件付き書き込みで重複排除します。課金調整はアウトボックス+整合化により、ネットワーク断やリトライ下でも二重課金・取りこぼしを防ぎます。
重い処理とUX: 帳票生成はスレッド並列、Excel 取り込みはイベント駆動 Lambda に分離し、フロントは指数バックオフ+可視状態連動のポーリングで完了を待機。重い処理でも管理画面の操作性を損なわない設計です。
運用に耐える基盤: インフラは 100% Terraform 化し、staging/production をコードで再現。停止期間は environment_active 一つで課金リソースをゼロに畳むコスト設計とし、Graviton/Fargate Spot/単一 NAT で平常時コストも最適化しています。
技術選定の理由
React 18 + TypeScript 5.9 + TanStack Query 5:型安全なUIと効率的なデータフェッチ/キャッシュ
Flask + SQLAlchemy 2.0 + Marshmallow 3:層分離アーキテクチャと境界での厳格バリデーション
AWS ECS Fargate + Cognito + Lambda + Terraform:IaCで再現可能・イベント駆動なSaaS基盤
Stripe Connect + DynamoDB:冪等なマーケットプレイス決済とWebhook重複排除
PostgreSQL 16:複雑な多段商流をリレーショナルに表現
担当領域
- 要件定義・アーキテクチャ設計
- フロントエンド開発(React / TypeScript / MUI)
- バックエンド開発(Python / Flask / SQLAlchemy)
- インフラ構築・運用(AWS / Terraform / IaC)
- データベース設計(PostgreSQL)
- セキュリティ監査・ペネトレーションテスト対応
- CI/CD・品質ゲート整備(GitHub Actions)
使用技術
数字で見る成果
- 認証欠落の検出数
- 0件全221エンドポイントをCognito認可で保護。実在15ロールでの第三者ペネトレーションテスト(R4)で認証バイパス0件を実証
- セキュリティ監査
- 4ラウンド静的監査→ライブ診断→ブラックボックス+ホワイトボックス・ペネトレ。クロステナントPII漏洩・決済改ざん等のCritical/High指摘を全てClose
- 自動テスト(バックエンド)
- 2,153件セーブポイント分離で全件を約11秒で実行。Router/UseCase/Schema各層を網羅
- DBマイグレーション
- 204世代Alembicで版管理。48本のFKインデックスはCREATE INDEX CONCURRENTLYで無停止適用
- Terraformモジュール
- 17個VPC・Cognito・ECS・RDS・CloudFront・12のLambdaまでインフラを100%コード化(IaC)
- 本番APIエンドポイント
- 221本Flask-RESTfulで実装。Router→UseCase→Repository→Modelの4層を厳格分離し変更容易性を担保
成果
- 【最大の成果】クライアントはこのプロダクトで「経済産業大臣賞」を受賞
- 公的認定の取得: 本プロダクトは京都府認定を取得し、自治体に認められた信頼性の高いDX基盤として運用
- 業界のDX実現: 電話/FAX/Excelで行われていたアナログな取引を、Web上で一元管理するSaaS化に成功(受発注は9状態のステートマシンとして実装)
- 新たなビジネス機会の創出: 従来の閉鎖的な取引から脱却し、企業をまたいで取引相手を検索・取引できるマーケットプレイスを実現(製材所が市場に足を運ばずとも取引可能に)
- トレーサビリティと信頼の向上: 産地証明(合法木材)・注文連動チャット・0〜5段階の企業評価により、透明性の高い取引を実現
- 業務効率化: 「見積書・納品書・請求書」のExcel/PDFをスレッド並列でワンクリック生成し、既存ExcelはS3イベント駆動Lambdaで自動DB化
- 実証されたセキュリティ: 第三者ペネトレーションテスト(実在15ロール)で全221エンドポイントの認証欠落0件を確認。クロステナントPII漏洩・決済改ざん等のCritical/High指摘を全てClose
- 冪等なマーケットプレイス決済: Stripe Connect+DynamoDBによるWebhook重複排除とトランザクショナル・アウトボックスで、二重課金・取りこぼしを防止
- 運用に耐える基盤: インフラを100% Terraform化(17モジュール・12 Lambda)、GitHub Actions OIDCで自動デプロイ、構造化ログとSlack/CloudWatchの多重アラートで可観測性を担保
同様の課題、抱えていませんか?
あなたのビジネス課題も、最新の技術で解決できます。 まずは30分の無料技術相談から、状況をお聞かせください。
自社の課題もSaaS化できるか相談するプロジェクト単位(請負)・技術顧問、どちらにも対応可能です