c8ctl-plugin-nano 1.5.1 → 1.6.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/c8ctl-plugin.js CHANGED
@@ -238,42 +238,66 @@ function getRepoRoot() {
238
238
  }
239
239
 
240
240
  /**
241
- * Locate the nanobpmn server binary. Resolution order:
242
- * 1. --binary flag
243
- * 2. configured binary path ("nano set bin <path>")
244
- * 3. NANOBPMN_BINARY env var
245
- * 4. matching platform package (optionalDependency), when installed via npm
246
- * 5. release build under the nanobpmn repo
247
- * 6. debug build under the nanobpmn repo
241
+ * Locate the nanobpmn server binary AND report its provenance. Resolution order:
242
+ * 1. --binary flag -> source 'flag' (self-managed)
243
+ * 2. configured binary path ("nano set bin") -> source 'configured' (self-managed)
244
+ * 3. NANOBPMN_BINARY env var -> source 'configured' (self-managed)
245
+ * 4. matching platform package (npm) -> source 'managed-npm' (managed)
246
+ * 5. release build under the nanobpmn repo -> source 'repo-release'(self-managed)
247
+ * 6. debug build under the nanobpmn repo -> source 'repo-debug' (self-managed)
248
+ *
249
+ * Returns `{ path, source, from, channel?, updatePkg? }`. Only the npm platform
250
+ * package (source 4) is a plugin-owned "managed" binary the plugin may update in
251
+ * place; for it we also report `channel:'npm'` and `updatePkg` (the plugin
252
+ * package the console/server should `npm view` for the latest version — the
253
+ * update unit, since the platform binary ships pinned to the plugin release).
254
+ * Every other source is a user-configured or dev/repo build: self-managed, so
255
+ * the console must disable self-update and suppress "update available" nags.
256
+ *
257
+ * Throws (with actionable guidance) when no binary can be found.
248
258
  */
249
- function findBinary(flags) {
259
+ function resolveBinary(flags) {
250
260
  const cfg = readConfig();
251
261
  const sources = [
252
- { val: flags?.binary && String(flags.binary), from: '--binary' },
253
- { val: cfg.binary && String(cfg.binary), from: 'configured bin ("nano set bin")' },
254
- { val: process.env.NANOBPMN_BINARY, from: 'NANOBPMN_BINARY' },
262
+ { val: flags?.binary && String(flags.binary), from: '--binary', source: 'flag' },
263
+ {
264
+ val: cfg.binary && String(cfg.binary),
265
+ from: 'configured bin ("nano set bin")',
266
+ source: 'configured',
267
+ },
268
+ { val: process.env.NANOBPMN_BINARY, from: 'NANOBPMN_BINARY', source: 'configured' },
255
269
  ];
256
- for (const { val, from } of sources) {
270
+ for (const { val, from, source } of sources) {
257
271
  if (!val) continue;
258
272
  const p = expandHome(val);
259
273
  const abs = isAbsolute(p) ? p : resolvePath(process.cwd(), p);
260
274
  if (!existsSync(abs)) {
261
275
  throw new Error(`Binary not found at ${abs} (from ${from})`);
262
276
  }
263
- return abs;
277
+ return { path: abs, source, from };
264
278
  }
265
279
 
266
280
  const fromPackage = findPlatformPackageBinary();
267
- if (fromPackage) return fromPackage;
281
+ if (fromPackage) {
282
+ return {
283
+ path: fromPackage,
284
+ source: 'managed-npm',
285
+ from: 'platform package (npm)',
286
+ channel: 'npm',
287
+ // The update unit is the plugin meta-package: the platform binary ships
288
+ // pinned to it, so `npm view <plugin> version` is the server's "latest".
289
+ updatePkg: pluginPackage().name,
290
+ };
291
+ }
268
292
 
269
293
  const repo = getRepoRoot();
270
294
  const name = 'nanobpm-gateway-rest-server';
271
295
  const candidates = [
272
- join(repo, 'server', 'target', 'release', name),
273
- join(repo, 'server', 'target', 'debug', name),
296
+ { path: join(repo, 'server', 'target', 'release', name), source: 'repo-release' },
297
+ { path: join(repo, 'server', 'target', 'debug', name), source: 'repo-debug' },
274
298
  ];
275
299
  for (const c of candidates) {
276
- if (existsSync(c)) return c;
300
+ if (existsSync(c.path)) return { path: c.path, source: c.source, from: `repo build (${c.source})` };
277
301
  }
278
302
  const host = `${process.platform}/${process.arch}`;
279
303
  const expectedPkg = platformForHost()?.pkg;
@@ -283,12 +307,43 @@ function findBinary(flags) {
283
307
  ? `No platform package installed for ${host} (expected "${expectedPkg}").\n` +
284
308
  `Reinstall the plugin so npm can fetch it, or build from source below.\n`
285
309
  : `No prebuilt binary is published for this platform (${host}).\n`) +
286
- `Looked for a local build in:\n ${candidates.join('\n ')}\n` +
310
+ `Looked for a local build in:\n ${candidates.map((c) => c.path).join('\n ')}\n` +
287
311
  `Build it with: (cd ${repo} && make release-gateway)\n` +
288
312
  `Or set one with "c8ctl nano set bin <path>", --binary <path>, or NANOBPMN_BINARY=<path>.`,
289
313
  );
290
314
  }
291
315
 
316
+ /**
317
+ * Locate the nanobpmn server binary (absolute path). Thin wrapper over
318
+ * [`resolveBinary`] for the many call sites that only need the path.
319
+ */
320
+ function findBinary(flags) {
321
+ return resolveBinary(flags).path;
322
+ }
323
+
324
+ /**
325
+ * Launcher-identity + binary-provenance env markers stamped onto every server
326
+ * process this plugin spawns, so the running server (and its console UI) can
327
+ * tell it was launched by us and whether its binary is plugin-managed
328
+ * (self-updatable) vs. self-managed/dev (update disabled, nags suppressed).
329
+ *
330
+ * `resolved` is a [`resolveBinary`] descriptor. Safe to call with `undefined`
331
+ * (e.g. when the binary could not be resolved) — it still stamps the launcher
332
+ * identity, and the server treats an absent source as self-managed/unknown.
333
+ */
334
+ function launcherEnvMarkers(resolved) {
335
+ const markers = { NANOBPMN_LAUNCHER: 'c8ctl-plugin-nano' };
336
+ const { version } = pluginPackage();
337
+ // The plugin version is the update unit's "current" in the npm channel's
338
+ // version space (same space as `npm view <plugin> version` -> latest), so the
339
+ // server compares like-for-like instead of against its own git-describe build.
340
+ if (version) markers.NANOBPMN_LAUNCHER_VERSION = version;
341
+ if (resolved?.source) markers.NANOBPMN_BINARY_SOURCE = resolved.source;
342
+ if (resolved?.channel) markers.NANOBPMN_UPDATE_CHANNEL = resolved.channel;
343
+ if (resolved?.updatePkg) markers.NANOBPMN_UPDATE_PKG = resolved.updatePkg;
344
+ return markers;
345
+ }
346
+
292
347
  // ---------------------------------------------------------------------------
293
348
  // Argument parsing
294
349
  // ---------------------------------------------------------------------------
@@ -527,7 +582,11 @@ async function startCluster(req) {
527
582
  }
528
583
  }
529
584
 
530
- const binary = findBinary(req);
585
+ const resolvedBinary = resolveBinary(req);
586
+ const binary = resolvedBinary.path;
587
+ // Launcher-identity + binary-provenance markers, stamped on every node so the
588
+ // server's console can offer (or suppress) a self-update. Computed once here.
589
+ const launcherMarkers = launcherEnvMarkers(resolvedBinary);
531
590
 
532
591
  // Pre-flight: make sure the chosen ports are free, and tell the user exactly
533
592
  // what is in the way (Camunda vs Nano vs some other HTTP server). We refuse to
@@ -584,6 +643,9 @@ async function startCluster(req) {
584
643
 
585
644
  const env = {
586
645
  ...process.env,
646
+ // Launcher-identity + binary-provenance markers (after the process.env
647
+ // spread so the launcher's own values win over any inherited stale ones).
648
+ ...launcherMarkers,
587
649
  PORT: String(port),
588
650
  NANOBPMN_NODE_ID: String(id),
589
651
  NANOBPMN_NODES: nodesEnv,
@@ -1961,14 +2023,20 @@ async function startProcessos(req) {
1961
2023
  // The plugin already knows where the nano binary lives, so auto-wire it.
1962
2024
  // Spawning the pilot engine is the DEFAULT; resolve the binary best-effort.
1963
2025
  let nanoBin;
2026
+ let resolvedPilot;
1964
2027
  try {
1965
- nanoBin = findBinary({});
2028
+ resolvedPilot = resolveBinary({});
2029
+ nanoBin = resolvedPilot.path;
1966
2030
  } catch {
1967
2031
  nanoBin = undefined;
1968
2032
  }
1969
2033
  if (nanoBin && !env.PROCESSOS_NANO_BIN) {
1970
2034
  env.PROCESSOS_NANO_BIN = nanoBin;
1971
2035
  }
2036
+ // Stamp launcher-identity + provenance markers so the pilot nano gateway
2037
+ // (spawned by ProcessOS from this env) can offer/suppress console self-update
2038
+ // the same way a directly-launched `nano start` node does.
2039
+ Object.assign(env, launcherEnvMarkers(resolvedPilot));
1972
2040
 
1973
2041
  // Decide whether to spawn the pilot engine. Precedence:
1974
2042
  // --no-spawn-nano flag -> off (explicit)
@@ -2341,6 +2409,9 @@ function parseProcessosRequest(args, flags) {
2341
2409
  // metadata + commands
2342
2410
  // ---------------------------------------------------------------------------
2343
2411
 
2412
+ // Internal helpers exported for tests/tooling only. c8ctl consumes just
2413
+ // `metadata` and `commands`; these named exports are inert to it.
2414
+ export { resolveBinary, findBinary, launcherEnvMarkers };
2344
2415
 
2345
2416
  export const metadata = {
2346
2417
  name: 'c8ctl-plugin-nano',
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.5",
3
- "commit": "50fc02f",
4
- "updated": "2026-07-04T23:25:35Z"
2
+ "version": "0.0.7",
3
+ "commit": "aa669bd",
4
+ "updated": "2026-07-07T05:01:14Z"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8ctl-plugin-nano",
3
- "version": "1.5.1",
3
+ "version": "1.6.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,10 +49,10 @@
49
49
  "semantic-release": "^25.0.3"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.5.1",
53
- "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.5.1",
54
- "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.5.1",
55
- "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.5.1",
56
- "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.5.1"
52
+ "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.6.0",
53
+ "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.6.0",
54
+ "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.6.0",
55
+ "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.6.0",
56
+ "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.6.0"
57
57
  }
58
58
  }