config: use D601 k3s namespace for WeChat collector
This commit is contained in:
@@ -67,7 +67,7 @@ interface WechatArchiveConfig {
|
||||
personalWechatIngress: {
|
||||
enabled: boolean;
|
||||
mode: string;
|
||||
target: { id: string; windowsRoute: string; hostRoute: string; dockerRoute: string };
|
||||
target: { id: string; windowsRoute: string; hostRoute: string; kubeRoute: string };
|
||||
pcWechat: {
|
||||
isolation: string;
|
||||
requiredVersion: string;
|
||||
@@ -91,7 +91,10 @@ interface WechatArchiveConfig {
|
||||
};
|
||||
collector: {
|
||||
runtime: string;
|
||||
containerName: string;
|
||||
namespace: string;
|
||||
createNamespace: boolean;
|
||||
workload: { kind: string; name: string; serviceAccountName: string; replicas: number; containerName: string };
|
||||
storage: { kind: string; name: string; mountPath: string; create: boolean };
|
||||
wcfHost: string;
|
||||
commandPort: number;
|
||||
messagePort: number;
|
||||
@@ -151,7 +154,7 @@ export function wechatArchiveHelp(): Record<string, unknown> {
|
||||
boundary: {
|
||||
langbot: "Receives WeChat/OpenClaw events and forwards archive events to the YAML-declared n8n webhook.",
|
||||
n8n: "Stores a YAML-rendered workflow that normalizes WeChat payloads.",
|
||||
personalWechatIngress: "Optionally declares the D601 Windows PC WeChat + WeChatFerry host and Docker read-only collector boundary.",
|
||||
personalWechatIngress: "Optionally declares the D601 Windows PC WeChat + WeChatFerry host and D601 k3s read-only collector boundary.",
|
||||
baiduNetdisk: "Uploads and downloads through the private backend-core microservice proxy; Baidu credentials remain in the baidu-netdisk service.",
|
||||
database: "LangBot and n8n continue to use the single PK01/Pika01 external PostgreSQL instance with separate databases/roles.",
|
||||
},
|
||||
@@ -550,10 +553,11 @@ function policyChecks(config: WechatArchiveConfig): Array<Record<string, unknown
|
||||
{ name: "baidu-private-proxy", ok: config.baiduNetdisk.proxyMode === "backend-core-microservice-proxy", detail: "Baidu Netdisk access stays behind backend-core microservice proxy." },
|
||||
{ name: "callback-token-source-ref", ok: Boolean(config.archiveCallback.tokenSourceRef && config.archiveCallback.tokenKey), detail: "n8n archive callback token is read from a YAML-declared local sourceRef and never reverse-engineered from runtime." },
|
||||
{ name: "personal-wechat-read-only", ok: config.langbot.readOnlyRecord.enabled && config.langbot.readOnlyRecord.discardPipelineUuid === "__discard__", detail: "LangBot inbound webhook must return skip_pipeline=true and bot fallback must discard so personal WeChat receives no automated replies." },
|
||||
{ name: "personal-wechat-ingress-yaml", ok: config.personalWechatIngress.enabled === true, detail: "D601 PC WeChat + WeChatFerry host and Docker collector boundary is declared in YAML." },
|
||||
{ name: "personal-wechat-ingress-yaml", ok: config.personalWechatIngress.enabled === true, detail: "D601 PC WeChat + WeChatFerry host and k3s collector boundary is declared in YAML." },
|
||||
{ name: "wcf-version-pin", ok: config.personalWechatIngress.pcWechat.requiredVersion === config.personalWechatIngress.wcfHost.requiredWechatVersion, detail: "The isolated PC WeChat version and WCF host requirement must match in YAML." },
|
||||
{ name: "wcf-no-public-exposure", ok: config.personalWechatIngress.wcfHost.firewall.publicExposure === false, detail: "WeChatFerry raw RPC must not be publicly exposed." },
|
||||
{ name: "collector-read-only", ok: config.personalWechatIngress.collector.readOnly.enabled === true && config.personalWechatIngress.collector.readOnly.sendCapability === false, detail: "Docker collector is a read-only WCF RPC client and must not export send/friend/group/database surfaces." },
|
||||
{ name: "collector-existing-namespace", ok: config.personalWechatIngress.collector.runtime === "d601-k3s" && config.personalWechatIngress.collector.namespace === "platform-infra" && config.personalWechatIngress.collector.createNamespace === false, detail: "D601 collector reuses the existing platform-infra namespace; namespace creation is disabled." },
|
||||
{ name: "collector-read-only", ok: config.personalWechatIngress.collector.readOnly.enabled === true && config.personalWechatIngress.collector.readOnly.sendCapability === false, detail: "k3s collector is a read-only WCF RPC client and must not export send/friend/group/database surfaces." },
|
||||
{ name: "collector-port-alignment", ok: config.personalWechatIngress.collector.commandPort === config.personalWechatIngress.wcfHost.commandPort && config.personalWechatIngress.collector.messagePort === config.personalWechatIngress.wcfHost.messagePort, detail: "Collector WCF ports must match the Windows WCF host ports declared in YAML." },
|
||||
{ name: "test-account-first", ok: config.personalWechatIngress.poc.accountPolicy === "test-account-first", detail: "Initial PoC must use a test or low-risk WeChat account before any production account promotion." },
|
||||
{ name: "single-pk01-postgres", ok: true, detail: "LangBot and n8n use dedicated databases inside the single PK01/Pika01 external PostgreSQL instance; this workflow adds no PostgreSQL instance." },
|
||||
@@ -569,6 +573,8 @@ function parsePersonalWechatIngress(raw: Record<string, unknown>): WechatArchive
|
||||
const wcfHost = recordField(raw, "wcfHost", `${configLabel}.personalWechatIngress`);
|
||||
const firewall = recordField(wcfHost, "firewall", `${configLabel}.personalWechatIngress.wcfHost`);
|
||||
const collector = recordField(raw, "collector", `${configLabel}.personalWechatIngress`);
|
||||
const workload = recordField(collector, "workload", `${configLabel}.personalWechatIngress.collector`);
|
||||
const storage = recordField(collector, "storage", `${configLabel}.personalWechatIngress.collector`);
|
||||
const readOnly = recordField(collector, "readOnly", `${configLabel}.personalWechatIngress.collector`);
|
||||
const poc = recordField(raw, "poc", `${configLabel}.personalWechatIngress`);
|
||||
return {
|
||||
@@ -578,7 +584,7 @@ function parsePersonalWechatIngress(raw: Record<string, unknown>): WechatArchive
|
||||
id: stringField(target, "id", `${configLabel}.personalWechatIngress.target`),
|
||||
windowsRoute: stringField(target, "windowsRoute", `${configLabel}.personalWechatIngress.target`),
|
||||
hostRoute: stringField(target, "hostRoute", `${configLabel}.personalWechatIngress.target`),
|
||||
dockerRoute: stringField(target, "dockerRoute", `${configLabel}.personalWechatIngress.target`),
|
||||
kubeRoute: stringField(target, "kubeRoute", `${configLabel}.personalWechatIngress.target`),
|
||||
},
|
||||
pcWechat: {
|
||||
isolation: stringField(pcWechat, "isolation", `${configLabel}.personalWechatIngress.pcWechat`),
|
||||
@@ -606,7 +612,21 @@ function parsePersonalWechatIngress(raw: Record<string, unknown>): WechatArchive
|
||||
},
|
||||
collector: {
|
||||
runtime: stringField(collector, "runtime", `${configLabel}.personalWechatIngress.collector`),
|
||||
containerName: stringField(collector, "containerName", `${configLabel}.personalWechatIngress.collector`),
|
||||
namespace: stringField(collector, "namespace", `${configLabel}.personalWechatIngress.collector`),
|
||||
createNamespace: booleanField(collector, "createNamespace", `${configLabel}.personalWechatIngress.collector`),
|
||||
workload: {
|
||||
kind: stringField(workload, "kind", `${configLabel}.personalWechatIngress.collector.workload`),
|
||||
name: stringField(workload, "name", `${configLabel}.personalWechatIngress.collector.workload`),
|
||||
serviceAccountName: stringField(workload, "serviceAccountName", `${configLabel}.personalWechatIngress.collector.workload`),
|
||||
replicas: numberField(workload, "replicas", `${configLabel}.personalWechatIngress.collector.workload`),
|
||||
containerName: stringField(workload, "containerName", `${configLabel}.personalWechatIngress.collector.workload`),
|
||||
},
|
||||
storage: {
|
||||
kind: stringField(storage, "kind", `${configLabel}.personalWechatIngress.collector.storage`),
|
||||
name: stringField(storage, "name", `${configLabel}.personalWechatIngress.collector.storage`),
|
||||
mountPath: stringField(storage, "mountPath", `${configLabel}.personalWechatIngress.collector.storage`),
|
||||
create: booleanField(storage, "create", `${configLabel}.personalWechatIngress.collector.storage`),
|
||||
},
|
||||
wcfHost: stringField(collector, "wcfHost", `${configLabel}.personalWechatIngress.collector`),
|
||||
commandPort: numberField(collector, "commandPort", `${configLabel}.personalWechatIngress.collector`),
|
||||
messagePort: numberField(collector, "messagePort", `${configLabel}.personalWechatIngress.collector`),
|
||||
@@ -631,6 +651,24 @@ function parsePersonalWechatIngress(raw: Record<string, unknown>): WechatArchive
|
||||
|
||||
function validatePersonalWechatIngress(config: WechatArchiveConfig["personalWechatIngress"]): void {
|
||||
if (!config.enabled) return;
|
||||
if (config.mode !== "d601-windows-wcf-host-with-k3s-collector") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.mode must be d601-windows-wcf-host-with-k3s-collector`);
|
||||
}
|
||||
if (config.target.id !== "D601" || config.target.kubeRoute !== "D601:k3s") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.target must route the collector through D601:k3s`);
|
||||
}
|
||||
if (config.collector.runtime !== "d601-k3s") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.collector.runtime must be d601-k3s`);
|
||||
}
|
||||
if (config.collector.namespace !== "platform-infra" || config.collector.createNamespace !== false) {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.collector must reuse platform-infra with createNamespace=false`);
|
||||
}
|
||||
if (config.collector.workload.kind !== "Deployment") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.collector.workload.kind must be Deployment`);
|
||||
}
|
||||
if (config.collector.storage.kind !== "PersistentVolumeClaim") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.collector.storage.kind must be PersistentVolumeClaim`);
|
||||
}
|
||||
if (config.pcWechat.requiredVersion !== config.wcfHost.requiredWechatVersion) {
|
||||
throw new Error(`${configLabel}.personalWechatIngress pcWechat.requiredVersion and wcfHost.requiredWechatVersion must match`);
|
||||
}
|
||||
@@ -649,6 +687,9 @@ function validatePersonalWechatIngress(config: WechatArchiveConfig["personalWech
|
||||
if (config.collector.archiveCallbackRef !== "archiveCallback") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.collector.archiveCallbackRef must point at archiveCallback`);
|
||||
}
|
||||
if (config.collector.wcfHost === "host.docker.internal") {
|
||||
throw new Error(`${configLabel}.personalWechatIngress.collector.wcfHost must be reachable from D601 k3s, not Docker host.docker.internal`);
|
||||
}
|
||||
}
|
||||
|
||||
function personalWechatIngressSummary(config: WechatArchiveConfig["personalWechatIngress"]): Record<string, unknown> {
|
||||
@@ -679,7 +720,10 @@ function personalWechatIngressSummary(config: WechatArchiveConfig["personalWecha
|
||||
},
|
||||
collector: {
|
||||
runtime: config.collector.runtime,
|
||||
containerName: config.collector.containerName,
|
||||
namespace: config.collector.namespace,
|
||||
createNamespace: config.collector.createNamespace,
|
||||
workload: config.collector.workload,
|
||||
storage: config.collector.storage,
|
||||
wcfHost: config.collector.wcfHost,
|
||||
commandPort: config.collector.commandPort,
|
||||
messagePort: config.collector.messagePort,
|
||||
|
||||
Reference in New Issue
Block a user