@laitszkin/apollo-toolkit 3.10.0 → 3.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/generate-spec/SKILL.md +17 -15
- package/generate-spec/agents/openai.yaml +1 -1
- package/generate-spec/references/TEMPLATE_SPEC.md +103 -84
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/init-project-html/SKILL.md +117 -125
- package/init-project-html/agents/openai.yaml +18 -9
- package/init-project-html/lib/atlas/assets/architecture.css +161 -0
- package/init-project-html/lib/atlas/assets/viewer.client.js +136 -0
- package/init-project-html/lib/atlas/cli.js +1023 -0
- package/init-project-html/lib/atlas/layout.js +330 -0
- package/init-project-html/lib/atlas/render.js +583 -0
- package/init-project-html/lib/atlas/schema.js +347 -0
- package/init-project-html/lib/atlas/state.js +402 -0
- package/init-project-html/references/TEMPLATE_SPEC.md +140 -83
- package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +160 -1058
- package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +136 -0
- package/init-project-html/sample-demo/resources/project-architecture/atlas/atlas.index.yaml +34 -0
- package/init-project-html/sample-demo/resources/project-architecture/atlas/features/get-invite-codes.yaml +172 -0
- package/init-project-html/sample-demo/resources/project-architecture/atlas/features/invite-code-registration.yaml +160 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/index.html +67 -52
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +64 -163
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +102 -196
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +82 -163
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +88 -150
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +83 -138
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/index.html +61 -51
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +84 -159
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +81 -143
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +98 -188
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +83 -138
- package/init-project-html/sample-demo/resources/project-architecture/index.html +256 -335
- package/init-project-html/scripts/architecture.js +65 -247
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
- package/package.json +6 -2
- package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
- package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
- package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
- package/spec-to-project-html/SKILL.md +74 -67
- package/spec-to-project-html/agents/openai.yaml +14 -8
- package/spec-to-project-html/references/TEMPLATE_SPEC.md +98 -83
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
|
@@ -1,161 +1,86 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
</
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
<tr>
|
|
87
|
-
<td class="sub-vars__name">inviteID</td>
|
|
88
|
-
<td class="sub-vars__type">UUID</td>
|
|
89
|
-
<td><span class="sub-vars__scope sub-vars__scope--tx">tx</span></td>
|
|
90
|
-
<td>從 SELECT 取得後跨多個寫入;把「核銷哪一張邀請」與「新 user 屬於哪張邀請」綁定,作為日後審計鏈。</td>
|
|
91
|
-
</tr>
|
|
92
|
-
<tr>
|
|
93
|
-
<td class="sub-vars__name">userID</td>
|
|
94
|
-
<td class="sub-vars__type">UUID</td>
|
|
95
|
-
<td><span class="sub-vars__scope sub-vars__scope--tx">tx</span></td>
|
|
96
|
-
<td><code>InsertUser RETURNING id</code> 的結果;同一 <code>tx</code> 內回填到 <code>consumed_by</code>,完成「誰用了邀請」的紀錄。</td>
|
|
97
|
-
</tr>
|
|
98
|
-
<tr>
|
|
99
|
-
<td class="sub-vars__name">now</td>
|
|
100
|
-
<td class="sub-vars__type">timestamp</td>
|
|
101
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
102
|
-
<td>核銷時的官方時間;由應用層提供以避免應用與 DB 時鐘漂移影響審計順序。</td>
|
|
103
|
-
</tr>
|
|
104
|
-
<tr>
|
|
105
|
-
<td class="sub-vars__name">RowsAffected</td>
|
|
106
|
-
<td class="sub-vars__type">int</td>
|
|
107
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
108
|
-
<td><code>MarkInviteConsumed</code> 條件更新結果;<code>0</code> 表示已被搶先核銷,本次必須回滾,否則會發生雙倍消費。</td>
|
|
109
|
-
</tr>
|
|
110
|
-
<tr>
|
|
111
|
-
<td class="sub-vars__name">consumed_at</td>
|
|
112
|
-
<td class="sub-vars__type">timestamp NULL</td>
|
|
113
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
114
|
-
<td><code>invite_codes</code> 列上欄位;非空代表「這張邀請已被消費」,與 <code>WHERE consumed_at IS NULL</code> 一起防雙重核銷。</td>
|
|
115
|
-
</tr>
|
|
116
|
-
<tr>
|
|
117
|
-
<td class="sub-vars__name">consumed_by</td>
|
|
118
|
-
<td class="sub-vars__type">FK → users.id</td>
|
|
119
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
120
|
-
<td><code>invite_codes</code> 列上欄位;紀錄是哪個 user 用掉這張邀請,是「邀請碼註冊」這條業務路徑留下的最終痕跡。</td>
|
|
121
|
-
</tr>
|
|
122
|
-
<tr>
|
|
123
|
-
<td class="sub-vars__name">users.email</td>
|
|
124
|
-
<td class="sub-vars__type">text UNIQUE</td>
|
|
125
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
126
|
-
<td>使用者唯一鍵;UNIQUE 違例代表「相同信箱已註冊」,業務上以 409 回應,呼叫端不應靜默忽略。</td>
|
|
127
|
-
</tr>
|
|
128
|
-
</tbody>
|
|
129
|
-
</table>
|
|
130
|
-
</section>
|
|
131
|
-
|
|
132
|
-
<section class="sub-dataflow">
|
|
133
|
-
<h2>內部資料流(單一交易視角)</h2>
|
|
134
|
-
<ol>
|
|
135
|
-
<li>呼叫端開 <code>tx</code> → 本子模組以該 <code>tx</code> 執行 SQL;交易控制不在本子模組內。</li>
|
|
136
|
-
<li><code>GetInviteForUpdate</code> 取得 <code>InviteRow</code> 並把 <strong>列鎖</strong> 綁在 <code>tx</code> 上。</li>
|
|
137
|
-
<li><code>InsertUser</code> 取得 <code>UserID</code>,作為下一步 <code>consumed_by</code> 的 FK 值。</li>
|
|
138
|
-
<li><code>MarkInviteConsumed</code> 以 <code>WHERE consumed_at IS NULL</code> 防雙重核銷。</li>
|
|
139
|
-
<li>所有寫入皆在 <code>tx</code> 內;commit/rollback 由呼叫端決定,本子模組對外只報告每個 SQL 的結果。</li>
|
|
140
|
-
</ol>
|
|
141
|
-
</section>
|
|
142
|
-
|
|
143
|
-
<section class="sub-errors">
|
|
144
|
-
<h2>本子模組會回傳的錯誤</h2>
|
|
145
|
-
<table>
|
|
146
|
-
<thead><tr><th>錯誤</th><th>觸發 SQL</th><th>含義</th></tr></thead>
|
|
147
|
-
<tbody>
|
|
148
|
-
<tr><td><code>NotFound</code></td><td><code>GetInviteForUpdate</code></td><td>無該邀請碼列。</td></tr>
|
|
149
|
-
<tr><td><code>UniqueViolation</code></td><td><code>InsertUser</code></td><td>email 重複。</td></tr>
|
|
150
|
-
<tr><td><code>LockWaitTimeout</code></td><td><code>GetInviteForUpdate</code></td><td>其他並發交易長時間持有鎖。</td></tr>
|
|
151
|
-
<tr><td><code>ConnTransient</code></td><td>任意</td><td>網路/restart;交易不會 partial。</td></tr>
|
|
152
|
-
</tbody>
|
|
153
|
-
</table>
|
|
154
|
-
</section>
|
|
155
|
-
|
|
156
|
-
<footer class="atlas-meta" style="margin-top: 2rem">
|
|
157
|
-
<p><a href="../../index.html">← 宏觀架構</a> · <a href="./index.html">← 功能總覽</a></p>
|
|
158
|
-
</footer>
|
|
159
|
-
</main>
|
|
160
|
-
</body>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Invite-code registration · postgresql</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<link rel="stylesheet" href="../../assets/architecture.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<header class="submodule-header">
|
|
11
|
+
<nav class="submodule-breadcrumb"><a href="../../index.html">← Atlas</a> · <a href="index.html">← Invite-code registration</a></nav>
|
|
12
|
+
<h1>postgresql <small class="submodule-kind submodule-kind--db">DB</small></h1>
|
|
13
|
+
<p class="submodule-role">Stores `users` rows and applies invite-code state transitions inside the registration tx.</p>
|
|
14
|
+
</header>
|
|
15
|
+
<main class="submodule-main">
|
|
16
|
+
<section class="sub-io" aria-label="Function I/O">
|
|
17
|
+
<h2>Function I/O</h2>
|
|
18
|
+
<table class="sub-table">
|
|
19
|
+
<thead><tr><th scope="col">Name</th><th scope="col">In</th><th scope="col">Out</th><th scope="col">Side</th><th scope="col">Purpose</th></tr></thead>
|
|
20
|
+
<tbody>
|
|
21
|
+
<tr><td>SELECT_invite_for_update</td><td>code</td><td>InviteCodeRow | nil</td><td>lock</td><td>Locks the invite row for the duration of the transaction.</td></tr>
|
|
22
|
+
<tr><td>INSERT_users</td><td>userRow</td><td>userId</td><td>write</td><td>Persists the new account.</td></tr>
|
|
23
|
+
<tr><td>UPDATE_invite_consumed</td><td>code, now</td><td>rows_affected</td><td>write</td><td>Marks the invite as consumed.</td></tr>
|
|
24
|
+
</tbody>
|
|
25
|
+
</table>
|
|
26
|
+
</section>
|
|
27
|
+
<section class="sub-vars" aria-label="Variables">
|
|
28
|
+
<h2>Variables</h2>
|
|
29
|
+
<table class="sub-table">
|
|
30
|
+
<thead><tr><th scope="col">Name</th><th scope="col">Type</th><th scope="col">Scope</th><th scope="col">Purpose</th></tr></thead>
|
|
31
|
+
<tbody>
|
|
32
|
+
<tr><td>users.email</td><td>text</td><td>persist</td><td>Unique account identity.</td></tr>
|
|
33
|
+
<tr><td>invite_codes.consumed_at</td><td>timestamptz</td><td>persist</td><td>Timestamp set the moment the invite row is consumed.</td></tr>
|
|
34
|
+
</tbody>
|
|
35
|
+
</table>
|
|
36
|
+
</section>
|
|
37
|
+
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
38
|
+
<h2>Internal data flow</h2>
|
|
39
|
+
<div class="sub-dataflow__canvas" data-pan-zoom-container>
|
|
40
|
+
<div class="sub-dataflow__toolbar" role="toolbar" aria-label="Diagram controls">
|
|
41
|
+
<button type="button" data-pan-zoom="zoom-in" aria-label="Zoom in">+</button>
|
|
42
|
+
<button type="button" data-pan-zoom="zoom-out" aria-label="Zoom out">−</button>
|
|
43
|
+
<button type="button" data-pan-zoom="fit" aria-label="Reset view">Fit</button>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="sub-dataflow__viewport" data-pan-zoom-viewport>
|
|
46
|
+
<svg class="sub-dataflow__svg" data-atlas-svg="sub-dataflow" viewBox="0 0 628 368" role="img" aria-label="Internal dataflow">
|
|
47
|
+
<defs>
|
|
48
|
+
<marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="9" markerHeight="9" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker>
|
|
49
|
+
</defs>
|
|
50
|
+
<g class="sub-dataflow__step">
|
|
51
|
+
<circle class="sub-dataflow__badge" cx="42" cy="68" r="18" />
|
|
52
|
+
<text class="sub-dataflow__badge-text" x="42" y="73" text-anchor="middle">1</text>
|
|
53
|
+
<rect class="sub-dataflow__box" x="80" y="32" width="520" height="72" rx="14" ry="14" />
|
|
54
|
+
<text class="sub-dataflow__text" x="340" y="74" text-anchor="middle">Apply row lock on invite_codes.</text>
|
|
55
|
+
</g>
|
|
56
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
57
|
+
<g class="sub-dataflow__step">
|
|
58
|
+
<circle class="sub-dataflow__badge" cx="42" cy="184" r="18" />
|
|
59
|
+
<text class="sub-dataflow__badge-text" x="42" y="189" text-anchor="middle">2</text>
|
|
60
|
+
<rect class="sub-dataflow__box" x="80" y="148" width="520" height="72" rx="14" ry="14" />
|
|
61
|
+
<text class="sub-dataflow__text" x="340" y="190" text-anchor="middle">Validate uniqueness of users.email.</text>
|
|
62
|
+
</g>
|
|
63
|
+
<line class="sub-dataflow__arrow" x1="340" y1="226" x2="340" y2="256" marker-end="url(#sub-arrow)" />
|
|
64
|
+
<g class="sub-dataflow__step">
|
|
65
|
+
<circle class="sub-dataflow__badge" cx="42" cy="300" r="18" />
|
|
66
|
+
<text class="sub-dataflow__badge-text" x="42" y="305" text-anchor="middle">3</text>
|
|
67
|
+
<rect class="sub-dataflow__box" x="80" y="264" width="520" height="72" rx="14" ry="14" />
|
|
68
|
+
<text class="sub-dataflow__text" x="340" y="306" text-anchor="middle">Write users row and update invite_codes.consumed_at.</text>
|
|
69
|
+
</g>
|
|
70
|
+
</svg>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</section>
|
|
74
|
+
<section class="sub-errors" aria-label="Errors">
|
|
75
|
+
<h2>Errors</h2>
|
|
76
|
+
<table class="sub-table">
|
|
77
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
78
|
+
<tbody>
|
|
79
|
+
<tr><td>ErrUniqueEmail</td><td>users.email unique constraint violated.</td><td>Bubble up so service can return ErrEmailTaken.</td></tr>
|
|
80
|
+
</tbody>
|
|
81
|
+
</table>
|
|
82
|
+
</section>
|
|
83
|
+
</main>
|
|
84
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
85
|
+
</body>
|
|
161
86
|
</html>
|
|
@@ -1,145 +1,83 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
</
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
<
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
</tr>
|
|
84
|
-
<tr>
|
|
85
|
-
<td class="sub-vars__name">RegisterInput</td>
|
|
86
|
-
<td class="sub-vars__type">{Email, Password, InviteCode}</td>
|
|
87
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
88
|
-
<td>HTTP body 解碼後的網域層承載;schema 校驗通過代表「結構面可進入業務」,避免錯誤輸入觸發無謂的 DB 開銷。</td>
|
|
89
|
-
</tr>
|
|
90
|
-
<tr>
|
|
91
|
-
<td class="sub-vars__name">httpStatus</td>
|
|
92
|
-
<td class="sub-vars__type">int</td>
|
|
93
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
94
|
-
<td><code>mapDomainError</code> 的輸出之一;業務面決定協議語意(409 與 503 不可混用,前者要使用者改、後者要使用者稍後再試)。</td>
|
|
95
|
-
</tr>
|
|
96
|
-
<tr>
|
|
97
|
-
<td class="sub-vars__name">ErrorBody</td>
|
|
98
|
-
<td class="sub-vars__type">{code, message}</td>
|
|
99
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
100
|
-
<td>結構化錯誤體;<code>code</code> 給 UI 對映本地化文字,<code>message</code> 僅供開發者排錯。</td>
|
|
101
|
-
</tr>
|
|
102
|
-
<tr>
|
|
103
|
-
<td class="sub-vars__name">http.ResponseWriter</td>
|
|
104
|
-
<td class="sub-vars__type">writer</td>
|
|
105
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
106
|
-
<td>對外副作用通道;本子模組保證一次回應只寫一次,避免重複寫入造成協議違例與使用者看到的不一致結果。</td>
|
|
107
|
-
</tr>
|
|
108
|
-
</tbody>
|
|
109
|
-
</table>
|
|
110
|
-
</section>
|
|
111
|
-
|
|
112
|
-
<section class="sub-dataflow">
|
|
113
|
-
<h2>內部資料流</h2>
|
|
114
|
-
<ol>
|
|
115
|
-
<li><code>http.Request.Body</code> → <code>decodeRegisterInput</code> → <code>RegisterInput</code>(失敗 → <code>ErrBadRequest</code>)。</li>
|
|
116
|
-
<li><code>RegisterInput</code> 作為傳入網域層的參數;本子模組<strong>不</strong>持有交易、密碼明文也只在這一函式內存在。</li>
|
|
117
|
-
<li>從網域層拿到 <code>NewUserID | error</code>:
|
|
118
|
-
<ul>
|
|
119
|
-
<li><code>NewUserID</code> → <code>writeSuccess</code>。</li>
|
|
120
|
-
<li><code>error</code> → <code>mapDomainError</code> → 對應 HTTP 狀態 + JSON。</li>
|
|
121
|
-
</ul>
|
|
122
|
-
</li>
|
|
123
|
-
<li>處理結束 / response 完成寫入後生命週期終止。</li>
|
|
124
|
-
</ol>
|
|
125
|
-
</section>
|
|
126
|
-
|
|
127
|
-
<section class="sub-errors">
|
|
128
|
-
<h2>本子模組會回應/轉化的錯誤</h2>
|
|
129
|
-
<table>
|
|
130
|
-
<thead><tr><th>條件</th><th>HTTP</th></tr></thead>
|
|
131
|
-
<tbody>
|
|
132
|
-
<tr><td>schema 失敗</td><td><code>400 BAD_REQUEST</code></td></tr>
|
|
133
|
-
<tr><td>網域回 <code>ErrInviteInvalid</code></td><td><code>409 INVITE_INVALID</code></td></tr>
|
|
134
|
-
<tr><td>網域回 <code>ErrTransient</code></td><td><code>503 SERVICE_UNAVAILABLE</code></td></tr>
|
|
135
|
-
<tr><td>panic 或未分類</td><td><code>500 INTERNAL</code></td></tr>
|
|
136
|
-
</tbody>
|
|
137
|
-
</table>
|
|
138
|
-
</section>
|
|
139
|
-
|
|
140
|
-
<footer class="atlas-meta" style="margin-top: 2rem">
|
|
141
|
-
<p><a href="../../index.html">← 宏觀架構</a> · <a href="./index.html">← 功能總覽</a></p>
|
|
142
|
-
</footer>
|
|
143
|
-
</main>
|
|
144
|
-
</body>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Invite-code registration · public-api</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<link rel="stylesheet" href="../../assets/architecture.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<header class="submodule-header">
|
|
11
|
+
<nav class="submodule-breadcrumb"><a href="../../index.html">← Atlas</a> · <a href="index.html">← Invite-code registration</a></nav>
|
|
12
|
+
<h1>public-api <small class="submodule-kind submodule-kind--api">API</small></h1>
|
|
13
|
+
<p class="submodule-role">HTTP boundary for `/api/register` POST requests.</p>
|
|
14
|
+
</header>
|
|
15
|
+
<main class="submodule-main">
|
|
16
|
+
<section class="sub-io" aria-label="Function I/O">
|
|
17
|
+
<h2>Function I/O</h2>
|
|
18
|
+
<table class="sub-table">
|
|
19
|
+
<thead><tr><th scope="col">Name</th><th scope="col">In</th><th scope="col">Out</th><th scope="col">Side</th><th scope="col">Purpose</th></tr></thead>
|
|
20
|
+
<tbody>
|
|
21
|
+
<tr><td>postRegister</td><td>HttpRequest</td><td>HttpResponse</td><td>network</td><td>Parses payload and delegates to registration-service.</td></tr>
|
|
22
|
+
</tbody>
|
|
23
|
+
</table>
|
|
24
|
+
</section>
|
|
25
|
+
<section class="sub-vars" aria-label="Variables">
|
|
26
|
+
<h2>Variables</h2>
|
|
27
|
+
<table class="sub-table">
|
|
28
|
+
<thead><tr><th scope="col">Name</th><th scope="col">Type</th><th scope="col">Scope</th><th scope="col">Purpose</th></tr></thead>
|
|
29
|
+
<tbody>
|
|
30
|
+
<tr><td>payload</td><td>RegisterDTO</td><td>call</td><td>Inbound registration intent.</td></tr>
|
|
31
|
+
</tbody>
|
|
32
|
+
</table>
|
|
33
|
+
</section>
|
|
34
|
+
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
35
|
+
<h2>Internal data flow</h2>
|
|
36
|
+
<div class="sub-dataflow__canvas" data-pan-zoom-container>
|
|
37
|
+
<div class="sub-dataflow__toolbar" role="toolbar" aria-label="Diagram controls">
|
|
38
|
+
<button type="button" data-pan-zoom="zoom-in" aria-label="Zoom in">+</button>
|
|
39
|
+
<button type="button" data-pan-zoom="zoom-out" aria-label="Zoom out">−</button>
|
|
40
|
+
<button type="button" data-pan-zoom="fit" aria-label="Reset view">Fit</button>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="sub-dataflow__viewport" data-pan-zoom-viewport>
|
|
43
|
+
<svg class="sub-dataflow__svg" data-atlas-svg="sub-dataflow" viewBox="0 0 628 368" role="img" aria-label="Internal dataflow">
|
|
44
|
+
<defs>
|
|
45
|
+
<marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="9" markerHeight="9" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker>
|
|
46
|
+
</defs>
|
|
47
|
+
<g class="sub-dataflow__step">
|
|
48
|
+
<circle class="sub-dataflow__badge" cx="42" cy="68" r="18" />
|
|
49
|
+
<text class="sub-dataflow__badge-text" x="42" y="73" text-anchor="middle">1</text>
|
|
50
|
+
<rect class="sub-dataflow__box" x="80" y="32" width="520" height="72" rx="14" ry="14" />
|
|
51
|
+
<text class="sub-dataflow__text" x="340" y="74" text-anchor="middle">Decode JSON body.</text>
|
|
52
|
+
</g>
|
|
53
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
54
|
+
<g class="sub-dataflow__step">
|
|
55
|
+
<circle class="sub-dataflow__badge" cx="42" cy="184" r="18" />
|
|
56
|
+
<text class="sub-dataflow__badge-text" x="42" y="189" text-anchor="middle">2</text>
|
|
57
|
+
<rect class="sub-dataflow__box" x="80" y="148" width="520" height="72" rx="14" ry="14" />
|
|
58
|
+
<text class="sub-dataflow__text" x="340" y="190" text-anchor="middle">Call registration-service.RegisterWithInvite.</text>
|
|
59
|
+
</g>
|
|
60
|
+
<line class="sub-dataflow__arrow" x1="340" y1="226" x2="340" y2="256" marker-end="url(#sub-arrow)" />
|
|
61
|
+
<g class="sub-dataflow__step">
|
|
62
|
+
<circle class="sub-dataflow__badge" cx="42" cy="300" r="18" />
|
|
63
|
+
<text class="sub-dataflow__badge-text" x="42" y="305" text-anchor="middle">3</text>
|
|
64
|
+
<rect class="sub-dataflow__box" x="80" y="264" width="520" height="72" rx="14" ry="14" />
|
|
65
|
+
<text class="sub-dataflow__text" x="340" y="306" text-anchor="middle">Serialize success or 422 / 5xx error.</text>
|
|
66
|
+
</g>
|
|
67
|
+
</svg>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</section>
|
|
71
|
+
<section class="sub-errors" aria-label="Errors">
|
|
72
|
+
<h2>Errors</h2>
|
|
73
|
+
<table class="sub-table">
|
|
74
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
75
|
+
<tbody>
|
|
76
|
+
<tr><td>ErrMalformedPayload</td><td>JSON parse fails.</td><td>400 response with `payload` reason.</td></tr>
|
|
77
|
+
</tbody>
|
|
78
|
+
</table>
|
|
79
|
+
</section>
|
|
80
|
+
</main>
|
|
81
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
82
|
+
</body>
|
|
145
83
|
</html>
|