feat: 完成模拟交易闭环、App 与 A 股行情接入
Checks / verify (push) Failing after 9m52s

统一单入口 Go 工程与前端依赖目录,增加后台供应商配置、候选审核、计划预算、成交冲正、持仓复盘和站内通知。接入策略版本、Python 回测、可配置 A 股公开行情及 zap 文件轮转日志,补充迁移、契约与验证。
This commit is contained in:
2026-10-08 22:58:52 +08:00
parent bffdb3858b
commit 92329ddce2
145 changed files with 18593 additions and 587 deletions
+56
View File
@@ -0,0 +1,56 @@
// Package secret encrypts provider credentials at rest using an environment-owned key.
package secret
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"git.sundynix.cn/Blizzard/Veyra/internal/apperror"
)
type Vault struct{ aead cipher.AEAD }
func NewVault(encodedKey string) (*Vault, error) {
if encodedKey == "" {
return &Vault{}, nil
}
key, err := base64.StdEncoding.DecodeString(encodedKey)
if err != nil || len(key) != 32 {
return nil, fmt.Errorf("SECRET_ENCRYPTION_KEY must be base64 of 32 bytes")
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("initialize secret cipher")
}
aead, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("initialize secret encryption")
}
return &Vault{aead: aead}, nil
}
func (v *Vault) Encrypt(value, binding string) ([]byte, error) {
if v == nil || v.aead == nil {
return nil, apperror.ErrUnavailable
}
nonce := make([]byte, v.aead.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, apperror.ErrUnavailable
}
return v.aead.Seal(nonce, nonce, []byte(value), []byte(binding)), nil
}
func (v *Vault) Decrypt(encrypted []byte, binding string) (string, error) {
if len(encrypted) == 0 {
return "", nil
}
if v == nil || v.aead == nil || len(encrypted) < v.aead.NonceSize() {
return "", apperror.ErrUnavailable
}
value, err := v.aead.Open(nil, encrypted[:v.aead.NonceSize()], encrypted[v.aead.NonceSize():], []byte(binding))
if err != nil {
return "", apperror.ErrUnavailable
}
return string(value), nil
}