{
  "schema_version": 1,
  "diagram_type": "architecture",
  "meta": {
    "title": "Pharos P1 — 상품 동기화·주문 수집 아키텍처",
    "quality_profile": "showcase",
    "viewBox": [1380, 780],
    "views": [
      {
        "id": "operator-path",
        "label": "운영자 요청 경로",
        "focus": ["operator", "web", "api", "db", "s3"],
        "note": "콘솔에서 API를 거쳐 tenant 트랜잭션으로 상품·outbox를 기록한다."
      },
      {
        "id": "async-sync",
        "label": "비동기 동기화",
        "focus": ["db", "sqs", "worker", "connectors"],
        "note": "outbox를 SQS로 중계하고 워커가 소비해 커넥터를 호출한다."
      },
      {
        "id": "channels",
        "label": "채널 경계",
        "focus": ["connectors", "naver", "coupang", "cafe24", "simulator"],
        "note": "시뮬레이터 검증은 실계정 증거가 아니다."
      }
    ]
  },
  "components": [
    {
      "id": "operator",
      "type": "external",
      "label": "운영자",
      "sublabel": "데스크톱 브라우저",
      "pos": [30, 260],
      "size": [130, 64]
    },
    {
      "id": "web",
      "type": "frontend",
      "label": "@pharos/web",
      "sublabel": "Next.js 콘솔 · FSD",
      "pos": [225, 260],
      "size": [130, 64],
      "brand": "next-js"
    },
    {
      "id": "api",
      "type": "backend",
      "label": "@pharos/api",
      "sublabel": "NestJS · 도메인 API",
      "pos": [420, 260],
      "size": [130, 64]
    },
    {
      "id": "s3",
      "type": "cloud",
      "label": "S3",
      "sublabel": "엑셀·파일 저장소",
      "pos": [420, 80],
      "size": [130, 64]
    },
    {
      "id": "db",
      "type": "database",
      "label": "PostgreSQL",
      "sublabel": "drizzle · outbox/inbox",
      "pos": [615, 260],
      "size": [130, 64]
    },
    {
      "id": "sqs",
      "type": "messagebus",
      "label": "SQS",
      "sublabel": "작업 큐 · DLQ",
      "pos": [615, 470],
      "size": [130, 64]
    },
    {
      "id": "worker",
      "type": "backend",
      "label": "@pharos/worker",
      "sublabel": "consumer · publisher",
      "pos": [810, 470],
      "size": [130, 64]
    },
    {
      "id": "connectors",
      "type": "backend",
      "label": "채널 커넥터",
      "sublabel": "connectors-core",
      "pos": [1005, 470],
      "size": [130, 64]
    },
    {
      "id": "naver",
      "type": "external",
      "label": "네이버 커머스API",
      "sublabel": "전자서명 · 토큰",
      "pos": [1200, 290],
      "size": [150, 60]
    },
    {
      "id": "coupang",
      "type": "external",
      "label": "쿠팡 WING",
      "sublabel": "CEA HMAC",
      "pos": [1200, 400],
      "size": [150, 60]
    },
    {
      "id": "cafe24",
      "type": "external",
      "label": "카페24 Admin API",
      "sublabel": "OAuth · refresh 회전",
      "pos": [1200, 510],
      "size": [150, 60]
    },
    {
      "id": "simulator",
      "type": "external",
      "label": "로컬 시뮬레이터",
      "sublabel": "local_simulator 전용",
      "pos": [1200, 640],
      "size": [150, 60],
      "tag": "실계정 증거 아님"
    }
  ],
  "boundaries": [
    {
      "kind": "region",
      "label": "Pharos 모노레포 런타임",
      "wraps": ["web", "api", "s3", "db", "sqs", "worker", "connectors"]
    }
  ],
  "connections": [
    {
      "id": "operator-to-web",
      "from": "operator",
      "to": "web",
      "label": "HTTPS",
      "variant": "emphasis"
    },
    {
      "id": "web-to-api",
      "from": "web",
      "to": "api",
      "label": "REST · zod",
      "variant": "emphasis"
    },
    {
      "id": "api-to-s3",
      "from": "api",
      "to": "s3",
      "label": "presigned URL",
      "variant": "dashed"
    },
    {
      "id": "api-to-db",
      "from": "api",
      "to": "db",
      "label": "tenant tx",
      "variant": "emphasis"
    },
    {
      "id": "db-to-sqs",
      "from": "db",
      "to": "sqs",
      "label": "outbox 중계",
      "variant": "emphasis",
      "fromSide": "bottom",
      "toSide": "top",
      "labelAt": [680, 397]
    },
    {
      "id": "sqs-to-worker",
      "from": "sqs",
      "to": "worker",
      "label": "consume",
      "variant": "emphasis"
    },
    {
      "id": "worker-to-db",
      "from": "worker",
      "to": "db",
      "label": "inbox·결과",
      "variant": "dashed",
      "fromSide": "top",
      "toSide": "right"
    },
    {
      "id": "worker-to-connectors",
      "from": "worker",
      "to": "connectors",
      "label": "port 호출",
      "variant": "emphasis"
    },
    {
      "id": "connectors-to-naver",
      "from": "connectors",
      "to": "naver"
    },
    {
      "id": "connectors-to-coupang",
      "from": "connectors",
      "to": "coupang"
    },
    {
      "id": "connectors-to-cafe24",
      "from": "connectors",
      "to": "cafe24"
    },
    {
      "id": "connectors-to-simulator",
      "from": "connectors",
      "to": "simulator",
      "variant": "dashed"
    }
  ],
  "cards": [
    {
      "dot": "cyan",
      "title": "앱 3개",
      "items": [
        "web: Next.js 한국어 콘솔, react-query",
        "api: NestJS + nestjs-zod, OTel 계측",
        "worker: SQS consumer/publisher 컨텍스트"
      ]
    },
    {
      "dot": "emerald",
      "title": "도메인 패키지",
      "items": [
        "catalog: product·sku·bundle·listing",
        "catalog-sync: revision·발행·drift",
        "integration: outbox·cursor·rate budget·DLQ"
      ]
    },
    {
      "dot": "amber",
      "title": "채널 게이트",
      "items": [
        "P1 범위: 상품 CRUD 동기화 + 주문 수집",
        "시뮬레이터 검증 ≠ 승인된 실계정 검증",
        "실채널 변경은 명시적 권한 필요"
      ]
    }
  ]
}
