c8ctl-plugin-nano 1.7.2 → 1.8.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/README.md CHANGED
@@ -169,6 +169,21 @@ and the history cap.
169
169
  > ⚠️ With `--in-memory`, restart recovers nothing, and Raft/replicated logs are
170
170
  > not persisted. Use it for stress/throughput testing, not durability testing.
171
171
 
172
+ ## Console profile (`--console` / `--profile`)
173
+
174
+ The server ships a browser console. Pick how much of it is exposed at runtime:
175
+
176
+ ```bash
177
+ c8ctl nano start # studio (default): full IDE + authoring API
178
+ c8ctl nano start --console observe # observability views only; authoring refused (403)
179
+ c8ctl nano start --console off # headless: no console router at all
180
+ ```
181
+
182
+ - Values: `studio` (default), `observe`, `off`. `--profile` is an alias for
183
+ `--console`, and an inherited `NANOBPMN_CONSOLE` env var is honored when neither
184
+ flag is passed. The plugin passes the choice through as `NANOBPMN_CONSOLE` on
185
+ every node.
186
+
172
187
  ## Configuration (`set` / `config`)
173
188
 
174
189
  Persistent settings are stored in `<state home>/config.json`:
package/c8ctl-plugin.js CHANGED
@@ -13,13 +13,15 @@
13
13
  * NANOBPMN_RF replication factor (1 = single-homed, no Raft)
14
14
  * NANOBPMN_RAFT set when RF > 1 to enable per-partition Raft
15
15
  * NANOBPMN_DATA_DIR this node's engine data directory
16
+ * NANOBPMN_CONSOLE runtime console profile (off | observe | studio)
17
+ * NANOBPMN_NODE_BIN Node path for the server's worker fallback runtime
16
18
  *
17
19
  * This plugin spawns N detached node processes wired to talk to each other on
18
20
  * localhost, tracks them in a state file, and stops them on request.
19
21
  *
20
22
  * Usage:
21
23
  * c8ctl nano start [<nodes>] [--port <basePort>] [--partitions <n>] [--rf <n>]
22
- * [--in-memory] [--history-max <n>]
24
+ * [--in-memory] [--history-max <n>] [--console <profile>]
23
25
  * c8ctl nano status
24
26
  * c8ctl nano stop [--purge]
25
27
  * c8ctl nano logs [<nodeId>] [--follow]
@@ -334,6 +336,18 @@ function findBinary(flags) {
334
336
  */
335
337
  function launcherEnvMarkers(resolved) {
336
338
  const markers = { NANOBPMN_LAUNCHER: 'c8ctl-plugin-nano' };
339
+
340
+ // This launcher IS a Node runtime, so hand the server a known-good Node path
341
+ // for its worker fallback (Deno-preferred, Node >= 22.6). Avoid pinning an
342
+ // older Node runtime (the plugin supports Node >=18) so the server can still
343
+ // fall back to a newer Node on PATH when available.
344
+ const [nodeMajor, nodeMinor, nodePatch] = process.versions.node
345
+ .split('.')
346
+ .map((n) => Number.parseInt(n, 10));
347
+ const nodeOk =
348
+ nodeMajor > 22 ||
349
+ (nodeMajor === 22 && (nodeMinor > 6 || (nodeMinor === 6 && nodePatch >= 0)));
350
+ if (nodeOk) markers.NANOBPMN_NODE_BIN = process.execPath;
337
351
  const { version } = pluginPackage();
338
352
  // The plugin version is the update unit's "current" in the npm channel's
339
353
  // version space (same space as `npm view <plugin> version` -> latest), so the
@@ -381,6 +395,7 @@ function parseRequest(args, flags) {
381
395
  capture: Boolean(flags?.capture),
382
396
  inMemory: Boolean(flags?.['in-memory'] || flags?.['no-journal']),
383
397
  historyMax: intFlag('history-max'),
398
+ console: flags?.console ?? flags?.profile,
384
399
  workspace: Boolean(flags?.workspace),
385
400
  check: Boolean(flags?.check),
386
401
  binary: flags?.binary,
@@ -529,6 +544,26 @@ async function waitForHealthy(url, timeoutMs = READINESS_TIMEOUT_MS) { const st
529
544
  // start
530
545
  // ---------------------------------------------------------------------------
531
546
 
547
+ /** Runtime console profiles the server understands (nano-bpm ADR 0035 §C). */
548
+ const CONSOLE_PROFILES = ['off', 'observe', 'studio'];
549
+
550
+ /**
551
+ * Resolves the runtime console profile to pass through as NANOBPMN_CONSOLE.
552
+ * Precedence: --console/--profile flag > inherited NANOBPMN_CONSOLE env >
553
+ * 'studio' (the full IDE, our default). Unknown values are rejected so a typo
554
+ * fails fast here rather than silently degrading the console in the server.
555
+ */
556
+ function resolveConsoleProfile(reqConsole) {
557
+ const raw = reqConsole ?? process.env.NANOBPMN_CONSOLE ?? 'studio';
558
+ const profile = String(raw).trim().toLowerCase();
559
+ if (!CONSOLE_PROFILES.includes(profile)) {
560
+ throw new Error(
561
+ `invalid console profile "${raw}" (use one of: ${CONSOLE_PROFILES.join(', ')})`,
562
+ );
563
+ }
564
+ return profile;
565
+ }
566
+
532
567
  async function startCluster(req) {
533
568
  const logger = getLogger();
534
569
 
@@ -557,6 +592,7 @@ async function startCluster(req) {
557
592
  const capture = Boolean(req.capture);
558
593
  const inMemory = Boolean(req.inMemory);
559
594
  const historyMax = req.historyMax;
595
+ const consoleProfile = resolveConsoleProfile(req.console);
560
596
 
561
597
  if (partitions < nodeCount) {
562
598
  logger.warn(
@@ -630,7 +666,8 @@ async function startCluster(req) {
630
666
  `Starting Nano BPM cluster: ${nodeCount} node(s), ${partitions} partition(s), ` +
631
667
  `RF=${rf}${raft ? ', Raft on' : ''}${capture ? ', trace capture on' : ''}` +
632
668
  `${inMemory ? ', in-memory (no disk)' : ''}` +
633
- `${historyMax !== undefined ? `, history-max=${historyMax}` : ''}`,
669
+ `${historyMax !== undefined ? `, history-max=${historyMax}` : ''}` +
670
+ `${consoleProfile !== 'studio' ? `, console=${consoleProfile}` : ''}`,
634
671
  );
635
672
  logger.info(`Binary: ${binary}`);
636
673
  logger.info(`Workspace: ${workspaceDir} (models/, workers/)`);
@@ -667,6 +704,10 @@ async function startCluster(req) {
667
704
  // Shared, persistent authoring workspace (models + workers). Lives
668
705
  // outside the per-node data dir so "nano clean" never wipes it.
669
706
  NANOBPMN_WORKSPACE_DIR: workspaceDir,
707
+ // Runtime console profile (off | observe | studio). Default studio (full
708
+ // IDE); pass-through so --console/--profile or an inherited NANOBPMN_CONSOLE
709
+ // picks the observability-only or headless surface. See nano-bpm ADR 0035 §C.
710
+ NANOBPMN_CONSOLE: consoleProfile,
670
711
  };
671
712
  // Storage axis: an on-disk journal + read-model under the per-node data dir
672
713
  // (default), or a fully in-memory engine (in-memory journal + :memory: read
@@ -2540,6 +2581,8 @@ export const commands = {
2540
2581
  'in-memory': { type: 'boolean', description: 'start: run with NO on-disk journal/read-model (in-memory engine; state lost on restart). Alias: --no-journal' },
2541
2582
  'no-journal': { type: 'boolean', description: 'start: alias for --in-memory' },
2542
2583
  'history-max': { type: 'string', description: 'start: cap retained terminal instances in the read model (NANOBPMN_HISTORY_MAX_INSTANCES; 0/unset = unbounded)' },
2584
+ console: { type: 'string', description: 'start: runtime console profile off|observe|studio (NANOBPMN_CONSOLE; default studio). Alias: --profile' },
2585
+ profile: { type: 'string', description: 'start: alias for --console (off|observe|studio; default studio)' },
2543
2586
  follow: { type: 'boolean', description: 'logs: stream output (tail -F)', short: 'f' },
2544
2587
  purge: { type: 'boolean', description: 'stop/restart: also delete per-node engine data' },
2545
2588
  force: { type: 'boolean', description: 'start: stop any existing cluster first' },
@@ -2671,7 +2714,7 @@ export const commands = {
2671
2714
 
2672
2715
  function printUsage() {
2673
2716
  console.log('Usage:');
2674
- console.log(' c8ctl nano start [<nodes>] [--port <basePort>] [--partitions <n>] [--rf <n>] [--raft] [--capture] [--in-memory] [--history-max <n>] [--binary <path>]');
2717
+ console.log(' c8ctl nano start [<nodes>] [--port <basePort>] [--partitions <n>] [--rf <n>] [--raft] [--capture] [--in-memory] [--history-max <n>] [--console <profile>] [--binary <path>]');
2675
2718
  console.log(' c8ctl nano status [--port <port>]');
2676
2719
  console.log(' c8ctl nano stop [--purge]');
2677
2720
  console.log(' c8ctl nano logs [<nodeId>] [--follow]');
@@ -2705,6 +2748,7 @@ function printUsage() {
2705
2748
  console.log(' --capture start: enable trace capture (recorded-input replay) on every node');
2706
2749
  console.log(' --in-memory start: run with NO on-disk journal/read-model (alias --no-journal; state lost on restart)');
2707
2750
  console.log(' --history-max <n> start: cap retained terminal instances in the read model (0/unset = unbounded)');
2751
+ console.log(' --console <profile> start: runtime console profile off|observe|studio (alias --profile; default studio)');
2708
2752
  console.log(' --binary <path> Path to the nanobpmn server binary (overrides "set bin")');
2709
2753
  console.log(' --purge stop: also delete per-node engine data');
2710
2754
  console.log(' --force start: stop any existing cluster first');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8ctl-plugin-nano",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "description": "c8ctl plugin to start, inspect, and stop a local Nano BPM (nanobpmn) cluster",
6
6
  "main": "c8ctl-plugin.js",
@@ -49,12 +49,12 @@
49
49
  "semantic-release": "^25.0.3"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.7.2",
53
- "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.7.2",
54
- "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.7.2",
55
- "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.7.2",
56
- "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.7.2",
57
- "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.7.2",
58
- "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.7.2"
52
+ "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.8.0",
53
+ "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.8.0",
54
+ "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.8.0",
55
+ "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.8.0",
56
+ "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.8.0",
57
+ "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.8.0",
58
+ "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.8.0"
59
59
  }
60
60
  }