@konfig.ts/k8s 0.0.9 → 0.0.10
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/dist/.generated/k8s-types/index.d.ts +1 -1
- package/dist/backend.d.ts +4 -14
- package/dist/env.d.ts +2 -2
- package/dist/index.d.ts +1 -15
- package/dist/index.mjs +104 -103
- package/dist/index.mjs.map +1 -1
- package/dist/nativeSecret.d.ts +2 -1
- package/dist/secretBind.d.ts +11 -4
- package/dist/workload.d.ts +5 -5
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Deployment, DeploymentSpec, StatefulSet, StatefulSetSpec } from "kubernetes-types/apps/v1";
|
|
1
|
+
export type { Deployment, DeploymentSpec, DeploymentStrategy, StatefulSet, StatefulSetSpec, StatefulSetUpdateStrategy } from "kubernetes-types/apps/v1";
|
|
2
2
|
export type { CronJob, Job, JobSpec } from "kubernetes-types/batch/v1";
|
|
3
3
|
export type { ConfigMap, Container, ContainerPort, EnvVar, EnvVarSource, LocalObjectReference, Namespace, PersistentVolume, PersistentVolumeClaim, PodSpec, PodTemplateSpec, Secret, Service, ServiceAccount, ServicePort, Volume, VolumeMount } from "kubernetes-types/core/v1";
|
|
4
4
|
export type { ObjectMeta } from "kubernetes-types/meta/v1";
|
package/dist/backend.d.ts
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
import type { Manifest } from "@konfig.ts/core";
|
|
2
2
|
import type { SecretSource } from "@konfig.ts/env";
|
|
3
3
|
export type BackendTag = "Sops" | "Sops.passthrough" | "SealedSecrets" | "ExternalSecrets" | "NativeSecret";
|
|
4
|
-
export interface BackendEmitInput<N extends string, K extends string> {
|
|
4
|
+
export interface BackendEmitInput<N extends string, K extends string, RequiresSource extends boolean = boolean> {
|
|
5
5
|
readonly name: N;
|
|
6
6
|
readonly namespace: string;
|
|
7
7
|
readonly keys: ReadonlyArray<K>;
|
|
8
8
|
readonly labels?: Readonly<Record<string, string>>;
|
|
9
9
|
readonly annotations?: Readonly<Record<string, string>>;
|
|
10
|
-
readonly source
|
|
10
|
+
readonly source: RequiresSource extends true ? SecretSource<K, Manifest.RenderServices> : SecretSource<K, Manifest.RenderServices> | undefined;
|
|
11
11
|
}
|
|
12
|
-
export interface SecretBackend<N extends string, K extends string, RequiresSource extends boolean = boolean> {
|
|
12
|
+
export interface SecretBackend<N extends string, K extends string, RequiresSource extends boolean = boolean, Out = unknown> {
|
|
13
13
|
readonly _tag: BackendTag;
|
|
14
14
|
readonly requiresSource: RequiresSource;
|
|
15
|
-
readonly emit: (input: BackendEmitInput<N, K>) => Manifest.Manifest<
|
|
15
|
+
readonly emit: (input: BackendEmitInput<N, K, RequiresSource>) => Manifest.Manifest<Out>;
|
|
16
16
|
}
|
|
17
|
-
declare const BackendSourceMissing_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
18
|
-
readonly _tag: "BackendSourceMissing";
|
|
19
|
-
} & Readonly<A>;
|
|
20
|
-
export declare class BackendSourceMissing extends BackendSourceMissing_base<{
|
|
21
|
-
readonly backend: BackendTag;
|
|
22
|
-
readonly secret: string;
|
|
23
|
-
}> {
|
|
24
|
-
get message(): string;
|
|
25
|
-
}
|
|
26
|
-
export {};
|
package/dist/env.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ConfigMapRef, SecretRef } from "@konfig.ts/core";
|
|
2
2
|
export interface EnvVarSource {
|
|
3
3
|
readonly secretKeyRef?: {
|
|
4
|
-
readonly name: string
|
|
4
|
+
readonly name: SecretRef<string>;
|
|
5
5
|
readonly key: string;
|
|
6
6
|
readonly optional?: boolean;
|
|
7
7
|
};
|
|
8
8
|
readonly configMapKeyRef?: {
|
|
9
|
-
readonly name: string
|
|
9
|
+
readonly name: ConfigMapRef<string>;
|
|
10
10
|
readonly key: string;
|
|
11
11
|
readonly optional?: boolean;
|
|
12
12
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -4,25 +4,11 @@ export { type ContainerPort, type ContainerProtocol, type ExecAction, type GrpcA
|
|
|
4
4
|
export { type ConfigMapEnvInput, EnvVar, type EnvVarSource, type RawEnvInput, type SecretEnvForPodInput, type SecretEnvInput, type ValueEnvInput } from "./env";
|
|
5
5
|
export { ConfigMap, type ConfigMapInput, type ConfigMapManifest, Namespace, type NamespaceInput, type NamespaceManifest, type SecretInput, type SecretManifest, ServiceAccount, type ServiceAccountInput, type ServiceAccountManifest } from "./identity";
|
|
6
6
|
import { Environment as _EnvironmentContract } from "@konfig.ts/env";
|
|
7
|
-
/**
|
|
8
|
-
* `Secret` value namespace — merges the env-contracts side (`define`)
|
|
9
|
-
* with the K8s side (`make`, `bind`, identity helpers). Importing
|
|
10
|
-
* `Secret` from `@konfig.ts/k8s` gives you the full surface:
|
|
11
|
-
*
|
|
12
|
-
* Secret.define({ name, namespace, env }) — env contract (from @konfig.ts/env)
|
|
13
|
-
* Secret.make({ name, namespace, stringData }) — K8s Secret manifest
|
|
14
|
-
* Secret.bind({ secret, backend, source }) — env-to-manifest binder
|
|
15
|
-
*/
|
|
16
7
|
export declare const Secret: {
|
|
17
8
|
bind: <N extends string, K extends string, E extends Readonly<Record<K, string>>, const Ns extends string = string>(input: import("./secretBind").BindSecretInput<N, K, E, Ns>) => import("./secretBind").DeclaredSecret<N, K, Ns>;
|
|
18
9
|
make: <const N extends string, const Ns extends string = string, const K extends string = string>(input: import("./identity").SecretInput<N, Ns, K>) => import("./identity").SecretManifest<N, Ns, K>;
|
|
19
10
|
define: <const N extends string, const E extends Readonly<Record<string, string>>>(input: import("@konfig.ts/env").DefineSecretInput<N, E>) => import("@konfig.ts/env").SecretEntry<N, keyof E & string, E>;
|
|
20
11
|
};
|
|
21
|
-
/**
|
|
22
|
-
* `Environment` value namespace — merges `define` (env-contracts) with
|
|
23
|
-
* `bind` + `runtime` (K8s). The same `Environment` symbol carries the
|
|
24
|
-
* declaration, the manifest binder, and the runtime decoder.
|
|
25
|
-
*/
|
|
26
12
|
export declare const Environment: {
|
|
27
13
|
bind: <const M extends Readonly<Record<string, import("@konfig.ts/env").EnvMember>>, const Ns extends string = string>(input: import("./environmentBind").BindEnvironmentInput<M, Ns>) => import("./environmentBind").DeclaredEnvironment<M, Ns>;
|
|
28
14
|
runtime: <M extends Readonly<Record<string, import("@konfig.ts/env").EnvMember>>>(env: _EnvironmentContract<M>) => import("effect/Effect").Effect<import("@konfig.ts/env").EnvironmentShape<M>, import("effect/Config").ConfigError>;
|
|
@@ -30,7 +16,7 @@ export declare const Environment: {
|
|
|
30
16
|
readonly _konfig_error: `Environment: envName "${Extract<{ [K in keyof M]: Extract<M[K] extends infer T ? T extends M[K] ? T extends import("@konfig.ts/env").SecretEntry<infer _N extends string, infer _K extends string, infer Envs extends Readonly<Record<infer _K extends string, string>>> ? Envs extends Readonly<Record<string, infer V extends string>> ? V : never : T extends import("@konfig.ts/env").LiteralEntry<infer EnvName extends string, infer _T> ? EnvName : T extends import("@konfig.ts/env").DownwardEntry<infer EnvName_1 extends string> ? EnvName_1 : never : never : never, { [Other in keyof M]: Other extends K ? never : M[Other] extends infer T_1 ? T_1 extends M[Other] ? T_1 extends import("@konfig.ts/env").SecretEntry<infer _N extends string, infer _K extends string, infer Envs extends Readonly<Record<infer _K extends string, string>>> ? Envs extends Readonly<Record<string, infer V extends string>> ? V : never : T_1 extends import("@konfig.ts/env").LiteralEntry<infer EnvName extends string, infer _T> ? EnvName : T_1 extends import("@konfig.ts/env").DownwardEntry<infer EnvName_1 extends string> ? EnvName_1 : never : never : never; }[keyof M]>; }[keyof M], string>}" is claimed by multiple members`;
|
|
31
17
|
})) => _EnvironmentContract<M>;
|
|
32
18
|
};
|
|
33
|
-
export { type BackendEmitInput,
|
|
19
|
+
export { type BackendEmitInput, type BackendTag, type SecretBackend } from "./backend";
|
|
34
20
|
export type { BindEnvironmentInput, DeclaredDownward, DeclaredEnvironment, DeclaredLiteral, DeclaredMember, HasSecrets, SecretMemberOptions, SecretMemberOptionsFor, SecretMembersOpts } from "./environmentBind";
|
|
35
21
|
export { NativeSecret, type NativeSecretOptions } from "./nativeSecret";
|
|
36
22
|
export { Ingress, type IngressInput, type IngressTLSInput, Service, type ServiceFromContainerInput, type ServiceFromPodSetInput, type ServiceInput } from "./network";
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dep, Manifest, RenderError, brand, unsafeCoerce } from "@konfig.ts/core";
|
|
2
|
-
import {
|
|
2
|
+
import { Effect, Layer, Match, Redacted } from "effect";
|
|
3
3
|
import { Environment as Environment$1, Secret as Secret$1, runtime } from "@konfig.ts/env";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
//#region \0rolldown/runtime.js
|
|
@@ -240,17 +240,27 @@ const Secret$2 = { make: (input) => {
|
|
|
240
240
|
} };
|
|
241
241
|
//#endregion
|
|
242
242
|
//#region src/secretBind.ts
|
|
243
|
+
const _buildValuesLayer = (input) => {
|
|
244
|
+
const values = Dep.SecretValues(input.name);
|
|
245
|
+
return {
|
|
246
|
+
values,
|
|
247
|
+
layer: Layer.effect(values, input.source.resolve.pipe(Effect.mapError((cause) => new RenderError({
|
|
248
|
+
message: `SecretValues(${input.namespace}/${input.name}): source failed for key "${cause.key}"`,
|
|
249
|
+
cause
|
|
250
|
+
}))))
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
const _buildEnvVars = (secret, ref) => secret.keys.map((key) => EnvVar.fromSecret({
|
|
254
|
+
name: secret.env[key],
|
|
255
|
+
ref,
|
|
256
|
+
key
|
|
257
|
+
}));
|
|
258
|
+
const _missingSourceManifest = (backend, name, namespace) => Manifest.make(() => Effect.fail(new RenderError({ message: `backend "${backend._tag}" requires a source but none was provided for secret "${namespace}/${name}"` })));
|
|
243
259
|
const bindSecret = (input) => {
|
|
244
260
|
const { secret } = input;
|
|
245
261
|
const namespace = unsafeCoerce(input.namespace ?? secret.namespace, "Ns defaults to `string`; the override (if present) is `Ns`, the secret's own namespace is `string` — runtime value either way is a string");
|
|
246
262
|
const ref = SecretRef.of(secret.name);
|
|
247
|
-
const
|
|
248
|
-
name: secret.env[key],
|
|
249
|
-
ref,
|
|
250
|
-
key
|
|
251
|
-
}));
|
|
252
|
-
const refLayer = Dep.provideSecret(secret.name);
|
|
253
|
-
const manifest = input.backend === void 0 ? void 0 : input.backend.emit({
|
|
263
|
+
const manifest = input.backend === void 0 ? void 0 : input.backend.requiresSource && input.source === void 0 ? _missingSourceManifest(input.backend, secret.name, namespace) : input.backend.emit({
|
|
254
264
|
name: secret.name,
|
|
255
265
|
namespace,
|
|
256
266
|
keys: secret.keys,
|
|
@@ -263,21 +273,17 @@ const bindSecret = (input) => {
|
|
|
263
273
|
name: secret.name,
|
|
264
274
|
namespace,
|
|
265
275
|
keys: secret.keys,
|
|
266
|
-
envVars,
|
|
276
|
+
envVars: _buildEnvVars(secret, ref),
|
|
267
277
|
manifest,
|
|
268
|
-
refLayer
|
|
278
|
+
refLayer: Dep.provideSecret(secret.name)
|
|
269
279
|
};
|
|
270
|
-
|
|
271
|
-
const source = input.source;
|
|
272
|
-
const valuesTag = Dep.SecretValues(secret.name);
|
|
273
|
-
const layer = Layer.effect(valuesTag, source.resolve.pipe(Effect.mapError((cause) => new RenderError({
|
|
274
|
-
message: `SecretValues(${namespace}/${secret.name}): source failed for key "${cause.key}"`,
|
|
275
|
-
cause
|
|
276
|
-
}))));
|
|
277
|
-
return {
|
|
280
|
+
return input.source === void 0 ? out : {
|
|
278
281
|
...out,
|
|
279
|
-
|
|
280
|
-
|
|
282
|
+
..._buildValuesLayer({
|
|
283
|
+
name: secret.name,
|
|
284
|
+
namespace,
|
|
285
|
+
source: input.source
|
|
286
|
+
})
|
|
281
287
|
};
|
|
282
288
|
};
|
|
283
289
|
//#endregion
|
|
@@ -344,8 +350,18 @@ const _handleEnvironment = (input) => {
|
|
|
344
350
|
input.acc.valuesLayers.push(unsafeCoerce(sub.valuesLayer, "valuesLayer aggregate over the recursive merge"));
|
|
345
351
|
};
|
|
346
352
|
const _dispatch = (input) => Match.value(input.entry._kind).pipe(Match.when("Secret", () => _handleSecret(input)), Match.when("Literal", () => _handleLiteral(input)), Match.when("Downward", () => _handleDownward(input)), Match.when("Environment", () => _handleEnvironment(input)), Match.exhaustive);
|
|
353
|
+
const _dispatchAllMembers = (input) => {
|
|
354
|
+
for (const memberKey of Object.keys(input.env.members)) _dispatch({
|
|
355
|
+
memberKey,
|
|
356
|
+
entry: unsafeCoerce(input.env.members[memberKey], "env.members values are EnvMember by construction"),
|
|
357
|
+
secretsOpts: input.secretsOpts,
|
|
358
|
+
literalsOpts: input.literalsOpts,
|
|
359
|
+
namespace: input.namespace,
|
|
360
|
+
acc: input.acc
|
|
361
|
+
});
|
|
362
|
+
};
|
|
363
|
+
const _mergeValuesLayers = (layers) => unsafeCoerce(layers.length === 0 ? Layer.empty : Layer.mergeAll(layers[0], ...layers.slice(1)), "merged Layer over a heterogeneous list of per-secret value layers");
|
|
347
364
|
const bindEnvironment = (input) => {
|
|
348
|
-
const { env } = input;
|
|
349
365
|
const acc = {
|
|
350
366
|
declared: {},
|
|
351
367
|
envVars: [],
|
|
@@ -354,34 +370,25 @@ const bindEnvironment = (input) => {
|
|
|
354
370
|
};
|
|
355
371
|
const secretsOpts = unsafeCoerce(input.secrets, "discriminated union from BindEnvironmentInput; iterate keys at runtime");
|
|
356
372
|
const literalsOpts = unsafeCoerce(input.literals, "discriminated union from BindEnvironmentInput; iterate keys at runtime");
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
entry: unsafeCoerce(env.members[memberKey], "env.members values are EnvMember by construction"),
|
|
373
|
+
_dispatchAllMembers({
|
|
374
|
+
env: input.env,
|
|
360
375
|
secretsOpts,
|
|
361
376
|
literalsOpts,
|
|
362
377
|
namespace: input.namespace,
|
|
363
378
|
acc
|
|
364
379
|
});
|
|
365
|
-
const valuesLayer = unsafeCoerce(acc.valuesLayers.length === 0 ? Layer.empty : Layer.mergeAll(acc.valuesLayers[0], ...acc.valuesLayers.slice(1)), "merged Layer over a heterogeneous list of per-secret value layers");
|
|
366
380
|
return {
|
|
367
381
|
envVars: acc.envVars,
|
|
368
382
|
manifests: acc.manifests,
|
|
369
383
|
members: unsafeCoerce(acc.declared, "declared populated by iterating env.members; each key maps to its DeclaredMember<M[K], Ns>"),
|
|
370
|
-
valuesLayer
|
|
384
|
+
valuesLayer: _mergeValuesLayers(acc.valuesLayers)
|
|
371
385
|
};
|
|
372
386
|
};
|
|
373
387
|
//#endregion
|
|
374
|
-
//#region src/backend.ts
|
|
375
|
-
var BackendSourceMissing = class extends Data.TaggedError("BackendSourceMissing") {
|
|
376
|
-
get message() {
|
|
377
|
-
return `backend "${this.backend}" requires a source but none was provided for secret "${this.secret}"`;
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
//#endregion
|
|
381
388
|
//#region src/nativeSecret.ts
|
|
382
389
|
const _emit = (input) => Manifest.make((_ctx) => Effect.gen(function* () {
|
|
383
390
|
if (input.opts.silenceWarning !== true) yield* Effect.logWarning(`NativeSecret backend emits a plaintext Secret with stringData on disk for "${input.base.namespace}/${input.base.name}". Pass { silenceWarning: true } to suppress, or switch to ExternalSecrets / SealedSecrets / Sops for production.`);
|
|
384
|
-
const resolved = yield* input.source.resolve.pipe(Effect.mapError((cause) => new RenderError({
|
|
391
|
+
const resolved = yield* input.base.source.resolve.pipe(Effect.mapError((cause) => new RenderError({
|
|
385
392
|
message: `NativeSecret(${input.base.namespace}/${input.base.name}): source failed for key "${cause.key}"`,
|
|
386
393
|
cause
|
|
387
394
|
})));
|
|
@@ -406,17 +413,10 @@ const NativeSecret = { backend: (opts) => {
|
|
|
406
413
|
return {
|
|
407
414
|
_tag: "NativeSecret",
|
|
408
415
|
requiresSource: true,
|
|
409
|
-
emit: (input) => {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
});
|
|
414
|
-
return _emit({
|
|
415
|
-
base: input,
|
|
416
|
-
opts: resolvedOpts,
|
|
417
|
-
source: input.source
|
|
418
|
-
});
|
|
419
|
-
}
|
|
416
|
+
emit: (input) => _emit({
|
|
417
|
+
base: input,
|
|
418
|
+
opts: resolvedOpts
|
|
419
|
+
})
|
|
420
420
|
};
|
|
421
421
|
} };
|
|
422
422
|
//#endregion
|
|
@@ -702,7 +702,7 @@ const Deployment = {
|
|
|
702
702
|
replicas: input.replicas,
|
|
703
703
|
selector: input.selector,
|
|
704
704
|
template: unsafeCoerce(input.template, "konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction"),
|
|
705
|
-
strategy:
|
|
705
|
+
strategy: input.strategy,
|
|
706
706
|
revisionHistoryLimit: input.revisionHistoryLimit,
|
|
707
707
|
progressDeadlineSeconds: input.progressDeadlineSeconds,
|
|
708
708
|
minReadySeconds: input.minReadySeconds
|
|
@@ -748,9 +748,9 @@ const StatefulSet = { make: (input) => {
|
|
|
748
748
|
selector: input.selector,
|
|
749
749
|
template: unsafeCoerce(input.template, "konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction"),
|
|
750
750
|
serviceName: input.serviceName,
|
|
751
|
-
volumeClaimTemplates: unsafeCoerce(input.volumeClaimTemplates, "
|
|
751
|
+
volumeClaimTemplates: unsafeCoerce(input.volumeClaimTemplates, "ReadonlyArray<K8sPersistentVolumeClaim> is structurally Array<PersistentVolumeClaim>; readonly-to-mutable variance is safe here"),
|
|
752
752
|
podManagementPolicy: input.podManagementPolicy,
|
|
753
|
-
updateStrategy:
|
|
753
|
+
updateStrategy: input.updateStrategy
|
|
754
754
|
}
|
|
755
755
|
};
|
|
756
756
|
return Manifest.make(() => Effect.succeed(resource));
|
|
@@ -829,20 +829,20 @@ const PodSet = { define: (input) => {
|
|
|
829
829
|
...input.netPol
|
|
830
830
|
}) : void 0;
|
|
831
831
|
return Manifest.make((ctx) => Effect.gen(function* () {
|
|
832
|
-
|
|
833
|
-
const s = service !== void 0 ? yield* service.render(ctx) : void 0;
|
|
834
|
-
const n = netPol !== void 0 ? yield* netPol.render(ctx) : void 0;
|
|
835
|
-
const reason = "tuple element types are statically known per branch; the array literal is widened by TS, the brand-free runtime shape matches the typed tuple";
|
|
836
|
-
if (s !== void 0 && n !== void 0) return unsafeCoerce([
|
|
837
|
-
d,
|
|
838
|
-
s,
|
|
839
|
-
n
|
|
840
|
-
], reason);
|
|
841
|
-
if (s !== void 0) return unsafeCoerce([d, s], reason);
|
|
842
|
-
if (n !== void 0) return unsafeCoerce([d, n], reason);
|
|
843
|
-
return unsafeCoerce([d], reason);
|
|
832
|
+
return _asPodSetOutput(yield* deployment.render(ctx), service !== void 0 ? yield* service.render(ctx) : void 0, netPol !== void 0 ? yield* netPol.render(ctx) : void 0);
|
|
844
833
|
}));
|
|
845
834
|
} };
|
|
835
|
+
const _asPodSetOutput = (d, s, n) => {
|
|
836
|
+
const reason = "PodSet.define: tuple shape is determined by which of service/netPol are present";
|
|
837
|
+
if (s !== void 0 && n !== void 0) return unsafeCoerce([
|
|
838
|
+
d,
|
|
839
|
+
s,
|
|
840
|
+
n
|
|
841
|
+
], reason);
|
|
842
|
+
if (s !== void 0) return unsafeCoerce([d, s], reason);
|
|
843
|
+
if (n !== void 0) return unsafeCoerce([d, n], reason);
|
|
844
|
+
return unsafeCoerce([d], reason);
|
|
845
|
+
};
|
|
846
846
|
//#endregion
|
|
847
847
|
//#region src/selector.ts
|
|
848
848
|
/**
|
|
@@ -869,14 +869,13 @@ const _reloaderAnnotations = (opt) => {
|
|
|
869
869
|
if (opt.configMaps && opt.configMaps.length > 0) out["configmap.reloader.stakater.com/reload"] = opt.configMaps.join(",");
|
|
870
870
|
return out;
|
|
871
871
|
};
|
|
872
|
-
const
|
|
873
|
-
const selectorLabels = { app: input.name };
|
|
872
|
+
const _webDeployment = ({ input, selectorLabels }) => {
|
|
874
873
|
const podLabels = {
|
|
875
874
|
...input.deployment.podLabels,
|
|
876
875
|
...selectorLabels
|
|
877
876
|
};
|
|
878
877
|
const reloaderAnns = _reloaderAnnotations(input.reloader);
|
|
879
|
-
|
|
878
|
+
return Deployment.make({
|
|
880
879
|
name: input.name,
|
|
881
880
|
namespace: input.namespace,
|
|
882
881
|
labels: {
|
|
@@ -902,33 +901,49 @@ const web = (input) => {
|
|
|
902
901
|
}
|
|
903
902
|
}
|
|
904
903
|
});
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
904
|
+
};
|
|
905
|
+
const _webService = ({ input, selectorLabels }) => Service.make({
|
|
906
|
+
name: input.name,
|
|
907
|
+
namespace: input.namespace,
|
|
908
|
+
labels: {
|
|
909
|
+
...selectorLabels,
|
|
910
|
+
...input.labels
|
|
911
|
+
},
|
|
912
|
+
annotations: input.annotations,
|
|
913
|
+
selector: selectorLabels,
|
|
914
|
+
type: input.service.type ?? "ClusterIP",
|
|
915
|
+
ports: unsafeCoerce(input.service.ports, "ServicePortSpec<Ports> structurally matches K8sServicePort; the PortName<Ports> brand on targetPort is a phantom whose runtime value is the underlying string")
|
|
916
|
+
});
|
|
917
|
+
const _webIngress = ({ ingress, input, selectorLabels }) => Ingress.make({
|
|
918
|
+
name: input.name,
|
|
919
|
+
namespace: input.namespace,
|
|
920
|
+
labels: {
|
|
921
|
+
...selectorLabels,
|
|
922
|
+
...input.labels
|
|
923
|
+
},
|
|
924
|
+
annotations: {
|
|
925
|
+
...input.annotations,
|
|
926
|
+
...ingress.annotations
|
|
927
|
+
},
|
|
928
|
+
ingressClassName: ingress.ingressClassName,
|
|
929
|
+
rules: ingress.rules,
|
|
930
|
+
tls: ingress.tls
|
|
931
|
+
});
|
|
932
|
+
const web = (input) => {
|
|
933
|
+
const selectorLabels = { app: input.name };
|
|
934
|
+
const deployment = _webDeployment({
|
|
935
|
+
input,
|
|
936
|
+
selectorLabels
|
|
937
|
+
});
|
|
938
|
+
const service = _webService({
|
|
939
|
+
input,
|
|
940
|
+
selectorLabels
|
|
916
941
|
});
|
|
917
942
|
if (input.ingress === void 0) return Manifest.make((ctx) => Effect.all([deployment.render(ctx), service.render(ctx)], { concurrency: "unbounded" }));
|
|
918
|
-
const ingress =
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
...selectorLabels,
|
|
923
|
-
...input.labels
|
|
924
|
-
},
|
|
925
|
-
annotations: {
|
|
926
|
-
...input.annotations,
|
|
927
|
-
...input.ingress.annotations
|
|
928
|
-
},
|
|
929
|
-
ingressClassName: input.ingress.ingressClassName,
|
|
930
|
-
rules: input.ingress.rules,
|
|
931
|
-
tls: input.ingress.tls
|
|
943
|
+
const ingress = _webIngress({
|
|
944
|
+
input,
|
|
945
|
+
selectorLabels,
|
|
946
|
+
ingress: input.ingress
|
|
932
947
|
});
|
|
933
948
|
return Manifest.make((ctx) => Effect.all([
|
|
934
949
|
deployment.render(ctx),
|
|
@@ -978,31 +993,17 @@ const cron = (input) => {
|
|
|
978
993
|
};
|
|
979
994
|
//#endregion
|
|
980
995
|
//#region src/index.ts
|
|
981
|
-
/**
|
|
982
|
-
* `Secret` value namespace — merges the env-contracts side (`define`)
|
|
983
|
-
* with the K8s side (`make`, `bind`, identity helpers). Importing
|
|
984
|
-
* `Secret` from `@konfig.ts/k8s` gives you the full surface:
|
|
985
|
-
*
|
|
986
|
-
* Secret.define({ name, namespace, env }) — env contract (from @konfig.ts/env)
|
|
987
|
-
* Secret.make({ name, namespace, stringData }) — K8s Secret manifest
|
|
988
|
-
* Secret.bind({ secret, backend, source }) — env-to-manifest binder
|
|
989
|
-
*/
|
|
990
996
|
const Secret = {
|
|
991
997
|
...Secret$1,
|
|
992
998
|
...Secret$2,
|
|
993
999
|
bind: bindSecret
|
|
994
1000
|
};
|
|
995
|
-
/**
|
|
996
|
-
* `Environment` value namespace — merges `define` (env-contracts) with
|
|
997
|
-
* `bind` + `runtime` (K8s). The same `Environment` symbol carries the
|
|
998
|
-
* declaration, the manifest binder, and the runtime decoder.
|
|
999
|
-
*/
|
|
1000
1001
|
const Environment = {
|
|
1001
1002
|
...Environment$1,
|
|
1002
1003
|
bind: bindEnvironment,
|
|
1003
1004
|
runtime
|
|
1004
1005
|
};
|
|
1005
1006
|
//#endregion
|
|
1006
|
-
export {
|
|
1007
|
+
export { ClusterRole, ClusterRoleBinding, ConfigMap, ConfigMapRef, Container, CronJob, Deployment, EnvVar, Environment, Ingress, Job, k8s_types_exports as K8s, Namespace, NativeSecret, NetworkPolicy, PersistentVolume, PersistentVolumeClaim, Pod, PodSet, Port, PvcRef, Role, RoleBinding, Secret, SecretRef, Selector, Service, ServiceAccount, ServiceAccountRef, StatefulSet, Volume, workloadHelpers_exports as Workload, hashSecretValues };
|
|
1007
1008
|
|
|
1008
1009
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["ServiceAccountRefValue","ConfigMapRefValue","Secret","SecretRefValue","SecretRefValue","L","M","_SecretContract","_SecretIdentity","_EnvironmentContract","envRuntime"],"sources":["../src/.generated/k8s-types/index.ts","../src/container.ts","../src/ports.ts","../src/env.ts","../src/refs.ts","../src/identity.ts","../src/secretBind.ts","../src/environmentBind.ts","../src/backend.ts","../src/nativeSecret.ts","../src/network.ts","../src/podHash.ts","../src/policy.ts","../src/volume.ts","../src/workload.ts","../src/podSet.ts","../src/selector.ts","../src/workloadHelpers.ts","../src/index.ts"],"sourcesContent":["// Pinned re-export of Kubernetes API types. The directory name is\n// historical — we don't regenerate from OpenAPI; we re-export the\n// pinned `kubernetes-types` package, which is itself a stable mirror\n// of the upstream Kubernetes Go types.\n//\n// Version policy: `kubernetes-types` is pinned to an exact patch\n// version in packages/k8s/package.json — no caret. The minor\n// (currently 1.30) tracks the cluster minor we test against. Bumping\n// is intentional: read upstream release notes, run `bun run check &&\n// bun run test`, and update CHANGELOG.\n//\n// Each export here is the K8s API type as-is. konfig wrappers (e.g.\n// `ContainerInput` in container.ts) accept a wider, branded shape\n// and lower into these types when emitting manifests.\n\nexport type { Deployment, DeploymentSpec, StatefulSet, StatefulSetSpec } from \"kubernetes-types/apps/v1\"\n\nexport type { CronJob, Job, JobSpec } from \"kubernetes-types/batch/v1\"\nexport type {\n ConfigMap,\n Container,\n ContainerPort,\n EnvVar,\n EnvVarSource,\n LocalObjectReference,\n Namespace,\n PersistentVolume,\n PersistentVolumeClaim,\n PodSpec,\n PodTemplateSpec,\n Secret,\n Service,\n ServiceAccount,\n ServicePort,\n Volume,\n VolumeMount\n} from \"kubernetes-types/core/v1\"\nexport type { ObjectMeta } from \"kubernetes-types/meta/v1\"\nexport type { Ingress, IngressRule, IngressSpec, IngressTLS, NetworkPolicy } from \"kubernetes-types/networking/v1\"\nexport type { ClusterRole, ClusterRoleBinding, Role, RoleBinding } from \"kubernetes-types/rbac/v1\"\n","import type { BuiltImageRef, SecretRef, ServiceAccountRef } from \"@konfig.ts/core\"\nimport { unsafeCoerce } from \"@konfig.ts/core\"\nimport type { Container as K8sContainer, PodSpec as K8sPodSpec } from \"./.generated/k8s-types\"\nimport type { EnvVar } from \"./env\"\nimport type { ContainerPort, NamesOf, ProbeTarget } from \"./ports\"\nimport type { Volume, VolumeMount, VolumeNamesOf } from \"./volume\"\n\n/**\n * Container input — extends the full K8s Container API. Konfig's\n * branded helpers (`EnvVar.value`, `EnvVar.fromSecret`,\n * `EnvVar.fromConfigMap`) produce `EnvVar` instances whose runtime\n * shape matches `K8sEnvVar`; the override\n * here narrows the field to readonly + the branded helper output so\n * `secretKeyRef.name` carries its `SecretRef<N>` brand at construction\n * time.\n *\n * `image` is overridden as required (K8s lets it be optional for\n * higher-level controllers that default it; konfig wants every\n * container to have an explicit image).\n *\n * `ports[i].name` accepts the branded `PortName<string>` from `Port.make(...)`\n * as well as a raw string; the typed builder `Container` is the\n * link that captures the literal name union for cross-reference checks.\n */\nexport interface ContainerInput extends\n Omit<\n K8sContainer,\n | \"env\"\n | \"image\"\n | \"ports\"\n | \"readinessProbe\"\n | \"livenessProbe\"\n | \"startupProbe\"\n | \"volumeMounts\"\n >\n{\n /**\n * Container image. Accepts a raw string (escape hatch for vendor\n * images: `ghcr.io/bitnami/postgresql:16.0.0`) or a `BuiltImageRef<App>`\n * produced by `Dep.builtImageRef` / `Dep.provideImage`. The branded\n * path ties the workload into the dep graph — a workload referencing\n * an image whose build module isn't in the composition fails at\n * `AppOfApps.entrypoint`.\n */\n readonly image: string | BuiltImageRef<string>\n readonly env?: ReadonlyArray<EnvVar>\n readonly ports?: ReadonlyArray<\n ContainerPort | {\n readonly containerPort: number\n readonly name?: string\n readonly protocol?: \"TCP\" | \"UDP\" | \"SCTP\"\n }\n >\n /**\n * Probes accept either the upstream K8s shape or konfig's branded\n * `ProbeTarget<string>` (from `Container`). The two are\n * structurally close — the union lets a `ContainerSpec` flow\n * through `Workload.web`'s containers slot without a cast.\n */\n readonly readinessProbe?: K8sContainer[\"readinessProbe\"] | ProbeTarget<string>\n readonly livenessProbe?: K8sContainer[\"livenessProbe\"] | ProbeTarget<string>\n readonly startupProbe?: K8sContainer[\"startupProbe\"] | ProbeTarget<string>\n /**\n * Volume mounts accept the upstream K8s shape or konfig's branded\n * `VolumeMount<string>` (from `Container` / `mountRef`). Same\n * rationale as the probe widening above.\n */\n readonly volumeMounts?:\n | K8sContainer[\"volumeMounts\"]\n | ReadonlyArray<VolumeMount<string>>\n}\n\n/**\n * Strongly-typed container builder. Captures the union of named ports\n * declared via `port({ name, containerPort })` as a phantom type\n * parameter, then constrains every probe's `port` field to that union.\n *\n * Pair with `Service.fromContainer({ forContainer })` in `network.ts`\n * to link a Service's `targetPort` to the same union — a typo or\n * undeclared port name is a compile error.\n */\nexport interface ContainerSpec<Ports extends string = string, Mounts extends string = string> extends\n Omit<\n ContainerInput,\n \"ports\" | \"readinessProbe\" | \"livenessProbe\" | \"startupProbe\" | \"volumeMounts\"\n >\n{\n readonly name: string\n readonly image: string\n readonly ports: ReadonlyArray<ContainerPort<Ports>>\n readonly readinessProbe?: ProbeTarget<Ports>\n readonly livenessProbe?: ProbeTarget<Ports>\n readonly startupProbe?: ProbeTarget<Ports>\n readonly volumeMounts?: ReadonlyArray<VolumeMount<Mounts>>\n readonly __portNames?: Ports\n readonly __mountNames?: Mounts\n}\n\nexport interface DefineContainerInput<\n Ports extends ReadonlyArray<ContainerPort<string>>,\n Mounts extends ReadonlyArray<VolumeMount<string>>,\n Envs extends ReadonlyArray<EnvVar<string>>\n> extends\n Omit<\n ContainerInput,\n \"ports\" | \"readinessProbe\" | \"livenessProbe\" | \"startupProbe\" | \"volumeMounts\" | \"env\"\n >\n{\n readonly name: string\n readonly image: string\n readonly ports: Ports\n readonly readinessProbe?: ProbeTarget<NamesOf<Ports>>\n readonly livenessProbe?: ProbeTarget<NamesOf<Ports>>\n readonly startupProbe?: ProbeTarget<NamesOf<Ports>>\n readonly volumeMounts?: Mounts\n readonly env?: Envs & EnvDupCheck<Envs>\n}\n\ntype MountNamesOf<M extends ReadonlyArray<VolumeMount<string>>> = {\n readonly [I in keyof M]: M[I] extends VolumeMount<infer N> ? N : never\n}[number]\n\ntype _EnvNameOf<X> = X extends EnvVar<infer N> ? N : never\n\n/**\n * Union of any literal env-var names that appear more than once in `Envs`.\n * Computes the intersection of pairwise names — if `Envs[I]` and `Envs[J]`\n * share a literal name (i ≠ j), that name leaks into the union. Empty\n * when every name is unique.\n */\ntype DuplicateEnvNames<Envs extends ReadonlyArray<EnvVar<string>>> = {\n [I in keyof Envs]: {\n [J in keyof Envs]: J extends I ? never\n : _EnvNameOf<Envs[I]> & _EnvNameOf<Envs[J]> extends never ? never\n : _EnvNameOf<Envs[I]> & _EnvNameOf<Envs[J]>\n }[number]\n}[number]\n\n/**\n * Empty (`unknown`) when `Envs` has no duplicate names; otherwise an\n * inline object type whose required `_konfig_duplicate_env_names`\n * property carries a template-literal hint sentence. Intersected with\n * the `env` slot, an unmet property surfaces the sentence inline in the\n * TS error — far more discoverable than a runtime \"last-wins\" surprise.\n */\ntype EnvDupCheck<Envs extends ReadonlyArray<EnvVar<string>>> = [DuplicateEnvNames<Envs>] extends [never] ? unknown\n : {\n readonly _konfig_duplicate_env_names: `Duplicate env name(s): \"${DuplicateEnvNames<\n Envs\n >}\". K8s silently last-wins; rename one of the colliding entries or remove the manual valueEnv that shadows another producer.`\n }\n\n/**\n * `Container` value namespace.\n *\n * const apiContainer = Container.define({\n * name: \"api\",\n * image: apiImage,\n * ports: [Port.make({ name: \"http\", containerPort: 8080 })],\n * readinessProbe: { httpGet: { port: Port.ref(\"http\") } },\n * env: [...],\n * });\n *\n * `Container.define` captures the union of named ports (from\n * `Port.make`) as `Ports`, the union of mounted volume names (from\n * `Volume.mountRef`) as `Mounts`, and validates that the `env` list\n * has no duplicate env-var names. The first two phantoms travel on\n * `ContainerSpec`; `Pod.define` checks the container's Mounts against\n * the pod's declared volume names.\n *\n * Duplicate env names are caught at the call site via a template-literal\n * error message — see `EnvDupCheck`. With no volumeMounts and no env,\n * all phantoms collapse to `never` so the container slots into any pod.\n */\nexport const Container = {\n define: <\n const Ports extends ReadonlyArray<ContainerPort<string>>,\n const Mounts extends ReadonlyArray<VolumeMount<string>> = readonly [],\n const Envs extends ReadonlyArray<EnvVar<string>> = readonly []\n >(\n input: DefineContainerInput<Ports, Mounts, Envs>\n ): ContainerSpec<NamesOf<Ports>, MountNamesOf<Mounts>> => {\n type P = NamesOf<Ports>\n type M = MountNamesOf<Mounts>\n const out: ContainerSpec<P, M> = {\n ...input,\n ports: unsafeCoerce<ReadonlyArray<ContainerPort<P>>>(\n input.ports,\n \"Ports tuple's element brands are the same PortName<N>; widening Ports → readonly ContainerPort<P>[] only changes the static shape, not the runtime values\"\n ),\n readinessProbe: input.readinessProbe,\n livenessProbe: input.livenessProbe,\n startupProbe: input.startupProbe,\n volumeMounts: unsafeCoerce<ReadonlyArray<VolumeMount<M>> | undefined>(\n input.volumeMounts,\n \"Mounts tuple's element brands are the same VolumeMount<N>; widening Mounts → readonly VolumeMount<M>[] preserves runtime shape\"\n ),\n env: unsafeCoerce<ReadonlyArray<EnvVar<string>> | undefined>(\n input.env,\n \"EnvDupCheck<Envs> intersection vanishes at runtime; the runtime value is the original EnvVar[]\"\n )\n }\n return out\n }\n}\n\n/**\n * `Pod.define` input. The pod declares a tuple of `Volume`s and lists\n * containers whose `Mounts` phantom is checked against the declared\n * volume names via `NoInfer`. A container referencing an undeclared\n * volume — or a typo — fails at the call site rather than at pod-startup\n * time with \"container references volume not found.\"\n */\nexport interface DefinePodInput<V extends ReadonlyArray<Volume<string>>> {\n readonly volumes: V\n readonly containers: ReadonlyArray<ContainerSpec<string, NoInfer<VolumeNamesOf<V>>>>\n readonly initContainers?: ReadonlyArray<ContainerSpec<string, NoInfer<VolumeNamesOf<V>>>>\n}\n\nexport interface DefinedPod<MountNames extends string> {\n readonly volumes: ReadonlyArray<Volume<MountNames>>\n readonly containers: ReadonlyArray<ContainerSpec<string, MountNames>>\n readonly initContainers?: ReadonlyArray<ContainerSpec<string, MountNames>>\n}\n\n/**\n * Pod spec input — extends K8s PodSpec but tightens the fields where\n * konfig adds brand checking: `imagePullSecrets`, `serviceAccountName`,\n * and `volumes` (the helpers in `volume.ts` produce konfig `Volume`\n * objects that lower to K8s `Volume`).\n */\nexport interface PodSpecInput extends\n Omit<\n K8sPodSpec,\n | \"containers\"\n | \"initContainers\"\n | \"volumes\"\n | \"imagePullSecrets\"\n | \"serviceAccountName\"\n >\n{\n readonly containers: ReadonlyArray<ContainerInput>\n readonly initContainers?: ReadonlyArray<ContainerInput>\n readonly volumes?: ReadonlyArray<Volume>\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n readonly serviceAccountName?: ServiceAccountRef<string> | string\n}\n\n/**\n * `Pod` value namespace.\n *\n * const pod = Pod.define({\n * volumes: [Volume.empty({ name: \"config\" })],\n * containers: [Container.define({ ..., volumeMounts: [...] })],\n * });\n *\n * imagePullSecrets: [Pod.imagePullSecret(ghcrRef)],\n *\n * - `Pod.define(input)` ties container `volumeMounts[i].name` to the\n * pod's declared volume names via `NoInfer`.\n * - `Pod.imagePullSecret(ref)` returns the `{ name: SecretRef }` entry\n * consumed by Deployment / StatefulSet / Job / CronJob workloads.\n */\nexport const Pod = {\n define: <const V extends ReadonlyArray<Volume<string>>>(\n input: DefinePodInput<V>\n ): DefinedPod<VolumeNamesOf<V>> => ({\n volumes: unsafeCoerce<ReadonlyArray<Volume<VolumeNamesOf<V>>>>(\n input.volumes,\n \"V tuple's elements are Volume<N>; widening V → readonly Volume<VolumeNamesOf<V>>[] is a structural relaxation, runtime value unchanged\"\n ),\n containers: input.containers,\n initContainers: input.initContainers\n }),\n imagePullSecret: (ref: SecretRef<string>): { readonly name: SecretRef<string> } => ({\n name: ref\n })\n}\n","import { brand } from \"@konfig.ts/core\"\n\n/**\n * Branded port name — a string carrying the literal `N` in its type.\n * Constructed by `Port.make({ name, containerPort })` and `Port.ref(name)`.\n * The brand lets probes and Service `targetPort` constrain their\n * `port` field to a member of the container's declared port-name union\n * rather than `string`.\n */\ndeclare const PortNameBrand: unique symbol\nexport type PortName<N extends string> = string & {\n readonly [PortNameBrand]: N\n}\n\nconst _portName = <const N extends string>(name: N): PortName<N> => brand<PortName<N>>(name)\n\nexport type ContainerProtocol = \"TCP\" | \"UDP\" | \"SCTP\"\n\nexport interface ContainerPort<N extends string = string> {\n readonly containerPort: number\n readonly name?: PortName<N>\n readonly protocol?: ContainerProtocol\n readonly hostPort?: number\n readonly hostIP?: string\n}\n\nexport interface PortInput<N extends string> {\n readonly name: N\n readonly containerPort: number\n readonly protocol?: ContainerProtocol\n readonly hostPort?: number\n readonly hostIP?: string\n}\n\n/**\n * `Port` value namespace.\n *\n * ports: [Port.make({ name: \"http\", containerPort: 8080 })],\n * readinessProbe: { httpGet: { port: Port.ref(\"http\") } },\n *\n * - `Port.make(input)` constructs a named container port; the literal\n * `name` is captured in the returned `ContainerPort<N>` brand so\n * `Container` can infer the port-name union and constrain\n * cross-references (probes, Service.targetPort).\n * - `Port.ref(name)` returns the brand alone, for probe targets and\n * `targetPort` references that need to name an existing declared port.\n */\nexport const Port = {\n make: <const N extends string>(input: PortInput<N>): ContainerPort<N> => ({\n containerPort: input.containerPort,\n name: _portName(input.name),\n protocol: input.protocol,\n hostPort: input.hostPort,\n hostIP: input.hostIP\n }),\n ref: <const N extends string>(name: N): PortName<N> => _portName(name)\n}\n\nexport interface HttpHeader {\n readonly name: string\n readonly value: string\n}\n\nexport interface HttpGetAction<Ports extends string> {\n readonly path?: string\n readonly port: number | PortName<Ports>\n readonly host?: string\n readonly scheme?: \"HTTP\" | \"HTTPS\"\n readonly httpHeaders?: ReadonlyArray<HttpHeader>\n}\n\nexport interface TcpSocketAction<Ports extends string> {\n readonly port: number | PortName<Ports>\n readonly host?: string\n}\n\nexport interface GrpcAction<Ports extends string> {\n readonly port: number | PortName<Ports>\n readonly service?: string\n}\n\nexport interface ExecAction {\n readonly command: ReadonlyArray<string>\n}\n\n/**\n * Probe target — `port` references on httpGet/tcpSocket/grpc are\n * constrained to `Ports`, the union of names declared on the owning\n * container. A bare number is always accepted; only the named variant\n * is checked.\n */\nexport interface ProbeTarget<Ports extends string> {\n readonly httpGet?: HttpGetAction<Ports>\n readonly tcpSocket?: TcpSocketAction<Ports>\n readonly grpc?: GrpcAction<Ports>\n readonly exec?: ExecAction\n readonly initialDelaySeconds?: number\n readonly periodSeconds?: number\n readonly timeoutSeconds?: number\n readonly successThreshold?: number\n readonly failureThreshold?: number\n readonly terminationGracePeriodSeconds?: number\n}\n\nexport type NamesOf<P extends ReadonlyArray<unknown>> = {\n readonly [K in keyof P]: P[K] extends ContainerPort<infer N> ? N : never\n}[number]\n\n/**\n * Service-port input bound to a container's port-name union. `targetPort`\n * accepts a bare number or a `PortName<Ports>`. The `Ports` parameter is\n * locked by `forContainer` on `Service.fromContainer`; use `Port.ref(name)`\n * to reference declared ports.\n */\nexport interface ServicePortSpec<Ports extends string> {\n readonly name?: string\n readonly port: number\n readonly targetPort: number | PortName<Ports>\n readonly protocol?: ContainerProtocol\n readonly appProtocol?: string\n readonly nodePort?: number\n}\n","import type { ConfigMapRef, SecretRef } from \"@konfig.ts/core\"\n\nexport interface EnvVarSource {\n readonly secretKeyRef?: {\n readonly name: string\n readonly key: string\n readonly optional?: boolean\n }\n readonly configMapKeyRef?: {\n readonly name: string\n readonly key: string\n readonly optional?: boolean\n }\n readonly fieldRef?: { readonly fieldPath: string; readonly apiVersion?: string }\n readonly resourceFieldRef?: { readonly containerName?: string; readonly resource: string }\n}\n\n/**\n * Container env-var entry. The phantom `N` records the literal env-var\n * name at the type level so `Container` can detect duplicates\n * across the entry list. The default `N = string` preserves loose-typed\n * call sites.\n */\nexport interface EnvVarShape<N extends string = string> {\n readonly name: N\n readonly value?: string\n readonly valueFrom?: EnvVarSource\n}\n\nexport interface ValueEnvInput<N extends string> {\n readonly name: N\n readonly value: string\n}\n\nexport interface SecretEnvInput<EnvName extends string, N extends string, K extends string> {\n readonly name: EnvName\n readonly ref: SecretRef<N, K>\n /**\n * Constrained to the keys carried by `ref`. `NoInfer` locks `K` to\n * whatever the ref declares, so the typo `key: \"passowrd\"` fails at\n * compile time when the ref's K is `\"url\" | \"username\" | \"password\"`.\n * Refs constructed with the default `K = string` accept any string.\n */\n readonly key: NoInfer<K>\n readonly optional?: boolean\n}\n\nexport interface SecretEnvForPodInput<\n EnvName extends string,\n N extends string,\n K extends string,\n Ns extends string\n> {\n readonly name: EnvName\n /**\n * Ref whose namespace slot must match `podNamespace`. Pass refs that\n * came from `Secret.make({ namespace })` in the same namespace as\n * the consuming pod. For legitimate cross-namespace cases, widen\n * via `SecretRef.unsafeReNamespace(ref)` first.\n */\n readonly ref: SecretRef<N, K, NoInfer<Ns>>\n readonly key: NoInfer<K>\n readonly podNamespace: Ns\n readonly optional?: boolean\n}\n\nexport interface ConfigMapEnvInput<EnvName extends string, N extends string, K extends string> {\n readonly name: EnvName\n readonly ref: ConfigMapRef<N, K>\n /**\n * Constrained to the keys carried by `ref`. `NoInfer` locks `K` to\n * whatever the ref declares — typos like `key: \"passwrod\"` fail at\n * compile time when the ref's K is `\"HOST\" | \"PORT\" | \"LOG_LEVEL\"`.\n * Refs constructed with the default `K = string` accept any string.\n */\n readonly key: NoInfer<K>\n readonly optional?: boolean\n}\n\nexport interface RawEnvInput<N extends string> {\n readonly name: N\n readonly value?: string\n readonly valueFrom?: EnvVarSource\n}\n\n/**\n * `EnvVar` value namespace.\n *\n * env: [\n * EnvVar.value({ name: \"PORT\", value: \"8080\" }),\n * EnvVar.fromSecret({ name: \"DB_URL\", ref: dbCreds.ref, key: \"url\" }),\n * EnvVar.fromSecretForPod({\n * name: \"DB_URL_PRIMARY\", ref: dbCreds.ref, key: \"url\",\n * podNamespace: \"app\",\n * }),\n * EnvVar.fromConfigMap({ name: \"NEW_UI\", ref: flags.ref, key: \"NEW_UI\" }),\n * EnvVar.raw({ name: \"POD_NAME\", valueFrom: { fieldRef: ... } }),\n * ]\n *\n * Each constructor captures the literal env-var name (`N`) so\n * `Container` can detect duplicate entries across the env list.\n */\nexport const EnvVar = {\n value: <const N extends string>(input: ValueEnvInput<N>): EnvVar<N> => ({\n name: input.name,\n value: input.value\n }),\n fromSecret: <const EnvName extends string, N extends string, K extends string = string>(\n input: SecretEnvInput<EnvName, N, K>\n ): EnvVar<EnvName> => ({\n name: input.name,\n valueFrom: {\n secretKeyRef: { name: input.ref, key: input.key, optional: input.optional }\n }\n }),\n /**\n * Namespace-checked variant. The ref's namespace slot (`Ns`) must\n * match `podNamespace`. Catches \"pod in namespace A references a\n * Secret in namespace B\" at compile time — kube-apiserver only\n * resolves `valueFrom.secretKeyRef` against the pod's own namespace,\n * so cross-namespace refs are runtime errors.\n */\n fromSecretForPod: <\n const EnvName extends string,\n N extends string,\n K extends string,\n const Ns extends string\n >(\n input: SecretEnvForPodInput<EnvName, N, K, Ns>\n ): EnvVar<EnvName> => ({\n name: input.name,\n valueFrom: {\n secretKeyRef: { name: input.ref, key: input.key, optional: input.optional }\n }\n }),\n fromConfigMap: <const EnvName extends string, N extends string, K extends string = string>(\n input: ConfigMapEnvInput<EnvName, N, K>\n ): EnvVar<EnvName> => ({\n name: input.name,\n valueFrom: {\n configMapKeyRef: { name: input.ref, key: input.key, optional: input.optional }\n }\n }),\n raw: <const N extends string>(input: RawEnvInput<N>): EnvVar<N> => input\n}\n\n// Alias the shape interface as the user-facing `EnvVar<N>` type. The\n// namespace `EnvVar` (value) and the type `EnvVar<N>` share a name —\n// TypeScript merges them.\nexport type EnvVar<N extends string = string> = EnvVarShape<N>\n","import {\n brand,\n type ConfigMapRef as CMRef,\n type PvcRef as PRef,\n type SecretRef as SRef,\n type ServiceAccountRef as SARef\n} from \"@konfig.ts/core\"\n\nexport type SecretRef<\n N extends string = string,\n K extends string = string,\n Ns extends string = string\n> = SRef<N, K, Ns>\nexport type ConfigMapRef<N extends string = string, K extends string = string> = CMRef<N, K>\nexport type ServiceAccountRef<N extends string = string> = SARef<N>\nexport type PvcRef<N extends string = string> = PRef<N>\nexport type { ConfigMapRefKeys, ConfigMapRefName, PvcRefName, SecretRefKeys, SecretRefName } from \"@konfig.ts/core\"\nexport type { SecretRefNamespace } from \"@konfig.ts/core\"\n\nexport const SecretRef = {\n of: <N extends string, K extends string = string, Ns extends string = string>(\n name: N\n ): SecretRef<N, K, Ns> => brand<SecretRef<N, K, Ns>>(name),\n /**\n * Escape hatch — widen a typed ref's namespace slot to `any`, making\n * it usable across any pod context. Use sparingly (legitimate\n * cross-namespace cases: ExternalSecret reflection, in-cluster\n * shared infra). The cast is grep-able so PR reviewers see opt-ins.\n */\n // oxlint-disable-next-line app/no-type-assertion\n unsafeReNamespace: <N extends string, K extends string>(\n // oxlint-disable-next-line app/no-type-assertion\n ref: SecretRef<N, K, any>\n // oxlint-disable-next-line app/no-type-assertion\n ): SecretRef<N, K, any> => ref\n}\n\nexport const ConfigMapRef = {\n of: <N extends string, K extends string = string>(name: N): ConfigMapRef<N, K> => brand<ConfigMapRef<N, K>>(name)\n}\n\nexport const ServiceAccountRef = {\n of: <N extends string>(name: N): ServiceAccountRef<N> => brand<ServiceAccountRef<N>>(name)\n}\n\nexport const PvcRef = {\n of: <N extends string>(name: N): PvcRef<N> => brand<PvcRef<N>>(name)\n}\n","import type { ConfigMapRef, SecretRef, ServiceAccountRef } from \"@konfig.ts/core\"\nimport { Manifest } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n ConfigMap as K8sConfigMap,\n Namespace as K8sNamespace,\n Secret as K8sSecret,\n ServiceAccount as K8sServiceAccount\n} from \"./.generated/k8s-types\"\nimport {\n ConfigMapRef as ConfigMapRefValue,\n SecretRef as SecretRefValue,\n ServiceAccountRef as ServiceAccountRefValue\n} from \"./refs\"\n\ntype CommonMeta = {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\nexport interface NamespaceInput<N extends string> extends CommonMeta {\n readonly name: N\n}\n\nexport interface NamespaceManifest<N extends string> extends Manifest.Manifest<K8sNamespace> {\n readonly ref: N\n}\n\nexport const Namespace = {\n make: <N extends string>(input: NamespaceInput<N>): NamespaceManifest<N> => {\n const resource: K8sNamespace = {\n apiVersion: \"v1\",\n kind: \"Namespace\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n }\n }\n const m = Manifest.make<K8sNamespace>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: input.name })\n }\n}\n\nexport interface ServiceAccountInput<N extends string> extends CommonMeta {\n readonly name: N\n readonly namespace: string\n readonly automountServiceAccountToken?: boolean\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n}\n\nexport interface ServiceAccountManifest<N extends string> extends Manifest.Manifest<K8sServiceAccount> {\n readonly ref: ServiceAccountRef<N>\n}\n\nexport const ServiceAccount = {\n make: <N extends string>(input: ServiceAccountInput<N>): ServiceAccountManifest<N> => {\n const resource: K8sServiceAccount = {\n apiVersion: \"v1\",\n kind: \"ServiceAccount\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n automountServiceAccountToken: input.automountServiceAccountToken,\n imagePullSecrets: input.imagePullSecrets?.map((s) => ({ name: s.name }))\n }\n const m = Manifest.make<K8sServiceAccount>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: ServiceAccountRefValue.of(input.name) })\n }\n}\n\nexport interface ConfigMapInput<N extends string, K extends string = string> extends CommonMeta {\n readonly name: N\n readonly namespace: string\n readonly data?: Readonly<Record<K, string>>\n readonly binaryData?: Readonly<Record<K, string>>\n readonly immutable?: boolean\n}\n\nexport interface ConfigMapManifest<N extends string, K extends string = string>\n extends Manifest.Manifest<K8sConfigMap>\n{\n readonly ref: ConfigMapRef<N, K>\n}\n\nexport const ConfigMap = {\n make: <const N extends string, const K extends string = string>(\n input: ConfigMapInput<N, K>\n ): ConfigMapManifest<N, K> => {\n const resource: K8sConfigMap = {\n apiVersion: \"v1\",\n kind: \"ConfigMap\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n data: input.data,\n binaryData: input.binaryData,\n immutable: input.immutable\n }\n const m = Manifest.make<K8sConfigMap>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: ConfigMapRefValue.of<N, K>(input.name) })\n }\n}\n\nexport interface SecretInput<\n N extends string,\n Ns extends string = string,\n K extends string = string\n> extends CommonMeta {\n readonly name: N\n readonly namespace: Ns\n readonly type?: string\n readonly data?: Readonly<Record<K, string>>\n readonly stringData?: Readonly<Record<K, string>>\n readonly immutable?: boolean\n}\n\nexport interface SecretManifest<\n N extends string,\n Ns extends string = string,\n K extends string = string\n> extends Manifest.Manifest<K8sSecret> {\n readonly ref: SecretRef<N, K, Ns>\n}\n\nexport const Secret = {\n make: <\n const N extends string,\n const Ns extends string = string,\n const K extends string = string\n >(\n input: SecretInput<N, Ns, K>\n ): SecretManifest<N, Ns, K> => {\n const resource: K8sSecret = {\n apiVersion: \"v1\",\n kind: \"Secret\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n type: input.type,\n data: input.data,\n stringData: input.stringData,\n immutable: input.immutable\n }\n const m = Manifest.make<K8sSecret>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: SecretRefValue.of<N, K, Ns>(input.name) })\n }\n}\n","import { Dep, type Manifest, RenderError, type SecretRef, unsafeCoerce } from \"@konfig.ts/core\"\nimport type { SecretEntry, SecretSource } from \"@konfig.ts/env\"\nimport { type Context, Effect, type Layer, Layer as L } from \"effect\"\nimport type { SecretBackend } from \"./backend\"\nimport { EnvVar } from \"./env\"\nimport { SecretRef as SecretRefValue } from \"./refs\"\n\nexport interface DeclaredSecret<N extends string, K extends string, Ns extends string = string> {\n readonly ref: SecretRef<N, K, Ns>\n readonly name: N\n readonly namespace: Ns\n readonly keys: ReadonlyArray<K>\n readonly envVars: ReadonlyArray<EnvVar>\n readonly manifest?: Manifest.Manifest<unknown>\n readonly refLayer: Layer.Layer<Dep.Provide<\"Secret\", N>>\n // values + layer present iff a source was supplied at bind time.\n readonly values?: Context.Service<\n Dep.Need<\"SecretValues\", N>,\n Dep.SecretValuesRecord<K>\n >\n readonly layer?: Layer.Layer<\n Dep.Provide<\"SecretValues\", N>,\n RenderError,\n Manifest.RenderServices\n >\n}\n\nexport interface BindSecretInput<\n N extends string,\n K extends string,\n E extends Readonly<Record<K, string>>,\n Ns extends string = string\n> {\n readonly secret: SecretEntry<N, K, E>\n readonly backend?: SecretBackend<N, K>\n readonly source?: SecretSource<K, Manifest.RenderServices>\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n /**\n * Override the contract's baked-in `namespace` for this bind. Useful\n * when the same `Secret` declaration is consumed across multiple\n * k8s namespaces (e.g. prod / staging / local of the same workload)\n * — the runtime read is namespace-independent, but each binding emits\n * its manifest into a different namespace.\n *\n * When passed as a string literal (via `Environment.bind`'s\n * `const namespace`), the literal flows into the ref's brand so\n * `secretEnvForPod` can enforce cross-namespace coherence.\n */\n readonly namespace?: Ns\n}\n\nexport const bindSecret = <\n N extends string,\n K extends string,\n E extends Readonly<Record<K, string>>,\n const Ns extends string = string\n>(\n input: BindSecretInput<N, K, E, Ns>\n): DeclaredSecret<N, K, Ns> => {\n const { secret } = input\n const namespace = unsafeCoerce<Ns>(\n input.namespace ?? secret.namespace,\n \"Ns defaults to `string`; the override (if present) is `Ns`, the secret's own namespace is `string` — runtime value either way is a string\"\n )\n const ref = SecretRefValue.of<N, K, Ns>(secret.name)\n const envVars: EnvVar[] = secret.keys.map((key: K) => EnvVar.fromSecret({ name: secret.env[key], ref, key }))\n const refLayer = Dep.provideSecret(secret.name)\n\n const manifest = input.backend === undefined\n ? undefined\n : input.backend.emit({\n name: secret.name,\n namespace,\n keys: secret.keys,\n labels: input.labels,\n annotations: input.annotations,\n source: input.source\n })\n\n const out: DeclaredSecret<N, K, Ns> = {\n ref,\n name: secret.name,\n namespace,\n keys: secret.keys,\n envVars,\n manifest,\n refLayer\n }\n\n if (input.source === undefined) return out\n\n const source = input.source\n const valuesTag = Dep.SecretValues<N, K>(secret.name)\n const layer = L.effect(\n valuesTag,\n source.resolve.pipe(\n Effect.mapError(\n (cause) =>\n new RenderError({\n message: `SecretValues(${namespace}/${secret.name}): source failed for key \"${cause.key}\"`,\n cause\n })\n )\n )\n )\n return { ...out, values: valuesTag, layer }\n}\n","import { type Manifest, type RenderError, unsafeCoerce } from \"@konfig.ts/core\"\nimport type {\n AnyEnvironment,\n DownwardEntry,\n Environment,\n EnvMember,\n LiteralEntry,\n SecretEntry,\n SecretSource\n} from \"@konfig.ts/env\"\nimport { Layer, Match } from \"effect\"\nimport type { SecretBackend } from \"./backend\"\nimport type { EnvVar } from \"./env\"\nimport { bindSecret, type DeclaredSecret } from \"./secretBind\"\n\nexport interface DeclaredLiteral<EnvName extends string, T> {\n readonly envName: EnvName\n readonly value: T\n readonly envVar: EnvVar\n}\n\nexport interface DeclaredDownward<EnvName extends string> {\n readonly envName: EnvName\n readonly fieldPath: string\n readonly envVar: EnvVar\n}\n\n/**\n * Per-member declared shape produced by `Environment.bind`. Mirrors the\n * structure of the bundle: secrets give `DeclaredSecret`, literals\n * `DeclaredLiteral`, downwards `DeclaredDownward`, and nested\n * `Environment` members give a `members` sub-record with the same\n * recursive shape.\n */\nexport type DeclaredMember<\n A extends EnvMember,\n Ns extends string = string\n> = A extends SecretEntry<infer N, infer K, infer _E> ? [N, K] extends [string, string] ? DeclaredSecret<N, K, Ns>\n : never\n : A extends LiteralEntry<infer EnvName, infer T> ? [EnvName] extends [string] ? DeclaredLiteral<EnvName, T>\n : never\n : A extends DownwardEntry<infer EnvName> ? [EnvName] extends [string] ? DeclaredDownward<EnvName>\n : never\n : A extends Environment<infer SubM> ? { readonly [K in keyof SubM]: DeclaredMember<SubM[K], Ns> }\n : never\n\nexport interface DeclaredEnvironment<\n M extends Readonly<Record<string, EnvMember>>,\n Ns extends string = string\n> {\n readonly envVars: ReadonlyArray<EnvVar>\n readonly manifests: ReadonlyArray<Manifest.Manifest<unknown>>\n readonly members: { readonly [K in keyof M]: DeclaredMember<M[K], Ns> }\n // merged values layer over every secret member with a source.\n readonly valuesLayer: Layer.Layer<unknown, RenderError, Manifest.RenderServices>\n}\n\ninterface _SecretMemberOptionsBase {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\ninterface _SecretMemberBackendRequiresSource<N extends string, K extends string> extends _SecretMemberOptionsBase {\n readonly backend: SecretBackend<N, K, true>\n readonly source: SecretSource<K, Manifest.RenderServices>\n}\n\ninterface _SecretMemberBackendOptionalSource<N extends string, K extends string> extends _SecretMemberOptionsBase {\n readonly backend: SecretBackend<N, K, false>\n readonly source?: SecretSource<K, Manifest.RenderServices>\n}\n\ninterface _SecretMemberSourceOnly<_N extends string, K extends string> extends _SecretMemberOptionsBase {\n readonly backend?: undefined\n readonly source: SecretSource<K, Manifest.RenderServices>\n}\n\n/**\n * Per-secret-member options at bind time. Backends with `RequiresSource: true`\n * (`Sops.backend`, `SealedSecrets.backend`, `NativeSecret.backend`) make\n * `source` mandatory at the type level. Backends with `false`\n * (`ExternalSecrets.backend`, `Sops.passthrough`) make it optional. With no\n * backend, `source` becomes mandatory — used to feed the in-process\n * `SecretValues` layer for tests / local renders.\n */\nexport type SecretMemberOptions<N extends string, K extends string> =\n | _SecretMemberBackendRequiresSource<N, K>\n | _SecretMemberBackendOptionalSource<N, K>\n | _SecretMemberSourceOnly<N, K>\n\nexport type SecretMemberOptionsFor<A> = A extends SecretEntry<infer N, infer K, infer _E>\n ? [N, K] extends [string, string] ? SecretMemberOptions<N, K>\n : never\n : never\n\n/**\n * True iff `M` (recursively, via nested `Environment` members)\n * contains at least one `SecretEntry`. Used to flip `secrets` between\n * required (any secrets present) and optional (literals/downwards\n * only) on `BindEnvironmentInput`.\n */\nexport type HasSecrets<M extends Readonly<Record<string, EnvMember>>> = true extends {\n readonly [K in keyof M]: M[K] extends SecretEntry<infer _N, infer _K, infer _E> ? true\n : M[K] extends Environment<infer Sub> ? HasSecrets<Sub>\n : false\n}[keyof M] ? true\n : false\n\n/**\n * Recursive per-member secret options. For a secret member, the option\n * matches its `SecretMemberOptionsFor` and is required. For a nested\n * `Environment` member that itself contains secrets, the option is\n * `SecretMembersOpts<SubM>` and is also required. Nested environments\n * with no secrets are omitted entirely (no key needed).\n *\n * Together with `HasSecrets`, this enforces at compile time that every\n * `Secret` reachable from the bundle is acknowledged at bind\n * time — adding a new secret to the env contract forces every call\n * site to update.\n */\nexport type SecretMembersOpts<M extends Readonly<Record<string, EnvMember>>> = {\n readonly [\n K in keyof M as M[K] extends SecretEntry<infer _N, infer _K, infer _E> ? K\n : M[K] extends Environment<infer SubM> ? HasSecrets<SubM> extends true ? K\n : never\n : never\n ]: M[K] extends SecretEntry<infer _N, infer _K, infer _E> ? SecretMemberOptionsFor<M[K]>\n : M[K] extends Environment<infer SubM> ? SecretMembersOpts<SubM>\n : never\n}\n\n/**\n * Per-literal value override for bind time. Keyed by member name, typed\n * to each literal's declared `T`. Useful when a `Literal` is a\n * runtime contract (carries a `schema: Config.string(envName)` for app\n * code to yield) but the manifest's emitted value differs per env —\n * e.g. `CLIENT_URL`, `S3_ENDPOINT`, host/URL literals.\n *\n * Recurses on nested `Environment` members — pass `{group: {host: \"x\"}}`\n * to override a literal nested inside a sub-bundle.\n */\nexport type LiteralMembersOpts<M extends Readonly<Record<string, EnvMember>>> = {\n readonly [\n K in keyof M as M[K] extends LiteralEntry<infer _EnvName, infer _T> ? K\n : M[K] extends Environment<infer _SubM> ? K\n : never\n ]?: M[K] extends LiteralEntry<infer _EnvName, infer T> ? T\n : M[K] extends Environment<infer SubM> ? LiteralMembersOpts<SubM>\n : never\n}\n\ninterface _BindEnvironmentInputBase<\n M extends Readonly<Record<string, EnvMember>>,\n Ns extends string = string\n> {\n readonly env: Environment<M>\n /**\n * Per-literal value override for the manifest's emitted env var. The\n * runtime read (via `entry.schema`, if provided) is unchanged —\n * overrides only affect what the konfig module writes into the\n * Deployment's `env` array.\n */\n readonly literals?: LiteralMembersOpts<M>\n /**\n * Override every secret member's namespace for this bind. Useful when\n * the bundle is consumed across multiple k8s namespaces (e.g. prod /\n * staging / local) without redeclaring each contract. Recurses into\n * nested `Environment` members.\n *\n * When passed as a string literal, the literal flows into each\n * `DeclaredSecret.ref`'s brand so `secretEnvForPod` can enforce\n * cross-namespace coherence on hand-spliced env entries.\n */\n readonly namespace?: Ns\n}\n\n/**\n * `secrets` flips between required and optional based on whether `M`\n * actually contains any secrets. A bundle of literals/downwards only\n * has nothing to bind, so `secrets` stays optional. A bundle with even\n * one `Secret` (directly or nested) forces the caller to supply\n * every secret member — and for each member, either a `backend` or a\n * `source` (see `SecretMemberOptions`).\n */\nexport type BindEnvironmentInput<\n M extends Readonly<Record<string, EnvMember>>,\n Ns extends string = string\n> =\n & _BindEnvironmentInputBase<M, Ns>\n & (HasSecrets<M> extends true ? { readonly secrets: SecretMembersOpts<M> }\n : { readonly secrets?: SecretMembersOpts<M> })\n\ninterface _BindLiteralInput {\n readonly entry: LiteralEntry<string, unknown>\n readonly override?: unknown\n}\nconst _bindLiteral = (input: _BindLiteralInput): DeclaredLiteral<string, unknown> => {\n const hasOverride = input.override !== undefined\n const value = hasOverride ? input.override : input.entry.value\n const serialized = hasOverride\n ? input.entry.serialize(input.override)\n : input.entry.serialized\n return {\n envName: input.entry.envName,\n value,\n envVar: { name: input.entry.envName, value: serialized }\n }\n}\n\ninterface _BindDownwardInput {\n readonly entry: DownwardEntry<string>\n}\nconst _bindDownward = (input: _BindDownwardInput): DeclaredDownward<string> => ({\n envName: input.entry.envName,\n fieldPath: input.entry.fieldPath,\n envVar: {\n name: input.entry.envName,\n valueFrom: { fieldRef: { fieldPath: input.entry.fieldPath } }\n }\n})\n\ntype _AnyValuesLayer = Layer.Layer<unknown, RenderError, Manifest.RenderServices>\n\ninterface _BindAcc {\n readonly declared: Record<string, unknown>\n readonly envVars: EnvVar[]\n readonly manifests: Manifest.Manifest<unknown>[]\n readonly valuesLayers: _AnyValuesLayer[]\n}\n\ninterface _DispatchInput {\n readonly memberKey: string\n readonly entry: EnvMember\n readonly secretsOpts: Record<string, unknown> | undefined\n readonly literalsOpts: Record<string, unknown> | undefined\n readonly namespace: string | undefined\n readonly acc: _BindAcc\n}\n\nconst _handleSecret = (input: _DispatchInput): void => {\n const memberOpts = unsafeCoerce<SecretMemberOptions<string, string> | undefined>(\n input.secretsOpts?.[input.memberKey],\n \"SecretMembersOpts<M> shape — runtime key lookup against the typed input\"\n )\n const secret = unsafeCoerce<SecretEntry<string, string, Readonly<Record<string, string>>>>(\n input.entry,\n \"Match.tag('Secret') narrowed entry to SecretEntry; the helper-level signature is the general SecretEntry shape\"\n )\n const d = bindSecret({\n secret,\n backend: memberOpts?.backend,\n source: memberOpts?.source,\n labels: memberOpts?.labels,\n annotations: memberOpts?.annotations,\n namespace: input.namespace\n })\n input.acc.declared[input.memberKey] = d\n input.acc.envVars.push(...d.envVars)\n if (d.manifest !== undefined) input.acc.manifests.push(d.manifest)\n if (d.layer !== undefined) {\n input.acc.valuesLayers.push(\n unsafeCoerce<_AnyValuesLayer>(\n d.layer,\n \"DeclaredSecret.layer is Layer<Provide<SecretValues, N>, ...>; widen to unknown for the heterogeneous Layer.mergeAll\"\n )\n )\n }\n}\n\nconst _handleLiteral = (input: _DispatchInput): void => {\n const literal = unsafeCoerce<LiteralEntry<string, unknown>>(\n input.entry,\n \"Match.tag('Literal') narrowed entry to LiteralEntry<string, unknown>\"\n )\n const d = _bindLiteral({ entry: literal, override: input.literalsOpts?.[input.memberKey] })\n input.acc.declared[input.memberKey] = d\n input.acc.envVars.push(d.envVar)\n}\n\nconst _handleDownward = (input: _DispatchInput): void => {\n const downward = unsafeCoerce<DownwardEntry<string>>(\n input.entry,\n \"Match.tag('Downward') narrowed entry to DownwardEntry<string>\"\n )\n const d = _bindDownward({ entry: downward })\n input.acc.declared[input.memberKey] = d\n input.acc.envVars.push(d.envVar)\n}\n\nconst _handleEnvironment = (input: _DispatchInput): void => {\n const subEnv = unsafeCoerce<AnyEnvironment>(\n input.entry,\n \"Match.tag('Environment') narrowed entry to a nested Environment\"\n )\n const sub = bindEnvironment({\n env: subEnv,\n secrets: unsafeCoerce<SecretMembersOpts<Readonly<Record<string, EnvMember>>>>(\n input.secretsOpts?.[input.memberKey] ?? {},\n \"sub-record from SecretMembersOpts<M> — type is checked at the outer call site\"\n ),\n literals: unsafeCoerce<LiteralMembersOpts<Readonly<Record<string, EnvMember>>>>(\n input.literalsOpts?.[input.memberKey] ?? {},\n \"sub-record from LiteralMembersOpts<M> — type is checked at the outer call site\"\n ),\n namespace: input.namespace\n })\n input.acc.declared[input.memberKey] = sub.members\n input.acc.envVars.push(...sub.envVars)\n input.acc.manifests.push(...sub.manifests)\n input.acc.valuesLayers.push(\n unsafeCoerce<_AnyValuesLayer>(\n sub.valuesLayer,\n \"valuesLayer aggregate over the recursive merge\"\n )\n )\n}\n\nconst _dispatch = (input: _DispatchInput): void =>\n Match.value(input.entry._kind).pipe(\n Match.when(\"Secret\", () => _handleSecret(input)),\n Match.when(\"Literal\", () => _handleLiteral(input)),\n Match.when(\"Downward\", () => _handleDownward(input)),\n Match.when(\"Environment\", () => _handleEnvironment(input)),\n Match.exhaustive\n )\n\nexport const bindEnvironment = <\n const M extends Readonly<Record<string, EnvMember>>,\n const Ns extends string = string\n>(\n input: BindEnvironmentInput<M, Ns>\n): DeclaredEnvironment<M, Ns> => {\n const { env } = input\n const acc: _BindAcc = {\n declared: {},\n envVars: [],\n manifests: [],\n valuesLayers: []\n }\n const secretsOpts = unsafeCoerce<Record<string, unknown> | undefined>(\n input.secrets,\n \"discriminated union from BindEnvironmentInput; iterate keys at runtime\"\n )\n const literalsOpts = unsafeCoerce<Record<string, unknown> | undefined>(\n input.literals,\n \"discriminated union from BindEnvironmentInput; iterate keys at runtime\"\n )\n\n for (const memberKey of Object.keys(env.members)) {\n const entry = unsafeCoerce<EnvMember>(\n env.members[memberKey],\n \"env.members values are EnvMember by construction\"\n )\n _dispatch({\n memberKey,\n entry,\n secretsOpts,\n literalsOpts,\n namespace: input.namespace,\n acc\n })\n }\n\n const valuesLayer = unsafeCoerce<_AnyValuesLayer>(\n acc.valuesLayers.length === 0\n ? Layer.empty\n : Layer.mergeAll(acc.valuesLayers[0]!, ...acc.valuesLayers.slice(1)),\n \"merged Layer over a heterogeneous list of per-secret value layers\"\n )\n\n return {\n envVars: acc.envVars,\n manifests: acc.manifests,\n members: unsafeCoerce<{ readonly [K in keyof M]: DeclaredMember<M[K], Ns> }>(\n acc.declared,\n \"declared populated by iterating env.members; each key maps to its DeclaredMember<M[K], Ns>\"\n ),\n valuesLayer\n }\n}\n","import type { Manifest } from \"@konfig.ts/core\"\nimport type { SecretSource } from \"@konfig.ts/env\"\nimport { Data } from \"effect\"\n\nexport type BackendTag =\n | \"Sops\"\n | \"Sops.passthrough\"\n | \"SealedSecrets\"\n | \"ExternalSecrets\"\n | \"NativeSecret\"\n\nexport interface BackendEmitInput<N extends string, K extends string> {\n readonly name: N\n readonly namespace: string\n readonly keys: ReadonlyArray<K>\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly source?: SecretSource<K, Manifest.RenderServices>\n}\n\nexport interface SecretBackend<\n N extends string,\n K extends string,\n RequiresSource extends boolean = boolean\n> {\n readonly _tag: BackendTag\n readonly requiresSource: RequiresSource\n readonly emit: (input: BackendEmitInput<N, K>) => Manifest.Manifest<unknown>\n}\n\nexport class BackendSourceMissing extends Data.TaggedError(\"BackendSourceMissing\")<{\n readonly backend: BackendTag\n readonly secret: string\n}> {\n get message(): string {\n return `backend \"${this.backend}\" requires a source but none was provided for secret \"${this.secret}\"`\n }\n}\n","import { Manifest, RenderError } from \"@konfig.ts/core\"\nimport type { SecretSource } from \"@konfig.ts/env\"\nimport { Effect, Redacted } from \"effect\"\nimport type { Secret as K8sSecret } from \"./.generated/k8s-types\"\nimport { type BackendEmitInput, BackendSourceMissing, type SecretBackend } from \"./backend\"\n\nexport interface NativeSecretOptions {\n readonly type?: string\n readonly immutable?: boolean\n readonly silenceWarning?: boolean\n}\n\ninterface _EmitInput<N extends string, K extends string> {\n readonly base: BackendEmitInput<N, K>\n readonly opts: NativeSecretOptions\n readonly source: SecretSource<K, Manifest.RenderServices>\n}\n\nconst _emit = <N extends string, K extends string>(\n input: _EmitInput<N, K>\n): Manifest.Manifest<K8sSecret> =>\n Manifest.make<K8sSecret>((_ctx) =>\n Effect.gen(function*() {\n if (input.opts.silenceWarning !== true) {\n yield* Effect.logWarning(\n `NativeSecret backend emits a plaintext Secret with stringData on disk for \"${input.base.namespace}/${input.base.name}\". Pass { silenceWarning: true } to suppress, or switch to ExternalSecrets / SealedSecrets / Sops for production.`\n )\n }\n const resolved = yield* input.source.resolve.pipe(\n Effect.mapError(\n (cause) =>\n new RenderError({\n message: `NativeSecret(${input.base.namespace}/${input.base.name}): source failed for key \"${cause.key}\"`,\n cause\n })\n )\n )\n const stringData: Record<string, string> = {}\n for (const key of input.base.keys) {\n stringData[key] = Redacted.value(resolved[key])\n }\n const out: K8sSecret = {\n apiVersion: \"v1\",\n kind: \"Secret\",\n metadata: {\n name: input.base.name,\n namespace: input.base.namespace,\n labels: input.base.labels,\n annotations: input.base.annotations\n },\n type: input.opts.type,\n stringData,\n immutable: input.opts.immutable\n }\n return out\n })\n )\n\nexport const NativeSecret = {\n backend: <N extends string, K extends string>(\n opts?: NativeSecretOptions\n ): SecretBackend<N, K, true> => {\n const resolvedOpts = opts ?? {}\n return {\n _tag: \"NativeSecret\",\n requiresSource: true,\n emit: (input: BackendEmitInput<N, K>) => {\n if (input.source === undefined) {\n throw new BackendSourceMissing({ backend: \"NativeSecret\", secret: input.name })\n }\n return _emit({ base: input, opts: resolvedOpts, source: input.source })\n }\n }\n }\n}\n","import { Manifest, type SecretRef, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type { IngressBackend as K8sIngressBackend } from \"kubernetes-types/networking/v1\"\nimport type {\n Ingress as K8sIngress,\n IngressRule as K8sIngressRule,\n IngressTLS as K8sIngressTLS,\n Service as K8sService,\n ServicePort as K8sServicePort\n} from \"./.generated/k8s-types\"\nimport type { ContainerSpec } from \"./container\"\nimport type { ServicePortSpec } from \"./ports\"\nimport type { Selector } from \"./selector\"\n\n/**\n * Strict input for a `Service`. `selector` and `ports` are required:\n * a Service with no selector has no endpoints, and one with no ports\n * is meaningless. ServicePort needs at minimum a `port`; the upstream\n * `K8sServicePort` only marks `port` as required — names/protocol\n * defaults match kube-apiserver behaviour.\n */\nexport interface ServiceInput {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly selector: Readonly<Record<string, string>>\n readonly ports: ReadonlyArray<K8sServicePort>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n readonly clusterIP?: string\n readonly sessionAffinity?: string\n readonly publishNotReadyAddresses?: boolean\n readonly externalTrafficPolicy?: string\n readonly internalTrafficPolicy?: string\n}\n\n/**\n * Strongly-typed Service input bound to a container's declared port-name\n * union. `selector` and `ports` are required; `ports[i].targetPort`\n * accepts a bare number or `Port.ref(name)` referencing a name declared\n * on `forContainer`. `NoInfer` locks `Ports` to `forContainer`, so the\n * port list is validated against that union rather than inferred from.\n */\nexport interface ServiceFromContainerInput<Ports extends string> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly selector: Readonly<Record<string, string>>\n readonly forContainer: ContainerSpec<Ports>\n readonly ports: ReadonlyArray<ServicePortSpec<NoInfer<Ports>>>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n readonly clusterIP?: string\n readonly sessionAffinity?: string\n readonly publishNotReadyAddresses?: boolean\n readonly externalTrafficPolicy?: string\n readonly internalTrafficPolicy?: string\n}\n\n/**\n * Service built from a `Selector`. The selector's labels populate\n * `spec.selector` — drift versus the matching Deployment is impossible\n * once both consume the same `podSet`.\n */\nexport interface ServiceFromPodSetInput<L extends Readonly<Record<string, string>>> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly podSet: Selector<L>\n readonly ports: ReadonlyArray<K8sServicePort>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n readonly clusterIP?: string\n readonly sessionAffinity?: string\n readonly publishNotReadyAddresses?: boolean\n readonly externalTrafficPolicy?: string\n readonly internalTrafficPolicy?: string\n}\n\nexport const Service = {\n make: (input: ServiceInput): Manifest.Manifest<K8sService> => {\n const resource: K8sService = {\n apiVersion: \"v1\",\n kind: \"Service\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n selector: input.selector,\n type: input.type,\n ports: unsafeCoerce(\n input.ports,\n \"input.ports is the user-typed Service spec; K8s ServicePort allows the same fields\"\n ),\n clusterIP: input.clusterIP,\n sessionAffinity: input.sessionAffinity,\n publishNotReadyAddresses: input.publishNotReadyAddresses,\n externalTrafficPolicy: input.externalTrafficPolicy,\n internalTrafficPolicy: input.internalTrafficPolicy\n }\n }\n return Manifest.make<K8sService>(() => Effect.succeed(resource))\n },\n fromContainer: <Ports extends string>(\n input: ServiceFromContainerInput<Ports>\n ): Manifest.Manifest<K8sService> =>\n Service.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n selector: input.selector,\n ports: unsafeCoerce<ReadonlyArray<K8sServicePort>>(\n input.ports,\n \"ServicePortSpec<Ports> structurally matches K8sServicePort; targetPort's PortName<Ports> brand is a phantom — runtime value is the underlying string\"\n ),\n type: input.type,\n clusterIP: input.clusterIP,\n sessionAffinity: input.sessionAffinity,\n publishNotReadyAddresses: input.publishNotReadyAddresses,\n externalTrafficPolicy: input.externalTrafficPolicy,\n internalTrafficPolicy: input.internalTrafficPolicy\n }),\n fromPodSet: <L extends Readonly<Record<string, string>>>(\n input: ServiceFromPodSetInput<L>\n ): Manifest.Manifest<K8sService> =>\n Service.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n selector: input.podSet.labels,\n ports: input.ports,\n type: input.type,\n clusterIP: input.clusterIP,\n sessionAffinity: input.sessionAffinity,\n publishNotReadyAddresses: input.publishNotReadyAddresses,\n externalTrafficPolicy: input.externalTrafficPolicy,\n internalTrafficPolicy: input.internalTrafficPolicy\n })\n}\n\nexport interface IngressTLSInput {\n readonly hosts?: ReadonlyArray<string>\n readonly secretName: SecretRef<string>\n}\n\nexport interface IngressInput {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly ingressClassName?: string\n readonly rules?: ReadonlyArray<K8sIngressRule>\n readonly tls?: ReadonlyArray<IngressTLSInput>\n readonly defaultBackend?: K8sIngressBackend\n}\n\nexport const Ingress = {\n make: (input: IngressInput): Manifest.Manifest<K8sIngress> => {\n const resource: K8sIngress = {\n apiVersion: \"networking.k8s.io/v1\",\n kind: \"Ingress\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n ingressClassName: input.ingressClassName,\n rules: unsafeCoerce(\n input.rules,\n \"user-supplied Ingress rules; widening from our convenience type to the K8s type\"\n ),\n tls: unsafeCoerce<K8sIngressTLS[]>(input.tls, \"Ingress.tls produces K8sIngressTLS with branded secretName\"),\n defaultBackend: unsafeCoerce(input.defaultBackend, \"user-supplied IngressBackend; structural match to K8s type\")\n }\n }\n return Manifest.make<K8sIngress>(() => Effect.succeed(resource))\n },\n /**\n * TLS entry constructor for `Ingress.make({ tls: [...] })`. Takes a\n * branded `SecretRef` so the secret's name can't widen to a raw\n * string at the call site.\n */\n tls: (input: {\n readonly secretName: SecretRef<string>\n readonly hosts?: ReadonlyArray<string>\n }): IngressTLSInput => ({ secretName: input.secretName, hosts: input.hosts })\n}\n","import { Redacted } from \"effect\"\nimport { createHash, type Hash } from \"node:crypto\"\n\nexport interface HashSecretValuesInput {\n readonly values: Readonly<Record<string, Redacted.Redacted<string>>>\n /**\n * Non-secret salt folded into the digest so it is NOT a pure function of the\n * plaintext — this defeats offline brute-force / rainbow-table recovery of\n * low-entropy secrets from the annotation. Use a stable per-workload\n * identifier such as `\"<namespace>/<name>\"`.\n */\n readonly salt: string\n}\n\n// Netstring-frames every field (`<byteLen>:<bytes>,`) before hashing. Plain\n// `key + \"=\" + value + \"\\n\"` concatenation is ambiguous — `{ \"a=b\": \"c\" }` and\n// `{ \"a\": \"b\\nc\" }` would hash identically. Length-prefixing makes each field\n// boundary unforgeable, so distinct records always produce distinct digests.\nconst _frame = (hasher: Hash, value: string): void => {\n const bytes = Buffer.from(value, \"utf8\")\n hasher.update(`${bytes.length}:`)\n hasher.update(bytes)\n hasher.update(\",\")\n}\n\n// Captures values AT BUILD TIME ONLY — rotations between builds need an\n// in-cluster watcher (e.g. Reloader). Redacted.value is inline so plaintext\n// is not bound to a local.\n//\n// NOTE: the returned digest is a change-detection fingerprint, NOT a\n// cryptographic commitment you may safely publish for a low-entropy secret.\n// It is salted (so it is not a bare sha256 of the plaintext) and emitted at\n// full width (no truncation), but it must not be treated as secret-safe.\nexport const hashSecretValues = (input: HashSecretValuesInput): string => {\n const hasher = createHash(\"sha256\")\n _frame(hasher, \"konfig/secret-values-hash/v1\")\n _frame(hasher, input.salt)\n const keys = Object.keys(input.values).sort()\n for (const key of keys) {\n _frame(hasher, key)\n _frame(hasher, Redacted.value(input.values[key]!))\n }\n return hasher.digest(\"hex\")\n}\n","import { Manifest, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type { PersistentVolumeSpec as K8sPersistentVolumeSpec } from \"kubernetes-types/core/v1\"\nimport type {\n NetworkPolicyEgressRule as K8sNetworkPolicyEgressRule,\n NetworkPolicyIngressRule as K8sNetworkPolicyIngressRule\n} from \"kubernetes-types/networking/v1\"\nimport type {\n ClusterRole as K8sClusterRole,\n ClusterRoleBinding as K8sClusterRoleBinding,\n NetworkPolicy as K8sNetworkPolicy,\n PersistentVolume as K8sPersistentVolume,\n PersistentVolumeClaim as K8sPersistentVolumeClaim,\n Role as K8sRole,\n RoleBinding as K8sRoleBinding\n} from \"./.generated/k8s-types\"\nimport type { Selector } from \"./selector\"\n\ninterface NamespacedMeta {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\ninterface ClusterMeta {\n readonly name: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\n/**\n * Standard k8s PV access modes. Constrained to the four documented\n * values so a typo (`\"ReadWriteonce\"`) is a compile-time error.\n */\nexport type PersistentVolumeAccessMode =\n | \"ReadWriteOnce\"\n | \"ReadOnlyMany\"\n | \"ReadWriteMany\"\n | \"ReadWriteOncePod\"\n\nexport type PersistentVolumeReclaimPolicy = \"Retain\" | \"Recycle\" | \"Delete\"\n\nexport type PersistentVolumeMode = \"Filesystem\" | \"Block\"\n\n/**\n * Strict input shape for a `PersistentVolume.spec`. Upstream\n * `kubernetes-types` types every field as optional (because the\n * OpenAPI generator emits the entire union), which makes invalid\n * specs (no capacity, no accessModes, no volume source) compile.\n * The fields the kube-apiserver actually requires are required here.\n *\n * Volume-source fields (`hostPath`, `csi`, `nfs`, `local`, etc.) are\n * inherited from the upstream `PersistentVolumeSpec` via `Omit` so\n * users can use whichever source they need. \"At least one source\"\n * isn't enforced statically (TS unions over 20+ variants would be\n * unwieldy) — the kube-apiserver rejects a spec with no source.\n */\nexport interface PersistentVolumeSpecInput extends\n Omit<\n K8sPersistentVolumeSpec,\n \"capacity\" | \"accessModes\" | \"persistentVolumeReclaimPolicy\" | \"volumeMode\" | \"claimRef\"\n >\n{\n readonly capacity: { readonly storage: string }\n readonly accessModes: ReadonlyArray<PersistentVolumeAccessMode>\n readonly persistentVolumeReclaimPolicy?: PersistentVolumeReclaimPolicy\n readonly volumeMode?: PersistentVolumeMode\n readonly claimRef?: { readonly namespace: string; readonly name: string }\n}\n\nexport interface PersistentVolumeInput extends ClusterMeta {\n readonly spec: PersistentVolumeSpecInput\n}\n\nexport const PersistentVolume = {\n make: (input: PersistentVolumeInput): Manifest.Manifest<K8sPersistentVolume> =>\n Manifest.make<K8sPersistentVolume>(() =>\n Effect.succeed({\n apiVersion: \"v1\",\n kind: \"PersistentVolume\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: unsafeCoerce<K8sPersistentVolume[\"spec\"]>(\n input.spec,\n \"user-supplied PV spec; structural match to the K8s type\"\n )\n })\n )\n}\n\n/**\n * Strict input shape for a `PersistentVolumeClaim.spec`. Same\n * rationale as `PersistentVolumeSpecInput` — accessModes + a storage\n * request are the fields the apiserver requires.\n */\nexport interface PersistentVolumeClaimSpecInput {\n readonly accessModes: ReadonlyArray<PersistentVolumeAccessMode>\n readonly resources: { readonly requests: { readonly storage: string } }\n readonly storageClassName?: string\n readonly volumeMode?: PersistentVolumeMode\n readonly volumeName?: string\n readonly selector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n}\n\nexport interface PersistentVolumeClaimInput extends NamespacedMeta {\n readonly spec: PersistentVolumeClaimSpecInput\n}\n\nexport const PersistentVolumeClaim = {\n make: (input: PersistentVolumeClaimInput): Manifest.Manifest<K8sPersistentVolumeClaim> =>\n Manifest.make<K8sPersistentVolumeClaim>(() =>\n Effect.succeed({\n apiVersion: \"v1\",\n kind: \"PersistentVolumeClaim\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: unsafeCoerce<K8sPersistentVolumeClaim[\"spec\"]>(\n input.spec,\n \"user-supplied PVC spec; structural match to the K8s type\"\n )\n })\n )\n}\n\nexport interface NetworkPolicyInput extends NamespacedMeta {\n readonly spec: K8sNetworkPolicy[\"spec\"]\n}\n\n/**\n * Peer rule for `NetworkPolicy.fromPodSet`. A peer is either a typed\n * `Selector` (matched as `podSelector.matchLabels`), a `namespaceSelector`,\n * or a CIDR block.\n */\nexport interface NetworkPolicyPeer {\n readonly podSet?: Selector<Readonly<Record<string, string>>>\n readonly namespaceSelector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n readonly ipBlock?: { readonly cidr: string; readonly except?: ReadonlyArray<string> }\n}\n\nexport interface NetworkPolicyIngressRule {\n readonly from?: ReadonlyArray<NetworkPolicyPeer>\n readonly ports?: K8sNetworkPolicyIngressRule[\"ports\"]\n}\n\nexport interface NetworkPolicyEgressRule {\n readonly to?: ReadonlyArray<NetworkPolicyPeer>\n readonly ports?: K8sNetworkPolicyEgressRule[\"ports\"]\n}\n\n/**\n * NetworkPolicy built from typed `Selector`s. `podSet` drives\n * `spec.podSelector`; ingress/egress peer rules accept further selectors\n * via `from[].podSet` / `to[].podSet`. Peer selectors need not match the\n * owning selector — the typing ties this NetworkPolicy's selection to a\n * single source of truth and lets peers be independently typed.\n */\nexport interface NetworkPolicyFromPodSetInput<L extends Readonly<Record<string, string>>> extends NamespacedMeta {\n readonly podSet: Selector<L>\n readonly policyTypes?: ReadonlyArray<\"Ingress\" | \"Egress\">\n readonly ingress?: ReadonlyArray<NetworkPolicyIngressRule>\n readonly egress?: ReadonlyArray<NetworkPolicyEgressRule>\n}\n\nconst _lowerPeer = (peer: NetworkPolicyPeer): {\n readonly podSelector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n readonly namespaceSelector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n readonly ipBlock?: { readonly cidr: string; readonly except?: ReadonlyArray<string> }\n} => ({\n ...(peer.podSet !== undefined ? { podSelector: { matchLabels: peer.podSet.labels } } : {}),\n ...(peer.namespaceSelector !== undefined ? { namespaceSelector: peer.namespaceSelector } : {}),\n ...(peer.ipBlock !== undefined ? { ipBlock: peer.ipBlock } : {})\n})\n\nexport const NetworkPolicy = {\n make: (input: NetworkPolicyInput): Manifest.Manifest<K8sNetworkPolicy> =>\n Manifest.make<K8sNetworkPolicy>(() =>\n Effect.succeed({\n apiVersion: \"networking.k8s.io/v1\",\n kind: \"NetworkPolicy\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: input.spec\n })\n ),\n fromPodSet: <L extends Readonly<Record<string, string>>>(\n input: NetworkPolicyFromPodSetInput<L>\n ): Manifest.Manifest<K8sNetworkPolicy> => {\n const ingress = input.ingress?.map((rule) => ({\n from: rule.from?.map(_lowerPeer),\n ports: rule.ports\n }))\n const egress = input.egress?.map((rule) => ({\n to: rule.to?.map(_lowerPeer),\n ports: rule.ports\n }))\n return NetworkPolicy.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n spec: unsafeCoerce<K8sNetworkPolicy[\"spec\"]>(\n {\n podSelector: { matchLabels: input.podSet.labels },\n policyTypes: input.policyTypes,\n ingress,\n egress\n },\n \"konfig peers carry readonly arrays; upstream NetworkPolicySpec is mutable but the runtime shape matches\"\n )\n })\n }\n}\n\nexport interface ClusterRoleInput extends ClusterMeta {\n readonly rules?: K8sClusterRole[\"rules\"]\n readonly aggregationRule?: K8sClusterRole[\"aggregationRule\"]\n}\n\nexport const ClusterRole = {\n make: (input: ClusterRoleInput): Manifest.Manifest<K8sClusterRole> =>\n Manifest.make<K8sClusterRole>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"ClusterRole\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n },\n rules: input.rules,\n aggregationRule: input.aggregationRule\n })\n )\n}\n\nexport interface ClusterRoleBindingInput extends ClusterMeta {\n readonly roleRef: K8sClusterRoleBinding[\"roleRef\"]\n readonly subjects?: K8sClusterRoleBinding[\"subjects\"]\n}\n\nexport const ClusterRoleBinding = {\n make: (input: ClusterRoleBindingInput): Manifest.Manifest<K8sClusterRoleBinding> =>\n Manifest.make<K8sClusterRoleBinding>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"ClusterRoleBinding\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n },\n roleRef: input.roleRef,\n subjects: input.subjects\n })\n )\n}\n\nexport interface RoleInput extends NamespacedMeta {\n readonly rules?: K8sRole[\"rules\"]\n}\n\nexport const Role = {\n make: (input: RoleInput): Manifest.Manifest<K8sRole> =>\n Manifest.make<K8sRole>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"Role\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n rules: input.rules\n })\n )\n}\n\nexport interface RoleBindingInput extends NamespacedMeta {\n readonly roleRef: K8sRoleBinding[\"roleRef\"]\n readonly subjects?: K8sRoleBinding[\"subjects\"]\n}\n\nexport const RoleBinding = {\n make: (input: RoleBindingInput): Manifest.Manifest<K8sRoleBinding> =>\n Manifest.make<K8sRoleBinding>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"RoleBinding\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n roleRef: input.roleRef,\n subjects: input.subjects\n })\n )\n}\n","import { brand } from \"@konfig.ts/core\"\nimport type { ConfigMapRef, PvcRef, SecretRef } from \"@konfig.ts/core\"\n\n/**\n * Branded volume name — a string carrying the literal `N` in its\n * phantom. Constructed by the volume factories\n * (`Volume.empty`, `Volume.fromSecret`, …) and `Volume.mountRef`. Lets\n * `VolumeMount<Mounts>` and `Pod` constrain a container's\n * `volumeMounts[i].name` to volumes that the pod actually declares.\n */\ndeclare const VolumeNameBrand: unique symbol\nexport type VolumeName<N extends string> = string & {\n readonly [VolumeNameBrand]: N\n}\n\nconst _volumeName = <const N extends string>(name: N): VolumeName<N> => brand<VolumeName<N>>(name)\n\nexport interface Volume<N extends string = string> {\n readonly name: VolumeName<N>\n readonly secret?: {\n readonly secretName: string\n readonly optional?: boolean\n readonly defaultMode?: number\n }\n readonly configMap?: {\n readonly name: string\n readonly optional?: boolean\n readonly defaultMode?: number\n readonly items?: ReadonlyArray<{ readonly key: string; readonly path: string }>\n }\n readonly emptyDir?: { readonly medium?: string; readonly sizeLimit?: string }\n readonly persistentVolumeClaim?: {\n readonly claimName: PvcRef<string>\n readonly readOnly?: boolean\n }\n readonly hostPath?: { readonly path: string; readonly type?: string }\n}\n\nexport interface EmptyVolumeInput<N extends string> {\n readonly name: N\n readonly medium?: string\n readonly sizeLimit?: string\n}\n\nexport interface VolumeFromSecretInput<N extends string> {\n readonly name: N\n readonly ref: SecretRef<string>\n readonly optional?: boolean\n readonly defaultMode?: number\n}\n\nexport interface VolumeFromConfigMapInput<N extends string> {\n readonly name: N\n readonly ref: ConfigMapRef<string>\n readonly optional?: boolean\n readonly defaultMode?: number\n readonly items?: ReadonlyArray<{ readonly key: string; readonly path: string }>\n}\n\nexport interface VolumeFromPvcInput<N extends string, PvcN extends string> {\n readonly name: N\n readonly claim: PvcRef<PvcN>\n readonly readOnly?: boolean\n}\n\n/**\n * `Volume` value namespace.\n *\n * volumes: [\n * Volume.empty({ name: \"config\" }),\n * Volume.fromSecret({ name: \"tls\", ref: tlsSecret.ref }),\n * Volume.fromConfigMap({ name: \"settings\", ref: cfg.ref }),\n * Volume.fromPvc({ name: \"data\", claim: pvc.ref }),\n * ],\n * volumeMounts: [\n * { name: Volume.mountRef(\"config\"), mountPath: \"/etc/conf\" },\n * ],\n *\n * All four constructors capture the literal `name` in the returned\n * `Volume<N>` brand; `Pod` infers the union and constrains each\n * container's `volumeMounts[i].name` to it.\n */\nexport const Volume = {\n empty: <const N extends string>(input: EmptyVolumeInput<N>): Volume<N> => ({\n name: _volumeName(input.name),\n emptyDir: { medium: input.medium, sizeLimit: input.sizeLimit }\n }),\n fromSecret: <const N extends string>(input: VolumeFromSecretInput<N>): Volume<N> => ({\n name: _volumeName(input.name),\n secret: {\n secretName: input.ref,\n optional: input.optional,\n defaultMode: input.defaultMode\n }\n }),\n fromConfigMap: <const N extends string>(input: VolumeFromConfigMapInput<N>): Volume<N> => ({\n name: _volumeName(input.name),\n configMap: {\n name: input.ref,\n optional: input.optional,\n defaultMode: input.defaultMode,\n items: input.items\n }\n }),\n fromPvc: <const N extends string, const PvcN extends string>(\n input: VolumeFromPvcInput<N, PvcN>\n ): Volume<N> => ({\n name: _volumeName(input.name),\n persistentVolumeClaim: { claimName: input.claim, readOnly: input.readOnly }\n }),\n mountRef: <const N extends string>(name: N): VolumeName<N> => _volumeName(name)\n}\n\n/**\n * Typed container volumeMount. `Mounts` is the union of volume names\n * declared on the surrounding pod; `name` must reference one of them.\n * Bare-number variants don't apply (mounts are always by name).\n */\nexport interface VolumeMount<Mounts extends string = string> {\n readonly name: VolumeName<Mounts>\n readonly mountPath: string\n readonly readOnly?: boolean\n readonly subPath?: string\n readonly subPathExpr?: string\n readonly mountPropagation?: string\n}\n\nexport type VolumeNamesOf<V extends ReadonlyArray<Volume<string>>> = {\n readonly [I in keyof V]: V[I] extends Volume<infer N> ? N : never\n}[number]\n","import { Manifest, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n CronJob as K8sCronJob,\n Deployment as K8sDeployment,\n Job as K8sJob,\n StatefulSet as K8sStatefulSet\n} from \"./.generated/k8s-types\"\nimport type { PodSpecInput } from \"./container\"\nimport type { Selector } from \"./selector\"\n\ninterface WorkloadMeta {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\ninterface SelectorAndTemplate {\n readonly selector: { readonly matchLabels: Readonly<Record<string, string>> }\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n}\n\nexport interface DeploymentInput extends WorkloadMeta, SelectorAndTemplate {\n readonly replicas?: number\n readonly strategy?: unknown\n readonly revisionHistoryLimit?: number\n readonly progressDeadlineSeconds?: number\n readonly minReadySeconds?: number\n}\n\n/**\n * Deployment built from a `Selector`. The selector's labels become both\n * the Deployment's `spec.selector.matchLabels` and the pod template's\n * `metadata.labels` — coherent by construction. Drift between selector\n * and template (the classic \"service has no endpoints\" footgun) is\n * structurally impossible once both consume the same `podSet`.\n */\nexport interface DeploymentFromPodSetInput<L extends Readonly<Record<string, string>>> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly podSet: Selector<L>\n readonly replicas?: number\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n readonly strategy?: unknown\n readonly revisionHistoryLimit?: number\n readonly progressDeadlineSeconds?: number\n readonly minReadySeconds?: number\n}\n\nexport const Deployment = {\n make: (input: DeploymentInput): Manifest.Manifest<K8sDeployment> => {\n const resource: K8sDeployment = {\n apiVersion: \"apps/v1\",\n kind: \"Deployment\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n replicas: input.replicas,\n selector: input.selector,\n template: unsafeCoerce(\n input.template,\n \"konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction\"\n ),\n strategy: unsafeCoerce(\n input.strategy,\n \"DeploymentStrategy is escape-hatch unknown; lift to K8s type for serialization\"\n ),\n revisionHistoryLimit: input.revisionHistoryLimit,\n progressDeadlineSeconds: input.progressDeadlineSeconds,\n minReadySeconds: input.minReadySeconds\n }\n }\n return Manifest.make<K8sDeployment>(() => Effect.succeed(resource))\n },\n fromPodSet: <L extends Readonly<Record<string, string>>>(\n input: DeploymentFromPodSetInput<L>\n ): Manifest.Manifest<K8sDeployment> =>\n Deployment.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n replicas: input.replicas,\n selector: { matchLabels: input.podSet.labels },\n template: {\n metadata: {\n // podSet labels are spread LAST so a colliding caller-supplied\n // template label can never shadow a selector label — that would\n // desync the pod template from `spec.selector` and strand the\n // Deployment with zero matching endpoints.\n labels: { ...input.template.metadata?.labels, ...input.podSet.labels },\n annotations: input.template.metadata?.annotations\n },\n spec: input.template.spec\n },\n strategy: input.strategy,\n revisionHistoryLimit: input.revisionHistoryLimit,\n progressDeadlineSeconds: input.progressDeadlineSeconds,\n minReadySeconds: input.minReadySeconds\n })\n}\n\nexport interface StatefulSetInput extends WorkloadMeta, SelectorAndTemplate {\n readonly replicas?: number\n readonly serviceName: string\n readonly volumeClaimTemplates?: ReadonlyArray<unknown>\n readonly podManagementPolicy?: string\n readonly updateStrategy?: unknown\n}\n\nexport const StatefulSet = {\n make: (input: StatefulSetInput): Manifest.Manifest<K8sStatefulSet> => {\n const resource: K8sStatefulSet = {\n apiVersion: \"apps/v1\",\n kind: \"StatefulSet\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n replicas: input.replicas,\n selector: input.selector,\n template: unsafeCoerce(\n input.template,\n \"konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction\"\n ),\n serviceName: input.serviceName,\n volumeClaimTemplates: unsafeCoerce(\n input.volumeClaimTemplates,\n \"StatefulSet volumeClaimTemplates is escape-hatch unknown; lift to K8s type\"\n ),\n podManagementPolicy: input.podManagementPolicy,\n updateStrategy: unsafeCoerce(input.updateStrategy, \"StatefulSetUpdateStrategy is escape-hatch unknown\")\n }\n }\n return Manifest.make<K8sStatefulSet>(() => Effect.succeed(resource))\n }\n}\n\nexport interface JobInput extends WorkloadMeta {\n readonly parallelism?: number\n readonly completions?: number\n readonly backoffLimit?: number\n readonly activeDeadlineSeconds?: number\n readonly ttlSecondsAfterFinished?: number\n readonly suspend?: boolean\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n}\n\nexport const Job = {\n make: (input: JobInput): Manifest.Manifest<K8sJob> => {\n const resource: K8sJob = {\n apiVersion: \"batch/v1\",\n kind: \"Job\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n parallelism: input.parallelism,\n completions: input.completions,\n backoffLimit: input.backoffLimit,\n activeDeadlineSeconds: input.activeDeadlineSeconds,\n ttlSecondsAfterFinished: input.ttlSecondsAfterFinished,\n suspend: input.suspend,\n template: unsafeCoerce(\n input.template,\n \"konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction\"\n )\n }\n }\n return Manifest.make<K8sJob>(() => Effect.succeed(resource))\n }\n}\n\nexport interface CronJobInput extends WorkloadMeta {\n readonly schedule: string\n readonly concurrencyPolicy?: string\n readonly successfulJobsHistoryLimit?: number\n readonly failedJobsHistoryLimit?: number\n readonly startingDeadlineSeconds?: number\n readonly suspend?: boolean\n readonly jobTemplate: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: {\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n readonly backoffLimit?: number\n readonly activeDeadlineSeconds?: number\n readonly ttlSecondsAfterFinished?: number\n }\n }\n}\n\nexport const CronJob = {\n make: (input: CronJobInput): Manifest.Manifest<K8sCronJob> => {\n const resource: K8sCronJob = {\n apiVersion: \"batch/v1\",\n kind: \"CronJob\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n schedule: input.schedule,\n concurrencyPolicy: input.concurrencyPolicy,\n successfulJobsHistoryLimit: input.successfulJobsHistoryLimit,\n failedJobsHistoryLimit: input.failedJobsHistoryLimit,\n startingDeadlineSeconds: input.startingDeadlineSeconds,\n suspend: input.suspend,\n jobTemplate: unsafeCoerce(\n input.jobTemplate,\n \"konfig CronJob jobTemplate is structurally a K8s JobTemplateSpec body\"\n )\n }\n }\n return Manifest.make<K8sCronJob>(() => Effect.succeed(resource))\n }\n}\n","import { Manifest, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n Deployment as K8sDeployment,\n NetworkPolicy as K8sNetworkPolicy,\n Service as K8sService\n} from \"./.generated/k8s-types\"\nimport { Service, type ServiceFromPodSetInput } from \"./network\"\nimport { NetworkPolicy, type NetworkPolicyFromPodSetInput } from \"./policy\"\nimport type { Selector } from \"./selector\"\nimport { Deployment, type DeploymentFromPodSetInput } from \"./workload\"\n\n/**\n * `PodSet.define` input. Drives a coherent Deployment + Service +\n * (optional) NetworkPolicy from a single `Selector` — every resource\n * derives its selector from `podSet`, so the trio cannot drift.\n */\nexport interface DefinePodSetInput<L extends Readonly<Record<string, string>>> {\n readonly podSet: Selector<L>\n readonly deployment: Omit<DeploymentFromPodSetInput<L>, \"podSet\">\n readonly service?: Omit<ServiceFromPodSetInput<L>, \"podSet\">\n readonly netPol?: Omit<NetworkPolicyFromPodSetInput<L>, \"podSet\">\n}\n\ntype PodSetOutput =\n | readonly [K8sDeployment, K8sService]\n | readonly [K8sDeployment, K8sService, K8sNetworkPolicy]\n | readonly [K8sDeployment, K8sNetworkPolicy]\n | readonly [K8sDeployment]\n\n/**\n * `PodSet` value namespace.\n *\n * const trio = PodSet.define({\n * podSet: redisCachePods,\n * deployment: { ... },\n * service: { ... },\n * netPol: { ... },\n * });\n *\n * Umbrella over `Deployment.fromPodSet`, `Service.fromPodSet`, and\n * `NetworkPolicy.fromPodSet` — emits whichever subset of the trio the\n * input specifies, all rooted at one `Selector`.\n */\nexport const PodSet = {\n define: <L extends Readonly<Record<string, string>>>(\n input: DefinePodSetInput<L>\n ): Manifest.Manifest<PodSetOutput> => {\n const deployment = Deployment.fromPodSet({ podSet: input.podSet, ...input.deployment })\n const service = input.service !== undefined\n ? Service.fromPodSet({ podSet: input.podSet, ...input.service })\n : undefined\n const netPol = input.netPol !== undefined\n ? NetworkPolicy.fromPodSet({ podSet: input.podSet, ...input.netPol })\n : undefined\n\n return Manifest.make<PodSetOutput>((ctx) =>\n Effect.gen(function*() {\n const d = yield* deployment.render(ctx)\n const s = service !== undefined ? yield* service.render(ctx) : undefined\n const n = netPol !== undefined ? yield* netPol.render(ctx) : undefined\n const reason =\n \"tuple element types are statically known per branch; the array literal is widened by TS, the brand-free runtime shape matches the typed tuple\"\n if (s !== undefined && n !== undefined) {\n return unsafeCoerce<readonly [K8sDeployment, K8sService, K8sNetworkPolicy]>([d, s, n], reason)\n }\n if (s !== undefined) return unsafeCoerce<readonly [K8sDeployment, K8sService]>([d, s], reason)\n if (n !== undefined) return unsafeCoerce<readonly [K8sDeployment, K8sNetworkPolicy]>([d, n], reason)\n return unsafeCoerce<readonly [K8sDeployment]>([d], reason)\n })\n )\n }\n}\n","import { unsafeCoerce } from \"@konfig.ts/core\"\n\n/**\n * Selector — one source of truth for \"this pod set.\"\n *\n * `Selector<L>` wraps a literal label record and brands it. Resources\n * that *select* pods — Deployment.selector, Service.selector,\n * NetworkPolicy.podSelector, HPA target — take the bundle directly via\n * `Deployment.fromPodSet` / `Service.fromPodSet` / `NetworkPolicy.fromPodSet`\n * so a drift across three resources (the classic \"service has no\n * endpoints / netpol denies everything\" bug) becomes a compile error.\n *\n * `Workload.web` already keeps these labels coherent internally; the\n * Selector is the win when users go off-script: StatefulSet, DaemonSet,\n * cross-namespace selectors, or wiring a NetworkPolicy from app A to\n * peer pods B.\n */\ndeclare const SelectorBrand: unique symbol\n\nexport interface Selector<L extends Readonly<Record<string, string>>> {\n readonly [SelectorBrand]: L\n readonly labels: L\n}\n\n/**\n * `Selector` value namespace.\n *\n * const apiPods = Selector.make({ app: \"api\", tier: \"web\" });\n */\nexport const Selector = {\n make: <const L extends Readonly<Record<string, string>>>(labels: L): Selector<L> =>\n unsafeCoerce<Selector<L>>(\n { labels },\n \"SelectorBrand is a unique-symbol phantom — no runtime value; runtime shape is { labels }\"\n )\n}\n\nexport type SelectorLabels<S> = S extends Selector<infer L> ? L : never\n","import type { Manifest, SecretRef } from \"@konfig.ts/core\"\nimport { Manifest as M, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n CronJob as K8sCronJob,\n Deployment as K8sDeployment,\n Ingress as K8sIngress,\n IngressRule as K8sIngressRule,\n Service as K8sService,\n ServiceAccount as K8sServiceAccount,\n ServicePort as K8sServicePort\n} from \"./.generated/k8s-types\"\nimport type { ContainerInput, ContainerSpec } from \"./container\"\nimport { Ingress, type IngressTLSInput, Service } from \"./network\"\nimport type { ServicePortSpec } from \"./ports\"\nimport type { Volume } from \"./volume\"\nimport { CronJob, Deployment } from \"./workload\"\n\n/**\n * Union of port names declared by every `ContainerSpec` in `Cs`. Raw\n * `ContainerInput` entries (no `Container.define`) contribute `never`,\n * so untyped containers don't widen the result — they just don't add\n * any named-port options to the Service. With every container untyped,\n * the union collapses to `never` and `targetPort` is effectively\n * `number`-only, matching Kubernetes' behaviour when no port is named.\n */\ntype _PortNamesOfContainers<Cs extends ReadonlyArray<ContainerInput>> = {\n readonly [K in keyof Cs]: Cs[K] extends ContainerSpec<infer P, string> ? P : never\n}[number]\n\n/**\n * Reloader integration shorthand. Two complementary rotation models:\n *\n * - *Build-time* rotation (re-render → new hash → rolling update). konfig\n * does NOT stamp this automatically; it ships `hashSecretValues` as a\n * helper you attach yourself — feed it your resolved secret values and\n * place the digest into `deployment.podAnnotations`, so a value change\n * flips the pod template and triggers a rollout.\n * - *Runtime* rotation via Stakater's Reloader (operator watches mounted\n * Secrets/ConfigMaps and patches the workload to restart pods on change),\n * selected by the option below.\n *\n * Pick:\n *\n * - `\"off\"` (default) — no Reloader annotation. Pair with a build-time\n * `hashSecretValues` annotation if you accept the redeploy-on-edit model.\n * - `\"stakater\"` — emit `reloader.stakater.com/auto: \"true\"`. Reloader\n * watches every Secret/ConfigMap referenced by the pod spec.\n * - `\"stakater-strict\"` — emit `reloader.stakater.com/auto: \"true\"`\n * plus `reloader.stakater.com/match: \"true\"`, restricting watch\n * to objects with the matching annotation set on them.\n * - `{ secrets, configMaps }` — explicit per-resource lists, emitted\n * as `secret.reloader.stakater.com/reload` /\n * `configmap.reloader.stakater.com/reload` (comma-joined).\n *\n * See packages/k8s/README.md for the trade-off between build-time\n * hashes and runtime reloader.\n */\nexport type ReloaderOption =\n | \"off\"\n | \"stakater\"\n | \"stakater-strict\"\n | {\n readonly secrets?: ReadonlyArray<string>\n readonly configMaps?: ReadonlyArray<string>\n }\n\nconst _reloaderAnnotations = (\n opt: ReloaderOption | undefined\n): Readonly<Record<string, string>> => {\n if (opt === undefined || opt === \"off\") return {}\n if (opt === \"stakater\") return { \"reloader.stakater.com/auto\": \"true\" }\n if (opt === \"stakater-strict\") {\n return {\n \"reloader.stakater.com/auto\": \"true\",\n \"reloader.stakater.com/match\": \"true\"\n }\n }\n const out: Record<string, string> = {}\n if (opt.secrets && opt.secrets.length > 0) {\n out[\"secret.reloader.stakater.com/reload\"] = opt.secrets.join(\",\")\n }\n if (opt.configMaps && opt.configMaps.length > 0) {\n out[\"configmap.reloader.stakater.com/reload\"] = opt.configMaps.join(\",\")\n }\n return out\n}\n\ninterface WebInput<Cs extends ReadonlyArray<ContainerInput>> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n /** Pod-restart-on-rotation integration. See `ReloaderOption`. */\n readonly reloader?: ReloaderOption\n readonly deployment: {\n readonly replicas?: number\n readonly containers: Cs\n readonly volumes?: ReadonlyArray<Volume>\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n readonly serviceAccountName?: string\n readonly podLabels?: Readonly<Record<string, string>>\n readonly podAnnotations?: Readonly<Record<string, string>>\n }\n readonly service: {\n readonly ports: ReadonlyArray<ServicePortSpec<NoInfer<_PortNamesOfContainers<Cs>>>>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n }\n readonly ingress?: {\n readonly ingressClassName?: string\n readonly rules?: ReadonlyArray<K8sIngressRule>\n readonly tls?: ReadonlyArray<IngressTLSInput>\n readonly annotations?: Readonly<Record<string, string>>\n }\n}\n\nexport const web = <const Cs extends ReadonlyArray<ContainerInput>>(\n input: WebInput<Cs>\n): Manifest.Manifest<\n readonly [K8sDeployment, K8sService] | readonly [K8sDeployment, K8sService, K8sIngress]\n> => {\n const selectorLabels = { app: input.name }\n // selectorLabels are spread LAST so a colliding user pod label can never\n // override the `app` selector — that would desync the pod template from\n // `spec.selector` and leave the Service with zero endpoints.\n const podLabels = { ...input.deployment.podLabels, ...selectorLabels }\n\n const reloaderAnns = _reloaderAnnotations(input.reloader)\n const deployment = Deployment.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: { ...input.annotations, ...reloaderAnns },\n replicas: input.deployment.replicas,\n selector: { matchLabels: selectorLabels },\n template: {\n metadata: { labels: podLabels, annotations: input.deployment.podAnnotations },\n spec: {\n containers: input.deployment.containers,\n volumes: input.deployment.volumes,\n imagePullSecrets: input.deployment.imagePullSecrets,\n serviceAccountName: input.deployment.serviceAccountName\n }\n }\n })\n\n const service = Service.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: input.annotations,\n selector: selectorLabels,\n type: input.service.type ?? \"ClusterIP\",\n ports: unsafeCoerce<ReadonlyArray<K8sServicePort>>(\n input.service.ports,\n \"ServicePortSpec<Ports> structurally matches K8sServicePort; the PortName<Ports> brand on targetPort is a phantom whose runtime value is the underlying string\"\n )\n })\n\n if (input.ingress === undefined) {\n return M.make((ctx) => Effect.all([deployment.render(ctx), service.render(ctx)], { concurrency: \"unbounded\" }))\n }\n\n const ingress = Ingress.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: { ...input.annotations, ...input.ingress.annotations },\n ingressClassName: input.ingress.ingressClassName,\n rules: input.ingress.rules,\n tls: input.ingress.tls\n })\n\n return M.make((ctx) =>\n Effect.all([deployment.render(ctx), service.render(ctx), ingress.render(ctx)], {\n concurrency: \"unbounded\"\n })\n )\n}\n\ninterface CronInput {\n readonly name: string\n readonly namespace: string\n readonly schedule: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly concurrencyPolicy?: \"Allow\" | \"Forbid\" | \"Replace\"\n readonly successfulJobsHistoryLimit?: number\n readonly failedJobsHistoryLimit?: number\n readonly containers: ReadonlyArray<ContainerInput>\n readonly volumes?: ReadonlyArray<Volume>\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n readonly restartPolicy?: \"OnFailure\" | \"Never\"\n}\n\nexport const cron = (\n input: CronInput\n): Manifest.Manifest<readonly [K8sServiceAccount, K8sCronJob]> => {\n const selectorLabels = { app: input.name }\n\n const sa: Manifest.Manifest<K8sServiceAccount> = M.make<K8sServiceAccount>(() =>\n Effect.succeed({\n apiVersion: \"v1\",\n kind: \"ServiceAccount\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: input.annotations\n }\n })\n )\n\n const cronJob = CronJob.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: input.annotations,\n schedule: input.schedule,\n concurrencyPolicy: input.concurrencyPolicy,\n successfulJobsHistoryLimit: input.successfulJobsHistoryLimit,\n failedJobsHistoryLimit: input.failedJobsHistoryLimit,\n jobTemplate: {\n spec: {\n template: {\n metadata: { labels: selectorLabels },\n spec: {\n containers: input.containers,\n volumes: input.volumes,\n imagePullSecrets: input.imagePullSecrets,\n serviceAccountName: input.name,\n restartPolicy: input.restartPolicy ?? \"OnFailure\"\n }\n }\n }\n }\n })\n\n return M.make((ctx) => Effect.all([sa.render(ctx), cronJob.render(ctx)], { concurrency: \"unbounded\" }))\n}\n","export * as K8s from \"./.generated/k8s-types\"\nexport {\n Container,\n type ContainerInput,\n type ContainerSpec,\n type DefineContainerInput,\n type DefinedPod,\n type DefinePodInput,\n Pod,\n type PodSpecInput\n} from \"./container\"\nexport {\n type ContainerPort,\n type ContainerProtocol,\n type ExecAction,\n type GrpcAction,\n type HttpGetAction,\n type HttpHeader,\n type NamesOf,\n Port,\n type PortInput,\n type PortName,\n type ProbeTarget,\n type ServicePortSpec,\n type TcpSocketAction\n} from \"./ports\"\n\nexport {\n type ConfigMapEnvInput,\n EnvVar,\n type EnvVarSource,\n type RawEnvInput,\n type SecretEnvForPodInput,\n type SecretEnvInput,\n type ValueEnvInput\n} from \"./env\"\nexport {\n ConfigMap,\n type ConfigMapInput,\n type ConfigMapManifest,\n Namespace,\n type NamespaceInput,\n type NamespaceManifest,\n type SecretInput,\n type SecretManifest,\n ServiceAccount,\n type ServiceAccountInput,\n type ServiceAccountManifest\n} from \"./identity\"\nimport { Environment as _EnvironmentContract, runtime as envRuntime, Secret as _SecretContract } from \"@konfig.ts/env\"\nimport { bindEnvironment } from \"./environmentBind\"\nimport { Secret as _SecretIdentity } from \"./identity\"\nimport { bindSecret } from \"./secretBind\"\n\n/**\n * `Secret` value namespace — merges the env-contracts side (`define`)\n * with the K8s side (`make`, `bind`, identity helpers). Importing\n * `Secret` from `@konfig.ts/k8s` gives you the full surface:\n *\n * Secret.define({ name, namespace, env }) — env contract (from @konfig.ts/env)\n * Secret.make({ name, namespace, stringData }) — K8s Secret manifest\n * Secret.bind({ secret, backend, source }) — env-to-manifest binder\n */\nexport const Secret = { ..._SecretContract, ..._SecretIdentity, bind: bindSecret }\n\n/**\n * `Environment` value namespace — merges `define` (env-contracts) with\n * `bind` + `runtime` (K8s). The same `Environment` symbol carries the\n * declaration, the manifest binder, and the runtime decoder.\n */\nexport const Environment = {\n ..._EnvironmentContract,\n bind: bindEnvironment,\n runtime: envRuntime\n}\nexport { type BackendEmitInput, BackendSourceMissing, type BackendTag, type SecretBackend } from \"./backend\"\nexport type {\n BindEnvironmentInput,\n DeclaredDownward,\n DeclaredEnvironment,\n DeclaredLiteral,\n DeclaredMember,\n HasSecrets,\n SecretMemberOptions,\n SecretMemberOptionsFor,\n SecretMembersOpts\n} from \"./environmentBind\"\nexport { NativeSecret, type NativeSecretOptions } from \"./nativeSecret\"\nexport {\n Ingress,\n type IngressInput,\n type IngressTLSInput,\n Service,\n type ServiceFromContainerInput,\n type ServiceFromPodSetInput,\n type ServiceInput\n} from \"./network\"\nexport { hashSecretValues, type HashSecretValuesInput } from \"./podHash\"\nexport {\n ClusterRole,\n ClusterRoleBinding,\n type ClusterRoleBindingInput,\n type ClusterRoleInput,\n NetworkPolicy,\n type NetworkPolicyEgressRule,\n type NetworkPolicyFromPodSetInput,\n type NetworkPolicyIngressRule,\n type NetworkPolicyInput,\n type NetworkPolicyPeer,\n PersistentVolume,\n PersistentVolumeClaim,\n type PersistentVolumeClaimInput,\n type PersistentVolumeInput,\n Role,\n RoleBinding,\n type RoleBindingInput,\n type RoleInput\n} from \"./policy\"\nexport type { ConfigMapRefName, PvcRefName, SecretRefName } from \"./refs\"\nexport { ConfigMapRef, PvcRef, SecretRef, ServiceAccountRef } from \"./refs\"\nexport type { BindSecretInput, DeclaredSecret } from \"./secretBind\"\nexport { Volume } from \"./volume\"\nexport type {\n EmptyVolumeInput,\n VolumeFromConfigMapInput,\n VolumeFromPvcInput,\n VolumeFromSecretInput,\n VolumeMount,\n VolumeName,\n VolumeNamesOf\n} from \"./volume\"\nexport {\n CronJob,\n type CronJobInput,\n Deployment,\n type DeploymentFromPodSetInput,\n type DeploymentInput,\n Job,\n type JobInput,\n StatefulSet,\n type StatefulSetInput\n} from \"./workload\"\n\nexport { type DefinePodSetInput, PodSet } from \"./podSet\"\nexport { Selector } from \"./selector\"\nexport type { SelectorLabels } from \"./selector\"\nexport * as Workload from \"./workloadHelpers\"\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["ServiceAccountRefValue","ConfigMapRefValue","Secret","SecretRefValue","L","SecretRefValue","M","_SecretContract","_SecretIdentity","_EnvironmentContract","envRuntime"],"sources":["../src/.generated/k8s-types/index.ts","../src/container.ts","../src/ports.ts","../src/env.ts","../src/refs.ts","../src/identity.ts","../src/secretBind.ts","../src/environmentBind.ts","../src/nativeSecret.ts","../src/network.ts","../src/podHash.ts","../src/policy.ts","../src/volume.ts","../src/workload.ts","../src/podSet.ts","../src/selector.ts","../src/workloadHelpers.ts","../src/index.ts"],"sourcesContent":["// Pinned re-export of Kubernetes API types. The directory name is\n// historical — we don't regenerate from OpenAPI; we re-export the\n// pinned `kubernetes-types` package, which is itself a stable mirror\n// of the upstream Kubernetes Go types.\n//\n// Version policy: `kubernetes-types` is pinned to an exact patch\n// version in packages/k8s/package.json — no caret. The minor\n// (currently 1.30) tracks the cluster minor we test against. Bumping\n// is intentional: read upstream release notes, run `bun run check &&\n// bun run test`, and update CHANGELOG.\n//\n// Each export here is the K8s API type as-is. konfig wrappers (e.g.\n// `ContainerInput` in container.ts) accept a wider, branded shape\n// and lower into these types when emitting manifests.\n\nexport type {\n Deployment,\n DeploymentSpec,\n DeploymentStrategy,\n StatefulSet,\n StatefulSetSpec,\n StatefulSetUpdateStrategy\n} from \"kubernetes-types/apps/v1\"\n\nexport type { CronJob, Job, JobSpec } from \"kubernetes-types/batch/v1\"\nexport type {\n ConfigMap,\n Container,\n ContainerPort,\n EnvVar,\n EnvVarSource,\n LocalObjectReference,\n Namespace,\n PersistentVolume,\n PersistentVolumeClaim,\n PodSpec,\n PodTemplateSpec,\n Secret,\n Service,\n ServiceAccount,\n ServicePort,\n Volume,\n VolumeMount\n} from \"kubernetes-types/core/v1\"\nexport type { ObjectMeta } from \"kubernetes-types/meta/v1\"\nexport type { Ingress, IngressRule, IngressSpec, IngressTLS, NetworkPolicy } from \"kubernetes-types/networking/v1\"\nexport type { ClusterRole, ClusterRoleBinding, Role, RoleBinding } from \"kubernetes-types/rbac/v1\"\n","import type { BuiltImageRef, SecretRef, ServiceAccountRef } from \"@konfig.ts/core\"\nimport { unsafeCoerce } from \"@konfig.ts/core\"\nimport type { Container as K8sContainer, PodSpec as K8sPodSpec } from \"./.generated/k8s-types\"\nimport type { EnvVar } from \"./env\"\nimport type { ContainerPort, NamesOf, ProbeTarget } from \"./ports\"\nimport type { Volume, VolumeMount, VolumeNamesOf } from \"./volume\"\n\n/**\n * Container input — extends the full K8s Container API. Konfig's\n * branded helpers (`EnvVar.value`, `EnvVar.fromSecret`,\n * `EnvVar.fromConfigMap`) produce `EnvVar` instances whose runtime\n * shape matches `K8sEnvVar`; the override\n * here narrows the field to readonly + the branded helper output so\n * `secretKeyRef.name` carries its `SecretRef<N>` brand at construction\n * time.\n *\n * `image` is overridden as required (K8s lets it be optional for\n * higher-level controllers that default it; konfig wants every\n * container to have an explicit image).\n *\n * `ports[i].name` accepts the branded `PortName<string>` from `Port.make(...)`\n * as well as a raw string; the typed builder `Container` is the\n * link that captures the literal name union for cross-reference checks.\n */\nexport interface ContainerInput extends\n Omit<\n K8sContainer,\n | \"env\"\n | \"image\"\n | \"ports\"\n | \"readinessProbe\"\n | \"livenessProbe\"\n | \"startupProbe\"\n | \"volumeMounts\"\n >\n{\n /**\n * Container image. Accepts a raw string (escape hatch for vendor\n * images: `ghcr.io/bitnami/postgresql:16.0.0`) or a `BuiltImageRef<App>`\n * produced by `Dep.builtImageRef` / `Dep.provideImage`. The branded\n * path ties the workload into the dep graph — a workload referencing\n * an image whose build module isn't in the composition fails at\n * `AppOfApps.entrypoint`.\n */\n readonly image: string | BuiltImageRef<string>\n readonly env?: ReadonlyArray<EnvVar>\n readonly ports?: ReadonlyArray<\n ContainerPort | {\n readonly containerPort: number\n readonly name?: string\n readonly protocol?: \"TCP\" | \"UDP\" | \"SCTP\"\n }\n >\n /**\n * Probes accept either the upstream K8s shape or konfig's branded\n * `ProbeTarget<string>` (from `Container`). The two are\n * structurally close — the union lets a `ContainerSpec` flow\n * through `Workload.web`'s containers slot without a cast.\n */\n readonly readinessProbe?: K8sContainer[\"readinessProbe\"] | ProbeTarget<string>\n readonly livenessProbe?: K8sContainer[\"livenessProbe\"] | ProbeTarget<string>\n readonly startupProbe?: K8sContainer[\"startupProbe\"] | ProbeTarget<string>\n /**\n * Volume mounts accept the upstream K8s shape or konfig's branded\n * `VolumeMount<string>` (from `Container` / `mountRef`). Same\n * rationale as the probe widening above.\n */\n readonly volumeMounts?:\n | K8sContainer[\"volumeMounts\"]\n | ReadonlyArray<VolumeMount<string>>\n}\n\n/**\n * Strongly-typed container builder. Captures the union of named ports\n * declared via `port({ name, containerPort })` as a phantom type\n * parameter, then constrains every probe's `port` field to that union.\n *\n * Pair with `Service.fromContainer({ forContainer })` in `network.ts`\n * to link a Service's `targetPort` to the same union — a typo or\n * undeclared port name is a compile error.\n */\nexport interface ContainerSpec<Ports extends string = string, Mounts extends string = string> extends\n Omit<\n ContainerInput,\n \"ports\" | \"readinessProbe\" | \"livenessProbe\" | \"startupProbe\" | \"volumeMounts\"\n >\n{\n readonly name: string\n readonly image: string\n readonly ports: ReadonlyArray<ContainerPort<Ports>>\n readonly readinessProbe?: ProbeTarget<Ports>\n readonly livenessProbe?: ProbeTarget<Ports>\n readonly startupProbe?: ProbeTarget<Ports>\n readonly volumeMounts?: ReadonlyArray<VolumeMount<Mounts>>\n readonly __portNames?: Ports\n readonly __mountNames?: Mounts\n}\n\nexport interface DefineContainerInput<\n Ports extends ReadonlyArray<ContainerPort<string>>,\n Mounts extends ReadonlyArray<VolumeMount<string>>,\n Envs extends ReadonlyArray<EnvVar<string>>\n> extends\n Omit<\n ContainerInput,\n \"ports\" | \"readinessProbe\" | \"livenessProbe\" | \"startupProbe\" | \"volumeMounts\" | \"env\"\n >\n{\n readonly name: string\n readonly image: string\n readonly ports: Ports\n readonly readinessProbe?: ProbeTarget<NamesOf<Ports>>\n readonly livenessProbe?: ProbeTarget<NamesOf<Ports>>\n readonly startupProbe?: ProbeTarget<NamesOf<Ports>>\n readonly volumeMounts?: Mounts\n readonly env?: Envs & EnvDupCheck<Envs>\n}\n\ntype MountNamesOf<M extends ReadonlyArray<VolumeMount<string>>> = {\n readonly [I in keyof M]: M[I] extends VolumeMount<infer N> ? N : never\n}[number]\n\ntype _EnvNameOf<X> = X extends EnvVar<infer N> ? N : never\n\n/**\n * Union of any literal env-var names that appear more than once in `Envs`.\n * Computes the intersection of pairwise names — if `Envs[I]` and `Envs[J]`\n * share a literal name (i ≠ j), that name leaks into the union. Empty\n * when every name is unique.\n */\ntype DuplicateEnvNames<Envs extends ReadonlyArray<EnvVar<string>>> = {\n [I in keyof Envs]: {\n [J in keyof Envs]: J extends I ? never\n : _EnvNameOf<Envs[I]> & _EnvNameOf<Envs[J]> extends never ? never\n : _EnvNameOf<Envs[I]> & _EnvNameOf<Envs[J]>\n }[number]\n}[number]\n\n/**\n * Empty (`unknown`) when `Envs` has no duplicate names; otherwise an\n * inline object type whose required `_konfig_duplicate_env_names`\n * property carries a template-literal hint sentence. Intersected with\n * the `env` slot, an unmet property surfaces the sentence inline in the\n * TS error — far more discoverable than a runtime \"last-wins\" surprise.\n */\ntype EnvDupCheck<Envs extends ReadonlyArray<EnvVar<string>>> = [DuplicateEnvNames<Envs>] extends [never] ? unknown\n : {\n readonly _konfig_duplicate_env_names: `Duplicate env name(s): \"${DuplicateEnvNames<\n Envs\n >}\". K8s silently last-wins; rename one of the colliding entries or remove the manual valueEnv that shadows another producer.`\n }\n\n/**\n * `Container` value namespace.\n *\n * const apiContainer = Container.define({\n * name: \"api\",\n * image: apiImage,\n * ports: [Port.make({ name: \"http\", containerPort: 8080 })],\n * readinessProbe: { httpGet: { port: Port.ref(\"http\") } },\n * env: [...],\n * });\n *\n * `Container.define` captures the union of named ports (from\n * `Port.make`) as `Ports`, the union of mounted volume names (from\n * `Volume.mountRef`) as `Mounts`, and validates that the `env` list\n * has no duplicate env-var names. The first two phantoms travel on\n * `ContainerSpec`; `Pod.define` checks the container's Mounts against\n * the pod's declared volume names.\n *\n * Duplicate env names are caught at the call site via a template-literal\n * error message — see `EnvDupCheck`. With no volumeMounts and no env,\n * all phantoms collapse to `never` so the container slots into any pod.\n */\nexport const Container = {\n define: <\n const Ports extends ReadonlyArray<ContainerPort<string>>,\n const Mounts extends ReadonlyArray<VolumeMount<string>> = readonly [],\n const Envs extends ReadonlyArray<EnvVar<string>> = readonly []\n >(\n input: DefineContainerInput<Ports, Mounts, Envs>\n ): ContainerSpec<NamesOf<Ports>, MountNamesOf<Mounts>> => {\n type P = NamesOf<Ports>\n type M = MountNamesOf<Mounts>\n const out: ContainerSpec<P, M> = {\n ...input,\n ports: unsafeCoerce<ReadonlyArray<ContainerPort<P>>>(\n input.ports,\n \"Ports tuple's element brands are the same PortName<N>; widening Ports → readonly ContainerPort<P>[] only changes the static shape, not the runtime values\"\n ),\n readinessProbe: input.readinessProbe,\n livenessProbe: input.livenessProbe,\n startupProbe: input.startupProbe,\n volumeMounts: unsafeCoerce<ReadonlyArray<VolumeMount<M>> | undefined>(\n input.volumeMounts,\n \"Mounts tuple's element brands are the same VolumeMount<N>; widening Mounts → readonly VolumeMount<M>[] preserves runtime shape\"\n ),\n env: unsafeCoerce<ReadonlyArray<EnvVar<string>> | undefined>(\n input.env,\n \"EnvDupCheck<Envs> intersection vanishes at runtime; the runtime value is the original EnvVar[]\"\n )\n }\n return out\n }\n}\n\n/**\n * `Pod.define` input. The pod declares a tuple of `Volume`s and lists\n * containers whose `Mounts` phantom is checked against the declared\n * volume names via `NoInfer`. A container referencing an undeclared\n * volume — or a typo — fails at the call site rather than at pod-startup\n * time with \"container references volume not found.\"\n */\nexport interface DefinePodInput<V extends ReadonlyArray<Volume<string>>> {\n readonly volumes: V\n readonly containers: ReadonlyArray<ContainerSpec<string, NoInfer<VolumeNamesOf<V>>>>\n readonly initContainers?: ReadonlyArray<ContainerSpec<string, NoInfer<VolumeNamesOf<V>>>>\n}\n\nexport interface DefinedPod<MountNames extends string> {\n readonly volumes: ReadonlyArray<Volume<MountNames>>\n readonly containers: ReadonlyArray<ContainerSpec<string, MountNames>>\n readonly initContainers?: ReadonlyArray<ContainerSpec<string, MountNames>>\n}\n\n/**\n * Pod spec input — extends K8s PodSpec but tightens the fields where\n * konfig adds brand checking: `imagePullSecrets`, `serviceAccountName`,\n * and `volumes` (the helpers in `volume.ts` produce konfig `Volume`\n * objects that lower to K8s `Volume`).\n */\nexport interface PodSpecInput extends\n Omit<\n K8sPodSpec,\n | \"containers\"\n | \"initContainers\"\n | \"volumes\"\n | \"imagePullSecrets\"\n | \"serviceAccountName\"\n >\n{\n readonly containers: ReadonlyArray<ContainerInput>\n readonly initContainers?: ReadonlyArray<ContainerInput>\n readonly volumes?: ReadonlyArray<Volume>\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n readonly serviceAccountName?: ServiceAccountRef<string> | string\n}\n\n/**\n * `Pod` value namespace.\n *\n * const pod = Pod.define({\n * volumes: [Volume.empty({ name: \"config\" })],\n * containers: [Container.define({ ..., volumeMounts: [...] })],\n * });\n *\n * imagePullSecrets: [Pod.imagePullSecret(ghcrRef)],\n *\n * - `Pod.define(input)` ties container `volumeMounts[i].name` to the\n * pod's declared volume names via `NoInfer`.\n * - `Pod.imagePullSecret(ref)` returns the `{ name: SecretRef }` entry\n * consumed by Deployment / StatefulSet / Job / CronJob workloads.\n */\nexport const Pod = {\n define: <const V extends ReadonlyArray<Volume<string>>>(\n input: DefinePodInput<V>\n ): DefinedPod<VolumeNamesOf<V>> => ({\n volumes: unsafeCoerce<ReadonlyArray<Volume<VolumeNamesOf<V>>>>(\n input.volumes,\n \"V tuple's elements are Volume<N>; widening V → readonly Volume<VolumeNamesOf<V>>[] is a structural relaxation, runtime value unchanged\"\n ),\n containers: input.containers,\n initContainers: input.initContainers\n }),\n imagePullSecret: (ref: SecretRef<string>): { readonly name: SecretRef<string> } => ({\n name: ref\n })\n}\n","import { brand } from \"@konfig.ts/core\"\n\n/**\n * Branded port name — a string carrying the literal `N` in its type.\n * Constructed by `Port.make({ name, containerPort })` and `Port.ref(name)`.\n * The brand lets probes and Service `targetPort` constrain their\n * `port` field to a member of the container's declared port-name union\n * rather than `string`.\n */\ndeclare const PortNameBrand: unique symbol\nexport type PortName<N extends string> = string & {\n readonly [PortNameBrand]: N\n}\n\nconst _portName = <const N extends string>(name: N): PortName<N> => brand<PortName<N>>(name)\n\nexport type ContainerProtocol = \"TCP\" | \"UDP\" | \"SCTP\"\n\nexport interface ContainerPort<N extends string = string> {\n readonly containerPort: number\n readonly name?: PortName<N>\n readonly protocol?: ContainerProtocol\n readonly hostPort?: number\n readonly hostIP?: string\n}\n\nexport interface PortInput<N extends string> {\n readonly name: N\n readonly containerPort: number\n readonly protocol?: ContainerProtocol\n readonly hostPort?: number\n readonly hostIP?: string\n}\n\n/**\n * `Port` value namespace.\n *\n * ports: [Port.make({ name: \"http\", containerPort: 8080 })],\n * readinessProbe: { httpGet: { port: Port.ref(\"http\") } },\n *\n * - `Port.make(input)` constructs a named container port; the literal\n * `name` is captured in the returned `ContainerPort<N>` brand so\n * `Container` can infer the port-name union and constrain\n * cross-references (probes, Service.targetPort).\n * - `Port.ref(name)` returns the brand alone, for probe targets and\n * `targetPort` references that need to name an existing declared port.\n */\nexport const Port = {\n make: <const N extends string>(input: PortInput<N>): ContainerPort<N> => ({\n containerPort: input.containerPort,\n name: _portName(input.name),\n protocol: input.protocol,\n hostPort: input.hostPort,\n hostIP: input.hostIP\n }),\n ref: <const N extends string>(name: N): PortName<N> => _portName(name)\n}\n\nexport interface HttpHeader {\n readonly name: string\n readonly value: string\n}\n\nexport interface HttpGetAction<Ports extends string> {\n readonly path?: string\n readonly port: number | PortName<Ports>\n readonly host?: string\n readonly scheme?: \"HTTP\" | \"HTTPS\"\n readonly httpHeaders?: ReadonlyArray<HttpHeader>\n}\n\nexport interface TcpSocketAction<Ports extends string> {\n readonly port: number | PortName<Ports>\n readonly host?: string\n}\n\nexport interface GrpcAction<Ports extends string> {\n readonly port: number | PortName<Ports>\n readonly service?: string\n}\n\nexport interface ExecAction {\n readonly command: ReadonlyArray<string>\n}\n\n/**\n * Probe target — `port` references on httpGet/tcpSocket/grpc are\n * constrained to `Ports`, the union of names declared on the owning\n * container. A bare number is always accepted; only the named variant\n * is checked.\n */\nexport interface ProbeTarget<Ports extends string> {\n readonly httpGet?: HttpGetAction<Ports>\n readonly tcpSocket?: TcpSocketAction<Ports>\n readonly grpc?: GrpcAction<Ports>\n readonly exec?: ExecAction\n readonly initialDelaySeconds?: number\n readonly periodSeconds?: number\n readonly timeoutSeconds?: number\n readonly successThreshold?: number\n readonly failureThreshold?: number\n readonly terminationGracePeriodSeconds?: number\n}\n\nexport type NamesOf<P extends ReadonlyArray<unknown>> = {\n readonly [K in keyof P]: P[K] extends ContainerPort<infer N> ? N : never\n}[number]\n\n/**\n * Service-port input bound to a container's port-name union. `targetPort`\n * accepts a bare number or a `PortName<Ports>`. The `Ports` parameter is\n * locked by `forContainer` on `Service.fromContainer`; use `Port.ref(name)`\n * to reference declared ports.\n */\nexport interface ServicePortSpec<Ports extends string> {\n readonly name?: string\n readonly port: number\n readonly targetPort: number | PortName<Ports>\n readonly protocol?: ContainerProtocol\n readonly appProtocol?: string\n readonly nodePort?: number\n}\n","import type { ConfigMapRef, SecretRef } from \"@konfig.ts/core\"\n\nexport interface EnvVarSource {\n readonly secretKeyRef?: {\n readonly name: SecretRef<string>\n readonly key: string\n readonly optional?: boolean\n }\n readonly configMapKeyRef?: {\n readonly name: ConfigMapRef<string>\n readonly key: string\n readonly optional?: boolean\n }\n readonly fieldRef?: { readonly fieldPath: string; readonly apiVersion?: string }\n readonly resourceFieldRef?: { readonly containerName?: string; readonly resource: string }\n}\n\n/**\n * Container env-var entry. The phantom `N` records the literal env-var\n * name at the type level so `Container` can detect duplicates\n * across the entry list. The default `N = string` preserves loose-typed\n * call sites.\n */\nexport interface EnvVarShape<N extends string = string> {\n readonly name: N\n readonly value?: string\n readonly valueFrom?: EnvVarSource\n}\n\nexport interface ValueEnvInput<N extends string> {\n readonly name: N\n readonly value: string\n}\n\nexport interface SecretEnvInput<EnvName extends string, N extends string, K extends string> {\n readonly name: EnvName\n readonly ref: SecretRef<N, K>\n /**\n * Constrained to the keys carried by `ref`. `NoInfer` locks `K` to\n * whatever the ref declares, so the typo `key: \"passowrd\"` fails at\n * compile time when the ref's K is `\"url\" | \"username\" | \"password\"`.\n * Refs constructed with the default `K = string` accept any string.\n */\n readonly key: NoInfer<K>\n readonly optional?: boolean\n}\n\nexport interface SecretEnvForPodInput<\n EnvName extends string,\n N extends string,\n K extends string,\n Ns extends string\n> {\n readonly name: EnvName\n /**\n * Ref whose namespace slot must match `podNamespace`. Pass refs that\n * came from `Secret.make({ namespace })` in the same namespace as\n * the consuming pod. For legitimate cross-namespace cases, widen\n * via `SecretRef.unsafeReNamespace(ref)` first.\n */\n readonly ref: SecretRef<N, K, NoInfer<Ns>>\n readonly key: NoInfer<K>\n readonly podNamespace: Ns\n readonly optional?: boolean\n}\n\nexport interface ConfigMapEnvInput<EnvName extends string, N extends string, K extends string> {\n readonly name: EnvName\n readonly ref: ConfigMapRef<N, K>\n /**\n * Constrained to the keys carried by `ref`. `NoInfer` locks `K` to\n * whatever the ref declares — typos like `key: \"passwrod\"` fail at\n * compile time when the ref's K is `\"HOST\" | \"PORT\" | \"LOG_LEVEL\"`.\n * Refs constructed with the default `K = string` accept any string.\n */\n readonly key: NoInfer<K>\n readonly optional?: boolean\n}\n\nexport interface RawEnvInput<N extends string> {\n readonly name: N\n readonly value?: string\n readonly valueFrom?: EnvVarSource\n}\n\n/**\n * `EnvVar` value namespace.\n *\n * env: [\n * EnvVar.value({ name: \"PORT\", value: \"8080\" }),\n * EnvVar.fromSecret({ name: \"DB_URL\", ref: dbCreds.ref, key: \"url\" }),\n * EnvVar.fromSecretForPod({\n * name: \"DB_URL_PRIMARY\", ref: dbCreds.ref, key: \"url\",\n * podNamespace: \"app\",\n * }),\n * EnvVar.fromConfigMap({ name: \"NEW_UI\", ref: flags.ref, key: \"NEW_UI\" }),\n * EnvVar.raw({ name: \"POD_NAME\", valueFrom: { fieldRef: ... } }),\n * ]\n *\n * Each constructor captures the literal env-var name (`N`) so\n * `Container` can detect duplicate entries across the env list.\n */\nexport const EnvVar = {\n value: <const N extends string>(input: ValueEnvInput<N>): EnvVar<N> => ({\n name: input.name,\n value: input.value\n }),\n fromSecret: <const EnvName extends string, N extends string, K extends string = string>(\n input: SecretEnvInput<EnvName, N, K>\n ): EnvVar<EnvName> => ({\n name: input.name,\n valueFrom: {\n secretKeyRef: { name: input.ref, key: input.key, optional: input.optional }\n }\n }),\n /**\n * Namespace-checked variant. The ref's namespace slot (`Ns`) must\n * match `podNamespace`. Catches \"pod in namespace A references a\n * Secret in namespace B\" at compile time — kube-apiserver only\n * resolves `valueFrom.secretKeyRef` against the pod's own namespace,\n * so cross-namespace refs are runtime errors.\n */\n fromSecretForPod: <\n const EnvName extends string,\n N extends string,\n K extends string,\n const Ns extends string\n >(\n input: SecretEnvForPodInput<EnvName, N, K, Ns>\n ): EnvVar<EnvName> => ({\n name: input.name,\n valueFrom: {\n secretKeyRef: { name: input.ref, key: input.key, optional: input.optional }\n }\n }),\n fromConfigMap: <const EnvName extends string, N extends string, K extends string = string>(\n input: ConfigMapEnvInput<EnvName, N, K>\n ): EnvVar<EnvName> => ({\n name: input.name,\n valueFrom: {\n configMapKeyRef: { name: input.ref, key: input.key, optional: input.optional }\n }\n }),\n raw: <const N extends string>(input: RawEnvInput<N>): EnvVar<N> => input\n}\n\n// Alias the shape interface as the user-facing `EnvVar<N>` type. The\n// namespace `EnvVar` (value) and the type `EnvVar<N>` share a name —\n// TypeScript merges them.\nexport type EnvVar<N extends string = string> = EnvVarShape<N>\n","import {\n brand,\n type ConfigMapRef as CMRef,\n type PvcRef as PRef,\n type SecretRef as SRef,\n type ServiceAccountRef as SARef\n} from \"@konfig.ts/core\"\n\nexport type SecretRef<\n N extends string = string,\n K extends string = string,\n Ns extends string = string\n> = SRef<N, K, Ns>\nexport type ConfigMapRef<N extends string = string, K extends string = string> = CMRef<N, K>\nexport type ServiceAccountRef<N extends string = string> = SARef<N>\nexport type PvcRef<N extends string = string> = PRef<N>\nexport type { ConfigMapRefKeys, ConfigMapRefName, PvcRefName, SecretRefKeys, SecretRefName } from \"@konfig.ts/core\"\nexport type { SecretRefNamespace } from \"@konfig.ts/core\"\n\nexport const SecretRef = {\n of: <N extends string, K extends string = string, Ns extends string = string>(\n name: N\n ): SecretRef<N, K, Ns> => brand<SecretRef<N, K, Ns>>(name),\n /**\n * Escape hatch — widen a typed ref's namespace slot to `any`, making\n * it usable across any pod context. Use sparingly (legitimate\n * cross-namespace cases: ExternalSecret reflection, in-cluster\n * shared infra). The cast is grep-able so PR reviewers see opt-ins.\n */\n // oxlint-disable-next-line app/no-type-assertion\n unsafeReNamespace: <N extends string, K extends string>(\n // oxlint-disable-next-line app/no-type-assertion\n ref: SecretRef<N, K, any>\n // oxlint-disable-next-line app/no-type-assertion\n ): SecretRef<N, K, any> => ref\n}\n\nexport const ConfigMapRef = {\n of: <N extends string, K extends string = string>(name: N): ConfigMapRef<N, K> => brand<ConfigMapRef<N, K>>(name)\n}\n\nexport const ServiceAccountRef = {\n of: <N extends string>(name: N): ServiceAccountRef<N> => brand<ServiceAccountRef<N>>(name)\n}\n\nexport const PvcRef = {\n of: <N extends string>(name: N): PvcRef<N> => brand<PvcRef<N>>(name)\n}\n","import type { ConfigMapRef, SecretRef, ServiceAccountRef } from \"@konfig.ts/core\"\nimport { Manifest } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n ConfigMap as K8sConfigMap,\n Namespace as K8sNamespace,\n Secret as K8sSecret,\n ServiceAccount as K8sServiceAccount\n} from \"./.generated/k8s-types\"\nimport {\n ConfigMapRef as ConfigMapRefValue,\n SecretRef as SecretRefValue,\n ServiceAccountRef as ServiceAccountRefValue\n} from \"./refs\"\n\ntype CommonMeta = {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\nexport interface NamespaceInput<N extends string> extends CommonMeta {\n readonly name: N\n}\n\nexport interface NamespaceManifest<N extends string> extends Manifest.Manifest<K8sNamespace> {\n readonly ref: N\n}\n\nexport const Namespace = {\n make: <N extends string>(input: NamespaceInput<N>): NamespaceManifest<N> => {\n const resource: K8sNamespace = {\n apiVersion: \"v1\",\n kind: \"Namespace\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n }\n }\n const m = Manifest.make<K8sNamespace>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: input.name })\n }\n}\n\nexport interface ServiceAccountInput<N extends string> extends CommonMeta {\n readonly name: N\n readonly namespace: string\n readonly automountServiceAccountToken?: boolean\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n}\n\nexport interface ServiceAccountManifest<N extends string> extends Manifest.Manifest<K8sServiceAccount> {\n readonly ref: ServiceAccountRef<N>\n}\n\nexport const ServiceAccount = {\n make: <N extends string>(input: ServiceAccountInput<N>): ServiceAccountManifest<N> => {\n const resource: K8sServiceAccount = {\n apiVersion: \"v1\",\n kind: \"ServiceAccount\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n automountServiceAccountToken: input.automountServiceAccountToken,\n imagePullSecrets: input.imagePullSecrets?.map((s) => ({ name: s.name }))\n }\n const m = Manifest.make<K8sServiceAccount>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: ServiceAccountRefValue.of(input.name) })\n }\n}\n\nexport interface ConfigMapInput<N extends string, K extends string = string> extends CommonMeta {\n readonly name: N\n readonly namespace: string\n readonly data?: Readonly<Record<K, string>>\n readonly binaryData?: Readonly<Record<K, string>>\n readonly immutable?: boolean\n}\n\nexport interface ConfigMapManifest<N extends string, K extends string = string>\n extends Manifest.Manifest<K8sConfigMap>\n{\n readonly ref: ConfigMapRef<N, K>\n}\n\nexport const ConfigMap = {\n make: <const N extends string, const K extends string = string>(\n input: ConfigMapInput<N, K>\n ): ConfigMapManifest<N, K> => {\n const resource: K8sConfigMap = {\n apiVersion: \"v1\",\n kind: \"ConfigMap\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n data: input.data,\n binaryData: input.binaryData,\n immutable: input.immutable\n }\n const m = Manifest.make<K8sConfigMap>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: ConfigMapRefValue.of<N, K>(input.name) })\n }\n}\n\nexport interface SecretInput<\n N extends string,\n Ns extends string = string,\n K extends string = string\n> extends CommonMeta {\n readonly name: N\n readonly namespace: Ns\n readonly type?: string\n readonly data?: Readonly<Record<K, string>>\n readonly stringData?: Readonly<Record<K, string>>\n readonly immutable?: boolean\n}\n\nexport interface SecretManifest<\n N extends string,\n Ns extends string = string,\n K extends string = string\n> extends Manifest.Manifest<K8sSecret> {\n readonly ref: SecretRef<N, K, Ns>\n}\n\nexport const Secret = {\n make: <\n const N extends string,\n const Ns extends string = string,\n const K extends string = string\n >(\n input: SecretInput<N, Ns, K>\n ): SecretManifest<N, Ns, K> => {\n const resource: K8sSecret = {\n apiVersion: \"v1\",\n kind: \"Secret\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n type: input.type,\n data: input.data,\n stringData: input.stringData,\n immutable: input.immutable\n }\n const m = Manifest.make<K8sSecret>(() => Effect.succeed(resource))\n return Object.assign(m, { ref: SecretRefValue.of<N, K, Ns>(input.name) })\n }\n}\n","import { Dep, Manifest, RenderError, type SecretRef, unsafeCoerce } from \"@konfig.ts/core\"\nimport type { SecretEntry, SecretSource } from \"@konfig.ts/env\"\nimport { type Context, Effect, type Layer, Layer as L } from \"effect\"\nimport type { SecretBackend } from \"./backend\"\nimport { EnvVar } from \"./env\"\nimport { SecretRef as SecretRefValue } from \"./refs\"\n\ninterface _DeclaredSecretBase<N extends string, K extends string, Ns extends string> {\n readonly ref: SecretRef<N, K, Ns>\n readonly name: N\n readonly namespace: Ns\n readonly keys: ReadonlyArray<K>\n readonly envVars: ReadonlyArray<EnvVar>\n readonly manifest?: Manifest.Manifest<unknown>\n readonly refLayer: Layer.Layer<Dep.Provide<\"Secret\", N>>\n}\n\n// `values` and `layer` are populated together, iff a source was supplied\n// at bind time — a discriminated union instead of two independent\n// optionals so that can't drift into a \"values but no layer\" state.\ntype _SecretValuesFields<N extends string, K extends string> =\n | {\n readonly values: Context.Service<Dep.Need<\"SecretValues\", N>, Dep.SecretValuesRecord<K>>\n readonly layer: Layer.Layer<Dep.Provide<\"SecretValues\", N>, RenderError, Manifest.RenderServices>\n }\n | { readonly values?: undefined; readonly layer?: undefined }\n\nexport type DeclaredSecret<N extends string, K extends string, Ns extends string = string> =\n & _DeclaredSecretBase<N, K, Ns>\n & _SecretValuesFields<N, K>\n\nexport interface BindSecretInput<\n N extends string,\n K extends string,\n E extends Readonly<Record<K, string>>,\n Ns extends string = string\n> {\n readonly secret: SecretEntry<N, K, E>\n readonly backend?: SecretBackend<N, K>\n readonly source?: SecretSource<K, Manifest.RenderServices>\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n /**\n * Override the contract's baked-in `namespace` for this bind. Useful\n * when the same `Secret` declaration is consumed across multiple\n * k8s namespaces (e.g. prod / staging / local of the same workload)\n * — the runtime read is namespace-independent, but each binding emits\n * its manifest into a different namespace.\n *\n * When passed as a string literal (via `Environment.bind`'s\n * `const namespace`), the literal flows into the ref's brand so\n * `secretEnvForPod` can enforce cross-namespace coherence.\n */\n readonly namespace?: Ns\n}\n\ninterface _ValuesLayerInput<N extends string, K extends string> {\n readonly name: N\n readonly namespace: string\n readonly source: SecretSource<K, Manifest.RenderServices>\n}\n\nconst _buildValuesLayer = <N extends string, K extends string>(\n input: _ValuesLayerInput<N, K>\n): {\n readonly values: Context.Service<Dep.Need<\"SecretValues\", N>, Dep.SecretValuesRecord<K>>\n readonly layer: Layer.Layer<Dep.Provide<\"SecretValues\", N>, RenderError, Manifest.RenderServices>\n} => {\n const values = Dep.SecretValues<N, K>(input.name)\n const layer = L.effect(\n values,\n input.source.resolve.pipe(\n Effect.mapError(\n (cause) =>\n new RenderError({\n message: `SecretValues(${input.namespace}/${input.name}): source failed for key \"${cause.key}\"`,\n cause\n })\n )\n )\n )\n return { values, layer }\n}\n\nconst _buildEnvVars = <N extends string, K extends string, Ns extends string>(\n secret: SecretEntry<N, K, Readonly<Record<K, string>>>,\n ref: SecretRef<N, K, Ns>\n): EnvVar[] => secret.keys.map((key: K) => EnvVar.fromSecret({ name: secret.env[key], ref, key }))\n\n// `backend`'s RequiresSource is erased to `boolean` at this generic call\n// site, so the compiler can't prove `source` is present the way each\n// concrete backend's own `emit` does. Catch the hole at runtime and fail\n// through the Manifest's Effect channel instead of letting `emit` read\n// `undefined.resolve` and throw.\nconst _missingSourceManifest = (backend: { readonly _tag: string }, name: string, namespace: string) =>\n Manifest.make<unknown>(() =>\n Effect.fail(\n new RenderError({\n message: `backend \"${backend._tag}\" requires a source but none was provided for secret \"${namespace}/${name}\"`\n })\n )\n )\n\nexport const bindSecret = <\n N extends string,\n K extends string,\n E extends Readonly<Record<K, string>>,\n const Ns extends string = string\n>(\n input: BindSecretInput<N, K, E, Ns>\n): DeclaredSecret<N, K, Ns> => {\n const { secret } = input\n const namespace = unsafeCoerce<Ns>(\n input.namespace ?? secret.namespace,\n \"Ns defaults to `string`; the override (if present) is `Ns`, the secret's own namespace is `string` — runtime value either way is a string\"\n )\n const ref = SecretRefValue.of<N, K, Ns>(secret.name)\n const manifest = input.backend === undefined\n ? undefined\n : input.backend.requiresSource && input.source === undefined\n ? _missingSourceManifest(input.backend, secret.name, namespace)\n : input.backend.emit({\n name: secret.name,\n namespace,\n keys: secret.keys,\n labels: input.labels,\n annotations: input.annotations,\n source: input.source\n })\n\n const out: DeclaredSecret<N, K, Ns> = {\n ref,\n name: secret.name,\n namespace,\n keys: secret.keys,\n envVars: _buildEnvVars(secret, ref),\n manifest,\n refLayer: Dep.provideSecret(secret.name)\n }\n\n return input.source === undefined\n ? out\n : { ...out, ..._buildValuesLayer({ name: secret.name, namespace, source: input.source }) }\n}\n","import { type Manifest, type RenderError, unsafeCoerce } from \"@konfig.ts/core\"\nimport type {\n AnyEnvironment,\n DownwardEntry,\n Environment,\n EnvMember,\n LiteralEntry,\n SecretEntry,\n SecretSource\n} from \"@konfig.ts/env\"\nimport { Layer, Match } from \"effect\"\nimport type { SecretBackend } from \"./backend\"\nimport type { EnvVar } from \"./env\"\nimport { bindSecret, type DeclaredSecret } from \"./secretBind\"\n\nexport interface DeclaredLiteral<EnvName extends string, T> {\n readonly envName: EnvName\n readonly value: T\n readonly envVar: EnvVar\n}\n\nexport interface DeclaredDownward<EnvName extends string> {\n readonly envName: EnvName\n readonly fieldPath: string\n readonly envVar: EnvVar\n}\n\n/**\n * Per-member declared shape produced by `Environment.bind`. Mirrors the\n * structure of the bundle: secrets give `DeclaredSecret`, literals\n * `DeclaredLiteral`, downwards `DeclaredDownward`, and nested\n * `Environment` members give a `members` sub-record with the same\n * recursive shape.\n */\nexport type DeclaredMember<\n A extends EnvMember,\n Ns extends string = string\n> = A extends SecretEntry<infer N, infer K, infer _E> ? [N, K] extends [string, string] ? DeclaredSecret<N, K, Ns>\n : never\n : A extends LiteralEntry<infer EnvName, infer T> ? [EnvName] extends [string] ? DeclaredLiteral<EnvName, T>\n : never\n : A extends DownwardEntry<infer EnvName> ? [EnvName] extends [string] ? DeclaredDownward<EnvName>\n : never\n : A extends Environment<infer SubM> ? { readonly [K in keyof SubM]: DeclaredMember<SubM[K], Ns> }\n : never\n\nexport interface DeclaredEnvironment<\n M extends Readonly<Record<string, EnvMember>>,\n Ns extends string = string\n> {\n readonly envVars: ReadonlyArray<EnvVar>\n readonly manifests: ReadonlyArray<Manifest.Manifest<unknown>>\n readonly members: { readonly [K in keyof M]: DeclaredMember<M[K], Ns> }\n // merged values layer over every secret member with a source.\n readonly valuesLayer: Layer.Layer<unknown, RenderError, Manifest.RenderServices>\n}\n\ninterface _SecretMemberOptionsBase {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\ninterface _SecretMemberBackendRequiresSource<N extends string, K extends string> extends _SecretMemberOptionsBase {\n readonly backend: SecretBackend<N, K, true>\n readonly source: SecretSource<K, Manifest.RenderServices>\n}\n\ninterface _SecretMemberBackendOptionalSource<N extends string, K extends string> extends _SecretMemberOptionsBase {\n readonly backend: SecretBackend<N, K, false>\n readonly source?: SecretSource<K, Manifest.RenderServices>\n}\n\ninterface _SecretMemberSourceOnly<_N extends string, K extends string> extends _SecretMemberOptionsBase {\n readonly backend?: undefined\n readonly source: SecretSource<K, Manifest.RenderServices>\n}\n\n/**\n * Per-secret-member options at bind time. Backends with `RequiresSource: true`\n * (`Sops.backend`, `SealedSecrets.backend`, `NativeSecret.backend`) make\n * `source` mandatory at the type level. Backends with `false`\n * (`ExternalSecrets.backend`, `Sops.passthrough`) make it optional. With no\n * backend, `source` becomes mandatory — used to feed the in-process\n * `SecretValues` layer for tests / local renders.\n */\nexport type SecretMemberOptions<N extends string, K extends string> =\n | _SecretMemberBackendRequiresSource<N, K>\n | _SecretMemberBackendOptionalSource<N, K>\n | _SecretMemberSourceOnly<N, K>\n\nexport type SecretMemberOptionsFor<A> = A extends SecretEntry<infer N, infer K, infer _E>\n ? [N, K] extends [string, string] ? SecretMemberOptions<N, K>\n : never\n : never\n\n/**\n * True iff `M` (recursively, via nested `Environment` members)\n * contains at least one `SecretEntry`. Used to flip `secrets` between\n * required (any secrets present) and optional (literals/downwards\n * only) on `BindEnvironmentInput`.\n */\nexport type HasSecrets<M extends Readonly<Record<string, EnvMember>>> = true extends {\n readonly [K in keyof M]: M[K] extends SecretEntry<infer _N, infer _K, infer _E> ? true\n : M[K] extends Environment<infer Sub> ? HasSecrets<Sub>\n : false\n}[keyof M] ? true\n : false\n\n/**\n * Recursive per-member secret options. For a secret member, the option\n * matches its `SecretMemberOptionsFor` and is required. For a nested\n * `Environment` member that itself contains secrets, the option is\n * `SecretMembersOpts<SubM>` and is also required. Nested environments\n * with no secrets are omitted entirely (no key needed).\n *\n * Together with `HasSecrets`, this enforces at compile time that every\n * `Secret` reachable from the bundle is acknowledged at bind\n * time — adding a new secret to the env contract forces every call\n * site to update.\n */\nexport type SecretMembersOpts<M extends Readonly<Record<string, EnvMember>>> = {\n readonly [\n K in keyof M as M[K] extends SecretEntry<infer _N, infer _K, infer _E> ? K\n : M[K] extends Environment<infer SubM> ? HasSecrets<SubM> extends true ? K\n : never\n : never\n ]: M[K] extends SecretEntry<infer _N, infer _K, infer _E> ? SecretMemberOptionsFor<M[K]>\n : M[K] extends Environment<infer SubM> ? SecretMembersOpts<SubM>\n : never\n}\n\n/**\n * Per-literal value override for bind time. Keyed by member name, typed\n * to each literal's declared `T`. Useful when a `Literal` is a\n * runtime contract (carries a `schema: Config.string(envName)` for app\n * code to yield) but the manifest's emitted value differs per env —\n * e.g. `CLIENT_URL`, `S3_ENDPOINT`, host/URL literals.\n *\n * Recurses on nested `Environment` members — pass `{group: {host: \"x\"}}`\n * to override a literal nested inside a sub-bundle.\n */\nexport type LiteralMembersOpts<M extends Readonly<Record<string, EnvMember>>> = {\n readonly [\n K in keyof M as M[K] extends LiteralEntry<infer _EnvName, infer _T> ? K\n : M[K] extends Environment<infer _SubM> ? K\n : never\n ]?: M[K] extends LiteralEntry<infer _EnvName, infer T> ? T\n : M[K] extends Environment<infer SubM> ? LiteralMembersOpts<SubM>\n : never\n}\n\ninterface _BindEnvironmentInputBase<\n M extends Readonly<Record<string, EnvMember>>,\n Ns extends string = string\n> {\n readonly env: Environment<M>\n /**\n * Per-literal value override for the manifest's emitted env var. The\n * runtime read (via `entry.schema`, if provided) is unchanged —\n * overrides only affect what the konfig module writes into the\n * Deployment's `env` array.\n */\n readonly literals?: LiteralMembersOpts<M>\n /**\n * Override every secret member's namespace for this bind. Useful when\n * the bundle is consumed across multiple k8s namespaces (e.g. prod /\n * staging / local) without redeclaring each contract. Recurses into\n * nested `Environment` members.\n *\n * When passed as a string literal, the literal flows into each\n * `DeclaredSecret.ref`'s brand so `secretEnvForPod` can enforce\n * cross-namespace coherence on hand-spliced env entries.\n */\n readonly namespace?: Ns\n}\n\n/**\n * `secrets` flips between required and optional based on whether `M`\n * actually contains any secrets. A bundle of literals/downwards only\n * has nothing to bind, so `secrets` stays optional. A bundle with even\n * one `Secret` (directly or nested) forces the caller to supply\n * every secret member — and for each member, either a `backend` or a\n * `source` (see `SecretMemberOptions`).\n */\nexport type BindEnvironmentInput<\n M extends Readonly<Record<string, EnvMember>>,\n Ns extends string = string\n> =\n & _BindEnvironmentInputBase<M, Ns>\n & (HasSecrets<M> extends true ? { readonly secrets: SecretMembersOpts<M> }\n : { readonly secrets?: SecretMembersOpts<M> })\n\ninterface _BindLiteralInput {\n readonly entry: LiteralEntry<string, unknown>\n readonly override?: unknown\n}\nconst _bindLiteral = (input: _BindLiteralInput): DeclaredLiteral<string, unknown> => {\n const hasOverride = input.override !== undefined\n const value = hasOverride ? input.override : input.entry.value\n const serialized = hasOverride\n ? input.entry.serialize(input.override)\n : input.entry.serialized\n return {\n envName: input.entry.envName,\n value,\n envVar: { name: input.entry.envName, value: serialized }\n }\n}\n\ninterface _BindDownwardInput {\n readonly entry: DownwardEntry<string>\n}\nconst _bindDownward = (input: _BindDownwardInput): DeclaredDownward<string> => ({\n envName: input.entry.envName,\n fieldPath: input.entry.fieldPath,\n envVar: {\n name: input.entry.envName,\n valueFrom: { fieldRef: { fieldPath: input.entry.fieldPath } }\n }\n})\n\ntype _AnyValuesLayer = Layer.Layer<unknown, RenderError, Manifest.RenderServices>\n\ninterface _BindAcc {\n readonly declared: Record<string, unknown>\n readonly envVars: EnvVar[]\n readonly manifests: Manifest.Manifest<unknown>[]\n readonly valuesLayers: _AnyValuesLayer[]\n}\n\ninterface _DispatchInput {\n readonly memberKey: string\n readonly entry: EnvMember\n readonly secretsOpts: Record<string, unknown> | undefined\n readonly literalsOpts: Record<string, unknown> | undefined\n readonly namespace: string | undefined\n readonly acc: _BindAcc\n}\n\nconst _handleSecret = (input: _DispatchInput): void => {\n const memberOpts = unsafeCoerce<SecretMemberOptions<string, string> | undefined>(\n input.secretsOpts?.[input.memberKey],\n \"SecretMembersOpts<M> shape — runtime key lookup against the typed input\"\n )\n const secret = unsafeCoerce<SecretEntry<string, string, Readonly<Record<string, string>>>>(\n input.entry,\n \"Match.tag('Secret') narrowed entry to SecretEntry; the helper-level signature is the general SecretEntry shape\"\n )\n const d = bindSecret({\n secret,\n backend: memberOpts?.backend,\n source: memberOpts?.source,\n labels: memberOpts?.labels,\n annotations: memberOpts?.annotations,\n namespace: input.namespace\n })\n input.acc.declared[input.memberKey] = d\n input.acc.envVars.push(...d.envVars)\n if (d.manifest !== undefined) input.acc.manifests.push(d.manifest)\n if (d.layer !== undefined) {\n input.acc.valuesLayers.push(\n unsafeCoerce<_AnyValuesLayer>(\n d.layer,\n \"DeclaredSecret.layer is Layer<Provide<SecretValues, N>, ...>; widen to unknown for the heterogeneous Layer.mergeAll\"\n )\n )\n }\n}\n\nconst _handleLiteral = (input: _DispatchInput): void => {\n const literal = unsafeCoerce<LiteralEntry<string, unknown>>(\n input.entry,\n \"Match.tag('Literal') narrowed entry to LiteralEntry<string, unknown>\"\n )\n const d = _bindLiteral({ entry: literal, override: input.literalsOpts?.[input.memberKey] })\n input.acc.declared[input.memberKey] = d\n input.acc.envVars.push(d.envVar)\n}\n\nconst _handleDownward = (input: _DispatchInput): void => {\n const downward = unsafeCoerce<DownwardEntry<string>>(\n input.entry,\n \"Match.tag('Downward') narrowed entry to DownwardEntry<string>\"\n )\n const d = _bindDownward({ entry: downward })\n input.acc.declared[input.memberKey] = d\n input.acc.envVars.push(d.envVar)\n}\n\nconst _handleEnvironment = (input: _DispatchInput): void => {\n const subEnv = unsafeCoerce<AnyEnvironment>(\n input.entry,\n \"Match.tag('Environment') narrowed entry to a nested Environment\"\n )\n const sub = bindEnvironment({\n env: subEnv,\n secrets: unsafeCoerce<SecretMembersOpts<Readonly<Record<string, EnvMember>>>>(\n input.secretsOpts?.[input.memberKey] ?? {},\n \"sub-record from SecretMembersOpts<M> — type is checked at the outer call site\"\n ),\n literals: unsafeCoerce<LiteralMembersOpts<Readonly<Record<string, EnvMember>>>>(\n input.literalsOpts?.[input.memberKey] ?? {},\n \"sub-record from LiteralMembersOpts<M> — type is checked at the outer call site\"\n ),\n namespace: input.namespace\n })\n input.acc.declared[input.memberKey] = sub.members\n input.acc.envVars.push(...sub.envVars)\n input.acc.manifests.push(...sub.manifests)\n input.acc.valuesLayers.push(\n unsafeCoerce<_AnyValuesLayer>(\n sub.valuesLayer,\n \"valuesLayer aggregate over the recursive merge\"\n )\n )\n}\n\nconst _dispatch = (input: _DispatchInput): void =>\n Match.value(input.entry._kind).pipe(\n Match.when(\"Secret\", () => _handleSecret(input)),\n Match.when(\"Literal\", () => _handleLiteral(input)),\n Match.when(\"Downward\", () => _handleDownward(input)),\n Match.when(\"Environment\", () => _handleEnvironment(input)),\n Match.exhaustive\n )\n\ninterface _DispatchAllInput {\n readonly env: AnyEnvironment\n readonly secretsOpts: Record<string, unknown> | undefined\n readonly literalsOpts: Record<string, unknown> | undefined\n readonly namespace: string | undefined\n readonly acc: _BindAcc\n}\n\nconst _dispatchAllMembers = (input: _DispatchAllInput): void => {\n for (const memberKey of Object.keys(input.env.members)) {\n const entry = unsafeCoerce<EnvMember>(\n input.env.members[memberKey],\n \"env.members values are EnvMember by construction\"\n )\n _dispatch({\n memberKey,\n entry,\n secretsOpts: input.secretsOpts,\n literalsOpts: input.literalsOpts,\n namespace: input.namespace,\n acc: input.acc\n })\n }\n}\n\nconst _mergeValuesLayers = (layers: ReadonlyArray<_AnyValuesLayer>): _AnyValuesLayer =>\n unsafeCoerce<_AnyValuesLayer>(\n layers.length === 0 ? Layer.empty : Layer.mergeAll(layers[0]!, ...layers.slice(1)),\n \"merged Layer over a heterogeneous list of per-secret value layers\"\n )\n\nexport const bindEnvironment = <\n const M extends Readonly<Record<string, EnvMember>>,\n const Ns extends string = string\n>(\n input: BindEnvironmentInput<M, Ns>\n): DeclaredEnvironment<M, Ns> => {\n const acc: _BindAcc = {\n declared: {},\n envVars: [],\n manifests: [],\n valuesLayers: []\n }\n const secretsOpts = unsafeCoerce<Record<string, unknown> | undefined>(\n input.secrets,\n \"discriminated union from BindEnvironmentInput; iterate keys at runtime\"\n )\n const literalsOpts = unsafeCoerce<Record<string, unknown> | undefined>(\n input.literals,\n \"discriminated union from BindEnvironmentInput; iterate keys at runtime\"\n )\n\n _dispatchAllMembers({ env: input.env, secretsOpts, literalsOpts, namespace: input.namespace, acc })\n\n return {\n envVars: acc.envVars,\n manifests: acc.manifests,\n members: unsafeCoerce<{ readonly [K in keyof M]: DeclaredMember<M[K], Ns> }>(\n acc.declared,\n \"declared populated by iterating env.members; each key maps to its DeclaredMember<M[K], Ns>\"\n ),\n valuesLayer: _mergeValuesLayers(acc.valuesLayers)\n }\n}\n","import { Manifest, RenderError } from \"@konfig.ts/core\"\nimport { Effect, Redacted } from \"effect\"\nimport type { Secret as K8sSecret } from \"./.generated/k8s-types\"\nimport { type BackendEmitInput, type SecretBackend } from \"./backend\"\n\nexport interface NativeSecretOptions {\n readonly type?: string\n readonly immutable?: boolean\n readonly silenceWarning?: boolean\n}\n\ninterface _EmitInput<N extends string, K extends string> {\n readonly base: BackendEmitInput<N, K, true>\n readonly opts: NativeSecretOptions\n}\n\nconst _emit = <N extends string, K extends string>(\n input: _EmitInput<N, K>\n): Manifest.Manifest<K8sSecret> =>\n Manifest.make<K8sSecret>((_ctx) =>\n Effect.gen(function*() {\n if (input.opts.silenceWarning !== true) {\n yield* Effect.logWarning(\n `NativeSecret backend emits a plaintext Secret with stringData on disk for \"${input.base.namespace}/${input.base.name}\". Pass { silenceWarning: true } to suppress, or switch to ExternalSecrets / SealedSecrets / Sops for production.`\n )\n }\n const resolved = yield* input.base.source.resolve.pipe(\n Effect.mapError(\n (cause) =>\n new RenderError({\n message: `NativeSecret(${input.base.namespace}/${input.base.name}): source failed for key \"${cause.key}\"`,\n cause\n })\n )\n )\n const stringData: Record<string, string> = {}\n for (const key of input.base.keys) {\n stringData[key] = Redacted.value(resolved[key])\n }\n const out: K8sSecret = {\n apiVersion: \"v1\",\n kind: \"Secret\",\n metadata: {\n name: input.base.name,\n namespace: input.base.namespace,\n labels: input.base.labels,\n annotations: input.base.annotations\n },\n type: input.opts.type,\n stringData,\n immutable: input.opts.immutable\n }\n return out\n })\n )\n\nexport const NativeSecret = {\n backend: <N extends string, K extends string>(\n opts?: NativeSecretOptions\n ): SecretBackend<N, K, true, K8sSecret> => {\n const resolvedOpts = opts ?? {}\n return {\n _tag: \"NativeSecret\",\n requiresSource: true,\n emit: (input: BackendEmitInput<N, K, true>) => _emit({ base: input, opts: resolvedOpts })\n }\n }\n}\n","import { Manifest, type SecretRef, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type { IngressBackend as K8sIngressBackend } from \"kubernetes-types/networking/v1\"\nimport type {\n Ingress as K8sIngress,\n IngressRule as K8sIngressRule,\n IngressTLS as K8sIngressTLS,\n Service as K8sService,\n ServicePort as K8sServicePort\n} from \"./.generated/k8s-types\"\nimport type { ContainerSpec } from \"./container\"\nimport type { ServicePortSpec } from \"./ports\"\nimport type { Selector } from \"./selector\"\n\n/**\n * Strict input for a `Service`. `selector` and `ports` are required:\n * a Service with no selector has no endpoints, and one with no ports\n * is meaningless. ServicePort needs at minimum a `port`; the upstream\n * `K8sServicePort` only marks `port` as required — names/protocol\n * defaults match kube-apiserver behaviour.\n */\nexport interface ServiceInput {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly selector: Readonly<Record<string, string>>\n readonly ports: ReadonlyArray<K8sServicePort>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n readonly clusterIP?: string\n readonly sessionAffinity?: string\n readonly publishNotReadyAddresses?: boolean\n readonly externalTrafficPolicy?: string\n readonly internalTrafficPolicy?: string\n}\n\n/**\n * Strongly-typed Service input bound to a container's declared port-name\n * union. `selector` and `ports` are required; `ports[i].targetPort`\n * accepts a bare number or `Port.ref(name)` referencing a name declared\n * on `forContainer`. `NoInfer` locks `Ports` to `forContainer`, so the\n * port list is validated against that union rather than inferred from.\n */\nexport interface ServiceFromContainerInput<Ports extends string> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly selector: Readonly<Record<string, string>>\n readonly forContainer: ContainerSpec<Ports>\n readonly ports: ReadonlyArray<ServicePortSpec<NoInfer<Ports>>>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n readonly clusterIP?: string\n readonly sessionAffinity?: string\n readonly publishNotReadyAddresses?: boolean\n readonly externalTrafficPolicy?: string\n readonly internalTrafficPolicy?: string\n}\n\n/**\n * Service built from a `Selector`. The selector's labels populate\n * `spec.selector` — drift versus the matching Deployment is impossible\n * once both consume the same `podSet`.\n */\nexport interface ServiceFromPodSetInput<L extends Readonly<Record<string, string>>> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly podSet: Selector<L>\n readonly ports: ReadonlyArray<K8sServicePort>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n readonly clusterIP?: string\n readonly sessionAffinity?: string\n readonly publishNotReadyAddresses?: boolean\n readonly externalTrafficPolicy?: string\n readonly internalTrafficPolicy?: string\n}\n\nexport const Service = {\n make: (input: ServiceInput): Manifest.Manifest<K8sService> => {\n const resource: K8sService = {\n apiVersion: \"v1\",\n kind: \"Service\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n selector: input.selector,\n type: input.type,\n ports: unsafeCoerce(\n input.ports,\n \"input.ports is the user-typed Service spec; K8s ServicePort allows the same fields\"\n ),\n clusterIP: input.clusterIP,\n sessionAffinity: input.sessionAffinity,\n publishNotReadyAddresses: input.publishNotReadyAddresses,\n externalTrafficPolicy: input.externalTrafficPolicy,\n internalTrafficPolicy: input.internalTrafficPolicy\n }\n }\n return Manifest.make<K8sService>(() => Effect.succeed(resource))\n },\n fromContainer: <Ports extends string>(\n input: ServiceFromContainerInput<Ports>\n ): Manifest.Manifest<K8sService> =>\n Service.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n selector: input.selector,\n ports: unsafeCoerce<ReadonlyArray<K8sServicePort>>(\n input.ports,\n \"ServicePortSpec<Ports> structurally matches K8sServicePort; targetPort's PortName<Ports> brand is a phantom — runtime value is the underlying string\"\n ),\n type: input.type,\n clusterIP: input.clusterIP,\n sessionAffinity: input.sessionAffinity,\n publishNotReadyAddresses: input.publishNotReadyAddresses,\n externalTrafficPolicy: input.externalTrafficPolicy,\n internalTrafficPolicy: input.internalTrafficPolicy\n }),\n fromPodSet: <L extends Readonly<Record<string, string>>>(\n input: ServiceFromPodSetInput<L>\n ): Manifest.Manifest<K8sService> =>\n Service.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n selector: input.podSet.labels,\n ports: input.ports,\n type: input.type,\n clusterIP: input.clusterIP,\n sessionAffinity: input.sessionAffinity,\n publishNotReadyAddresses: input.publishNotReadyAddresses,\n externalTrafficPolicy: input.externalTrafficPolicy,\n internalTrafficPolicy: input.internalTrafficPolicy\n })\n}\n\nexport interface IngressTLSInput {\n readonly hosts?: ReadonlyArray<string>\n readonly secretName: SecretRef<string>\n}\n\nexport interface IngressInput {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly ingressClassName?: string\n readonly rules?: ReadonlyArray<K8sIngressRule>\n readonly tls?: ReadonlyArray<IngressTLSInput>\n readonly defaultBackend?: K8sIngressBackend\n}\n\nexport const Ingress = {\n make: (input: IngressInput): Manifest.Manifest<K8sIngress> => {\n const resource: K8sIngress = {\n apiVersion: \"networking.k8s.io/v1\",\n kind: \"Ingress\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n ingressClassName: input.ingressClassName,\n rules: unsafeCoerce(\n input.rules,\n \"user-supplied Ingress rules; widening from our convenience type to the K8s type\"\n ),\n tls: unsafeCoerce<K8sIngressTLS[]>(input.tls, \"Ingress.tls produces K8sIngressTLS with branded secretName\"),\n defaultBackend: unsafeCoerce(input.defaultBackend, \"user-supplied IngressBackend; structural match to K8s type\")\n }\n }\n return Manifest.make<K8sIngress>(() => Effect.succeed(resource))\n },\n /**\n * TLS entry constructor for `Ingress.make({ tls: [...] })`. Takes a\n * branded `SecretRef` so the secret's name can't widen to a raw\n * string at the call site.\n */\n tls: (input: {\n readonly secretName: SecretRef<string>\n readonly hosts?: ReadonlyArray<string>\n }): IngressTLSInput => ({ secretName: input.secretName, hosts: input.hosts })\n}\n","import { Redacted } from \"effect\"\nimport { createHash, type Hash } from \"node:crypto\"\n\nexport interface HashSecretValuesInput {\n readonly values: Readonly<Record<string, Redacted.Redacted<string>>>\n /**\n * Non-secret salt folded into the digest so it is NOT a pure function of the\n * plaintext — this defeats offline brute-force / rainbow-table recovery of\n * low-entropy secrets from the annotation. Use a stable per-workload\n * identifier such as `\"<namespace>/<name>\"`.\n */\n readonly salt: string\n}\n\n// Netstring-frames every field (`<byteLen>:<bytes>,`) before hashing. Plain\n// `key + \"=\" + value + \"\\n\"` concatenation is ambiguous — `{ \"a=b\": \"c\" }` and\n// `{ \"a\": \"b\\nc\" }` would hash identically. Length-prefixing makes each field\n// boundary unforgeable, so distinct records always produce distinct digests.\nconst _frame = (hasher: Hash, value: string): void => {\n const bytes = Buffer.from(value, \"utf8\")\n hasher.update(`${bytes.length}:`)\n hasher.update(bytes)\n hasher.update(\",\")\n}\n\n// Captures values AT BUILD TIME ONLY — rotations between builds need an\n// in-cluster watcher (e.g. Reloader). Redacted.value is inline so plaintext\n// is not bound to a local.\n//\n// NOTE: the returned digest is a change-detection fingerprint, NOT a\n// cryptographic commitment you may safely publish for a low-entropy secret.\n// It is salted (so it is not a bare sha256 of the plaintext) and emitted at\n// full width (no truncation), but it must not be treated as secret-safe.\nexport const hashSecretValues = (input: HashSecretValuesInput): string => {\n const hasher = createHash(\"sha256\")\n _frame(hasher, \"konfig/secret-values-hash/v1\")\n _frame(hasher, input.salt)\n const keys = Object.keys(input.values).sort()\n for (const key of keys) {\n _frame(hasher, key)\n _frame(hasher, Redacted.value(input.values[key]!))\n }\n return hasher.digest(\"hex\")\n}\n","import { Manifest, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type { PersistentVolumeSpec as K8sPersistentVolumeSpec } from \"kubernetes-types/core/v1\"\nimport type {\n NetworkPolicyEgressRule as K8sNetworkPolicyEgressRule,\n NetworkPolicyIngressRule as K8sNetworkPolicyIngressRule\n} from \"kubernetes-types/networking/v1\"\nimport type {\n ClusterRole as K8sClusterRole,\n ClusterRoleBinding as K8sClusterRoleBinding,\n NetworkPolicy as K8sNetworkPolicy,\n PersistentVolume as K8sPersistentVolume,\n PersistentVolumeClaim as K8sPersistentVolumeClaim,\n Role as K8sRole,\n RoleBinding as K8sRoleBinding\n} from \"./.generated/k8s-types\"\nimport type { Selector } from \"./selector\"\n\ninterface NamespacedMeta {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\ninterface ClusterMeta {\n readonly name: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\n/**\n * Standard k8s PV access modes. Constrained to the four documented\n * values so a typo (`\"ReadWriteonce\"`) is a compile-time error.\n */\nexport type PersistentVolumeAccessMode =\n | \"ReadWriteOnce\"\n | \"ReadOnlyMany\"\n | \"ReadWriteMany\"\n | \"ReadWriteOncePod\"\n\nexport type PersistentVolumeReclaimPolicy = \"Retain\" | \"Recycle\" | \"Delete\"\n\nexport type PersistentVolumeMode = \"Filesystem\" | \"Block\"\n\n/**\n * Strict input shape for a `PersistentVolume.spec`. Upstream\n * `kubernetes-types` types every field as optional (because the\n * OpenAPI generator emits the entire union), which makes invalid\n * specs (no capacity, no accessModes, no volume source) compile.\n * The fields the kube-apiserver actually requires are required here.\n *\n * Volume-source fields (`hostPath`, `csi`, `nfs`, `local`, etc.) are\n * inherited from the upstream `PersistentVolumeSpec` via `Omit` so\n * users can use whichever source they need. \"At least one source\"\n * isn't enforced statically (TS unions over 20+ variants would be\n * unwieldy) — the kube-apiserver rejects a spec with no source.\n */\nexport interface PersistentVolumeSpecInput extends\n Omit<\n K8sPersistentVolumeSpec,\n \"capacity\" | \"accessModes\" | \"persistentVolumeReclaimPolicy\" | \"volumeMode\" | \"claimRef\"\n >\n{\n readonly capacity: { readonly storage: string }\n readonly accessModes: ReadonlyArray<PersistentVolumeAccessMode>\n readonly persistentVolumeReclaimPolicy?: PersistentVolumeReclaimPolicy\n readonly volumeMode?: PersistentVolumeMode\n readonly claimRef?: { readonly namespace: string; readonly name: string }\n}\n\nexport interface PersistentVolumeInput extends ClusterMeta {\n readonly spec: PersistentVolumeSpecInput\n}\n\nexport const PersistentVolume = {\n make: (input: PersistentVolumeInput): Manifest.Manifest<K8sPersistentVolume> =>\n Manifest.make<K8sPersistentVolume>(() =>\n Effect.succeed({\n apiVersion: \"v1\",\n kind: \"PersistentVolume\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: unsafeCoerce<K8sPersistentVolume[\"spec\"]>(\n input.spec,\n \"user-supplied PV spec; structural match to the K8s type\"\n )\n })\n )\n}\n\n/**\n * Strict input shape for a `PersistentVolumeClaim.spec`. Same\n * rationale as `PersistentVolumeSpecInput` — accessModes + a storage\n * request are the fields the apiserver requires.\n */\nexport interface PersistentVolumeClaimSpecInput {\n readonly accessModes: ReadonlyArray<PersistentVolumeAccessMode>\n readonly resources: { readonly requests: { readonly storage: string } }\n readonly storageClassName?: string\n readonly volumeMode?: PersistentVolumeMode\n readonly volumeName?: string\n readonly selector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n}\n\nexport interface PersistentVolumeClaimInput extends NamespacedMeta {\n readonly spec: PersistentVolumeClaimSpecInput\n}\n\nexport const PersistentVolumeClaim = {\n make: (input: PersistentVolumeClaimInput): Manifest.Manifest<K8sPersistentVolumeClaim> =>\n Manifest.make<K8sPersistentVolumeClaim>(() =>\n Effect.succeed({\n apiVersion: \"v1\",\n kind: \"PersistentVolumeClaim\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: unsafeCoerce<K8sPersistentVolumeClaim[\"spec\"]>(\n input.spec,\n \"user-supplied PVC spec; structural match to the K8s type\"\n )\n })\n )\n}\n\nexport interface NetworkPolicyInput extends NamespacedMeta {\n readonly spec: K8sNetworkPolicy[\"spec\"]\n}\n\n/**\n * Peer rule for `NetworkPolicy.fromPodSet`. A peer is either a typed\n * `Selector` (matched as `podSelector.matchLabels`), a `namespaceSelector`,\n * or a CIDR block.\n */\nexport interface NetworkPolicyPeer {\n readonly podSet?: Selector<Readonly<Record<string, string>>>\n readonly namespaceSelector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n readonly ipBlock?: { readonly cidr: string; readonly except?: ReadonlyArray<string> }\n}\n\nexport interface NetworkPolicyIngressRule {\n readonly from?: ReadonlyArray<NetworkPolicyPeer>\n readonly ports?: K8sNetworkPolicyIngressRule[\"ports\"]\n}\n\nexport interface NetworkPolicyEgressRule {\n readonly to?: ReadonlyArray<NetworkPolicyPeer>\n readonly ports?: K8sNetworkPolicyEgressRule[\"ports\"]\n}\n\n/**\n * NetworkPolicy built from typed `Selector`s. `podSet` drives\n * `spec.podSelector`; ingress/egress peer rules accept further selectors\n * via `from[].podSet` / `to[].podSet`. Peer selectors need not match the\n * owning selector — the typing ties this NetworkPolicy's selection to a\n * single source of truth and lets peers be independently typed.\n */\nexport interface NetworkPolicyFromPodSetInput<L extends Readonly<Record<string, string>>> extends NamespacedMeta {\n readonly podSet: Selector<L>\n readonly policyTypes?: ReadonlyArray<\"Ingress\" | \"Egress\">\n readonly ingress?: ReadonlyArray<NetworkPolicyIngressRule>\n readonly egress?: ReadonlyArray<NetworkPolicyEgressRule>\n}\n\nconst _lowerPeer = (peer: NetworkPolicyPeer): {\n readonly podSelector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n readonly namespaceSelector?: { readonly matchLabels?: Readonly<Record<string, string>> }\n readonly ipBlock?: { readonly cidr: string; readonly except?: ReadonlyArray<string> }\n} => ({\n ...(peer.podSet !== undefined ? { podSelector: { matchLabels: peer.podSet.labels } } : {}),\n ...(peer.namespaceSelector !== undefined ? { namespaceSelector: peer.namespaceSelector } : {}),\n ...(peer.ipBlock !== undefined ? { ipBlock: peer.ipBlock } : {})\n})\n\nexport const NetworkPolicy = {\n make: (input: NetworkPolicyInput): Manifest.Manifest<K8sNetworkPolicy> =>\n Manifest.make<K8sNetworkPolicy>(() =>\n Effect.succeed({\n apiVersion: \"networking.k8s.io/v1\",\n kind: \"NetworkPolicy\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: input.spec\n })\n ),\n fromPodSet: <L extends Readonly<Record<string, string>>>(\n input: NetworkPolicyFromPodSetInput<L>\n ): Manifest.Manifest<K8sNetworkPolicy> => {\n const ingress = input.ingress?.map((rule) => ({\n from: rule.from?.map(_lowerPeer),\n ports: rule.ports\n }))\n const egress = input.egress?.map((rule) => ({\n to: rule.to?.map(_lowerPeer),\n ports: rule.ports\n }))\n return NetworkPolicy.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n spec: unsafeCoerce<K8sNetworkPolicy[\"spec\"]>(\n {\n podSelector: { matchLabels: input.podSet.labels },\n policyTypes: input.policyTypes,\n ingress,\n egress\n },\n \"konfig peers carry readonly arrays; upstream NetworkPolicySpec is mutable but the runtime shape matches\"\n )\n })\n }\n}\n\nexport interface ClusterRoleInput extends ClusterMeta {\n readonly rules?: K8sClusterRole[\"rules\"]\n readonly aggregationRule?: K8sClusterRole[\"aggregationRule\"]\n}\n\nexport const ClusterRole = {\n make: (input: ClusterRoleInput): Manifest.Manifest<K8sClusterRole> =>\n Manifest.make<K8sClusterRole>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"ClusterRole\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n },\n rules: input.rules,\n aggregationRule: input.aggregationRule\n })\n )\n}\n\nexport interface ClusterRoleBindingInput extends ClusterMeta {\n readonly roleRef: K8sClusterRoleBinding[\"roleRef\"]\n readonly subjects?: K8sClusterRoleBinding[\"subjects\"]\n}\n\nexport const ClusterRoleBinding = {\n make: (input: ClusterRoleBindingInput): Manifest.Manifest<K8sClusterRoleBinding> =>\n Manifest.make<K8sClusterRoleBinding>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"ClusterRoleBinding\",\n metadata: {\n name: input.name,\n labels: input.labels,\n annotations: input.annotations\n },\n roleRef: input.roleRef,\n subjects: input.subjects\n })\n )\n}\n\nexport interface RoleInput extends NamespacedMeta {\n readonly rules?: K8sRole[\"rules\"]\n}\n\nexport const Role = {\n make: (input: RoleInput): Manifest.Manifest<K8sRole> =>\n Manifest.make<K8sRole>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"Role\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n rules: input.rules\n })\n )\n}\n\nexport interface RoleBindingInput extends NamespacedMeta {\n readonly roleRef: K8sRoleBinding[\"roleRef\"]\n readonly subjects?: K8sRoleBinding[\"subjects\"]\n}\n\nexport const RoleBinding = {\n make: (input: RoleBindingInput): Manifest.Manifest<K8sRoleBinding> =>\n Manifest.make<K8sRoleBinding>(() =>\n Effect.succeed({\n apiVersion: \"rbac.authorization.k8s.io/v1\",\n kind: \"RoleBinding\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n roleRef: input.roleRef,\n subjects: input.subjects\n })\n )\n}\n","import { brand } from \"@konfig.ts/core\"\nimport type { ConfigMapRef, PvcRef, SecretRef } from \"@konfig.ts/core\"\n\n/**\n * Branded volume name — a string carrying the literal `N` in its\n * phantom. Constructed by the volume factories\n * (`Volume.empty`, `Volume.fromSecret`, …) and `Volume.mountRef`. Lets\n * `VolumeMount<Mounts>` and `Pod` constrain a container's\n * `volumeMounts[i].name` to volumes that the pod actually declares.\n */\ndeclare const VolumeNameBrand: unique symbol\nexport type VolumeName<N extends string> = string & {\n readonly [VolumeNameBrand]: N\n}\n\nconst _volumeName = <const N extends string>(name: N): VolumeName<N> => brand<VolumeName<N>>(name)\n\nexport interface Volume<N extends string = string> {\n readonly name: VolumeName<N>\n readonly secret?: {\n readonly secretName: string\n readonly optional?: boolean\n readonly defaultMode?: number\n }\n readonly configMap?: {\n readonly name: string\n readonly optional?: boolean\n readonly defaultMode?: number\n readonly items?: ReadonlyArray<{ readonly key: string; readonly path: string }>\n }\n readonly emptyDir?: { readonly medium?: string; readonly sizeLimit?: string }\n readonly persistentVolumeClaim?: {\n readonly claimName: PvcRef<string>\n readonly readOnly?: boolean\n }\n readonly hostPath?: { readonly path: string; readonly type?: string }\n}\n\nexport interface EmptyVolumeInput<N extends string> {\n readonly name: N\n readonly medium?: string\n readonly sizeLimit?: string\n}\n\nexport interface VolumeFromSecretInput<N extends string> {\n readonly name: N\n readonly ref: SecretRef<string>\n readonly optional?: boolean\n readonly defaultMode?: number\n}\n\nexport interface VolumeFromConfigMapInput<N extends string> {\n readonly name: N\n readonly ref: ConfigMapRef<string>\n readonly optional?: boolean\n readonly defaultMode?: number\n readonly items?: ReadonlyArray<{ readonly key: string; readonly path: string }>\n}\n\nexport interface VolumeFromPvcInput<N extends string, PvcN extends string> {\n readonly name: N\n readonly claim: PvcRef<PvcN>\n readonly readOnly?: boolean\n}\n\n/**\n * `Volume` value namespace.\n *\n * volumes: [\n * Volume.empty({ name: \"config\" }),\n * Volume.fromSecret({ name: \"tls\", ref: tlsSecret.ref }),\n * Volume.fromConfigMap({ name: \"settings\", ref: cfg.ref }),\n * Volume.fromPvc({ name: \"data\", claim: pvc.ref }),\n * ],\n * volumeMounts: [\n * { name: Volume.mountRef(\"config\"), mountPath: \"/etc/conf\" },\n * ],\n *\n * All four constructors capture the literal `name` in the returned\n * `Volume<N>` brand; `Pod` infers the union and constrains each\n * container's `volumeMounts[i].name` to it.\n */\nexport const Volume = {\n empty: <const N extends string>(input: EmptyVolumeInput<N>): Volume<N> => ({\n name: _volumeName(input.name),\n emptyDir: { medium: input.medium, sizeLimit: input.sizeLimit }\n }),\n fromSecret: <const N extends string>(input: VolumeFromSecretInput<N>): Volume<N> => ({\n name: _volumeName(input.name),\n secret: {\n secretName: input.ref,\n optional: input.optional,\n defaultMode: input.defaultMode\n }\n }),\n fromConfigMap: <const N extends string>(input: VolumeFromConfigMapInput<N>): Volume<N> => ({\n name: _volumeName(input.name),\n configMap: {\n name: input.ref,\n optional: input.optional,\n defaultMode: input.defaultMode,\n items: input.items\n }\n }),\n fromPvc: <const N extends string, const PvcN extends string>(\n input: VolumeFromPvcInput<N, PvcN>\n ): Volume<N> => ({\n name: _volumeName(input.name),\n persistentVolumeClaim: { claimName: input.claim, readOnly: input.readOnly }\n }),\n mountRef: <const N extends string>(name: N): VolumeName<N> => _volumeName(name)\n}\n\n/**\n * Typed container volumeMount. `Mounts` is the union of volume names\n * declared on the surrounding pod; `name` must reference one of them.\n * Bare-number variants don't apply (mounts are always by name).\n */\nexport interface VolumeMount<Mounts extends string = string> {\n readonly name: VolumeName<Mounts>\n readonly mountPath: string\n readonly readOnly?: boolean\n readonly subPath?: string\n readonly subPathExpr?: string\n readonly mountPropagation?: string\n}\n\nexport type VolumeNamesOf<V extends ReadonlyArray<Volume<string>>> = {\n readonly [I in keyof V]: V[I] extends Volume<infer N> ? N : never\n}[number]\n","import { Manifest, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n CronJob as K8sCronJob,\n Deployment as K8sDeployment,\n DeploymentStrategy,\n Job as K8sJob,\n PersistentVolumeClaim as K8sPersistentVolumeClaim,\n StatefulSet as K8sStatefulSet,\n StatefulSetUpdateStrategy\n} from \"./.generated/k8s-types\"\nimport type { PodSpecInput } from \"./container\"\nimport type { Selector } from \"./selector\"\n\ninterface WorkloadMeta {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n}\n\ninterface SelectorAndTemplate {\n readonly selector: { readonly matchLabels: Readonly<Record<string, string>> }\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n}\n\nexport interface DeploymentInput extends WorkloadMeta, SelectorAndTemplate {\n readonly replicas?: number\n readonly strategy?: DeploymentStrategy\n readonly revisionHistoryLimit?: number\n readonly progressDeadlineSeconds?: number\n readonly minReadySeconds?: number\n}\n\n/**\n * Deployment built from a `Selector`. The selector's labels become both\n * the Deployment's `spec.selector.matchLabels` and the pod template's\n * `metadata.labels` — coherent by construction. Drift between selector\n * and template (the classic \"service has no endpoints\" footgun) is\n * structurally impossible once both consume the same `podSet`.\n */\nexport interface DeploymentFromPodSetInput<L extends Readonly<Record<string, string>>> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly podSet: Selector<L>\n readonly replicas?: number\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n readonly strategy?: DeploymentStrategy\n readonly revisionHistoryLimit?: number\n readonly progressDeadlineSeconds?: number\n readonly minReadySeconds?: number\n}\n\nexport const Deployment = {\n make: (input: DeploymentInput): Manifest.Manifest<K8sDeployment> => {\n const resource: K8sDeployment = {\n apiVersion: \"apps/v1\",\n kind: \"Deployment\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n replicas: input.replicas,\n selector: input.selector,\n template: unsafeCoerce(\n input.template,\n \"konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction\"\n ),\n strategy: input.strategy,\n revisionHistoryLimit: input.revisionHistoryLimit,\n progressDeadlineSeconds: input.progressDeadlineSeconds,\n minReadySeconds: input.minReadySeconds\n }\n }\n return Manifest.make<K8sDeployment>(() => Effect.succeed(resource))\n },\n fromPodSet: <L extends Readonly<Record<string, string>>>(\n input: DeploymentFromPodSetInput<L>\n ): Manifest.Manifest<K8sDeployment> =>\n Deployment.make({\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations,\n replicas: input.replicas,\n selector: { matchLabels: input.podSet.labels },\n template: {\n metadata: {\n // podSet labels are spread LAST so a colliding caller-supplied\n // template label can never shadow a selector label — that would\n // desync the pod template from `spec.selector` and strand the\n // Deployment with zero matching endpoints.\n labels: { ...input.template.metadata?.labels, ...input.podSet.labels },\n annotations: input.template.metadata?.annotations\n },\n spec: input.template.spec\n },\n strategy: input.strategy,\n revisionHistoryLimit: input.revisionHistoryLimit,\n progressDeadlineSeconds: input.progressDeadlineSeconds,\n minReadySeconds: input.minReadySeconds\n })\n}\n\nexport interface StatefulSetInput extends WorkloadMeta, SelectorAndTemplate {\n readonly replicas?: number\n readonly serviceName: string\n readonly volumeClaimTemplates?: ReadonlyArray<K8sPersistentVolumeClaim>\n readonly podManagementPolicy?: string\n readonly updateStrategy?: StatefulSetUpdateStrategy\n}\n\nexport const StatefulSet = {\n make: (input: StatefulSetInput): Manifest.Manifest<K8sStatefulSet> => {\n const resource: K8sStatefulSet = {\n apiVersion: \"apps/v1\",\n kind: \"StatefulSet\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n replicas: input.replicas,\n selector: input.selector,\n template: unsafeCoerce(\n input.template,\n \"konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction\"\n ),\n serviceName: input.serviceName,\n volumeClaimTemplates: unsafeCoerce(\n input.volumeClaimTemplates,\n \"ReadonlyArray<K8sPersistentVolumeClaim> is structurally Array<PersistentVolumeClaim>; readonly-to-mutable variance is safe here\"\n ),\n podManagementPolicy: input.podManagementPolicy,\n updateStrategy: input.updateStrategy\n }\n }\n return Manifest.make<K8sStatefulSet>(() => Effect.succeed(resource))\n }\n}\n\nexport interface JobInput extends WorkloadMeta {\n readonly parallelism?: number\n readonly completions?: number\n readonly backoffLimit?: number\n readonly activeDeadlineSeconds?: number\n readonly ttlSecondsAfterFinished?: number\n readonly suspend?: boolean\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n}\n\nexport const Job = {\n make: (input: JobInput): Manifest.Manifest<K8sJob> => {\n const resource: K8sJob = {\n apiVersion: \"batch/v1\",\n kind: \"Job\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n parallelism: input.parallelism,\n completions: input.completions,\n backoffLimit: input.backoffLimit,\n activeDeadlineSeconds: input.activeDeadlineSeconds,\n ttlSecondsAfterFinished: input.ttlSecondsAfterFinished,\n suspend: input.suspend,\n template: unsafeCoerce(\n input.template,\n \"konfig PodSpecInput is structurally a K8s PodTemplateSpec body; brand-checked fields lower at construction\"\n )\n }\n }\n return Manifest.make<K8sJob>(() => Effect.succeed(resource))\n }\n}\n\nexport interface CronJobInput extends WorkloadMeta {\n readonly schedule: string\n readonly concurrencyPolicy?: string\n readonly successfulJobsHistoryLimit?: number\n readonly failedJobsHistoryLimit?: number\n readonly startingDeadlineSeconds?: number\n readonly suspend?: boolean\n readonly jobTemplate: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: {\n readonly template: {\n readonly metadata?: {\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n }\n readonly spec: PodSpecInput\n }\n readonly backoffLimit?: number\n readonly activeDeadlineSeconds?: number\n readonly ttlSecondsAfterFinished?: number\n }\n }\n}\n\nexport const CronJob = {\n make: (input: CronJobInput): Manifest.Manifest<K8sCronJob> => {\n const resource: K8sCronJob = {\n apiVersion: \"batch/v1\",\n kind: \"CronJob\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: input.labels,\n annotations: input.annotations\n },\n spec: {\n schedule: input.schedule,\n concurrencyPolicy: input.concurrencyPolicy,\n successfulJobsHistoryLimit: input.successfulJobsHistoryLimit,\n failedJobsHistoryLimit: input.failedJobsHistoryLimit,\n startingDeadlineSeconds: input.startingDeadlineSeconds,\n suspend: input.suspend,\n jobTemplate: unsafeCoerce(\n input.jobTemplate,\n \"konfig CronJob jobTemplate is structurally a K8s JobTemplateSpec body\"\n )\n }\n }\n return Manifest.make<K8sCronJob>(() => Effect.succeed(resource))\n }\n}\n","import { Manifest, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n Deployment as K8sDeployment,\n NetworkPolicy as K8sNetworkPolicy,\n Service as K8sService\n} from \"./.generated/k8s-types\"\nimport { Service, type ServiceFromPodSetInput } from \"./network\"\nimport { NetworkPolicy, type NetworkPolicyFromPodSetInput } from \"./policy\"\nimport type { Selector } from \"./selector\"\nimport { Deployment, type DeploymentFromPodSetInput } from \"./workload\"\n\n/**\n * `PodSet.define` input. Drives a coherent Deployment + Service +\n * (optional) NetworkPolicy from a single `Selector` — every resource\n * derives its selector from `podSet`, so the trio cannot drift.\n */\nexport interface DefinePodSetInput<L extends Readonly<Record<string, string>>> {\n readonly podSet: Selector<L>\n readonly deployment: Omit<DeploymentFromPodSetInput<L>, \"podSet\">\n readonly service?: Omit<ServiceFromPodSetInput<L>, \"podSet\">\n readonly netPol?: Omit<NetworkPolicyFromPodSetInput<L>, \"podSet\">\n}\n\ntype PodSetOutput =\n | readonly [K8sDeployment, K8sService]\n | readonly [K8sDeployment, K8sService, K8sNetworkPolicy]\n | readonly [K8sDeployment, K8sNetworkPolicy]\n | readonly [K8sDeployment]\n\n/**\n * `PodSet` value namespace.\n *\n * const trio = PodSet.define({\n * podSet: redisCachePods,\n * deployment: { ... },\n * service: { ... },\n * netPol: { ... },\n * });\n *\n * Umbrella over `Deployment.fromPodSet`, `Service.fromPodSet`, and\n * `NetworkPolicy.fromPodSet` — emits whichever subset of the trio the\n * input specifies, all rooted at one `Selector`.\n */\nexport const PodSet = {\n define: <L extends Readonly<Record<string, string>>>(\n input: DefinePodSetInput<L>\n ): Manifest.Manifest<PodSetOutput> => {\n const deployment = Deployment.fromPodSet({ podSet: input.podSet, ...input.deployment })\n const service = input.service !== undefined\n ? Service.fromPodSet({ podSet: input.podSet, ...input.service })\n : undefined\n const netPol = input.netPol !== undefined\n ? NetworkPolicy.fromPodSet({ podSet: input.podSet, ...input.netPol })\n : undefined\n\n return Manifest.make<PodSetOutput>((ctx) =>\n Effect.gen(function*() {\n const d = yield* deployment.render(ctx)\n const s = service !== undefined ? yield* service.render(ctx) : undefined\n const n = netPol !== undefined ? yield* netPol.render(ctx) : undefined\n return _asPodSetOutput(d, s, n)\n })\n )\n }\n}\n\n// tuple element types are statically known per branch; the array literal is\n// widened by TS, the brand-free runtime shape matches the typed tuple.\nconst _asPodSetOutput = (\n d: K8sDeployment,\n s: K8sService | undefined,\n n: K8sNetworkPolicy | undefined\n): PodSetOutput => {\n const reason = \"PodSet.define: tuple shape is determined by which of service/netPol are present\"\n if (s !== undefined && n !== undefined) {\n return unsafeCoerce<readonly [K8sDeployment, K8sService, K8sNetworkPolicy]>([d, s, n], reason)\n }\n if (s !== undefined) return unsafeCoerce<readonly [K8sDeployment, K8sService]>([d, s], reason)\n if (n !== undefined) return unsafeCoerce<readonly [K8sDeployment, K8sNetworkPolicy]>([d, n], reason)\n return unsafeCoerce<readonly [K8sDeployment]>([d], reason)\n}\n","import { unsafeCoerce } from \"@konfig.ts/core\"\n\n/**\n * Selector — one source of truth for \"this pod set.\"\n *\n * `Selector<L>` wraps a literal label record and brands it. Resources\n * that *select* pods — Deployment.selector, Service.selector,\n * NetworkPolicy.podSelector, HPA target — take the bundle directly via\n * `Deployment.fromPodSet` / `Service.fromPodSet` / `NetworkPolicy.fromPodSet`\n * so a drift across three resources (the classic \"service has no\n * endpoints / netpol denies everything\" bug) becomes a compile error.\n *\n * `Workload.web` already keeps these labels coherent internally; the\n * Selector is the win when users go off-script: StatefulSet, DaemonSet,\n * cross-namespace selectors, or wiring a NetworkPolicy from app A to\n * peer pods B.\n */\ndeclare const SelectorBrand: unique symbol\n\nexport interface Selector<L extends Readonly<Record<string, string>>> {\n readonly [SelectorBrand]: L\n readonly labels: L\n}\n\n/**\n * `Selector` value namespace.\n *\n * const apiPods = Selector.make({ app: \"api\", tier: \"web\" });\n */\nexport const Selector = {\n make: <const L extends Readonly<Record<string, string>>>(labels: L): Selector<L> =>\n unsafeCoerce<Selector<L>>(\n { labels },\n \"SelectorBrand is a unique-symbol phantom — no runtime value; runtime shape is { labels }\"\n )\n}\n\nexport type SelectorLabels<S> = S extends Selector<infer L> ? L : never\n","import type { Manifest, SecretRef } from \"@konfig.ts/core\"\nimport { Manifest as M, unsafeCoerce } from \"@konfig.ts/core\"\nimport { Effect } from \"effect\"\nimport type {\n CronJob as K8sCronJob,\n Deployment as K8sDeployment,\n Ingress as K8sIngress,\n IngressRule as K8sIngressRule,\n Service as K8sService,\n ServiceAccount as K8sServiceAccount,\n ServicePort as K8sServicePort\n} from \"./.generated/k8s-types\"\nimport type { ContainerInput, ContainerSpec } from \"./container\"\nimport { Ingress, type IngressTLSInput, Service } from \"./network\"\nimport type { ServicePortSpec } from \"./ports\"\nimport type { Volume } from \"./volume\"\nimport { CronJob, Deployment } from \"./workload\"\n\n/**\n * Union of port names declared by every `ContainerSpec` in `Cs`. Raw\n * `ContainerInput` entries (no `Container.define`) contribute `never`,\n * so untyped containers don't widen the result — they just don't add\n * any named-port options to the Service. With every container untyped,\n * the union collapses to `never` and `targetPort` is effectively\n * `number`-only, matching Kubernetes' behaviour when no port is named.\n */\ntype _PortNamesOfContainers<Cs extends ReadonlyArray<ContainerInput>> = {\n readonly [K in keyof Cs]: Cs[K] extends ContainerSpec<infer P, string> ? P : never\n}[number]\n\n/**\n * Reloader integration shorthand. Two complementary rotation models:\n *\n * - *Build-time* rotation (re-render → new hash → rolling update). konfig\n * does NOT stamp this automatically; it ships `hashSecretValues` as a\n * helper you attach yourself — feed it your resolved secret values and\n * place the digest into `deployment.podAnnotations`, so a value change\n * flips the pod template and triggers a rollout.\n * - *Runtime* rotation via Stakater's Reloader (operator watches mounted\n * Secrets/ConfigMaps and patches the workload to restart pods on change),\n * selected by the option below.\n *\n * Pick:\n *\n * - `\"off\"` (default) — no Reloader annotation. Pair with a build-time\n * `hashSecretValues` annotation if you accept the redeploy-on-edit model.\n * - `\"stakater\"` — emit `reloader.stakater.com/auto: \"true\"`. Reloader\n * watches every Secret/ConfigMap referenced by the pod spec.\n * - `\"stakater-strict\"` — emit `reloader.stakater.com/auto: \"true\"`\n * plus `reloader.stakater.com/match: \"true\"`, restricting watch\n * to objects with the matching annotation set on them.\n * - `{ secrets, configMaps }` — explicit per-resource lists, emitted\n * as `secret.reloader.stakater.com/reload` /\n * `configmap.reloader.stakater.com/reload` (comma-joined).\n *\n * See packages/k8s/README.md for the trade-off between build-time\n * hashes and runtime reloader.\n */\nexport type ReloaderOption =\n | \"off\"\n | \"stakater\"\n | \"stakater-strict\"\n | {\n readonly secrets?: ReadonlyArray<string>\n readonly configMaps?: ReadonlyArray<string>\n }\n\nconst _reloaderAnnotations = (\n opt: ReloaderOption | undefined\n): Readonly<Record<string, string>> => {\n if (opt === undefined || opt === \"off\") return {}\n if (opt === \"stakater\") return { \"reloader.stakater.com/auto\": \"true\" }\n if (opt === \"stakater-strict\") {\n return {\n \"reloader.stakater.com/auto\": \"true\",\n \"reloader.stakater.com/match\": \"true\"\n }\n }\n const out: Record<string, string> = {}\n if (opt.secrets && opt.secrets.length > 0) {\n out[\"secret.reloader.stakater.com/reload\"] = opt.secrets.join(\",\")\n }\n if (opt.configMaps && opt.configMaps.length > 0) {\n out[\"configmap.reloader.stakater.com/reload\"] = opt.configMaps.join(\",\")\n }\n return out\n}\n\ninterface WebInput<Cs extends ReadonlyArray<ContainerInput>> {\n readonly name: string\n readonly namespace: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n /** Pod-restart-on-rotation integration. See `ReloaderOption`. */\n readonly reloader?: ReloaderOption\n readonly deployment: {\n readonly replicas?: number\n readonly containers: Cs\n readonly volumes?: ReadonlyArray<Volume>\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n readonly serviceAccountName?: string\n readonly podLabels?: Readonly<Record<string, string>>\n readonly podAnnotations?: Readonly<Record<string, string>>\n }\n readonly service: {\n readonly ports: ReadonlyArray<ServicePortSpec<NoInfer<_PortNamesOfContainers<Cs>>>>\n readonly type?: \"ClusterIP\" | \"NodePort\" | \"LoadBalancer\"\n }\n readonly ingress?: {\n readonly ingressClassName?: string\n readonly rules?: ReadonlyArray<K8sIngressRule>\n readonly tls?: ReadonlyArray<IngressTLSInput>\n readonly annotations?: Readonly<Record<string, string>>\n }\n}\n\ninterface _WebPartInput<Cs extends ReadonlyArray<ContainerInput>> {\n readonly input: WebInput<Cs>\n readonly selectorLabels: Readonly<Record<string, string>>\n}\n\nconst _webDeployment = <Cs extends ReadonlyArray<ContainerInput>>(\n { input, selectorLabels }: _WebPartInput<Cs>\n): Manifest.Manifest<K8sDeployment> => {\n // selectorLabels are spread LAST so a colliding user pod label can never\n // override the `app` selector — that would desync the pod template from\n // `spec.selector` and leave the Service with zero endpoints.\n const podLabels = { ...input.deployment.podLabels, ...selectorLabels }\n const reloaderAnns = _reloaderAnnotations(input.reloader)\n return Deployment.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: { ...input.annotations, ...reloaderAnns },\n replicas: input.deployment.replicas,\n selector: { matchLabels: selectorLabels },\n template: {\n metadata: { labels: podLabels, annotations: input.deployment.podAnnotations },\n spec: {\n containers: input.deployment.containers,\n volumes: input.deployment.volumes,\n imagePullSecrets: input.deployment.imagePullSecrets,\n serviceAccountName: input.deployment.serviceAccountName\n }\n }\n })\n}\n\nconst _webService = <Cs extends ReadonlyArray<ContainerInput>>(\n { input, selectorLabels }: _WebPartInput<Cs>\n): Manifest.Manifest<K8sService> =>\n Service.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: input.annotations,\n selector: selectorLabels,\n type: input.service.type ?? \"ClusterIP\",\n ports: unsafeCoerce<ReadonlyArray<K8sServicePort>>(\n input.service.ports,\n \"ServicePortSpec<Ports> structurally matches K8sServicePort; the PortName<Ports> brand on targetPort is a phantom whose runtime value is the underlying string\"\n )\n })\n\nconst _webIngress = <Cs extends ReadonlyArray<ContainerInput>>(\n { ingress, input, selectorLabels }: _WebPartInput<Cs> & { readonly ingress: NonNullable<WebInput<Cs>[\"ingress\"]> }\n): Manifest.Manifest<K8sIngress> =>\n Ingress.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: { ...input.annotations, ...ingress.annotations },\n ingressClassName: ingress.ingressClassName,\n rules: ingress.rules,\n tls: ingress.tls\n })\n\nexport const web = <const Cs extends ReadonlyArray<ContainerInput>>(\n input: WebInput<Cs>\n): Manifest.Manifest<\n readonly [K8sDeployment, K8sService] | readonly [K8sDeployment, K8sService, K8sIngress]\n> => {\n const selectorLabels = { app: input.name }\n const deployment = _webDeployment({ input, selectorLabels })\n const service = _webService({ input, selectorLabels })\n\n if (input.ingress === undefined) {\n return M.make((ctx) => Effect.all([deployment.render(ctx), service.render(ctx)], { concurrency: \"unbounded\" }))\n }\n\n const ingress = _webIngress({ input, selectorLabels, ingress: input.ingress })\n return M.make((ctx) =>\n Effect.all([deployment.render(ctx), service.render(ctx), ingress.render(ctx)], {\n concurrency: \"unbounded\"\n })\n )\n}\n\ninterface CronInput {\n readonly name: string\n readonly namespace: string\n readonly schedule: string\n readonly labels?: Readonly<Record<string, string>>\n readonly annotations?: Readonly<Record<string, string>>\n readonly concurrencyPolicy?: \"Allow\" | \"Forbid\" | \"Replace\"\n readonly successfulJobsHistoryLimit?: number\n readonly failedJobsHistoryLimit?: number\n readonly containers: ReadonlyArray<ContainerInput>\n readonly volumes?: ReadonlyArray<Volume>\n readonly imagePullSecrets?: ReadonlyArray<{ readonly name: SecretRef<string> }>\n readonly restartPolicy?: \"OnFailure\" | \"Never\"\n}\n\nexport const cron = (\n input: CronInput\n): Manifest.Manifest<readonly [K8sServiceAccount, K8sCronJob]> => {\n const selectorLabels = { app: input.name }\n\n const sa: Manifest.Manifest<K8sServiceAccount> = M.make<K8sServiceAccount>(() =>\n Effect.succeed({\n apiVersion: \"v1\",\n kind: \"ServiceAccount\",\n metadata: {\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: input.annotations\n }\n })\n )\n\n const cronJob = CronJob.make({\n name: input.name,\n namespace: input.namespace,\n labels: { ...selectorLabels, ...input.labels },\n annotations: input.annotations,\n schedule: input.schedule,\n concurrencyPolicy: input.concurrencyPolicy,\n successfulJobsHistoryLimit: input.successfulJobsHistoryLimit,\n failedJobsHistoryLimit: input.failedJobsHistoryLimit,\n jobTemplate: {\n spec: {\n template: {\n metadata: { labels: selectorLabels },\n spec: {\n containers: input.containers,\n volumes: input.volumes,\n imagePullSecrets: input.imagePullSecrets,\n serviceAccountName: input.name,\n restartPolicy: input.restartPolicy ?? \"OnFailure\"\n }\n }\n }\n }\n })\n\n return M.make((ctx) => Effect.all([sa.render(ctx), cronJob.render(ctx)], { concurrency: \"unbounded\" }))\n}\n","export * as K8s from \"./.generated/k8s-types\"\nexport {\n Container,\n type ContainerInput,\n type ContainerSpec,\n type DefineContainerInput,\n type DefinedPod,\n type DefinePodInput,\n Pod,\n type PodSpecInput\n} from \"./container\"\nexport {\n type ContainerPort,\n type ContainerProtocol,\n type ExecAction,\n type GrpcAction,\n type HttpGetAction,\n type HttpHeader,\n type NamesOf,\n Port,\n type PortInput,\n type PortName,\n type ProbeTarget,\n type ServicePortSpec,\n type TcpSocketAction\n} from \"./ports\"\n\nexport {\n type ConfigMapEnvInput,\n EnvVar,\n type EnvVarSource,\n type RawEnvInput,\n type SecretEnvForPodInput,\n type SecretEnvInput,\n type ValueEnvInput\n} from \"./env\"\nexport {\n ConfigMap,\n type ConfigMapInput,\n type ConfigMapManifest,\n Namespace,\n type NamespaceInput,\n type NamespaceManifest,\n type SecretInput,\n type SecretManifest,\n ServiceAccount,\n type ServiceAccountInput,\n type ServiceAccountManifest\n} from \"./identity\"\nimport { Environment as _EnvironmentContract, runtime as envRuntime, Secret as _SecretContract } from \"@konfig.ts/env\"\nimport { bindEnvironment } from \"./environmentBind\"\nimport { Secret as _SecretIdentity } from \"./identity\"\nimport { bindSecret } from \"./secretBind\"\n\n// Compile-time guard for the namespace merges below: resolves to `false`\n// (a type error at the `= true` assignment) if `A` and `B` share a key,\n// so a same-named member added upstream can't silently shadow one of\n// ours via spread order instead of failing the build.\ntype IsDisjoint<A, B> = keyof A & keyof B extends never ? true : false\n\n/**\n * `Secret` value namespace — merges the env-contracts side (`define`)\n * with the K8s side (`make`, `bind`, identity helpers). Importing\n * `Secret` from `@konfig.ts/k8s` gives you the full surface:\n *\n * Secret.define({ name, namespace, env }) — env contract (from @konfig.ts/env)\n * Secret.make({ name, namespace, stringData }) — K8s Secret manifest\n * Secret.bind({ secret, backend, source }) — env-to-manifest binder\n */\nconst _secretContractIdentityDisjoint: IsDisjoint<typeof _SecretContract, typeof _SecretIdentity> = true\nconst _secretBindDisjoint: IsDisjoint<\n typeof _SecretContract & typeof _SecretIdentity,\n { readonly bind: typeof bindSecret }\n> = true\nexport const Secret = { ..._SecretContract, ..._SecretIdentity, bind: bindSecret }\n\n/**\n * `Environment` value namespace — merges `define` (env-contracts) with\n * `bind` + `runtime` (K8s). The same `Environment` symbol carries the\n * declaration, the manifest binder, and the runtime decoder.\n */\nconst _environmentBindRuntimeDisjoint: IsDisjoint<\n typeof _EnvironmentContract,\n { readonly bind: typeof bindEnvironment; readonly runtime: typeof envRuntime }\n> = true\nexport const Environment = {\n ..._EnvironmentContract,\n bind: bindEnvironment,\n runtime: envRuntime\n}\nexport { type BackendEmitInput, type BackendTag, type SecretBackend } from \"./backend\"\nexport type {\n BindEnvironmentInput,\n DeclaredDownward,\n DeclaredEnvironment,\n DeclaredLiteral,\n DeclaredMember,\n HasSecrets,\n SecretMemberOptions,\n SecretMemberOptionsFor,\n SecretMembersOpts\n} from \"./environmentBind\"\nexport { NativeSecret, type NativeSecretOptions } from \"./nativeSecret\"\nexport {\n Ingress,\n type IngressInput,\n type IngressTLSInput,\n Service,\n type ServiceFromContainerInput,\n type ServiceFromPodSetInput,\n type ServiceInput\n} from \"./network\"\nexport { hashSecretValues, type HashSecretValuesInput } from \"./podHash\"\nexport {\n ClusterRole,\n ClusterRoleBinding,\n type ClusterRoleBindingInput,\n type ClusterRoleInput,\n NetworkPolicy,\n type NetworkPolicyEgressRule,\n type NetworkPolicyFromPodSetInput,\n type NetworkPolicyIngressRule,\n type NetworkPolicyInput,\n type NetworkPolicyPeer,\n PersistentVolume,\n PersistentVolumeClaim,\n type PersistentVolumeClaimInput,\n type PersistentVolumeInput,\n Role,\n RoleBinding,\n type RoleBindingInput,\n type RoleInput\n} from \"./policy\"\nexport type { ConfigMapRefName, PvcRefName, SecretRefName } from \"./refs\"\nexport { ConfigMapRef, PvcRef, SecretRef, ServiceAccountRef } from \"./refs\"\nexport type { BindSecretInput, DeclaredSecret } from \"./secretBind\"\nexport { Volume } from \"./volume\"\nexport type {\n EmptyVolumeInput,\n VolumeFromConfigMapInput,\n VolumeFromPvcInput,\n VolumeFromSecretInput,\n VolumeMount,\n VolumeName,\n VolumeNamesOf\n} from \"./volume\"\nexport {\n CronJob,\n type CronJobInput,\n Deployment,\n type DeploymentFromPodSetInput,\n type DeploymentInput,\n Job,\n type JobInput,\n StatefulSet,\n type StatefulSetInput\n} from \"./workload\"\n\nexport { type DefinePodSetInput, PodSet } from \"./podSet\"\nexport { Selector } from \"./selector\"\nexport type { SelectorLabels } from \"./selector\"\nexport * as Workload from \"./workloadHelpers\"\n"],"mappings":"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"}
|
package/dist/nativeSecret.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Secret as K8sSecret } from "./.generated/k8s-types";
|
|
1
2
|
import { type SecretBackend } from "./backend";
|
|
2
3
|
export interface NativeSecretOptions {
|
|
3
4
|
readonly type?: string;
|
|
@@ -5,5 +6,5 @@ export interface NativeSecretOptions {
|
|
|
5
6
|
readonly silenceWarning?: boolean;
|
|
6
7
|
}
|
|
7
8
|
export declare const NativeSecret: {
|
|
8
|
-
backend: <N extends string, K extends string>(opts?: NativeSecretOptions) => SecretBackend<N, K, true>;
|
|
9
|
+
backend: <N extends string, K extends string>(opts?: NativeSecretOptions) => SecretBackend<N, K, true, K8sSecret>;
|
|
9
10
|
};
|
package/dist/secretBind.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Dep,
|
|
1
|
+
import { Dep, Manifest, RenderError, type SecretRef } from "@konfig.ts/core";
|
|
2
2
|
import type { SecretEntry, SecretSource } from "@konfig.ts/env";
|
|
3
3
|
import { type Context, type Layer } from "effect";
|
|
4
4
|
import type { SecretBackend } from "./backend";
|
|
5
5
|
import { EnvVar } from "./env";
|
|
6
|
-
|
|
6
|
+
interface _DeclaredSecretBase<N extends string, K extends string, Ns extends string> {
|
|
7
7
|
readonly ref: SecretRef<N, K, Ns>;
|
|
8
8
|
readonly name: N;
|
|
9
9
|
readonly namespace: Ns;
|
|
@@ -11,9 +11,15 @@ export interface DeclaredSecret<N extends string, K extends string, Ns extends s
|
|
|
11
11
|
readonly envVars: ReadonlyArray<EnvVar>;
|
|
12
12
|
readonly manifest?: Manifest.Manifest<unknown>;
|
|
13
13
|
readonly refLayer: Layer.Layer<Dep.Provide<"Secret", N>>;
|
|
14
|
-
readonly values?: Context.Service<Dep.Need<"SecretValues", N>, Dep.SecretValuesRecord<K>>;
|
|
15
|
-
readonly layer?: Layer.Layer<Dep.Provide<"SecretValues", N>, RenderError, Manifest.RenderServices>;
|
|
16
14
|
}
|
|
15
|
+
type _SecretValuesFields<N extends string, K extends string> = {
|
|
16
|
+
readonly values: Context.Service<Dep.Need<"SecretValues", N>, Dep.SecretValuesRecord<K>>;
|
|
17
|
+
readonly layer: Layer.Layer<Dep.Provide<"SecretValues", N>, RenderError, Manifest.RenderServices>;
|
|
18
|
+
} | {
|
|
19
|
+
readonly values?: undefined;
|
|
20
|
+
readonly layer?: undefined;
|
|
21
|
+
};
|
|
22
|
+
export type DeclaredSecret<N extends string, K extends string, Ns extends string = string> = _DeclaredSecretBase<N, K, Ns> & _SecretValuesFields<N, K>;
|
|
17
23
|
export interface BindSecretInput<N extends string, K extends string, E extends Readonly<Record<K, string>>, Ns extends string = string> {
|
|
18
24
|
readonly secret: SecretEntry<N, K, E>;
|
|
19
25
|
readonly backend?: SecretBackend<N, K>;
|
|
@@ -34,3 +40,4 @@ export interface BindSecretInput<N extends string, K extends string, E extends R
|
|
|
34
40
|
readonly namespace?: Ns;
|
|
35
41
|
}
|
|
36
42
|
export declare const bindSecret: <N extends string, K extends string, E extends Readonly<Record<K, string>>, const Ns extends string = string>(input: BindSecretInput<N, K, E, Ns>) => DeclaredSecret<N, K, Ns>;
|
|
43
|
+
export {};
|
package/dist/workload.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Manifest } from "@konfig.ts/core";
|
|
2
|
-
import type { CronJob as K8sCronJob, Deployment as K8sDeployment, Job as K8sJob, StatefulSet as K8sStatefulSet } from "./.generated/k8s-types";
|
|
2
|
+
import type { CronJob as K8sCronJob, Deployment as K8sDeployment, DeploymentStrategy, Job as K8sJob, PersistentVolumeClaim as K8sPersistentVolumeClaim, StatefulSet as K8sStatefulSet, StatefulSetUpdateStrategy } from "./.generated/k8s-types";
|
|
3
3
|
import type { PodSpecInput } from "./container";
|
|
4
4
|
import type { Selector } from "./selector";
|
|
5
5
|
interface WorkloadMeta {
|
|
@@ -22,7 +22,7 @@ interface SelectorAndTemplate {
|
|
|
22
22
|
}
|
|
23
23
|
export interface DeploymentInput extends WorkloadMeta, SelectorAndTemplate {
|
|
24
24
|
readonly replicas?: number;
|
|
25
|
-
readonly strategy?:
|
|
25
|
+
readonly strategy?: DeploymentStrategy;
|
|
26
26
|
readonly revisionHistoryLimit?: number;
|
|
27
27
|
readonly progressDeadlineSeconds?: number;
|
|
28
28
|
readonly minReadySeconds?: number;
|
|
@@ -48,7 +48,7 @@ export interface DeploymentFromPodSetInput<L extends Readonly<Record<string, str
|
|
|
48
48
|
};
|
|
49
49
|
readonly spec: PodSpecInput;
|
|
50
50
|
};
|
|
51
|
-
readonly strategy?:
|
|
51
|
+
readonly strategy?: DeploymentStrategy;
|
|
52
52
|
readonly revisionHistoryLimit?: number;
|
|
53
53
|
readonly progressDeadlineSeconds?: number;
|
|
54
54
|
readonly minReadySeconds?: number;
|
|
@@ -60,9 +60,9 @@ export declare const Deployment: {
|
|
|
60
60
|
export interface StatefulSetInput extends WorkloadMeta, SelectorAndTemplate {
|
|
61
61
|
readonly replicas?: number;
|
|
62
62
|
readonly serviceName: string;
|
|
63
|
-
readonly volumeClaimTemplates?: ReadonlyArray<
|
|
63
|
+
readonly volumeClaimTemplates?: ReadonlyArray<K8sPersistentVolumeClaim>;
|
|
64
64
|
readonly podManagementPolicy?: string;
|
|
65
|
-
readonly updateStrategy?:
|
|
65
|
+
readonly updateStrategy?: StatefulSetUpdateStrategy;
|
|
66
66
|
}
|
|
67
67
|
export declare const StatefulSet: {
|
|
68
68
|
make: (input: StatefulSetInput) => Manifest.Manifest<K8sStatefulSet>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@konfig.ts/k8s",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Kubernetes resource builders (workloads, network, identity, policy, volume, env) for konfig.ts.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "David Stahl-Gruber",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"postpack": "node ../../scripts/prepack-exports.mjs restore"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@konfig.ts/core": "0.0.
|
|
54
|
-
"@konfig.ts/env": "0.0.
|
|
53
|
+
"@konfig.ts/core": "0.0.10",
|
|
54
|
+
"@konfig.ts/env": "0.0.10",
|
|
55
55
|
"kubernetes-types": "~1.30.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|