@rogatio/cli 6.0.1 → 6.1.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
@@ -40,8 +40,8 @@ rogatio <command> [options]
40
40
  | `rogatio verify [path]` | Validate a `.rogatio.json` file (schema + compiler). |
41
41
  | `rogatio test [path] [url...]` | Run offline dry-run tests against `.rogatio.json`. |
42
42
  | `rogatio ai <setup\|ls\|show\|delete\|test>` | AI provider configuration. `setup` interactive; `ls` list; `show` redacted; `delete` remove; `test` connection. |
43
- | `rogatio runtime <install\|uninstall>` | Register the native-messaging host with `install --extension-id <id>` (and, on capable platforms, the device-local CA) in one transactional install; `uninstall` removes the host manifest, the device-local CA files, and the CA trust installation (idempotent). |
44
- | `rogatio runtime host <path>` | Run the consolidated native-messaging host for the project (pair/authorize/body transforms over stdio). Normally launched by the browser; run manually only for debugging. |
43
+ | `rogatio runtime <install\|uninstall\|verify>` | Register the native-messaging host with `install --extension-id <id>` and trust the device-local CA in one **transactional** call; it needs elevated privileges (Linux `sudo`, macOS keychain authorization, Windows Administrator) and rolls back with exit `1` and `trust unsupported: <reasons>` when a capability or elevation is missing. `uninstall` removes the host manifest, the device-local CA files, and the CA trust installation (idempotent). `verify` reports whether manifest, `runtime-host` wrapper, allowed origins, and CA trust are all valid. |
44
+ | `rogatio runtime host [path]` | Run the consolidated native-messaging host for the project (pair/authorize/body transforms over stdio). Normally launched by the browser; run manually only for debugging. `--root <dir>` overrides the confined file root; `--mock-port <n>` binds the loopback mock-response faucet. |
45
45
 
46
46
  Global options: `--help, -h` and `--version, -v`. Run `rogatio <command> --help`
47
47
  for command-specific usage.
@@ -65,9 +65,29 @@ rogatio runtime host .rogatio.json
65
65
  ## Exit codes
66
66
 
67
67
  - `0` — success
68
- - `1` — invalid project (diagnostics present) or test/validation errors
68
+ - `1` — invalid project (diagnostics present), test/validation errors, or a failed
69
+ `runtime install` / `runtime verify` check
69
70
  - `2` — usage or IO error
70
71
 
72
+ ## Local runtime
73
+
74
+ ```sh
75
+ # Register the native-messaging host and trust the device-local CA (needs elevation)
76
+ rogatio runtime install --extension-id <id>
77
+
78
+ # Check manifest, runtime-host wrapper, allowed origins, and CA trust
79
+ rogatio runtime verify
80
+
81
+ # Remove the host manifest, CA files, and trust installation
82
+ rogatio runtime uninstall
83
+
84
+ # Run the native-messaging host (normally launched by the browser)
85
+ rogatio runtime host .rogatio.json
86
+ ```
87
+
88
+ Start and stop of the runtime **session** is driven from the extension's **Start runtime** /
89
+ **Stop runtime** controls. The CLI has no session lifecycle subcommand.
90
+
71
91
  ## AI-Assisted Rule Authoring
72
92
 
73
93
  ```sh
@@ -385,6 +385,10 @@
385
385
  justify-content: space-between;
386
386
  gap: 0.65rem;
387
387
  }
388
+ .rogatio-editor [data-group-heading] button[data-group-enable] {
389
+ padding: 0.55rem 1.05rem;
390
+ font-size: 0.95rem;
391
+ }
388
392
  .rogatio-editor [data-group-heading] h2,
389
393
  .rogatio-editor [data-section-heading] h2,
390
394
  .rogatio-editor [data-rule-heading] h3 {
@@ -2108,6 +2108,8 @@ var EditorControllerImpl = class {
2108
2108
  conversionDiagnostics = /* @__PURE__ */ new Map();
2109
2109
  extensionErrors = /* @__PURE__ */ new Map();
2110
2110
  controls = /* @__PURE__ */ new Map();
2111
+ /** Live draft group object to the id last saved for that group. */
2112
+ savedGroupIds = /* @__PURE__ */ new WeakMap();
2111
2113
  extensionControls = /* @__PURE__ */ new Map();
2112
2114
  extensionCleanups = [];
2113
2115
  confirmation;
@@ -2137,6 +2139,7 @@ var EditorControllerImpl = class {
2137
2139
  this.instanceId = `rogatio-editor-${++editorInstanceCount}`;
2138
2140
  this.draft = initial;
2139
2141
  this.committed = cloneSnapshot(initial);
2142
+ this.bindSavedGroupIds();
2140
2143
  this.errors = this.collectDiagnostics(this.draft);
2141
2144
  if (this.errors.length > 0) {
2142
2145
  this.statusMessage = `${this.errors.length} validation error${this.errors.length === 1 ? "" : "s"} found.`;
@@ -2893,6 +2896,7 @@ var EditorControllerImpl = class {
2893
2896
  return;
2894
2897
  }
2895
2898
  this.draft = cloneSnapshot(this.committed);
2899
+ this.bindSavedGroupIds();
2896
2900
  this.revision += 1;
2897
2901
  this.errors = [];
2898
2902
  this.conversionDiagnostics.clear();
@@ -2941,6 +2945,7 @@ var EditorControllerImpl = class {
2941
2945
  }
2942
2946
  if (isSaveSuccess(result)) {
2943
2947
  this.committed = cloneSnapshot(snapshot);
2948
+ this.bindSavedGroupIds();
2944
2949
  this.errors = [];
2945
2950
  this.statusMessage = "Saved";
2946
2951
  this.render();
@@ -3318,6 +3323,22 @@ var EditorControllerImpl = class {
3318
3323
  this.statusMessage = "";
3319
3324
  this.render();
3320
3325
  }
3326
+ syncGroupEnablement(enabledGroupIds) {
3327
+ if (this.destroyed) return;
3328
+ const enabled = /* @__PURE__ */ new Set();
3329
+ for (const id of enabledGroupIds) {
3330
+ if (typeof id === "string") enabled.add(id);
3331
+ }
3332
+ const buttons = this.host.querySelectorAll(
3333
+ "button[data-group-enable]"
3334
+ );
3335
+ for (const button of buttons) {
3336
+ const groupId = button.dataset.groupId ?? "";
3337
+ const headingName = button.parentElement?.querySelector("h2")?.textContent?.trim();
3338
+ const groupName = headingName && headingName.length > 0 ? headingName : displayName(this.groupById(groupId)?.name, "Unnamed group");
3339
+ this.applyGroupEnablementLabel(button, enabled.has(groupId), groupName);
3340
+ }
3341
+ }
3321
3342
  navigateToSearchResult(path) {
3322
3343
  const segments = decodePointer(path);
3323
3344
  if (segments?.[0] !== "groups") {
@@ -3645,7 +3666,35 @@ var EditorControllerImpl = class {
3645
3666
  { groupId },
3646
3667
  "danger"
3647
3668
  );
3648
- headingRow.append(heading, copyGroup, removeGroup);
3669
+ const savedGroupId = this.savedGroupId(group);
3670
+ const enablement = this.options.groupEnablement;
3671
+ if (enablement && savedGroupId) {
3672
+ const enableButton = this.document.createElement("button");
3673
+ enableButton.type = "button";
3674
+ enableButton.dataset.groupEnable = "true";
3675
+ enableButton.dataset.groupId = savedGroupId;
3676
+ enableButton.dataset.btn = "primary";
3677
+ this.applyGroupEnablementLabel(
3678
+ enableButton,
3679
+ enablement.isEnabled(savedGroupId) === true,
3680
+ groupName
3681
+ );
3682
+ enableButton.addEventListener("click", (event) => {
3683
+ event.preventDefault();
3684
+ event.stopPropagation();
3685
+ if (enableButton.disabled) return;
3686
+ const next = enablement.isEnabled(savedGroupId) !== true;
3687
+ enableButton.disabled = true;
3688
+ void Promise.resolve(enablement.setEnabled(savedGroupId, next)).finally(
3689
+ () => {
3690
+ if (enableButton.isConnected) enableButton.disabled = false;
3691
+ }
3692
+ );
3693
+ });
3694
+ headingRow.append(heading, enableButton, copyGroup, removeGroup);
3695
+ } else {
3696
+ headingRow.append(heading, copyGroup, removeGroup);
3697
+ }
3649
3698
  this.form.append(headingRow);
3650
3699
  const settings = this.document.createElement("fieldset");
3651
3700
  settings.dataset.groupCard = "true";
@@ -4403,6 +4452,26 @@ var EditorControllerImpl = class {
4403
4452
  button.dataset.editorKey = `button:${key}`;
4404
4453
  return button;
4405
4454
  }
4455
+ applyGroupEnablementLabel(button, enabled, groupName) {
4456
+ const action = enabled ? "Disable" : "Enable";
4457
+ button.textContent = action;
4458
+ button.setAttribute("aria-label", `${action} group ${groupName}`);
4459
+ }
4460
+ bindSavedGroupIds() {
4461
+ for (let index = 0; index < this.draft.groups.length; index += 1) {
4462
+ const draftGroup = this.draft.groups[index];
4463
+ const savedGroup = this.committed.groups[index];
4464
+ const savedId = savedGroup?.id;
4465
+ if (!draftGroup || typeof savedId !== "string" || savedId.length === 0) {
4466
+ continue;
4467
+ }
4468
+ this.savedGroupIds.set(draftGroup, savedId);
4469
+ }
4470
+ }
4471
+ savedGroupId(group) {
4472
+ const savedId = this.savedGroupIds.get(group);
4473
+ return typeof savedId === "string" && savedId.length > 0 ? savedId : void 0;
4474
+ }
4406
4475
  createCommandButton(label, command, disabled, data = {}, tone = "secondary") {
4407
4476
  const button = this.createButton(
4408
4477
  label,
@@ -24974,9 +24974,12 @@ Commands:
24974
24974
  install Install the native-messaging host manifest and (on capable
24975
24975
  platforms) provision the device-local CA (requires --extension-id).
24976
24976
  CA trust requires root/admin privileges (Linux: sudo, macOS: keychain
24977
- password, Windows: Administrator).
24977
+ password, Windows: Administrator). Transactional: when CA trust is
24978
+ unavailable the manifest is rolled back and the command exits 1.
24978
24979
  uninstall Remove the native-messaging host manifest and device-local CA trust
24979
24980
  (idempotent).
24981
+ verify Check that the manifest, runtime-host wrapper, allowed origins, and
24982
+ device-local CA trust are all present and valid.
24980
24983
  host [path] Run the native-messaging runtime host. The browser launches this
24981
24984
  process via the native-messaging manifest to handle rule matching.
24982
24985
 
@@ -24986,12 +24989,14 @@ Start/Stop controls, not the CLI. Run 'rogatio runtime install --extension-id
24986
24989
 
24987
24990
  Options:
24988
24991
  --extension-id Extension ID for native messaging manifest (required for install)
24989
- --root <dir> Root for confined runtime file access (default: project directory)
24992
+ --root <dir> Root for confined runtime file access (host only; default: project directory)
24993
+ --mock-port <n> Bind the loopback mock-response faucet to this port (host only, 1-65535)
24990
24994
  --help, -h Show this help
24991
24995
 
24992
24996
  Exit codes:
24993
24997
  0 Stopped cleanly / success
24994
- 1 Invalid project (diagnostics present) or file outside the root
24998
+ 1 Invalid project (diagnostics present), file outside the root, or a failed
24999
+ trust / verification check
24995
25000
  2 Error (IO or usage)`);
24996
25001
  }
24997
25002
  function showTestHelp() {
@@ -27328,11 +27333,11 @@ async function runtimeCommand(args, options = {}) {
27328
27333
  return 0;
27329
27334
  }
27330
27335
  const first = args[0];
27331
- if (first === "install" || first === "trust" || first === "uninstall" || first === "verify")
27336
+ if (first === "install" || first === "uninstall" || first === "verify")
27332
27337
  return trustRuntimeCommand(args);
27333
27338
  if (first === "host") return runtimeHostCommand(args.slice(1), options);
27334
27339
  console.error(
27335
- `Error: 'rogatio runtime' no longer starts or stops the runtime. Use 'rogatio runtime install|uninstall' to manage the host manifest and request-body trust, or 'rogatio runtime host [path]' to run the native-messaging host. Start/stop is driven from the extension's controls.`
27340
+ `Error: 'rogatio runtime' no longer starts or stops the runtime. Use 'rogatio runtime install|uninstall|verify' to manage the host manifest and request-body trust, or 'rogatio runtime host [path]' to run the native-messaging host. Start/stop is driven from the extension's controls.`
27336
27341
  );
27337
27342
  showRuntimeHelp();
27338
27343
  return 2;
@@ -27907,8 +27912,9 @@ Commands:
27907
27912
  edit [path] Launch browser editor for .rogatio.json
27908
27913
  test [path] [url...] Run offline dry-run tests against .rogatio.json
27909
27914
  verify [path] Validate .rogatio.json file
27910
- runtime <install|uninstall|host> Native messaging runtime control
27915
+ runtime <install|uninstall|verify|host> Native messaging runtime control
27911
27916
  runtime host [path] Run the native-messaging runtime host
27917
+ ai <setup|ls|show|delete|test> AI provider configuration
27912
27918
 
27913
27919
  Global Options:
27914
27920
  --help, -h Show help
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogatio/cli",
3
- "version": "6.0.1",
3
+ "version": "6.1.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local-first browser request and response rules — editor host, file verification, test runner, and runtime dispatch.",