feat(cloudflare): add DNS pointing integration

Implement Cloudflare connection management, pointing groups and members, asynchronous A-record reconciliation, node IP triggers, admin APIs, management pages, migrations, tests, and documentation.
This commit is contained in:
ryan
2026-08-04 12:32:37 +08:00
parent 99f0f63b99
commit 3edcdb9e9f
47 changed files with 7019 additions and 49 deletions
+2 -1
View File
@@ -16,6 +16,7 @@ import (
"testing"
"time"
"github.com/Rain-kl/Wavelet/internal/apps/openflare/credential"
"github.com/Rain-kl/Wavelet/internal/repository"
"github.com/Rain-kl/Wavelet/internal/infra/config"
@@ -128,7 +129,7 @@ func TestCreateCertificateEncryptsPrivateKey(t *testing.T) {
stored, err := repository.GetTLSCertificateByID(ctx, certificate.ID)
require.NoError(t, err)
assert.NotEqual(t, keyPEM, stored.KeyPEM)
assert.Contains(t, stored.KeyPEM, sensitiveValuePrefix)
assert.Contains(t, stored.KeyPEM, credential.Prefix)
content, err := GetCertificateContent(ctx, certificate.ID)
require.NoError(t, err)
+3 -44
View File
@@ -3,40 +3,10 @@
package tls
import (
"crypto/sha256"
"encoding/hex"
"errors"
"strings"
"github.com/Rain-kl/Wavelet/internal/infra/config"
"github.com/Rain-kl/Wavelet/pkg/util"
)
const sensitiveValuePrefix = "enc:v1:"
func sensitiveEncryptionKey() string {
if config.Config == nil || strings.TrimSpace(config.Config.App.SessionSecret) == "" {
return ""
}
sum := sha256.Sum256([]byte(config.Config.App.SessionSecret))
return hex.EncodeToString(sum[:])
}
import "github.com/Rain-kl/Wavelet/internal/apps/openflare/credential"
func sealSensitive(plaintext string) (string, error) {
plaintext = strings.TrimSpace(plaintext)
if plaintext == "" {
return "", nil
}
key := sensitiveEncryptionKey()
if key == "" {
return plaintext, nil
}
encrypted, err := util.Encrypt(key, plaintext)
if err != nil {
return "", err
}
return sensitiveValuePrefix + encrypted, nil
return credential.Seal(plaintext)
}
// OpenKeyPEM decrypts a stored certificate private key for runtime distribution.
@@ -45,16 +15,5 @@ func OpenKeyPEM(stored string) (string, error) {
}
func openSensitive(stored string) (string, error) {
stored = strings.TrimSpace(stored)
if stored == "" {
return "", nil
}
if !strings.HasPrefix(stored, sensitiveValuePrefix) {
return stored, nil
}
key := sensitiveEncryptionKey()
if key == "" {
return "", errors.New("cannot decrypt sensitive field without session secret")
}
return util.Decrypt(key, strings.TrimPrefix(stored, sensitiveValuePrefix))
return credential.Open(stored)
}