total-recall-brain 3.41.1 → 3.41.2

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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +10 -0
  3. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +1456 -12
  4. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +4 -4
  5. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +1 -1
  6. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +210 -27
  7. package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-catalog.mjs +10 -1
  8. package/scaffold/.agent/skills/total-recall/plugins/auth/src/rotation-capability.mjs +15 -0
  9. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-env-export.mjs +78 -6
  10. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-merge.mjs +131 -0
  11. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-remote-deploy.mjs +111 -2
  12. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +26 -5
  13. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +4 -4
  14. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +4 -4
  15. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +4 -4
  16. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +4 -4
  17. package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +10 -0
  18. package/scaffold/.agent/skills/total-recall/plugins/mesh/{src/core/headscale-server.mjs → capability/control-server.mjs} +5 -2
  19. package/scaffold/.agent/skills/total-recall/plugins/mesh/capability/headscale-api.mjs +192 -0
  20. package/scaffold/.agent/skills/total-recall/plugins/mesh/capability/index.mjs +46 -0
  21. package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -1
  22. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +23 -22
  23. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +6 -3
  24. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +242 -8
  25. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +14 -9
  26. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/server.mjs +1 -1
  27. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/credentials.mjs +4 -2
  28. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/headscale-client.mjs +34 -181
  29. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-auth.mjs +2 -2
  30. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/presence.mjs +5 -5
  31. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/screen-view.mjs +78 -0
  32. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +211 -12
  33. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/card.js +323 -388
  34. package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +12 -1
  35. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +7 -4
  36. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +6 -6
  37. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +3 -2
  38. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +34 -1
  39. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/bootstrap.mjs +99 -0
  40. package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/README.md +10 -0
  41. package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/architecture.md +5 -0
  42. package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/ide.md +10 -0
  43. package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/memory.md +11 -0
  44. package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/secrets.md +7 -0
  45. package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/skills.md +7 -0
  46. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +4 -4
  47. package/scaffold/.agent/skills/total-recall/references/auth.md +2 -0
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Mesh control-server capability: the developer's own Headscale, host-free.
3
+ *
4
+ * A project that vendors this brick provisions, updates and administers its
5
+ * own control server without Total Recall. The caller supplies the target host,
6
+ * and may inject the command runner (`exec`), the release lookups and the HTTP
7
+ * transport; the defaults use only Node built-ins (`ssh` through
8
+ * child_process, global `fetch`). Credentials are never read from a store or
9
+ * the environment here: provisioning returns the new API key to the caller,
10
+ * and the API client takes the key as an argument.
11
+ */
12
+ import {
13
+ meshTargetOf,
14
+ sshExec,
15
+ provisionHeadscale,
16
+ updateHeadscale,
17
+ installConsole,
18
+ updateConsole,
19
+ } from './control-server.mjs';
20
+
21
+ export { meshTargetOf, sshExec, shellQuote, patchConfig, parseChecksum, consoleConfig } from './control-server.mjs';
22
+ export { createHeadscaleApi, buildMeshSshPolicy, assertSecureControlUrl, normalizeControlUrl } from './headscale-api.mjs';
23
+
24
+ /**
25
+ * Bind the control-server lifecycle to one host.
26
+ * @param {{ target: { name?: string, host: string, user: string, port?: number, domain: string },
27
+ * exec?: Function, fetchJson?: Function, fetchText?: Function, checkDns?: Function,
28
+ * log?: Function, wait?: Function }} options
29
+ */
30
+ export function createControlServer({ target, exec, ...deps } = {}) {
31
+ const resolved = meshTargetOf({ name: target?.name, ssh: { host: target?.host, user: target?.user, port: target?.port }, domain: target?.domain });
32
+ if (!resolved) throw new Error('A control-server target needs a valid SSH host, SSH user and a public domain pointing at that host');
33
+ const run = exec || sshExec(resolved);
34
+ const shared = Object.fromEntries(Object.entries(deps).filter(([, v]) => v !== undefined));
35
+ return {
36
+ target: resolved,
37
+ /** Install Headscale on a fresh Debian 12+/Ubuntu 22.04+ host; returns the control URL, API key and a 1-hour pre-auth key. */
38
+ provision: (opts = {}) => provisionHeadscale(resolved, { ...shared, ...opts, exec: run }),
39
+ /** Stage, trial, switch and roll back to the latest release; `checkOnly` reports without changing anything. */
40
+ update: (opts = {}) => updateHeadscale(resolved, { ...shared, ...opts, exec: run }),
41
+ /** Install the optional Headplane console, bound to loopback. */
42
+ installConsole: (opts = {}) => installConsole(resolved, { ...shared, ...opts, exec: run }),
43
+ /** Move the console to the latest release, restoring the previous image on failure. */
44
+ updateConsole: (opts = {}) => updateConsole(resolved, { ...shared, ...opts, exec: run }),
45
+ };
46
+ }
@@ -18,7 +18,15 @@ export async function run(argv = []) {
18
18
  const at=args.indexOf('--mode');const mode=at<0?0o600:Number.parseInt(args[at+1],8);
19
19
  console.log(JSON.stringify(await putMeshFile({node:args[2],source:args[3],destination:args[4],mode})));return;
20
20
  }
21
- if (sub === 'status' || sub === 'view' || sub === 'probe') {
21
+ if (sub === 'view') {
22
+ const { readMeshView } = await import('./src/core/screen-view.mjs');
23
+ if (args.slice(1).some(arg => arg.startsWith('-') && arg !== '--json')) throw new Error('view accepts a screen and --json only');
24
+ const names = args.slice(1).filter(arg => arg !== '--json');
25
+ if (names.length > 1) throw new Error('view accepts one screen');
26
+ console.log(JSON.stringify(await readMeshView(names[0])));
27
+ return;
28
+ }
29
+ if (sub === 'status' || sub === 'probe') {
22
30
  const result = await meshStatus();
23
31
  console.log(JSON.stringify(result));
24
32
  if (sub === 'probe' && !result.control.verified) process.exitCode = 1;
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "tr-plugin-mesh",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "tr-plugin-mesh",
9
- "version": "0.2.2",
9
+ "version": "0.2.4",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "express": "^5.2.1"
13
13
  },
14
14
  "devDependencies": {
15
15
  "jsdom": "^29.1.1",
16
- "supertest": "^7.2.2",
17
- "total-recall-brain": "3.40.1",
18
- "vitest": "^4.1.11"
16
+ "supertest": "^7.3.1",
17
+ "total-recall-brain": "3.41.1",
18
+ "vitest": "^4.1.12"
19
19
  }
20
20
  },
21
21
  "node_modules/@asamuzakjp/css-color": {
@@ -1259,18 +1259,18 @@
1259
1259
  }
1260
1260
  },
1261
1261
  "node_modules/body-parser": {
1262
- "version": "2.3.0",
1263
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
1264
- "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==",
1262
+ "version": "2.4.0",
1263
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.4.0.tgz",
1264
+ "integrity": "sha512-Ifk1KcLrxaGt1occQagQNFNNOqRt1LFuehEnHHzB8Z6cRgIxRU1TBaiIsUiCdA+gy5PL7Y1IX31DNKkRmxtXjQ==",
1265
1265
  "license": "MIT",
1266
1266
  "dependencies": {
1267
1267
  "bytes": "^3.1.2",
1268
- "content-type": "^2.0.0",
1268
+ "content-type": "^2.1.0",
1269
1269
  "debug": "^4.4.3",
1270
1270
  "http-errors": "^2.0.1",
1271
- "iconv-lite": "^0.7.2",
1271
+ "iconv-lite": "^0.7.3",
1272
1272
  "on-finished": "^2.4.1",
1273
- "qs": "^6.15.2",
1273
+ "qs": "^6.16.1",
1274
1274
  "raw-body": "^3.0.2",
1275
1275
  "type-is": "^2.1.0"
1276
1276
  },
@@ -4187,22 +4187,22 @@
4187
4187
  }
4188
4188
  },
4189
4189
  "node_modules/tldts": {
4190
- "version": "7.4.18",
4191
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.18.tgz",
4192
- "integrity": "sha512-somxA8xKAUzlAxl0TX/jMSYIbRNFIVGnI96pVGJPeMc5BsHmfVXn6mOJT6U++ELnl04eGfzpfcEuZe8WiASkXg==",
4190
+ "version": "7.4.19",
4191
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.19.tgz",
4192
+ "integrity": "sha512-48dH6aSpQnpbzDUc4vIQZ1VjB8tkK+e8c1yx05/SZK+rkssgjEOlxDd/yU8/a4vGYQ9vRgJr9dwMq9TJ0b3X2Q==",
4193
4193
  "dev": true,
4194
4194
  "license": "MIT",
4195
4195
  "dependencies": {
4196
- "tldts-core": "^7.4.18"
4196
+ "tldts-core": "^7.4.19"
4197
4197
  },
4198
4198
  "bin": {
4199
4199
  "tldts": "bin/cli.js"
4200
4200
  }
4201
4201
  },
4202
4202
  "node_modules/tldts-core": {
4203
- "version": "7.4.18",
4204
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.18.tgz",
4205
- "integrity": "sha512-KI2PKvCmvQI/xD6ypPqkU0i7oxNXR/O58RLRaHR4svsgVUQ2JE/XC8BtMbG6PSehD27I8sZJRcC1ASnCy6lp3g==",
4203
+ "version": "7.4.19",
4204
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.19.tgz",
4205
+ "integrity": "sha512-goNXV6Ho9TIOfpJZanTd6CKG5DyYgYAL+k+22T0SLh8l6+KHIfBUPFuePuSZv05UttIaaLmI9tb7TmGIdK5AkQ==",
4206
4206
  "dev": true,
4207
4207
  "license": "MIT"
4208
4208
  },
@@ -4216,9 +4216,9 @@
4216
4216
  }
4217
4217
  },
4218
4218
  "node_modules/total-recall-brain": {
4219
- "version": "3.40.1",
4220
- "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.40.1.tgz",
4221
- "integrity": "sha512-tZMnDHXsMT1sa698oF26Np/G4k+Cn4ZXpTdo+BTNOvUMYEhxWR+7Tl+upHLMhcEEPuEM0EiAObL53a9JELzGag==",
4219
+ "version": "3.41.1",
4220
+ "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.41.1.tgz",
4221
+ "integrity": "sha512-QraXzcZpCTMssx1gaz8xjvSKf5KqirAaxzzER/ICBrWvawdNTLUDDMsVEYQUA/7thgwtL1QVIxU4dpfCGZwp+g==",
4222
4222
  "dev": true,
4223
4223
  "license": "MIT",
4224
4224
  "workspaces": [
@@ -4247,7 +4247,8 @@
4247
4247
  "bin": {
4248
4248
  "antigravity": "bin/antigravity.mjs",
4249
4249
  "total-recall": "bin/total-recall.mjs",
4250
- "total-recall-memory": "bin/total-recall-memory.mjs"
4250
+ "total-recall-memory": "bin/total-recall-memory.mjs",
4251
+ "vibebrain": "bin/total-recall.mjs"
4251
4252
  },
4252
4253
  "optionalDependencies": {
4253
4254
  "playwright": "^1.60.0"
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "tr-plugin-mesh",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "description": "Headscale and Tailscale SSH control-server mesh administration and node discovery",
6
6
  "scripts": {
7
- "test": "node --test test/*.test.mjs"
7
+ "test": "node --test test/*.test.mjs && vitest run"
8
8
  },
9
9
  "license": "MIT",
10
10
  "dependencies": {
@@ -16,6 +16,9 @@
16
16
  "README.md",
17
17
  "LICENSE",
18
18
  "ui/",
19
- "src/"
19
+ "capability/",
20
+ "src/",
21
+ "!src/**/*.spec.mjs",
22
+ "!src/**/*.test.mjs"
20
23
  ]
21
24
  }
@@ -2,9 +2,15 @@
2
2
  "$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
3
3
  "id": "mesh",
4
4
  "name": "Headscale",
5
- "version": "0.2.2",
5
+ "version": "0.2.4",
6
6
  "description": "Control-server mesh administration, Tailscale SSH, and peer node discovery.",
7
7
  "license": "MIT",
8
+ "requires": [
9
+ {
10
+ "id": "auth",
11
+ "range": ">=1.2.1"
12
+ }
13
+ ],
8
14
  "branding": {
9
15
  "name": "Headscale",
10
16
  "color": "#818cf8",
@@ -90,10 +96,34 @@
90
96
  "effect": "write",
91
97
  "output": "json",
92
98
  "args": [
93
- {"name":"operation","label":"Operation","type":"string","positional":true,"required":true},
94
- {"name":"node","label":"Node","type":"string","positional":true,"required":true},
95
- {"name":"source","label":"Source","type":"string","positional":true,"required":true},
96
- {"name":"destination","label":"Destination","type":"string","positional":true,"required":true}
99
+ {
100
+ "name": "operation",
101
+ "label": "Operation",
102
+ "type": "string",
103
+ "positional": true,
104
+ "required": true
105
+ },
106
+ {
107
+ "name": "node",
108
+ "label": "Node",
109
+ "type": "string",
110
+ "positional": true,
111
+ "required": true
112
+ },
113
+ {
114
+ "name": "source",
115
+ "label": "Source",
116
+ "type": "string",
117
+ "positional": true,
118
+ "required": true
119
+ },
120
+ {
121
+ "name": "destination",
122
+ "label": "Destination",
123
+ "type": "string",
124
+ "positional": true,
125
+ "required": true
126
+ }
97
127
  ]
98
128
  },
99
129
  {
@@ -103,8 +133,30 @@
103
133
  },
104
134
  {
105
135
  "name": "view",
106
- "description": "Inspect live mesh state",
107
- "effect": "read"
136
+ "description": "Read independent owner observations for mesh screens",
137
+ "effect": "read",
138
+ "timeout_ms": 60000,
139
+ "args": [
140
+ {
141
+ "name": "screen",
142
+ "label": "Screen",
143
+ "type": "choice",
144
+ "positional": true,
145
+ "options": [
146
+ "machines",
147
+ "flows",
148
+ "placement",
149
+ "boundary",
150
+ "join"
151
+ ]
152
+ },
153
+ {
154
+ "name": "json",
155
+ "label": "JSON output",
156
+ "type": "boolean",
157
+ "flag": "--json"
158
+ }
159
+ ]
108
160
  },
109
161
  {
110
162
  "name": "nodes",
@@ -145,7 +197,7 @@
145
197
  {
146
198
  "name": "enroll",
147
199
  "description": "Mesh enroll operation",
148
- "effect": "write"
200
+ "effect": "destructive"
149
201
  },
150
202
  {
151
203
  "name": "preauthkey",
@@ -292,5 +344,187 @@
292
344
  "distribution": {
293
345
  "tier": "official",
294
346
  "license": "open"
347
+ },
348
+ "mesh": {
349
+ "version": 1,
350
+ "description": "Declared support and observation contracts; declarations are not live readiness or primitive grants.",
351
+ "provides": [
352
+ {
353
+ "id": "node-inventory",
354
+ "operation": "status",
355
+ "runtime": "mesh",
356
+ "observation": "machines.status"
357
+ },
358
+ {
359
+ "id": "execution-probe",
360
+ "operation": "doctor",
361
+ "runtime": "mesh",
362
+ "observation": "doctor"
363
+ },
364
+ {
365
+ "id": "remote-execution",
366
+ "operation": "exec",
367
+ "runtime": "mesh",
368
+ "observation": "doctor"
369
+ },
370
+ {
371
+ "id": "path-probe",
372
+ "operation": "ping",
373
+ "runtime": "mesh",
374
+ "observation": "ping"
375
+ },
376
+ {
377
+ "id": "presence",
378
+ "operation": "presence",
379
+ "runtime": "presence",
380
+ "observation": "machines.presence"
381
+ },
382
+ {
383
+ "id": "file-push",
384
+ "operation": "file",
385
+ "runtime": "mesh",
386
+ "observation": null
387
+ },
388
+ {
389
+ "id": "secret-grants",
390
+ "operation": "grants",
391
+ "runtime": "mesh-identity",
392
+ "observation": "flows.grants"
393
+ },
394
+ {
395
+ "id": "control-policy",
396
+ "operation": "policy",
397
+ "runtime": "headscale-client",
398
+ "observation": "boundary.policy"
399
+ },
400
+ {
401
+ "id": "enrollment",
402
+ "operation": "enroll",
403
+ "runtime": "mesh-enroll",
404
+ "observation": "join.status"
405
+ }
406
+ ],
407
+ "integrations": [
408
+ {
409
+ "id": "auth",
410
+ "owner": "auth",
411
+ "purpose": "One host credential store; no values in views",
412
+ "observation": "machines.status",
413
+ "evidence": "control.verified"
414
+ },
415
+ {
416
+ "id": "headscale",
417
+ "owner": "mesh",
418
+ "purpose": "Control server authentication and membership",
419
+ "observation": "machines.status",
420
+ "evidence": "control.verified"
421
+ },
422
+ {
423
+ "id": "tailscale",
424
+ "owner": "mesh",
425
+ "purpose": "Client enrollment and mesh network state",
426
+ "observation": "machines.status",
427
+ "evidence": "network_available"
428
+ },
429
+ {
430
+ "id": "ssh",
431
+ "owner": "mesh",
432
+ "purpose": "Per-machine execution probes",
433
+ "observation": "doctor",
434
+ "evidence": "reachable per machine"
435
+ },
436
+ {
437
+ "id": "presence",
438
+ "owner": "mesh",
439
+ "purpose": "Authenticated fresh activity observations",
440
+ "observation": "machines.presence",
441
+ "evidence": "peer states and timestamps"
442
+ },
443
+ {
444
+ "id": "plugin-sharing",
445
+ "owner": "mesh",
446
+ "purpose": "Peer plugin inventories",
447
+ "observation": "flows.plugins",
448
+ "evidence": "peer status"
449
+ },
450
+ {
451
+ "id": "updates",
452
+ "owner": "core",
453
+ "purpose": "Last automatic maintenance report",
454
+ "observation": "flows.updates",
455
+ "evidence": "recorded last result"
456
+ },
457
+ {
458
+ "id": "schedules",
459
+ "owner": "user-automations",
460
+ "purpose": "Task declarations and node placement",
461
+ "observation": "flows.tasks",
462
+ "evidence": "node inventory; no execution inferred"
463
+ },
464
+ {
465
+ "id": "agents",
466
+ "owner": "core",
467
+ "purpose": "Running and recent process inventory",
468
+ "observation": "flows.agents",
469
+ "evidence": "process records"
470
+ },
471
+ {
472
+ "id": "alerts",
473
+ "owner": "operator-alerts",
474
+ "purpose": "Recorded delivery attempts",
475
+ "observation": "flows.alerts",
476
+ "evidence": "ledger result; no recipient view inferred"
477
+ },
478
+ {
479
+ "id": "deployments",
480
+ "owner": "deploy",
481
+ "purpose": "Selected project release state",
482
+ "observation": "flows.deployments",
483
+ "evidence": "configured slot; no fleet-wide inference"
484
+ }
485
+ ],
486
+ "endpoints": [
487
+ {
488
+ "path": "/api/mesh/presence/local",
489
+ "method": "GET",
490
+ "runtime": "route-mesh-presence",
491
+ "authentication": "mesh peer"
492
+ },
493
+ {
494
+ "path": "/api/mesh/plugins",
495
+ "method": "GET",
496
+ "runtime": "route-plugins-mesh",
497
+ "authentication": "mesh peer"
498
+ }
499
+ ],
500
+ "task_placement": "Declared task placement is selected-node or per-node; actual execution requires a verified daemon report.",
501
+ "unavailable": [
502
+ "transfer-history",
503
+ "service-health-cli",
504
+ "exit-node-management",
505
+ "subnet-route-management",
506
+ "tunnel-inventory",
507
+ "public-exposure-inventory",
508
+ "speed-measurement",
509
+ "messages",
510
+ "shared-file-spaces"
511
+ ]
512
+ },
513
+ "capability": {
514
+ "entry": "capability/index.mjs",
515
+ "dependencies": [],
516
+ "exports": [
517
+ "createControlServer",
518
+ "createHeadscaleApi",
519
+ "buildMeshSshPolicy",
520
+ "meshTargetOf",
521
+ "sshExec",
522
+ "assertSecureControlUrl",
523
+ "normalizeControlUrl",
524
+ "shellQuote",
525
+ "patchConfig",
526
+ "parseChecksum",
527
+ "consoleConfig"
528
+ ]
295
529
  }
296
530
  }
@@ -46,6 +46,7 @@ function printHelp() {
46
46
  Usage: total-recall mesh <command> [options]
47
47
 
48
48
  status Control-server reachability and credential state
49
+ view <screen> Read Machines, Flows, Placement, Boundary or Join sources (--json)
49
50
  doctor Probe reachability & compute capabilities across all nodes
50
51
  nodes List mesh nodes and how to reach each one
51
52
  ssh <node> [cmd…] Open a session using the node's recorded access
@@ -194,9 +195,9 @@ export default async function meshCli(argv = []) {
194
195
  }
195
196
 
196
197
  if (command === 'doctor' || command === 'diagnostics') {
197
- console.log('\n🩺 Total Recall — Mesh Diagnostics & Compute Capability Audit\n');
198
198
  const enriched = listEnrichedMeshNodes(vaultRoot);
199
199
  const isJson = args.includes('--json');
200
+ if (!isJson) console.log('\n🩺 Total Recall — Mesh Diagnostics & Compute Capability Audit\n');
200
201
 
201
202
  const stripAnsi = (s) => String(s || '').replace(/\x1b\[[0-9;]*m/g, '');
202
203
  const pad = (s, l) => String(s || '') + ' '.repeat(Math.max(0, l - stripAnsi(s).length));
@@ -217,13 +218,17 @@ export default async function meshCli(argv = []) {
217
218
  reachable: false,
218
219
  error: null
219
220
  };
221
+ nodeInfo.tested_runtimes = ['ollama', 'docker', 'node', 'git'];
222
+ nodeInfo.tested_harnesses = ['agy', 'claude', 'codex', 'gemini'];
220
223
 
221
224
  if (node.self) {
222
225
  try {
223
226
  const { detectHarnesses } = await import('../core/meta-harness.mjs');
224
- nodeInfo.harnesses = detectHarnesses().filter(h => h.available).map(h => h.id);
225
- } catch {}
226
- nodeInfo.runtimes = ['node', 'git'];
227
+ const detected = detectHarnesses();
228
+ nodeInfo.harnesses = detected.filter(h => h.available).map(h => h.id);
229
+ nodeInfo.tested_harnesses = detected.map(h => h.id);
230
+ } catch { nodeInfo.tested_harnesses = []; }
231
+ nodeInfo.runtimes = nodeInfo.tested_runtimes.filter(tool => spawnSync('/bin/sh', ['-c', 'command -v "$1"', 'mesh-probe', tool], { encoding: 'utf8', timeout: 3000 }).status === 0);
227
232
  nodeInfo.reachable = true;
228
233
  } else if (resolved.complete) {
229
234
  try {
@@ -233,16 +238,12 @@ export default async function meshCli(argv = []) {
233
238
  // reachable machines as down.
234
239
  const res = await execMeshCommand(node.hostname, probeCmd, { vaultRoot, timeoutMs: 15000 });
235
240
  nodeInfo.reachable = res.success;
236
- if (res.success && !node.access?.verified_at) {
237
- // A login that just worked is the only kind worth sharing with peers.
238
- await setMeshNodeAccess(node.hostname, { verified_at: new Date().toISOString() }, { vaultRoot });
239
- }
240
241
  if (res.success) {
241
242
  const parts = res.stdout.split(/\s+/);
242
243
  for (const part of parts) {
243
244
  const [k, v] = part.split('=');
244
245
  if (v && v.trim()) {
245
- if (['agy', 'claude', 'codex', 'gemini', 'ollama'].includes(k)) {
246
+ if (['agy', 'claude', 'codex', 'gemini'].includes(k)) {
246
247
  nodeInfo.harnesses.push(k);
247
248
  } else {
248
249
  nodeInfo.runtimes.push(k);
@@ -770,6 +771,10 @@ export default async function meshCli(argv = []) {
770
771
  if (reportPolicyModeError(err)) return;
771
772
  throw err;
772
773
  }
774
+ if (args.includes('--json')) {
775
+ console.log(JSON.stringify({ configured: current.configured, policy: current.policy, updatedAt: current.updatedAt || null }));
776
+ return;
777
+ }
773
778
  if (!current.configured) {
774
779
  console.log('No policy is set on the control server.');
775
780
  console.log('Run `total-recall mesh policy init-ssh` to enable Tailscale SSH.');
@@ -3,7 +3,7 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { spawnSync } from 'node:child_process';
6
- import { meshTargetOf, provisionHeadscale, updateHeadscale, updateConsole, sshExec } from '../core/headscale-server.mjs';
6
+ import { meshTargetOf, provisionHeadscale, updateHeadscale, updateConsole, sshExec } from '../../capability/control-server.mjs';
7
7
  import { saveCredential } from '../core/credentials.mjs';
8
8
  import { brainDir } from '../core/config.mjs';
9
9
  import { PluginStateStore } from '../ssss-store.mjs';
@@ -1,7 +1,8 @@
1
1
  import { importHostModule } from '../host-runtime.mjs';
2
2
  const { loadPluginModule: __loadOwnedPlugin } = await importHostModule('src/core/plugin-runtime.mjs');
3
3
  import { assertSecureControlUrl, normalizeControlUrl, headscaleUrlFromEnv, findHeadscaleKeyMeta } from './headscale-client.mjs';
4
- const { setSecret, defaultBrainDir } = await __loadOwnedPlugin('auth', 'secrets-store');
4
+ const { setSecret } = await __loadOwnedPlugin('auth', 'secrets-store');
5
+ const { hostSecretsBrainDir } = await __loadOwnedPlugin('auth', 'host-secrets-store');
5
6
 
6
7
  export async function verifyCredential(value, url, fetchImpl = fetch) {
7
8
  if (typeof value !== 'string' || !value.trim()) throw new Error('A credential is required');
@@ -18,8 +19,9 @@ export async function verifyCredential(value, url, fetchImpl = fetch) {
18
19
  return { verified: true, url: normalizeControlUrl(url) };
19
20
  }
20
21
 
21
- export async function saveCredential({ key, value, configuration = {}, brainDir = defaultBrainDir() }, dependencies = {}) {
22
+ export async function saveCredential({ key, value, configuration = {} }, dependencies = {}) {
22
23
  if (key !== 'HEADSCALE_API_KEY') throw new Error('Unsupported mesh credential');
24
+ const brainDir = hostSecretsBrainDir();
23
25
  const meta = await findHeadscaleKeyMeta(brainDir);
24
26
  const url = configuration.controlUrl || headscaleUrlFromEnv() || meta?.headscale_url;
25
27
  if (!url) throw new Error('Set the control server URL before saving the credential');