Skip to content

Commit a0689f5

Browse files
committed
feat(docs): enhance documentation with new authentication and event-storming guides, add mermaid integration for visualizations, and update architecture details
1 parent b373d40 commit a0689f5

12 files changed

Lines changed: 1583 additions & 16 deletions

docs/.vitepress/cache/deps/_metadata.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,49 @@
11
{
2-
"hash": "bbcebb07",
3-
"configHash": "c1bf3f29",
4-
"lockfileHash": "a6ae498c",
5-
"browserHash": "78a35d48",
2+
"hash": "db3a1610",
3+
"configHash": "f4b5b642",
4+
"lockfileHash": "3164415e",
5+
"browserHash": "e30350e1",
66
"optimized": {
77
"vue": {
88
"src": "../../../../node_modules/.pnpm/vue@3.5.31_typescript@5.8.3/node_modules/vue/dist/vue.runtime.esm-bundler.js",
99
"file": "vue.js",
10-
"fileHash": "1a8698c3",
10+
"fileHash": "0d96fa44",
1111
"needsInterop": false
1212
},
1313
"vitepress > @vue/devtools-api": {
1414
"src": "../../../../node_modules/.pnpm/@vue+devtools-api@7.7.9/node_modules/@vue/devtools-api/dist/index.js",
1515
"file": "vitepress___@vue_devtools-api.js",
16-
"fileHash": "a892885c",
16+
"fileHash": "698e342a",
1717
"needsInterop": false
1818
},
1919
"vitepress > @vueuse/core": {
2020
"src": "../../../../node_modules/.pnpm/@vueuse+core@12.8.2_typescript@5.8.3/node_modules/@vueuse/core/index.mjs",
2121
"file": "vitepress___@vueuse_core.js",
22-
"fileHash": "fe228ddd",
22+
"fileHash": "2a59afc7",
2323
"needsInterop": false
2424
},
2525
"vitepress > @vueuse/integrations/useFocusTrap": {
2626
"src": "../../../../node_modules/.pnpm/@vueuse+integrations@12.8.2_focus-trap@7.8.0_typescript@5.8.3/node_modules/@vueuse/integrations/useFocusTrap.mjs",
2727
"file": "vitepress___@vueuse_integrations_useFocusTrap.js",
28-
"fileHash": "ad72cb21",
28+
"fileHash": "e5d9d891",
2929
"needsInterop": false
3030
},
3131
"vitepress > mark.js/src/vanilla.js": {
3232
"src": "../../../../node_modules/.pnpm/mark.js@8.11.1/node_modules/mark.js/src/vanilla.js",
3333
"file": "vitepress___mark__js_src_vanilla__js.js",
34-
"fileHash": "df7242a4",
34+
"fileHash": "d1e4d4ea",
3535
"needsInterop": false
3636
},
3737
"vitepress > minisearch": {
3838
"src": "../../../../node_modules/.pnpm/minisearch@7.2.0/node_modules/minisearch/dist/es/index.js",
3939
"file": "vitepress___minisearch.js",
40-
"fileHash": "f59f5134",
40+
"fileHash": "e2ba2c74",
4141
"needsInterop": false
4242
},
4343
"@theme/index": {
4444
"src": "../../../../node_modules/.pnpm/vitepress@1.6.4_@algolia+client-search@5.50.0_@types+node@25.5.0_@types+react@18.3.18_l_1e318b9ed515b7a0a1a7d0feed54422c/node_modules/vitepress/dist/client/theme-default/index.js",
4545
"file": "@theme_index.js",
46-
"fileHash": "06e65756",
46+
"fileHash": "b3fd745c",
4747
"needsInterop": false
4848
}
4949
},

docs/.vitepress/config.mjs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,43 @@
11
import { defineConfig } from "vitepress";
2+
import { withMermaid } from "vitepress-plugin-mermaid";
23

3-
export default defineConfig({
4+
export default withMermaid(
5+
defineConfig({
46
lang: "ko-KR",
57
title: "Harness Docs",
68
description: "Harness Docs 제품과 아키텍처를 설명하는 내부 문서 사이트",
79
base: "/harness-docs/",
810
cleanUrls: true,
11+
mermaid: {
12+
theme: "default"
13+
},
914
themeConfig: {
1015
nav: [
1116
{ text: "가이드", link: "/guide/getting-started" },
17+
{ text: "인증", link: "/guide/authentication" },
1218
{ text: "아키텍처", link: "/guide/architecture" },
1319
{ text: "도메인", link: "/guide/domain-model" },
20+
{ text: "이벤트스토밍", link: "/guide/event-storming-app-flow" },
21+
{ text: "도메인 코드", link: "/guide/domain-code-mermaid" },
1422
{ text: "레퍼런스", link: "/reference/packages" }
1523
],
1624
sidebar: [
1725
{
1826
text: "가이드",
1927
items: [
2028
{ text: "시작하기", link: "/guide/getting-started" },
29+
{ text: "인증과 로그인", link: "/guide/authentication" },
2130
{ text: "아키텍처", link: "/guide/architecture" },
22-
{ text: "도메인 모델", link: "/guide/domain-model" }
31+
{ text: "도메인 모델", link: "/guide/domain-model" },
32+
{ text: "앱 플로우 이벤트스토밍", link: "/guide/event-storming-app-flow" },
33+
{ text: "도메인 코드 Mermaid", link: "/guide/domain-code-mermaid" }
2334
]
2435
},
2536
{
2637
text: "레퍼런스",
2738
items: [
2839
{ text: "구현 현황", link: "/reference/implementation-status" },
40+
{ text: "Publish Governance RPC", link: "/reference/publish-governance-rpc" },
2941
{ text: "패키지 구성", link: "/reference/packages" },
3042
{ text: "문서 타입", link: "/reference/document-types" },
3143
{ text: "원문 사양", link: "/reference/spec-sources" }
@@ -40,4 +52,5 @@ export default defineConfig({
4052
copyright: "Copyright 2026 Harness Docs"
4153
}
4254
}
43-
});
55+
})
56+
);

docs/guide/architecture.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,6 @@ API가 해야 하는 일:
7070
- stale/current 계산
7171
- unresolved approval snapshot 생성
7272
- publish 가능 여부 판정
73+
- stale publish 시 rationale 요구 여부 판정
7374
- publish record 저장
7475
- GitHub 자동화 실행

docs/guide/authentication.md

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
# 인증과 로그인
2+
3+
## 한 줄 설명
4+
5+
Harness Docs의 로그인은 `GitHub OAuth -> desktop authentication session -> workspace bootstrap` 순서로 이어진다.
6+
7+
## 현재 범위
8+
9+
현재 구현 기준의 인증 범위는 다음과 같다.
10+
11+
- 인증 provider는 `github_oauth` 하나다.
12+
- 인증 세션 상태는 `authenticated` 또는 `signed_out` 두 가지다.
13+
- desktop은 인증 세션을 복원한 뒤 workspace session bootstrap을 시도한다.
14+
- browser/mock 환경에서는 저장소 기반 mock 세션을 사용한다.
15+
- Tauri 환경에서는 네이티브 command를 통해 GitHub 인증 세션을 복원하거나 시작한다.
16+
17+
관련 소스:
18+
19+
- `apps/desktop/src/services/contracts.ts`
20+
- `apps/desktop/src/services/mockHarnessDocsServices.ts`
21+
- `apps/desktop/src/services/tauriHarnessDocsServices.ts`
22+
- `apps/desktop/src/services/rpcWorkspaceSession.ts`
23+
- `apps/api/src/server.ts`
24+
25+
## 핵심 타입
26+
27+
인증 서비스 경계는 `apps/desktop/src/services/contracts.ts`에 있다.
28+
29+
### `AuthenticationProviderDescriptor`
30+
31+
- `id`
32+
- `label`
33+
- `kind`
34+
- `loginCtaLabel`
35+
36+
현재 값:
37+
38+
- `id = github_oauth`
39+
- `kind = oauth`
40+
41+
### `AuthenticationSessionSnapshot`
42+
43+
union:
44+
45+
- `AuthenticatedSessionSnapshot`
46+
- `SignedOutSessionSnapshot`
47+
48+
즉, 데스크톱 앱은 로그인 여부를 복잡한 중간 상태보다 명시적인 두 상태로 본다.
49+
50+
### `AppSessionSnapshot`
51+
52+
union:
53+
54+
- signed out:
55+
`authentication = signed_out`, `workspace = null`
56+
- authenticated:
57+
`authentication = authenticated`, `workspace = WorkspaceSessionSnapshot`
58+
59+
이 구조 때문에 workspace bootstrap은 로그인 이후에만 수행된다.
60+
61+
## 로그인 흐름
62+
63+
```mermaid
64+
sequenceDiagram
65+
actor User as 사용자
66+
participant Desktop as Desktop App
67+
participant Auth as AuthenticationService
68+
participant Workspace as WorkspaceSessionService
69+
participant API as Harness Docs API
70+
71+
User->>Desktop: 앱 진입
72+
Desktop->>Auth: restoreSession()
73+
74+
alt authenticated
75+
Auth-->>Desktop: AuthenticationSessionSnapshot(authenticated)
76+
Desktop->>Workspace: getSnapshot(session)
77+
Workspace->>API: GET /api/session/bootstrap
78+
API-->>Workspace: BootstrapSessionDto
79+
Workspace-->>Desktop: WorkspaceSessionSnapshot
80+
else signed_out
81+
Auth-->>Desktop: AuthenticationSessionSnapshot(signed_out)
82+
Desktop-->>User: 로그인 화면 표시
83+
end
84+
```
85+
86+
## Browser / Mock 환경
87+
88+
출처:
89+
90+
- `apps/desktop/src/services/mockHarnessDocsServices.ts`
91+
92+
browser/mock 환경의 동작은 다음과 같다.
93+
94+
### provider
95+
96+
- provider는 여전히 `github_oauth`로 고정한다.
97+
98+
### 세션 저장
99+
100+
- storage key: `harness-docs/mock-auth-session`
101+
- 값이 `signed_out`이면 로그아웃 상태
102+
- 그 외에는 `authenticated`
103+
104+
### `restoreSession()`
105+
106+
- local storage에서 상태를 읽는다.
107+
- authenticated면 `mockSession.user`를 반환한다.
108+
- signed out이면 `user = null`을 반환한다.
109+
110+
### `startSignIn()`
111+
112+
- provider가 `github_oauth`인지 확인한다.
113+
- storage를 `authenticated`로 쓴다.
114+
- mock user 기반 인증 세션을 반환한다.
115+
116+
### `signOut()`
117+
118+
- storage를 `signed_out`으로 쓴다.
119+
- signed out 세션을 반환한다.
120+
121+
## Tauri / GitHub OAuth 환경
122+
123+
출처:
124+
125+
- `apps/desktop/src/services/tauriHarnessDocsServices.ts`
126+
127+
Tauri 환경에서는 인증 상태를 desktop app이 직접 계산하지 않고 command layer를 통해 받는다.
128+
129+
### 사용 command
130+
131+
- `get_github_authentication_session`
132+
- `start_github_sign_in`
133+
- `sign_out_github`
134+
135+
### `restoreSession()`
136+
137+
- runtime이 `tauri`가 아니면 signed out 반환
138+
- runtime이 `tauri``get_github_authentication_session` command 호출
139+
- 반환된 GitHub identity를 앱의 `SessionUser` shape로 변환
140+
141+
### `startSignIn()`
142+
143+
- provider가 `github_oauth`인지 검증
144+
- tauri runtime이 아니면 에러
145+
- `start_github_sign_in` command 호출
146+
- GitHub identity를 앱 세션으로 변환
147+
148+
### `signOut()`
149+
150+
- tauri runtime이면 `sign_out_github` command 호출
151+
- 결과를 signed out 또는 authenticated 세션으로 다시 매핑
152+
153+
## GitHub identity -> 앱 사용자 매핑
154+
155+
Tauri 서비스는 raw GitHub user를 앱의 `SessionUser`로 바꾼다.
156+
157+
매핑 규칙:
158+
159+
- `handle = @${githubLogin}`
160+
- `avatarInitials = name 또는 login 기반 이니셜`
161+
- `primaryEmail = GitHub email이 없으면 mock fallback`
162+
163+
즉, 인증 provider는 GitHub지만 desktop 내부 세션은 제품 고유 타입으로 유지한다.
164+
165+
## Workspace bootstrap 연결
166+
167+
출처:
168+
169+
- `apps/desktop/src/services/rpcWorkspaceSession.ts`
170+
171+
인증이 성공했다고 바로 workspace 데이터가 생기는 것은 아니다.
172+
173+
다음 단계가 필요하다.
174+
175+
1. `AuthenticationSessionSnapshot.status === authenticated`
176+
2. `WorkspaceSessionService.getSnapshot(session)` 호출
177+
3. RPC client가 `GET /api/session/bootstrap` 호출
178+
4. `BootstrapSessionDto``WorkspaceSessionSnapshot`으로 매핑
179+
180+
fallback 규칙:
181+
182+
- RPC bootstrap 실패 시 mock snapshot 사용
183+
- 단 user는 현재 authentication session의 user로 덮어쓴다
184+
185+
이 구조 덕분에 인증과 workspace bootstrap이 분리된다.
186+
187+
## 인증과 API의 관계
188+
189+
현재 `apps/api/src/server.ts`는 인증 provider를 직접 소유하지 않는다.
190+
191+
현재 API가 하는 일:
192+
193+
- Hono server 시작
194+
- datasource 선택
195+
- publish governance adapter 연결
196+
197+
즉, 현재 로그인 구조는 desktop 주도형이다.
198+
199+
- desktop이 인증 세션을 복원
200+
- desktop이 bootstrap 호출
201+
- API는 bootstrap 응답 제공
202+
203+
장기적으로 서버 측 session 검증이나 token 검증이 붙더라도, 현재 문서 기준 source of truth는 desktop authentication service 쪽에 있다.
204+
205+
## 현재 구현의 한계
206+
207+
### provider 다양성 없음
208+
209+
- 현재는 `github_oauth`만 지원한다.
210+
211+
### token/credential 문서화 부족
212+
213+
- access token 저장 위치
214+
- refresh 규칙
215+
- 만료 처리
216+
- API 요청 인증 헤더 규칙
217+
218+
은 아직 현재 문서 범위에 없다.
219+
220+
### server-side auth 정책 부족
221+
222+
- API가 지금은 bootstrap과 도메인 응답을 중심으로 동작한다.
223+
- 실제 사용자 권한 검증과 GitHub identity 검증은 더 강화되어야 한다.
224+
225+
### 로그인 화면과 route 문서 부족
226+
227+
- 현재 file-based route 리팩터링 중이라 로그인 route 문서는 안정화 이후 보강 필요
228+
229+
## Mermaid 구조도
230+
231+
```mermaid
232+
flowchart TD
233+
A["User opens desktop app"] --> B["AuthenticationService.restoreSession()"]
234+
B --> C{"authenticated?"}
235+
C -->|no| D["SignedOutAppSessionSnapshot"]
236+
C -->|yes| E["WorkspaceSessionService.getSnapshot(session)"]
237+
E --> F["GET /api/session/bootstrap"]
238+
F --> G["WorkspaceSessionSnapshot"]
239+
G --> H["AuthenticatedAppSessionSnapshot"]
240+
```
241+
242+
## 구현 파일별 책임
243+
244+
### `apps/desktop/src/services/contracts.ts`
245+
246+
- authentication 관련 public service contract
247+
- session snapshot union 정의
248+
249+
### `apps/desktop/src/services/mockHarnessDocsServices.ts`
250+
251+
- browser/mock 인증 상태 복원
252+
- mock sign-in/sign-out
253+
- local storage 상태 관리
254+
255+
### `apps/desktop/src/services/tauriHarnessDocsServices.ts`
256+
257+
- Tauri command 기반 GitHub OAuth 연동
258+
- raw GitHub identity -> 앱 세션 매핑
259+
260+
### `apps/desktop/src/services/rpcWorkspaceSession.ts`
261+
262+
- 인증 이후 workspace bootstrap RPC 호출
263+
- bootstrap fallback 관리
264+
265+
### `apps/api/src/server.ts`
266+
267+
- API startup
268+
- 현재 인증 provider 로직은 직접 소유하지 않음
269+
270+
## 지금 추천되는 다음 문서
271+
272+
이 문서 다음으로 분리하면 좋은 주제는 두 가지다.
273+
274+
1. `desktop route auth flow`
275+
2. `server-side auth and authorization policy`

0 commit comments

Comments
 (0)