@laitszkin/apollo-toolkit 3.11.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 +17 -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/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/init-project-html/SKILL.md +56 -20
- package/init-project-html/agents/openai.yaml +6 -6
- package/init-project-html/lib/atlas/assets/architecture.css +27 -6
- package/init-project-html/lib/atlas/assets/viewer.client.js +124 -81
- package/init-project-html/lib/atlas/cli.js +31 -3
- package/init-project-html/lib/atlas/layout.js +112 -11
- package/init-project-html/lib/atlas/render.js +131 -33
- package/init-project-html/lib/atlas/schema.js +39 -2
- package/init-project-html/references/TEMPLATE_SPEC.md +26 -8
- package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +27 -6
- package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +124 -81
- package/init-project-html/sample-demo/resources/project-architecture/atlas/features/get-invite-codes.yaml +17 -4
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +23 -7
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +45 -13
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +28 -10
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +33 -13
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +28 -10
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +28 -10
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +28 -10
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +38 -17
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +29 -11
- package/init-project-html/sample-demo/resources/project-architecture/index.html +100 -76
- 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 +1 -1
- 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 +25 -16
- package/spec-to-project-html/agents/openai.yaml +5 -5
- package/spec-to-project-html/references/TEMPLATE_SPEC.md +2 -0
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js
CHANGED
|
@@ -1,93 +1,136 @@
|
|
|
1
|
-
/* viewer.client.js — pan/zoom for
|
|
2
|
-
*
|
|
3
|
-
* [data-
|
|
4
|
-
*
|
|
1
|
+
/* viewer.client.js — pan/zoom for every atlas SVG on the page.
|
|
2
|
+
*
|
|
3
|
+
* Each `[data-pan-zoom-viewport]` element gets its own state and
|
|
4
|
+
* handlers, so a single page can host the macro atlas SVG AND
|
|
5
|
+
* sub-module-internal dataflow SVGs simultaneously. Toolbar buttons
|
|
6
|
+
* (`[data-pan-zoom="zoom-in|zoom-out|fit"]`) are scoped to the
|
|
7
|
+
* containing `[data-pan-zoom-container]` (falls back to the viewport's
|
|
8
|
+
* direct parent), so multiple toolbars on one page do not collide.
|
|
9
|
+
* Keyboard shortcuts (`←` / `→` / `↑` / `↓` / `+` / `−` / `0`) drive
|
|
10
|
+
* the page's first viewport — the "primary" diagram of that page
|
|
11
|
+
* (macro SVG on `index.html`; sub-dataflow SVG on a sub-module page).
|
|
12
|
+
*/
|
|
5
13
|
|
|
6
14
|
(function () {
|
|
7
15
|
'use strict';
|
|
8
16
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (!svg) return;
|
|
17
|
+
const viewports = Array.from(document.querySelectorAll('[data-pan-zoom-viewport]'));
|
|
18
|
+
const controllers = viewports.map(setupViewport).filter(Boolean);
|
|
19
|
+
if (controllers.length === 0) return;
|
|
13
20
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
const primary = controllers[0];
|
|
22
|
+
document.addEventListener('keydown', function (evt) {
|
|
23
|
+
if (evt.target && (evt.target.tagName === 'INPUT' || evt.target.tagName === 'TEXTAREA')) return;
|
|
24
|
+
if (evt.key === 'ArrowLeft') { primary.pan(-1, 0); }
|
|
25
|
+
else if (evt.key === 'ArrowRight') { primary.pan(1, 0); }
|
|
26
|
+
else if (evt.key === 'ArrowUp') { primary.pan(0, -1); }
|
|
27
|
+
else if (evt.key === 'ArrowDown') { primary.pan(0, 1); }
|
|
28
|
+
else if (evt.key === '+' || evt.key === '=') { primary.zoom(1 / 1.2); }
|
|
29
|
+
else if (evt.key === '-' || evt.key === '_') { primary.zoom(1.2); }
|
|
30
|
+
else if (evt.key === '0') { primary.fit(); }
|
|
31
|
+
});
|
|
22
32
|
|
|
23
|
-
function
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
state
|
|
30
|
-
state.h = newH;
|
|
31
|
-
apply();
|
|
32
|
-
}
|
|
33
|
+
function setupViewport(viewport) {
|
|
34
|
+
const svg = viewport.querySelector('[data-atlas-svg]');
|
|
35
|
+
if (!svg) return null;
|
|
36
|
+
const initial = svg.getAttribute('viewBox');
|
|
37
|
+
if (!initial) return null;
|
|
38
|
+
const [ix, iy, iw, ih] = initial.split(/\s+/).map(Number);
|
|
39
|
+
const state = { x: ix, y: iy, w: iw, h: ih };
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
function apply() {
|
|
42
|
+
svg.setAttribute('viewBox', `${state.x} ${state.y} ${state.w} ${state.h}`);
|
|
43
|
+
}
|
|
44
|
+
function fit() {
|
|
45
|
+
state.x = ix; state.y = iy; state.w = iw; state.h = ih;
|
|
46
|
+
apply();
|
|
47
|
+
}
|
|
48
|
+
function zoom(factor, cx, cy) {
|
|
49
|
+
const newW = Math.max(40, Math.min(state.w * factor, iw * 8));
|
|
50
|
+
const newH = newW * (state.h / state.w);
|
|
51
|
+
if (cx == null) { cx = state.x + state.w / 2; cy = state.y + state.h / 2; }
|
|
52
|
+
state.x = cx - (cx - state.x) * (newW / state.w);
|
|
53
|
+
state.y = cy - (cy - state.y) * (newH / state.h);
|
|
54
|
+
state.w = newW;
|
|
55
|
+
state.h = newH;
|
|
56
|
+
apply();
|
|
57
|
+
}
|
|
58
|
+
function pan(dirX, dirY) {
|
|
59
|
+
const stepX = state.w * 0.08;
|
|
60
|
+
const stepY = state.h * 0.08;
|
|
61
|
+
state.x += dirX * stepX;
|
|
62
|
+
state.y += dirY * stepY;
|
|
63
|
+
apply();
|
|
64
|
+
}
|
|
65
|
+
function clientToSvg(evt) {
|
|
66
|
+
const rect = svg.getBoundingClientRect();
|
|
67
|
+
const xRatio = (evt.clientX - rect.left) / rect.width;
|
|
68
|
+
const yRatio = (evt.clientY - rect.top) / rect.height;
|
|
69
|
+
return { x: state.x + xRatio * state.w, y: state.y + yRatio * state.h };
|
|
70
|
+
}
|
|
40
71
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
72
|
+
viewport.addEventListener('wheel', function (evt) {
|
|
73
|
+
if (!evt.ctrlKey && !evt.metaKey && Math.abs(evt.deltaY) < 4 && Math.abs(evt.deltaX) < 4) return;
|
|
74
|
+
evt.preventDefault();
|
|
75
|
+
const factor = evt.deltaY > 0 ? 1.1 : 1 / 1.1;
|
|
76
|
+
const pt = clientToSvg(evt);
|
|
77
|
+
zoom(factor, pt.x, pt.y);
|
|
78
|
+
}, { passive: false });
|
|
48
79
|
|
|
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
|
-
|
|
80
|
+
// Drag-pan: defer the pointer capture (and the "is-grabbing" class)
|
|
81
|
+
// until the pointer actually moves past a small threshold. Without
|
|
82
|
+
// this, a single click on an SVG <a> (sub-module link) would be
|
|
83
|
+
// captured by the viewport and never reach the link.
|
|
84
|
+
const DRAG_THRESHOLD_PX = 4;
|
|
85
|
+
let pending = null;
|
|
86
|
+
let dragging = null;
|
|
87
|
+
viewport.addEventListener('pointerdown', function (evt) {
|
|
88
|
+
if (evt.button !== 0) return;
|
|
89
|
+
pending = { x: evt.clientX, y: evt.clientY, pointerId: evt.pointerId };
|
|
90
|
+
});
|
|
91
|
+
viewport.addEventListener('pointermove', function (evt) {
|
|
92
|
+
if (!dragging && pending && pending.pointerId === evt.pointerId) {
|
|
93
|
+
const dx = evt.clientX - pending.x;
|
|
94
|
+
const dy = evt.clientY - pending.y;
|
|
95
|
+
if (Math.hypot(dx, dy) < DRAG_THRESHOLD_PX) return;
|
|
96
|
+
dragging = { x: pending.x, y: pending.y, pointerId: pending.pointerId };
|
|
97
|
+
pending = null;
|
|
98
|
+
viewport.classList.add('is-grabbing');
|
|
99
|
+
try { viewport.setPointerCapture(dragging.pointerId); } catch (e) { /* ignore */ }
|
|
100
|
+
}
|
|
101
|
+
if (!dragging || dragging.pointerId !== evt.pointerId) return;
|
|
102
|
+
evt.preventDefault();
|
|
103
|
+
const rect = svg.getBoundingClientRect();
|
|
104
|
+
const dx = ((evt.clientX - dragging.x) / rect.width) * state.w;
|
|
105
|
+
const dy = ((evt.clientY - dragging.y) / rect.height) * state.h;
|
|
106
|
+
state.x -= dx;
|
|
107
|
+
state.y -= dy;
|
|
108
|
+
dragging.x = evt.clientX;
|
|
109
|
+
dragging.y = evt.clientY;
|
|
110
|
+
apply();
|
|
111
|
+
});
|
|
112
|
+
function endDrag(evt) {
|
|
113
|
+
pending = null;
|
|
114
|
+
if (!dragging) return;
|
|
115
|
+
const draggedId = dragging.pointerId;
|
|
116
|
+
dragging = null;
|
|
117
|
+
viewport.classList.remove('is-grabbing');
|
|
118
|
+
try { viewport.releasePointerCapture(draggedId); } catch (e) { /* ignore */ }
|
|
119
|
+
// Suppress the synthetic click that would follow a drag-release
|
|
120
|
+
// on top of a sub-module <a>; only the no-movement case should
|
|
121
|
+
// navigate.
|
|
122
|
+
const swallow = (e) => { e.preventDefault(); e.stopPropagation(); };
|
|
123
|
+
viewport.addEventListener('click', swallow, { capture: true, once: true });
|
|
124
|
+
}
|
|
125
|
+
viewport.addEventListener('pointerup', endDrag);
|
|
126
|
+
viewport.addEventListener('pointercancel', endDrag);
|
|
127
|
+
viewport.addEventListener('pointerleave', endDrag);
|
|
75
128
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
else if (evt.key === 'ArrowRight') { state.x += step; apply(); }
|
|
81
|
-
else if (evt.key === 'ArrowUp') { state.y -= step; apply(); }
|
|
82
|
-
else if (evt.key === 'ArrowDown') { state.y += step; apply(); }
|
|
83
|
-
else if (evt.key === '+' || evt.key === '=') { zoom(1 / 1.2); }
|
|
84
|
-
else if (evt.key === '-' || evt.key === '_') { zoom(1.2); }
|
|
85
|
-
else if (evt.key === '0') { state.x = ix; state.y = iy; state.w = iw; state.h = ih; apply(); }
|
|
86
|
-
});
|
|
129
|
+
const container = viewport.closest('[data-pan-zoom-container]') || viewport.parentElement || document;
|
|
130
|
+
container.querySelectorAll('[data-pan-zoom="zoom-in"]').forEach((btn) => btn.addEventListener('click', () => zoom(1 / 1.2)));
|
|
131
|
+
container.querySelectorAll('[data-pan-zoom="zoom-out"]').forEach((btn) => btn.addEventListener('click', () => zoom(1.2)));
|
|
132
|
+
container.querySelectorAll('[data-pan-zoom="fit"]').forEach((btn) => btn.addEventListener('click', fit));
|
|
87
133
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
document.querySelectorAll('[data-pan-zoom="fit"]').forEach((btn) => btn.addEventListener('click', () => {
|
|
91
|
-
state.x = ix; state.y = iy; state.w = iw; state.h = ih; apply();
|
|
92
|
-
}));
|
|
134
|
+
return { zoom, fit, pan };
|
|
135
|
+
}
|
|
93
136
|
})();
|
|
@@ -83,10 +83,23 @@ submodules:
|
|
|
83
83
|
scope: tx
|
|
84
84
|
purpose: Persisted invite_codes row carrying owner, code, expiry, and consumption state.
|
|
85
85
|
dataflow:
|
|
86
|
-
- Open transaction.
|
|
87
|
-
|
|
88
|
-
-
|
|
89
|
-
|
|
86
|
+
- step: Open transaction.
|
|
87
|
+
fn: Issue
|
|
88
|
+
- step: Build candidate code from random bytes.
|
|
89
|
+
fn: generateCode
|
|
90
|
+
writes:
|
|
91
|
+
- code
|
|
92
|
+
- step: Persist row via INSERT (retry on unique-violation).
|
|
93
|
+
fn: Issue
|
|
94
|
+
reads:
|
|
95
|
+
- code
|
|
96
|
+
writes:
|
|
97
|
+
- row
|
|
98
|
+
- step: Commit transaction and return code to caller.
|
|
99
|
+
fn: Issue
|
|
100
|
+
reads:
|
|
101
|
+
- code
|
|
102
|
+
- row
|
|
90
103
|
errors:
|
|
91
104
|
- name: ErrCollision
|
|
92
105
|
when: Unique constraint on code repeatedly violated.
|
|
@@ -28,23 +28,39 @@
|
|
|
28
28
|
</section>
|
|
29
29
|
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
30
30
|
<h2>Internal data flow</h2>
|
|
31
|
-
<
|
|
32
|
-
|
|
31
|
+
<div class="sub-dataflow__canvas" data-pan-zoom-container>
|
|
32
|
+
<div class="sub-dataflow__toolbar" role="toolbar" aria-label="Diagram controls">
|
|
33
|
+
<button type="button" data-pan-zoom="zoom-in" aria-label="Zoom in">+</button>
|
|
34
|
+
<button type="button" data-pan-zoom="zoom-out" aria-label="Zoom out">−</button>
|
|
35
|
+
<button type="button" data-pan-zoom="fit" aria-label="Reset view">Fit</button>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="sub-dataflow__viewport" data-pan-zoom-viewport>
|
|
38
|
+
<svg class="sub-dataflow__svg" data-atlas-svg="sub-dataflow" viewBox="0 0 628 252" role="img" aria-label="Internal dataflow">
|
|
39
|
+
<defs>
|
|
40
|
+
<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>
|
|
41
|
+
</defs>
|
|
33
42
|
<g class="sub-dataflow__step">
|
|
34
|
-
<
|
|
35
|
-
<text x="
|
|
43
|
+
<circle class="sub-dataflow__badge" cx="42" cy="68" r="18" />
|
|
44
|
+
<text class="sub-dataflow__badge-text" x="42" y="73" text-anchor="middle">1</text>
|
|
45
|
+
<rect class="sub-dataflow__box" x="80" y="32" width="520" height="72" rx="14" ry="14" />
|
|
46
|
+
<text class="sub-dataflow__text" x="340" y="74" text-anchor="middle">Read 8 random bytes.</text>
|
|
36
47
|
</g>
|
|
37
|
-
<line class="sub-dataflow__arrow" x1="
|
|
48
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
38
49
|
<g class="sub-dataflow__step">
|
|
39
|
-
<
|
|
40
|
-
<text x="
|
|
50
|
+
<circle class="sub-dataflow__badge" cx="42" cy="184" r="18" />
|
|
51
|
+
<text class="sub-dataflow__badge-text" x="42" y="189" text-anchor="middle">2</text>
|
|
52
|
+
<rect class="sub-dataflow__box" x="80" y="148" width="520" height="72" rx="14" ry="14" />
|
|
53
|
+
<text class="sub-dataflow__text" x="340" y="190" text-anchor="middle">Base32 encode without padding.</text>
|
|
41
54
|
</g>
|
|
42
55
|
</svg>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
43
58
|
</section>
|
|
44
59
|
<section class="sub-errors" aria-label="Errors">
|
|
45
60
|
<h2>Errors</h2>
|
|
46
61
|
<p class="sub-section__empty">No errors recorded.</p>
|
|
47
62
|
</section>
|
|
48
63
|
</main>
|
|
64
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
49
65
|
</body>
|
|
50
66
|
</html>
|
|
@@ -35,28 +35,59 @@
|
|
|
35
35
|
</section>
|
|
36
36
|
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
37
37
|
<h2>Internal data flow</h2>
|
|
38
|
-
<
|
|
39
|
-
|
|
38
|
+
<div class="sub-dataflow__canvas" data-pan-zoom-container>
|
|
39
|
+
<div class="sub-dataflow__toolbar" role="toolbar" aria-label="Diagram controls">
|
|
40
|
+
<button type="button" data-pan-zoom="zoom-in" aria-label="Zoom in">+</button>
|
|
41
|
+
<button type="button" data-pan-zoom="zoom-out" aria-label="Zoom out">−</button>
|
|
42
|
+
<button type="button" data-pan-zoom="fit" aria-label="Reset view">Fit</button>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="sub-dataflow__viewport" data-pan-zoom-viewport>
|
|
45
|
+
<svg class="sub-dataflow__svg" data-atlas-svg="sub-dataflow" viewBox="0 0 628 626" role="img" aria-label="Internal dataflow">
|
|
46
|
+
<defs>
|
|
47
|
+
<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>
|
|
48
|
+
</defs>
|
|
40
49
|
<g class="sub-dataflow__step">
|
|
41
|
-
<
|
|
42
|
-
<text x="
|
|
50
|
+
<circle class="sub-dataflow__badge" cx="42" cy="76" r="18" />
|
|
51
|
+
<text class="sub-dataflow__badge-text" x="42" y="81" text-anchor="middle">1</text>
|
|
52
|
+
<rect class="sub-dataflow__box" x="80" y="32" width="520" height="88" rx="14" ry="14" />
|
|
53
|
+
<rect class="sub-dataflow__fn-bg" x="94" y="46" width="79.2" height="20" rx="10" ry="10" />
|
|
54
|
+
<text class="sub-dataflow__fn-text" x="104" y="60">fn Issue</text>
|
|
55
|
+
<text class="sub-dataflow__text" x="340" y="98" text-anchor="middle">Open transaction.</text>
|
|
43
56
|
</g>
|
|
44
|
-
<line class="sub-dataflow__arrow" x1="
|
|
57
|
+
<line class="sub-dataflow__arrow" x1="340" y1="126" x2="340" y2="156" marker-end="url(#sub-arrow)" />
|
|
45
58
|
<g class="sub-dataflow__step">
|
|
46
|
-
<
|
|
47
|
-
<text x="
|
|
59
|
+
<circle class="sub-dataflow__badge" cx="42" cy="221" r="18" />
|
|
60
|
+
<text class="sub-dataflow__badge-text" x="42" y="226" text-anchor="middle">2</text>
|
|
61
|
+
<rect class="sub-dataflow__box" x="80" y="164" width="520" height="114" rx="14" ry="14" />
|
|
62
|
+
<rect class="sub-dataflow__fn-bg" x="94" y="178" width="131" height="20" rx="10" ry="10" />
|
|
63
|
+
<text class="sub-dataflow__fn-text" x="104" y="192">fn generateCode</text>
|
|
64
|
+
<text class="sub-dataflow__text" x="340" y="230" text-anchor="middle">Build candidate code from random bytes.</text>
|
|
65
|
+
<text class="sub-dataflow__chip sub-dataflow__chip--writes" x="586" y="266" text-anchor="end">→ writes: code</text>
|
|
48
66
|
</g>
|
|
49
|
-
<line class="sub-dataflow__arrow" x1="
|
|
67
|
+
<line class="sub-dataflow__arrow" x1="340" y1="284" x2="340" y2="314" marker-end="url(#sub-arrow)" />
|
|
50
68
|
<g class="sub-dataflow__step">
|
|
51
|
-
<
|
|
52
|
-
<text x="
|
|
69
|
+
<circle class="sub-dataflow__badge" cx="42" cy="379" r="18" />
|
|
70
|
+
<text class="sub-dataflow__badge-text" x="42" y="384" text-anchor="middle">3</text>
|
|
71
|
+
<rect class="sub-dataflow__box" x="80" y="322" width="520" height="114" rx="14" ry="14" />
|
|
72
|
+
<rect class="sub-dataflow__fn-bg" x="94" y="336" width="79.2" height="20" rx="10" ry="10" />
|
|
73
|
+
<text class="sub-dataflow__fn-text" x="104" y="350">fn Issue</text>
|
|
74
|
+
<text class="sub-dataflow__text" x="340" y="388" text-anchor="middle">Persist row via INSERT (retry on unique-violation).</text>
|
|
75
|
+
<text class="sub-dataflow__chip sub-dataflow__chip--reads" x="94" y="424">← reads: code</text>
|
|
76
|
+
<text class="sub-dataflow__chip sub-dataflow__chip--writes" x="586" y="424" text-anchor="end">→ writes: row</text>
|
|
53
77
|
</g>
|
|
54
|
-
<line class="sub-dataflow__arrow" x1="
|
|
78
|
+
<line class="sub-dataflow__arrow" x1="340" y1="442" x2="340" y2="472" marker-end="url(#sub-arrow)" />
|
|
55
79
|
<g class="sub-dataflow__step">
|
|
56
|
-
<
|
|
57
|
-
<text x="
|
|
80
|
+
<circle class="sub-dataflow__badge" cx="42" cy="537" r="18" />
|
|
81
|
+
<text class="sub-dataflow__badge-text" x="42" y="542" text-anchor="middle">4</text>
|
|
82
|
+
<rect class="sub-dataflow__box" x="80" y="480" width="520" height="114" rx="14" ry="14" />
|
|
83
|
+
<rect class="sub-dataflow__fn-bg" x="94" y="494" width="79.2" height="20" rx="10" ry="10" />
|
|
84
|
+
<text class="sub-dataflow__fn-text" x="104" y="508">fn Issue</text>
|
|
85
|
+
<text class="sub-dataflow__text" x="340" y="546" text-anchor="middle">Commit transaction and return code to caller.</text>
|
|
86
|
+
<text class="sub-dataflow__chip sub-dataflow__chip--reads" x="94" y="582">← reads: code, row</text>
|
|
58
87
|
</g>
|
|
59
88
|
</svg>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
60
91
|
</section>
|
|
61
92
|
<section class="sub-errors" aria-label="Errors">
|
|
62
93
|
<h2>Errors</h2>
|
|
@@ -68,5 +99,6 @@
|
|
|
68
99
|
</table>
|
|
69
100
|
</section>
|
|
70
101
|
</main>
|
|
102
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
71
103
|
</body>
|
|
72
104
|
</html>
|
|
@@ -34,23 +34,40 @@
|
|
|
34
34
|
</section>
|
|
35
35
|
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
36
36
|
<h2>Internal data flow</h2>
|
|
37
|
-
<
|
|
38
|
-
|
|
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>
|
|
39
48
|
<g class="sub-dataflow__step">
|
|
40
|
-
<
|
|
41
|
-
<text x="
|
|
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>
|
|
42
53
|
</g>
|
|
43
|
-
<line class="sub-dataflow__arrow" x1="
|
|
54
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
44
55
|
<g class="sub-dataflow__step">
|
|
45
|
-
<
|
|
46
|
-
<text x="
|
|
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>
|
|
47
60
|
</g>
|
|
48
|
-
<line class="sub-dataflow__arrow" x1="
|
|
61
|
+
<line class="sub-dataflow__arrow" x1="340" y1="226" x2="340" y2="256" marker-end="url(#sub-arrow)" />
|
|
49
62
|
<g class="sub-dataflow__step">
|
|
50
|
-
<
|
|
51
|
-
<text x="
|
|
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>
|
|
52
67
|
</g>
|
|
53
68
|
</svg>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
54
71
|
</section>
|
|
55
72
|
<section class="sub-errors" aria-label="Errors">
|
|
56
73
|
<h2>Errors</h2>
|
|
@@ -62,5 +79,6 @@
|
|
|
62
79
|
</table>
|
|
63
80
|
</section>
|
|
64
81
|
</main>
|
|
82
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
65
83
|
</body>
|
|
66
84
|
</html>
|
|
@@ -33,28 +33,47 @@
|
|
|
33
33
|
</section>
|
|
34
34
|
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
35
35
|
<h2>Internal data flow</h2>
|
|
36
|
-
<
|
|
37
|
-
|
|
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>
|
|
38
47
|
<g class="sub-dataflow__step">
|
|
39
|
-
<
|
|
40
|
-
<text x="
|
|
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>
|
|
41
52
|
</g>
|
|
42
|
-
<line class="sub-dataflow__arrow" x1="
|
|
53
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
43
54
|
<g class="sub-dataflow__step">
|
|
44
|
-
<
|
|
45
|
-
<text x="
|
|
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>
|
|
46
59
|
</g>
|
|
47
|
-
<line class="sub-dataflow__arrow" x1="
|
|
60
|
+
<line class="sub-dataflow__arrow" x1="340" y1="226" x2="340" y2="256" marker-end="url(#sub-arrow)" />
|
|
48
61
|
<g class="sub-dataflow__step">
|
|
49
|
-
<
|
|
50
|
-
<text x="
|
|
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>
|
|
51
66
|
</g>
|
|
52
|
-
<line class="sub-dataflow__arrow" x1="
|
|
67
|
+
<line class="sub-dataflow__arrow" x1="340" y1="342" x2="340" y2="372" marker-end="url(#sub-arrow)" />
|
|
53
68
|
<g class="sub-dataflow__step">
|
|
54
|
-
<
|
|
55
|
-
<text x="
|
|
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>
|
|
56
73
|
</g>
|
|
57
74
|
</svg>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
58
77
|
</section>
|
|
59
78
|
<section class="sub-errors" aria-label="Errors">
|
|
60
79
|
<h2>Errors</h2>
|
|
@@ -66,5 +85,6 @@
|
|
|
66
85
|
</table>
|
|
67
86
|
</section>
|
|
68
87
|
</main>
|
|
88
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
69
89
|
</body>
|
|
70
90
|
</html>
|
|
@@ -34,23 +34,40 @@
|
|
|
34
34
|
</section>
|
|
35
35
|
<section class="sub-dataflow" aria-label="Internal data flow">
|
|
36
36
|
<h2>Internal data flow</h2>
|
|
37
|
-
<
|
|
38
|
-
|
|
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>
|
|
39
48
|
<g class="sub-dataflow__step">
|
|
40
|
-
<
|
|
41
|
-
<text x="
|
|
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">Read userId from auth context.</text>
|
|
42
53
|
</g>
|
|
43
|
-
<line class="sub-dataflow__arrow" x1="
|
|
54
|
+
<line class="sub-dataflow__arrow" x1="340" y1="110" x2="340" y2="140" marker-end="url(#sub-arrow)" />
|
|
44
55
|
<g class="sub-dataflow__step">
|
|
45
|
-
<
|
|
46
|
-
<text x="
|
|
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">POST /api/invites with userId.</text>
|
|
47
60
|
</g>
|
|
48
|
-
<line class="sub-dataflow__arrow" x1="
|
|
61
|
+
<line class="sub-dataflow__arrow" x1="340" y1="226" x2="340" y2="256" marker-end="url(#sub-arrow)" />
|
|
49
62
|
<g class="sub-dataflow__step">
|
|
50
|
-
<
|
|
51
|
-
<text x="
|
|
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">Render returned code or surface error.</text>
|
|
52
67
|
</g>
|
|
53
68
|
</svg>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
54
71
|
</section>
|
|
55
72
|
<section class="sub-errors" aria-label="Errors">
|
|
56
73
|
<h2>Errors</h2>
|
|
@@ -63,5 +80,6 @@
|
|
|
63
80
|
</table>
|
|
64
81
|
</section>
|
|
65
82
|
</main>
|
|
83
|
+
<script src="../../assets/viewer.client.js" defer></script>
|
|
66
84
|
</body>
|
|
67
85
|
</html>
|