@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,293 @@
1
+ /**
2
+ * `vibes infra audit`
3
+ *
4
+ * Composes existing infra/* implementations into one human-readable
5
+ * report. Mirrors the manual CF dashboard sweep we keep doing:
6
+ *
7
+ * - infra/alerts: policies configured (or "GAP" if none)
8
+ * - infra/logs: log sources, retention, analytics-snapshot
9
+ * - (future: infra/observability, infra/rum, infra/worker stats)
10
+ *
11
+ * Read-only. Never modifies provider state. `--output json` emits a
12
+ * structured payload for piping into ops dashboards.
13
+ */
14
+
15
+ import { getVibesRuntime } from '@vibesdotdev/runtime';
16
+ import { type UIContext } from '@vibesdotdev/cli/providers';
17
+ import type {
18
+ AlertsImplementation,
19
+ AlertPolicy,
20
+ InfraAlertsDescriptor,
21
+ InfraLogsDescriptor,
22
+ InfraObservabilityDescriptor,
23
+ ObservabilityImplementation,
24
+ ObservabilitySnapshot
25
+ } from '@vibesdotdev/infra-core/kinds';
26
+
27
+ function readString(v: unknown): string | undefined {
28
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
29
+ }
30
+
31
+ interface AlertsSection {
32
+ providers: Array<{
33
+ descriptorId: string;
34
+ adapter: string;
35
+ policies: Array<AlertPolicy & { providerId: string }>;
36
+ error?: string;
37
+ }>;
38
+ gaps: string[];
39
+ }
40
+
41
+ interface LogsSection {
42
+ providers: Array<{
43
+ descriptorId: string;
44
+ adapter: string;
45
+ sources: InfraLogsDescriptor['sources'];
46
+ retention?: InfraLogsDescriptor['retention'];
47
+ alertsConfigured: number;
48
+ error?: string;
49
+ }>;
50
+ }
51
+
52
+ interface ObservabilitySection {
53
+ providers: Array<{
54
+ descriptorId: string;
55
+ adapter: string;
56
+ workerCount: number;
57
+ minSampling?: number;
58
+ maxSampling?: number;
59
+ avgSampling?: number;
60
+ overSampledWorkers: string[];
61
+ error?: string;
62
+ }>;
63
+ gaps: string[];
64
+ }
65
+
66
+ interface AuditReport {
67
+ timestamp: string;
68
+ alerts?: AlertsSection;
69
+ logs?: LogsSection;
70
+ observability?: ObservabilitySection;
71
+ notes: string[];
72
+ }
73
+
74
+ async function gatherAlerts(runtime: ReturnType<typeof getVibesRuntime>): Promise<AlertsSection> {
75
+ const section: AlertsSection = { providers: [], gaps: [] };
76
+ if (!runtime.hasKind('infra/alerts')) {
77
+ section.gaps.push('infra/alerts kind not registered — no provider plugin loaded for alerting.');
78
+ return section;
79
+ }
80
+ const descriptors = runtime.assets('infra/alerts').descriptors() as InfraAlertsDescriptor[];
81
+ if (descriptors.length === 0) {
82
+ section.gaps.push('No infra/alerts descriptors registered.');
83
+ return section;
84
+ }
85
+ for (const d of descriptors) {
86
+ try {
87
+ const impl = (await runtime
88
+ .query('infra/alerts')
89
+ .withId(d.id)
90
+ .resolve()) as AlertsImplementation;
91
+ const policies = await impl.listPolicies();
92
+ section.providers.push({ descriptorId: d.id, adapter: d.adapter, policies });
93
+ if (policies.length === 0) {
94
+ section.gaps.push(
95
+ `${d.adapter}: zero policies configured. Budget/usage/error-rate alerts are not in place.`
96
+ );
97
+ }
98
+ } catch (err) {
99
+ section.providers.push({
100
+ descriptorId: d.id,
101
+ adapter: d.adapter,
102
+ policies: [],
103
+ error: err instanceof Error ? err.message : String(err)
104
+ });
105
+ }
106
+ }
107
+ return section;
108
+ }
109
+
110
+ async function gatherObservability(
111
+ runtime: ReturnType<typeof getVibesRuntime>
112
+ ): Promise<ObservabilitySection> {
113
+ const section: ObservabilitySection = { providers: [], gaps: [] };
114
+ if (!runtime.hasKind('infra/observability')) {
115
+ section.gaps.push('infra/observability kind not registered — no provider plugin loaded.');
116
+ return section;
117
+ }
118
+ const descriptors = runtime
119
+ .assets('infra/observability')
120
+ .descriptors() as InfraObservabilityDescriptor[];
121
+ for (const d of descriptors) {
122
+ try {
123
+ const impl = (await runtime
124
+ .query('infra/observability')
125
+ .withId(d.id)
126
+ .resolve()) as ObservabilityImplementation;
127
+ const snapshots = (await impl.getStatus({ kind: 'account-wide' })) as ObservabilitySnapshot[];
128
+ const samples = snapshots
129
+ .map((s) => s.settings.logs?.headSamplingRate)
130
+ .filter((r): r is number => typeof r === 'number');
131
+ const overSampled = snapshots
132
+ .filter((s) => (s.settings.logs?.headSamplingRate ?? 0) >= 1)
133
+ .map((s) => s.workerName);
134
+ section.providers.push({
135
+ descriptorId: d.id,
136
+ adapter: d.adapter,
137
+ workerCount: snapshots.length,
138
+ minSampling: samples.length ? Math.min(...samples) : undefined,
139
+ maxSampling: samples.length ? Math.max(...samples) : undefined,
140
+ avgSampling: samples.length ? samples.reduce((a, b) => a + b, 0) / samples.length : undefined,
141
+ overSampledWorkers: overSampled
142
+ });
143
+ if (overSampled.length > 0) {
144
+ section.gaps.push(
145
+ `${d.adapter}: ${overSampled.length} worker(s) at 100% log sampling — runaway-cost risk under the new CF Observability metering.`
146
+ );
147
+ }
148
+ } catch (err) {
149
+ section.providers.push({
150
+ descriptorId: d.id,
151
+ adapter: d.adapter,
152
+ workerCount: 0,
153
+ overSampledWorkers: [],
154
+ error: err instanceof Error ? err.message : String(err)
155
+ });
156
+ }
157
+ }
158
+ return section;
159
+ }
160
+
161
+ async function gatherLogs(runtime: ReturnType<typeof getVibesRuntime>): Promise<LogsSection> {
162
+ const section: LogsSection = { providers: [] };
163
+ if (!runtime.hasKind('infra/logs')) return section;
164
+ const descriptors = runtime.assets('infra/logs').descriptors() as InfraLogsDescriptor[];
165
+ for (const d of descriptors) {
166
+ try {
167
+ await runtime.query('infra/logs').withId(d.id).resolve(); // probe resolves
168
+ section.providers.push({
169
+ descriptorId: d.id,
170
+ adapter: d.adapter,
171
+ sources: d.sources ?? [],
172
+ retention: d.retention,
173
+ alertsConfigured: (d.alerts ?? []).length
174
+ });
175
+ } catch (err) {
176
+ section.providers.push({
177
+ descriptorId: d.id,
178
+ adapter: d.adapter,
179
+ sources: [],
180
+ alertsConfigured: 0,
181
+ error: err instanceof Error ? err.message : String(err)
182
+ });
183
+ }
184
+ }
185
+ return section;
186
+ }
187
+
188
+ export default {
189
+ async execute(_args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
190
+ const runtime = await getVibesRuntime();
191
+ const ui = (await runtime.context('cli/ui')) as UIContext;
192
+
193
+ const include = (readString(opts.include) ?? 'alerts,logs,observability')
194
+ .split(',')
195
+ .map((s) => s.trim());
196
+ const output = readString(opts.output) ?? 'text';
197
+
198
+ const report: AuditReport = { timestamp: new Date().toISOString(), notes: [] };
199
+
200
+ if (include.includes('alerts')) report.alerts = await gatherAlerts(runtime);
201
+ if (include.includes('logs')) report.logs = await gatherLogs(runtime);
202
+ if (include.includes('observability')) report.observability = await gatherObservability(runtime);
203
+
204
+ if (include.includes('rum')) {
205
+ report.notes.push('infra/rum kind is not implemented yet (Phase 3 of design doc).');
206
+ }
207
+ if (include.includes('workers')) {
208
+ report.notes.push(
209
+ 'Workers fleet audit not implemented yet — use `vibes infra deploy list` for the deployed-app inventory and CF dashboard for live request counts.'
210
+ );
211
+ }
212
+
213
+ if (output === 'json') {
214
+ ui.json(report);
215
+ return;
216
+ }
217
+
218
+ ui.info(`=== Infra audit (${report.timestamp}) ===\n`);
219
+
220
+ if (report.alerts) {
221
+ ui.info('## Alerts');
222
+ for (const p of report.alerts.providers) {
223
+ ui.info(`\n[${p.adapter}] (${p.descriptorId})`);
224
+ if (p.error) {
225
+ ui.error(` ${p.error}`);
226
+ continue;
227
+ }
228
+ if (p.policies.length === 0) {
229
+ ui.warn(' (no policies — billing / usage / error-rate alerts are off)');
230
+ continue;
231
+ }
232
+ for (const policy of p.policies) {
233
+ const mech = policy.mechanisms.map((m) => `${m.kind}:${m.target}`).join(', ');
234
+ ui.info(
235
+ ` ${policy.enabled ? '✓' : '✗'} ${policy.type.padEnd(12)} ${policy.name.padEnd(40)} threshold=${policy.threshold} → ${mech}`
236
+ );
237
+ }
238
+ }
239
+ if (report.alerts.gaps.length > 0) {
240
+ ui.info('\nGaps:');
241
+ for (const gap of report.alerts.gaps) ui.warn(` • ${gap}`);
242
+ }
243
+ }
244
+
245
+ if (report.logs) {
246
+ ui.info('\n## Logs');
247
+ for (const p of report.logs.providers) {
248
+ ui.info(`\n[${p.adapter}] (${p.descriptorId})`);
249
+ if (p.error) {
250
+ ui.error(` ${p.error}`);
251
+ continue;
252
+ }
253
+ ui.info(` sources=${p.sources.length} alerts=${p.alertsConfigured}`);
254
+ if (p.retention) {
255
+ ui.info(
256
+ ` retention: hot=${p.retention.hotDays}d cold=${p.retention.coldDays}d`
257
+ );
258
+ }
259
+ }
260
+ }
261
+
262
+ if (report.observability) {
263
+ ui.info('\n## Observability');
264
+ const fmt = (r: number | undefined): string =>
265
+ r === undefined ? '—' : `${(r * 100).toFixed(0)}%`;
266
+ for (const p of report.observability.providers) {
267
+ ui.info(`\n[${p.adapter}] (${p.descriptorId})`);
268
+ if (p.error) {
269
+ ui.error(` ${p.error}`);
270
+ continue;
271
+ }
272
+ ui.info(
273
+ ` workers=${p.workerCount} sampling min=${fmt(p.minSampling)} avg=${fmt(p.avgSampling)} max=${fmt(p.maxSampling)}`
274
+ );
275
+ if (p.overSampledWorkers.length > 0) {
276
+ ui.warn(
277
+ ` ${p.overSampledWorkers.length} worker(s) at 100% sampling — tune with ` +
278
+ '`vibes infra observability set --sampling 0.1 --filter "vibes-*"`'
279
+ );
280
+ }
281
+ }
282
+ if (report.observability.gaps.length > 0) {
283
+ ui.info('\nGaps:');
284
+ for (const gap of report.observability.gaps) ui.warn(` • ${gap}`);
285
+ }
286
+ }
287
+
288
+ if (report.notes.length > 0) {
289
+ ui.info('\n## Notes');
290
+ for (const note of report.notes) ui.info(` • ${note}`);
291
+ }
292
+ }
293
+ };
@@ -0,0 +1,12 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-deploy',
5
+ kind: 'cli/group',
6
+ name: 'deploy',
7
+ description: 'Build and deploy apps declared in deployment.config.ts',
8
+ parent: 'infra',
9
+ surfaces: ['cli'],
10
+ hardware: ['consumer', 'cloud'],
11
+ enabled: true
12
+ });
@@ -0,0 +1,11 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra',
5
+ kind: 'cli/group',
6
+ name: 'infra',
7
+ description: 'Infrastructure commands',
8
+ surfaces: ['cli'],
9
+ hardware: ['consumer', 'cloud'],
10
+ enabled: true
11
+ });
@@ -0,0 +1,29 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-deploy.list',
5
+ kind: 'cli/command',
6
+ name: 'list',
7
+ description: 'List deployable apps under <root> (scans for deployment.config.ts)',
8
+ group: 'infra-deploy',
9
+ arguments: [
10
+ {
11
+ name: 'root',
12
+ description: 'Root directory to scan (defaults to cwd)',
13
+ required: false,
14
+ variadic: false
15
+ }
16
+ ],
17
+ options: [
18
+ {
19
+ flags: '-o, --output <format>',
20
+ description: 'Output format (text|json|table)',
21
+ default: 'table'
22
+ },
23
+ { flags: '--max-depth <n>', description: 'Maximum directory depth to scan', default: '4', type: 'number' },
24
+ { flags: '--order, --graph', description: 'Show suggested deploy order based on dependsOn (topological)' }
25
+ ],
26
+ surfaces: ['cli'],
27
+ hardware: ['consumer', 'cloud'],
28
+ enabled: true
29
+ });
@@ -0,0 +1,125 @@
1
+ import { isAbsolute, relative, resolve } from 'node:path';
2
+ import { getVibesRuntime } from '@vibesdotdev/runtime';
3
+ import type { UIContext } from '@vibesdotdev/cli/providers';
4
+ import { discoverDeployments } from '../shared/discover-deployments.ts';
5
+
6
+ function readString(v: unknown): string | undefined {
7
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
8
+ }
9
+
10
+ /**
11
+ * Simple topological order for deploy (earlier = must deploy first).
12
+ * Apps with no dependsOn come first. Uses Kahn's algorithm.
13
+ */
14
+ function computeDeployOrder(
15
+ apps: Array<{ appId: string; dependsOn: Array<{ appId: string }> }>
16
+ ): string[] {
17
+ const graph = new Map<string, Set<string>>();
18
+ const indegree = new Map<string, number>();
19
+
20
+ for (const a of apps) {
21
+ if (!graph.has(a.appId)) graph.set(a.appId, new Set());
22
+ indegree.set(a.appId, indegree.get(a.appId) ?? 0);
23
+ for (const dep of a.dependsOn ?? []) {
24
+ if (!graph.has(dep.appId)) graph.set(dep.appId, new Set());
25
+ graph.get(dep.appId)!.add(a.appId);
26
+ indegree.set(a.appId, (indegree.get(a.appId) ?? 0) + 1);
27
+ }
28
+ }
29
+
30
+ const queue: string[] = [];
31
+ for (const [id, deg] of indegree) if (deg === 0) queue.push(id);
32
+
33
+ const order: string[] = [];
34
+ while (queue.length) {
35
+ const node = queue.shift()!;
36
+ order.push(node);
37
+ for (const neighbor of graph.get(node) ?? []) {
38
+ indegree.set(neighbor, (indegree.get(neighbor) ?? 1) - 1);
39
+ if (indegree.get(neighbor) === 0) queue.push(neighbor);
40
+ }
41
+ }
42
+
43
+ // Any remaining (cycles) appended at end
44
+ for (const [id] of indegree) if (!order.includes(id)) order.push(id);
45
+
46
+ return order;
47
+ }
48
+
49
+ export default {
50
+ async execute(args: Record<string, unknown>, opts: Record<string, unknown>): Promise<void> {
51
+ const runtime = getVibesRuntime();
52
+ const ui = (await runtime.context('cli/ui')) as UIContext;
53
+
54
+ const rootInput = readString(args.root) ?? '.';
55
+ const output = readString(opts.output) ?? 'table';
56
+ const maxDepthRaw = readString(opts.maxDepth);
57
+ const maxDepthParsed = maxDepthRaw ? Number.parseInt(maxDepthRaw, 10) : 4;
58
+ const maxDepth = Number.isFinite(maxDepthParsed) ? maxDepthParsed : 4;
59
+
60
+ function readBoolean(v: unknown): boolean {
61
+ return v === true || v === 'true' || v === 'yes';
62
+ }
63
+
64
+ const showOrder = readBoolean(opts.order) || readBoolean(opts.graph);
65
+
66
+ const rows: Array<{
67
+ appId: string;
68
+ appName: string;
69
+ provider: string;
70
+ path: string;
71
+ dependsOn: string[];
72
+ }> = [];
73
+ const appData: Array<{ appId: string; dependsOn: Array<{ appId: string }> }> = [];
74
+
75
+ const discovered = await discoverDeployments({
76
+ root: rootInput,
77
+ maxDepth,
78
+ onError: ({ appDir, error }) => {
79
+ rows.push({
80
+ appId: '(unparseable)',
81
+ appName: error.message,
82
+ provider: '-',
83
+ path: relative(process.cwd(), appDir) || '.',
84
+ dependsOn: []
85
+ });
86
+ }
87
+ });
88
+
89
+ for (const d of discovered) {
90
+ const depIds = d.dependsOn.map((dep) => dep.appId);
91
+ rows.push({
92
+ appId: d.appId,
93
+ appName: d.appName,
94
+ provider: d.provider,
95
+ path: relative(process.cwd(), d.appDir) || '.',
96
+ dependsOn: depIds
97
+ });
98
+ appData.push({ appId: d.appId, dependsOn: d.dependsOn });
99
+ }
100
+
101
+ if (rows.length === 0) {
102
+ const root = isAbsolute(rootInput) ? rootInput : resolve(process.cwd(), rootInput);
103
+ if (output === 'json') ui.json([]);
104
+ else ui.info(`No deployment configs found under ${root}`);
105
+ return;
106
+ }
107
+
108
+ if (showOrder) {
109
+ const order = computeDeployOrder(appData);
110
+ if (output === 'json') {
111
+ ui.json({ order, apps: rows });
112
+ } else {
113
+ ui.info('Suggested deploy order (earlier = prerequisites first):');
114
+ order.forEach((id, i) => ui.log(` ${i + 1}. ${id}`));
115
+ }
116
+ return;
117
+ }
118
+
119
+ if (output === 'json') {
120
+ ui.json(rows);
121
+ return;
122
+ }
123
+ ui.table(rows, { columns: ['appId', 'appName', 'provider', 'path', 'dependsOn'] });
124
+ }
125
+ };
@@ -0,0 +1,65 @@
1
+ import { createRuntimeAsset } from '@vibesdotdev/runtime';
2
+
3
+ export default createRuntimeAsset({
4
+ id: 'infra-logs',
5
+ kind: 'cli/command',
6
+ name: 'logs',
7
+ description: 'List and query log sources (Workers, Pages, D1, etc.)',
8
+ group: 'infra',
9
+ arguments: [
10
+ {
11
+ name: 'source',
12
+ description: 'Log source name to query (optional, lists all if omitted)',
13
+ required: false,
14
+ variadic: false
15
+ },
16
+ {
17
+ name: 'worker',
18
+ description: 'Worker name to filter logs (when source has multiple workers)',
19
+ required: false,
20
+ variadic: false
21
+ }
22
+ ],
23
+ options: [
24
+ {
25
+ flags: '-o, --output <format>',
26
+ description: 'Output format (text|json|table)',
27
+ default: 'table'
28
+ },
29
+ {
30
+ flags: '--analytics',
31
+ description: 'Get analytics summary for a source',
32
+ default: false
33
+ },
34
+ {
35
+ flags: '--timeStart <range>',
36
+ description: 'Time range for analytics (e.g., 1h, 24h, 7d)',
37
+ default: '24h'
38
+ },
39
+ {
40
+ flags: '--tail',
41
+ description: 'Stream logs in real-time',
42
+ default: false
43
+ },
44
+ {
45
+ flags: '--status <status>',
46
+ description: 'Filter by status (ok|error|canceled)',
47
+ default: undefined
48
+ },
49
+ {
50
+ flags: '--limit <n>',
51
+ description: 'Max log entries to retrieve',
52
+ default: '100',
53
+ type: 'number'
54
+ },
55
+ {
56
+ flags: '--window <duration>',
57
+ description:
58
+ 'Capture window for windowed query mode (e.g., 30s, 2m). Default 30s. Cloudflare exposes only live Tail for per-event data, so this brief window is the largest practical batch.',
59
+ default: '30s'
60
+ }
61
+ ],
62
+ surfaces: ['cli'],
63
+ hardware: ['consumer', 'cloud'],
64
+ enabled: true
65
+ });