@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.
- package/README.md +125 -0
- package/SPEC.md +181 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.d.ts +39 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.js +61 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.descriptor.js.map +1 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.impl.d.ts +13 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.impl.js +109 -0
- package/dist/cli/alerts/infra-alerts-create.cli-command.impl.js.map +1 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.d.ts +31 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.js +36 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.descriptor.js.map +1 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.d.ts +11 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.js +67 -0
- package/dist/cli/alerts/infra-alerts-delete.cli-command.impl.js.map +1 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.d.ts +21 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.js +27 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.descriptor.js.map +1 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.impl.d.ts +12 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.impl.js +74 -0
- package/dist/cli/alerts/infra-alerts-list.cli-command.impl.js.map +1 -0
- package/dist/cli/alerts/infra-alerts.cli-group.descriptor.d.ts +12 -0
- package/dist/cli/alerts/infra-alerts.cli-group.descriptor.d.ts.map +1 -0
- package/dist/cli/alerts/infra-alerts.cli-group.descriptor.js +12 -0
- package/dist/cli/alerts/infra-alerts.cli-group.descriptor.js.map +1 -0
- package/dist/cli/audit/infra-audit.cli-command.descriptor.d.ts +21 -0
- package/dist/cli/audit/infra-audit.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/audit/infra-audit.cli-command.descriptor.js +28 -0
- package/dist/cli/audit/infra-audit.cli-command.descriptor.js.map +1 -0
- package/dist/cli/audit/infra-audit.cli-command.impl.d.ts +18 -0
- package/dist/cli/audit/infra-audit.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/audit/infra-audit.cli-command.impl.js +219 -0
- package/dist/cli/audit/infra-audit.cli-command.impl.js.map +1 -0
- package/dist/cli/infra-deploy.cli-group.descriptor.d.ts +12 -0
- package/dist/cli/infra-deploy.cli-group.descriptor.d.ts.map +1 -0
- package/dist/cli/infra-deploy.cli-group.descriptor.js +12 -0
- package/dist/cli/infra-deploy.cli-group.descriptor.js.map +1 -0
- package/dist/cli/infra.cli-group.descriptor.d.ts +11 -0
- package/dist/cli/infra.cli-group.descriptor.d.ts.map +1 -0
- package/dist/cli/infra.cli-group.descriptor.js +11 -0
- package/dist/cli/infra.cli-group.descriptor.js.map +1 -0
- package/dist/cli/list/infra-deploy.list.cli-command.descriptor.d.ts +34 -0
- package/dist/cli/list/infra-deploy.list.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/list/infra-deploy.list.cli-command.descriptor.js +29 -0
- package/dist/cli/list/infra-deploy.list.cli-command.descriptor.js.map +1 -0
- package/dist/cli/list/infra-deploy.list.cli-command.impl.d.ts +5 -0
- package/dist/cli/list/infra-deploy.list.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/list/infra-deploy.list.cli-command.impl.js +110 -0
- package/dist/cli/list/infra-deploy.list.cli-command.impl.js.map +1 -0
- package/dist/cli/logs/infra-logs.cli-command.descriptor.d.ts +39 -0
- package/dist/cli/logs/infra-logs.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/logs/infra-logs.cli-command.descriptor.js +64 -0
- package/dist/cli/logs/infra-logs.cli-command.descriptor.js.map +1 -0
- package/dist/cli/logs/infra-logs.cli-command.impl.d.ts +5 -0
- package/dist/cli/logs/infra-logs.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/logs/infra-logs.cli-command.impl.js +323 -0
- package/dist/cli/logs/infra-logs.cli-command.impl.js.map +1 -0
- package/dist/cli/logs/stream-worker-tail.d.ts +62 -0
- package/dist/cli/logs/stream-worker-tail.d.ts.map +1 -0
- package/dist/cli/logs/stream-worker-tail.js +165 -0
- package/dist/cli/logs/stream-worker-tail.js.map +1 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.d.ts +27 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.js +75 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.descriptor.js.map +1 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.impl.d.ts +5 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.impl.js +383 -0
- package/dist/cli/npm/infra-npm-publish.cli-command.impl.js.map +1 -0
- package/dist/cli/npm/infra-npm.cli-group.descriptor.d.ts +12 -0
- package/dist/cli/npm/infra-npm.cli-group.descriptor.d.ts.map +1 -0
- package/dist/cli/npm/infra-npm.cli-group.descriptor.js +12 -0
- package/dist/cli/npm/infra-npm.cli-group.descriptor.js.map +1 -0
- package/dist/cli/observability/infra-observability-set.cli-command.descriptor.d.ts +25 -0
- package/dist/cli/observability/infra-observability-set.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/observability/infra-observability-set.cli-command.descriptor.js +57 -0
- package/dist/cli/observability/infra-observability-set.cli-command.descriptor.js.map +1 -0
- package/dist/cli/observability/infra-observability-set.cli-command.impl.d.ts +17 -0
- package/dist/cli/observability/infra-observability-set.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/observability/infra-observability-set.cli-command.impl.js +152 -0
- package/dist/cli/observability/infra-observability-set.cli-command.impl.js.map +1 -0
- package/dist/cli/observability/infra-observability-status.cli-command.descriptor.d.ts +21 -0
- package/dist/cli/observability/infra-observability-status.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/observability/infra-observability-status.cli-command.descriptor.js +35 -0
- package/dist/cli/observability/infra-observability-status.cli-command.descriptor.js.map +1 -0
- package/dist/cli/observability/infra-observability-status.cli-command.impl.d.ts +17 -0
- package/dist/cli/observability/infra-observability-status.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/observability/infra-observability-status.cli-command.impl.js +99 -0
- package/dist/cli/observability/infra-observability-status.cli-command.impl.js.map +1 -0
- package/dist/cli/observability/infra-observability.cli-group.descriptor.d.ts +12 -0
- package/dist/cli/observability/infra-observability.cli-group.descriptor.d.ts.map +1 -0
- package/dist/cli/observability/infra-observability.cli-group.descriptor.js +12 -0
- package/dist/cli/observability/infra-observability.cli-group.descriptor.js.map +1 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.d.ts +27 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.js +35 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.js.map +1 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.d.ts +5 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.js +99 -0
- package/dist/cli/regenerate/infra-deploy.regenerate.cli-command.impl.js.map +1 -0
- package/dist/cli/rum/infra-rum-status.cli-command.descriptor.d.ts +21 -0
- package/dist/cli/rum/infra-rum-status.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/rum/infra-rum-status.cli-command.descriptor.js +27 -0
- package/dist/cli/rum/infra-rum-status.cli-command.descriptor.js.map +1 -0
- package/dist/cli/rum/infra-rum-status.cli-command.impl.d.ts +12 -0
- package/dist/cli/rum/infra-rum-status.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/rum/infra-rum-status.cli-command.impl.js +88 -0
- package/dist/cli/rum/infra-rum-status.cli-command.impl.js.map +1 -0
- package/dist/cli/rum/infra-rum.cli-group.descriptor.d.ts +12 -0
- package/dist/cli/rum/infra-rum.cli-group.descriptor.d.ts.map +1 -0
- package/dist/cli/rum/infra-rum.cli-group.descriptor.js +12 -0
- package/dist/cli/rum/infra-rum.cli-group.descriptor.js.map +1 -0
- package/dist/cli/run/infra-deploy.run.cli-command.descriptor.d.ts +27 -0
- package/dist/cli/run/infra-deploy.run.cli-command.descriptor.d.ts.map +1 -0
- package/dist/cli/run/infra-deploy.run.cli-command.descriptor.js +49 -0
- package/dist/cli/run/infra-deploy.run.cli-command.descriptor.js.map +1 -0
- package/dist/cli/run/infra-deploy.run.cli-command.impl.d.ts +5 -0
- package/dist/cli/run/infra-deploy.run.cli-command.impl.d.ts.map +1 -0
- package/dist/cli/run/infra-deploy.run.cli-command.impl.js +272 -0
- package/dist/cli/run/infra-deploy.run.cli-command.impl.js.map +1 -0
- package/dist/cli/shared/discover-deployments.d.ts +41 -0
- package/dist/cli/shared/discover-deployments.d.ts.map +1 -0
- package/dist/cli/shared/discover-deployments.js +95 -0
- package/dist/cli/shared/discover-deployments.js.map +1 -0
- package/dist/config-loader.d.ts +24 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +135 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/infra-deploy.plugin.d.ts +3 -0
- package/dist/infra-deploy.plugin.d.ts.map +1 -0
- package/dist/infra-deploy.plugin.js +59 -0
- package/dist/infra-deploy.plugin.js.map +1 -0
- package/dist/regenerate.d.ts +55 -0
- package/dist/regenerate.d.ts.map +1 -0
- package/dist/regenerate.js +206 -0
- package/dist/regenerate.js.map +1 -0
- package/package.json +85 -0
- package/src/cli/alerts/infra-alerts-create.cli-command.descriptor.ts +61 -0
- package/src/cli/alerts/infra-alerts-create.cli-command.impl.ts +131 -0
- package/src/cli/alerts/infra-alerts-delete.cli-command.descriptor.ts +36 -0
- package/src/cli/alerts/infra-alerts-delete.cli-command.impl.ts +75 -0
- package/src/cli/alerts/infra-alerts-list.cli-command.descriptor.ts +27 -0
- package/src/cli/alerts/infra-alerts-list.cli-command.impl.ts +88 -0
- package/src/cli/alerts/infra-alerts.cli-group.descriptor.ts +12 -0
- package/src/cli/audit/infra-audit.cli-command.descriptor.ts +28 -0
- package/src/cli/audit/infra-audit.cli-command.impl.ts +293 -0
- package/src/cli/infra-deploy.cli-group.descriptor.ts +12 -0
- package/src/cli/infra.cli-group.descriptor.ts +11 -0
- package/src/cli/list/infra-deploy.list.cli-command.descriptor.ts +29 -0
- package/src/cli/list/infra-deploy.list.cli-command.impl.ts +125 -0
- package/src/cli/logs/infra-logs.cli-command.descriptor.ts +65 -0
- package/src/cli/logs/infra-logs.cli-command.impl.ts +354 -0
- package/src/cli/logs/stream-worker-tail.ts +202 -0
- package/src/cli/npm/infra-npm-publish.cli-command.descriptor.ts +75 -0
- package/src/cli/npm/infra-npm-publish.cli-command.impl.ts +474 -0
- package/src/cli/npm/infra-npm.cli-group.descriptor.ts +12 -0
- package/src/cli/observability/infra-observability-set.cli-command.descriptor.ts +57 -0
- package/src/cli/observability/infra-observability-set.cli-command.impl.ts +173 -0
- package/src/cli/observability/infra-observability-status.cli-command.descriptor.ts +35 -0
- package/src/cli/observability/infra-observability-status.cli-command.impl.ts +124 -0
- package/src/cli/observability/infra-observability.cli-group.descriptor.ts +12 -0
- package/src/cli/regenerate/infra-deploy.regenerate.cli-command.descriptor.ts +36 -0
- package/src/cli/regenerate/infra-deploy.regenerate.cli-command.impl.ts +103 -0
- package/src/cli/rum/infra-rum-status.cli-command.descriptor.ts +27 -0
- package/src/cli/rum/infra-rum-status.cli-command.impl.ts +112 -0
- package/src/cli/rum/infra-rum.cli-group.descriptor.ts +12 -0
- package/src/cli/run/infra-deploy.run.cli-command.descriptor.ts +49 -0
- package/src/cli/run/infra-deploy.run.cli-command.impl.ts +330 -0
- package/src/cli/shared/discover-deployments.ts +127 -0
- package/src/config-loader.ts +179 -0
- package/src/index.ts +11 -0
- package/src/infra-deploy.plugin.ts +83 -0
- 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
|
+
});
|