この記事で得られること
- 「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 Portal | system-api | 3001 / 8080 |
| Provider Portal | provider-api | 3002 / 8081 |
| Reseller Portal | reseller-api | 3003 / 8082 |
| Customer Portal | customer-api | 3004 / 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-spec | specify後 | 仕様の検証(要件の網羅性、実現可能性、矛盾の有無) |
/qa.verify-design | plan後 | 設計の検証(アーキテクチャの妥当性、既存パターンとの整合性) |
実装後の検証:
/qa.verify-impl → /qa.verify-test → テスト → Lint → コミット → PR → CI
| コマンド | 用途 |
|---|---|
/qa.verify-impl | 実装コードの検証(設計との整合性、コードスタイル、セキュリティ) |
/qa.verify-test | テストコードの検証(カバレッジ、テストパターン) |
/qa.verify-migration | DBマイグレーションの検証(Up/Down整合性、RLS、インデックス) |
/qa.verify-rls | RLSポリシーの検証(テナント分離、クロスアクセス防止) |
/qa.verify-api | API設計の検証(REST設計、認証、エラーハンドリング) |
問題調査:
| コマンド | 用途 |
|---|---|
/qa.investigate | 多角的な調査(MCP、専門家エージェント、サブエージェント活用) |
技術スタック
| 領域 | 技術 |
|---|---|
| Frontend | Next.js 14 (App Router), TypeScript, TanStack Query, shadcn/ui |
| Backend | Go, Echo, sqlc |
| Database | PostgreSQL with Row-Level Security |
| Auth | Keycloak |
| Test | Playwright (E2E), WebAuthn仮想認証器 |
| CI/CD | GitHub Actions (Self-hosted Runner) |
画面イメージ
System Portal ログイン画面

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

6桁のワンタイムパスワードを入力して認証。
Provider Portal サインアップ画面

サービス提供者として新規登録する画面。
現段階で実装済みの機能
- 4ポータルの基本UI
- 4APIの基本エンドポイント
- Keycloak認証統合(WebAuthn + OTP)
- アカウント・ユーザーCRUD
- RLSによるデータ分離
- Capabilityモデルによる権限制御
- Playwright E2Eテスト(WebAuthn対応)
- CI/CDパイプライン
今後の予定
- 多言語対応(i18n)
- 多通貨対応
- サブスクリプション管理機能
- 決済連携(Stripe等)
- Webhook連携による自動プロビジョニング