@vibesdotdev/infra-core 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 +78 -0
- package/SPEC.md +169 -0
- package/dist/bootstrap/index.d.ts +5 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +4 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/bootstrap/seed.descriptor.d.ts +31 -0
- package/dist/bootstrap/seed.descriptor.d.ts.map +1 -0
- package/dist/bootstrap/seed.descriptor.js +18 -0
- package/dist/bootstrap/seed.descriptor.js.map +1 -0
- package/dist/bootstrap/seed.impl-shape.d.ts +5 -0
- package/dist/bootstrap/seed.impl-shape.d.ts.map +1 -0
- package/dist/bootstrap/seed.impl-shape.js +2 -0
- package/dist/bootstrap/seed.impl-shape.js.map +1 -0
- package/dist/bootstrap/seed.kind.d.ts +5 -0
- package/dist/bootstrap/seed.kind.d.ts.map +1 -0
- package/dist/bootstrap/seed.kind.js +14 -0
- package/dist/bootstrap/seed.kind.js.map +1 -0
- package/dist/bootstrap/seed.runner.d.ts +18 -0
- package/dist/bootstrap/seed.runner.d.ts.map +1 -0
- package/dist/bootstrap/seed.runner.js +59 -0
- package/dist/bootstrap/seed.runner.js.map +1 -0
- package/dist/credentials/resolve.d.ts +80 -0
- package/dist/credentials/resolve.d.ts.map +1 -0
- package/dist/credentials/resolve.js +128 -0
- package/dist/credentials/resolve.js.map +1 -0
- package/dist/deployment.d.ts +9 -0
- package/dist/deployment.d.ts.map +1 -0
- package/dist/deployment.js +25 -0
- package/dist/deployment.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/infra.plugin.d.ts +18 -0
- package/dist/infra.plugin.d.ts.map +1 -0
- package/dist/infra.plugin.js +52 -0
- package/dist/infra.plugin.js.map +1 -0
- package/dist/kinds/alerts.kind.d.ts +192 -0
- package/dist/kinds/alerts.kind.d.ts.map +1 -0
- package/dist/kinds/alerts.kind.js +116 -0
- package/dist/kinds/alerts.kind.js.map +1 -0
- package/dist/kinds/artifact.kind.d.ts +96 -0
- package/dist/kinds/artifact.kind.d.ts.map +1 -0
- package/dist/kinds/artifact.kind.js +53 -0
- package/dist/kinds/artifact.kind.js.map +1 -0
- package/dist/kinds/cache.kind.d.ts +128 -0
- package/dist/kinds/cache.kind.d.ts.map +1 -0
- package/dist/kinds/cache.kind.js +90 -0
- package/dist/kinds/cache.kind.js.map +1 -0
- package/dist/kinds/database.kind.d.ts +141 -0
- package/dist/kinds/database.kind.d.ts.map +1 -0
- package/dist/kinds/database.kind.js +103 -0
- package/dist/kinds/database.kind.js.map +1 -0
- package/dist/kinds/discovery.d.ts +20 -0
- package/dist/kinds/discovery.d.ts.map +1 -0
- package/dist/kinds/discovery.js +25 -0
- package/dist/kinds/discovery.js.map +1 -0
- package/dist/kinds/git-hosting.kind.d.ts +98 -0
- package/dist/kinds/git-hosting.kind.d.ts.map +1 -0
- package/dist/kinds/git-hosting.kind.js +81 -0
- package/dist/kinds/git-hosting.kind.js.map +1 -0
- package/dist/kinds/index.d.ts +16 -0
- package/dist/kinds/index.d.ts.map +1 -0
- package/dist/kinds/index.js +16 -0
- package/dist/kinds/index.js.map +1 -0
- package/dist/kinds/logs.kind.d.ts +91 -0
- package/dist/kinds/logs.kind.d.ts.map +1 -0
- package/dist/kinds/logs.kind.js +73 -0
- package/dist/kinds/logs.kind.js.map +1 -0
- package/dist/kinds/object-storage.kind.d.ts +85 -0
- package/dist/kinds/object-storage.kind.d.ts.map +1 -0
- package/dist/kinds/object-storage.kind.js +81 -0
- package/dist/kinds/object-storage.kind.js.map +1 -0
- package/dist/kinds/observability.kind.d.ts +176 -0
- package/dist/kinds/observability.kind.d.ts.map +1 -0
- package/dist/kinds/observability.kind.js +120 -0
- package/dist/kinds/observability.kind.js.map +1 -0
- package/dist/kinds/package-registry.kind.d.ts +89 -0
- package/dist/kinds/package-registry.kind.d.ts.map +1 -0
- package/dist/kinds/package-registry.kind.js +78 -0
- package/dist/kinds/package-registry.kind.js.map +1 -0
- package/dist/kinds/queue.kind.d.ts +113 -0
- package/dist/kinds/queue.kind.d.ts.map +1 -0
- package/dist/kinds/queue.kind.js +86 -0
- package/dist/kinds/queue.kind.js.map +1 -0
- package/dist/kinds/rum.kind.d.ts +113 -0
- package/dist/kinds/rum.kind.d.ts.map +1 -0
- package/dist/kinds/rum.kind.js +80 -0
- package/dist/kinds/rum.kind.js.map +1 -0
- package/dist/kinds/sandbox.kind.d.ts +111 -0
- package/dist/kinds/sandbox.kind.d.ts.map +1 -0
- package/dist/kinds/sandbox.kind.js +94 -0
- package/dist/kinds/sandbox.kind.js.map +1 -0
- package/dist/kinds/web-app.kind.d.ts +99 -0
- package/dist/kinds/web-app.kind.d.ts.map +1 -0
- package/dist/kinds/web-app.kind.js +86 -0
- package/dist/kinds/web-app.kind.js.map +1 -0
- package/dist/kinds/worker.kind.d.ts +244 -0
- package/dist/kinds/worker.kind.d.ts.map +1 -0
- package/dist/kinds/worker.kind.js +171 -0
- package/dist/kinds/worker.kind.js.map +1 -0
- package/dist/schemas.d.ts +125 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +102 -0
- package/dist/schemas.js.map +1 -0
- package/package.json +92 -0
- package/src/bootstrap/index.ts +15 -0
- package/src/bootstrap/seed.descriptor.ts +24 -0
- package/src/bootstrap/seed.impl-shape.ts +5 -0
- package/src/bootstrap/seed.kind.ts +26 -0
- package/src/bootstrap/seed.runner.ts +87 -0
- package/src/credentials/resolve.ts +205 -0
- package/src/deployment.ts +57 -0
- package/src/index.ts +149 -0
- package/src/infra.plugin.ts +54 -0
- package/src/kinds/alerts.kind.ts +164 -0
- package/src/kinds/artifact.kind.ts +96 -0
- package/src/kinds/cache.kind.ts +104 -0
- package/src/kinds/database.kind.ts +120 -0
- package/src/kinds/discovery.ts +26 -0
- package/src/kinds/git-hosting.kind.ts +100 -0
- package/src/kinds/index.ts +139 -0
- package/src/kinds/logs.kind.ts +104 -0
- package/src/kinds/object-storage.kind.ts +101 -0
- package/src/kinds/observability.kind.ts +178 -0
- package/src/kinds/package-registry.kind.ts +95 -0
- package/src/kinds/queue.kind.ts +102 -0
- package/src/kinds/rum.kind.ts +135 -0
- package/src/kinds/sandbox.kind.ts +115 -0
- package/src/kinds/web-app.kind.ts +103 -0
- package/src/kinds/worker.kind.ts +203 -0
- package/src/schemas.ts +127 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-agnostic credential resolution for infra/* adapters.
|
|
3
|
+
*
|
|
4
|
+
* Routes through the `secrets/store` runtime kind so every adapter
|
|
5
|
+
* (alerts, RUM, observability, …) reads from the same credential chain
|
|
6
|
+
* the rest of the platform uses. The chain (highest precedence first):
|
|
7
|
+
*
|
|
8
|
+
* 1. process.env (CI / explicit overrides)
|
|
9
|
+
* 2. The tier-resolved secrets/store implementation
|
|
10
|
+
* - local tier → encrypted-local → env-file
|
|
11
|
+
* - production → cloudflare-secrets-store → cloudflare-api
|
|
12
|
+
*
|
|
13
|
+
* Adapters declare the secret KEY NAMES (e.g. CLOUDFLARE_API_TOKEN) on
|
|
14
|
+
* their descriptor's `adapterConfig` and use this helper to resolve
|
|
15
|
+
* the values. The helper supports `keyCandidates` for fallback chains
|
|
16
|
+
* (e.g. prefer a scoped CLOUDFLARE_NOTIFICATIONS_API_TOKEN, fall back
|
|
17
|
+
* to the broad CLOUDFLARE_API_TOKEN).
|
|
18
|
+
*
|
|
19
|
+
* Why a helper instead of inlining the secrets/store query: provider
|
|
20
|
+
* adapters live in different packages and shouldn't all duplicate the
|
|
21
|
+
* tier-walk + env-overlay logic. Keeping it in infra-core makes the
|
|
22
|
+
* abstraction explicit ("infra/* adapters route credentials through
|
|
23
|
+
* vibes secrets") and gives us one place to evolve the chain (e.g.
|
|
24
|
+
* adding 1Password CLI as a backend).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
28
|
+
|
|
29
|
+
export type EnvironmentTier = 'local' | 'dev' | 'staging' | 'production';
|
|
30
|
+
|
|
31
|
+
export interface ResolveAdapterCredentialOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Ordered list of candidate keys. First one that resolves to a
|
|
34
|
+
* non-empty value wins. Useful for scoped → fallback patterns:
|
|
35
|
+
* ['CLOUDFLARE_NOTIFICATIONS_API_TOKEN', 'CLOUDFLARE_API_TOKEN']
|
|
36
|
+
*/
|
|
37
|
+
keyCandidates: readonly string[];
|
|
38
|
+
/**
|
|
39
|
+
* Environment name to read from the secrets store (default: 'local').
|
|
40
|
+
* Maps onto vault.environments[name] in encrypted-local.
|
|
41
|
+
*/
|
|
42
|
+
environment?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Tier hint for runtime store selection. Defaults to inferring from
|
|
45
|
+
* the environment name when it matches a known tier; falls back to
|
|
46
|
+
* 'local' otherwise.
|
|
47
|
+
*/
|
|
48
|
+
tier?: EnvironmentTier;
|
|
49
|
+
/**
|
|
50
|
+
* Whether to consult process.env first. Defaults true — CI/CD and
|
|
51
|
+
* explicit shell overrides should win. Pass false to force
|
|
52
|
+
* store-only resolution.
|
|
53
|
+
*/
|
|
54
|
+
includeProcessEnv?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Optional human-readable name for the credential, used in error
|
|
57
|
+
* messages when no candidate resolves (e.g. "Cloudflare API token").
|
|
58
|
+
*/
|
|
59
|
+
humanName?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ResolvedAdapterCredential {
|
|
63
|
+
/** The KEY that resolved (one of keyCandidates). Useful for audit. */
|
|
64
|
+
key: string;
|
|
65
|
+
/** The resolved secret value. Never logged. */
|
|
66
|
+
value: string;
|
|
67
|
+
/** Where the value came from: 'process.env' or the store backend id. */
|
|
68
|
+
source: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface SecretsStoreImplShape {
|
|
72
|
+
id?: string;
|
|
73
|
+
get?(environment: string, key: string): Promise<string | undefined>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface SecretsStoreDescriptorShape {
|
|
77
|
+
id: string;
|
|
78
|
+
priority?: number;
|
|
79
|
+
tiers?: readonly EnvironmentTier[] | EnvironmentTier[];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Tier-aware backend selection. Mirrors the secrets/store kind's own
|
|
84
|
+
* resolver (`packages/secrets/src/kinds/store.kind.ts`) so callers
|
|
85
|
+
* don't need to import internal helpers.
|
|
86
|
+
*/
|
|
87
|
+
function pickBackend(
|
|
88
|
+
descriptors: SecretsStoreDescriptorShape[],
|
|
89
|
+
tier: EnvironmentTier
|
|
90
|
+
): SecretsStoreDescriptorShape | undefined {
|
|
91
|
+
if (descriptors.length === 0) return undefined;
|
|
92
|
+
const matches = descriptors.filter((d) => (d.tiers ?? []).includes(tier));
|
|
93
|
+
const pool = matches.length > 0 ? matches : descriptors;
|
|
94
|
+
pool.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
95
|
+
return pool[0];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function inferTier(environment: string, override?: EnvironmentTier): EnvironmentTier {
|
|
99
|
+
if (override) return override;
|
|
100
|
+
if (environment === 'local' || environment === 'dev' || environment === 'staging' || environment === 'production') {
|
|
101
|
+
return environment;
|
|
102
|
+
}
|
|
103
|
+
return 'local';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve a single credential by walking the candidate keys against
|
|
108
|
+
* process.env then the active secrets store. Returns the first match.
|
|
109
|
+
*
|
|
110
|
+
* Throws when no candidate resolves — adapters should let this bubble
|
|
111
|
+
* up so the CLI surfaces a clean "missing credentials" message rather
|
|
112
|
+
* than a vague "401 Unauthorized" downstream.
|
|
113
|
+
*/
|
|
114
|
+
export async function resolveAdapterCredential(
|
|
115
|
+
options: ResolveAdapterCredentialOptions
|
|
116
|
+
): Promise<ResolvedAdapterCredential> {
|
|
117
|
+
const env = options.environment ?? 'local';
|
|
118
|
+
const tier = inferTier(env, options.tier);
|
|
119
|
+
const includeEnv = options.includeProcessEnv ?? true;
|
|
120
|
+
|
|
121
|
+
// 1. process.env (CI / shell override)
|
|
122
|
+
if (includeEnv) {
|
|
123
|
+
for (const key of options.keyCandidates) {
|
|
124
|
+
const v = process.env[key];
|
|
125
|
+
if (v && v.length > 0) {
|
|
126
|
+
return { key, value: v, source: 'process.env' };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 2. secrets/store runtime resolution (tier-aware, priority-ordered)
|
|
132
|
+
const runtime = getVibesRuntime();
|
|
133
|
+
if (!runtime.hasKind('secrets/store')) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`No secrets/store kind registered; cannot resolve ${options.humanName ?? options.keyCandidates[0]}. ` +
|
|
136
|
+
'Load the secrets plugin (and a backend like encrypted-local) before calling this adapter.'
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const descriptors = runtime
|
|
141
|
+
.assets('secrets/store')
|
|
142
|
+
.descriptors() as SecretsStoreDescriptorShape[];
|
|
143
|
+
// `VIBES_DEBUG_SECRETS=1` dumps the visible descriptor pool when
|
|
144
|
+
// you're tracing why a credential is missing or getting misrouted.
|
|
145
|
+
if (process.env.VIBES_DEBUG_SECRETS === '1') {
|
|
146
|
+
console.error(`[secrets-debug] descriptors visible at tier=${tier}:`);
|
|
147
|
+
for (const d of descriptors) {
|
|
148
|
+
console.error(` - id=${d.id} priority=${d.priority ?? '-'} tiers=${JSON.stringify(d.tiers)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const target = pickBackend(descriptors, tier);
|
|
152
|
+
if (!target) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`No secrets/store backend available for tier=${tier}. Register a backend ` +
|
|
155
|
+
'(encrypted-local for local, cloudflare-secrets-store for production) before calling this adapter.'
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const store = (await runtime
|
|
160
|
+
.query('secrets/store')
|
|
161
|
+
.withId(target.id)
|
|
162
|
+
.resolve()) as SecretsStoreImplShape;
|
|
163
|
+
|
|
164
|
+
if (!store || typeof store.get !== 'function') {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Resolved secrets/store '${target.id}' has no get() method for ${options.humanName ?? options.keyCandidates[0]}.`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const key of options.keyCandidates) {
|
|
171
|
+
try {
|
|
172
|
+
const v = await store.get(env, key);
|
|
173
|
+
if (v && v.length > 0) {
|
|
174
|
+
return { key, value: v, source: target.id };
|
|
175
|
+
}
|
|
176
|
+
} catch {
|
|
177
|
+
// next candidate
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Missing credential: none of [${options.keyCandidates.join(', ')}] resolved from process.env or ` +
|
|
183
|
+
`${target.id} (environment=${env}, tier=${tier}). ` +
|
|
184
|
+
`Set the value with \`vibes secrets set --environment ${env} ${options.keyCandidates[0]} <value>\`.`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Convenience wrapper for resolving multiple credentials at once.
|
|
190
|
+
* Each key gets a candidate list of one (the key itself). Use the
|
|
191
|
+
* single-credential form when you need fallback chains.
|
|
192
|
+
*/
|
|
193
|
+
export async function resolveAdapterCredentials(
|
|
194
|
+
keys: readonly string[],
|
|
195
|
+
options?: Omit<ResolveAdapterCredentialOptions, 'keyCandidates' | 'humanName'>
|
|
196
|
+
): Promise<Record<string, ResolvedAdapterCredential>> {
|
|
197
|
+
const out: Record<string, ResolvedAdapterCredential> = {};
|
|
198
|
+
for (const key of keys) {
|
|
199
|
+
out[key] = await resolveAdapterCredential({
|
|
200
|
+
keyCandidates: [key],
|
|
201
|
+
...(options ?? {})
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appDeploymentSchema,
|
|
3
|
+
deploymentDependencySchema,
|
|
4
|
+
deploymentEnvRequirementSchema,
|
|
5
|
+
deploymentOriginSchema,
|
|
6
|
+
type AppDeployment,
|
|
7
|
+
type AppDeploymentInput,
|
|
8
|
+
type DeploymentDependency,
|
|
9
|
+
type DeploymentEnvRequirement,
|
|
10
|
+
type DeploymentOrigin,
|
|
11
|
+
type DeploymentUpstream
|
|
12
|
+
} from './schemas.ts';
|
|
13
|
+
|
|
14
|
+
export function createAppDeployment(input: AppDeploymentInput): AppDeployment {
|
|
15
|
+
return appDeploymentSchema.parse(input);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createDeploymentOrigin(input: DeploymentOrigin): DeploymentOrigin {
|
|
19
|
+
return deploymentOriginSchema.parse(input);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function createDeploymentEnvRequirement(
|
|
23
|
+
input: DeploymentEnvRequirement
|
|
24
|
+
): DeploymentEnvRequirement {
|
|
25
|
+
return deploymentEnvRequirementSchema.parse(input);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function createDeploymentDependency(input: DeploymentDependency): DeploymentDependency {
|
|
29
|
+
return deploymentDependencySchema.parse(input);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getPrimaryOrigin(deployment: AppDeployment): DeploymentOrigin {
|
|
33
|
+
return (
|
|
34
|
+
deployment.origins.find((origin) => origin.kind === 'primary') ?? deployment.origins[0]
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getUpstreamOriginEnv(
|
|
39
|
+
upstream: DeploymentUpstream
|
|
40
|
+
): Record<string, string> {
|
|
41
|
+
if (!upstream.originEnvVar) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
[upstream.originEnvVar]: upstream.origin
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type {
|
|
51
|
+
AppDeployment,
|
|
52
|
+
AppDeploymentInput,
|
|
53
|
+
DeploymentDependency,
|
|
54
|
+
DeploymentEnvRequirement,
|
|
55
|
+
DeploymentOrigin,
|
|
56
|
+
DeploymentUpstream
|
|
57
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createAppDeployment,
|
|
3
|
+
createDeploymentOrigin,
|
|
4
|
+
createDeploymentEnvRequirement,
|
|
5
|
+
createDeploymentDependency,
|
|
6
|
+
getPrimaryOrigin,
|
|
7
|
+
getUpstreamOriginEnv
|
|
8
|
+
} from './deployment.ts';
|
|
9
|
+
export type {
|
|
10
|
+
AppDeployment,
|
|
11
|
+
AppDeploymentInput,
|
|
12
|
+
DeploymentDependency,
|
|
13
|
+
DeploymentEnvRequirement,
|
|
14
|
+
DeploymentOrigin,
|
|
15
|
+
DeploymentUpstream
|
|
16
|
+
} from './deployment.ts';
|
|
17
|
+
export {
|
|
18
|
+
deploymentProviderSchema,
|
|
19
|
+
appRuntimeSchema,
|
|
20
|
+
deploymentOriginSchema,
|
|
21
|
+
deploymentBuildSchema,
|
|
22
|
+
deploymentEnvRequirementSchema,
|
|
23
|
+
deploymentDependencySchema,
|
|
24
|
+
deploymentUpstreamSchema,
|
|
25
|
+
appDeploymentSchema
|
|
26
|
+
} from './schemas.ts';
|
|
27
|
+
export type {
|
|
28
|
+
DeploymentProvider,
|
|
29
|
+
AppRuntime,
|
|
30
|
+
DeploymentOrigin as DeploymentOriginType,
|
|
31
|
+
DeploymentBuild,
|
|
32
|
+
DeploymentEnvRequirement as DeploymentEnvRequirementType,
|
|
33
|
+
DeploymentDependency as DeploymentDependencyType,
|
|
34
|
+
DeploymentUpstream as DeploymentUpstreamType,
|
|
35
|
+
AppDeploymentInput as AppDeploymentInputType,
|
|
36
|
+
AppDeployment as AppDeploymentType
|
|
37
|
+
} from './schemas.ts';
|
|
38
|
+
export {
|
|
39
|
+
webAppKind, WebAppDescriptorSchema, WebAppConfigSchema, CloudflareWorkersWebAppConfigSchema, DigitalOceanAppWebAppConfigSchema
|
|
40
|
+
} from './kinds/index.ts';
|
|
41
|
+
export type { WebAppDescriptor, WebAppDependency } from './kinds/index.ts';
|
|
42
|
+
export {
|
|
43
|
+
workerKind, WorkerDescriptorSchema, WorkerConfigSchema, DoksDeploymentWorkerConfigSchema, WorkerScalingSchema
|
|
44
|
+
} from './kinds/index.ts';
|
|
45
|
+
export type { WorkerDescriptor, WorkerScaling } from './kinds/index.ts';
|
|
46
|
+
export {
|
|
47
|
+
databaseKind, DatabaseDescriptorSchema, DatabaseConfigSchema, DoksDatabaseConfigSchema, DOManagedPostgresConfigSchema, TursoDatabaseConfigSchema, CloudflareD1ConfigSchema, DatabaseBackupSchema
|
|
48
|
+
} from './kinds/index.ts';
|
|
49
|
+
export type { DatabaseDescriptor, DatabaseBackup } from './kinds/index.ts';
|
|
50
|
+
export {
|
|
51
|
+
queueKind, QueueDescriptorSchema, QueueConfigSchema, DoksQueueConfigSchema, QueueTopicSchema
|
|
52
|
+
} from './kinds/index.ts';
|
|
53
|
+
export type { QueueDescriptor, QueueTopic } from './kinds/index.ts';
|
|
54
|
+
export { cacheKind, CacheDescriptorSchema, CacheConfigSchema, DOManagedRedisConfigSchema } from './kinds/index.ts';
|
|
55
|
+
export type { CacheDescriptor } from './kinds/index.ts';
|
|
56
|
+
export {
|
|
57
|
+
objectStorageKind, ObjectStorageDescriptorSchema, ObjectStorageConfigSchema, DOSpacesConfigSchema, CorsRuleSchema, LifecycleRuleSchema
|
|
58
|
+
} from './kinds/index.ts';
|
|
59
|
+
export type { ObjectStorageDescriptor, CorsRule, LifecycleRule } from './kinds/index.ts';
|
|
60
|
+
export {
|
|
61
|
+
sandboxKind, SandboxDescriptorSchema, SandboxConfigSchema, CloudflareSandboxConfigSchema, DockerSandboxConfigSchema, DigitalOceanDropletSandboxConfigSchema, SandboxOutboundProxySchema, SandboxResourceLimitsSchema
|
|
62
|
+
} from './kinds/index.ts';
|
|
63
|
+
export type { SandboxDescriptor, SandboxOutboundProxy, SandboxResourceLimits } from './kinds/index.ts';
|
|
64
|
+
export {
|
|
65
|
+
gitHostingKind, GitHostingDescriptorSchema, GitHostingConfigSchema, GiteaDoksGitHostingConfigSchema, GitHostingTypeSchema, GitHostingAuthMethodSchema
|
|
66
|
+
} from './kinds/index.ts';
|
|
67
|
+
export type { GitHostingDescriptor, GitHostingType, GitHostingAuthMethod } from './kinds/index.ts';
|
|
68
|
+
export {
|
|
69
|
+
packageRegistryKind, PackageRegistryDescriptorSchema, PackageRegistryConfigSchema, VerdaccioDoksPackageRegistryConfigSchema, PackageRegistryTypeSchema
|
|
70
|
+
} from './kinds/index.ts';
|
|
71
|
+
export type { PackageRegistryDescriptor, PackageRegistryType } from './kinds/index.ts';
|
|
72
|
+
export {
|
|
73
|
+
logsKind, InfraLogsDescriptorSchema, type InfraLogsDescriptor, type InfraLogsDescriptorInput, type InfraLogsKind, type InfraLogsKindInput, type LogsImplementation
|
|
74
|
+
} from './kinds/index.ts';
|
|
75
|
+
export {
|
|
76
|
+
artifactKind,
|
|
77
|
+
ArtifactDescriptorSchema,
|
|
78
|
+
type ArtifactDescriptor,
|
|
79
|
+
type ArtifactGenerator,
|
|
80
|
+
type ArtifactOutput
|
|
81
|
+
} from './kinds/index.ts';
|
|
82
|
+
export { INFRA_DISCOVERY_PATTERN, extractStem } from './kinds/index.ts';
|
|
83
|
+
export {
|
|
84
|
+
alertsKind,
|
|
85
|
+
InfraAlertsDescriptorSchema,
|
|
86
|
+
AlertPolicySchema,
|
|
87
|
+
AlertMechanismSchema,
|
|
88
|
+
AlertTypeSchema,
|
|
89
|
+
AlertWindowSchema,
|
|
90
|
+
type InfraAlertsDescriptor,
|
|
91
|
+
type InfraAlertsDescriptorInput,
|
|
92
|
+
type InfraAlertsKind,
|
|
93
|
+
type InfraAlertsKindInput,
|
|
94
|
+
type AlertsImplementation,
|
|
95
|
+
type AlertPolicy,
|
|
96
|
+
type AlertMechanism,
|
|
97
|
+
type AlertType
|
|
98
|
+
} from './kinds/index.ts';
|
|
99
|
+
export {
|
|
100
|
+
observabilityKind,
|
|
101
|
+
InfraObservabilityDescriptorSchema,
|
|
102
|
+
ObservabilityScopeSchema,
|
|
103
|
+
ObservabilitySettingsSchema,
|
|
104
|
+
type InfraObservabilityDescriptor,
|
|
105
|
+
type InfraObservabilityDescriptorInput,
|
|
106
|
+
type InfraObservabilityKind,
|
|
107
|
+
type InfraObservabilityKindInput,
|
|
108
|
+
type ObservabilityImplementation,
|
|
109
|
+
type ObservabilityScope,
|
|
110
|
+
type ObservabilitySettings,
|
|
111
|
+
type ObservabilitySnapshot,
|
|
112
|
+
type SetObservabilityInput,
|
|
113
|
+
type SetObservabilityResult
|
|
114
|
+
} from './kinds/index.ts';
|
|
115
|
+
export {
|
|
116
|
+
rumKind,
|
|
117
|
+
InfraRumDescriptorSchema,
|
|
118
|
+
RumPrivacySchema,
|
|
119
|
+
RumInjectionSchema,
|
|
120
|
+
type InfraRumDescriptor,
|
|
121
|
+
type InfraRumDescriptorInput,
|
|
122
|
+
type InfraRumKind,
|
|
123
|
+
type InfraRumKindInput,
|
|
124
|
+
type RumImplementation,
|
|
125
|
+
type RumSiteSnapshot,
|
|
126
|
+
type RumPrivacy,
|
|
127
|
+
type RumInjection
|
|
128
|
+
} from './kinds/index.ts';
|
|
129
|
+
export {
|
|
130
|
+
resolveAdapterCredential,
|
|
131
|
+
resolveAdapterCredentials,
|
|
132
|
+
type EnvironmentTier,
|
|
133
|
+
type ResolveAdapterCredentialOptions,
|
|
134
|
+
type ResolvedAdapterCredential
|
|
135
|
+
} from './credentials/resolve.ts';
|
|
136
|
+
export {
|
|
137
|
+
bootstrapSeedKind,
|
|
138
|
+
bootstrapSeedConditionSchema,
|
|
139
|
+
bootstrapSeedDescriptorSchema,
|
|
140
|
+
bootstrapSeedModeSchema,
|
|
141
|
+
runBootstrapSeeds,
|
|
142
|
+
type BootstrapSeedCondition,
|
|
143
|
+
type BootstrapSeedDescriptor,
|
|
144
|
+
type BootstrapSeedImpl,
|
|
145
|
+
type BootstrapSeedMode,
|
|
146
|
+
type BootstrapSeedRunOptions,
|
|
147
|
+
type BootstrapSeedRunResult
|
|
148
|
+
} from './bootstrap/index.ts';
|
|
149
|
+
export { default as infraPlugin } from './infra.plugin';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure Runtime Plugin
|
|
3
|
+
*
|
|
4
|
+
* Registers all infra resource kinds with the runtime.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createRuntimePlugin } from '@vibesdotdev/runtime/factory/plugin';
|
|
8
|
+
import { webAppKind } from './kinds/web-app.kind';
|
|
9
|
+
import { workerKind } from './kinds/worker.kind';
|
|
10
|
+
import { databaseKind } from './kinds/database.kind';
|
|
11
|
+
import { queueKind } from './kinds/queue.kind';
|
|
12
|
+
import { cacheKind } from './kinds/cache.kind';
|
|
13
|
+
import { objectStorageKind } from './kinds/object-storage.kind';
|
|
14
|
+
import { sandboxKind } from './kinds/sandbox.kind';
|
|
15
|
+
import { gitHostingKind } from './kinds/git-hosting.kind';
|
|
16
|
+
import { packageRegistryKind } from './kinds/package-registry.kind';
|
|
17
|
+
import { logsKind } from './kinds/logs.kind';
|
|
18
|
+
import { alertsKind } from './kinds/alerts.kind.ts';
|
|
19
|
+
import { observabilityKind } from './kinds/observability.kind.ts';
|
|
20
|
+
import { rumKind } from './kinds/rum.kind.ts';
|
|
21
|
+
import { bootstrapSeedKind } from './bootstrap/index.ts';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Note on layering: inference is an apps/ai domain concern, not an infra kind.
|
|
25
|
+
* Existing runtime kinds `ai/provider`, `ai/adapter`, `ai/model`, and
|
|
26
|
+
* `ai/generation` already express "who/how/where inference runs", and the
|
|
27
|
+
* runtime's hardware scope + connectionMode qualifier + priority already
|
|
28
|
+
* select between consumer-direct, consumer-worker, cloud-worker, and
|
|
29
|
+
* cloud-via-API strategies. New strategies (CF Unified Inference, Agents
|
|
30
|
+
* Week bindings) should be added as new `ai/provider` descriptors + adapters,
|
|
31
|
+
* not as a parallel `infra/inference` kind.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export default createRuntimePlugin({
|
|
35
|
+
id: 'infra',
|
|
36
|
+
name: 'Infrastructure',
|
|
37
|
+
description: 'Resource kinds for deployable infrastructure',
|
|
38
|
+
kinds: [
|
|
39
|
+
webAppKind,
|
|
40
|
+
workerKind,
|
|
41
|
+
databaseKind,
|
|
42
|
+
queueKind,
|
|
43
|
+
cacheKind,
|
|
44
|
+
objectStorageKind,
|
|
45
|
+
sandboxKind,
|
|
46
|
+
gitHostingKind,
|
|
47
|
+
packageRegistryKind,
|
|
48
|
+
logsKind,
|
|
49
|
+
alertsKind,
|
|
50
|
+
observabilityKind,
|
|
51
|
+
rumKind,
|
|
52
|
+
bootstrapSeedKind
|
|
53
|
+
]
|
|
54
|
+
});
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infra Alerts Kind
|
|
3
|
+
*
|
|
4
|
+
* Provider-agnostic schema for alerting / notification policies that
|
|
5
|
+
* span billing (budget + per-product usage), reliability (error rate,
|
|
6
|
+
* latency), and operational lifecycle (deploys, subscription changes).
|
|
7
|
+
*
|
|
8
|
+
* Per-provider implementations (cloudflare-alerts, do-monitoring,
|
|
9
|
+
* cloudwatch-alarms) map this shape onto the native API. Where a
|
|
10
|
+
* provider doesn't support a `type`, the impl rejects with a clear
|
|
11
|
+
* "unsupported" error rather than silently falling back.
|
|
12
|
+
*
|
|
13
|
+
* Configuration is declarative — typically encoded in an
|
|
14
|
+
* `infra/account.config.ts` or `infra/alerts.infra.ts` file alongside
|
|
15
|
+
* `infra/dns.ts`. The CLI (`vibes infra alerts list|create|delete`)
|
|
16
|
+
* wraps the same primitive for one-off ops and drift detection.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import * as z from 'zod/v4';
|
|
20
|
+
import { createRuntimeKind } from '@vibesdotdev/runtime/factory/kind';
|
|
21
|
+
import { RuntimeDescriptorSchema } from '@vibesdotdev/runtime/schemas/descriptor';
|
|
22
|
+
import { INFRA_DISCOVERY_PATTERN, extractStem } from './discovery.ts';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Delivery channel for an alert. Provider impls translate these to
|
|
26
|
+
* native delivery slots (e.g. CF's `mechanisms.email[]`).
|
|
27
|
+
*/
|
|
28
|
+
const AlertMechanismSchema = z.discriminatedUnion('kind', [
|
|
29
|
+
z.object({
|
|
30
|
+
kind: z.literal('email'),
|
|
31
|
+
/** Email address — must be a verified destination on the provider. */
|
|
32
|
+
target: z.email()
|
|
33
|
+
}),
|
|
34
|
+
z.object({
|
|
35
|
+
kind: z.literal('webhook'),
|
|
36
|
+
/** Outbound webhook URL. */
|
|
37
|
+
target: z.string().url(),
|
|
38
|
+
/** Optional secret name (in the active secrets store) used for HMAC signing. */
|
|
39
|
+
secretRef: z.string().optional()
|
|
40
|
+
}),
|
|
41
|
+
z.object({
|
|
42
|
+
kind: z.literal('pagerduty'),
|
|
43
|
+
/** PagerDuty integration key (Events API v2). */
|
|
44
|
+
target: z.string().min(1)
|
|
45
|
+
}),
|
|
46
|
+
z.object({
|
|
47
|
+
kind: z.literal('slack'),
|
|
48
|
+
/** Slack webhook URL (Incoming Webhooks). */
|
|
49
|
+
target: z.string().url()
|
|
50
|
+
})
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
export type AlertMechanism = z.infer<typeof AlertMechanismSchema>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Cross-provider alert categories. Each maps to one or more native
|
|
57
|
+
* alert types per provider.
|
|
58
|
+
*/
|
|
59
|
+
const AlertTypeSchema = z.enum([
|
|
60
|
+
/** Total cost crossed a dollar threshold for the current billing period. */
|
|
61
|
+
'budget',
|
|
62
|
+
/** Per-product usage crossed a numeric threshold (events/req/GB/etc.). */
|
|
63
|
+
'usage',
|
|
64
|
+
/** Worker/service error rate over a rolling window. */
|
|
65
|
+
'error-rate',
|
|
66
|
+
/** P99 latency or wall-time crossed a threshold. */
|
|
67
|
+
'latency',
|
|
68
|
+
/** Catch-all for provider-specific types not yet modeled here. */
|
|
69
|
+
'custom'
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
export type AlertType = z.infer<typeof AlertTypeSchema>;
|
|
73
|
+
|
|
74
|
+
const AlertWindowSchema = z.enum(['5m', '15m', '1h', '6h', '24h', '7d', '30d']);
|
|
75
|
+
|
|
76
|
+
const AlertPolicySchema = z.object({
|
|
77
|
+
/** Stable id for diffing. Auto-generated when omitted. */
|
|
78
|
+
id: z.string().min(1).optional(),
|
|
79
|
+
/** Human-readable name (also surfaced by the provider). */
|
|
80
|
+
name: z.string().min(1),
|
|
81
|
+
type: AlertTypeSchema,
|
|
82
|
+
/**
|
|
83
|
+
* Threshold value. `budget` reads it as USD (or local currency).
|
|
84
|
+
* `usage`/`error-rate`/`latency` read it as units defined by the
|
|
85
|
+
* filter (event count, %, ms).
|
|
86
|
+
*/
|
|
87
|
+
threshold: z.number().nonnegative(),
|
|
88
|
+
/** Optional secondary threshold for tiered alerts. */
|
|
89
|
+
warningThreshold: z.number().nonnegative().optional(),
|
|
90
|
+
/** Rolling window for `usage`/`error-rate`/`latency`. Ignored for `budget`. */
|
|
91
|
+
window: AlertWindowSchema.optional(),
|
|
92
|
+
/**
|
|
93
|
+
* Adapter-specific filters. Examples:
|
|
94
|
+
* { product: 'workers_observability' } // usage on a specific CF product
|
|
95
|
+
* { worker: 'vibes-account' } // error-rate scoped to one worker
|
|
96
|
+
* { native_alert_type: 'health_check_status_notification' } // custom escape
|
|
97
|
+
*/
|
|
98
|
+
filters: z.record(z.string(), z.string()).default({}),
|
|
99
|
+
mechanisms: z.array(AlertMechanismSchema).min(1),
|
|
100
|
+
enabled: z.boolean().default(true),
|
|
101
|
+
description: z.string().optional()
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export type AlertPolicy = z.infer<typeof AlertPolicySchema>;
|
|
105
|
+
|
|
106
|
+
const AlertsBaseSchema = RuntimeDescriptorSchema.extend({
|
|
107
|
+
kind: z.literal('infra/alerts'),
|
|
108
|
+
/** Adapter id (e.g. 'cloudflare-alerts', 'do-monitoring'). */
|
|
109
|
+
adapter: z.string().min(1),
|
|
110
|
+
adapterConfig: z.record(z.string(), z.unknown()).optional(),
|
|
111
|
+
/**
|
|
112
|
+
* Default environment name for credential resolution via `vibes
|
|
113
|
+
* secrets`. Defaults to 'local' since the CLI / dev workflow is
|
|
114
|
+
* the primary caller; production Workers that consume this adapter
|
|
115
|
+
* read credentials from CF Secrets Store bindings directly, not
|
|
116
|
+
* through this descriptor.
|
|
117
|
+
*/
|
|
118
|
+
environment: z.string().default('local'),
|
|
119
|
+
policies: z.array(AlertPolicySchema).default([])
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export type InfraAlertsDescriptor = z.infer<typeof AlertsBaseSchema>;
|
|
123
|
+
export type InfraAlertsDescriptorInput = z.input<typeof AlertsBaseSchema>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Implementation contract every provider implements. Operations are
|
|
127
|
+
* idempotent: `applyPolicies` reconciles the live policy set to the
|
|
128
|
+
* desired set without trampling unrelated policies on the provider.
|
|
129
|
+
*/
|
|
130
|
+
export interface AlertsImplementation {
|
|
131
|
+
/** List policies currently configured on the provider. */
|
|
132
|
+
listPolicies(): Promise<Array<AlertPolicy & { providerId: string }>>;
|
|
133
|
+
/** Create a single policy. Returns the provider-assigned id. */
|
|
134
|
+
createPolicy(policy: AlertPolicy): Promise<{ providerId: string }>;
|
|
135
|
+
/** Delete a policy by provider id. */
|
|
136
|
+
deletePolicy(providerId: string): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Diff desired (descriptor) against live; return the set of policies
|
|
139
|
+
* that need create/update/delete. Empty arrays = in sync.
|
|
140
|
+
*/
|
|
141
|
+
diff(desired: AlertPolicy[]): Promise<{
|
|
142
|
+
create: AlertPolicy[];
|
|
143
|
+
update: Array<{ providerId: string; policy: AlertPolicy }>;
|
|
144
|
+
delete: Array<{ providerId: string; name: string }>;
|
|
145
|
+
}>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const alertsKind = createRuntimeKind<InfraAlertsDescriptor, AlertsImplementation>({
|
|
149
|
+
id: 'infra/alerts',
|
|
150
|
+
descriptorSchema: AlertsBaseSchema,
|
|
151
|
+
discoveryPattern: INFRA_DISCOVERY_PATTERN,
|
|
152
|
+
extractStem
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export type InfraAlertsKind = InfraAlertsDescriptor;
|
|
156
|
+
export type InfraAlertsKindInput = InfraAlertsDescriptorInput;
|
|
157
|
+
|
|
158
|
+
export {
|
|
159
|
+
AlertsBaseSchema as InfraAlertsDescriptorSchema,
|
|
160
|
+
AlertPolicySchema,
|
|
161
|
+
AlertMechanismSchema,
|
|
162
|
+
AlertTypeSchema,
|
|
163
|
+
AlertWindowSchema
|
|
164
|
+
};
|