@ricsam/r5dctl 0.0.73 → 0.0.74

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
@@ -109,8 +109,18 @@ r5dctl k8s usage
109
109
  r5dctl k8s usage --namespace default --workload api --container server
110
110
  r5dctl k8s usage --window 7d
111
111
  r5dctl k8s usage --workload default/api --window 7d --json
112
+ r5dctl vcluster trusted-workflow add --repo owner/repository --workflow .github/workflows/deploy.yml
113
+ r5dctl vcluster trusted-workflow list
114
+ r5dctl vcluster trusted-workflow remove <workflow-id>
112
115
  ```
113
116
 
117
+ Trusted workflows authenticate Kubernetes through the dedicated
118
+ `ricsam/r5d-cluster-auth` GitHub Action. They do not run or authenticate
119
+ `r5dctl` inside GitHub Actions, and no R5D secret needs to be stored in the
120
+ repository. Trust applies to that workflow path on every Git ref and grants
121
+ cluster-admin, so protect workflow changes and do not invoke it for untrusted
122
+ pull requests.
123
+
114
124
  `session start` creates an ordinary agent-mode chat on an explicitly selected existing worktree, or creates a named worktree from an explicit `worktree:<branch>` source. It requires project, worker, model, and prompt and never infers them from the current shell. Starts and prompts return after durable enqueue while execution continues asynchronously. Task specialization belongs in the prompt; there are no predefined debug, explore, research, or test agents. `session stop` returns as soon as the agent run is stopped; the stopped worktree's workspace publication finishes asynchronously behind the response, and `merge` republishes at its own boundary before reading the worktree.
115
125
 
116
126
  Add `-f`/`--follow`/`--watch` to `session start` to attach after enqueue, or to `conversation` to print the current transcript and follow new output. Assistant text is written to stdout and lifecycle/tool progress to stderr; `--tools` includes tool calls and results. With global `--json`, follow mode emits one JSON event per line. Ctrl-C only detaches and never stops the session. The CLI reconnects transiently interrupted event streams and resynchronizes committed conversation revisions without repeating assistant text.
package/dist/cjs/cli.cjs CHANGED
@@ -149,6 +149,9 @@ const PS_HELP_TEXT = [
149
149
  const K8S_HELP_TEXT = [
150
150
  "Usage:",
151
151
  " r5dctl k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
152
+ " r5dctl vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
153
+ " r5dctl vcluster trusted-workflow list",
154
+ " r5dctl vcluster trusted-workflow remove <workflow-id>",
152
155
  "",
153
156
  "Show current and rolling CPU and memory usage for managed-vCluster workload containers.",
154
157
  ""
@@ -305,6 +308,17 @@ const SHARED_HELP_ENTRIES = [
305
308
  usage: "k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
306
309
  description: "Show current and rolling CPU and memory usage for managed-vCluster workload containers."
307
310
  },
311
+ {
312
+ section: "kubernetes",
313
+ usage: "vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
314
+ description: "Trust an exact GitHub Actions workflow path to authenticate kubectl against your managed vCluster."
315
+ },
316
+ { section: "kubernetes", usage: "vcluster trusted-workflow list", description: "List trusted GitHub Actions workflows." },
317
+ {
318
+ section: "kubernetes",
319
+ usage: "vcluster trusted-workflow remove <workflow-id>",
320
+ description: "Revoke a trusted GitHub Actions workflow and its outstanding credentials."
321
+ },
308
322
  {
309
323
  section: "processes",
310
324
  usage: "ps list [--worker <label>]",
@@ -2642,6 +2656,40 @@ async function executeR5dctlCommand(client, json, args) {
2642
2656
  write(report, renderK8sUsageReport(report));
2643
2657
  return;
2644
2658
  }
2659
+ if (first === "vcluster" && second === "trusted-workflow") {
2660
+ const subcommand = requireValue(args[2], "Missing trusted-workflow command");
2661
+ if (subcommand === "add") {
2662
+ const parsed = parseCommandOperands(args.slice(3), /* @__PURE__ */ new Set(["--repo", "--workflow"]), /* @__PURE__ */ new Map(), "trusted-workflow add");
2663
+ if (parsed.positionals.length > 0) throw new Error(`Unexpected trusted-workflow add value: ${parsed.positionals[0]}`);
2664
+ const workflow = await client.k8s.trustedWorkflows.add({
2665
+ repository: requireValue(parsed.values.get("--repo"), "--repo <owner/repository> is required"),
2666
+ workflowPath: requireValue(parsed.values.get("--workflow"), "--workflow <path> is required")
2667
+ });
2668
+ write(workflow, "Trusted GitHub workflow configured successfully.\n");
2669
+ return;
2670
+ }
2671
+ if (subcommand === "list") {
2672
+ if (args.length > 3) throw new Error(`Unexpected trusted-workflow list value: ${args[3]}`);
2673
+ const workflows = await client.k8s.trustedWorkflows.list();
2674
+ write(
2675
+ workflows,
2676
+ workflows.length === 0 ? "No trusted GitHub workflows.\n" : `${workflows.map(
2677
+ (workflow) => `${workflow.id} ${workflow.repository} ${workflow.workflowPath} ${workflow.revokedAt ? "revoked" : "active"}`
2678
+ ).join("\n")}
2679
+ `
2680
+ );
2681
+ return;
2682
+ }
2683
+ if (subcommand === "remove") {
2684
+ const workflowId = requireValue(args[3], "Missing trusted workflow id");
2685
+ if (args.length > 4) throw new Error(`Unexpected trusted-workflow remove value: ${args[4]}`);
2686
+ const result = await client.k8s.trustedWorkflows.revoke(workflowId);
2687
+ if (!result.success) throw new Error("Trusted GitHub workflow was not found or was already revoked");
2688
+ write(result, "Trusted GitHub workflow revoked.\n");
2689
+ return;
2690
+ }
2691
+ throw new Error(`Unknown trusted-workflow command: ${subcommand}`);
2692
+ }
2645
2693
  if (first === "ps" && second === "list") {
2646
2694
  const processes = await client.processes.list(parsePsListArgs(args.slice(2)));
2647
2695
  write(processes, renderProcessList(processes));
@@ -3011,12 +3059,23 @@ function resolveCommandExecution(options, rest) {
3011
3059
  }
3012
3060
  if (command === "k8s") {
3013
3061
  const subcommand = commandArgs[0];
3014
- if (subcommand !== "usage") throw new Error(`Unknown k8s command: ${subcommand ?? ""}`.trim());
3015
3062
  if (options.project || options.branch || options.session) {
3016
- throw new Error("Project, branch, and session scopes are not supported for `k8s usage`");
3063
+ throw new Error("Project, branch, and session scopes are not supported for `k8s`");
3064
+ }
3065
+ if (subcommand === "usage") {
3066
+ parseK8sUsageArgs(commandArgs.slice(1));
3067
+ return { kind: "plugin", pluginArgs: ["k8s", "usage", ...commandArgs.slice(1)] };
3068
+ }
3069
+ throw new Error(`Unknown k8s command: ${subcommand ?? ""}`.trim());
3070
+ }
3071
+ if (command === "vcluster") {
3072
+ if (options.project || options.branch || options.session) {
3073
+ throw new Error("Project, branch, and session scopes are not supported for `vcluster`");
3074
+ }
3075
+ if (commandArgs[0] !== "trusted-workflow") {
3076
+ throw new Error(`Unknown vcluster command: ${commandArgs[0] ?? ""}`.trim());
3017
3077
  }
3018
- parseK8sUsageArgs(commandArgs.slice(1));
3019
- return { kind: "plugin", pluginArgs: ["k8s", "usage", ...commandArgs.slice(1)] };
3078
+ return { kind: "plugin", pluginArgs: ["vcluster", "trusted-workflow", ...commandArgs.slice(1)] };
3020
3079
  }
3021
3080
  if (command === "get") {
3022
3081
  const target = commandArgs[0];
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.73",
3
+ "version": "0.0.74",
4
4
  "type": "commonjs"
5
5
  }
package/dist/mjs/cli.mjs CHANGED
@@ -63,6 +63,9 @@ const PS_HELP_TEXT = [
63
63
  const K8S_HELP_TEXT = [
64
64
  "Usage:",
65
65
  " r5dctl k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
66
+ " r5dctl vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
67
+ " r5dctl vcluster trusted-workflow list",
68
+ " r5dctl vcluster trusted-workflow remove <workflow-id>",
66
69
  "",
67
70
  "Show current and rolling CPU and memory usage for managed-vCluster workload containers.",
68
71
  ""
@@ -219,6 +222,17 @@ const SHARED_HELP_ENTRIES = [
219
222
  usage: "k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
220
223
  description: "Show current and rolling CPU and memory usage for managed-vCluster workload containers."
221
224
  },
225
+ {
226
+ section: "kubernetes",
227
+ usage: "vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
228
+ description: "Trust an exact GitHub Actions workflow path to authenticate kubectl against your managed vCluster."
229
+ },
230
+ { section: "kubernetes", usage: "vcluster trusted-workflow list", description: "List trusted GitHub Actions workflows." },
231
+ {
232
+ section: "kubernetes",
233
+ usage: "vcluster trusted-workflow remove <workflow-id>",
234
+ description: "Revoke a trusted GitHub Actions workflow and its outstanding credentials."
235
+ },
222
236
  {
223
237
  section: "processes",
224
238
  usage: "ps list [--worker <label>]",
@@ -2556,6 +2570,40 @@ async function executeR5dctlCommand(client, json, args) {
2556
2570
  write(report, renderK8sUsageReport(report));
2557
2571
  return;
2558
2572
  }
2573
+ if (first === "vcluster" && second === "trusted-workflow") {
2574
+ const subcommand = requireValue(args[2], "Missing trusted-workflow command");
2575
+ if (subcommand === "add") {
2576
+ const parsed = parseCommandOperands(args.slice(3), /* @__PURE__ */ new Set(["--repo", "--workflow"]), /* @__PURE__ */ new Map(), "trusted-workflow add");
2577
+ if (parsed.positionals.length > 0) throw new Error(`Unexpected trusted-workflow add value: ${parsed.positionals[0]}`);
2578
+ const workflow = await client.k8s.trustedWorkflows.add({
2579
+ repository: requireValue(parsed.values.get("--repo"), "--repo <owner/repository> is required"),
2580
+ workflowPath: requireValue(parsed.values.get("--workflow"), "--workflow <path> is required")
2581
+ });
2582
+ write(workflow, "Trusted GitHub workflow configured successfully.\n");
2583
+ return;
2584
+ }
2585
+ if (subcommand === "list") {
2586
+ if (args.length > 3) throw new Error(`Unexpected trusted-workflow list value: ${args[3]}`);
2587
+ const workflows = await client.k8s.trustedWorkflows.list();
2588
+ write(
2589
+ workflows,
2590
+ workflows.length === 0 ? "No trusted GitHub workflows.\n" : `${workflows.map(
2591
+ (workflow) => `${workflow.id} ${workflow.repository} ${workflow.workflowPath} ${workflow.revokedAt ? "revoked" : "active"}`
2592
+ ).join("\n")}
2593
+ `
2594
+ );
2595
+ return;
2596
+ }
2597
+ if (subcommand === "remove") {
2598
+ const workflowId = requireValue(args[3], "Missing trusted workflow id");
2599
+ if (args.length > 4) throw new Error(`Unexpected trusted-workflow remove value: ${args[4]}`);
2600
+ const result = await client.k8s.trustedWorkflows.revoke(workflowId);
2601
+ if (!result.success) throw new Error("Trusted GitHub workflow was not found or was already revoked");
2602
+ write(result, "Trusted GitHub workflow revoked.\n");
2603
+ return;
2604
+ }
2605
+ throw new Error(`Unknown trusted-workflow command: ${subcommand}`);
2606
+ }
2559
2607
  if (first === "ps" && second === "list") {
2560
2608
  const processes = await client.processes.list(parsePsListArgs(args.slice(2)));
2561
2609
  write(processes, renderProcessList(processes));
@@ -2925,12 +2973,23 @@ function resolveCommandExecution(options, rest) {
2925
2973
  }
2926
2974
  if (command === "k8s") {
2927
2975
  const subcommand = commandArgs[0];
2928
- if (subcommand !== "usage") throw new Error(`Unknown k8s command: ${subcommand ?? ""}`.trim());
2929
2976
  if (options.project || options.branch || options.session) {
2930
- throw new Error("Project, branch, and session scopes are not supported for `k8s usage`");
2977
+ throw new Error("Project, branch, and session scopes are not supported for `k8s`");
2978
+ }
2979
+ if (subcommand === "usage") {
2980
+ parseK8sUsageArgs(commandArgs.slice(1));
2981
+ return { kind: "plugin", pluginArgs: ["k8s", "usage", ...commandArgs.slice(1)] };
2982
+ }
2983
+ throw new Error(`Unknown k8s command: ${subcommand ?? ""}`.trim());
2984
+ }
2985
+ if (command === "vcluster") {
2986
+ if (options.project || options.branch || options.session) {
2987
+ throw new Error("Project, branch, and session scopes are not supported for `vcluster`");
2988
+ }
2989
+ if (commandArgs[0] !== "trusted-workflow") {
2990
+ throw new Error(`Unknown vcluster command: ${commandArgs[0] ?? ""}`.trim());
2931
2991
  }
2932
- parseK8sUsageArgs(commandArgs.slice(1));
2933
- return { kind: "plugin", pluginArgs: ["k8s", "usage", ...commandArgs.slice(1)] };
2992
+ return { kind: "plugin", pluginArgs: ["vcluster", "trusted-workflow", ...commandArgs.slice(1)] };
2934
2993
  }
2935
2994
  if (command === "get") {
2936
2995
  const target = commandArgs[0];
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.73",
3
+ "version": "0.0.74",
4
4
  "type": "module"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.73",
3
+ "version": "0.0.74",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/cli.cjs",
6
6
  "module": "./dist/mjs/cli.mjs",
@@ -26,7 +26,7 @@
26
26
  "r5dctl": "dist/cjs/main.cjs"
27
27
  },
28
28
  "dependencies": {
29
- "@ricsam/r5d-api": "^0.0.73",
29
+ "@ricsam/r5d-api": "^0.0.74",
30
30
  "dotenv": "^17",
31
31
  "qrcode": "^1.5.4",
32
32
  "ws": "^8.18.3"