fix: expose hwpod platform db secret status

This commit is contained in:
Codex
2026-06-09 07:07:30 +00:00
parent 53f319ea9d
commit cf1dc4802a
4 changed files with 132 additions and 27 deletions
+77 -25
View File
@@ -6,7 +6,7 @@ import { runHwlabG14Command } from "./hwlab-g14";
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane } from "./hwlab-node-lanes";
type SecretAction = "status" | "ensure" | "cleanup-owned-postgres";
type SecretPreset = "openfga" | "master-server-admin-api-key" | "code-agent-provider" | "cloud-api-db" | "owned-postgres-cleanup";
type SecretPreset = "openfga" | "master-server-admin-api-key" | "code-agent-provider" | "cloud-api-db" | "hwpod-db" | "owned-postgres-cleanup";
type DelegatedNodeDomain = "control-plane" | "git-mirror";
interface NodeSecretOptions {
@@ -41,6 +41,11 @@ interface RuntimeSecretSpec {
cloudApiDbUser: string;
cloudApiDbHost: string;
cloudApiDeployment: string;
hwpodDbSecret: string;
hwpodDbKey: string;
hwpodDbName: string;
hwpodDbUser: string;
hwpodDbHost: string;
codeAgentProviderSecret: string;
codeAgentProviderSourceNamespace: string;
codeAgentProviderSourceSecret: string;
@@ -87,6 +92,7 @@ export function hwlabNodeHelp(): Record<string, unknown> {
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwlab-v03-openfga",
"bun scripts/cli.ts hwlab nodes secret ensure --node G14 --lane v03 --name hwlab-v03-master-server-admin-api-key --confirm",
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwlab-cloud-api-v03-db",
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwpod-v03-db",
"bun scripts/cli.ts hwlab nodes secret cleanup-owned-postgres --node G14 --lane v03 --dry-run",
"bun scripts/cli.ts hwlab nodes secret cleanup-owned-postgres --node G14 --lane v03 --confirm",
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwlab-v03-code-agent-provider",
@@ -210,7 +216,7 @@ function rewriteDelegatedNodeString(value: string, scoped: ReturnType<typeof par
function parseSecretOptions(args: string[]): NodeSecretOptions {
const [actionRaw] = args;
if (actionRaw !== "status" && actionRaw !== "ensure" && actionRaw !== "cleanup-owned-postgres") {
throw new Error("secret usage: status|ensure --node NODE --lane vNN --name hwlab-vNN-openfga|hwlab-vNN-master-server-admin-api-key|hwlab-cloud-api-vNN-db|hwlab-vNN-code-agent-provider [--dry-run|--confirm] | cleanup-owned-postgres --node NODE --lane vNN [--dry-run|--confirm]");
throw new Error("secret usage: status|ensure --node NODE --lane vNN --name hwlab-vNN-openfga|hwlab-vNN-master-server-admin-api-key|hwlab-cloud-api-vNN-db|hwpod-vNN-db|hwlab-vNN-code-agent-provider [--dry-run|--confirm] | cleanup-owned-postgres --node NODE --lane vNN [--dry-run|--confirm]");
}
const node = requiredOption(args, "--node");
assertNodeId(node);
@@ -284,8 +290,26 @@ function parseSecretOptions(args: string[]): NodeSecretOptions {
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 240, 900),
};
}
if (name === spec.hwpodDbSecret) {
if (!spec.platformDb) throw new Error(`secret ${name} is only supported for v0.3+ platform DB lanes`);
if (key !== undefined && key !== spec.hwpodDbKey) throw new Error(`secret ${name} supports only key ${spec.hwpodDbKey}`);
if (actionRaw === "ensure") {
throw new Error(`secret ensure for ${name} on --lane ${lane} was removed after native platform DB migration; use status plus platform DB SecretRef rotation CLI when it exists`);
}
return {
action: actionRaw,
node,
lane,
name,
key: key ?? spec.hwpodDbKey,
preset: "hwpod-db",
confirm,
dryRun: true,
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 240, 900),
};
}
if (name !== spec.openFgaSecret) {
throw new Error(`secret status/ensure supports --name ${spec.openFgaSecret}, ${spec.masterAdminApiKeySecret}, ${spec.cloudApiDbSecret}, or ${spec.codeAgentProviderSecret} for --lane ${lane}`);
throw new Error(`secret status/ensure supports --name ${spec.openFgaSecret}, ${spec.masterAdminApiKeySecret}, ${spec.cloudApiDbSecret}, ${spec.hwpodDbSecret}, or ${spec.codeAgentProviderSecret} for --lane ${lane}`);
}
if (key !== undefined && key !== OPENFGA_AUTHN_KEY && key !== OPENFGA_DATASTORE_URI_KEY && key !== OPENFGA_POSTGRES_PASSWORD_KEY) {
throw new Error(`secret ${name} supports keys ${OPENFGA_AUTHN_KEY}, ${OPENFGA_DATASTORE_URI_KEY}, and ${OPENFGA_POSTGRES_PASSWORD_KEY}`);
@@ -332,6 +356,11 @@ function runtimeSecretSpec(input: { node: string; lane: string }): RuntimeSecret
cloudApiDbUser: platformDb ? `hwlab_${input.lane}_app` : `hwlab_${input.lane}`,
cloudApiDbHost: platformDb ? platformPostgresHost : legacyPostgresHost,
cloudApiDeployment: "hwlab-cloud-api",
hwpodDbSecret: `hwpod-${input.lane}-db`,
hwpodDbKey: CLOUD_API_DB_KEY,
hwpodDbName: `hwpod_${input.lane}`,
hwpodDbUser: platformDb ? `hwpod_${input.lane}_app` : `hwpod_${input.lane}`,
hwpodDbHost: platformDb ? platformPostgresHost : legacyPostgresHost,
codeAgentProviderSecret: `${namespace}-code-agent-provider`,
codeAgentProviderSourceNamespace: CODE_AGENT_PROVIDER_SOURCE_NAMESPACE,
codeAgentProviderSourceSecret: CODE_AGENT_PROVIDER_SOURCE_SECRET,
@@ -348,7 +377,7 @@ function runNodeSecret(options: NodeSecretOptions): Record<string, unknown> {
? spec.platformDb ? platformDbSecretStatusScript(options, spec) : openFgaSecretScript(options, spec)
: options.preset === "master-server-admin-api-key"
? masterAdminApiKeySecretScript(options, spec)
: options.preset === "cloud-api-db"
: options.preset === "cloud-api-db" || options.preset === "hwpod-db"
? spec.platformDb ? platformDbSecretStatusScript(options, spec) : cloudApiDbSecretScript(options, spec)
: options.preset === "owned-postgres-cleanup"
? ownedPostgresCleanupScript(options, spec)
@@ -380,7 +409,7 @@ function nextSecretCommand(options: NodeSecretOptions, spec: RuntimeSecretSpec):
if (options.action === "cleanup-owned-postgres") {
return { ensure: `bun scripts/cli.ts hwlab nodes secret cleanup-owned-postgres --node ${options.node} --lane ${options.lane} --confirm` };
}
if (spec.platformDb && (options.preset === "cloud-api-db" || options.preset === "openfga")) {
if (spec.platformDb && (options.preset === "cloud-api-db" || options.preset === "openfga" || options.preset === "hwpod-db")) {
return {
status: `bun scripts/cli.ts hwlab nodes secret status --node ${options.node} --lane ${options.lane} --name ${options.name}${options.key ? ` --key ${options.key}` : ""}`,
controlPlaneStatus: `bun scripts/cli.ts hwlab nodes control-plane status --node ${options.node} --lane ${options.lane}`,
@@ -769,12 +798,13 @@ function ownedPostgresCleanupScript(options: NodeSecretOptions, spec: RuntimeSec
function platformDbSecretStatusScript(options: NodeSecretOptions, spec: RuntimeSecretSpec): string {
const isOpenFga = options.preset === "openfga";
const isHwpodDb = options.preset === "hwpod-db";
const platformEndpointSlice = `${spec.platformPostgresService}-host`;
return [
"set +e",
`namespace=${shellQuote(spec.namespace)}`,
`name=${shellQuote(isOpenFga ? spec.openFgaSecret : spec.cloudApiDbSecret)}`,
`database_url_key=${shellQuote(isOpenFga ? OPENFGA_DATASTORE_URI_KEY : spec.cloudApiDbKey)}`,
`name=${shellQuote(isOpenFga ? spec.openFgaSecret : isHwpodDb ? spec.hwpodDbSecret : spec.cloudApiDbSecret)}`,
`database_url_key=${shellQuote(isOpenFga ? OPENFGA_DATASTORE_URI_KEY : isHwpodDb ? spec.hwpodDbKey : spec.cloudApiDbKey)}`,
`authn_key=${shellQuote(OPENFGA_AUTHN_KEY)}`,
`postgres_password_key=${shellQuote(OPENFGA_POSTGRES_PASSWORD_KEY)}`,
`legacy_postgres_secret=${shellQuote(spec.postgresSecret)}`,
@@ -782,9 +812,9 @@ function platformDbSecretStatusScript(options: NodeSecretOptions, spec: RuntimeS
`platform_endpointslice=${shellQuote(platformEndpointSlice)}`,
`platform_host=${shellQuote(spec.platformPostgresService)}`,
`platform_host_fqdn=${shellQuote(spec.openFgaDbHost)}`,
`db_name=${shellQuote(isOpenFga ? spec.openFgaDbName : spec.cloudApiDbName)}`,
`db_user=${shellQuote(isOpenFga ? spec.openFgaDbUser : spec.cloudApiDbUser)}`,
`db_host=${shellQuote(isOpenFga ? spec.openFgaDbHost : spec.cloudApiDbHost)}`,
`db_name=${shellQuote(isOpenFga ? spec.openFgaDbName : isHwpodDb ? spec.hwpodDbName : spec.cloudApiDbName)}`,
`db_user=${shellQuote(isOpenFga ? spec.openFgaDbUser : isHwpodDb ? spec.hwpodDbUser : spec.cloudApiDbUser)}`,
`db_host=${shellQuote(isOpenFga ? spec.openFgaDbHost : isHwpodDb ? spec.hwpodDbHost : spec.cloudApiDbHost)}`,
`selected_key=${shellQuote(options.key ?? "")}`,
`preset=${shellQuote(options.preset)}`,
"dry_run=true",
@@ -1432,7 +1462,13 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
summary: healthy ? `${fields.secret || spec.codeAgentProviderSecret} has a usable provider key` : `${fields.secret || spec.codeAgentProviderSecret} missing provider keys`,
};
}
if (fields.preset === "cloud-api-db") {
if (fields.preset === "cloud-api-db" || fields.preset === "hwpod-db") {
const hwpodDb = fields.preset === "hwpod-db";
const expectedSecret = hwpodDb ? spec.hwpodDbSecret : spec.cloudApiDbSecret;
const expectedKey = hwpodDb ? spec.hwpodDbKey : spec.cloudApiDbKey;
const expectedDbName = hwpodDb ? spec.hwpodDbName : spec.cloudApiDbName;
const expectedDbUser = hwpodDb ? spec.hwpodDbUser : spec.cloudApiDbUser;
const expectedDbHost = hwpodDb ? spec.hwpodDbHost : spec.cloudApiDbHost;
const beforeUrlBytes = numericField(fields.beforeDatabaseUrlBytes);
const afterUrlBytes = numericField(fields.afterDatabaseUrlBytes);
if (fields.platformDbMode === "true") {
@@ -1449,9 +1485,9 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
return {
ok: commandOk && healthy,
namespace: fields.namespace || spec.namespace,
secret: fields.secret || spec.cloudApiDbSecret,
key: fields.key || spec.cloudApiDbKey,
preset: "cloud-api-db",
secret: fields.secret || expectedSecret,
key: fields.key || expectedKey,
preset: hwpodDb ? "hwpod-db" : "cloud-api-db",
action: fields.action || null,
dryRun: fields.dryRun === "true",
mutation: fields.mutation === "true",
@@ -1472,9 +1508,9 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
endpointSlice: fields.platformEndpointSlice || `${spec.platformPostgresService}-host`,
endpointSliceExists: fields.platformEndpointSliceExists === "yes",
},
dbName: fields.dbName || spec.cloudApiDbName,
dbUser: fields.dbUser || spec.cloudApiDbUser,
dbHost: fields.dbHost || spec.cloudApiDbHost,
dbName: fields.dbName || expectedDbName,
dbUser: fields.dbUser || expectedDbUser,
dbHost: fields.dbHost || expectedDbHost,
dbHostMatchesPlatform: fields.dbHostMatchesPlatform === "yes",
dbNameMatchesExpected: fields.dbNameMatchesExpected === "yes",
dbUserMatchesExpected: fields.dbUserMatchesExpected === "yes",
@@ -1482,8 +1518,24 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
stderr: commandOk ? "" : stderr.trim().slice(0, 2000),
valuesRedacted: true,
summary: healthy
? `${fields.secret || spec.cloudApiDbSecret}/${fields.key || spec.cloudApiDbKey} points to ${fields.platformService || spec.platformPostgresService}`
: `${fields.secret || spec.cloudApiDbSecret}/${fields.key || spec.cloudApiDbKey} is not aligned to platform DB`,
? `${fields.secret || expectedSecret}/${fields.key || expectedKey} points to ${fields.platformService || spec.platformPostgresService}`
: `${fields.secret || expectedSecret}/${fields.key || expectedKey} is not aligned to platform DB`,
};
}
if (hwpodDb) {
return {
ok: false,
namespace: fields.namespace || spec.namespace,
secret: fields.secret || expectedSecret,
key: fields.key || expectedKey,
preset: "hwpod-db",
action: fields.action || null,
dryRun: fields.dryRun === "true",
mutation: false,
exitCode,
stderr: commandOk ? "" : stderr.trim().slice(0, 2000),
valuesRedacted: true,
summary: "HWPOD DB Secret status is only supported for native platform DB lanes",
};
}
const keysHealthy = fields.afterExists === "yes" &&
@@ -1494,8 +1546,8 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
return {
ok: commandOk && healthy,
namespace: fields.namespace || spec.namespace,
secret: fields.secret || spec.cloudApiDbSecret,
key: fields.key || spec.cloudApiDbKey,
secret: fields.secret || expectedSecret,
key: fields.key || expectedKey,
preset: "cloud-api-db",
action: fields.action || null,
dryRun: fields.dryRun === "true",
@@ -1521,9 +1573,9 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
},
postgresAdminSecretPresent: fields.postgresAdminSecretPresent === "yes",
postgresSecret: fields.postgresSecret || spec.postgresSecret,
dbName: fields.dbName || spec.cloudApiDbName,
dbUser: fields.dbUser || spec.cloudApiDbUser,
dbHost: fields.dbHost || spec.cloudApiDbHost,
dbName: fields.dbName || expectedDbName,
dbUser: fields.dbUser || expectedDbUser,
dbHost: fields.dbHost || expectedDbHost,
cloudApiDeployment: fields.cloudApiDeployment || spec.cloudApiDeployment,
applyExitCode: numericField(fields.applyExitCode),
dbEnsureExitCode: numericField(fields.dbEnsureExitCode),
@@ -1532,7 +1584,7 @@ function secretStatusFromText(text: string, commandOk: boolean, exitCode: number
exitCode,
stderr: commandOk ? "" : stderr.trim().slice(0, 2000),
valuesRedacted: true,
summary: healthy ? `${fields.secret || spec.cloudApiDbSecret}/${fields.key || spec.cloudApiDbKey} exists and runtime database is present` : `${fields.secret || spec.cloudApiDbSecret}/${fields.key || spec.cloudApiDbKey} or runtime database missing`,
summary: healthy ? `${fields.secret || expectedSecret}/${fields.key || expectedKey} exists and runtime database is present` : `${fields.secret || expectedSecret}/${fields.key || expectedKey} or runtime database missing`,
};
}
const afterAuthnBytes = numericField(fields.afterAuthnBytes);