unoverse 0.1.35 → 0.1.37
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/lib/create.mjs +58 -17
- package/operator/lib/db-verify.sh +1 -1
- package/operator/lib/init.sh +9 -1
- package/package.json +1 -1
package/lib/create.mjs
CHANGED
|
@@ -33,11 +33,22 @@ async function ask(rl, q) {
|
|
|
33
33
|
* credential gets refused, so detect it and pass it through untouched. */
|
|
34
34
|
/** The raw dop_v1 token, whichever shape was pasted. docker login needs the raw form,
|
|
35
35
|
* so the base64 user:token blob is decoded before anything downstream sees it. */
|
|
36
|
-
function rawToken(
|
|
37
|
-
|
|
36
|
+
function rawToken(input) {
|
|
37
|
+
// Whatever shape arrives, the dop_v1 token inside comes out:
|
|
38
|
+
// - the raw token
|
|
39
|
+
// - base64("token:token") (API-token docker auth)
|
|
40
|
+
// - base64(":token") (DO's READ-ONLY credential: EMPTY username —
|
|
41
|
+
// the shape the downloaded Docker Credentials file actually carries, and the one
|
|
42
|
+
// a required-username decoder silently passed through, so docker was handed the
|
|
43
|
+
// whole blob as a username and answered "unauthorized")
|
|
44
|
+
// - the whole credentials JSON pasted as-is
|
|
45
|
+
const token = input.trim().replace(/^["']|["']$/g, "");
|
|
46
|
+
const inline = /dop_v1_[0-9a-f]{64}/.exec(token);
|
|
47
|
+
if (inline) return inline[0];
|
|
48
|
+
if (/^[A-Za-z0-9+/]+=*$/.test(token)) {
|
|
38
49
|
const decoded = Buffer.from(token, "base64").toString("utf8");
|
|
39
|
-
const m = /^([\x20-\x7e]
|
|
40
|
-
if (m) return m[1];
|
|
50
|
+
const m = /^([\x20-\x7e]*):([\x20-\x7e]+)$/.exec(decoded);
|
|
51
|
+
if (m) return m[1] || m[2];
|
|
41
52
|
}
|
|
42
53
|
return token;
|
|
43
54
|
}
|
|
@@ -104,6 +115,24 @@ function resolveTarget(nameArg) {
|
|
|
104
115
|
/** Human name for the target, for messages that should not say "./.". */
|
|
105
116
|
const label = (dir) => (dir === "." ? "this folder" : `./${dir}`);
|
|
106
117
|
|
|
118
|
+
function dockerUp() {
|
|
119
|
+
return spawnSync("docker", ["info"], { stdio: "ignore" }).status === 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** The ONLY honest validation is the operation itself. create used to probe the auth
|
|
123
|
+
* realm with its own HTTP call and say "token accepted", then docker login failed on
|
|
124
|
+
* the same credential two minutes later — the tool approving a token with a weaker
|
|
125
|
+
* check than the one that counts. When Docker is up, validation IS docker login (and
|
|
126
|
+
* the credential lands in the keychain, so nothing downstream logs in again). */
|
|
127
|
+
function dockerLogin(token) {
|
|
128
|
+
const r = spawnSync("docker", ["login", REGISTRY_HOST, "-u", token, "--password-stdin"], {
|
|
129
|
+
input: token,
|
|
130
|
+
encoding: "utf8",
|
|
131
|
+
});
|
|
132
|
+
const err = (r.stderr || "").split("\n").filter((l) => l && !/^WARNING/i.test(l)).pop() || "";
|
|
133
|
+
return { ok: r.status === 0, err };
|
|
134
|
+
}
|
|
135
|
+
|
|
107
136
|
function download(dir, stripComponents = 1, filter = "") {
|
|
108
137
|
mkdirSync(dir, { recursive: true });
|
|
109
138
|
const r = spawnSync(
|
|
@@ -248,20 +277,32 @@ export async function create(nameArg) {
|
|
|
248
277
|
|
|
249
278
|
console.log(`\n ${cyan("A universe needs a registry access token.")}`);
|
|
250
279
|
console.log(` ${dim("It authorizes the platform's images. Your Unoverse admin issues it.")}\n`);
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
280
|
+
const useDocker = dockerUp();
|
|
281
|
+
let token;
|
|
282
|
+
// A refused token re-asks RIGHT HERE. Being thrown out of the wizard to run
|
|
283
|
+
// create again is its own bug.
|
|
284
|
+
for (;;) {
|
|
285
|
+
token = rawToken(await ask(rl, "Registry access token: "));
|
|
286
|
+
if (!token) {
|
|
287
|
+
fail("no token. The universe kit is available to licensed operators");
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
process.stdout.write(" validating against the registry...");
|
|
291
|
+
if (useDocker) {
|
|
292
|
+
const res = dockerLogin(token);
|
|
293
|
+
console.log("");
|
|
294
|
+
if (res.ok) { ok("token accepted"); break; }
|
|
295
|
+
fail("the registry refused it:");
|
|
296
|
+
console.log(` ${dim(res.err)}`);
|
|
297
|
+
console.log(` ${dim("Paste the credential exactly as your admin sent it (any shape works), or Ctrl-C to stop.")}\n`);
|
|
298
|
+
} else {
|
|
299
|
+
const valid = await validateRegistryToken(token);
|
|
300
|
+
console.log("");
|
|
301
|
+
if (valid) { ok("token accepted"); break; }
|
|
302
|
+
fail("that token was refused by the registry");
|
|
303
|
+
console.log(` ${dim("Check it with your Unoverse admin, or Ctrl-C to stop.")}\n`);
|
|
304
|
+
}
|
|
263
305
|
}
|
|
264
|
-
ok("token accepted");
|
|
265
306
|
|
|
266
307
|
download(name);
|
|
267
308
|
ok(`universe scaffolded in ${label(name)}`);
|
|
@@ -35,7 +35,7 @@ cmd_db_verify() {
|
|
|
35
35
|
workflows: [
|
|
36
36
|
"id", "name", "description", "nodes", "edges", "active",
|
|
37
37
|
"execution_mode", "test_inputs", "umap_settings", "viewport",
|
|
38
|
-
"mcp_schema", "memory_config", "created_at", "updated_at"
|
|
38
|
+
"mcp_schema", "memory_config", "content_taxonomy", "created_at", "updated_at"
|
|
39
39
|
],
|
|
40
40
|
workflow_executions: [
|
|
41
41
|
"execution_id", "workflow_id", "status", "start_time", "end_time",
|
package/operator/lib/init.sh
CHANGED
|
@@ -151,10 +151,18 @@ cmd_init() {
|
|
|
151
151
|
else
|
|
152
152
|
read -p " DOCR Token (from your Unoverse admin): " DOCR_TOKEN || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
|
|
153
153
|
fi
|
|
154
|
+
# Accept the credential in any shape: raw dop_v1, or the base64 blob from DO's
|
|
155
|
+
# downloaded Docker credentials (which does NOT start with dop_v1 — it wraps the
|
|
156
|
+
# token behind an empty username). Extract rather than lecture about the format.
|
|
157
|
+
if [[ "$DOCR_TOKEN" != dop_v1_* ]]; then
|
|
158
|
+
local decoded
|
|
159
|
+
decoded=$(printf '%s' "$DOCR_TOKEN" | base64 -d 2>/dev/null | tr -d '\0')
|
|
160
|
+
case "$decoded" in *dop_v1_*) DOCR_TOKEN="dop_v1_${decoded##*dop_v1_}";; esac
|
|
161
|
+
fi
|
|
154
162
|
if [[ "$DOCR_TOKEN" == dop_v1_* ]]; then
|
|
155
163
|
break
|
|
156
164
|
fi
|
|
157
|
-
fail "
|
|
165
|
+
fail "That does not look like a registry credential. Paste it exactly as it was sent"
|
|
158
166
|
done
|
|
159
167
|
fi
|
|
160
168
|
|
package/package.json
CHANGED