Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
5543c40
feat(sre): require registered authority and isolate Kubernetes creden…
pallakatos Sep 8, 2026
05b3a77
fix(cli): reject invalid push targets before SRE preflight
pallakatos Sep 8, 2026
941d6c2
fix(sre): complete status conventions and verify request boundaries
pallakatos Sep 8, 2026
9978768
test(sre): initialize TLS provider in isolated boundary regression
pallakatos Sep 8, 2026
3c9523e
test(sre): repair schema-valid authority acceptance fixtures
pallakatos Sep 8, 2026
e9e1038
ci(sre): validate public registration schema before image-dependent t…
pallakatos Sep 8, 2026
e2aefef
test(sre): compare API-evidenced CEL namespace accessors
pallakatos Sep 8, 2026
447312d
fix(sre): escape custom namespace fields in registration CEL
pallakatos Sep 8, 2026
8616229
fix(cli): preserve SRE release discovery on Helm 3 and 4
pallakatos Sep 8, 2026
7f7a4ac
test(sre): defer custom readiness until explicit migration
pallakatos Sep 8, 2026
ee24037
Merge assembled credential foundations into SRE prerequisite
pallakatos Sep 8, 2026
bc392ce
test(sre): capture controller admission before teardown
pallakatos Sep 8, 2026
9a3921c
test(sre): parse kubectl multi-object diagnostic output
pallakatos Sep 8, 2026
cc3c008
test(sre): retain fatal policy wait while collecting Pod evidence
pallakatos Sep 8, 2026
436fa33
test(sre): capture control-plane health without log contents
pallakatos Sep 8, 2026
b19d597
test(sre): prove preserved JSON schema candidate on actual API
pallakatos Sep 8, 2026
4e012ec
fix(sre): preserve action JSON without the Kubernetes nil-schema crash
pallakatos Sep 8, 2026
d9910d4
test(sre): stabilize real token fixtures without minting credentials
pallakatos Sep 8, 2026
ae692a3
test(sre): retain sanitized migration rejection coordinates
pallakatos Sep 8, 2026
59f25ac
test(sre): preserve token fixture parents after cleanup conflicts
pallakatos Sep 8, 2026
fa09d3b
test(sre): prove controller retirement bind authority on real Kind
pallakatos Sep 8, 2026
b935015
test(sre): use the exact pinned legacy chart file set
pallakatos Sep 8, 2026
c1d14fa
test(sre): distinguish the real immutable-UID retirement rejection
pallakatos Sep 8, 2026
b8d130d
fix(sre): preflight reviewed binding retirement with narrow authority
pallakatos Sep 8, 2026
105da37
test(e2e): establish immutable legacy CRDs before Helm hooks
pallakatos Sep 9, 2026
7d4656f
test(e2e): preserve Helm ownership in historical CRD bootstrap
pallakatos Sep 9, 2026
83850fa
test(e2e): let Helm own historical CRD creation and readiness
pallakatos Sep 9, 2026
0137a05
test(e2e): diagnose built-in controller private ReplicaSet admission
pallakatos Sep 9, 2026
91e4f32
chore(deps): qualify approved js-yaml 4.3.2 patch locks
pallakatos Sep 9, 2026
c967be0
chore(deps): persist verified js-yaml 4.3.2 patch locks
pallakatos Sep 9, 2026
c08465a
fix(sre): authorize the Deployment controller's ReplicaSet handoff
pallakatos Sep 9, 2026
3421791
test(e2e): isolate distroless SRE readiness command failures
pallakatos Sep 9, 2026
f319d83
fix(sre): expose bounded authority-readiness failure diagnostics
pallakatos Sep 9, 2026
7c7aefb
test(e2e): parse actual JSON readiness diagnostics
pallakatos Sep 9, 2026
3f70e35
test(e2e): distinguish router startup from readiness checks
pallakatos Sep 9, 2026
e243f08
fix(sre): trace bounded TLS and authority readiness stages
pallakatos Sep 9, 2026
63f5225
test(e2e): isolate private router API transport failures
pallakatos Sep 9, 2026
cf2f274
test(e2e): compare same-node API connectivity without credentials
pallakatos Sep 9, 2026
4f6e95a
test(e2e): inspect exact Pod firewall state without mutations
pallakatos Sep 9, 2026
e2f6801
test(e2e): isolate guard backend effects in owned empty Pods
pallakatos Sep 9, 2026
e4aaf00
test(e2e): compare isolated network policy enforcement
pallakatos Sep 9, 2026
2700071
test(e2e): prove exact post-DNAT API egress without agent bypass
pallakatos Sep 9, 2026
6b01d03
fix(sre): allow exact ready API endpoints after service DNAT
pallakatos Sep 9, 2026
42e2fcd
test(e2e): expose safe HTTP status at the real Hermes boundary
pallakatos Sep 9, 2026
026cda4
fix(sre): filter native SecretList items without per-item TypeMeta
pallakatos Sep 9, 2026
41820a2
test(e2e): diagnose Kubernetes log media without exposing logs
pallakatos Sep 9, 2026
4b4a92a
fix(sre): negotiate Kubernetes log streams with supported media
pallakatos Sep 9, 2026
e2b31f5
test(e2e): prove guarded canonical consumer cleanup authority
pallakatos Sep 9, 2026
38aba96
test(e2e): hand off only the owned consumer to cleanup proof
pallakatos Sep 9, 2026
f979d1f
test(e2e): qualify ReplicaSet updates and forged owner references
pallakatos Sep 9, 2026
6816956
fix(sre): remove only the quiesced owned consumer before retirement
pallakatos Sep 9, 2026
acd34cb
fix(sre): preserve protected names during collection deletion
pallakatos Sep 9, 2026
5c9be46
fix(sre): guard collection names with explicit CEL presence checks
pallakatos Sep 10, 2026
633095a
test(e2e): retain only public compiler vocabulary in policy failures
pallakatos Sep 10, 2026
3f20fac
fix(sre): avoid mixed string and dyn lists in collection guards
pallakatos Sep 10, 2026
6ec8542
test(e2e): verify the explicitly configured Hermes image pin
pallakatos Sep 10, 2026
203e232
test(e2e): fence collection previews against status-only RV races
pallakatos Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 86 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ jobs:
# transitive oci-client→reqwest) compiles natively with the
# runner's gcc.
run: cargo build --release --workspace
- name: Legacy Hermes HTTPS client test dependency
if: needs.changes.outputs.code == 'true'
run: python3 -m pip install 'httpx==0.28.1'
- name: cargo nextest run (release)
if: needs.changes.outputs.code == 'true'
# Reuses the target/release/ artefacts the previous step just
Expand Down Expand Up @@ -393,6 +396,67 @@ jobs:
- name: RBAC idempotency gate
run: python3 ci/bicep-rbac-idempotency.py

sre-crd-schema:
name: SRE CRD API Schema
runs-on: ubuntu-latest
timeout-minutes: 10
env:
KUBECONFIG: ${{ github.workspace }}/.e2e-sre-schema-kubeconfig
PYTHONDONTWRITEBYTECODE: "1"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Same pinned tools and unmodified node configuration as e2e-kind.
# Kind v0.24.0 defaults to the observed kindest/node:v1.31.0 image.
- uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
with:
install_only: true
version: v0.24.0
- uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d # v4
with:
version: v1.30.5
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
- name: Check public-schema diagnostic privacy
run: PYTHONPATH=tests/e2e python3 -m unittest sre_authority.registration_schema_test sre_authority.bootstrap_probe_test sre_authority.binding_probe_test sre_authority.legacy_crds_test
- name: Create the same disposable API server as the real harness
run: kind create cluster --name kars-e2e --config tests/e2e/kind-config.yaml --kubeconfig "$KUBECONFIG"
- name: Prove native historical Helm wait orders CRDs before hooks and permits schema upgrades
run: PYTHONPATH=tests/e2e python3 -m sre_authority.legacy_crd_probe
- name: Reset disposable cluster after historical Helm proof
run: |
kind delete cluster --name kars-e2e
kind create cluster --name kars-e2e --config tests/e2e/kind-config.yaml --kubeconfig "$KUBECONFIG"
- name: Validate the SRE CRD against the actual API server
id: sre_schema
run: python3 tests/e2e/sre_authority/registration_schema.py --exercise
- name: Prove controller Pod admission with all chart policies and no image execution
id: sre_bootstrap
run: PYTHONPATH=tests/e2e python3 -m sre_authority.bootstrap_probe --retirement-bind-proof
- name: Collect nil-schema adapter candidate evidence without weakening production gates
if: failure() && steps.sre_bootstrap.outcome == 'failure'
run: PYTHONPATH=tests/e2e python3 -m sre_authority.bootstrap_probe --json-params-candidate
- name: Collect namespace-accessor candidate evidence without relaxing the failing production gate
if: failure() && steps.sre_schema.outcome == 'failure'
run: python3 tests/e2e/sre_authority/registration_schema.py --namespace-accessor-candidate --exercise
- name: Upload only public CRD schema evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4
with:
name: sre-crd-schema-${{ github.run_id }}
path: |
e2e-sre-schema-diag/versions.json
e2e-sre-schema-diag/legacy-helm-readiness.json
e2e-sre-schema-diag/validation.json
e2e-sre-schema-diag/validation-instances.json
e2e-sre-schema-diag/namespace-accessor-candidate.json
e2e-sre-schema-diag/namespace-accessor-candidate-instances.json
e2e-sre-schema-diag/bootstrap-*.json
e2e-sre-schema-diag/candidate-bootstrap-*.json
if-no-files-found: warn
retention-days: 7
- name: Remove disposable schema cluster
if: always()
run: kind delete cluster --name kars-e2e

helm-lint:
name: Helm Lint
runs-on: ubuntu-latest
Expand Down Expand Up @@ -572,7 +636,7 @@ jobs:
# Fetch enough history to diff.
git fetch --no-tags --depth=50 origin "$base" "$head" 2>/dev/null || true
if git diff --name-only "$base" "$head" 2>/dev/null \
| grep -E '^(controller/|inference-router/|a2a-gateway/|kars-a2a-core/|deploy/helm/|sandbox-images/|tests/e2e/|Cargo\.toml|Cargo\.lock|Makefile)' >/dev/null; then
| grep -E '^(controller/|inference-router/|a2a-gateway/|kars-a2a-core/|deploy/helm/|sandbox-images/|tests/e2e/|shared/|runtimes/hermes/src/kars_runtime_hermes/plugin/sre|cli/src/(commands/sre|lib/sre|lib/namespace-ownership)|Cargo\.toml|Cargo\.lock|Makefile)' >/dev/null; then
echo "run=true" >> "$GITHUB_OUTPUT"
else
echo "run=false" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -616,6 +680,21 @@ jobs:
docker system prune -af --volumes >/dev/null 2>&1 || true
df -h

- name: Set up Node for real SRE authority CLI acceptance
if: steps.paths.outputs.run == 'true'
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '22'
cache: npm
cache-dependency-path: cli/package-lock.json
- name: Build locked CLI for Kind acceptance
if: steps.paths.outputs.run == 'true'
working-directory: cli
run: npm ci && npm run build
- name: SRE Kind unchanged Hermes HTTPS client dependency
if: steps.paths.outputs.run == 'true'
run: python3 -m pip install 'httpx==0.28.1'

# Pre-built binaries from build-rust are COPY'd into the
# distroless runtime images; no `cargo build` runs inside Docker.
# Result: each image build is ~30s instead of ~8min.
Expand Down Expand Up @@ -690,7 +769,12 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4
with:
name: e2e-diagnostics-${{ github.run_id }}
path: e2e-diag/
path: |
e2e-diag/
e2e-sre-schema-diag/versions.json
e2e-sre-schema-diag/validation.json
e2e-sre-schema-diag/registration-create.json
e2e-sre-schema-diag/bootstrap-*.json
retention-days: 7

bench-regression:
Expand Down
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"
# with "Could not automatically determine the process-level
# CryptoProvider" when multiple feature flags resolve.
rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs"] }
rcgen = { version = "0.13.2", default-features = false, features = ["aws_lc_rs", "pem"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["aws_lc_rs"] }
rustls-pemfile = "2"
time = "0.3"
tower = { version = "0.5", features = ["limit"] }
tower-http = { version = "0.6", features = ["trace", "cors"] }
hyper = "1"
Expand Down
1 change: 1 addition & 0 deletions ci/no-custom-crypto.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ ALLOW_PATHS=(

# Production paths to scan.
PROD_PATHS=(
'shared/'
'controller/src/'
'inference-router/src/'
'cli/src/'
Expand Down
1 change: 1 addition & 0 deletions ci/no-stubs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ REPO_ROOT="$(git rev-parse --show-toplevel)"
cd "$REPO_ROOT"

PROD_PATHS=(
'shared/'
'controller/src/'
'inference-router/src/'
'cli/src/'
Expand Down
2 changes: 1 addition & 1 deletion ci/security-audit-required.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ REPO_ROOT="$(git rev-parse --show-toplevel)"
cd "$REPO_ROOT"

# Capability-introducing paths — mirrors §4.4 of the plan.
CAP_RE='^(controller/src/(crd|reconcilers|admission)|inference-router/src/(mcp|a2a|providers|routes)|cli/src/(commands|migrate|adapters)|runtimes/openclaw/src/(core|index\.ts)|sandbox-images/[^/]+/(Dockerfile|entrypoint\.sh)|cli/profiles/|deploy/seccomp/|deploy/helm/kars/files/)'
CAP_RE='^(controller/src/(crd|reconcilers|admission)|inference-router/src/(mcp|a2a|providers|routes)|cli/src/(commands|migrate|adapters)|runtimes/openclaw/src/(core|index\.ts)|sandbox-images/[^/]+/(Dockerfile|entrypoint\.sh)|cli/profiles/|deploy/seccomp/|deploy/helm/kars/files/|shared/.*\.rs$)'

changed=$(git diff --name-only "${BASE_REF}...HEAD" 2>/dev/null || git diff --name-only HEAD)
# Exclude test files — they exercise capabilities but don't introduce
Expand Down
6 changes: 6 additions & 0 deletions cli/src/commands/destroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { Command } from "commander";
import chalk from "chalk";
import ora from "ora";
import { assertDestroySafe } from "../lib/sre-authority.js";

export function destroyCommand(): Command {
const cmd = new Command("destroy");
Expand All @@ -22,6 +23,11 @@ export function destroyCommand(): Command {
const rg = options.resourceGroup || `kars-${options.region}`;
// Propagate --context to every kubectl invocation in this command.
const kctlCtx = options.context ? ["--context", options.context] : [];
if ((!options.local || options.cloud) && (!name || name === "sre" || options.all)) {
const { execa } = await import("execa");
await assertDestroySafe((file,args,commandOptions) =>
execa(file,[...kctlCtx,...args],commandOptions));
}

if (options.all) {
// Full teardown — delete the entire resource group
Expand Down
5 changes: 5 additions & 0 deletions cli/src/commands/dev/local-k8s.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { ensureAgtRepo, ensureAgtWheels } from "../../lib/agt-bootstrap.js";
import { resolveBundledAsset, requireBundledAsset, findRepoRootOrNull } from "../../lib/repo-assets.js";
import { buildCopilotFallbackChain } from "../../github-copilot.js";
import { CLAIM, prepareCredentialNamespace } from "../../lib/namespace-ownership.js";
import { assertSafeMutation } from "../../lib/sre-authority.js";

export interface LocalK8sOptions {
/** Sandbox / agent name. Reused as Helm release name suffix. */
Expand Down Expand Up @@ -1337,6 +1338,10 @@ export async function runLocalK8s(opts: LocalK8sOptions): Promise<void> {

stepper.step(`Ensuring kind cluster '${opts.clusterName}' exists…`);
await ensureCluster(tools.kind, opts.clusterName, tools.env);
await assertSafeMutation((file,args,commandOptions) => execa(
file === "kubectl" ? tools.kubectl : file,
["--context", `kind-${opts.clusterName}`, ...args], commandOptions,
));
stepper.done(`kind cluster '${opts.clusterName}' is ready`);

// Ensure the three local-dev images exist AND match the host arch.
Expand Down
8 changes: 8 additions & 0 deletions cli/src/commands/push-apply.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ function fixture(options: { legacyCore?: boolean; mesh?: "absent" | "helm" | "ex
}

describe("selected core push artifacts", () => {
it("still requires SRE authority preflight before resolving or applying valid core artifacts", async () => {
const f = fixture({ fail: "karssreregistrations.kars.azure.com" });
await expect(applyPushedImages(f.execute, [pushed("controller")], "chart"))
.rejects.toThrow("karssreregistrations.kars.azure.com");
expect(f.calls().some(([bin, args]) => bin === "az"
|| ["upgrade", "patch", "annotate", "rollout"].includes(args[0]))).toBe(false);
});

it("moves a GHCR/pinned Helm controller to its pushed ACR digest without resetting customer values", async () => {
const f = fixture();
await applyPushedImages(f.execute, [pushed("controller")], "chart");
Expand Down
2 changes: 2 additions & 0 deletions cli/src/commands/push-apply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { coreImageValues, imageValueArgs, PUSH_COMPONENTS, resolvePushedArtifacts, type PushedImage } from "../lib/image-targets.js";
import { inspectCoreInstallation, recheckCoreOwnership, requireHealthyDeployment, updateLegacyCore, verifyCoreConfiguration } from "../lib/core-image-apply.js";
import { inspectSandboxPlans, refreshSandboxImages } from "../lib/sandbox-image-apply.js";
import { assertSafeMutation } from "../lib/sre-authority.js";

export interface PushApplyResult {
applied: string[];
Expand Down Expand Up @@ -41,6 +42,7 @@ export async function applyPushedImages(
throw new Error("External or absent AgentMesh cannot be updated; choose explicit core targets instead.");
}
if (core?.kind === "helm" && mesh) assertMeshReleaseConsistency(mesh, core.values);
await assertSafeMutation(execute);
const artifacts = await resolvePushedArtifacts(execute, deployable);
const coreImages = artifacts.filter(item => !isMesh(item));
const meshImages: MeshImages = {};
Expand Down
82 changes: 82 additions & 0 deletions cli/src/commands/sre-authority.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { Command } from "commander";
import { execa } from "execa";
import { requireBundledAsset } from "../lib/repo-assets.js";
import { enroll, preview, requireRegistrar, retire, waitForAuthority, type Execute } from "../lib/sre-authority.js";
import { stageSource } from "../lib/sre-source.js";
import { stageAuthority } from "../lib/sre-stage.js";

function executor(context?: string): Execute {
return (file, args, options) => execa(file, [
...(context ? [file === "helm" ? "--kube-context" : "--context", context] : []), ...args,
], options);
}

export function authorityCommand(): Command {
const command = new Command("authority").description("Stage, review, enroll and retire cluster-authorized SRE privacy");
const common = (name: string) => command.command(name)
.option("--namespace <namespace>", "Controller/release namespace", "kars-system")
.option("--release <release>", "Owning Helm release", "kars")
.option("--context <context>", "Kubernetes context");
common("stage")
.description("Explicit registrar staging: install authority APIs/controller while retaining legacy grants unchanged")
.requiredOption("--controller-image <image>", "Qualified prerequisite controller repository:tag")
.requiredOption("--router-image <image>", "Qualified prerequisite router repository:tag")
.option("--dry-run", "Server-side preview without deployment changes")
.action(async options => {
const execute = executor(options.context);
await stageAuthority(execute,requireBundledAsset("deploy/helm/kars"),options.namespace,options.release,
options.controllerImage,options.routerImage,!!options.dryRun);
console.log("Authority controller staged. Preview and explicitly enroll the exact SRE source/grants before normal upgrades.");
});
common("preview").description("Read exact enrollment identities and legacy grants; no mutations")
.action(async options => {
const spec = await preview(executor(options.context),options.namespace,options.release);
console.log(JSON.stringify(spec,null,2));
for (const binding of spec.legacyBindings) {
console.log(`--binding '${binding.kind}/${binding.namespace ?? ""}/${binding.name}=${binding.uid}@${binding.resourceVersion}'`);
}
if (spec.legacyConsumer) console.log(`--consumer '${spec.legacyConsumer.uid}@${spec.legacyConsumer.resourceVersion}'`);
});
common("stage-source").description("Atomically create a genuinely new, unprivileged SRE source and wait for its exact claim")
.option("--model <model>", "SRE model deployment")
.action(async options => {
const execute=executor(options.context);
await requireRegistrar(execute);
const result=await execute("helm",["template",options.release,requireBundledAsset("deploy/helm/kars"),
"--namespace",options.namespace,"--show-only","templates/sre.yaml",
"--set","sre.enabled=true","--set","azure.workloadIdentity.clientId=dummy",
...(options.model?["--set-string",`sre.model=${options.model}`]:[])],{stdio:"pipe"});
const created=await stageSource(execute,result.stdout,options.namespace,options.release);
console.log(`Created and claimed source: --sandbox-uid ${created.uid} --namespace-uid ${created.namespaceUid}`);
});
common("enroll").description("Enroll only reviewed source/namespace and grant UIDs under cluster registrar authority")
.requiredOption("--sandbox-uid <uid>", "Reviewed canonical Sandbox UID")
.requiredOption("--namespace-uid <uid>", "Reviewed claimed runtime namespace UID")
.option("--binding <review>", "Exact binding review from preview; repeat per binding", (value: string, all: string[]) => [...all,value], [])
.option("--consumer <uid@resourceVersion>", "Reviewed legacy SRE Deployment")
.option("--registration-uid <uid>", "Required when updating an existing registration")
.option("--resource-version <version>", "Required when updating an existing registration")
.option("--dry-run", "Print the enrollment without writing it")
.action(async options => {
const execute = executor(options.context);
const spec = await preview(execute,options.namespace,options.release);
console.log(await enroll(execute,spec,options,!!options.dryRun));
});
common("migrate").description("Wait for the controller to complete the explicitly enrolled migration")
.action(async options => {
await requireRegistrar(executor(options.context));
await waitForAuthority(executor(options.context),"Ready");
console.log("SRE authority Ready: legacy credentials denied and private renewable identity configured.");
});
common("retire").description("Disable and retire a reviewed registration before SRE uninstall")
.requiredOption("--registration-uid <uid>", "Reviewed registration UID")
.requiredOption("--resource-version <version>", "Reviewed registration resourceVersion")
.action(async options => {
await retire(executor(options.context),options.registrationUid,options.resourceVersion);
console.log("SRE authority Retired; owned private grants and credentials are revoked.");
});
return command;
}
Loading
Loading