{
  "schemaVersion": "1.0.0",
  "metadata": {
    "serviceName": "かけあい",
    "modelKind": "repository-evidenced-current-state",
    "primaryEnvironment": "production configuration",
    "runtimeQualification": "production用設定に基づく論理構成・実稼働未確認",
    "observedAt": "2026-10-01T16:33:08+09:00",
    "repositoryRoot": "/mnt/hdd8tb/kk/works/bluem/CommunityAI/OKR/mock_okr_cai",
    "branch": "main",
    "commit": "30b101f70ea31c11706ea148f7272fbc29053a69",
    "initialWorktree": "clean",
    "includesPreExistingUncommittedChanges": false,
    "arrowSemantics": "実線は要求・主要データの論理方向（応答は同じ接続を戻る）。青の破線は接続確立方向。灰色の点線は利用者が任意に開く外部リンク。"
  },
  "boundaries": [
    {
      "id": "B01",
      "name": "利用者端末",
      "owner": "利用者／導入機関"
    },
    {
      "id": "B02",
      "name": "Cloudflare 管理領域",
      "owner": "外部サービス"
    },
    {
      "id": "B03",
      "name": "自社管理の本番ホスト",
      "owner": "サービス運営者",
      "qualification": "プライバシーポリシーは国内自社サーバーとするが、実ホスト所在地は未確認"
    },
    {
      "id": "B04",
      "name": "OpenAI 管理領域",
      "owner": "外部サービス"
    },
    {
      "id": "B05",
      "name": "利用者が指定する外部ファイル保管先",
      "owner": "導入機関／第三者",
      "qualification": "かけあいはファイル本体をアップロードせずHTTPS URLだけを保存"
    }
  ],
  "nodes": [
    {
      "id": "N01",
      "name": "一般利用者のブラウザ",
      "shortName": "学生・参加者",
      "kind": "person-client",
      "boundaryId": "B01",
      "technology": "Web browser",
      "responsibility": "member は目標・成果物・相談を作成、viewer は許可された提出済み情報を閲覧",
      "runtimeStatus": "role implemented",
      "evidenceRefs": ["R001", "R002", "R003"]
    },
    {
      "id": "N02",
      "name": "スタッフのブラウザ",
      "shortName": "メンター・管理者",
      "kind": "person-client",
      "boundaryId": "B01",
      "technology": "Web browser",
      "responsibility": "mentor は運用・支援機能、admin は管理者限定操作を利用",
      "runtimeStatus": "role implemented",
      "evidenceRefs": ["R001", "R004"]
    },
    {
      "id": "N03",
      "name": "Cloudflare Edge / Tunnel サービス",
      "shortName": "公開Web入口",
      "kind": "external-service",
      "boundaryId": "B02",
      "technology": "Cloudflare edge + Tunnel",
      "responsibility": "app/admin の公開HTTPSを受け、既存Tunnelを通じローカルoriginへ中継",
      "runtimeStatus": "configuration present; live resource unverified",
      "evidenceRefs": ["R005", "R006", "R007"]
    },
    {
      "id": "N04",
      "name": "Cloudflare Access",
      "shortName": "スタッフ認証ゲート",
      "kind": "external-service",
      "boundaryId": "B02",
      "technology": "Access application + RS256 JWT/JWKS",
      "responsibility": "admin host のスタッフ認証。管理操作は有効な通常スタッフ認証とサーバー側の権限検査を使用",
      "runtimeStatus": "application integration implemented; dashboard policy unverified",
      "evidenceRefs": ["R008", "R009", "R010"]
    },
    {
      "id": "N05",
      "name": "cloudflared connector",
      "shortName": "Tunnel接続プロセス",
      "kind": "host-process",
      "boundaryId": "B03",
      "technology": "cloudflared / systemd",
      "responsibility": "外向きにTunnel接続を確立し、受信要求を固定loopback originへ渡す",
      "runtimeStatus": "production unit/config present; service state unverified",
      "evidenceRefs": ["R006", "R011"]
    },
    {
      "id": "N06",
      "name": "HAProxy",
      "shortName": "ローカル切替入口",
      "kind": "host-process",
      "boundaryId": "B03",
      "technology": "HAProxy / systemd",
      "responsibility": "固定loopback portで受け、active Web slotへ転送。更新時は旧slotをdrain",
      "runtimeStatus": "production configuration implemented; service state unverified",
      "evidenceRefs": ["R005", "R012", "R013"]
    },
    {
      "id": "N07",
      "name": "かけあい Web",
      "shortName": "Next.js Web コンテナ",
      "kind": "application-container",
      "boundaryId": "B03",
      "technology": "Next.js 16 / Node.js 22 / Docker",
      "responsibility": "画面・same-origin API、一般利用者セッション、Access JWT検証、認可、DB更新、AIジョブ投入",
      "runtimeStatus": "blue/green slots configured; active slot and live container unverified",
      "evidenceRefs": ["R014", "R015", "R016", "R017"]
    },
    {
      "id": "N08",
      "name": "かけあい AI Worker",
      "shortName": "Next.js Worker コンテナ",
      "kind": "worker-container",
      "boundaryId": "B03",
      "technology": "Node.js 22 / Docker / PostgreSQL durable jobs",
      "responsibility": "永続キューをclaimし、OpenAI呼び出し後に結果を業務データへ反映",
      "runtimeStatus": "blue/green slots configured; live worker unverified",
      "evidenceRefs": ["R018", "R019", "R020"]
    },
    {
      "id": "N09",
      "name": "業務 PostgreSQL",
      "shortName": "業務・セッション・ジョブの正本",
      "kind": "database-container",
      "boundaryId": "B03",
      "technology": "PostgreSQL 17 / internal Docker network",
      "responsibility": "プロフィール、組織、目標、成果物、相談、アプリセッション、監査、AIジョブ・結果を永続化",
      "runtimeStatus": "production container/migrations present; live DB and backup unverified",
      "evidenceRefs": ["R021", "R022", "R023", "R024"]
    },
    {
      "id": "N10",
      "name": "一般利用者 Auth Worker",
      "shortName": "登録・OTP・パスワード認証",
      "kind": "external-worker",
      "boundaryId": "B02",
      "technology": "Cloudflare Workers / Hono",
      "responsibility": "許可ドメイン判定、登録OTP、パスワード認証・再発行、短命JWT発行",
      "runtimeStatus": "production Worker config present; deployed version unverified",
      "evidenceRefs": ["R025", "R026", "R027"]
    },
    {
      "id": "N11",
      "name": "認証 D1",
      "shortName": "認証データの正本",
      "kind": "external-database",
      "boundaryId": "B02",
      "technology": "Cloudflare D1",
      "responsibility": "メールID、パスワードハッシュ、OTP/再発行トークンのハッシュ、同意記録、rate limitを保存",
      "runtimeStatus": "binding/migrations present; live data and residency unverified",
      "evidenceRefs": ["R025", "R028", "R029"]
    },
    {
      "id": "N12",
      "name": "認証メール配信",
      "shortName": "OTP・再発行通知",
      "kind": "external-service",
      "boundaryId": "B02",
      "technology": "Cloudflare Email Sending binding",
      "responsibility": "登録・再発行OTPと再発行完了通知を利用者メールへ送信",
      "runtimeStatus": "binding/code present; delivery configuration and live sends unverified",
      "evidenceRefs": ["R025", "R030"]
    },
    {
      "id": "N13",
      "name": "OpenAI API",
      "shortName": "AI回答・埋め込み・Web検索",
      "kind": "external-service",
      "boundaryId": "B04",
      "technology": "Responses API / Embeddings API",
      "responsibility": "最小化済み入力から回答・フィードバック・類似性ベクトル・調査結果を生成",
      "runtimeStatus": "integration implemented; account settings, contract and live requests unverified",
      "evidenceRefs": ["R031", "R032", "R033", "R034"]
    },
    {
      "id": "N14",
      "name": "外部ファイル保管先",
      "shortName": "利用者が登録したHTTPS URL",
      "kind": "external-link-target",
      "boundaryId": "B05",
      "technology": "unspecified external HTTPS service",
      "responsibility": "成果物タスクに紐づくファイル本体を外部側で保持。かけあいはURLだけを保存",
      "runtimeStatus": "optional data model field; provider unspecified",
      "evidenceRefs": ["R035", "R036"]
    }
  ],
  "edges": [
    {
      "id": "E01",
      "from": "N01",
      "to": "N03",
      "label": "公開ページ・ログイン後画面・same-origin API",
      "protocol": "HTTPS",
      "data": "画面入力、Cookie、目標・成果物・相談",
      "kind": "request",
      "evidenceRefs": ["R006", "R015", "R037"]
    },
    {
      "id": "E02",
      "from": "N02",
      "to": "N04",
      "label": "admin host アクセス",
      "protocol": "HTTPS / Cloudflare Access",
      "data": "スタッフ認証、Access assertion",
      "kind": "request",
      "evidenceRefs": ["R008", "R010"]
    },
    {
      "id": "E03",
      "from": "N04",
      "to": "N03",
      "label": "認証済み管理要求",
      "protocol": "Cloudflare edge internal",
      "data": "Access JWT付きHTTP要求",
      "kind": "request",
      "evidenceRefs": ["R008", "R009"]
    },
    {
      "id": "E04",
      "from": "N03",
      "to": "N05",
      "label": "Tunnel内の論理リクエスト方向",
      "protocol": "Cloudflare Tunnel",
      "data": "通常Web/API本文を含むHTTP要求",
      "kind": "request",
      "evidenceRefs": ["R005", "R006"]
    },
    {
      "id": "E05",
      "from": "N05",
      "to": "N03",
      "label": "connectorが外向きに接続確立",
      "protocol": "outbound tunnel connection",
      "data": "Tunnel接続",
      "kind": "connection-establishment",
      "evidenceRefs": ["R011"]
    },
    {
      "id": "E06",
      "from": "N05",
      "to": "N06",
      "label": "公開hostを固定originへ転送",
      "protocol": "HTTP loopback :3001",
      "data": "Hostを保持したWeb/API要求",
      "kind": "request",
      "evidenceRefs": ["R005", "R012", "R013"]
    },
    {
      "id": "E07",
      "from": "N06",
      "to": "N07",
      "label": "active Web slotへ転送",
      "protocol": "HTTP loopback :3002 または :3003",
      "data": "Web/API要求。旧slotはdrain",
      "kind": "request",
      "evidenceRefs": ["R012", "R013"]
    },
    {
      "id": "E08",
      "from": "N07",
      "to": "N09",
      "label": "セッション照合・業務読書き・AIジョブ投入",
      "protocol": "PostgreSQL protocol / TLS required by production example",
      "data": "プロフィール、組織/チーム、成果物、相談、監査、ジョブ",
      "kind": "data",
      "evidenceRefs": ["R016", "R021", "R022", "R038"]
    },
    {
      "id": "E09",
      "from": "N07",
      "to": "N10",
      "label": "登録・OTP・ログイン・再発行",
      "protocol": "HTTPS POST / service client credentials",
      "data": "メールID、パスワード/OTP、氏名、管理用識別子、同意版",
      "kind": "request",
      "evidenceRefs": ["R026", "R039", "R040"]
    },
    {
      "id": "E10",
      "from": "N10",
      "to": "N11",
      "label": "認証データ保存・照合・期限切れ清掃",
      "protocol": "D1 binding / scheduled daily",
      "data": "認証ID、credential hash、OTP/token hash、同意、rate limit",
      "kind": "data",
      "evidenceRefs": ["R025", "R027", "R028", "R029"]
    },
    {
      "id": "E11",
      "from": "N10",
      "to": "N12",
      "label": "OTP・再発行通知",
      "protocol": "Email Sending binding",
      "data": "宛先メール、OTPまたは通知本文",
      "kind": "request",
      "evidenceRefs": ["R030"]
    },
    {
      "id": "E12",
      "from": "N07",
      "to": "N04",
      "label": "Access JWTをJWKSで再検証",
      "protocol": "HTTPS / RS256 JWKS",
      "data": "公開鍵取得、issuer/audience/claims検証",
      "kind": "request",
      "evidenceRefs": ["R009", "R010"]
    },
    {
      "id": "E13",
      "from": "N08",
      "to": "N09",
      "label": "永続ジョブclaim・結果反映",
      "protocol": "PostgreSQL protocol / TLS",
      "data": "queue/attempt/lease、生成結果、AI監査メタデータ",
      "kind": "data",
      "evidenceRefs": ["R018", "R019", "R020"]
    },
    {
      "id": "E14",
      "from": "N08",
      "to": "N13",
      "label": "回答・フィードバック・埋め込み・調査",
      "protocol": "HTTPS POST",
      "data": "氏名alias化・メール/ID/電話/secret除去後の必要文脈。store=false",
      "kind": "request",
      "evidenceRefs": ["R031", "R032", "R033", "R034"]
    },
    {
      "id": "E15",
      "from": "N01",
      "to": "N14",
      "label": "保存済みURLを利用者が任意に開く",
      "protocol": "HTTPS (browser direct)",
      "data": "リンク先への通常ブラウザ要求。アプリによるファイル転送ではない",
      "kind": "optional-user-navigation",
      "evidenceRefs": ["R035", "R036"]
    }
  ],
  "stakeholderAggregation": [
    { "id": "S01", "name": "学生・参加者", "nodeIds": ["N01"] },
    { "id": "S02", "name": "メンター・管理者", "nodeIds": ["N02"] },
    { "id": "S03", "name": "CloudflareのWeb入口", "nodeIds": ["N03", "N04"] },
    { "id": "S04", "name": "自社内の通信入口", "nodeIds": ["N05", "N06"] },
    { "id": "S05", "name": "かけあい", "nodeIds": ["N07", "N08"] },
    { "id": "S06", "name": "自社管理の記録保管", "nodeIds": ["N09"] },
    { "id": "S07", "name": "Cloudflare認証サービス", "nodeIds": ["N10", "N11", "N12"] },
    { "id": "S08", "name": "OpenAI", "nodeIds": ["N13"] },
    { "id": "S09", "name": "外部ファイル保管先", "nodeIds": ["N14"] }
  ],
  "stakeholderConnections": [
    { "id": "SA01", "from": "S01", "to": "S03", "edgeIds": ["E01"], "label": "入力・閲覧" },
    { "id": "SA02", "from": "S02", "to": "S03", "edgeIds": ["E02", "E03"], "label": "管理画面" },
    { "id": "SA03", "from": "S03", "to": "S04", "edgeIds": ["E04", "E05", "E06"], "label": "Tunnel中継" },
    { "id": "SA04", "from": "S04", "to": "S05", "edgeIds": ["E07"], "label": "Web/API" },
    { "id": "SA05", "from": "S05", "to": "S06", "edgeIds": ["E08", "E13"], "label": "記録を保存" },
    { "id": "SA06", "from": "S05", "to": "S07", "edgeIds": ["E09", "E10", "E11"], "label": "登録・ログイン" },
    { "id": "SA07", "from": "S05", "to": "S08", "edgeIds": ["E14"], "label": "加工後の必要情報でAI処理を依頼" },
    { "id": "SA08", "from": "S01", "to": "S09", "edgeIds": ["E15"], "label": "保存済みリンクを任意に開く" }
  ],
  "environments": [
    {
      "id": "production",
      "summary": "本図の主対象。bridge network、固定origin :3001、blue/green Web/Worker、OpenAI key分離。リポジトリ内設定のみで実稼働未確認。"
    },
    {
      "id": "staging",
      "summary": "host network、固定origin :3200、blue/green Web/Worker、OpenAI key共有を許可。内部検証用で本番/PITR代替ではない。"
    },
    {
      "id": "development",
      "summary": "通常SaaSはPostgreSQLを使う。任意の非本番dev authがあり、standalone demoは別workspace・sample data。"
    }
  ],
  "runtimeViews": [
    {
      "id": "RV01",
      "diagram": "supplementary/03-blue-green-deployment",
      "name": "Blue-Green Deployment構成",
      "scope": "production用local blue/green設定。同一migrationVersionの通常リリース。平常時は1 Worker container、更新中は新旧2 Worker containers。実稼働未確認。",
      "nodes": [
        { "id": "Z01", "name": "Cloudflare Edge / Tunnel", "evidenceRefs": ["R041"] },
        { "id": "Z02", "name": "cloudflared connector", "evidenceRefs": ["R041"] },
        { "id": "Z03", "name": "HAProxy固定origin", "evidenceRefs": ["R041", "R044"] },
        { "id": "Z04", "name": "local-bluegreen orchestrator / supervisor", "evidenceRefs": ["R044"] },
        { "id": "Z05", "name": "Blue slot（Web ×1 + AI Worker ×1）", "evidenceRefs": ["R042", "R043", "R047", "R049", "R050", "R051", "R052"] },
        { "id": "Z06", "name": "Green slot（Web ×1 + AI Worker ×1）", "evidenceRefs": ["R042", "R043", "R047", "R049", "R050", "R051", "R052"] },
        { "id": "Z07", "name": "共有PostgreSQL", "evidenceRefs": ["R041", "R042"] },
        { "id": "Z08", "name": "OpenAI API", "evidenceRefs": ["R032"] }
      ],
      "edges": [
        { "id": "ZE01", "from": "Z01", "to": "Z02", "label": "Tunnel内の要求", "evidenceRefs": ["R041"] },
        { "id": "ZE02", "from": "Z02", "to": "Z03", "label": "固定origin :3001", "evidenceRefs": ["R041", "R042"] },
        { "id": "ZE03", "from": "Z03", "to": "Z05", "label": "active slotへ新規要求", "evidenceRefs": ["R044"] },
        { "id": "ZE04", "from": "Z03", "to": "Z06", "label": "readiness後に一括切替", "evidenceRefs": ["R044"] },
        { "id": "ZE05", "from": "Z04", "to": "Z03", "label": "Runtime APIでweight / drain制御", "evidenceRefs": ["R044"] },
        { "id": "ZE06", "from": "Z04", "to": "Z06", "label": "空slot起動・readiness確認", "evidenceRefs": ["R044"] },
        { "id": "ZE07", "from": "Z05", "to": "Z07", "label": "業務・session・release別job", "evidenceRefs": ["R041", "R043"] },
        { "id": "ZE08", "from": "Z06", "to": "Z07", "label": "業務・session・release別job", "evidenceRefs": ["R041", "R043"] },
        { "id": "ZE09", "from": "Z05", "to": "Z08", "label": "旧slot WorkerからAI要求", "evidenceRefs": ["R032", "R043", "R049", "R050", "R051"] },
        { "id": "ZE10", "from": "Z06", "to": "Z08", "label": "切替後slot WorkerからAI要求", "evidenceRefs": ["R032", "R043", "R047"] }
      ],
      "caveats": [
        "平常時はactive slotのAI Worker 1 container。更新中だけ新旧2 Worker containersが並行稼働する。",
        "旧Webは接続数0まで、旧Workerは旧releaseのjob・attempt・command・provider leaseが全て0になるまで保持する。",
        "migrationVersionが異なる通常deployは拒否される。非互換DB変更は計画停止が必要。",
        "初回の単一runtimeからの切替には1回限りの計画停止が必要。"
      ]
    },
    {
      "id": "RV02",
      "diagram": "supplementary/04-legacy-single-runtime",
      "name": "旧・単一runtime構成",
      "scope": "repositoryに併存するsingle production runtime / Compose構成。採用履歴・実稼働未確認。",
      "nodes": [
        { "id": "L01", "name": "Cloudflare Edge / Tunnel", "evidenceRefs": ["R045"] },
        { "id": "L02", "name": "cloudflared connector", "evidenceRefs": ["R045"] },
        { "id": "L03", "name": "単一combined SaaS container", "evidenceRefs": ["R045", "R046", "R047", "R048"] },
        { "id": "L04", "name": "PostgreSQL", "evidenceRefs": ["R045", "R048"] },
        { "id": "L05", "name": "OpenAI API", "evidenceRefs": ["R032", "R047"] },
        { "id": "L06", "name": "production host-runtime supervisor", "evidenceRefs": ["R045"] }
      ],
      "edges": [
        { "id": "LE01", "from": "L01", "to": "L02", "label": "Tunnel内の要求", "evidenceRefs": ["R045"] },
        { "id": "LE02", "from": "L02", "to": "L03", "label": "loopback :3000へ直接転送", "evidenceRefs": ["R045", "R048"] },
        { "id": "LE03", "from": "L03", "to": "L04", "label": "業務・session・job", "evidenceRefs": ["R045", "R048"] },
        { "id": "LE04", "from": "L03", "to": "L05", "label": "combined process内WorkerからAI要求", "evidenceRefs": ["R032", "R047"] },
        { "id": "LE05", "from": "L06", "to": "L02", "label": "readiness連動で起動・停止", "evidenceRefs": ["R045"] },
        { "id": "LE06", "from": "L06", "to": "L03", "label": "stop/remove/create/start", "evidenceRefs": ["R045"] }
      ],
      "caveats": [
        "更新時は旧containerを停止・削除してから新containerを作成・起動する。",
        "新runtimeのreadiness成功後にTunnelを再開するため、blue/greenの同時稼働・drainはない。",
        "combined roleではWebとAI Workerが同じprocessで動き、shutdown時のWorker drainは既定OFF。"
      ]
    },
    {
      "id": "RV03",
      "diagram": "supplementary/05-data-flow",
      "name": "データの流れと保存先",
      "scope": "認証・セッション、画面・業務データ、AI処理、外部ファイルの4経路を、データ種別ごとの小さな流れとして整理する。実線は主要な送信・保存方向、灰色点線はブラウザが外部ファイルを直接開く経路。",
      "nodes": [
        { "id": "F01", "name": "利用者ブラウザ（認証）", "evidenceRefs": ["R039"] },
        { "id": "F02", "name": "かけあい Web（認証受付）", "evidenceRefs": ["R039", "R040"] },
        { "id": "F03", "name": "一般利用者 Auth Worker", "evidenceRefs": ["R025", "R026", "R027"] },
        { "id": "F04", "name": "認証D1", "evidenceRefs": ["R028", "R029"] },
        { "id": "F05", "name": "認証メール", "evidenceRefs": ["R030"] },
        { "id": "F06", "name": "業務PostgreSQL（session）", "evidenceRefs": ["R016", "R023"] },
        { "id": "F07", "name": "利用者・スタッフブラウザ", "evidenceRefs": ["R001", "R004", "R015"] },
        { "id": "F08", "name": "Cloudflare Edge / Tunnel", "evidenceRefs": ["R005", "R006", "R008"] },
        { "id": "F09", "name": "かけあい Web（業務API）", "evidenceRefs": ["R002", "R015"] },
        { "id": "F10", "name": "業務PostgreSQL（業務・監査）", "evidenceRefs": ["R021", "R022"] },
        { "id": "F11", "name": "かけあい Web（AI要求受付）", "evidenceRefs": ["R038"] },
        { "id": "F12", "name": "PostgreSQL command / job", "evidenceRefs": ["R019", "R038"] },
        { "id": "F13", "name": "AI Worker", "evidenceRefs": ["R018", "R019", "R020"] },
        { "id": "F14", "name": "AI入力最小化", "evidenceRefs": ["R031"] },
        { "id": "F15", "name": "OpenAI API", "evidenceRefs": ["R032", "R033", "R034"] },
        { "id": "F16", "name": "AI Worker（応答検査・反映）", "evidenceRefs": ["R020", "R031", "R032"] },
        { "id": "F17", "name": "PostgreSQL AI結果", "evidenceRefs": ["R020", "R022"] },
        { "id": "F18", "name": "利用者ブラウザ（外部ファイル）", "evidenceRefs": ["R035", "R036"] },
        { "id": "F19", "name": "かけあい Web（URL受付）", "evidenceRefs": ["R035"] },
        { "id": "F20", "name": "PostgreSQL URL記録", "evidenceRefs": ["R035", "R036"] },
        { "id": "F21", "name": "利用者指定の外部ファイル保管先", "evidenceRefs": ["R035", "R036"] }
      ],
      "edges": [
        { "id": "FE01", "from": "F01", "to": "F02", "label": "login／登録／reset入力", "evidenceRefs": ["R039"] },
        { "id": "FE02", "from": "F02", "to": "F03", "label": "service credentials付きHTTPS POST", "evidenceRefs": ["R039", "R040"] },
        { "id": "FE03", "from": "F03", "to": "F04", "label": "credential・OTP・同意のhash", "evidenceRefs": ["R027", "R028", "R029"] },
        { "id": "FE04", "from": "F03", "to": "F05", "label": "OTP・reset通知", "evidenceRefs": ["R030"] },
        { "id": "FE05", "from": "F02", "to": "F06", "label": "app session token hash", "evidenceRefs": ["R016", "R023", "R039"] },
        { "id": "FE06", "from": "F07", "to": "F08", "label": "画面・same-origin API・認証情報", "evidenceRefs": ["R006", "R008", "R015"] },
        { "id": "FE07", "from": "F08", "to": "F09", "label": "Tunnel経由のWeb/API要求", "evidenceRefs": ["R005", "R006"] },
        { "id": "FE08", "from": "F09", "to": "F10", "label": "目標・成果物・相談・監査", "evidenceRefs": ["R002", "R022"] },
        { "id": "FE09", "from": "F11", "to": "F12", "label": "永続command／job投入", "evidenceRefs": ["R038"] },
        { "id": "FE10", "from": "F12", "to": "F13", "label": "release別claim・lease", "evidenceRefs": ["R019"] },
        { "id": "FE11", "from": "F13", "to": "F14", "label": "AI処理に必要な文脈", "evidenceRefs": ["R031"] },
        { "id": "FE12", "from": "F14", "to": "F15", "label": "alias／redaction済み入力・store:false", "evidenceRefs": ["R031", "R032", "R034"] },
        { "id": "FE13", "from": "F15", "to": "F16", "label": "回答・usage・provider ID", "evidenceRefs": ["R020", "R032"] },
        { "id": "FE14", "from": "F16", "to": "F17", "label": "応答検査・業務entity反映", "evidenceRefs": ["R020", "R022", "R031"] },
        { "id": "FE15", "from": "F18", "to": "F19", "label": "HTTPS URL登録", "evidenceRefs": ["R035"] },
        { "id": "FE16", "from": "F19", "to": "F20", "label": "URL・filenameのみ保存", "evidenceRefs": ["R035", "R036"] },
        { "id": "FE17", "from": "F18", "to": "F21", "label": "ファイル本体をbrowser direct HTTPSで取得", "evidenceRefs": ["R035", "R036"] }
      ],
      "caveats": [
        "同じ論理componentをデータ種別ごとの行で繰り返している。物理instance数を表す図ではない。",
        "ブラウザとWeb間の通信は各行ともCloudflare Edge／Tunnelを通るが、重複を避けるためFLOW 2だけに明示した。",
        "業務データとsessionはPostgreSQL、credential・OTP・同意はD1へ分離する。",
        "外部ファイル本体のupload実装はなく、アプリはHTTPS URLとfilenameだけを保存する。"
      ]
    },
    {
      "id": "RV04",
      "diagram": "supplementary/06-database-operation-legacy",
      "name": "2026-09-29時点｜組織全体スナップショット方式",
      "scope": "Git tag v2026.09.29（commit eba90cd721d3905ae2d09ae05d2e8db94606259f）にある業務PostgreSQLの通常read、通常write、AI worker DB処理。認証D1は対象外。",
      "nodes": [
        { "id": "O01", "name": "画面・API要求", "evidenceRefs": ["R053"] },
        { "id": "O02", "name": "PostgreSQL request wrapper", "evidenceRefs": ["R053"] },
        { "id": "O03", "name": "組織revision別snapshot coordinator", "evidenceRefs": ["R053"] },
        { "id": "O04", "name": "PostgreSQLの組織内業務表", "evidenceRefs": ["R053"] },
        { "id": "O05", "name": "全AppDataをdecodeしてメモリ内選択", "evidenceRefs": ["R053"] },
        { "id": "O06", "name": "同じ組織の独立した更新A・B", "evidenceRefs": ["R053"] },
        { "id": "O07", "name": "組織単位advisory transaction lock", "evidenceRefs": ["R053"] },
        { "id": "O08", "name": "全AppData読込・structuredClone", "evidenceRefs": ["R053"] },
        { "id": "O09", "name": "メモリ内domain operation", "evidenceRefs": ["R053"] },
        { "id": "O10", "name": "変更aggregateのUnit of Work書込", "evidenceRefs": ["R053"] },
        { "id": "O11", "name": "組織revision更新・全量再読検証", "evidenceRefs": ["R053"] },
        { "id": "O12", "name": "PostgreSQL durable command / job", "evidenceRefs": ["R019", "R054"] },
        { "id": "O13", "name": "AI Worker claim / lease", "evidenceRefs": ["R019", "R054"] },
        { "id": "O14", "name": "AI文脈を組織全snapshotから解決", "evidenceRefs": ["R054"] },
        { "id": "O15", "name": "OpenAI API", "evidenceRefs": ["R032"] },
        { "id": "O16", "name": "snapshot mutationで結果反映", "evidenceRefs": ["R054"] },
        { "id": "O17", "name": "lock待ち・pool枯渇の障害連鎖", "evidenceRefs": ["R053"] }
      ],
      "edges": [
        { "id": "OE01", "from": "O01", "to": "O02", "label": "request", "evidenceRefs": ["R053"] },
        { "id": "OE02", "from": "O02", "to": "O03", "label": "revision確認・snapshot要求", "evidenceRefs": ["R053"] },
        { "id": "OE03", "from": "O03", "to": "O04", "label": "cache miss時に全対象表をSELECT", "evidenceRefs": ["R053"] },
        { "id": "OE04", "from": "O04", "to": "O05", "label": "組織全体の行をdecode", "evidenceRefs": ["R053"] },
        { "id": "OE05", "from": "O06", "to": "O07", "label": "更新A・Bが同じlockへ", "evidenceRefs": ["R053"] },
        { "id": "OE06", "from": "O07", "to": "O08", "label": "直列化したcritical section", "evidenceRefs": ["R053"] },
        { "id": "OE07", "from": "O08", "to": "O09", "label": "mutable draft", "evidenceRefs": ["R053"] },
        { "id": "OE08", "from": "O09", "to": "O10", "label": "変更箇所を選別", "evidenceRefs": ["R053"] },
        { "id": "OE09", "from": "O10", "to": "O11", "label": "差分書込後に整合確認", "evidenceRefs": ["R053"] },
        { "id": "OE10", "from": "O12", "to": "O13", "label": "永続queueをclaim", "evidenceRefs": ["R019"] },
        { "id": "OE11", "from": "O13", "to": "O14", "label": "実行時文脈をload", "evidenceRefs": ["R054"] },
        { "id": "OE12", "from": "O14", "to": "O15", "label": "最小化後にprovider実行", "evidenceRefs": ["R031", "R032"] },
        { "id": "OE13", "from": "O15", "to": "O16", "label": "結果をmaterialize", "evidenceRefs": ["R054"] }
      ],
      "caveats": [
        "readは組織revision別のimmutable cacheとin-flight coalescingを持つため、全要求が必ず物理的な全表読込になるわけではない。cache missやrevision更新後は全量読込になる。",
        "writeは全表置換ではなく、全量snapshotを比較したうえで変更aggregateをUnit of Workとして書く。ただしlock中の全量読込・clone・全量再検証が残る。",
        "AI command/jobの永続queue、claim、leaseは既に存在した。旧方式との差は、実行文脈の取得と結果反映が組織全snapshotに依存していた点にある。"
      ]
    },
    {
      "id": "RV05",
      "diagram": "supplementary/07-database-operation-current",
      "name": "現在｜対象別クエリ・Entity Transaction方式",
      "scope": "2026-10-01のmain（commit 30b101f70ea31c11706ea148f7272fbc29053a69）にある業務PostgreSQLの主要画面、通常API、AI worker DB処理。認証D1は対象外。",
      "nodes": [
        { "id": "C01", "name": "画面・API要求", "evidenceRefs": ["R055", "R057"] },
        { "id": "C02", "name": "actor解決・live DB認可・runtime fence", "evidenceRefs": ["R057"] },
        { "id": "C03", "name": "route / target別reader", "evidenceRefs": ["R055", "R058"] },
        { "id": "C04", "name": "PostgreSQLの必要行・必要履歴だけ", "evidenceRefs": ["R055", "R058"] },
        { "id": "C05", "name": "小さなDTO / AppData互換projection", "evidenceRefs": ["R055"] },
        { "id": "C06", "name": "異なるentityの更新A・B", "evidenceRefs": ["R054"] },
        { "id": "C07", "name": "entity repository transaction", "evidenceRefs": ["R056", "R058"] },
        { "id": "C08", "name": "対象行の認可・row lock", "evidenceRefs": ["R056", "R058"] },
        { "id": "C09", "name": "revision / lease条件付きCAS", "evidenceRefs": ["R056", "R058"] },
        { "id": "C10", "name": "対象行・履歴・監査・outboxだけ更新", "evidenceRefs": ["R054"] },
        { "id": "C11", "name": "短いcommit・組織revision非更新", "evidenceRefs": ["R054", "R058"] },
        { "id": "C12", "name": "PostgreSQL durable command / job", "evidenceRefs": ["R019", "R059"] },
        { "id": "C13", "name": "AI Worker SKIP LOCKED claim / lease", "evidenceRefs": ["R059"] },
        { "id": "C14", "name": "対象workflow graph・直近履歴", "evidenceRefs": ["R060"] },
        { "id": "C15", "name": "OpenAI API（DB transaction外）", "evidenceRefs": ["R032", "R060"] },
        { "id": "C16", "name": "対象別materialize・job完了", "evidenceRefs": ["R054", "R059"] },
        { "id": "C17", "name": "bounded admission・critical予約枠", "evidenceRefs": ["R061"] }
      ],
      "edges": [
        { "id": "CE01", "from": "C01", "to": "C02", "label": "request identity", "evidenceRefs": ["R057"] },
        { "id": "CE02", "from": "C02", "to": "C03", "label": "org・role・target scope", "evidenceRefs": ["R055", "R057"] },
        { "id": "CE03", "from": "C03", "to": "C04", "label": "複数の限定SQL・cursor / limit", "evidenceRefs": ["R055"] },
        { "id": "CE04", "from": "C04", "to": "C05", "label": "必要分だけdecode", "evidenceRefs": ["R055"] },
        { "id": "CE05", "from": "C06", "to": "C07", "label": "entityごとに独立", "evidenceRefs": ["R054"] },
        { "id": "CE06", "from": "C07", "to": "C08", "label": "transaction内で再認可", "evidenceRefs": ["R056", "R058"] },
        { "id": "CE07", "from": "C08", "to": "C09", "label": "対象競合だけ直列化", "evidenceRefs": ["R056", "R058"] },
        { "id": "CE08", "from": "C09", "to": "C10", "label": "一致時だけwrite", "evidenceRefs": ["R054", "R056"] },
        { "id": "CE09", "from": "C10", "to": "C11", "label": "同一transactionで確定", "evidenceRefs": ["R054"] },
        { "id": "CE10", "from": "C12", "to": "C13", "label": "複数workerでも重複claim回避", "evidenceRefs": ["R059"] },
        { "id": "CE11", "from": "C13", "to": "C14", "label": "対象IDから必要文脈をload", "evidenceRefs": ["R060"] },
        { "id": "CE12", "from": "C14", "to": "C15", "label": "接続を保持せずprovider実行", "evidenceRefs": ["R060"] },
        { "id": "CE13", "from": "C15", "to": "C16", "label": "leaseを検証して対象別反映", "evidenceRefs": ["R054", "R059"] }
      ],
      "caveats": [
        "対象別readは1 SQLを意味しない。認可、対象、依存関係、最近の履歴を、同じ短いtransaction内の複数SQLで組み立てる。",
        "通常production APIの旧snapshot mutationはhandler実行前に拒否する。全量snapshot repository自体はbootstrap、import、保守と非本番fallbackのために残る。",
        "organization-wide lockを全廃したわけではない。AI enqueueのsingle-flight等は対象を狭めたadvisory lockを使い、job claimはSKIP LOCKEDを使う。"
      ]
    }
  ],
  "evidence": [
    { "id": "R001", "path": "okr-cai-saas/src/lib/types.ts", "lines": "3-13, 120-143, 183-196", "type": "implementation", "status": "repository-confirmed", "note": "一般利用者 member/viewer とスタッフ mentor/admin の型。" },
    { "id": "R002", "path": "okr-cai-saas/src/lib/route-helpers.ts", "lines": "67-195", "type": "implementation", "status": "repository-confirmed", "note": "owner/team/組織/提出状態を考慮した読書き認可。" },
    { "id": "R003", "path": "okr-cai-saas/src/lib/team-membership.ts", "lines": "3-21", "type": "implementation", "status": "repository-confirmed", "note": "更新時はviewer grantではなく明示team membershipを要求。" },
    { "id": "R004", "path": "okr-cai-saas/src/lib/route-helpers.ts", "lines": "198-258", "type": "implementation", "status": "repository-confirmed", "note": "スタッフ解決とadmin-only認可。" },
    { "id": "R005", "path": "docs/operations/bluegreen/local-bluegreen-deployment.md", "lines": "3-56", "type": "configuration-document", "status": "repository-confirmed-live-unverified", "note": "既存Tunnel→HAProxy→blue/green Web、PostgreSQL/Worker配置。" },
    { "id": "R006", "path": "okr-cai-saas/deploy/cloudflared-config.example.yml", "lines": "1-15", "type": "configuration", "status": "repository-confirmed-live-unverified", "note": "app/admin双方を同じloopback originへ中継しHostを保持。" },
    { "id": "R007", "path": "okr-cai-saas/.env.local.example", "lines": "49-83", "type": "configuration-example", "status": "repository-confirmed-live-unverified", "note": "public host、Auth Worker、Access境界。" },
    { "id": "R008", "path": "okr-cai-saas/src/proxy.ts", "lines": "68-99, 101-215, 268-312", "type": "implementation", "status": "repository-confirmed", "note": "host分離、admin hostの通常Access認証、内部rewriteでの再検証。追加のsensitive audienceは使用しない。" },
    { "id": "R009", "path": "okr-cai-saas/src/lib/cloudflare-access.ts", "lines": "21-42, 44-90", "type": "implementation", "status": "repository-confirmed", "note": "単一のissuer/audience/JWKSでAccess assertionを検証。" },
    { "id": "R010", "path": "okr-cai-saas/src/lib/verified-staff.ts", "lines": "20-54, 56-88", "type": "implementation", "status": "repository-confirmed", "note": "route側でAccess assertionを独立再検証しスタッフ記録に結合。" },
    { "id": "R011", "path": "deploy/local-bluegreen/local-bluegreen.mjs", "lines": "1257-1284", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "readiness後にcloudflaredがtoken fileで外向きTunnel接続を開始。" },
    { "id": "R012", "path": "deploy/local-bluegreen/local-bluegreen.mjs", "lines": "202-230", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "HAProxy loopback frontendとblue/green Web backends。" },
    { "id": "R013", "path": "config/local-bluegreen.production.example.json", "lines": "1-52", "type": "configuration-example", "status": "repository-confirmed-live-unverified", "note": "production origin :3001、Web :3002/:3003、Worker :3012/:3013、bridge network、drain、key分離。" },
    { "id": "R014", "path": "Dockerfile", "lines": "72-118", "type": "configuration", "status": "repository-confirmed", "note": "Node.js 22 distroless Next.js runner-saas image。" },
    { "id": "R015", "path": "okr-cai-saas/src/proxy.ts", "lines": "385-467, 469-554, 721-737", "type": "implementation", "status": "repository-confirmed", "note": "公開ページ、一般利用者のPostgreSQLセッション、保護ページ/API。" },
    { "id": "R016", "path": "okr-cai-saas/src/lib/db/postgres/session-auth.ts", "lines": "59-149", "type": "implementation", "status": "repository-confirmed", "note": "hash化tokenでsession/user/org/membershipを結合しactive状態を検証。" },
    { "id": "R017", "path": "deploy/local-bluegreen/local-bluegreen.mjs", "lines": "232-294", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "Web/Worker別roleのDocker実行単位、loopback publish、read-only制約。" },
    { "id": "R018", "path": "okr-cai-saas/src/instrumentation.ts", "lines": "9-44", "type": "implementation", "status": "repository-confirmed", "note": "worker roleがdurable feedback/generation/command materializerを起動。" },
    { "id": "R019", "path": "okr-cai-saas/src/lib/ai/generation-job.ts", "lines": "558-725", "type": "implementation", "status": "repository-confirmed", "note": "PostgreSQLへ永続job投入、provider lease取得、claim。" },
    { "id": "R020", "path": "okr-cai-saas/src/lib/ai/feedback-job.ts", "lines": "907-950, 1123-1165", "type": "implementation", "status": "repository-confirmed", "note": "結果を業務データへ反映し、telemetryはhash/count/ID等に限定。" },
    { "id": "R021", "path": "compose.production-db.yaml", "lines": "1-46", "type": "configuration", "status": "repository-confirmed-live-unverified", "note": "PostgreSQL 17、named volume、internal network、rotated json logs。" },
    { "id": "R022", "path": "okr-cai-saas/db/postgres/migrations/0001_initial.sql", "lines": "3-67, 96-159, 375-595", "type": "implementation-schema", "status": "repository-confirmed", "note": "組織/利用者/セッション、成果物、相談、AI run、feedbackの永続表。" },
    { "id": "R023", "path": "okr-cai-saas/db/postgres/migrations/0032_password_auth_sessions.sql", "lines": "20-69", "type": "implementation-schema", "status": "repository-confirmed", "note": "password app sessionsと認証credential floor。秘密はD1だけに置くと明記。" },
    { "id": "R024", "path": "okr-cai-saas/.env.local.example", "lines": "7-38", "type": "configuration-example", "status": "repository-confirmed", "note": "通常production SaaSの業務storeはPostgreSQLのみ。" },
    { "id": "R025", "path": "okr-cai-auth-worker/wrangler.jsonc", "lines": "1-46, 95-157", "type": "configuration", "status": "repository-confirmed-live-unverified", "note": "Worker entry、daily cron、Email binding、D1 binding、production env。実識別値は成果物へ転載しない。" },
    { "id": "R026", "path": "okr-cai-auth-worker/src/index.ts", "lines": "17-58, 96-102", "type": "implementation", "status": "repository-confirmed", "note": "password auth endpoints、JWKS、health、日次cleaner。" },
    { "id": "R027", "path": "okr-cai-auth-worker/src/password.ts", "lines": "62-136, 139-305, 394-468", "type": "implementation", "status": "repository-confirmed", "note": "domain判定、OTP、登録、password hash、login/reset。" },
    { "id": "R028", "path": "okr-cai-auth-worker/migrations/0003_password_credentials.sql", "lines": "1-69", "type": "implementation-schema", "status": "repository-confirmed", "note": "password hash、OTP hash、reset grant hash。" },
    { "id": "R029", "path": "okr-cai-auth-worker/migrations/0004_legal_document_acceptances.sql", "lines": "1-10", "type": "implementation-schema", "status": "repository-confirmed", "note": "規約・プライバシーポリシーの同意版と時刻。" },
    { "id": "R030", "path": "okr-cai-auth-worker/src/password.ts", "lines": "558-584", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "Email bindingによるOTP・reset通知。" },
    { "id": "R031", "path": "okr-cai-saas/src/lib/ai/data-minimization.ts", "lines": "18-115, 117-237", "type": "implementation", "status": "repository-confirmed", "note": "氏名alias化、メール/学生ID/電話/secret除去、応答alias復元とリンク検査。" },
    { "id": "R032", "path": "okr-cai-saas/src/lib/ai/openai-responses.ts", "lines": "399-410, 758-792, 825-853, 1286-1294", "type": "implementation", "status": "repository-confirmed", "note": "最小化後のResponses API送信、store=false、prompt hash。" },
    { "id": "R033", "path": "okr-cai-saas/src/lib/ai/openai-embeddings.ts", "lines": "107-124, 296-324", "type": "implementation", "status": "repository-confirmed", "note": "正規化・重複排除・最小化後のEmbeddings API送信。" },
    { "id": "R034", "path": "okr-cai-saas/src/lib/ai/proposal-research.ts", "lines": "276-309, 312-319", "type": "implementation", "status": "repository-confirmed", "note": "Responses API web_search tool、source metadata、store=false。" },
    { "id": "R035", "path": "okr-cai-saas/db/postgres/migrations/0030_project_task_output_file_url.sql", "lines": "1-13", "type": "implementation-schema", "status": "repository-confirmed", "note": "project taskはHTTPS URLだけを保存。" },
    { "id": "R036", "path": "docs/operations/backup/backup-capacity-estimate_okr-cai-saas_2026-08-27.md", "lines": "55-60", "type": "documentation", "status": "repository-confirmed", "note": "外部ファイル本体をobject storageへ保存しない。" },
    { "id": "R037", "path": "okr-cai-saas/src/proxy.ts", "lines": "625-633", "type": "implementation", "status": "repository-confirmed", "note": "client supplied auth headersを除去。" },
    { "id": "R038", "path": "okr-cai-saas/src/app/api/workflows/[sessionId]/messages/route.ts", "lines": "67-168", "type": "implementation", "status": "repository-confirmed", "note": "productionは相談を永続commandとしてenqueueし202応答。" },
    { "id": "R039", "path": "okr-cai-saas/src/app/api/auth/login/route.ts", "lines": "27-58", "type": "implementation", "status": "repository-confirmed", "note": "ブラウザ→SaaS same-origin login→Auth Worker→local session発行。" },
    { "id": "R040", "path": "okr-cai-saas/src/lib/auth-worker.ts", "lines": "104-192, 238-324, 393-399", "type": "implementation", "status": "repository-confirmed", "note": "SaaSからservice credentials付きHTTPS POST。" },
    { "id": "R041", "path": "docs/operations/bluegreen/local-bluegreen-deployment.md", "lines": "3-38, 40-47", "type": "configuration-document", "status": "repository-confirmed-live-unverified", "note": "固定origin、blue/green Web/Worker、readiness、切替、drain、初回計画停止。" },
    { "id": "R042", "path": "config/local-bluegreen.production.example.json", "lines": "1-52", "type": "configuration-example", "status": "repository-confirmed-live-unverified", "note": "production origin、blue/green Web/Worker ports、network、drain設定。" },
    { "id": "R043", "path": "deploy/local-bluegreen/local-bluegreen.mjs", "lines": "26, 232-294", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "各slotのWeb/Worker 2 role、container identity、release label、Worker drain設定。" },
    { "id": "R044", "path": "deploy/local-bluegreen/local-bluegreen.mjs", "lines": "583-688, 985-1050, 1177-1236", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "candidate Worker/Web起動とreadiness、HAProxy切替、旧slot回収、rollback。" },
    { "id": "R045", "path": "deploy/production/host-runtime.mjs", "lines": "29-45, 65-72, 98-140", "type": "implementation", "status": "repository-confirmed-live-unverified", "note": "combinedの単一production containerをstop/remove/create/startし、readiness後にcloudflaredを起動。" },
    { "id": "R046", "path": "okr-cai-saas/src/lib/runtime-role.ts", "lines": "1-33", "type": "implementation", "status": "repository-confirmed", "note": "role未指定時はcombined。Worker shutdown drainは未指定時false。" },
    { "id": "R047", "path": "okr-cai-saas/src/instrumentation.ts", "lines": "9-44", "type": "implementation", "status": "repository-confirmed", "note": "worker/combined roleの1 process内でfeedback、generation、command materializerの3 processorを起動。" },
    { "id": "R048", "path": "compose.yaml", "lines": "1-121", "type": "configuration", "status": "repository-confirmed-live-unverified", "note": "単一okr-cai-saas service、loopback :3000、PostgreSQL利用、restart=no。" },
    { "id": "R049", "path": "okr-cai-saas/src/lib/db/postgres/runtime-control.ts", "lines": "170-240", "type": "implementation", "status": "repository-confirmed", "note": "release別のbackground job、running attempt、command execution、provider leaseが全て0のときdrained。" },
    { "id": "R050", "path": "okr-cai-saas/src/lib/ai/generation-job.ts", "lines": "540-555, 1979-2011", "type": "implementation", "status": "repository-confirmed", "note": "generation workerはrelease contractを検査し、drain modeでは実行中処理をabortせず完了待ち。" },
    { "id": "R051", "path": "okr-cai-saas/src/lib/ai/feedback-job.ts", "lines": "235-332, 950-971", "type": "implementation", "status": "repository-confirmed", "note": "feedback workerはreleaseVersionでclaimし、drain modeでは実行中処理をabortせず完了待ち。" },
    { "id": "R052", "path": "okr-cai-saas/src/lib/ai/production-command-job.ts", "lines": "557-593, 869-900", "type": "implementation", "status": "repository-confirmed", "note": "command materializerはreleaseVersionでclaimし、停止時は実行中promiseの完了を待つ。" },
    { "id": "R053", "path": "docs/engineering/history/100-concurrent-db-remediation-plan-2026-09-30.md", "lines": "84-128", "type": "historical-investigation", "status": "repository-confirmed-historical", "note": "9月29日方式の組織単位lock、全AppData読込・clone・差分書込と、lock待ちからpool枯渇へ至る障害連鎖。" },
    { "id": "R054", "path": "docs/engineering/history/100-concurrent-db-remediation-plan-2026-09-30.md", "lines": "28-38, 200-239, 241-330, 418-438", "type": "implementation-and-validation-record", "status": "repository-confirmed-staging", "note": "対象別read/write/AI処理、CAS、通常snapshot mutation遮断、admission controlと学生側Staging検証結果。" },
    { "id": "R055", "path": "okr-cai-saas/src/lib/db/postgres/dashboard-reader.ts", "lines": "18-90, 120-170", "type": "implementation", "status": "repository-confirmed", "note": "主要画面を本人・担当team・対象artifact・bounded historyへ限定し、AppData互換projectionへdecode。" },
    { "id": "R056", "path": "okr-cai-saas/src/lib/db/postgres/profile.ts", "lines": "13-62", "type": "implementation", "status": "repository-confirmed", "note": "本人プロフィールをlive認可、対象行lock、revision CASでread/update。" },
    { "id": "R057", "path": "okr-cai-saas/src/lib/postgres-entity-api.ts", "lines": "13-68", "type": "implementation", "status": "repository-confirmed", "note": "検証済みidentityからactorを解決し、repository側のlive DB認可とadmission/runtime失敗をRetry-After付き503へ分類。" },
    { "id": "R058", "path": "okr-cai-saas/src/lib/db/postgres/workflow-collaboration.ts", "lines": "32-72, 101-177, 188-228", "type": "implementation", "status": "repository-confirmed", "note": "共同編集をsession/artifact/lease対象行へ限定し、row lockと条件付きUPDATEでCAS。snapshot load・organization revision writeは行わない。" },
    { "id": "R059", "path": "okr-cai-saas/src/lib/db/postgres/ai-generation-jobs.ts", "lines": "187-288, 364-430", "type": "implementation", "status": "repository-confirmed", "note": "AI jobを永続enqueueし、release条件とFOR UPDATE SKIP LOCKEDでclaim、leaseを付与。" },
    { "id": "R060", "path": "okr-cai-saas/src/lib/db/postgres/ai-workflow.ts", "lines": "16-137", "type": "implementation", "status": "repository-confirmed", "note": "AI provider入力を1 workflowとsource graph、直近messageへ限定し、provider I/Oをtransaction外で実行。" },
    { "id": "R061", "path": "okr-cai-saas/src/lib/db/postgres/pool-admission.ts", "lines": "19-51, 57-143, 166-184", "type": "implementation", "status": "repository-confirmed", "note": "checkout前のbounded queue、期限、normal/critical予約枠、admission snapshot。" },
    { "id": "R062", "path": "okr-cai-saas/src/lib/postgres-request-store.ts", "lines": "174-217", "type": "implementation", "status": "repository-confirmed", "note": "通常production HTTPのsnapshot mutationを遮断し、全量writerを保守/import・非本番fallbackへ限定。" }
  ],
  "knownContradictions": [
    {
      "id": "C01",
      "statement": "プライバシーポリシーは相談内容・成果物の通信がCloudflareを経由しないとする。",
      "documentationEvidence": "docs/legal/terms/02_かけあい_プライバシーポリシー_v1.6.md:103-113",
      "implementationEvidence": "okr-cai-saas/deploy/cloudflared-config.example.yml:6-15; docs/operations/bluegreen/local-bluegreen-deployment.md:3-21",
      "diagramTreatment": "実装・設定に従い通常Web/APIもCloudflare Edge/Tunnel経由として描画。法務文書の要修正候補。"
    },
    {
      "id": "C02",
      "statement": "バックアップ方針は3か月保持だが、production入力例は30日で、定常backupジョブの実装は見つからない。",
      "documentationEvidence": "docs/legal/terms/02_かけあい_プライバシーポリシー_v1.6.md:147-157",
      "implementationEvidence": "config/pc-deploy.inputs.example.env:62-73",
      "diagramTreatment": "PostgreSQLのbackupを確定ノードにせず、表で未実装・未稼働確認として扱う。"
    },
    {
      "id": "C03",
      "statement": "単一Next.js runtimeのComposeと、新しいblue/green Web/Worker分離構成が併存する。",
      "documentationEvidence": "compose.yaml:1-121",
      "implementationEvidence": "docs/operations/bluegreen/local-bluegreen-deployment.md:3-56; deploy/local-bluegreen/local-bluegreen.mjs:202-294",
      "diagramTreatment": "最新のproduction用blue/green構成を主図に採用し、単一runtimeは代替/旧経路として環境・運用表へ分離。実配備方式は未確認。"
    }
  ]
}
