@vibesdotdev/infra-deploy 0.0.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 (183) hide show
  1. package/README.md +125 -0
  2. package/SPEC.md +181 -0
  3. package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.d.ts +39 -0
  4. package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.d.ts.map +1 -0
  5. package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.js +61 -0
  6. package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.js.map +1 -0
  7. package/dist/cli/alerts/infra-alerts-create.cli-command.impl.d.ts +13 -0
  8. package/dist/cli/alerts/infra-alerts-create.cli-command.impl.d.ts.map +1 -0
  9. package/dist/cli/alerts/infra-alerts-create.cli-command.impl.js +109 -0
  10. package/dist/cli/alerts/infra-alerts-create.cli-command.impl.js.map +1 -0
  11. package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.d.ts +31 -0
  12. package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.d.ts.map +1 -0
  13. package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.js +36 -0
  14. package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.js.map +1 -0
  15. package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.d.ts +11 -0
  16. package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.d.ts.map +1 -0
  17. package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.js +67 -0
  18. package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.js.map +1 -0
  19. package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.d.ts +21 -0
  20. package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.d.ts.map +1 -0
  21. package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.js +27 -0
  22. package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.js.map +1 -0
  23. package/dist/cli/alerts/infra-alerts-list.cli-command.impl.d.ts +12 -0
  24. package/dist/cli/alerts/infra-alerts-list.cli-command.impl.d.ts.map +1 -0
  25. package/dist/cli/alerts/infra-alerts-list.cli-command.impl.js +74 -0
  26. package/dist/cli/alerts/infra-alerts-list.cli-command.impl.js.map +1 -0
  27. package/dist/cli/alerts/infra-alerts.cli-group.descriptor.d.ts +12 -0
  28. package/dist/cli/alerts/infra-alerts.cli-group.descriptor.d.ts.map +1 -0
  29. package/dist/cli/alerts/infra-alerts.cli-group.descriptor.js +12 -0
  30. package/dist/cli/alerts/infra-alerts.cli-group.descriptor.js.map +1 -0
  31. package/dist/cli/audit/infra-audit.cli-command.descriptor.d.ts +21 -0
  32. package/dist/cli/audit/infra-audit.cli-command.descriptor.d.ts.map +1 -0
  33. package/dist/cli/audit/infra-audit.cli-command.descriptor.js +28 -0
  34. package/dist/cli/audit/infra-audit.cli-command.descriptor.js.map +1 -0
  35. package/dist/cli/audit/infra-audit.cli-command.impl.d.ts +18 -0
  36. package/dist/cli/audit/infra-audit.cli-command.impl.d.ts.map +1 -0
  37. package/dist/cli/audit/infra-audit.cli-command.impl.js +219 -0
  38. package/dist/cli/audit/infra-audit.cli-command.impl.js.map +1 -0
  39. package/dist/cli/infra-deploy.cli-group.descriptor.d.ts +12 -0
  40. package/dist/cli/infra-deploy.cli-group.descriptor.d.ts.map +1 -0
  41. package/dist/cli/infra-deploy.cli-group.descriptor.js +12 -0
  42. package/dist/cli/infra-deploy.cli-group.descriptor.js.map +1 -0
  43. package/dist/cli/infra.cli-group.descriptor.d.ts +11 -0
  44. package/dist/cli/infra.cli-group.descriptor.d.ts.map +1 -0
  45. package/dist/cli/infra.cli-group.descriptor.js +11 -0
  46. package/dist/cli/infra.cli-group.descriptor.js.map +1 -0
  47. package/dist/cli/list/infra-deploy.list.cli-command.descriptor.d.ts +34 -0
  48. package/dist/cli/list/infra-deploy.list.cli-command.descriptor.d.ts.map +1 -0
  49. package/dist/cli/list/infra-deploy.list.cli-command.descriptor.js +29 -0
  50. package/dist/cli/list/infra-deploy.list.cli-command.descriptor.js.map +1 -0
  51. package/dist/cli/list/infra-deploy.list.cli-command.impl.d.ts +5 -0
  52. package/dist/cli/list/infra-deploy.list.cli-command.impl.d.ts.map +1 -0
  53. package/dist/cli/list/infra-deploy.list.cli-command.impl.js +110 -0
  54. package/dist/cli/list/infra-deploy.list.cli-command.impl.js.map +1 -0
  55. package/dist/cli/logs/infra-logs.cli-command.descriptor.d.ts +39 -0
  56. package/dist/cli/logs/infra-logs.cli-command.descriptor.d.ts.map +1 -0
  57. package/dist/cli/logs/infra-logs.cli-command.descriptor.js +64 -0
  58. package/dist/cli/logs/infra-logs.cli-command.descriptor.js.map +1 -0
  59. package/dist/cli/logs/infra-logs.cli-command.impl.d.ts +5 -0
  60. package/dist/cli/logs/infra-logs.cli-command.impl.d.ts.map +1 -0
  61. package/dist/cli/logs/infra-logs.cli-command.impl.js +323 -0
  62. package/dist/cli/logs/infra-logs.cli-command.impl.js.map +1 -0
  63. package/dist/cli/logs/stream-worker-tail.d.ts +62 -0
  64. package/dist/cli/logs/stream-worker-tail.d.ts.map +1 -0
  65. package/dist/cli/logs/stream-worker-tail.js +165 -0
  66. package/dist/cli/logs/stream-worker-tail.js.map +1 -0
  67. package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.d.ts +27 -0
  68. package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.d.ts.map +1 -0
  69. package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.js +75 -0
  70. package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.js.map +1 -0
  71. package/dist/cli/npm/infra-npm-publish.cli-command.impl.d.ts +5 -0
  72. package/dist/cli/npm/infra-npm-publish.cli-command.impl.d.ts.map +1 -0
  73. package/dist/cli/npm/infra-npm-publish.cli-command.impl.js +383 -0
  74. package/dist/cli/npm/infra-npm-publish.cli-command.impl.js.map +1 -0
  75. package/dist/cli/npm/infra-npm.cli-group.descriptor.d.ts +12 -0
  76. package/dist/cli/npm/infra-npm.cli-group.descriptor.d.ts.map +1 -0
  77. package/dist/cli/npm/infra-npm.cli-group.descriptor.js +12 -0
  78. package/dist/cli/npm/infra-npm.cli-group.descriptor.js.map +1 -0
  79. package/dist/cli/observability/infra-observability-set.cli-command.descriptor.d.ts +25 -0
  80. package/dist/cli/observability/infra-observability-set.cli-command.descriptor.d.ts.map +1 -0
  81. package/dist/cli/observability/infra-observability-set.cli-command.descriptor.js +57 -0
  82. package/dist/cli/observability/infra-observability-set.cli-command.descriptor.js.map +1 -0
  83. package/dist/cli/observability/infra-observability-set.cli-command.impl.d.ts +17 -0
  84. package/dist/cli/observability/infra-observability-set.cli-command.impl.d.ts.map +1 -0
  85. package/dist/cli/observability/infra-observability-set.cli-command.impl.js +152 -0
  86. package/dist/cli/observability/infra-observability-set.cli-command.impl.js.map +1 -0
  87. package/dist/cli/observability/infra-observability-status.cli-command.descriptor.d.ts +21 -0
  88. package/dist/cli/observability/infra-observability-status.cli-command.descriptor.d.ts.map +1 -0
  89. package/dist/cli/observability/infra-observability-status.cli-command.descriptor.js +35 -0
  90. package/dist/cli/observability/infra-observability-status.cli-command.descriptor.js.map +1 -0
  91. package/dist/cli/observability/infra-observability-status.cli-command.impl.d.ts +17 -0
  92. package/dist/cli/observability/infra-observability-status.cli-command.impl.d.ts.map +1 -0
  93. package/dist/cli/observability/infra-observability-status.cli-command.impl.js +99 -0
  94. package/dist/cli/observability/infra-observability-status.cli-command.impl.js.map +1 -0
  95. package/dist/cli/observability/infra-observability.cli-group.descriptor.d.ts +12 -0
  96. package/dist/cli/observability/infra-observability.cli-group.descriptor.d.ts.map +1 -0
  97. package/dist/cli/observability/infra-observability.cli-group.descriptor.js +12 -0
  98. package/dist/cli/observability/infra-observability.cli-group.descriptor.js.map +1 -0
  99. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.d.ts +27 -0
  100. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.d.ts.map +1 -0
  101. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.js +35 -0
  102. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.js.map +1 -0
  103. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.d.ts +5 -0
  104. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.d.ts.map +1 -0
  105. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.js +99 -0
  106. package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.js.map +1 -0
  107. package/dist/cli/rum/infra-rum-status.cli-command.descriptor.d.ts +21 -0
  108. package/dist/cli/rum/infra-rum-status.cli-command.descriptor.d.ts.map +1 -0
  109. package/dist/cli/rum/infra-rum-status.cli-command.descriptor.js +27 -0
  110. package/dist/cli/rum/infra-rum-status.cli-command.descriptor.js.map +1 -0
  111. package/dist/cli/rum/infra-rum-status.cli-command.impl.d.ts +12 -0
  112. package/dist/cli/rum/infra-rum-status.cli-command.impl.d.ts.map +1 -0
  113. package/dist/cli/rum/infra-rum-status.cli-command.impl.js +88 -0
  114. package/dist/cli/rum/infra-rum-status.cli-command.impl.js.map +1 -0
  115. package/dist/cli/rum/infra-rum.cli-group.descriptor.d.ts +12 -0
  116. package/dist/cli/rum/infra-rum.cli-group.descriptor.d.ts.map +1 -0
  117. package/dist/cli/rum/infra-rum.cli-group.descriptor.js +12 -0
  118. package/dist/cli/rum/infra-rum.cli-group.descriptor.js.map +1 -0
  119. package/dist/cli/run/infra-deploy.run.cli-command.descriptor.d.ts +27 -0
  120. package/dist/cli/run/infra-deploy.run.cli-command.descriptor.d.ts.map +1 -0
  121. package/dist/cli/run/infra-deploy.run.cli-command.descriptor.js +49 -0
  122. package/dist/cli/run/infra-deploy.run.cli-command.descriptor.js.map +1 -0
  123. package/dist/cli/run/infra-deploy.run.cli-command.impl.d.ts +5 -0
  124. package/dist/cli/run/infra-deploy.run.cli-command.impl.d.ts.map +1 -0
  125. package/dist/cli/run/infra-deploy.run.cli-command.impl.js +272 -0
  126. package/dist/cli/run/infra-deploy.run.cli-command.impl.js.map +1 -0
  127. package/dist/cli/shared/discover-deployments.d.ts +41 -0
  128. package/dist/cli/shared/discover-deployments.d.ts.map +1 -0
  129. package/dist/cli/shared/discover-deployments.js +95 -0
  130. package/dist/cli/shared/discover-deployments.js.map +1 -0
  131. package/dist/config-loader.d.ts +24 -0
  132. package/dist/config-loader.d.ts.map +1 -0
  133. package/dist/config-loader.js +135 -0
  134. package/dist/config-loader.js.map +1 -0
  135. package/dist/index.d.ts +5 -0
  136. package/dist/index.d.ts.map +1 -0
  137. package/dist/index.js +4 -0
  138. package/dist/index.js.map +1 -0
  139. package/dist/infra-deploy.plugin.d.ts +3 -0
  140. package/dist/infra-deploy.plugin.d.ts.map +1 -0
  141. package/dist/infra-deploy.plugin.js +59 -0
  142. package/dist/infra-deploy.plugin.js.map +1 -0
  143. package/dist/regenerate.d.ts +55 -0
  144. package/dist/regenerate.d.ts.map +1 -0
  145. package/dist/regenerate.js +206 -0
  146. package/dist/regenerate.js.map +1 -0
  147. package/package.json +85 -0
  148. package/src/cli/alerts/infra-alerts-create.cli-command.descriptor.ts +61 -0
  149. package/src/cli/alerts/infra-alerts-create.cli-command.impl.ts +131 -0
  150. package/src/cli/alerts/infra-alerts-delete.cli-command.descriptor.ts +36 -0
  151. package/src/cli/alerts/infra-alerts-delete.cli-command.impl.ts +75 -0
  152. package/src/cli/alerts/infra-alerts-list.cli-command.descriptor.ts +27 -0
  153. package/src/cli/alerts/infra-alerts-list.cli-command.impl.ts +88 -0
  154. package/src/cli/alerts/infra-alerts.cli-group.descriptor.ts +12 -0
  155. package/src/cli/audit/infra-audit.cli-command.descriptor.ts +28 -0
  156. package/src/cli/audit/infra-audit.cli-command.impl.ts +293 -0
  157. package/src/cli/infra-deploy.cli-group.descriptor.ts +12 -0
  158. package/src/cli/infra.cli-group.descriptor.ts +11 -0
  159. package/src/cli/list/infra-deploy.list.cli-command.descriptor.ts +29 -0
  160. package/src/cli/list/infra-deploy.list.cli-command.impl.ts +125 -0
  161. package/src/cli/logs/infra-logs.cli-command.descriptor.ts +65 -0
  162. package/src/cli/logs/infra-logs.cli-command.impl.ts +354 -0
  163. package/src/cli/logs/stream-worker-tail.ts +202 -0
  164. package/src/cli/npm/infra-npm-publish.cli-command.descriptor.ts +75 -0
  165. package/src/cli/npm/infra-npm-publish.cli-command.impl.ts +474 -0
  166. package/src/cli/npm/infra-npm.cli-group.descriptor.ts +12 -0
  167. package/src/cli/observability/infra-observability-set.cli-command.descriptor.ts +57 -0
  168. package/src/cli/observability/infra-observability-set.cli-command.impl.ts +173 -0
  169. package/src/cli/observability/infra-observability-status.cli-command.descriptor.ts +35 -0
  170. package/src/cli/observability/infra-observability-status.cli-command.impl.ts +124 -0
  171. package/src/cli/observability/infra-observability.cli-group.descriptor.ts +12 -0
  172. package/src/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.ts +36 -0
  173. package/src/cli/regenerate/infra-deploy.regenerate.cli-command.impl.ts +103 -0
  174. package/src/cli/rum/infra-rum-status.cli-command.descriptor.ts +27 -0
  175. package/src/cli/rum/infra-rum-status.cli-command.impl.ts +112 -0
  176. package/src/cli/rum/infra-rum.cli-group.descriptor.ts +12 -0
  177. package/src/cli/run/infra-deploy.run.cli-command.descriptor.ts +49 -0
  178. package/src/cli/run/infra-deploy.run.cli-command.impl.ts +330 -0
  179. package/src/cli/shared/discover-deployments.ts +127 -0
  180. package/src/config-loader.ts +179 -0
  181. package/src/index.ts +11 -0
  182. package/src/infra-deploy.plugin.ts +83 -0
  183. package/src/regenerate.ts +230 -0
@@ -0,0 +1,173 @@
1
+ /**
2
+ * `vibes infra observability set [--worker NAME] [--filter GLOB]
3
+ * [--sampling 0.1] [--logs true|false]
4
+ * [--traces true|false] [--dry-run]`
5
+ *
6
+ * Writes observability config to one Worker, a glob-matched subset, or
7
+ * the entire fleet. `--dry-run` shows the diff without writing. Multi-
8
+ * worker writes require `--yes` confirmation.
9
+ *
10
+ * Skips Workers whose live settings already match the requested state
11
+ * (the impl handles this via `skipUnchanged`).
12
+ */
13
+
14
+ import { getVibesRuntime } from '@vibesdotdev/runtime';
15
+ import { requestCLIExit, type UIContext } from '@vibesdotdev/cli/providers';
16
+ import type {
17
+ ObservabilityImplementation,
18
+ ObservabilityScope,
19
+ ObservabilitySettings,
20
+ InfraObservabilityDescriptor,
21
+ SetObservabilityResult
22
+ } from '@vibesdotdev/infra-core';
23
+
24
+ function readString(v: unknown): string | undefined {
25
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
26
+ }
27
+
28
+ function readBoolean(v: unknown): boolean {
29
+ return v === true || v === 'true';
30
+ }
31
+
32
+ function parseBoolean(raw: string | undefined): boolean | undefined {
33
+ if (!raw) return undefined;
34
+ const v = raw.toLowerCase();
35
+ if (v === 'true' || v === '1' || v === 'on' || v === 'yes') return true;
36
+ if (v === 'false' || v === '0' || v === 'off' || v === 'no') return false;
37
+ return undefined;
38
+ }
39
+
40
+ function formatPct(rate: number | undefined): string {
41
+ if (rate === undefined) return '—';
42
+ return `${(rate * 100).toFixed(0)}%`;
43
+ }
44
+
45
+ export default {
46
+ async execute(_args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
47
+ const runtime = await getVibesRuntime();
48
+ const ui = (await runtime.context('cli/ui')) as UIContext;
49
+
50
+ const worker = readString(opts.worker);
51
+ const filter = readString(opts.filter);
52
+ const samplingRaw = readString(opts.sampling);
53
+ const logsEnabledRaw = readString(opts.logs);
54
+ const tracesEnabledRaw = readString(opts.traces);
55
+ const providerFilter = readString(opts.provider);
56
+ const dryRun = readBoolean(opts['dry-run']) || readBoolean(opts.dryRun);
57
+ const yes = readBoolean(opts.yes);
58
+ const output = readString(opts.output) ?? 'text';
59
+
60
+ // Build the partial settings update.
61
+ const update: ObservabilitySettings = {};
62
+ const logsUpdate: NonNullable<ObservabilitySettings['logs']> = { enabled: false };
63
+ let hasLogsField = false;
64
+ if (samplingRaw !== undefined) {
65
+ const sampling = Number(samplingRaw);
66
+ if (!Number.isFinite(sampling) || sampling < 0 || sampling > 1) {
67
+ ui.error(`--sampling must be a number in [0, 1]; got "${samplingRaw}".`);
68
+ requestCLIExit(1);
69
+ return;
70
+ }
71
+ logsUpdate.headSamplingRate = sampling;
72
+ // Sampling rate change implies logs stay enabled (CF gates head_sampling_rate behind enabled).
73
+ logsUpdate.enabled = true;
74
+ hasLogsField = true;
75
+ }
76
+ const logsToggle = parseBoolean(logsEnabledRaw);
77
+ if (logsToggle !== undefined) {
78
+ logsUpdate.enabled = logsToggle;
79
+ hasLogsField = true;
80
+ }
81
+ if (hasLogsField) update.logs = logsUpdate;
82
+
83
+ const tracesToggle = parseBoolean(tracesEnabledRaw);
84
+ if (tracesToggle !== undefined) {
85
+ update.traces = { enabled: tracesToggle };
86
+ }
87
+
88
+ if (!update.logs && !update.traces) {
89
+ ui.error('Nothing to change. Pass --sampling, --logs, or --traces.');
90
+ requestCLIExit(1);
91
+ return;
92
+ }
93
+
94
+ if (!runtime.hasKind('infra/observability')) {
95
+ ui.error('No infra/observability kind registered.');
96
+ requestCLIExit(1);
97
+ return;
98
+ }
99
+ const descriptors = runtime.assets('infra/observability').descriptors() as InfraObservabilityDescriptor[];
100
+ const target = providerFilter
101
+ ? descriptors.find((d) => d.adapter === providerFilter || d.id === providerFilter)
102
+ : descriptors[0];
103
+ if (!target) {
104
+ ui.error('No matching observability provider.');
105
+ requestCLIExit(1);
106
+ return;
107
+ }
108
+
109
+ const scope: ObservabilityScope = worker
110
+ ? { kind: 'worker', workerName: worker }
111
+ : { kind: 'account-wide', ...(filter ? { filter } : {}) };
112
+
113
+ const impl = (await runtime
114
+ .query('infra/observability')
115
+ .withId(target.id)
116
+ .resolve()) as ObservabilityImplementation;
117
+
118
+ // Multi-worker writes need confirmation (unless --yes).
119
+ if (scope.kind === 'account-wide' && !yes && !dryRun) {
120
+ ui.warn(
121
+ `About to update observability on every Worker matching ${
122
+ filter ? `glob "${filter}"` : 'all workers'
123
+ }.\nRe-run with --yes to confirm, or --dry-run to preview.`
124
+ );
125
+ requestCLIExit(0);
126
+ return;
127
+ }
128
+
129
+ if (dryRun) {
130
+ // Use getStatus to compute the diff, then print without writing.
131
+ const snapshots = await impl.getStatus(scope);
132
+ ui.info(`Dry run — ${snapshots.length} worker(s) in scope.`);
133
+ for (const s of snapshots) {
134
+ const beforeSample = s.settings.logs?.headSamplingRate;
135
+ const afterSample = update.logs?.headSamplingRate ?? beforeSample;
136
+ const change = beforeSample !== afterSample
137
+ ? `sampling ${formatPct(beforeSample)} → ${formatPct(afterSample)}`
138
+ : '(no change)';
139
+ ui.info(` ${s.workerName}: ${change}`);
140
+ }
141
+ return;
142
+ }
143
+
144
+ let result: SetObservabilityResult;
145
+ try {
146
+ result = await impl.set({ scope, settings: update });
147
+ } catch (err) {
148
+ ui.error(`Apply failed: ${err instanceof Error ? err.message : String(err)}`);
149
+ requestCLIExit(1);
150
+ return;
151
+ }
152
+
153
+ if (output === 'json') {
154
+ ui.json(result);
155
+ return;
156
+ }
157
+
158
+ ui.success(`Applied. changed=${result.changed.length} unchanged=${result.unchanged.length} failed=${result.failed.length}`);
159
+ for (const c of result.changed) {
160
+ const beforeRate = c.before.logs?.headSamplingRate;
161
+ const afterRate = c.after.logs?.headSamplingRate;
162
+ ui.info(` ${c.workerName}: sampling ${formatPct(beforeRate)} → ${formatPct(afterRate)}`);
163
+ }
164
+ if (result.unchanged.length > 0) {
165
+ ui.info(`\nUnchanged (already at target): ${result.unchanged.join(', ')}`);
166
+ }
167
+ if (result.failed.length > 0) {
168
+ ui.error('\nFailed:');
169
+ for (const f of result.failed) ui.error(` ${f.workerName}: ${f.error}`);
170
+ requestCLIExit(1);
171
+ }
172
+ }
173
+ };
@@ -0,0 +1,35 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-observability.status',
5
+ kind: 'cli/command',
6
+ name: 'status',
7
+ description: 'Read observability config (sampling, logs, traces) across Workers',
8
+ group: 'infra-observability',
9
+ options: [
10
+ {
11
+ flags: '--worker <name>',
12
+ description: 'Scope to a single Worker (omit for fleet-wide sweep)'
13
+ },
14
+ {
15
+ flags: '--filter <glob>',
16
+ description: 'Glob to narrow the fleet sweep (e.g. "vibes-*")'
17
+ },
18
+ {
19
+ flags: '--provider <id>',
20
+ description: 'Provider impl id (default: cloudflare-workers-observability)'
21
+ },
22
+ {
23
+ flags: '--environment <name>',
24
+ description: 'Vibes environment for secret resolution (local|dev|staging|production)'
25
+ },
26
+ {
27
+ flags: '-o, --output <format>',
28
+ description: 'Output format (text|json)',
29
+ default: 'text'
30
+ }
31
+ ],
32
+ surfaces: ['cli'],
33
+ hardware: ['consumer', 'cloud'],
34
+ enabled: true
35
+ });
@@ -0,0 +1,124 @@
1
+ /**
2
+ * `vibes infra observability status [--worker NAME] [--filter GLOB]`
3
+ *
4
+ * Reads observability config for one Worker, a glob-matched subset, or
5
+ * the entire fleet. Renders a table:
6
+ *
7
+ * worker logs.enabled logs.sample traces.enabled modified
8
+ * ---------------- ------------ ----------- -------------- ------------
9
+ * vibes-account true 100% false 2026-05-22T…
10
+ *
11
+ * `--output json` emits the raw ObservabilitySnapshot[] for piping.
12
+ */
13
+
14
+ import { getVibesRuntime } from '@vibesdotdev/runtime';
15
+ import { type UIContext } from '@vibesdotdev/cli/providers';
16
+ import type {
17
+ ObservabilityImplementation,
18
+ ObservabilitySnapshot,
19
+ ObservabilityScope,
20
+ InfraObservabilityDescriptor
21
+ } from '@vibesdotdev/infra-core';
22
+
23
+ function readString(v: unknown): string | undefined {
24
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
25
+ }
26
+
27
+ function formatPct(rate: number | undefined): string {
28
+ if (rate === undefined) return '—';
29
+ return `${(rate * 100).toFixed(0)}%`;
30
+ }
31
+
32
+ export default {
33
+ async execute(_args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
34
+ const runtime = await getVibesRuntime();
35
+ const ui = (await runtime.context('cli/ui')) as UIContext;
36
+
37
+ const worker = readString(opts.worker);
38
+ const filter = readString(opts.filter);
39
+ const providerFilter = readString(opts.provider);
40
+ const output = readString(opts.output) ?? 'text';
41
+
42
+ if (!runtime.hasKind('infra/observability')) {
43
+ ui.warn('No infra/observability kind registered. Load infra-cloudflare or a sibling provider plugin.');
44
+ return;
45
+ }
46
+ const descriptors = runtime.assets('infra/observability').descriptors() as InfraObservabilityDescriptor[];
47
+ const target = providerFilter
48
+ ? descriptors.find((d) => d.adapter === providerFilter || d.id === providerFilter)
49
+ : descriptors[0];
50
+ if (!target) {
51
+ ui.error('No matching observability provider.');
52
+ return;
53
+ }
54
+
55
+ const scope: ObservabilityScope = worker
56
+ ? { kind: 'worker', workerName: worker }
57
+ : { kind: 'account-wide', ...(filter ? { filter } : {}) };
58
+
59
+ let snapshots: ObservabilitySnapshot[];
60
+ try {
61
+ const impl = (await runtime
62
+ .query('infra/observability')
63
+ .withId(target.id)
64
+ .resolve()) as ObservabilityImplementation;
65
+ snapshots = await impl.getStatus(scope);
66
+ } catch (err) {
67
+ ui.error(`Failed to read observability: ${err instanceof Error ? err.message : String(err)}`);
68
+ return;
69
+ }
70
+
71
+ if (output === 'json') {
72
+ ui.json(snapshots);
73
+ return;
74
+ }
75
+
76
+ if (snapshots.length === 0) {
77
+ ui.info('No workers in scope.');
78
+ return;
79
+ }
80
+
81
+ // Compute column widths.
82
+ const nameWidth = Math.max(6, ...snapshots.map((s) => s.workerName.length));
83
+ ui.info(
84
+ ` ${'worker'.padEnd(nameWidth)} ${'logs'.padEnd(6)} ${'sample'.padEnd(7)} ${'traces'.padEnd(7)} modified`
85
+ );
86
+ ui.info(` ${'-'.repeat(nameWidth)} ------ ------- ------- --------------------`);
87
+ for (const s of snapshots) {
88
+ const logsEnabled = s.settings.logs?.enabled ?? false;
89
+ const logsSample = formatPct(s.settings.logs?.headSamplingRate);
90
+ const tracesEnabled = s.settings.traces?.enabled ?? false;
91
+ const modified = s.modifiedAt ? s.modifiedAt.slice(0, 19) : '—';
92
+ ui.info(
93
+ ` ${s.workerName.padEnd(nameWidth)} ${String(logsEnabled).padEnd(6)} ${logsSample.padEnd(7)} ${String(tracesEnabled).padEnd(7)} ${modified}`
94
+ );
95
+ }
96
+
97
+ // Surface a fleet-wide summary so the gap is impossible to miss.
98
+ const samples = snapshots
99
+ .map((s) => s.settings.logs?.headSamplingRate)
100
+ .filter((r): r is number => typeof r === 'number');
101
+ if (samples.length > 0) {
102
+ const min = Math.min(...samples);
103
+ const max = Math.max(...samples);
104
+ const avg = samples.reduce((a, b) => a + b, 0) / samples.length;
105
+ ui.info(
106
+ `\nFleet logs head-sampling: min=${formatPct(min)} avg=${formatPct(avg)} max=${formatPct(max)} ` +
107
+ `(${snapshots.length} workers scanned)`
108
+ );
109
+ if (max >= 1) {
110
+ const overSampled = snapshots
111
+ .filter((s) => (s.settings.logs?.headSamplingRate ?? 0) >= 1)
112
+ .map((s) => s.workerName);
113
+ ui.warn(
114
+ `\n${overSampled.length} worker(s) at 100% sampling — eligible for tuning:\n ${overSampled.join('\n ')}`
115
+ );
116
+ ui.info(
117
+ '\nRun `vibes infra observability set --sampling 0.1 --filter "vibes-*"` to drop ' +
118
+ 'customer-facing workers to 10% (recommended before accepting the new CF Workers ' +
119
+ 'Observability pricing).'
120
+ );
121
+ }
122
+ }
123
+ }
124
+ };
@@ -0,0 +1,12 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-observability',
5
+ kind: 'cli/group',
6
+ name: 'observability',
7
+ description: 'Provider-agnostic observability config — sampling, logs, traces, exports',
8
+ parent: 'infra',
9
+ surfaces: ['cli'],
10
+ hardware: ['consumer', 'cloud'],
11
+ enabled: true
12
+ });
@@ -0,0 +1,36 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-deploy.regenerate',
5
+ kind: 'cli/command',
6
+ name: 'regenerate',
7
+ description:
8
+ 'Regenerate wrangler.jsonc from deployment.config.ts for managed apps (or check for drift)',
9
+ group: 'infra-deploy',
10
+ arguments: [
11
+ {
12
+ name: 'path',
13
+ description: 'App directory (defaults to cwd; ignored when --all is set)',
14
+ required: false,
15
+ variadic: false
16
+ }
17
+ ],
18
+ options: [
19
+ {
20
+ flags: '--all',
21
+ description: 'Regenerate every managed app under <root> (defaults to cwd)'
22
+ },
23
+ {
24
+ flags: '--root <dir>',
25
+ description: 'Root directory to scan when --all is set (defaults to cwd)'
26
+ },
27
+ {
28
+ flags: '--check',
29
+ description: 'Read-only drift detection; exit 1 if any managed app is out of sync'
30
+ },
31
+ { flags: '-o, --output <format>', description: 'Output format (text|json)', default: 'text' }
32
+ ],
33
+ surfaces: ['cli'],
34
+ hardware: ['consumer', 'cloud'],
35
+ enabled: true
36
+ });
@@ -0,0 +1,103 @@
1
+ import { relative, resolve } from 'node:path';
2
+ import { getVibesRuntime } from '@vibesdotdev/runtime';
3
+ import type { UIContext } from '@vibesdotdev/cli/providers';
4
+ import { regenerateAll, regenerateApp, regenExitCode, type RegenResult } from '../../regenerate.ts';
5
+
6
+ function readString(v: unknown): string | undefined {
7
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
8
+ }
9
+
10
+ function readBoolean(v: unknown): boolean {
11
+ return v === true || v === 'true';
12
+ }
13
+
14
+ function statusGlyph(status: RegenResult['status']): string {
15
+ switch (status) {
16
+ case 'unchanged':
17
+ return '·';
18
+ case 'updated':
19
+ return '✎';
20
+ case 'drift':
21
+ return '✗';
22
+ case 'skipped':
23
+ return '–';
24
+ case 'error':
25
+ return '!';
26
+ }
27
+ }
28
+
29
+ function summarize(results: RegenResult[]): Record<RegenResult['status'], number> {
30
+ const counts: Record<RegenResult['status'], number> = {
31
+ unchanged: 0,
32
+ updated: 0,
33
+ drift: 0,
34
+ skipped: 0,
35
+ error: 0
36
+ };
37
+ for (const r of results) counts[r.status] += 1;
38
+ return counts;
39
+ }
40
+
41
+ export default {
42
+ async execute(args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
43
+ const runtime = getVibesRuntime();
44
+ const ui = (await runtime.context('cli/ui')) as UIContext;
45
+
46
+ const all = readBoolean(opts.all);
47
+ const check = readBoolean(opts.check);
48
+ const output = readString(opts.output) ?? 'text';
49
+ const mode = check ? 'check' : 'write';
50
+
51
+ const results: RegenResult[] = [];
52
+ if (all) {
53
+ const root = resolve(readString(opts.root) ?? process.cwd());
54
+ const r = await regenerateAll(root, { mode });
55
+ results.push(...r);
56
+ } else {
57
+ const path = readString(args.path) ?? process.cwd();
58
+ results.push(await regenerateApp(resolve(path), { mode }));
59
+ }
60
+
61
+ if (output === 'json') {
62
+ ui.json({
63
+ mode,
64
+ results: results.map((r) => ({
65
+ appId: r.appId,
66
+ appDir: relative(process.cwd(), r.appDir) || '.',
67
+ wranglerJsoncPath: relative(process.cwd(), r.wranglerJsoncPath),
68
+ status: r.status,
69
+ workerName: r.workerName,
70
+ reason: r.reason,
71
+ diff: r.diff
72
+ })),
73
+ summary: summarize(results)
74
+ });
75
+ } else {
76
+ for (const r of results) {
77
+ const path = relative(process.cwd(), r.wranglerJsoncPath);
78
+ const glyph = statusGlyph(r.status);
79
+ const tail =
80
+ r.status === 'drift'
81
+ ? ` (drift; run without --check to rewrite)`
82
+ : r.status === 'skipped'
83
+ ? ` (skipped: ${r.reason ?? 'not managed'})`
84
+ : r.status === 'error'
85
+ ? ` (error: ${r.reason ?? 'unknown'})`
86
+ : '';
87
+ ui.log(` ${glyph} ${r.appId.padEnd(20)} ${path}${tail}`);
88
+ if (r.status === 'drift' && r.diff) {
89
+ for (const line of r.diff.split('\n')) ui.log(` ${line}`);
90
+ }
91
+ }
92
+ const counts = summarize(results);
93
+ const summary = Object.entries(counts)
94
+ .filter(([, n]) => n > 0)
95
+ .map(([k, n]) => `${n} ${k}`)
96
+ .join(', ');
97
+ if (summary) ui.info(`Summary: ${summary} (mode=${mode})`);
98
+ }
99
+
100
+ const code = regenExitCode(results, mode);
101
+ if (code !== 0) process.exitCode = code;
102
+ }
103
+ };
@@ -0,0 +1,27 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-rum.status',
5
+ kind: 'cli/command',
6
+ name: 'status',
7
+ description: 'List configured RUM sites + injection mode across providers',
8
+ group: 'infra-rum',
9
+ options: [
10
+ {
11
+ flags: '--provider <id>',
12
+ description: 'Provider impl id (default: cloudflare-web-analytics)'
13
+ },
14
+ {
15
+ flags: '--environment <name>',
16
+ description: 'Vibes environment for secret resolution (local|dev|staging|production)'
17
+ },
18
+ {
19
+ flags: '-o, --output <format>',
20
+ description: 'Output format (text|json)',
21
+ default: 'text'
22
+ }
23
+ ],
24
+ surfaces: ['cli'],
25
+ hardware: ['consumer', 'cloud'],
26
+ enabled: true
27
+ });
@@ -0,0 +1,112 @@
1
+ /**
2
+ * `vibes infra rum status`
3
+ *
4
+ * Lists configured RUM sites across registered providers, plus the
5
+ * declared injection mode + privacy posture from the descriptor.
6
+ * Flags the "auto-injection but SSR Workers" gap that bit us earlier.
7
+ */
8
+
9
+ import { getVibesRuntime } from '@vibesdotdev/runtime';
10
+ import { type UIContext } from '@vibesdotdev/cli/providers';
11
+ import type {
12
+ RumImplementation,
13
+ RumSiteSnapshot,
14
+ InfraRumDescriptor
15
+ } from '@vibesdotdev/infra-core/kinds';
16
+
17
+ function readString(v: unknown): string | undefined {
18
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
19
+ }
20
+
21
+ export default {
22
+ async execute(_args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
23
+ const runtime = await getVibesRuntime();
24
+ const ui = (await runtime.context('cli/ui')) as UIContext;
25
+
26
+ const providerFilter = readString(opts.provider);
27
+ const output = readString(opts.output) ?? 'text';
28
+
29
+ if (!runtime.hasKind('infra/rum')) {
30
+ ui.warn('No infra/rum kind registered.');
31
+ return;
32
+ }
33
+ const descriptors = runtime.assets('infra/rum').descriptors() as InfraRumDescriptor[];
34
+ const candidates = providerFilter
35
+ ? descriptors.filter((d) => d.adapter === providerFilter || d.id === providerFilter)
36
+ : descriptors;
37
+ if (candidates.length === 0) {
38
+ ui.info('No infra/rum providers registered.');
39
+ return;
40
+ }
41
+
42
+ interface ProviderReport {
43
+ descriptorId: string;
44
+ adapter: string;
45
+ declaredInjection: string;
46
+ declaredHostnames: string[];
47
+ sites: RumSiteSnapshot[];
48
+ error?: string;
49
+ }
50
+
51
+ const reports: ProviderReport[] = [];
52
+ for (const d of candidates) {
53
+ try {
54
+ const impl = (await runtime
55
+ .query('infra/rum')
56
+ .withId(d.id)
57
+ .resolve()) as RumImplementation;
58
+ const sites = await impl.listSites();
59
+ reports.push({
60
+ descriptorId: d.id,
61
+ adapter: d.adapter,
62
+ declaredInjection: d.injection,
63
+ declaredHostnames: d.hostnames,
64
+ sites
65
+ });
66
+ } catch (err) {
67
+ reports.push({
68
+ descriptorId: d.id,
69
+ adapter: d.adapter,
70
+ declaredInjection: d.injection,
71
+ declaredHostnames: d.hostnames,
72
+ sites: [],
73
+ error: err instanceof Error ? err.message : String(err)
74
+ });
75
+ }
76
+ }
77
+
78
+ if (output === 'json') {
79
+ ui.json(reports);
80
+ return;
81
+ }
82
+
83
+ for (const r of reports) {
84
+ ui.info(`\n[${r.adapter}] (${r.descriptorId})`);
85
+ ui.info(` injection: ${r.declaredInjection}`);
86
+ ui.info(` declared hostnames: ${r.declaredHostnames.join(', ')}`);
87
+ if (r.error) {
88
+ ui.error(` ${r.error}`);
89
+ continue;
90
+ }
91
+ if (r.sites.length === 0) {
92
+ ui.warn(' (no sites configured on provider)');
93
+ continue;
94
+ }
95
+ for (const s of r.sites) {
96
+ ui.info(
97
+ ` ${s.enabled ? '✓' : '✗'} site_tag=${s.siteTag} hosts=${s.hostnames.join(',')} ` +
98
+ `injection=${s.injection ?? '?'} created=${(s.createdAt ?? '?').slice(0, 10)}`
99
+ );
100
+ }
101
+ // Flag the SSR-injection gap clearly.
102
+ if (r.declaredInjection === 'provider-auto' || r.sites.some((s) => s.injection === 'provider-auto')) {
103
+ ui.warn(
104
+ '\n ⚠ provider-auto injection only fires on origin/cache responses. SvelteKit ' +
105
+ 'SSR Workers will report 0 page views unless the beacon is also injected at ' +
106
+ 'render time (use injection: "sveltekit-hook" + the cloudflare-web-analytics ' +
107
+ 'SvelteKit handle).'
108
+ );
109
+ }
110
+ }
111
+ }
112
+ };
@@ -0,0 +1,12 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-rum',
5
+ kind: 'cli/group',
6
+ name: 'rum',
7
+ description: 'Real User Monitoring (beacon-based front-end telemetry) — CF Web Analytics, Sentry, …',
8
+ parent: 'infra',
9
+ surfaces: ['cli'],
10
+ hardware: ['consumer', 'cloud'],
11
+ enabled: true
12
+ });
@@ -0,0 +1,49 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-deploy.run',
5
+ kind: 'cli/command',
6
+ name: 'run',
7
+ description: 'Build and deploy the app in <path> (defaults to cwd)',
8
+ group: 'infra-deploy',
9
+ arguments: [
10
+ {
11
+ name: 'path',
12
+ description: 'Path to app directory containing deployment.config.ts',
13
+ required: false,
14
+ variadic: false
15
+ }
16
+ ],
17
+ options: [
18
+ { flags: '--skip-build', description: 'Skip build step (deploy pre-built output)' },
19
+ {
20
+ flags: '--skip-d1-migrations',
21
+ description: 'Skip D1 migration replay for this deploy (Workers only)'
22
+ },
23
+ { flags: '--dry-run', description: 'Show what would be deployed, without uploading' },
24
+ {
25
+ flags: '--workspace-root <dir>',
26
+ description: 'Override workspace root (default: process.cwd())'
27
+ },
28
+ {
29
+ flags: '--environment <name>',
30
+ description: 'Target Vibes environment for deploy credential resolution'
31
+ },
32
+ { flags: '--branch <name>', description: 'Deploy branch (default: main)', default: 'main' },
33
+ {
34
+ flags: '--wrangler-env <name>',
35
+ description: 'Wrangler environment name (Workers only)'
36
+ },
37
+ {
38
+ flags: '--do-app-id <id>',
39
+ description: 'Existing DigitalOcean App id (update instead of create)'
40
+ },
41
+ { flags: '--do-region <slug>', description: 'DO region slug (default: nyc)' },
42
+ { flags: '--do-git-repo <url>', description: 'DO App source git repo URL' },
43
+ { flags: '--do-git-branch <name>', description: 'DO App source branch (default: main)' },
44
+ { flags: '-o, --output <format>', description: 'Output format (text|json)', default: 'text' }
45
+ ],
46
+ surfaces: ['cli'],
47
+ hardware: ['consumer', 'cloud'],
48
+ enabled: true
49
+ });