Files
codebuddy 3750b5be9f fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
fix(config): stop injecting certificate/private-key into non-cert-protocol listeners
Root cause: generateListeners unconditionally ran certstore.Load + TLS
ensure + cert copy-back for every protocol. Protocols whose Mihomo
listener schema has no top-level certificate/private-key (shadowsocks,
snell, shadowquic, mieru, sudoku — verified against
dongchengjie/meta-json-schema) then failed schema validation and got
skipped, breaking config generation.
The most common trigger: certstore is keyed by listener ID only. A
cert-capable protocol (e.g. vless, ID 1) mints+saves a PEM pair; when
that ID is later reused by a non-cert protocol (SQLite reuses deleted
row IDs, or the operator switched protocols), certstore.Load returns
the stale PEM, ensureListenerTLSMaterial sees a complete pair and keeps
it, and ValidateListenerConfig hard-rejects the unsupported field.
This manifested as 4 pre-existing test failures in internal/mihomo/config
(TestGenerateListenersUsesNativeSchema,
TestGenerateShadowQUICUsesCredentialsAsList, TestConfigEngineGeneration,
TestGenerateListenersForExportNormalizesShadowQUICUsers) — the test
suite self-contaminated via the shared on-disk certstore.
Fix:
- generator.go: add listenerProtocolSupportsCertField() (derives from
MihomoListenerSchemas.Fields["certificate"]). Guard certstore.Load,
ensureListenerTLSMaterial, cert copy-back, and certstore.Save behind
supportsCert. For non-cert protocols, strip any stale
certificate/private-key/private_key/allow-insecure before validation.
- hydrate.go: guard HydrateListenersFromDisk + HydrateFromMihomoYAML
with protocolSupportsCertField() so startup hydration does not pollute
non-cert-protocol DB configs (certstore cannot import mihomo/config
without a circular dep, so the list is local with a sync comment).
- main_test.go: TestMain isolates certstore to a per-run temp dir
(3M_UI_CERT_DIR) so tests are hermetic regardless of host disk state.
All 4 previously-failing tests now pass; full backend suite green
(go test ./... ok). go vet + gofmt clean.
Reference schemas checked:
- shadowsocks: password/cipher/udp/mux-option/shadow-tls/res-tls/
jls-config/kcp-tun/simple-obfs — NO certificate/private-key.
- shadowquic: users/jls-upstream/alpn/quic-versions/.../mux-option —
NO certificate/private-key.
2026-09-14 13:55:12 +08:00
..