integration-corp-ops — curumi-ops

curumi-corp ↔︎ curumi-ops 疎結合連携仕様

curumi の2つのリポジトリの役割境界・共有点・分離点を整理する。境界が曖昧だと修正範囲が膨らみ、片方の変更が他方を壊すリスクが上がる。

ステータス: 以下に記載される役割表は 設計上の目標 を含む。2026-04 時点での ops 側の実装状況: - ✅ 稼働中: 戦略ドキュメント配信(ops.curumi.co.jp) - 🗑 撤去済: 広告管理 (apps/ops_archive/)、ナレッジ収集 (apps/knowledge-base 削除) - 📅 再実装候補: 広告管理、クライアントレポート、ナレッジ収集

再実装する場合のリファレンスとして本書を保持。疎結合の原則(Turso 共有のみ、コード依存なし)は変わらない。

全体像(目標像)

curumi-corp (集客サイト)              curumi-ops (社内運用)
┌─────────────────────┐             ┌─────────────────────┐
│ admin.curumi.co.jp   │             │ ops.curumi.co.jp      │
│  - 記事管理          │             │  - 戦略docs (稼働中)  │
│  - 編集方針         │             │  - 広告管理 (未実装)  │
│  - cron (記事生成)   │             │  - レポート (未実装)  │
│ curumi.co.jp         │             │  - ナレッジ (未実装)  │
│  - 記事閲覧          │             │  - ペルソナ (未実装)  │
│  - sitemap/llms.txt  │             │                      │
└──────────┬──────────┘             └──────────┬──────────┘
           │                                    │
           │  read/write                        │  read
           └─────────┬──────────────────────────┘
                     ▼
           ┌────────────────────┐
           │   Turso (libSQL)   │ ← 単一の真実
           │  - articles        │
           │  - keywords        │
           │  - personas        │
           │  - editorial cfg   │
           └────────────────────┘

役割境界

領域 curumi-corp curumi-ops ops 実装状況
記事管理(CRUD) ★ Owner
記事閲覧(公開) ★ Owner
記事生成 cron ★ Owner
キーワード管理 ★ Owner(管理画面) ○ 参照のみ 未実装
編集方針 / ブランド設定 ★ Owner(*.config.ts ○ 参照のみ 未実装
広告データ収集(Google/Meta API) ★ Owner 未実装(旧実装は _archive/
広告レポート生成 ★ Owner 未実装(旧実装は _archive/
クライアント別レポート閲覧 ★ Owner 未実装(旧実装は _archive/
ペルソナ定義 ○ 参照(記事生成で使用) ★ Owner(管理画面) 未実装
マーケ知識収集(articles/x/youtube) ★ Owner(GHA cron) 未実装(旧実装は削除)
戦略ドキュメント配信 ★ Owner(docs/strategy/ops.curumi.co.jp ✅ 稼働中

★ = 一次責任、○ = 二次参照

共有しているもの

Turso DB

1つの DB を両方が使う。テーブル単位で「書き手は誰か」が決まっている。

articles, keywords, editorial_*  → corp が書き手
personas, ad_*, report_*         → ops が書き手

rule: - 自分のテーブルしか書かない - 他方のテーブルは read のみ、SQL で直接更新しない - スキーマ変更は drizzle-kit generate → migrate(手動 ALTER 禁止、ops の CLAUDE.md 参照)

環境変数の管理

変数 管理場所 共有
TURSO_DATABASE_URL 1Password vault curumi 両方が参照
TURSO_AUTH_TOKEN 1Password vault curumi 両方が参照
アプリ固有のキー apps/*/.env.local (corp/ops それぞれ) 各repo独立

重要なインシデント教訓(corp CLAUDE.md より): - 過去に staging DB の URL を本番 GitHub Secrets に上書き → 全記事消失 - .env(staging)と GitHub Secrets(本番)を絶対に混ぜない

分離しているもの(独立性)

片方が落ちても他方は稼働可能。これが疎結合の意味。

連携が発生するケース

ケース 連携手段 注意
corp で記事生成時にペルソナを参照 DB read(personas テーブル) personas のスキーマ変更時は事前共有
ops で記事の閲覧数を集計 DB read(articles テーブル) articles のスキーマ変更時は事前共有
ブランド設定変更 corp の brand.config.ts を編集 → 必要なら ops 側で同等の設定を更新 二重管理。将来は DB に集約検討

API 経由の連携は現時点では無し。すべて DB 経由。

障害時の独立性チェックリスト

corp が落ちた場合

ops が落ちた場合

Turso が落ちた場合

設計原則

  1. DB を共有してもアプリは疎結合: コード共有はしない、依存もしない
  2. テーブルの書き手は1つ: 同じテーブルを両方から書くと整合性が崩れる
  3. スキーマ変更は事前共有: 影響範囲を見てから migrate
  4. 片方の障害は他方に伝播させない: API直接依存を作らない
  5. 設定の二重管理は許容するが、いずれDBに集約: 現状は許容、整理は将来課題

将来の検討事項