@rulebricks/cli 2.1.6 → 2.3.1

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.
Files changed (114) hide show
  1. package/README.md +75 -14
  2. package/cluster-setup/aws/README.md +123 -0
  3. package/cluster-setup/aws/check-aws-access.sh +242 -0
  4. package/cluster-setup/aws/parameters.json +13 -0
  5. package/cluster-setup/aws/rulebricks-cluster.cfn.yaml +355 -0
  6. package/cluster-setup/azure/README.md +141 -0
  7. package/cluster-setup/azure/check-aks-prereqs.sh +276 -0
  8. package/cluster-setup/azure/parameters.json +30 -0
  9. package/cluster-setup/azure/rulebricks-cluster.bicep +546 -0
  10. package/cluster-setup/gcp/README.md +189 -0
  11. package/cluster-setup/gcp/check-gke-prereqs.sh +260 -0
  12. package/dist/commands/backup.d.ts +5 -0
  13. package/dist/commands/backup.js +104 -0
  14. package/dist/commands/deploy.d.ts +3 -1
  15. package/dist/commands/deploy.js +226 -326
  16. package/dist/commands/destroy.d.ts +1 -1
  17. package/dist/commands/destroy.js +73 -123
  18. package/dist/commands/init.d.ts +5 -1
  19. package/dist/commands/init.js +78 -47
  20. package/dist/commands/list.d.ts +1 -0
  21. package/dist/commands/list.js +74 -0
  22. package/dist/commands/open.d.ts +1 -1
  23. package/dist/commands/open.js +4 -12
  24. package/dist/commands/redeploy.d.ts +6 -0
  25. package/dist/commands/redeploy.js +310 -0
  26. package/dist/commands/restore.d.ts +5 -0
  27. package/dist/commands/restore.js +338 -0
  28. package/dist/commands/status.js +62 -49
  29. package/dist/commands/upgrade.js +74 -51
  30. package/dist/components/DNSWaitScreen.d.ts +5 -1
  31. package/dist/components/DNSWaitScreen.js +47 -41
  32. package/dist/components/Wizard/WizardContext.d.ts +174 -29
  33. package/dist/components/Wizard/WizardContext.js +896 -91
  34. package/dist/components/Wizard/steps/CloudProviderStep.js +192 -102
  35. package/dist/components/Wizard/steps/DomainStep.js +5 -24
  36. package/dist/components/Wizard/steps/ExternalServicesStep.d.ts +6 -0
  37. package/dist/components/Wizard/steps/ExternalServicesStep.js +645 -0
  38. package/dist/components/Wizard/steps/FeatureConfigStep.d.ts +2 -1
  39. package/dist/components/Wizard/steps/FeatureConfigStep.js +959 -248
  40. package/dist/components/Wizard/steps/FeaturesStep.js +31 -35
  41. package/dist/components/Wizard/steps/ObservabilityStep.d.ts +6 -0
  42. package/dist/components/Wizard/steps/ObservabilityStep.js +137 -0
  43. package/dist/components/Wizard/steps/ReviewStep.d.ts +2 -1
  44. package/dist/components/Wizard/steps/ReviewStep.js +56 -7
  45. package/dist/components/Wizard/steps/StorageStep.d.ts +9 -0
  46. package/dist/components/Wizard/steps/StorageStep.js +592 -0
  47. package/dist/components/Wizard/steps/SupabaseCredentialsStep.js +20 -21
  48. package/dist/components/Wizard/steps/VersionStep.js +45 -23
  49. package/dist/components/Wizard/steps/index.d.ts +3 -3
  50. package/dist/components/Wizard/steps/index.js +3 -3
  51. package/dist/components/common/CommandApproval.d.ts +12 -0
  52. package/dist/components/common/CommandApproval.js +91 -0
  53. package/dist/components/common/DeploymentPicker.d.ts +14 -0
  54. package/dist/components/common/DeploymentPicker.js +16 -0
  55. package/dist/components/common/index.d.ts +2 -0
  56. package/dist/components/common/index.js +2 -0
  57. package/dist/index.js +94 -62
  58. package/dist/lib/cloudCli.d.ts +134 -63
  59. package/dist/lib/cloudCli.js +512 -220
  60. package/dist/lib/clusterSetupDefaults.d.ts +30 -0
  61. package/dist/lib/clusterSetupDefaults.js +64 -0
  62. package/dist/lib/commandApproval.d.ts +26 -0
  63. package/dist/lib/commandApproval.js +114 -0
  64. package/dist/lib/config.d.ts +12 -10
  65. package/dist/lib/config.js +91 -33
  66. package/dist/lib/configFixtures.d.ts +5 -0
  67. package/dist/lib/configFixtures.js +513 -0
  68. package/dist/lib/deploymentHealth.d.ts +32 -0
  69. package/dist/lib/deploymentHealth.js +157 -0
  70. package/dist/lib/dns.d.ts +1 -1
  71. package/dist/lib/dns.js +19 -1
  72. package/dist/lib/dns.test.d.ts +1 -0
  73. package/dist/lib/dns.test.js +27 -0
  74. package/dist/lib/dockerHub.d.ts +12 -1
  75. package/dist/lib/dockerHub.js +18 -8
  76. package/dist/lib/helm.d.ts +4 -0
  77. package/dist/lib/helm.js +16 -0
  78. package/dist/lib/helmValues.d.ts +25 -0
  79. package/dist/lib/helmValues.js +1937 -259
  80. package/dist/lib/helmValues.test.d.ts +1 -0
  81. package/dist/lib/helmValues.test.js +966 -0
  82. package/dist/lib/htpasswd.d.ts +1 -0
  83. package/dist/lib/htpasswd.js +15 -0
  84. package/dist/lib/kubernetes.d.ts +126 -13
  85. package/dist/lib/kubernetes.js +624 -134
  86. package/dist/lib/secrets.d.ts +23 -0
  87. package/dist/lib/secrets.js +158 -0
  88. package/dist/lib/validateValues.d.ts +31 -0
  89. package/dist/lib/validateValues.js +253 -0
  90. package/dist/lib/versions.d.ts +82 -11
  91. package/dist/lib/versions.js +131 -31
  92. package/dist/lib/versions.test.d.ts +1 -0
  93. package/dist/lib/versions.test.js +81 -0
  94. package/dist/lib/wizardSteps.d.ts +14 -0
  95. package/dist/lib/wizardSteps.js +23 -0
  96. package/dist/lib/workloadIdentity.d.ts +26 -0
  97. package/dist/lib/workloadIdentity.js +323 -0
  98. package/dist/lib/workloadIdentity.test.d.ts +1 -0
  99. package/dist/lib/workloadIdentity.test.js +57 -0
  100. package/dist/types/index.d.ts +2152 -95
  101. package/dist/types/index.js +554 -286
  102. package/package.json +10 -4
  103. package/schema/values.schema.json +1934 -0
  104. package/dist/components/Wizard/steps/CredentialsStep.d.ts +0 -6
  105. package/dist/components/Wizard/steps/CredentialsStep.js +0 -22
  106. package/dist/components/Wizard/steps/DeploymentModeStep.d.ts +0 -5
  107. package/dist/components/Wizard/steps/DeploymentModeStep.js +0 -26
  108. package/dist/components/Wizard/steps/TierStep.d.ts +0 -6
  109. package/dist/components/Wizard/steps/TierStep.js +0 -29
  110. package/dist/lib/terraform.d.ts +0 -66
  111. package/dist/lib/terraform.js +0 -754
  112. package/terraform/aws/main.tf +0 -355
  113. package/terraform/azure/main.tf +0 -371
  114. package/terraform/gcp/main.tf +0 -407
@@ -1,6 +1,96 @@
1
1
  import { CHANGELOG_URL, getNamespace, getReleaseName, } from "../types/index.js";
2
2
  import { fetchChartVersions, getInstalledVersion } from "./helm.js";
3
3
  import { fetchAllImageTags, normalizeVersion, } from "./dockerHub.js";
4
+ // ============================================================================
5
+ // Image registry & repositories
6
+ // ============================================================================
7
+ // Every image the chart pulls now lives under docker.io/rulebricks/* (mirrored
8
+ // or built by the helm repo's images/manifest.yaml pipeline). The CLI sets the
9
+ // rulebricks/* defaults; when config.imageRegistry is set, the registry HOST is
10
+ // rewritten per chart while the rulebricks/<name> path is kept. Names + tags
11
+ // here mirror images/manifest.yaml in the helm repo.
12
+ export const DEFAULT_IMAGE_REGISTRY = "docker.io";
13
+ // Self-hosted Supabase Postgres image (mirrored to rulebricks/*). The backup
14
+ // path uses pg_dump/rclone (no barman), so there is no custom fork.
15
+ export const SUPABASE_POSTGRES_IMAGE_REPOSITORY = "rulebricks/supabase-postgres";
16
+ export const SUPABASE_POSTGRES_IMAGE_TAG = "17.6.1.141";
17
+ // Cross-cloud uploader used by the backup CronJob and `rulebricks restore`.
18
+ export const RCLONE_IMAGE = "docker.io/rulebricks/rclone:1.71.1";
19
+ // kafka-proxy sidecar fronting MSK IAM brokers for Vector (mirrored to rulebricks/*).
20
+ export const KAFKA_PROXY_IMAGE = "docker.io/rulebricks/kafka-proxy:0.4.3";
21
+ /**
22
+ * Repository defaults (registry + repository + tag) for the rulebricks/* images
23
+ * the CLI sets directly: the app stack, clickstack, the kafka-proxy bridge, and
24
+ * the six Tier-2 upstream charts. The registry HOST is overridable via
25
+ * config.imageRegistry; the repository path (rulebricks/<name>) is never changed.
26
+ * Tags mirror images/manifest.yaml in the helm repo.
27
+ */
28
+ export const IMAGE_REPOSITORIES = {
29
+ // App stack (pinned by global.version, not by a fixed tag here)
30
+ app: "rulebricks/app",
31
+ hps: "rulebricks/hps",
32
+ // ClickStack
33
+ hyperdx: { repository: "rulebricks/hyperdx", tag: "2.19.0" },
34
+ clickstackOtelCollector: {
35
+ repository: "rulebricks/clickstack-otel-collector",
36
+ tag: "2.19.0",
37
+ },
38
+ ferretdb: { repository: "rulebricks/ferretdb", tag: "2.7.0" },
39
+ postgresDocumentdb: {
40
+ repository: "rulebricks/postgres-documentdb",
41
+ tag: "17-0.107.0-ferretdb-2.7.0",
42
+ },
43
+ // Parent-chart OpenTelemetry collector (BYO tracing, ClickStack disabled)
44
+ opentelemetryCollector: {
45
+ repository: "rulebricks/opentelemetry-collector",
46
+ tag: "0.155.0-debian13-contrib",
47
+ },
48
+ // Bridge sidecar
49
+ kafkaProxy: { repository: "rulebricks/kafka-proxy", tag: "v0.4.3" },
50
+ // Self-hosted Supabase Postgres
51
+ supabasePostgres: {
52
+ repository: "rulebricks/supabase-postgres",
53
+ tag: "17.6.1.141",
54
+ },
55
+ // --- Tier-2: kube-prometheus-stack sub-images ---
56
+ prometheus: "rulebricks/prometheus",
57
+ alertmanager: "rulebricks/alertmanager",
58
+ prometheusOperator: "rulebricks/prometheus-operator",
59
+ prometheusConfigReloader: "rulebricks/prometheus-config-reloader",
60
+ kubeWebhookCertgen: "rulebricks/kube-webhook-certgen",
61
+ grafana: "rulebricks/grafana",
62
+ k8sSidecar: "rulebricks/k8s-sidecar",
63
+ kubeStateMetrics: "rulebricks/kube-state-metrics",
64
+ nodeExporter: "rulebricks/node-exporter",
65
+ // --- Tier-2: cert-manager ---
66
+ certManagerController: "rulebricks/cert-manager-controller",
67
+ certManagerWebhook: "rulebricks/cert-manager-webhook",
68
+ certManagerCainjector: "rulebricks/cert-manager-cainjector",
69
+ certManagerStartupapicheck: "rulebricks/cert-manager-startupapicheck",
70
+ certManagerAcmesolver: "rulebricks/cert-manager-acmesolver",
71
+ // --- Tier-2: traefik / keda / vector / external-dns ---
72
+ traefik: "rulebricks/traefik",
73
+ keda: "rulebricks/keda",
74
+ kedaMetricsApiServer: "rulebricks/keda-metrics-apiserver",
75
+ kedaAdmissionWebhooks: "rulebricks/keda-admission-webhooks",
76
+ vector: "rulebricks/vector",
77
+ externalDns: "rulebricks/external-dns",
78
+ };
79
+ /**
80
+ * Generated name -> sha256 digest map. Populated by the helm repo's
81
+ * scripts/images/render-digests.sh (from images/digests.json); this const is
82
+ * regenerated by that script. Empty until the mirror pipeline runs. When a name
83
+ * is present, the chart image helper pins @sha256 instead of :tag, and the CLI
84
+ * threads this through global.imageDigests so the Tier-2 charts pin too.
85
+ */
86
+ export const IMAGE_DIGESTS = {};
87
+ export function hasRegistryDigestMismatch(deployedDigests, registryDigests) {
88
+ if (deployedDigests.length === 0 || !registryDigests?.length) {
89
+ return false;
90
+ }
91
+ const registryDigestSet = new Set(registryDigests);
92
+ return deployedDigests.some((digest) => !registryDigestSet.has(digest));
93
+ }
4
94
  /**
5
95
  * Fetches complete version information (legacy chart-based)
6
96
  */
@@ -21,51 +111,61 @@ export async function getVersionInfo(deploymentName, overrideNamespace) {
21
111
  changelogUrl: CHANGELOG_URL,
22
112
  };
23
113
  }
24
- /**
25
- * Normalizes a Date to the start of day (midnight UTC).
26
- * This allows comparing dates without time components.
27
- */
28
- function toStartOfDay(date) {
29
- const d = new Date(date);
30
- d.setUTCHours(0, 0, 0, 0);
31
- return d;
114
+ const KNOWN_BAD_PRODUCT_VERSIONS = new Set(["0.0.1"]);
115
+ function isSingleNodeArchitecture(architecture) {
116
+ return architecture === "amd64" || architecture === "arm64";
117
+ }
118
+ function supportsArchitecture(tag, architecture) {
119
+ if (!isSingleNodeArchitecture(architecture))
120
+ return true;
121
+ return tag.architectures.includes(architecture);
32
122
  }
33
123
  /**
34
- * Matches HPS versions to app versions based on release dates.
35
- * For each app version, finds the latest HPS version released on or before that date.
36
- * Compares dates only (ignoring time), so an HPS released later in the same day
37
- * as the app version will still be matched.
124
+ * Matches app versions to exact HPS server and worker versions.
38
125
  *
39
126
  * @param appTags - Array of app image tags
40
127
  * @param hpsTags - Array of HPS image tags
41
- * @returns Array of AppVersion with matched HPS versions
128
+ * @param hpsWorkerTags - Array of HPS worker image tags
129
+ * @returns Array of product versions with app, HPS, and worker images available
42
130
  */
43
- export function matchHpsVersions(appTags, hpsTags) {
44
- // Sort HPS tags by date descending for efficient matching
45
- const sortedHpsTags = [...hpsTags].sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime());
46
- return appTags.map((appTag) => {
47
- // Normalize app release date to start of day for comparison
48
- const appDateStart = toStartOfDay(appTag.lastUpdated);
49
- // Find the latest HPS version released on or before the app version's date
50
- // Compare by date only (start of day), ignoring time
51
- const matchedHps = sortedHpsTags.find((hpsTag) => toStartOfDay(hpsTag.lastUpdated).getTime() <= appDateStart.getTime());
131
+ export function matchExactHpsVersions(appTags, hpsTags, hpsWorkerTags, architecture) {
132
+ const compatibleAppTags = appTags.filter((tag) => supportsArchitecture(tag, architecture));
133
+ const hpsByVersion = new Map(hpsTags
134
+ .filter((tag) => supportsArchitecture(tag, architecture))
135
+ .map((tag) => [normalizeVersion(tag.name), tag]));
136
+ const workerByVersion = new Map(hpsWorkerTags
137
+ .filter((tag) => supportsArchitecture(tag, architecture))
138
+ .map((tag) => [normalizeVersion(tag.name.replace(/^worker-/, "")), tag]));
139
+ return compatibleAppTags
140
+ .flatMap((appTag) => {
141
+ const version = normalizeVersion(appTag.name);
142
+ if (KNOWN_BAD_PRODUCT_VERSIONS.has(version)) {
143
+ return [];
144
+ }
145
+ const matchedHps = hpsByVersion.get(version);
146
+ const matchedWorker = workerByVersion.get(version);
147
+ if (!matchedHps || !matchedWorker) {
148
+ return [];
149
+ }
52
150
  return {
53
- version: normalizeVersion(appTag.name),
151
+ version,
54
152
  releaseDate: appTag.lastUpdated.toISOString(),
55
- hpsVersion: matchedHps ? normalizeVersion(matchedHps.name) : null,
56
153
  digest: appTag.digest,
154
+ hpsDigests: matchedHps.imageDigests,
155
+ hpsWorkerDigests: matchedWorker.imageDigests,
57
156
  };
58
- });
157
+ })
158
+ .sort((a, b) => compareVersions(b.version, a.version));
59
159
  }
60
160
  /**
61
- * Fetches app versions with matched HPS versions from Docker Hub
161
+ * Fetches product versions with app, HPS, and worker images from Docker Hub
62
162
  *
63
163
  * @param licenseKey - The Rulebricks license key (Docker PAT)
64
164
  * @returns Array of AppVersion objects
65
165
  */
66
- export async function fetchAppVersions(licenseKey) {
67
- const { appTags, hpsTags } = await fetchAllImageTags(licenseKey);
68
- return matchHpsVersions(appTags, hpsTags);
166
+ export async function fetchAppVersions(licenseKey, architecture) {
167
+ const { appTags, hpsTags, hpsWorkerTags } = await fetchAllImageTags(licenseKey);
168
+ return matchExactHpsVersions(appTags, hpsTags, hpsWorkerTags, architecture);
69
169
  }
70
170
  /**
71
171
  * Gets complete app version information for a deployment
@@ -74,8 +174,8 @@ export async function fetchAppVersions(licenseKey) {
74
174
  * @param currentAppVersion - Currently installed app version (if known)
75
175
  * @returns AppVersionInfo with current, latest, and available versions
76
176
  */
77
- export async function getAppVersionInfo(licenseKey, currentAppVersion) {
78
- const available = await fetchAppVersions(licenseKey);
177
+ export async function getAppVersionInfo(licenseKey, currentAppVersion, architecture) {
178
+ const available = await fetchAppVersions(licenseKey, architecture);
79
179
  const latest = available.length > 0 ? available[0] : null;
80
180
  // Find current version in available list
81
181
  const current = currentAppVersion
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,81 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { hasRegistryDigestMismatch, matchExactHpsVersions, } from "./versions.js";
4
+ import { extractImageDigest, extractImageTag } from "./kubernetes.js";
5
+ import { resolveDeploymentConfigVersion } from "./config.js";
6
+ import { classifyDeploymentHealth } from "./deploymentHealth.js";
7
+ function tag(name, digest = `sha256:${name.replace(/[^a-zA-Z0-9]/g, "")}`) {
8
+ return {
9
+ name,
10
+ lastUpdated: new Date(`2026-01-${name === "0.0.1" ? "31" : "01"}T00:00:00Z`),
11
+ digest,
12
+ imageDigests: [digest],
13
+ fullSize: 1,
14
+ architectures: ["amd64", "arm64"],
15
+ };
16
+ }
17
+ test("matches only exact app, HPS, and worker versions", () => {
18
+ const versions = matchExactHpsVersions([tag("1.8.17"), tag("1.8.16")], [tag("1.8.17")], [tag("worker-1.8.17")]);
19
+ assert.deepEqual(versions.map((version) => version.version), ["1.8.17"]);
20
+ });
21
+ test("sorts product versions by semver instead of Docker Hub update time", () => {
22
+ const versions = matchExactHpsVersions([tag("0.0.1"), tag("1.8.16"), tag("1.8.17")], [tag("0.0.1"), tag("1.8.16"), tag("1.8.17")], [tag("worker-0.0.1"), tag("worker-1.8.16"), tag("worker-1.8.17")]);
23
+ assert.deepEqual(versions.map((version) => version.version), ["1.8.17", "1.8.16"]);
24
+ });
25
+ test("detects same-version registry digest mismatches", () => {
26
+ assert.equal(hasRegistryDigestMismatch(["sha256:old"], ["sha256:new", "sha256:other"]), true);
27
+ assert.equal(hasRegistryDigestMismatch(["sha256:new"], ["sha256:new", "sha256:other"]), false);
28
+ });
29
+ test("extracts image tags and digests from Kubernetes image fields", () => {
30
+ assert.equal(extractImageTag("index.docker.io/rulebricks/hps:worker-1.8.17"), "worker-1.8.17");
31
+ assert.equal(extractImageDigest("docker-pullable://index.docker.io/rulebricks/hps@sha256:abc123"), "sha256:abc123");
32
+ });
33
+ test("resolves missing deployment config version from generated artifacts", () => {
34
+ assert.equal(resolveDeploymentConfigVersion({ chartVersion: "1.0.0" }, { global: { version: "2.0.0" } }, { application: { version: "1.5.0" } }), "2.0.0");
35
+ assert.equal(resolveDeploymentConfigVersion({ chartVersion: "1.0.0" }, undefined, { application: { version: "1.5.0" } }), "1.5.0");
36
+ assert.equal(resolveDeploymentConfigVersion({}), "latest");
37
+ });
38
+ test("classifies installed deployment health with HTTP reachability", () => {
39
+ const readyPod = {
40
+ name: "rulebricks-app",
41
+ status: "Running",
42
+ ready: true,
43
+ restarts: 0,
44
+ };
45
+ assert.equal(classifyDeploymentHealth({
46
+ state: null,
47
+ helmVersion: null,
48
+ pods: [],
49
+ httpReachable: false,
50
+ }), "not-installed");
51
+ assert.equal(classifyDeploymentHealth({
52
+ state: {
53
+ name: "demo",
54
+ version: "1.0.0",
55
+ createdAt: "",
56
+ updatedAt: "",
57
+ status: "destroyed",
58
+ },
59
+ helmVersion: null,
60
+ pods: [],
61
+ httpReachable: false,
62
+ }), "destroyed");
63
+ assert.equal(classifyDeploymentHealth({
64
+ state: null,
65
+ helmVersion: "1.0.0",
66
+ pods: [readyPod],
67
+ httpReachable: true,
68
+ }), "online");
69
+ assert.equal(classifyDeploymentHealth({
70
+ state: null,
71
+ helmVersion: "1.0.0",
72
+ pods: [readyPod],
73
+ httpReachable: false,
74
+ }), "installed-unreachable");
75
+ assert.equal(classifyDeploymentHealth({
76
+ state: null,
77
+ helmVersion: "1.0.0",
78
+ pods: [],
79
+ httpReachable: true,
80
+ }), "installed-degraded");
81
+ });
@@ -0,0 +1,14 @@
1
+ export type WizardStepId = "cloud" | "domain" | "smtp" | "database" | "database-creds" | "external-services" | "storage" | "observability" | "features" | "feature-config" | "version" | "review";
2
+ export interface WizardStepState {
3
+ databaseType: string | null;
4
+ aiEnabled: boolean;
5
+ ssoEnabled: boolean;
6
+ clickStackEnabled: boolean;
7
+ metricsExportEnabled: boolean;
8
+ tracingEnabled: boolean;
9
+ appLogsEnabled: boolean;
10
+ valkeyAdminEnabled: boolean;
11
+ loggingSink: string;
12
+ customEmailsEnabled: boolean;
13
+ }
14
+ export declare function getActiveWizardSteps(state: WizardStepState, mode: "create" | "redeploy"): WizardStepId[];
@@ -0,0 +1,23 @@
1
+ export function getActiveWizardSteps(state, mode) {
2
+ const steps = mode === "redeploy" ? [] : ["cloud"];
3
+ steps.push("domain", "smtp", "database");
4
+ if (state.databaseType === "self-hosted") {
5
+ steps.push("database-creds");
6
+ }
7
+ steps.push("external-services");
8
+ steps.push("storage");
9
+ steps.push("observability");
10
+ steps.push("features");
11
+ if (state.aiEnabled ||
12
+ state.ssoEnabled ||
13
+ (!state.clickStackEnabled && state.metricsExportEnabled) ||
14
+ (!state.clickStackEnabled && state.tracingEnabled) ||
15
+ (!state.clickStackEnabled && state.appLogsEnabled) ||
16
+ state.valkeyAdminEnabled ||
17
+ state.loggingSink !== "console" ||
18
+ state.customEmailsEnabled) {
19
+ steps.push("feature-config");
20
+ }
21
+ steps.push("version", "review");
22
+ return steps;
23
+ }
@@ -0,0 +1,26 @@
1
+ import { DeploymentConfig } from "../types/index.js";
2
+ export interface FederationOutcome {
3
+ created: string[];
4
+ existing: string[];
5
+ skipped?: string;
6
+ }
7
+ export declare function isAwsPodIdentityCliUnsupported(stderr: string): boolean;
8
+ export declare function isAwsPodIdentityTrustPolicyInvalid(stderr: string): boolean;
9
+ /** A Kubernetes ServiceAccount that needs cloud access, plus the cloud principal it maps to. */
10
+ interface SubjectBinding {
11
+ serviceAccount: string;
12
+ principal: string;
13
+ }
14
+ /**
15
+ * The SAs that need workload-identity trust, given the deployment config. Vector
16
+ * and the backup job use the storage identity; Prometheus uses the metrics
17
+ * identity (the consolidated setup makes these the same principal, but we read
18
+ * them independently so split setups still work).
19
+ */
20
+ export declare function plannedBindings(config: DeploymentConfig): SubjectBinding[];
21
+ /**
22
+ * Ensures the per-namespace workload-identity trust exists for this deployment.
23
+ * No-op (with a `skipped` reason) for non-cloud providers or secret-based auth.
24
+ */
25
+ export declare function ensureWorkloadIdentityFederation(config: DeploymentConfig): Promise<FederationOutcome>;
26
+ export {};