@laitszkin/apollo-toolkit 3.9.7 → 3.11.0
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/AGENTS.md +2 -0
- package/CHANGELOG.md +37 -0
- package/README.md +6 -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/cjk-pdf/agents/openai.yaml +5 -0
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/generate-spec/SKILL.md +26 -4
- package/generate-spec/agents/openai.yaml +1 -0
- package/generate-spec/references/TEMPLATE_SPEC.md +117 -0
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/init-project-html/SKILL.md +137 -0
- package/init-project-html/agents/openai.yaml +22 -0
- package/init-project-html/lib/atlas/assets/architecture.css +140 -0
- package/init-project-html/lib/atlas/assets/viewer.client.js +93 -0
- package/init-project-html/lib/atlas/cli.js +995 -0
- package/init-project-html/lib/atlas/layout.js +229 -0
- package/init-project-html/lib/atlas/render.js +485 -0
- package/init-project-html/lib/atlas/schema.js +310 -0
- package/init-project-html/lib/atlas/state.js +402 -0
- package/init-project-html/references/TEMPLATE_SPEC.md +137 -0
- package/init-project-html/references/architecture-page.template.html +35 -0
- package/init-project-html/references/architecture.css +1059 -0
- package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +140 -0
- package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +93 -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 +159 -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 +69 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +50 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +72 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +66 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +70 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +67 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/index.html +63 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +68 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +65 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +79 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +67 -0
- package/init-project-html/sample-demo/resources/project-architecture/index.html +234 -0
- package/init-project-html/scripts/architecture.js +314 -0
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/lib/cli.js +2 -0
- package/lib/tool-runner.js +7 -0
- package/merge-conflict-resolver/agents/openai.yaml +5 -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 +114 -0
- package/spec-to-project-html/agents/openai.yaml +18 -0
- package/spec-to-project-html/references/TEMPLATE_SPEC.md +111 -0
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Get invite codes · invite-code-generator</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>invite-code-generator <small class="submodule-kind submodule-kind--pure-fn">Pure fn</small></h1>
|
|
13
|
+
<p class="submodule-role">Pure helper that turns random bytes into a printable invite code.</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>encode</td><td>bytes[8]</td><td>code</td><td>pure</td><td>Base32 encoding without padding for human-readable codes.</td></tr>
|
|
22
|
+
</tbody>
|
|
23
|
+
</table>
|
|
24
|
+
</section>
|
|
25
|
+
<section class="sub-vars" aria-label="Variables">
|
|
26
|
+
<h2>Variables</h2>
|
|
27
|
+
<p class="sub-section__empty">No variables recorded.</p>
|
|
28
|
+
</section>
|
|
29
|
+
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
30
|
+
<h2>Internal data flow</h2>
|
|
31
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 180" role="img" aria-label="Internal dataflow">
|
|
32
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
33
|
+
<g class="sub-dataflow__step">
|
|
34
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
35
|
+
<text x="200" y="44" text-anchor="middle">Read 8 random bytes.</text>
|
|
36
|
+
</g>
|
|
37
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
38
|
+
<g class="sub-dataflow__step">
|
|
39
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
40
|
+
<text x="200" y="128" text-anchor="middle">Base32 encode without padding.</text>
|
|
41
|
+
</g>
|
|
42
|
+
</svg>
|
|
43
|
+
</section>
|
|
44
|
+
<section class="sub-errors" aria-label="Errors">
|
|
45
|
+
<h2>Errors</h2>
|
|
46
|
+
<p class="sub-section__empty">No errors recorded.</p>
|
|
47
|
+
</section>
|
|
48
|
+
</main>
|
|
49
|
+
</body>
|
|
50
|
+
</html>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Get invite codes · invite-issuance-service</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>invite-issuance-service <small class="submodule-kind submodule-kind--service">Service</small></h1>
|
|
13
|
+
<p class="submodule-role">Domain service that mints and persists a single invite row per request.</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>Issue</td><td>ctx, userId</td><td>InviteCode | error</td><td>tx</td><td>Generates a unique code and writes the matching invite_codes row.</td></tr>
|
|
22
|
+
<tr><td>generateCode</td><td>rand</td><td>code</td><td>pure</td><td>Produces a 10-char alphanumeric token.</td></tr>
|
|
23
|
+
</tbody>
|
|
24
|
+
</table>
|
|
25
|
+
</section>
|
|
26
|
+
<section class="sub-vars" aria-label="Variables">
|
|
27
|
+
<h2>Variables</h2>
|
|
28
|
+
<table class="sub-table">
|
|
29
|
+
<thead><tr><th scope="col">Name</th><th scope="col">Type</th><th scope="col">Scope</th><th scope="col">Purpose</th></tr></thead>
|
|
30
|
+
<tbody>
|
|
31
|
+
<tr><td>code</td><td>string</td><td>tx</td><td>Newly minted invite token recorded against the member.</td></tr>
|
|
32
|
+
<tr><td>row</td><td>InviteCodeRow</td><td>tx</td><td>Persisted invite_codes row carrying owner, code, expiry, and consumption state.</td></tr>
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
|
+
</section>
|
|
36
|
+
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
37
|
+
<h2>Internal data flow</h2>
|
|
38
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 348" role="img" aria-label="Internal dataflow">
|
|
39
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
40
|
+
<g class="sub-dataflow__step">
|
|
41
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
42
|
+
<text x="200" y="44" text-anchor="middle">Open transaction.</text>
|
|
43
|
+
</g>
|
|
44
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
45
|
+
<g class="sub-dataflow__step">
|
|
46
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
47
|
+
<text x="200" y="128" text-anchor="middle">Generate candidate code via generateCode.</text>
|
|
48
|
+
</g>
|
|
49
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
50
|
+
<g class="sub-dataflow__step">
|
|
51
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
52
|
+
<text x="200" y="212" text-anchor="middle">INSERT invite_codes row (retry on unique-violation).</text>
|
|
53
|
+
</g>
|
|
54
|
+
<line class="sub-dataflow__arrow" x1="200" y1="244" x2="200" y2="272" marker-end="url(#sub-arrow)" />
|
|
55
|
+
<g class="sub-dataflow__step">
|
|
56
|
+
<rect x="20" y="272" width="360" height="56" rx="8" ry="8" />
|
|
57
|
+
<text x="200" y="296" text-anchor="middle">Commit and return code.</text>
|
|
58
|
+
</g>
|
|
59
|
+
</svg>
|
|
60
|
+
</section>
|
|
61
|
+
<section class="sub-errors" aria-label="Errors">
|
|
62
|
+
<h2>Errors</h2>
|
|
63
|
+
<table class="sub-table">
|
|
64
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
65
|
+
<tbody>
|
|
66
|
+
<tr><td>ErrCollision</td><td>Unique constraint on code repeatedly violated.</td><td>Surface 503 after retry budget exhausted.</td></tr>
|
|
67
|
+
</tbody>
|
|
68
|
+
</table>
|
|
69
|
+
</section>
|
|
70
|
+
</main>
|
|
71
|
+
</body>
|
|
72
|
+
</html>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
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
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 264" role="img" aria-label="Internal dataflow">
|
|
38
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
39
|
+
<g class="sub-dataflow__step">
|
|
40
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
41
|
+
<text x="200" y="44" text-anchor="middle">Accept INSERT from invite-issuance-service.</text>
|
|
42
|
+
</g>
|
|
43
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
44
|
+
<g class="sub-dataflow__step">
|
|
45
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
46
|
+
<text x="200" y="128" text-anchor="middle">Enforce unique constraint on code.</text>
|
|
47
|
+
</g>
|
|
48
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
49
|
+
<g class="sub-dataflow__step">
|
|
50
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
51
|
+
<text x="200" y="212" text-anchor="middle">Return new rowid.</text>
|
|
52
|
+
</g>
|
|
53
|
+
</svg>
|
|
54
|
+
</section>
|
|
55
|
+
<section class="sub-errors" aria-label="Errors">
|
|
56
|
+
<h2>Errors</h2>
|
|
57
|
+
<table class="sub-table">
|
|
58
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
59
|
+
<tbody>
|
|
60
|
+
<tr><td>ErrUniqueViolation</td><td>Two issuance attempts pick the same code.</td><td>Bubble up so issuance can retry.</td></tr>
|
|
61
|
+
</tbody>
|
|
62
|
+
</table>
|
|
63
|
+
</section>
|
|
64
|
+
</main>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
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
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 348" role="img" aria-label="Internal dataflow">
|
|
37
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
38
|
+
<g class="sub-dataflow__step">
|
|
39
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
40
|
+
<text x="200" y="44" text-anchor="middle">Validate Authorization header.</text>
|
|
41
|
+
</g>
|
|
42
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
43
|
+
<g class="sub-dataflow__step">
|
|
44
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
45
|
+
<text x="200" y="128" text-anchor="middle">Resolve userId from token.</text>
|
|
46
|
+
</g>
|
|
47
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
48
|
+
<g class="sub-dataflow__step">
|
|
49
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
50
|
+
<text x="200" y="212" text-anchor="middle">Call invite-issuance-service.Issue.</text>
|
|
51
|
+
</g>
|
|
52
|
+
<line class="sub-dataflow__arrow" x1="200" y1="244" x2="200" y2="272" marker-end="url(#sub-arrow)" />
|
|
53
|
+
<g class="sub-dataflow__step">
|
|
54
|
+
<rect x="20" y="272" width="360" height="56" rx="8" ry="8" />
|
|
55
|
+
<text x="200" y="296" text-anchor="middle">Serialize response.</text>
|
|
56
|
+
</g>
|
|
57
|
+
</svg>
|
|
58
|
+
</section>
|
|
59
|
+
<section class="sub-errors" aria-label="Errors">
|
|
60
|
+
<h2>Errors</h2>
|
|
61
|
+
<table class="sub-table">
|
|
62
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
63
|
+
<tbody>
|
|
64
|
+
<tr><td>ErrUnauthorized</td><td>Token missing or invalid.</td><td>401 response.</td></tr>
|
|
65
|
+
</tbody>
|
|
66
|
+
</table>
|
|
67
|
+
</section>
|
|
68
|
+
</main>
|
|
69
|
+
</body>
|
|
70
|
+
</html>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Get invite codes · web-get-invite-ui</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>web-get-invite-ui <small class="submodule-kind submodule-kind--ui">UI</small></h1>
|
|
13
|
+
<p class="submodule-role">React page that lets a signed-in member request a new invite code.</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>handleGenerate</td><td>MouseEvent</td><td>void</td><td>io</td><td>Calls POST /api/invites and renders the returned code.</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>userId</td><td>string</td><td>call</td><td>Identifies the member who will own the new invite row.</td></tr>
|
|
31
|
+
<tr><td>code</td><td>string</td><td>instance</td><td>Last issued code shown to the member.</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
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 264" role="img" aria-label="Internal dataflow">
|
|
38
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
39
|
+
<g class="sub-dataflow__step">
|
|
40
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
41
|
+
<text x="200" y="44" text-anchor="middle">Read userId from auth context.</text>
|
|
42
|
+
</g>
|
|
43
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
44
|
+
<g class="sub-dataflow__step">
|
|
45
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
46
|
+
<text x="200" y="128" text-anchor="middle">POST /api/invites with userId.</text>
|
|
47
|
+
</g>
|
|
48
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
49
|
+
<g class="sub-dataflow__step">
|
|
50
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
51
|
+
<text x="200" y="212" text-anchor="middle">Render returned code or surface error.</text>
|
|
52
|
+
</g>
|
|
53
|
+
</svg>
|
|
54
|
+
</section>
|
|
55
|
+
<section class="sub-errors" aria-label="Errors">
|
|
56
|
+
<h2>Errors</h2>
|
|
57
|
+
<table class="sub-table">
|
|
58
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
59
|
+
<tbody>
|
|
60
|
+
<tr><td>ErrUnauthenticated</td><td>Session is missing on the client.</td><td>Redirect to sign-in.</td></tr>
|
|
61
|
+
<tr><td>ErrIssuanceFailed</td><td>API returns 500.</td><td>Show retry banner.</td></tr>
|
|
62
|
+
</tbody>
|
|
63
|
+
</table>
|
|
64
|
+
</section>
|
|
65
|
+
</main>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-atlas-page="feature">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Invite-code registration</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="feature-header">
|
|
11
|
+
<nav class="feature-breadcrumb"><a href="../../index.html">← Atlas</a></nav>
|
|
12
|
+
<h1>Invite-code registration</h1>
|
|
13
|
+
<p class="feature-depends">Depends on: <a href="../get-invite-codes/index.html">get-invite-codes</a></p>
|
|
14
|
+
</header>
|
|
15
|
+
<main class="feature-main">
|
|
16
|
+
<section class="feature-story"><p>A visitor holding an invite code submits email/password plus the code. The registration service validates the code inside a single transaction; on success it creates a new user and consumes the invite_codes row issued earlier by `get-invite-codes`.</p></section>
|
|
17
|
+
<section class="feature-submodules" aria-label="Submodules">
|
|
18
|
+
<h2>Submodules</h2>
|
|
19
|
+
<ul class="submodule-nav">
|
|
20
|
+
<li class="submodule-card">
|
|
21
|
+
<a class="submodule-card__link" href="web-register-ui.html">
|
|
22
|
+
<span class="submodule-card__name">web-register-ui</span>
|
|
23
|
+
<span class="submodule-card__kind submodule-card__kind--ui">UI</span>
|
|
24
|
+
</a>
|
|
25
|
+
<p class="submodule-card__role">React page that captures email, password, and invite code.</p>
|
|
26
|
+
</li>
|
|
27
|
+
<li class="submodule-card">
|
|
28
|
+
<a class="submodule-card__link" href="public-api.html">
|
|
29
|
+
<span class="submodule-card__name">public-api</span>
|
|
30
|
+
<span class="submodule-card__kind submodule-card__kind--api">API</span>
|
|
31
|
+
</a>
|
|
32
|
+
<p class="submodule-card__role">HTTP boundary for `/api/register` POST requests.</p>
|
|
33
|
+
</li>
|
|
34
|
+
<li class="submodule-card">
|
|
35
|
+
<a class="submodule-card__link" href="registration-service.html">
|
|
36
|
+
<span class="submodule-card__name">registration-service</span>
|
|
37
|
+
<span class="submodule-card__kind submodule-card__kind--service">Service</span>
|
|
38
|
+
</a>
|
|
39
|
+
<p class="submodule-card__role">Owns the registration transaction (consumer side of the invite_codes data row).</p>
|
|
40
|
+
</li>
|
|
41
|
+
<li class="submodule-card">
|
|
42
|
+
<a class="submodule-card__link" href="postgresql.html">
|
|
43
|
+
<span class="submodule-card__name">postgresql</span>
|
|
44
|
+
<span class="submodule-card__kind submodule-card__kind--db">DB</span>
|
|
45
|
+
</a>
|
|
46
|
+
<p class="submodule-card__role">Stores `users` rows and applies invite-code state transitions inside the registration tx.</p>
|
|
47
|
+
</li>
|
|
48
|
+
</ul>
|
|
49
|
+
</section>
|
|
50
|
+
<section class="feature-edges" aria-label="Intra-feature edges">
|
|
51
|
+
<h2>Intra-feature edges</h2>
|
|
52
|
+
<ul class="feature-edges__list">
|
|
53
|
+
<li class="feature-edges__item feature-edges__item--call"><span class="feature-edges__endpoints">web-register-ui → public-api</span><span class="feature-edges__kind">call</span><span class="feature-edges__label">POST /api/register</span></li>
|
|
54
|
+
<li class="feature-edges__item feature-edges__item--call"><span class="feature-edges__endpoints">public-api → registration-service</span><span class="feature-edges__kind">call</span><span class="feature-edges__label">RegisterWithInvite(ctx, RegisterInput)</span></li>
|
|
55
|
+
<li class="feature-edges__item feature-edges__item--call"><span class="feature-edges__endpoints">registration-service → postgresql</span><span class="feature-edges__kind">call</span><span class="feature-edges__label">SELECT invite_codes FOR UPDATE</span></li>
|
|
56
|
+
<li class="feature-edges__item feature-edges__item--call"><span class="feature-edges__endpoints">registration-service → postgresql</span><span class="feature-edges__kind">call</span><span class="feature-edges__label">INSERT users</span></li>
|
|
57
|
+
<li class="feature-edges__item feature-edges__item--call"><span class="feature-edges__endpoints">registration-service → postgresql</span><span class="feature-edges__kind">call</span><span class="feature-edges__label">UPDATE invite_codes.consumed_at</span></li>
|
|
58
|
+
<li class="feature-edges__item feature-edges__item--return"><span class="feature-edges__endpoints">postgresql → registration-service</span><span class="feature-edges__kind">return</span><span class="feature-edges__label">row | rows_affected</span></li>
|
|
59
|
+
</ul>
|
|
60
|
+
</section>
|
|
61
|
+
</main>
|
|
62
|
+
</body>
|
|
63
|
+
</html>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
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
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 264" role="img" aria-label="Internal dataflow">
|
|
40
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
41
|
+
<g class="sub-dataflow__step">
|
|
42
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
43
|
+
<text x="200" y="44" text-anchor="middle">Apply row lock on invite_codes.</text>
|
|
44
|
+
</g>
|
|
45
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
46
|
+
<g class="sub-dataflow__step">
|
|
47
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
48
|
+
<text x="200" y="128" text-anchor="middle">Validate uniqueness of users.email.</text>
|
|
49
|
+
</g>
|
|
50
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
51
|
+
<g class="sub-dataflow__step">
|
|
52
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
53
|
+
<text x="200" y="212" text-anchor="middle">Write users row and update invite_codes.consumed_at.</text>
|
|
54
|
+
</g>
|
|
55
|
+
</svg>
|
|
56
|
+
</section>
|
|
57
|
+
<section class="sub-errors" aria-label="Errors">
|
|
58
|
+
<h2>Errors</h2>
|
|
59
|
+
<table class="sub-table">
|
|
60
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
61
|
+
<tbody>
|
|
62
|
+
<tr><td>ErrUniqueEmail</td><td>users.email unique constraint violated.</td><td>Bubble up so service can return ErrEmailTaken.</td></tr>
|
|
63
|
+
</tbody>
|
|
64
|
+
</table>
|
|
65
|
+
</section>
|
|
66
|
+
</main>
|
|
67
|
+
</body>
|
|
68
|
+
</html>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
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
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 264" role="img" aria-label="Internal dataflow">
|
|
37
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
38
|
+
<g class="sub-dataflow__step">
|
|
39
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
40
|
+
<text x="200" y="44" text-anchor="middle">Decode JSON body.</text>
|
|
41
|
+
</g>
|
|
42
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
43
|
+
<g class="sub-dataflow__step">
|
|
44
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
45
|
+
<text x="200" y="128" text-anchor="middle">Call registration-service.RegisterWithInvite.</text>
|
|
46
|
+
</g>
|
|
47
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
48
|
+
<g class="sub-dataflow__step">
|
|
49
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
50
|
+
<text x="200" y="212" text-anchor="middle">Serialize success or 422 / 5xx error.</text>
|
|
51
|
+
</g>
|
|
52
|
+
</svg>
|
|
53
|
+
</section>
|
|
54
|
+
<section class="sub-errors" aria-label="Errors">
|
|
55
|
+
<h2>Errors</h2>
|
|
56
|
+
<table class="sub-table">
|
|
57
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
58
|
+
<tbody>
|
|
59
|
+
<tr><td>ErrMalformedPayload</td><td>JSON parse fails.</td><td>400 response with `payload` reason.</td></tr>
|
|
60
|
+
</tbody>
|
|
61
|
+
</table>
|
|
62
|
+
</section>
|
|
63
|
+
</main>
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-atlas-page="submodule">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Invite-code registration · registration-service</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>registration-service <small class="submodule-kind submodule-kind--service">Service</small></h1>
|
|
13
|
+
<p class="submodule-role">Owns the registration transaction (consumer side of the invite_codes 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>RegisterWithInvite</td><td>ctx, RegisterInput</td><td>NewUserID | ErrInvalidCode | ErrEmailTaken</td><td>tx</td><td>Validates code, hashes password, inserts user, consumes invite.</td></tr>
|
|
22
|
+
<tr><td>decideInviteValid</td><td>row, now</td><td>true | ErrInvalidCode</td><td>pure</td><td>Checks existence, expiry, consumption state.</td></tr>
|
|
23
|
+
</tbody>
|
|
24
|
+
</table>
|
|
25
|
+
</section>
|
|
26
|
+
<section class="sub-vars" aria-label="Variables">
|
|
27
|
+
<h2>Variables</h2>
|
|
28
|
+
<table class="sub-table">
|
|
29
|
+
<thead><tr><th scope="col">Name</th><th scope="col">Type</th><th scope="col">Scope</th><th scope="col">Purpose</th></tr></thead>
|
|
30
|
+
<tbody>
|
|
31
|
+
<tr><td>inviteRow</td><td>InviteCodeRow</td><td>tx</td><td>Row read with SELECT FOR UPDATE; gates the rest of the flow.</td></tr>
|
|
32
|
+
<tr><td>passwordHash</td><td>string</td><td>tx</td><td>bcrypt/argon2 hash of the submitted password; plaintext is discarded.</td></tr>
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
|
+
</section>
|
|
36
|
+
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
37
|
+
<h2>Internal data flow</h2>
|
|
38
|
+
<svg class="sub-dataflow__svg" viewBox="0 0 400 432" role="img" aria-label="Internal dataflow">
|
|
39
|
+
<defs><marker id="sub-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 Z" /></marker></defs>
|
|
40
|
+
<g class="sub-dataflow__step">
|
|
41
|
+
<rect x="20" y="20" width="360" height="56" rx="8" ry="8" />
|
|
42
|
+
<text x="200" y="44" text-anchor="middle">Open transaction.</text>
|
|
43
|
+
</g>
|
|
44
|
+
<line class="sub-dataflow__arrow" x1="200" y1="76" x2="200" y2="104" marker-end="url(#sub-arrow)" />
|
|
45
|
+
<g class="sub-dataflow__step">
|
|
46
|
+
<rect x="20" y="104" width="360" height="56" rx="8" ry="8" />
|
|
47
|
+
<text x="200" y="128" text-anchor="middle">SELECT invite_codes FOR UPDATE WHERE code = ?</text>
|
|
48
|
+
</g>
|
|
49
|
+
<line class="sub-dataflow__arrow" x1="200" y1="160" x2="200" y2="188" marker-end="url(#sub-arrow)" />
|
|
50
|
+
<g class="sub-dataflow__step">
|
|
51
|
+
<rect x="20" y="188" width="360" height="56" rx="8" ry="8" />
|
|
52
|
+
<text x="200" y="212" text-anchor="middle">decideInviteValid against current time.</text>
|
|
53
|
+
</g>
|
|
54
|
+
<line class="sub-dataflow__arrow" x1="200" y1="244" x2="200" y2="272" marker-end="url(#sub-arrow)" />
|
|
55
|
+
<g class="sub-dataflow__step">
|
|
56
|
+
<rect x="20" y="272" width="360" height="56" rx="8" ry="8" />
|
|
57
|
+
<text x="200" y="296" text-anchor="middle">INSERT users row and UPDATE</text>
|
|
58
|
+
<text x="200" y="312" text-anchor="middle">invite_codes.consumed_at.</text>
|
|
59
|
+
</g>
|
|
60
|
+
<line class="sub-dataflow__arrow" x1="200" y1="328" x2="200" y2="356" marker-end="url(#sub-arrow)" />
|
|
61
|
+
<g class="sub-dataflow__step">
|
|
62
|
+
<rect x="20" y="356" width="360" height="56" rx="8" ry="8" />
|
|
63
|
+
<text x="200" y="380" text-anchor="middle">Commit and return NewUserID.</text>
|
|
64
|
+
</g>
|
|
65
|
+
</svg>
|
|
66
|
+
</section>
|
|
67
|
+
<section class="sub-errors" aria-label="Errors">
|
|
68
|
+
<h2>Errors</h2>
|
|
69
|
+
<table class="sub-table">
|
|
70
|
+
<thead><tr><th scope="col">Name</th><th scope="col">When</th><th scope="col">Means</th></tr></thead>
|
|
71
|
+
<tbody>
|
|
72
|
+
<tr><td>ErrInvalidCode</td><td>Row missing, expired, or already consumed.</td><td>422 response with `invite_code` reason.</td></tr>
|
|
73
|
+
<tr><td>ErrEmailTaken</td><td>Unique violation on users.email.</td><td>422 response with `email` reason.</td></tr>
|
|
74
|
+
</tbody>
|
|
75
|
+
</table>
|
|
76
|
+
</section>
|
|
77
|
+
</main>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|