ultravisor 1.0.21 → 1.0.22
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/docs/_version.json +7 -0
- package/docs/css/docuserve.css +277 -23
- package/docs/features/beacon-authentication.md +24 -31
- package/docs/features/beacon-providers.md +31 -37
- package/docs/features/beacons.md +20 -19
- package/docs/features/case-study-retold-remote.md +28 -28
- package/docs/features/llm-model-setup.md +15 -15
- package/docs/features/llm.md +29 -27
- package/docs/features/platform-cards.md +10 -10
- package/docs/features/reachability-matrix.md +12 -12
- package/docs/features/tasks-content-system.md +32 -32
- package/docs/features/tasks-data-transform.md +64 -64
- package/docs/features/tasks-extension.md +14 -14
- package/docs/features/tasks-file-system.md +94 -94
- package/docs/features/tasks-flow-control.md +38 -38
- package/docs/features/tasks-http-client.md +40 -40
- package/docs/features/tasks-llm.md +58 -58
- package/docs/features/tasks-meadow-api.md +50 -50
- package/docs/features/tasks-user-interaction.md +12 -12
- package/docs/features/tasks.md +20 -20
- package/docs/features/universal-addressing.md +12 -12
- package/docs/index.html +2 -2
- package/docs/retold-catalog.json +30 -1
- package/docs/retold-keyword-index.json +15389 -12741
- package/package.json +4 -3
- package/source/services/Ultravisor-Beacon-Coordinator.cjs +39 -0
- package/source/services/Ultravisor-OperationAuditor.cjs +471 -0
- package/source/web_server/Ultravisor-API-Server.cjs +54 -0
package/docs/css/docuserve.css
CHANGED
|
@@ -1,73 +1,327 @@
|
|
|
1
1
|
/* ============================================================================
|
|
2
|
-
Pict Docuserve - Base Styles
|
|
2
|
+
Pict Docuserve - Base Styles & Theme Variables
|
|
3
3
|
============================================================================ */
|
|
4
4
|
|
|
5
|
-
/*
|
|
6
|
-
|
|
5
|
+
/* ----------------------------------------------------------------------------
|
|
6
|
+
Theme variables — light defaults on :root.
|
|
7
|
+
Dark mode applies when either:
|
|
8
|
+
(a) the user explicitly selected dark via <html data-theme="dark">
|
|
9
|
+
(b) the user hasn't chosen anything AND the system prefers dark
|
|
10
|
+
An explicit <html data-theme="light"> pins the light palette regardless.
|
|
11
|
+
---------------------------------------------------------------------------- */
|
|
12
|
+
|
|
13
|
+
:root
|
|
14
|
+
{
|
|
15
|
+
/* Surfaces */
|
|
16
|
+
--docuserve-bg: #FDFBF7;
|
|
17
|
+
--docuserve-bg-elevated: #FFFFFF;
|
|
18
|
+
--docuserve-border: #DDD6CA;
|
|
19
|
+
--docuserve-border-soft: #EAE3D8;
|
|
20
|
+
|
|
21
|
+
/* Text */
|
|
22
|
+
--docuserve-text: #2A241E;
|
|
23
|
+
--docuserve-text-strong: #3D3229;
|
|
24
|
+
--docuserve-text-muted: #5E5549;
|
|
25
|
+
--docuserve-text-dim: #8A7F72;
|
|
26
|
+
|
|
27
|
+
/* Accent / links */
|
|
28
|
+
--docuserve-accent: #2E7D74;
|
|
29
|
+
--docuserve-accent-hover: #236660;
|
|
30
|
+
|
|
31
|
+
/* Top bar */
|
|
32
|
+
--docuserve-topbar-bg: #3D3229;
|
|
33
|
+
--docuserve-topbar-text: #E8E0D4;
|
|
34
|
+
--docuserve-topbar-text-muted: #B5AA9A;
|
|
35
|
+
--docuserve-topbar-text-dim: #8A7F72;
|
|
36
|
+
--docuserve-topbar-hover-bg: #524438;
|
|
37
|
+
--docuserve-topbar-version-bg: rgba(255, 255, 255, 0.06);
|
|
38
|
+
--docuserve-topbar-version-border: rgba(255, 255, 255, 0.08);
|
|
39
|
+
--docuserve-topbar-version-text: #B5AA9A;
|
|
40
|
+
|
|
41
|
+
/* Sidebar */
|
|
42
|
+
--docuserve-sidebar-bg: #FAF7F1;
|
|
43
|
+
--docuserve-sidebar-border: #DDD6CA;
|
|
44
|
+
--docuserve-sidebar-border-soft: #E5DED1;
|
|
45
|
+
--docuserve-sidebar-text: #423D37;
|
|
46
|
+
--docuserve-sidebar-group-title: #3D3229;
|
|
47
|
+
--docuserve-sidebar-module-text: #5E5549;
|
|
48
|
+
--docuserve-sidebar-hover-bg: #EAE3D8;
|
|
49
|
+
--docuserve-sidebar-hover-text: #2E7D74;
|
|
50
|
+
--docuserve-sidebar-active-bg: #E5DED1;
|
|
51
|
+
--docuserve-sidebar-active-text: #2E7D74;
|
|
52
|
+
--docuserve-sidebar-search-bg: #FFFFFF;
|
|
53
|
+
--docuserve-sidebar-search-border: #DDD6CA;
|
|
54
|
+
|
|
55
|
+
/* Inline code */
|
|
56
|
+
--docuserve-inline-code-bg: #F0ECE4;
|
|
57
|
+
--docuserve-inline-code-text: #9E3A50;
|
|
58
|
+
|
|
59
|
+
/* Code block panel */
|
|
60
|
+
--docuserve-code-bg: #F6F3EE;
|
|
61
|
+
--docuserve-code-border: #E5DED1;
|
|
62
|
+
--docuserve-code-gutter-bg: #EFEAE0;
|
|
63
|
+
--docuserve-code-gutter-border: #DDD6CA;
|
|
64
|
+
--docuserve-code-gutter-text: #A59986;
|
|
65
|
+
--docuserve-code-text: #2A241E;
|
|
66
|
+
|
|
67
|
+
/* Syntax tokens — low-chroma dark-on-light palette */
|
|
68
|
+
--docuserve-tok-keyword: #A03472;
|
|
69
|
+
--docuserve-tok-string: #1A6640;
|
|
70
|
+
--docuserve-tok-number: #B25A00;
|
|
71
|
+
--docuserve-tok-comment: #8A7F72;
|
|
72
|
+
--docuserve-tok-operator: #2E7D74;
|
|
73
|
+
--docuserve-tok-punctuation: #2A241E;
|
|
74
|
+
--docuserve-tok-function: #2A5DB0;
|
|
75
|
+
--docuserve-tok-property: #9E3A50;
|
|
76
|
+
--docuserve-tok-tag: #9E3A50;
|
|
77
|
+
--docuserve-tok-attr-name: #B25A00;
|
|
78
|
+
--docuserve-tok-attr-value: #1A6640;
|
|
79
|
+
|
|
80
|
+
/* Tables, blockquotes, mermaid */
|
|
81
|
+
--docuserve-table-header-bg: #F5F0E8;
|
|
82
|
+
--docuserve-table-row-alt-bg: #F9F6F0;
|
|
83
|
+
--docuserve-blockquote-bg: #F7F5F0;
|
|
84
|
+
--docuserve-blockquote-border: #2E7D74;
|
|
85
|
+
--docuserve-blockquote-text: #5E5549;
|
|
86
|
+
--docuserve-mermaid-bg: #FFFFFF;
|
|
87
|
+
|
|
88
|
+
/* Scrollbars */
|
|
89
|
+
--docuserve-scrollbar-track: #F5F0E8;
|
|
90
|
+
--docuserve-scrollbar-thumb: #D4CCBE;
|
|
91
|
+
--docuserve-scrollbar-thumb-hover: #B5AA9A;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@media (prefers-color-scheme: dark)
|
|
95
|
+
{
|
|
96
|
+
:root:not([data-theme="light"])
|
|
97
|
+
{
|
|
98
|
+
--docuserve-bg: #15120F;
|
|
99
|
+
--docuserve-bg-elevated: #1B1814;
|
|
100
|
+
--docuserve-border: #2F2823;
|
|
101
|
+
--docuserve-border-soft: #26211C;
|
|
102
|
+
|
|
103
|
+
--docuserve-text: #E8E0D4;
|
|
104
|
+
--docuserve-text-strong: #F2ECE0;
|
|
105
|
+
--docuserve-text-muted: #B5AA9A;
|
|
106
|
+
--docuserve-text-dim: #7A6F62;
|
|
107
|
+
|
|
108
|
+
--docuserve-accent: #5DB8A8;
|
|
109
|
+
--docuserve-accent-hover: #7FCCB8;
|
|
110
|
+
|
|
111
|
+
--docuserve-topbar-bg: #1A1612;
|
|
112
|
+
--docuserve-topbar-text: #E8E0D4;
|
|
113
|
+
--docuserve-topbar-text-muted: #B5AA9A;
|
|
114
|
+
--docuserve-topbar-text-dim: #7A6F62;
|
|
115
|
+
--docuserve-topbar-hover-bg: #2A241E;
|
|
116
|
+
--docuserve-topbar-version-bg: rgba(255, 255, 255, 0.05);
|
|
117
|
+
--docuserve-topbar-version-border: rgba(255, 255, 255, 0.09);
|
|
118
|
+
--docuserve-topbar-version-text: #B5AA9A;
|
|
119
|
+
|
|
120
|
+
--docuserve-sidebar-bg: #1B1814;
|
|
121
|
+
--docuserve-sidebar-border: #2F2823;
|
|
122
|
+
--docuserve-sidebar-border-soft: #26211C;
|
|
123
|
+
--docuserve-sidebar-text: #C9C0B3;
|
|
124
|
+
--docuserve-sidebar-group-title: #F2ECE0;
|
|
125
|
+
--docuserve-sidebar-module-text: #B5AA9A;
|
|
126
|
+
--docuserve-sidebar-hover-bg: #2A241E;
|
|
127
|
+
--docuserve-sidebar-hover-text: #7FCCB8;
|
|
128
|
+
--docuserve-sidebar-active-bg: #2F2823;
|
|
129
|
+
--docuserve-sidebar-active-text: #7FCCB8;
|
|
130
|
+
--docuserve-sidebar-search-bg: #26211C;
|
|
131
|
+
--docuserve-sidebar-search-border: #2F2823;
|
|
132
|
+
|
|
133
|
+
--docuserve-inline-code-bg: #2A241E;
|
|
134
|
+
--docuserve-inline-code-text: #E8B07A;
|
|
135
|
+
|
|
136
|
+
--docuserve-code-bg: #1E1A17;
|
|
137
|
+
--docuserve-code-border: #2F2823;
|
|
138
|
+
--docuserve-code-gutter-bg: #17130F;
|
|
139
|
+
--docuserve-code-gutter-border: #2F2823;
|
|
140
|
+
--docuserve-code-gutter-text: #6A6052;
|
|
141
|
+
--docuserve-code-text: #E8E0D4;
|
|
142
|
+
|
|
143
|
+
--docuserve-tok-keyword: #C678DD;
|
|
144
|
+
--docuserve-tok-string: #98C379;
|
|
145
|
+
--docuserve-tok-number: #D19A66;
|
|
146
|
+
--docuserve-tok-comment: #7F848E;
|
|
147
|
+
--docuserve-tok-operator: #56B6C2;
|
|
148
|
+
--docuserve-tok-punctuation: #E8E0D4;
|
|
149
|
+
--docuserve-tok-function: #61AFEF;
|
|
150
|
+
--docuserve-tok-property: #E06C75;
|
|
151
|
+
--docuserve-tok-tag: #E06C75;
|
|
152
|
+
--docuserve-tok-attr-name: #D19A66;
|
|
153
|
+
--docuserve-tok-attr-value: #98C379;
|
|
154
|
+
|
|
155
|
+
--docuserve-table-header-bg: #26211C;
|
|
156
|
+
--docuserve-table-row-alt-bg: #1F1B17;
|
|
157
|
+
--docuserve-blockquote-bg: #1F1B17;
|
|
158
|
+
--docuserve-blockquote-border: #5DB8A8;
|
|
159
|
+
--docuserve-blockquote-text: #C9C0B3;
|
|
160
|
+
--docuserve-mermaid-bg: #E8E0D4;
|
|
161
|
+
|
|
162
|
+
--docuserve-scrollbar-track: #1B1814;
|
|
163
|
+
--docuserve-scrollbar-thumb: #3A322B;
|
|
164
|
+
--docuserve-scrollbar-thumb-hover: #524438;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
:root[data-theme="dark"]
|
|
169
|
+
{
|
|
170
|
+
--docuserve-bg: #15120F;
|
|
171
|
+
--docuserve-bg-elevated: #1B1814;
|
|
172
|
+
--docuserve-border: #2F2823;
|
|
173
|
+
--docuserve-border-soft: #26211C;
|
|
174
|
+
|
|
175
|
+
--docuserve-text: #E8E0D4;
|
|
176
|
+
--docuserve-text-strong: #F2ECE0;
|
|
177
|
+
--docuserve-text-muted: #B5AA9A;
|
|
178
|
+
--docuserve-text-dim: #7A6F62;
|
|
179
|
+
|
|
180
|
+
--docuserve-accent: #5DB8A8;
|
|
181
|
+
--docuserve-accent-hover: #7FCCB8;
|
|
182
|
+
|
|
183
|
+
--docuserve-topbar-bg: #1A1612;
|
|
184
|
+
--docuserve-topbar-text: #E8E0D4;
|
|
185
|
+
--docuserve-topbar-text-muted: #B5AA9A;
|
|
186
|
+
--docuserve-topbar-text-dim: #7A6F62;
|
|
187
|
+
--docuserve-topbar-hover-bg: #2A241E;
|
|
188
|
+
--docuserve-topbar-version-bg: rgba(255, 255, 255, 0.05);
|
|
189
|
+
--docuserve-topbar-version-border: rgba(255, 255, 255, 0.09);
|
|
190
|
+
--docuserve-topbar-version-text: #B5AA9A;
|
|
191
|
+
|
|
192
|
+
--docuserve-sidebar-bg: #1B1814;
|
|
193
|
+
--docuserve-sidebar-border: #2F2823;
|
|
194
|
+
--docuserve-sidebar-border-soft: #26211C;
|
|
195
|
+
--docuserve-sidebar-text: #C9C0B3;
|
|
196
|
+
--docuserve-sidebar-group-title: #F2ECE0;
|
|
197
|
+
--docuserve-sidebar-module-text: #B5AA9A;
|
|
198
|
+
--docuserve-sidebar-hover-bg: #2A241E;
|
|
199
|
+
--docuserve-sidebar-hover-text: #7FCCB8;
|
|
200
|
+
--docuserve-sidebar-active-bg: #2F2823;
|
|
201
|
+
--docuserve-sidebar-active-text: #7FCCB8;
|
|
202
|
+
--docuserve-sidebar-search-bg: #26211C;
|
|
203
|
+
--docuserve-sidebar-search-border: #2F2823;
|
|
204
|
+
|
|
205
|
+
--docuserve-inline-code-bg: #2A241E;
|
|
206
|
+
--docuserve-inline-code-text: #E8B07A;
|
|
207
|
+
|
|
208
|
+
--docuserve-code-bg: #1E1A17;
|
|
209
|
+
--docuserve-code-border: #2F2823;
|
|
210
|
+
--docuserve-code-gutter-bg: #17130F;
|
|
211
|
+
--docuserve-code-gutter-border: #2F2823;
|
|
212
|
+
--docuserve-code-gutter-text: #6A6052;
|
|
213
|
+
--docuserve-code-text: #E8E0D4;
|
|
214
|
+
|
|
215
|
+
--docuserve-tok-keyword: #C678DD;
|
|
216
|
+
--docuserve-tok-string: #98C379;
|
|
217
|
+
--docuserve-tok-number: #D19A66;
|
|
218
|
+
--docuserve-tok-comment: #7F848E;
|
|
219
|
+
--docuserve-tok-operator: #56B6C2;
|
|
220
|
+
--docuserve-tok-punctuation: #E8E0D4;
|
|
221
|
+
--docuserve-tok-function: #61AFEF;
|
|
222
|
+
--docuserve-tok-property: #E06C75;
|
|
223
|
+
--docuserve-tok-tag: #E06C75;
|
|
224
|
+
--docuserve-tok-attr-name: #D19A66;
|
|
225
|
+
--docuserve-tok-attr-value: #98C379;
|
|
226
|
+
|
|
227
|
+
--docuserve-table-header-bg: #26211C;
|
|
228
|
+
--docuserve-table-row-alt-bg: #1F1B17;
|
|
229
|
+
--docuserve-blockquote-bg: #1F1B17;
|
|
230
|
+
--docuserve-blockquote-border: #5DB8A8;
|
|
231
|
+
--docuserve-blockquote-text: #C9C0B3;
|
|
232
|
+
--docuserve-mermaid-bg: #E8E0D4;
|
|
233
|
+
|
|
234
|
+
--docuserve-scrollbar-track: #1B1814;
|
|
235
|
+
--docuserve-scrollbar-thumb: #3A322B;
|
|
236
|
+
--docuserve-scrollbar-thumb-hover: #524438;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* ----------------------------------------------------------------------------
|
|
240
|
+
Reset and base
|
|
241
|
+
---------------------------------------------------------------------------- */
|
|
242
|
+
|
|
243
|
+
*, *::before, *::after
|
|
244
|
+
{
|
|
7
245
|
box-sizing: border-box;
|
|
8
246
|
}
|
|
9
247
|
|
|
10
|
-
html, body
|
|
248
|
+
html, body
|
|
249
|
+
{
|
|
11
250
|
margin: 0;
|
|
12
251
|
padding: 0;
|
|
13
252
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
14
253
|
font-size: 16px;
|
|
15
254
|
line-height: 1.5;
|
|
16
|
-
color:
|
|
17
|
-
background-color:
|
|
255
|
+
color: var(--docuserve-text);
|
|
256
|
+
background-color: var(--docuserve-bg);
|
|
18
257
|
-webkit-font-smoothing: antialiased;
|
|
19
258
|
-moz-osx-font-smoothing: grayscale;
|
|
259
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
20
260
|
}
|
|
21
261
|
|
|
22
262
|
/* Typography */
|
|
23
|
-
h1, h2, h3, h4, h5, h6
|
|
263
|
+
h1, h2, h3, h4, h5, h6
|
|
264
|
+
{
|
|
24
265
|
margin-top: 0;
|
|
25
266
|
line-height: 1.3;
|
|
267
|
+
color: var(--docuserve-text-strong);
|
|
26
268
|
}
|
|
27
269
|
|
|
28
|
-
a
|
|
29
|
-
|
|
270
|
+
a
|
|
271
|
+
{
|
|
272
|
+
color: var(--docuserve-accent);
|
|
30
273
|
text-decoration: none;
|
|
31
274
|
}
|
|
32
275
|
|
|
33
|
-
a:hover
|
|
34
|
-
|
|
276
|
+
a:hover
|
|
277
|
+
{
|
|
278
|
+
color: var(--docuserve-accent-hover);
|
|
35
279
|
}
|
|
36
280
|
|
|
37
281
|
/* Application container */
|
|
38
|
-
#Docuserve-Application-Container
|
|
282
|
+
#Docuserve-Application-Container
|
|
283
|
+
{
|
|
39
284
|
min-height: 100vh;
|
|
40
285
|
}
|
|
41
286
|
|
|
42
287
|
/* Utility: scrollbar styling */
|
|
43
|
-
::-webkit-scrollbar
|
|
288
|
+
::-webkit-scrollbar
|
|
289
|
+
{
|
|
44
290
|
width: 8px;
|
|
291
|
+
height: 8px;
|
|
45
292
|
}
|
|
46
293
|
|
|
47
|
-
::-webkit-scrollbar-track
|
|
48
|
-
|
|
294
|
+
::-webkit-scrollbar-track
|
|
295
|
+
{
|
|
296
|
+
background: var(--docuserve-scrollbar-track);
|
|
49
297
|
}
|
|
50
298
|
|
|
51
|
-
::-webkit-scrollbar-thumb
|
|
52
|
-
|
|
299
|
+
::-webkit-scrollbar-thumb
|
|
300
|
+
{
|
|
301
|
+
background: var(--docuserve-scrollbar-thumb);
|
|
53
302
|
border-radius: 4px;
|
|
54
303
|
}
|
|
55
304
|
|
|
56
|
-
::-webkit-scrollbar-thumb:hover
|
|
57
|
-
|
|
305
|
+
::-webkit-scrollbar-thumb:hover
|
|
306
|
+
{
|
|
307
|
+
background: var(--docuserve-scrollbar-thumb-hover);
|
|
58
308
|
}
|
|
59
309
|
|
|
60
310
|
/* Responsive adjustments */
|
|
61
|
-
@media (max-width: 768px)
|
|
62
|
-
|
|
311
|
+
@media (max-width: 768px)
|
|
312
|
+
{
|
|
313
|
+
html
|
|
314
|
+
{
|
|
63
315
|
font-size: 14px;
|
|
64
316
|
}
|
|
65
317
|
|
|
66
|
-
#Docuserve-Sidebar-Container
|
|
318
|
+
#Docuserve-Sidebar-Container
|
|
319
|
+
{
|
|
67
320
|
display: none;
|
|
68
321
|
}
|
|
69
322
|
|
|
70
|
-
.docuserve-body
|
|
323
|
+
.docuserve-body
|
|
324
|
+
{
|
|
71
325
|
flex-direction: column;
|
|
72
326
|
}
|
|
73
327
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
Ultravisor uses Orator Authentication to manage beacon identity and connectivity. Beacons authenticate with the server before registering, receive a session cookie, and use it on all subsequent requests. If a session expires or the server restarts, beacons automatically re-authenticate and re-register
|
|
5
|
+
Ultravisor uses Orator Authentication to manage beacon identity and connectivity. Beacons authenticate with the server before registering, receive a session cookie, and use it on all subsequent requests. If a session expires or the server restarts, beacons automatically re-authenticate and re-register -- eliminating "unknown beacon" errors and providing graceful reconnection.
|
|
6
6
|
|
|
7
7
|
## Architecture
|
|
8
8
|
|
|
@@ -10,28 +10,21 @@ Ultravisor uses Orator Authentication to manage beacon identity and connectivity
|
|
|
10
10
|
|
|
11
11
|
Rather than a custom identity scheme, beacons use Orator's cookie-based session system:
|
|
12
12
|
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
│ │
|
|
29
|
-
│ POST /Beacon/Work/Poll │
|
|
30
|
-
│ Cookie: SessionID=<uuid> │ (every 5s)
|
|
31
|
-
│───────────────────────────────────────▸ │
|
|
32
|
-
│ │ Validate session → OK
|
|
33
|
-
│ ◂─── 200 { WorkItem } or null │
|
|
34
|
-
│ │
|
|
13
|
+
```mermaid
|
|
14
|
+
sequenceDiagram
|
|
15
|
+
participant BC as Beacon Client
|
|
16
|
+
participant UV as Ultravisor Server
|
|
17
|
+
BC->>UV: POST /1.0/Authenticate<br/>{ UserName: "gpu-worker-1" }
|
|
18
|
+
Note right of UV: Create session
|
|
19
|
+
UV-->>BC: 200 { LoggedIn: true }<br/>Set-Cookie: SessionID
|
|
20
|
+
BC->>UV: POST /Beacon/Register<br/>Cookie: SessionID<br/>{ Capabilities, MaxConcurrent, Tags }
|
|
21
|
+
Note right of UV: Create/reclaim beacon record<br/>Associate with session
|
|
22
|
+
UV-->>BC: 200 { BeaconID: "bcn-..." }
|
|
23
|
+
loop Every 5s
|
|
24
|
+
BC->>UV: POST /Beacon/Work/Poll<br/>Cookie: SessionID
|
|
25
|
+
Note right of UV: Validate session
|
|
26
|
+
UV-->>BC: 200 { WorkItem } or null
|
|
27
|
+
end
|
|
35
28
|
```
|
|
36
29
|
|
|
37
30
|
### Separation of Concerns
|
|
@@ -118,10 +111,10 @@ node Ultravisor-Beacon-CLI.cjs --password <password>
|
|
|
118
111
|
|
|
119
112
|
The system is designed for incremental security hardening:
|
|
120
113
|
|
|
121
|
-
**Level 0
|
|
114
|
+
**Level 0 -- Open (default):**
|
|
122
115
|
No credentials required. Any beacon name is accepted. Suitable for development and trusted networks.
|
|
123
116
|
|
|
124
|
-
**Level 1
|
|
117
|
+
**Level 1 -- Shared secret:**
|
|
125
118
|
Set a custom authenticator that checks passwords against a configured secret or API key list:
|
|
126
119
|
|
|
127
120
|
```javascript
|
|
@@ -135,7 +128,7 @@ tmpAuth.setAuthenticator((pUsername, pPassword, fCallback) =>
|
|
|
135
128
|
});
|
|
136
129
|
```
|
|
137
130
|
|
|
138
|
-
**Level 2
|
|
131
|
+
**Level 2 -- Per-beacon credentials:**
|
|
139
132
|
Validate each beacon's name and password against a database or config:
|
|
140
133
|
|
|
141
134
|
```javascript
|
|
@@ -151,7 +144,7 @@ tmpAuth.setAuthenticator((pUsername, pPassword, fCallback) =>
|
|
|
151
144
|
});
|
|
152
145
|
```
|
|
153
146
|
|
|
154
|
-
**Level 3
|
|
147
|
+
**Level 3 -- OAuth/OIDC:**
|
|
155
148
|
For beacons on remote networks, use Orator Authentication's built-in OIDC provider to authenticate against an identity provider (Azure AD, Okta, etc.).
|
|
156
149
|
|
|
157
150
|
## HTTP Endpoints
|
|
@@ -195,10 +188,10 @@ For beacons on remote networks, use Orator Authentication's built-in OIDC provid
|
|
|
195
188
|
|
|
196
189
|
### Session Lifecycle
|
|
197
190
|
|
|
198
|
-
1. **Creation:** Beacon POSTs to `/1.0/Authenticate`
|
|
199
|
-
2. **Validation:** Every beacon request
|
|
200
|
-
3. **Expiry:** Session TTL exceeded (default 24h)
|
|
201
|
-
4. **Server restart:** All sessions lost (in-memory)
|
|
191
|
+
1. **Creation:** Beacon POSTs to `/1.0/Authenticate` -> session created in-memory Map -> `Set-Cookie` header returned
|
|
192
|
+
2. **Validation:** Every beacon request -> `getSessionForRequest()` parses cookie, looks up session, checks TTL, updates `LastAccess`
|
|
193
|
+
3. **Expiry:** Session TTL exceeded (default 24h) -> next request returns 401 -> beacon reconnects
|
|
194
|
+
4. **Server restart:** All sessions lost (in-memory) -> all beacons get 401 -> all reconnect automatically
|
|
202
195
|
|
|
203
196
|
### Timeout Interactions
|
|
204
197
|
|
|
@@ -92,26 +92,20 @@ cd /path/to/config && node /path/to/Ultravisor-Beacon-CLI.cjs
|
|
|
92
92
|
## Anatomy of a Provider
|
|
93
93
|
|
|
94
94
|
Every provider is a plain JavaScript class that extends
|
|
95
|
-
`UltravisorBeaconCapabilityProvider`. There is no Fable dependency
|
|
95
|
+
`UltravisorBeaconCapabilityProvider`. There is no Fable dependency -- keep
|
|
96
96
|
providers lightweight and self-contained.
|
|
97
97
|
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
│ │
|
|
110
|
-
│ execute(pAction, pWorkItem, pContext, │
|
|
111
|
-
│ fCallback, fReportProgress) │
|
|
112
|
-
│ │
|
|
113
|
-
│ _ProviderConfig ← per-provider cfg │
|
|
114
|
-
└──────────────────────────────────────────┘
|
|
98
|
+
```mermaid
|
|
99
|
+
classDiagram
|
|
100
|
+
class CapabilityProvider {
|
|
101
|
+
+String Name = "MyProvider"
|
|
102
|
+
+String Capability = "SomeCapability"
|
|
103
|
+
+Object _ProviderConfig
|
|
104
|
+
+get actions() Map~String, Action~
|
|
105
|
+
+initialize(fCallback) optional
|
|
106
|
+
+shutdown(fCallback) optional
|
|
107
|
+
+execute(pAction, pWorkItem, pContext, fCallback, fReportProgress)
|
|
108
|
+
}
|
|
115
109
|
```
|
|
116
110
|
|
|
117
111
|
### The `execute` Contract
|
|
@@ -693,10 +687,10 @@ class FFmpegTranscodeProvider extends libBeaconCapabilityProvider
|
|
|
693
687
|
this._FFmpegPath = this._ProviderConfig.FFmpegPath || 'ffmpeg';
|
|
694
688
|
this._FFprobePath = this._ProviderConfig.FFprobePath || 'ffprobe';
|
|
695
689
|
|
|
696
|
-
// Preset library
|
|
690
|
+
// Preset library -- each preset is an array of FFmpeg arguments
|
|
697
691
|
this._Presets =
|
|
698
692
|
{
|
|
699
|
-
// H.264 + AAC in MP4
|
|
693
|
+
// H.264 + AAC in MP4 -- plays in all modern browsers
|
|
700
694
|
'browser-mp4':
|
|
701
695
|
[
|
|
702
696
|
'-c:v', 'libx264',
|
|
@@ -708,7 +702,7 @@ class FFmpegTranscodeProvider extends libBeaconCapabilityProvider
|
|
|
708
702
|
'-pix_fmt', 'yuv420p' // broad compatibility
|
|
709
703
|
],
|
|
710
704
|
|
|
711
|
-
// VP9 + Opus in WebM
|
|
705
|
+
// VP9 + Opus in WebM -- smaller files, good for web
|
|
712
706
|
'browser-webm':
|
|
713
707
|
[
|
|
714
708
|
'-c:v', 'libvpx-vp9',
|
|
@@ -718,7 +712,7 @@ class FFmpegTranscodeProvider extends libBeaconCapabilityProvider
|
|
|
718
712
|
'-b:a', '96k'
|
|
719
713
|
],
|
|
720
714
|
|
|
721
|
-
// H.264 Low
|
|
715
|
+
// H.264 Low -- mobile-friendly, small file
|
|
722
716
|
'browser-mobile':
|
|
723
717
|
[
|
|
724
718
|
'-c:v', 'libx264',
|
|
@@ -731,14 +725,14 @@ class FFmpegTranscodeProvider extends libBeaconCapabilityProvider
|
|
|
731
725
|
'-pix_fmt', 'yuv420p'
|
|
732
726
|
],
|
|
733
727
|
|
|
734
|
-
// Thumbnail extraction
|
|
728
|
+
// Thumbnail extraction -- single frame to JPEG
|
|
735
729
|
'thumbnail':
|
|
736
730
|
[
|
|
737
731
|
'-vframes', '1',
|
|
738
732
|
'-q:v', '2'
|
|
739
733
|
],
|
|
740
734
|
|
|
741
|
-
// Audio extraction
|
|
735
|
+
// Audio extraction -- AAC in M4A container
|
|
742
736
|
'audio-only':
|
|
743
737
|
[
|
|
744
738
|
'-vn',
|
|
@@ -787,7 +781,7 @@ class FFmpegTranscodeProvider extends libBeaconCapabilityProvider
|
|
|
787
781
|
}
|
|
788
782
|
|
|
789
783
|
// -------------------------------------------------------------------
|
|
790
|
-
// Lifecycle
|
|
784
|
+
// Lifecycle -- validate FFmpeg is installed
|
|
791
785
|
// -------------------------------------------------------------------
|
|
792
786
|
|
|
793
787
|
initialize(fCallback)
|
|
@@ -987,7 +981,7 @@ class FFmpegTranscodeProvider extends libBeaconCapabilityProvider
|
|
|
987
981
|
}
|
|
988
982
|
|
|
989
983
|
// -------------------------------------------------------------------
|
|
990
|
-
// Probe
|
|
984
|
+
// Probe -- return media metadata as JSON
|
|
991
985
|
// -------------------------------------------------------------------
|
|
992
986
|
|
|
993
987
|
_executeProbe(pWorkItem, pContext, fCallback, fReportProgress)
|
|
@@ -1163,7 +1157,7 @@ Probe file metadata before deciding how to transcode:
|
|
|
1163
1157
|
### Full Pipeline Manifest
|
|
1164
1158
|
|
|
1165
1159
|
A complete manifest that probes a file, then transcodes it into browser-MP4,
|
|
1166
|
-
mobile-MP4, and thumbnail
|
|
1160
|
+
mobile-MP4, and thumbnail -- distributed across media workers:
|
|
1167
1161
|
|
|
1168
1162
|
```json
|
|
1169
1163
|
{
|
|
@@ -1272,28 +1266,28 @@ up the first task. This avoids copying the source file across workers.
|
|
|
1272
1266
|
|
|
1273
1267
|
Use this as a reference when building your own provider:
|
|
1274
1268
|
|
|
1275
|
-
- [ ] **Extend `CapabilityProvider`**
|
|
1269
|
+
- [ ] **Extend `CapabilityProvider`** -- set `Name` and `Capability` in the
|
|
1276
1270
|
constructor.
|
|
1277
|
-
- [ ] **Declare actions**
|
|
1271
|
+
- [ ] **Declare actions** -- implement `get actions()` returning the action
|
|
1278
1272
|
map. Each action should have a `Description` and optionally a
|
|
1279
1273
|
`SettingsSchema` array.
|
|
1280
|
-
- [ ] **Implement `execute`**
|
|
1274
|
+
- [ ] **Implement `execute`** -- dispatch on `pAction`, read from
|
|
1281
1275
|
`pWorkItem.Settings`, resolve paths against `pContext.StagingPath`, call
|
|
1282
1276
|
`fCallback` when done.
|
|
1283
|
-
- [ ] **Return structured results**
|
|
1277
|
+
- [ ] **Return structured results** -- always include `Outputs.ExitCode`
|
|
1284
1278
|
(0 = success), `Outputs.StdOut` (summary), and `Outputs.Result` (data).
|
|
1285
|
-
- [ ] **Use `fReportProgress`**
|
|
1279
|
+
- [ ] **Use `fReportProgress`** -- for any operation that takes more than a
|
|
1286
1280
|
few seconds, report progress so the orchestrator can track it.
|
|
1287
|
-
- [ ] **Implement `initialize`**
|
|
1281
|
+
- [ ] **Implement `initialize`** -- validate prerequisites (is the binary
|
|
1288
1282
|
installed? can we connect to the service?). Return an error to prevent
|
|
1289
1283
|
the Beacon from starting if the provider cannot function.
|
|
1290
|
-
- [ ] **Implement `shutdown`**
|
|
1284
|
+
- [ ] **Implement `shutdown`** -- release resources (close browser, disconnect
|
|
1291
1285
|
from service, clean up temp files).
|
|
1292
|
-
- [ ] **Handle errors gracefully**
|
|
1286
|
+
- [ ] **Handle errors gracefully** -- catch exceptions and return them as
|
|
1293
1287
|
`ExitCode: 1` results rather than throwing. The Beacon must stay alive
|
|
1294
1288
|
even if individual work items fail.
|
|
1295
|
-
- [ ] **Resolve paths**
|
|
1289
|
+
- [ ] **Resolve paths** -- use `pContext.StagingPath` to resolve relative file
|
|
1296
1290
|
paths. This keeps file operations predictable across machines.
|
|
1297
|
-
- [ ] **Guard external access**
|
|
1291
|
+
- [ ] **Guard external access** -- if the provider makes network requests or
|
|
1298
1292
|
accesses the filesystem, add configuration to restrict what it can reach
|
|
1299
1293
|
(e.g. `AllowedDomains`, `AllowedPaths`).
|