/*
observability.workers.validate — offline lint ensuring every wrangler config exports traces to the signoz destination (RFC-0339).
- Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.
- RFC-0339: initial implementation.
*/
import { join } from "node:path";
import type {
CheckResult,
Diagnostic,
KernelCommandInput,
KernelCommandResult,
KernelRuntimeContext,
} from "@warpgogol/werkstatt-engine/kernel";
import { diagnosticsResult } from "@warpgogol/werkstatt-shared/checks";
interface WranglerConfig {
main?: string;
observability?: {
enabled?: boolean;
head_sampling_rate?: number;
traces?: {
enabled?: boolean;
destinations?: string[];
head_sampling_rate?: number;
};
logs?: {
enabled?: boolean;
head_sampling_rate?: number;
};
};
}
function stripJsonComments(text: string): string {
return text.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
}
function parseJsonc(text: string): WranglerConfig {
const stripped = stripJsonComments(text);
const cleaned = stripped.replace(/,(\s*[}\]])/g, "$1");
return JSON.parse(cleaned) as WranglerConfig;
}
const WRANGLER_GLOBS = [
"apps/*/wrangler.jsonc",
"services/*/wrangler.jsonc",
"packages/os/site-kernel-onboarding/src/templates/wrangler.template.jsonc",
];
export async function runObservabilityWorkersValidate(
_input: KernelCommandInput,
context: KernelRuntimeContext,
): Promise> {
const diagnostics: Diagnostic[] = [];
const root = context.workspaceRoot;
for (const glob of WRANGLER_GLOBS) {
const files = await context.io.glob(glob, { cwd: root });
for (const file of files) {
const normalized = file.replace(/\\/g, "/");
const text = await context.io.readFile(join(root, normalized));
let config: WranglerConfig;
try {
config = parseJsonc(text);
} catch {
diagnostics.push({
ruleId: "OBS-WRK-01",
severity: "error",
file: normalized,
message: `Failed to parse wrangler config as JSONC.`,
fixHint: "Fix the JSONC syntax error in this file.",
});
continue;
}
// Skip config-only fragments (no main entry = not a deployable Worker)
if (!config.main) continue;
const obs = config.observability;
const isTemplate = normalized.includes("wrangler.template.jsonc");
// OBS-WRK-01: traces.enabled must be true
if (!obs?.traces?.enabled) {
diagnostics.push({
ruleId: "OBS-WRK-01",
severity: "error",
file: normalized,
message: `Wrangler config with main entry lacks observability.traces.enabled: true.`,
fixHint: isTemplate
? "Add the traces block to the onboarding template; regenerate site wrangler files."
: 'Add "traces": { "enabled": true, "destinations": ["signoz"], "head_sampling_rate": 1.0 } to the observability block.',
});
continue;
}
// OBS-WRK-02: destinations must be exactly ["signoz"]
const destinations = obs.traces.destinations;
if (!destinations || destinations.length !== 1 || destinations[0] !== "signoz") {
diagnostics.push({
ruleId: "OBS-WRK-02",
severity: "error",
file: normalized,
message: `observability.traces.destinations must be exactly ["signoz"], got: ${JSON.stringify(destinations)}`,
fixHint: 'Set "destinations": ["signoz"] — no other destinations are allowed.',
});
}
// OBS-WRK-03: sampling rate and logs.enabled warnings
if (obs.traces.head_sampling_rate !== 1.0) {
diagnostics.push({
ruleId: "OBS-WRK-03",
severity: "warning",
file: normalized,
message: `observability.traces.head_sampling_rate is ${obs.traces.head_sampling_rate}, expected 1.0.`,
fixHint: "Set head_sampling_rate to 1.0 until fleet scale demands sampling.",
});
}
if (!obs.logs?.enabled) {
diagnostics.push({
ruleId: "OBS-WRK-03",
severity: "warning",
file: normalized,
message: `observability.logs.enabled is not true.`,
fixHint: "Enable logs in the observability block.",
});
}
}
}
return diagnosticsResult("observability.workers.validate", diagnostics);
}