@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,165 +1,84 @@
|
|
|
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
|
-
<td>SQL 參數;標記新邀請碼擁有者,也是計數視窗鍵;錯誤帶入會把額度算到別人頭上。</td>
|
|
85
|
-
</tr>
|
|
86
|
-
<tr>
|
|
87
|
-
<td class="sub-vars__name">since</td>
|
|
88
|
-
<td class="sub-vars__type">timestamp</td>
|
|
89
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
90
|
-
<td>滑動視窗起點;決定 <code>count(*)</code> 的時段;起點漂移會讓額度執行不準。</td>
|
|
91
|
-
</tr>
|
|
92
|
-
<tr>
|
|
93
|
-
<td class="sub-vars__name">InviteCodeRecord</td>
|
|
94
|
-
<td class="sub-vars__type">{code, owner_user_id, allowed_registration, ...}</td>
|
|
95
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
96
|
-
<td>待插入的邀請碼資料;其欄位直接落在 <code>invite_codes</code> 列上。</td>
|
|
97
|
-
</tr>
|
|
98
|
-
<tr>
|
|
99
|
-
<td class="sub-vars__name">UserStatus</td>
|
|
100
|
-
<td class="sub-vars__type">{status, banned_at}</td>
|
|
101
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
102
|
-
<td><code>GetUserStatus</code> 的回傳;給呼叫端判定是否准予發放。</td>
|
|
103
|
-
</tr>
|
|
104
|
-
<tr>
|
|
105
|
-
<td class="sub-vars__name">invite_codes.code</td>
|
|
106
|
-
<td class="sub-vars__type">text UNIQUE</td>
|
|
107
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
108
|
-
<td>列上欄位;UNIQUE 約束在本子模組是「衝突信號源」,呼叫端據此換碼重試。</td>
|
|
109
|
-
</tr>
|
|
110
|
-
<tr>
|
|
111
|
-
<td class="sub-vars__name">invite_codes.owner_user_id</td>
|
|
112
|
-
<td class="sub-vars__type">FK → users.id</td>
|
|
113
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
114
|
-
<td>列上欄位;建立「誰擁有這張邀請」的關聯;額度查詢與後續審計都依此欄。</td>
|
|
115
|
-
</tr>
|
|
116
|
-
<tr>
|
|
117
|
-
<td class="sub-vars__name">invite_codes.allowed_registration</td>
|
|
118
|
-
<td class="sub-vars__type">boolean</td>
|
|
119
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
120
|
-
<td>列上欄位;發放時寫 <code>true</code>;「邀請碼註冊」功能在判定時讀此欄,<code>false</code> 即拒絕該邀請可用。</td>
|
|
121
|
-
</tr>
|
|
122
|
-
<tr>
|
|
123
|
-
<td class="sub-vars__name">invite_codes.consumed_at</td>
|
|
124
|
-
<td class="sub-vars__type">timestamp NULL</td>
|
|
125
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
126
|
-
<td>列上欄位;本子模組寫入時為 <code>NULL</code>;之後由「邀請碼註冊」標記消費,是橋接兩個功能模組的關鍵欄位。</td>
|
|
127
|
-
</tr>
|
|
128
|
-
<tr>
|
|
129
|
-
<td class="sub-vars__name">invite_codes.created_at</td>
|
|
130
|
-
<td class="sub-vars__type">timestamp</td>
|
|
131
|
-
<td><span class="sub-vars__scope sub-vars__scope--persist">persist</span></td>
|
|
132
|
-
<td>列上欄位;額度的滑動視窗計數憑此欄位,業務上要與 <code>now</code> 同步以免漂移。</td>
|
|
133
|
-
</tr>
|
|
134
|
-
</tbody>
|
|
135
|
-
</table>
|
|
136
|
-
</section>
|
|
137
|
-
|
|
138
|
-
<section class="sub-dataflow">
|
|
139
|
-
<h2>內部資料流(單一交易視角)</h2>
|
|
140
|
-
<ol>
|
|
141
|
-
<li>呼叫端開 <code>tx</code> → 本子模組以該 <code>tx</code> 執行 SQL;交易控制不在本子模組內。</li>
|
|
142
|
-
<li><code>CountInvitesSince</code> 與 <code>GetUserStatus</code> 為純讀;不變動列。</li>
|
|
143
|
-
<li><code>InsertInviteCode</code>:寫入後回傳 <code>InviteID</code> 或 <code>UniqueViolation</code>;<strong>無</strong> partial row。</li>
|
|
144
|
-
<li>所有寫入皆在 <code>tx</code> 內;本子模組對外只報告每個 SQL 結果。</li>
|
|
145
|
-
</ol>
|
|
146
|
-
</section>
|
|
147
|
-
|
|
148
|
-
<section class="sub-errors">
|
|
149
|
-
<h2>本子模組會回傳的錯誤</h2>
|
|
150
|
-
<table>
|
|
151
|
-
<thead><tr><th>錯誤</th><th>觸發 SQL</th></tr></thead>
|
|
152
|
-
<tbody>
|
|
153
|
-
<tr><td><code>UniqueViolation</code></td><td><code>InsertInviteCode</code>(<code>code</code> 已存在)</td></tr>
|
|
154
|
-
<tr><td><code>NotFound</code></td><td><code>GetUserStatus</code></td></tr>
|
|
155
|
-
<tr><td><code>ConnTransient</code></td><td>任意</td></tr>
|
|
156
|
-
</tbody>
|
|
157
|
-
</table>
|
|
158
|
-
</section>
|
|
159
|
-
|
|
160
|
-
<footer class="atlas-meta" style="margin-top: 2rem">
|
|
161
|
-
<p><a href="../../index.html">← 宏觀架構</a> · <a href="./index.html">← 功能總覽</a></p>
|
|
162
|
-
</footer>
|
|
163
|
-
</main>
|
|
164
|
-
</body>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Get invite codes · 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">← Get invite codes</a></nav>
|
|
12
|
+
<h1>postgresql <small class="submodule-kind submodule-kind--db">DB</small></h1>
|
|
13
|
+
<p class="submodule-role">Owns the `invite_codes` table (producer side of the cross-feature data row).</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>INSERT_invite_codes</td><td>row</td><td>rowid</td><td>write</td><td>Persists the issued invite row.</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>invite_codes.code</td><td>text</td><td>persist</td><td>Unique business key consumed by the registration flow.</td></tr>
|
|
31
|
+
<tr><td>invite_codes.consumed_at</td><td>timestamptz</td><td>persist</td><td>Stays null until the registration flow consumes the code.</td></tr>
|
|
32
|
+
</tbody>
|
|
33
|
+
</table>
|
|
34
|
+
</section>
|
|
35
|
+
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
36
|
+
<h2>Internal data flow</h2>
|
|
37
|
+
<div class="sub-dataflow__canvas" data-pan-zoom-container>
|
|
38
|
+
<div class="sub-dataflow__toolbar" role="toolbar" aria-label="Diagram controls">
|
|
39
|
+
<button type="button" data-pan-zoom="zoom-in" aria-label="Zoom in">+</button>
|
|
40
|
+
<button type="button" data-pan-zoom="zoom-out" aria-label="Zoom out">−</button>
|
|
41
|
+
<button type="button" data-pan-zoom="fit" aria-label="Reset view">Fit</button>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="sub-dataflow__viewport" data-pan-zoom-viewport>
|
|
44
|
+
<svg class="sub-dataflow__svg" data-atlas-svg="sub-dataflow" viewBox="0 0 628 368" role="img" aria-label="Internal dataflow">
|
|
45
|
+
<defs>
|
|
46
|
+
<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>
|
|
47
|
+
</defs>
|
|
48
|
+
<g class="sub-dataflow__step">
|
|
49
|
+
<circle class="sub-dataflow__badge" cx="42" cy="68" r="18" />
|
|
50
|
+
<text class="sub-dataflow__badge-text" x="42" y="73" text-anchor="middle">1</text>
|
|
51
|
+
<rect class="sub-dataflow__box" x="80" y="32" width="520" height="72" rx="14" ry="14" />
|
|
52
|
+
<text class="sub-dataflow__text" x="340" y="74" text-anchor="middle">Accept INSERT from invite-issuance-service.</text>
|
|
53
|
+
</g>
|
|
54
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
55
|
+
<g class="sub-dataflow__step">
|
|
56
|
+
<circle class="sub-dataflow__badge" cx="42" cy="184" r="18" />
|
|
57
|
+
<text class="sub-dataflow__badge-text" x="42" y="189" text-anchor="middle">2</text>
|
|
58
|
+
<rect class="sub-dataflow__box" x="80" y="148" width="520" height="72" rx="14" ry="14" />
|
|
59
|
+
<text class="sub-dataflow__text" x="340" y="190" text-anchor="middle">Enforce unique constraint on code.</text>
|
|
60
|
+
</g>
|
|
61
|
+
<line class="sub-dataflow__arrow" x1="340" y1="226" x2="340" y2="256" marker-end="url(#sub-arrow)" />
|
|
62
|
+
<g class="sub-dataflow__step">
|
|
63
|
+
<circle class="sub-dataflow__badge" cx="42" cy="300" r="18" />
|
|
64
|
+
<text class="sub-dataflow__badge-text" x="42" y="305" text-anchor="middle">3</text>
|
|
65
|
+
<rect class="sub-dataflow__box" x="80" y="264" width="520" height="72" rx="14" ry="14" />
|
|
66
|
+
<text class="sub-dataflow__text" x="340" y="306" text-anchor="middle">Return new rowid.</text>
|
|
67
|
+
</g>
|
|
68
|
+
</svg>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
<section class="sub-errors" aria-label="Errors">
|
|
73
|
+
<h2>Errors</h2>
|
|
74
|
+
<table class="sub-table">
|
|
75
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
76
|
+
<tbody>
|
|
77
|
+
<tr><td>ErrUniqueViolation</td><td>Two issuance attempts pick the same code.</td><td>Bubble up so issuance can retry.</td></tr>
|
|
78
|
+
</tbody>
|
|
79
|
+
</table>
|
|
80
|
+
</section>
|
|
81
|
+
</main>
|
|
82
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
83
|
+
</body>
|
|
165
84
|
</html>
|
|
@@ -1,152 +1,90 @@
|
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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> 的輸出之一;<code>ErrQuotaExceeded</code> 必須對映成 <code>429</code> 才能搭配 <code>Retry-After</code> 讓 UI 知道是節流。</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 對映本地化文字(例如「今日額度用盡」)。</td>
|
|
101
|
-
</tr>
|
|
102
|
-
<tr>
|
|
103
|
-
<td class="sub-vars__name">Retry-After</td>
|
|
104
|
-
<td class="sub-vars__type">int seconds</td>
|
|
105
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
106
|
-
<td>節流提示 header;UI 透過它倒數禁用按鈕,避免使用者反覆 429。</td>
|
|
107
|
-
</tr>
|
|
108
|
-
<tr>
|
|
109
|
-
<td class="sub-vars__name">NewCode</td>
|
|
110
|
-
<td class="sub-vars__type">string</td>
|
|
111
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
112
|
-
<td>網域回傳的新碼;序列化為 201 body 給使用者複製分享。</td>
|
|
113
|
-
</tr>
|
|
114
|
-
<tr>
|
|
115
|
-
<td class="sub-vars__name">http.ResponseWriter</td>
|
|
116
|
-
<td class="sub-vars__type">writer</td>
|
|
117
|
-
<td><span class="sub-vars__scope sub-vars__scope--call">call</span></td>
|
|
118
|
-
<td>對外副作用通道;保證一次回應只寫一次。</td>
|
|
119
|
-
</tr>
|
|
120
|
-
</tbody>
|
|
121
|
-
</table>
|
|
122
|
-
</section>
|
|
123
|
-
|
|
124
|
-
<section class="sub-dataflow">
|
|
125
|
-
<h2>內部資料流</h2>
|
|
126
|
-
<ol>
|
|
127
|
-
<li><code>Request</code> → <code>AuthMiddleware</code> → 注入 <code>Principal{UserID}</code>,失敗即 <code>401</code>。</li>
|
|
128
|
-
<li><code>Principal.UserID</code> 作為網域層輸入;本子模組不持有 token 明文。</li>
|
|
129
|
-
<li>從網域層取得 <code>NewCode | error</code>。</li>
|
|
130
|
-
<li><code>NewCode</code> → <code>writeCreated</code>;<code>error</code> → <code>mapDomainError</code>。</li>
|
|
131
|
-
</ol>
|
|
132
|
-
</section>
|
|
133
|
-
|
|
134
|
-
<section class="sub-errors">
|
|
135
|
-
<h2>HTTP 對映</h2>
|
|
136
|
-
<table>
|
|
137
|
-
<thead><tr><th>條件</th><th>HTTP</th></tr></thead>
|
|
138
|
-
<tbody>
|
|
139
|
-
<tr><td>無 session</td><td><code>401</code></td></tr>
|
|
140
|
-
<tr><td>網域 <code>ErrQuotaExceeded</code></td><td><code>429</code> + <code>Retry-After</code></td></tr>
|
|
141
|
-
<tr><td>網域 <code>ErrForbidden</code></td><td><code>403</code></td></tr>
|
|
142
|
-
<tr><td>網域 <code>ErrTransient</code></td><td><code>503</code></td></tr>
|
|
143
|
-
</tbody>
|
|
144
|
-
</table>
|
|
145
|
-
</section>
|
|
146
|
-
|
|
147
|
-
<footer class="atlas-meta" style="margin-top: 2rem">
|
|
148
|
-
<p><a href="../../index.html">← 宏觀架構</a> · <a href="./index.html">← 功能總覽</a></p>
|
|
149
|
-
</footer>
|
|
150
|
-
</main>
|
|
151
|
-
</body>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Get invite codes · 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">← Get invite codes</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/invites` 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>postInvites</td><td>HttpRequest</td><td>HttpResponse</td><td>network</td><td>Validates the bearer token then delegates to invite-issuance-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>token</td><td>string</td><td>call</td><td>Bearer token used to resolve the requesting member.</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 484" 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">Validate Authorization header.</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">Resolve userId from token.</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">Call invite-issuance-service.Issue.</text>
|
|
66
|
+
</g>
|
|
67
|
+
<line class="sub-dataflow__arrow" x1="340" y1="342" x2="340" y2="372" marker-end="url(#sub-arrow)" />
|
|
68
|
+
<g class="sub-dataflow__step">
|
|
69
|
+
<circle class="sub-dataflow__badge" cx="42" cy="416" r="18" />
|
|
70
|
+
<text class="sub-dataflow__badge-text" x="42" y="421" text-anchor="middle">4</text>
|
|
71
|
+
<rect class="sub-dataflow__box" x="80" y="380" width="520" height="72" rx="14" ry="14" />
|
|
72
|
+
<text class="sub-dataflow__text" x="340" y="422" text-anchor="middle">Serialize response.</text>
|
|
73
|
+
</g>
|
|
74
|
+
</svg>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</section>
|
|
78
|
+
<section class="sub-errors" aria-label="Errors">
|
|
79
|
+
<h2>Errors</h2>
|
|
80
|
+
<table class="sub-table">
|
|
81
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
82
|
+
<tbody>
|
|
83
|
+
<tr><td>ErrUnauthorized</td><td>Token missing or invalid.</td><td>401 response.</td></tr>
|
|
84
|
+
</tbody>
|
|
85
|
+
</table>
|
|
86
|
+
</section>
|
|
87
|
+
</main>
|
|
88
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
89
|
+
</body>
|
|
152
90
|
</html>
|