# StartView 3-App Cross-Role Consistency — Design Spec

**Date:** 2026-08-11
**Branch:** `combine-datas`
**Status:** Approved design, ready for implementation planning

## 1. Context & Goal

StartView is a Korean influencer-marketing platform prototyped as **three separate front-end apps** in this repo, each showing the same world from one seat:

- `creator/` — the creator (influencer) app. **Freshest** product thinking.
- `advertiser/` — the advertiser/brand console. **Second** freshest; owns the cleanest data model (`advertiser/data.js` → `window.SVData`).
- `admin/` — the internal operations console. **Stale in content/flow**; its UI/chrome is current, its data and lifecycle are a snapshot behind.

These are UI/UX prototypes with **no backend**. Today the three apps disagree at nearly every seam: the same entity has different names, different statuses, and disjoint seed data depending on which app you open. A reviewer cannot walk a single case (a proposal, a campaign, a payment) across the three seats because the records don't line up.

**Goal:** make the three prototypes tell **one coherent, walkable story** — a shared vocabulary, aligned status machines, and at least one concrete case that appears *identically* across all three apps — so the whole thing reads as one connected system. No backend; consistency is achieved by convention and shared seed data.

## 2. Scope

**In scope**
- Canonical vocabulary (entity names, product types, money model).
- One proposal/collaboration state machine and one campaign state machine, each rendered from three seats.
- The missing **admin payment-approval gate** made explicit across all three apps.
- Retiring 수요조사 (demand survey) by folding it into the proposal/collaboration model.
- A **golden thread**: a small shared cast + one unified date, woven so a single case is walkable creator → advertiser → admin.
- Bringing admin's data/flow up to date (its UI is preserved).

**Out of scope**
- **공동구매 (group-buy)** and **어필리에이트 (affiliate)** — owned by another teammate, not yet on prod. Exclude entirely; treat as external dependencies.
- A full rebuild of admin's mock data model — we deepen only what the golden thread needs.
- Any real backend, API, or persistence.
- The demand-survey machinery beyond folding it away (`/demand-survey`, `/demand-db` retire; `/demand-payment` is repurposed, see §5).
- `구매형` product type (tied to purchase/group-buy flows that are out of scope).

## 3. Authority Model (how conflicts resolve)

When two apps disagree:

1. **Creator wins on flow and UX.** It is the freshest and defines the intended journey.
2. **Advertiser's `data.js` is the structural template.** It is the cleanest data model (stable IDs, single-source figures, `seed:`/`mine()` conventions) and is where shared entity shapes are anchored.
3. **Admin conforms.** Its chrome/UI stays as-is; its data, statuses, labels, and flow are updated to match creator + advertiser.

## 4. Canonical Dictionary

### 4.1 Entity names

| Concept | Canonical term | Replaces |
|---|---|---|
| Creator/influencer | **크리에이터** | admin's **리뷰어** (menu group 리뷰어 관리 → 크리에이터 관리; `/reviewer` roster becomes the creator roster; `리뷰어 신청 이력`, `PAYOUTS` labels follow) |
| Advertiser | 광고주 | (unchanged) |
| Brand | 브랜드 | (unchanged) |
| Company | 기업 / 회사 | (unchanged) |
| Campaign | 캠페인 | (unchanged) |
| Product | 상품 | (unchanged) |
| Collaboration/proposal | 제안 / 협업 | (unified, see §5.1) |

### 4.2 Product types

Canonical set is **배송형 / 방문형** only.

- Drop admin's third type **구매형** (out of scope with purchase/group-buy).
- Internal keys stay `delivery` / `visit` (advertiser + creator already use these).

### 4.3 Money model (one number, role-specific names)

The same amount is named differently by seat, but it is one figure:

```
advertiser  캐시 (prepaid wallet)
              │  funds
              ▼
           리워드 / 원고료   ← same number, advertiser calls it 리워드, creator calls it 원고료
              │  on collab completion, lands in
              ▼
creator     포인트 (wallet)  ← plus attendance/event 포인트
              │  창작자 requests
              ▼
           정산 (withdraw to bank, 3.3% 원천징수)
```

- Advertiser spends **캐시** to fund a campaign/collab **리워드**.
- The creator earns that as **원고료**, credited to their **포인트** wallet.
- The creator does **정산** (payout) to withdraw 포인트 to a bank account, with 3.3% withholding.
- **Admin approves two gates**: (a) the advertiser's payment before a collab offer is dispatched, and (b) the creator's 정산 before payout.

## 5. Canonical State Machines

### 5.1 Proposal / collaboration — one machine, three views

Today each app has its own proposal vocabulary and, critically, the advertiser model **skips the admin payment-approval step** that the creator app explicitly documents (`creator/main.dc.html:4337–4339`: *"광고주가 최종 제안을 보내고(어드민이 결제를 승인해야 발송된다) 크리에이터가 5일 안에 수락…"*).

The fix: **one canonical state set**, with each seat rendering its own label, and the **admin payment-approval gate promoted to an explicit state** that all three show.

| Canonical state | Creator label | Advertiser label | Admin label / queue |
|---|---|---|---|
| `received` | 채택 대기 (광고주 검토 중) | 검토 대기 | — |
| `awaiting_payment_approval` ⬅ **new gate** | 채택 대기 | 수락 대기 (결제됨) | **결제 승인 대기** (queue) |
| `awaiting_creator` | 응답 대기 (내 차례, 5일) | 수락 대기 | 발송됨 |
| `linked` | 확정됨 | 진행 중 | 협업 진행 |
| `content_review` | 검수중 | 검수 중 | **협업 검수** (queue) |
| `revision` | 수정 요청 | 반려 | 수정요청 |
| `settled` | 정산 완료 | 완료 | 협업 정산 완료 |
| `dropped` | 광고주 미채택 | 미채택 | — |
| `declined` | 협업 거절 / 기한 만료 | 거절 | — |

Notes:
- `direction: inbound | outbound` from the advertiser model is retained (`inbound` = creator proposed from Brand Zone; `outbound` = advertiser reached out first). Outbound skips the `received` queue as today.
- The advertiser's existing state names (`received / awaiting / linked / dropped / declined`, `advertiser/data.js:937–942`) map onto the canonical set; only `awaiting_payment_approval` is genuinely new and sits between "advertiser paid" and "creator sees the offer".
- Creator's existing `P_STATUS` labels (`creator/main.dc.html:4344–4353`) become the Creator column verbatim.
- Admin's `협업 검수` (`/collaboration-inspection`) and `협업 정산` (`/collaboration-settlement`) are the correct homes for `content_review` and `settled`; admin's `/demand-payment` is repurposed as **결제 승인** for `awaiting_payment_approval` (see §5.3).

### 5.2 Campaign — one superset, macro view for creators

| Canonical state | Creator (macro) | Advertiser | Admin |
|---|---|---|---|
| `draft` | — | 임시 저장 | 임시저장 |
| `payment_pending` | — | 결제 대기 | 결제대기 |
| `review_pending` ⬅ admin gate | — | 등록 검수 중 | **등록 대기 / 승인 대기** (queue) |
| `recruiting` | 모집중 | 모집중 | 모집중 |
| `select_required` | 크리에이터 선정 | 선정 필요 | 선정 필요 |
| `ongoing` | 리뷰 등록 기간 / 방문 예약 | 진행 중 | 진행중 |
| `content_review` | 검수중 | 검수 중 | 검수중 |
| `done` | 완료 | 완료 | 완료 |
| `cancelled` | — | 취소 | 취소 |

- Creator sees the 4 macro stages it uses today (`모집중 → 크리에이터 선정 → 리뷰 등록 기간 → 검수중`, `creator/main.dc.html:7127`).
- Advertiser's 5 states (`select_required/review/ongoing/done/draft`) expand to include the front-of-line gate states.
- Admin's ~10 states (`임시저장/등록대기중/승인대기중/모집대기중/모집중/진행대기중/진행중/검수중/완료/취소`) collapse onto this set — its bespoke `대기중` variants either map to a canonical state or become admin-only queue framing, not new entity states. Admin's **two parallel campaign models** (classic 체험단 vs. brand-zone/demand) are unified into this one.

### 5.3 Demand survey (수요조사) — retired

The advertiser prototype already abolished 수요조사 and folded it into 제안 관리 (`advertiser/main.dc.html` legacy redirect `brand/survey → proposals/all`). Creator never had it. Admin is the only app still running it as a first-class flow. Reconciliation:

- `/demand-survey`, `/demand-db` — **removed** from admin (or folded into the collaboration oversight views).
- `/demand-payment` — **repurposed as 결제 승인**, wired to the `awaiting_payment_approval` gate in §5.1.
- Admin keeps `/collaboration-inspection` (협업 검수) and `/collaboration-settlement` (협업 정산) as the homes for content review and settlement.

## 6. The Golden Thread

To make the flow "accurate" and walkable, a single shared cast appears **identically** across all three apps, on **one unified date**.

### 6.1 Unified date

**Canonical "today" = `2026.08.11`** (admin already uses it; creator and advertiser bump forward from 08.03/08.05). All D-days and relative stamps compute from this.

### 6.2 Shared cast (canonical records)

| Entity | Canonical value | Fixes |
|---|---|---|
| Creator 보미 | name `보미`, handle `@bomi.daily`, 인스타 팔로워 **12,000 (1.2만)**, 원고료 300,000 (creator's version wins) | advertiser `bomi` today = `봄이일상 / @bomi.day / 4,730` (`data.js:156`) → updated to match; admin roster gains 보미 with same numbers |
| Brand 글로우드롭 | `글로우드롭` (advertiser account brand, `주식회사 글로우드롭`) | creator's anchor brand `글로우리프` (`creator/main.dc.html:4229`) → renamed to `글로우드롭` |
| The proposal | inbound proposal 보미 → 글로우드롭, 원고료 300,000, sent 2026.08.10, response deadline 2026.08.15 | new/aligned record present in all three |

Other creators/brands/campaigns may remain app-specific demo data; only the thread records must be identical everywhere. Where cheap, align additional overlapping records too.

### 6.3 The walkable scenario

One case, identical names/numbers/dates at every seat:

1. **Creator app** — 보미 (Brand Zone) proposes to 글로우드롭, 원고료 300,000, on 08.10 → `채택 대기`.
2. **Advertiser app** — 글로우드롭 console shows it in 제안 관리 / 검토 대기 (`received`, inbound) → approves + pays 캐시 → `수락 대기 (결제됨)` but gated.
3. **Admin app** — appears in **결제 승인 대기** queue → admin approves payment → offer dispatched.
4. **Creator app** — 보미 sees `응답 대기` (내 차례, D-day 08.15) → accepts → `확정됨`. Advertiser sees `진행 중` (hidden `origin:'proposal'` campaign auto-created, per `advertiser/data.js:325–395`); admin sees 협업 진행.
5. **Creator** submits content → `검수중` everywhere → **admin 협업 검수** approves → `정산` → 보미's 원고료 lands as 포인트 → 보미 does 정산 신청 → **admin approves 정산** → paid.

## 7. Per-App Change Lists

### 7.1 Creator (light — it is the reference)
- Rename anchor brand `글로우리프` → `글로우드롭` (and dependent strings: `BRAND_INFO`, offer titles, point-log/notification copy referencing 글로우리프).
- Adopt unified date `2026.08.11` for the thread records (proposal sent/deadline, notifications).
- No status-machine changes — creator's proposal/campaign labels are the canonical Creator column.

### 7.2 Advertiser (medium — align flow, keep `data.js` structure)
- Update `bomi` pool record (`data.js:156`) to canonical `보미 / @bomi.daily / 12,000`; propagate wherever `bomi`/`봄이일상` appears (applicants, selectedList, shipments — e.g. `data.js:191,228`).
- Add/align the inbound 보미 → 글로우드롭 proposal in `proposals` with the thread's dates.
- Introduce the `awaiting_payment_approval` state between advertiser-pays and creator-sees-offer, so the lifecycle matches the creator app and admin's queue.
- Bump canonical date 08.05 → 08.11 (`data.js` `metricsUpdatedAt`, `createdAt`, sub dates, etc.).
- Optionally fix the cross-role numeric defects in §8 that touch shared records.

### 7.3 Admin (heavy — UI preserved, data/flow updated)
- **리뷰어 → 크리에이터** relabel across menu group, `/reviewer` and related screens.
- Adopt canonical **proposal/collaboration** and **campaign** vocabularies (§5.1, §5.2); collapse the two parallel campaign models into one.
- **Retire 수요조사** (§5.3): remove/fold `/demand-survey`, `/demand-db`; repurpose `/demand-payment` → **결제 승인** wired to the `awaiting_payment_approval` gate.
- Drop **구매형** product type.
- Seed the **shared cast** (§6.2) so admin's 결제 승인 / 협업 검수 / 크리에이터 queues show the *same* 보미 / 글로우드롭 / proposal records the other two apps produce.
- Deepen the placeholder detail model just enough to carry the thread records (real per-record fields + stable IDs for the thread; not a full rebuild). Note: admin detail today fabricates a generic history (`이수현`, hardcoded 타겟 성별/연령) for every record — the thread records must be real, not placeholder.
- Admin's "current admin" identity may stay borrowed from the review roster (no RBAC in scope).

## 8. Cross-Role Data Defects To Fix (subset of GAP §24 that affects the shared world)

Prioritize the ones touching shared/thread records:
- `bomi` identity mismatch across creator/advertiser (name, handle, follower count) — **fixed by §6.2**.
- Brand name collision 글로우리프 vs 글로우드롭 — **fixed by §6.2**.
- Divergent "today" dates producing misaligned D-days — **fixed by §6.1**.
- Admin ↔ advertiser share zero campaign/creator records — **addressed by seeding the shared cast**.
- Other single-app numeric defects (e.g. label-vs-count mismatches listed in `advertiser/GAP-vs-platform.md:482–497`) are secondary; fix opportunistically when editing the same screen.

## 9. Implementation Waves

1. **Dictionary + relabels** — admin 리뷰어→크리에이터, drop 구매형, retire demand-survey screens, apply the canonical term map. Low risk, high legibility win.
2. **Proposal/collaboration lifecycle** — implement the one state machine with per-seat labels and the new `awaiting_payment_approval` admin gate across all three apps.
3. **Golden thread** — align the shared cast (보미, 글로우드롭, the proposal) and unified date; seed the same records into admin's queues so the scenario is walkable end-to-end.
4. **Campaign lifecycle + cleanup** — align the campaign state superset; sweep residual cross-role data defects on screens already being touched.

Each wave is independently reviewable; the prototype stays runnable between waves.

## 10. Resolved Decisions

- Strategy: **spec the whole thing first**, then implement in waves.
- 공동구매 / 어필리에이트: **excluded** (teammate-owned, not on prod).
- 수요조사: **retired**, folded into proposal/collaboration.
- Golden thread: **yes**, anchored on 보미 / 글로우드롭.
- Unified date: **2026.08.11**.
- Canonical brand: **글로우드롭** (creator's 글로우리프 renamed).
- Canonical 보미 identity: **creator's version** (`보미 / @bomi.daily / 12,000`).

## 11. Open Questions (for implementation planning)

- Should the canonical vocabulary/status maps live as a small shared constants file duplicated per app, or as documented conventions applied inline? (Each app has its own bundling; there is no shared module today.)
- How much of admin's placeholder detail model must be deepened beyond the thread records to avoid the "every record shows 이수현" tell — thread-only, or a broader pass?
- Whether to bump *all* dates in creator/advertiser to a 08.11 frame, or only the thread-relevant records (the rest being historical stamps that can stay in the past).
