この記事で得られること

  • 「1人で作れる規模」を超えたシステムに挑む際の考え方
  • 複雑なマルチテナントシステムの設計概要
  • 手動テストゼロを実現する自動化戦略

はじめに

「1人で保守できないものは作るな」

ソロ開発の鉄則だと思う。でも、あえてその限界に挑戦してみたくなった。

AIコーディングエージェント(Claude Code、GitHub Copilot等)を数カ月実務で使ってきて、「これなら1人でも複雑なものを作れるかもしれない」と思い始めた。ただし条件がある。徹底的な自動化だ。

このブログでは、マルチテナント型サブスクリプション管理システム「Saru」の開発記録を残していく。複雑なシステムを1人で作り切るために、何を自動化し、どう設計したかを共有する。

なぜ「保守できない複雑さ」に挑むのか

  • AIコーディングエージェントで「ちょっとしたもの」ではなく「本格的なもの」を作ってみたい
  • 1人では普通作れない規模のシステムに、自動化でどこまで対抗できるか試したい
  • 失敗しても学びになる。成功すれば再現可能なノウハウになる

Saruの複雑さ

4階層のアカウント構造

一般的なSaaSは「管理者 → ユーザー」の2階層。Saruは4階層ある。

階層役割説明
Systemプラットフォーム管理全体を統括
Providerサービス提供SaaSや商品を提供
Reseller販売代理Providerのサービスを販売
Consumer購入・利用サブスクリプションを購入

さらに:

  • ResellerがPROVIDE権限を持つと独自サービスも提供可能
  • ConsumerがPROVIDE権限を持つとCreator(個人事業者)になれる

この柔軟性が複雑さの源泉であり、差別化ポイントでもある。

4ポータル × 4API

各階層に専用のフロントエンドとAPIがある。

ポータルAPIポート
System Portalsystem-api3001 / 8080
Provider Portalprovider-api3002 / 8081
Reseller Portalreseller-api3003 / 8082
Customer Portalcustomer-api3004 / 8083

ポータルは動的サブドメインで分離(例: provider-xxx.example.com

その他の複雑さ

  • 認証: Keycloak統合、WebAuthnパスキー、OTP認証、ポータル間セッション分離
  • データ分離: PostgreSQL Row-Level Security(RLS)によるマルチテナント分離
  • 権限制御: Capabilityモデル(CONSUME/PROVIDE/RESELL/ADMINISTER)

自動化戦略:手動テストゼロ

この複雑さを1人で保守するために、手動テストを完全に排除する方針を取った。

E2Eテスト(Playwright)

  • WebAuthn(パスキー)認証のテストも自動化
  • 仮想認証器を使ってCI環境でも実行可能
  • 全ポータルの主要フローをカバー

CI/CD

  • Self-hosted GitHub Actions Runner(WSL2上)
  • PR作成時に自動でE2Eテスト実行
  • Lint(ESLint, golangci-lint)・型チェック(TypeScript)

開発フロー

Claude Codeのspeckitワークフローで、仕様→設計→実装→検証を一貫して行う。

/speckit.specify(仕様作成)
    ↓
/qa.verify-spec(仕様の検証)← 仕様作成後に実行
    ↓
/speckit.clarify + 専門家検証(曖昧さ解消)
    ↓
/speckit.plan(設計計画)
    ↓
/qa.verify-design(設計の検証)← 設計後に実行
    ↓
/speckit.tasks(タスク生成)
    ↓
/speckit.analyze(整合性確認)← 実装前に必ず実行
    ↓
/speckit.implement(実装)
    ↓
/qa.verify-*(各種検証)
    ↓
テスト → Lint → コミット → PR → CI

フェーズ別ツール活用

各フェーズで使うツールを決めておくことで、抜け漏れを防ぐ。

フェーズ補助ツール
仕様作成Context7、Tavily、Sequential Thinking
仕様明確化backend-architect、security-engineer
設計計画backend-architect、Context7
タスク生成Serena、Sequential Thinking
整合性確認Serena、Codex
実装Serena、security-engineer

検証コマンド

仕様・設計の検証:

コマンドタイミング用途
/qa.verify-specspecify後仕様の検証(要件の網羅性、実現可能性、矛盾の有無)
/qa.verify-designplan後設計の検証(アーキテクチャの妥当性、既存パターンとの整合性)

実装後の検証:

/qa.verify-impl → /qa.verify-test → テスト → Lint → コミット → PR → CI
コマンド用途
/qa.verify-impl実装コードの検証(設計との整合性、コードスタイル、セキュリティ)
/qa.verify-testテストコードの検証(カバレッジ、テストパターン)
/qa.verify-migrationDBマイグレーションの検証(Up/Down整合性、RLS、インデックス)
/qa.verify-rlsRLSポリシーの検証(テナント分離、クロスアクセス防止)
/qa.verify-apiAPI設計の検証(REST設計、認証、エラーハンドリング)

問題調査:

コマンド用途
/qa.investigate多角的な調査(MCP、専門家エージェント、サブエージェント活用)

技術スタック

領域技術
FrontendNext.js 14 (App Router), TypeScript, TanStack Query, shadcn/ui
BackendGo, Echo, sqlc
DatabasePostgreSQL with Row-Level Security
AuthKeycloak
TestPlaywright (E2E), WebAuthn仮想認証器
CI/CDGitHub Actions (Self-hosted Runner)

画面イメージ

System Portal ログイン画面

System Portal ログイン

メールアドレスを入力してOTPを送信する。

OTP入力画面

OTP入力

6桁のワンタイムパスワードを入力して認証。

Provider Portal サインアップ画面

Provider Portal サインアップ

サービス提供者として新規登録する画面。

現段階で実装済みの機能

  • 4ポータルの基本UI
  • 4APIの基本エンドポイント
  • Keycloak認証統合(WebAuthn + OTP)
  • アカウント・ユーザーCRUD
  • RLSによるデータ分離
  • Capabilityモデルによる権限制御
  • Playwright E2Eテスト(WebAuthn対応)
  • CI/CDパイプライン

今後の予定

  • 多言語対応(i18n)
  • 多通貨対応
  • サブスクリプション管理機能
  • 決済連携(Stripe等)
  • Webhook連携による自動プロビジョニング