This commit is contained in:
+233
-167
@@ -2,6 +2,7 @@ package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -22,91 +23,100 @@ const (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ServiceName string
|
||||
Environment string
|
||||
LogLevel string
|
||||
HTTPAddr string
|
||||
DatabaseURL string
|
||||
RedisAddr string
|
||||
RedisPassword string
|
||||
RedisDB int
|
||||
AuthIssuerURL string
|
||||
AuthJWKSURL string
|
||||
AuthAudience string
|
||||
OTLPEndpoint string
|
||||
RateLimitRPS float64
|
||||
RateLimitBurst int
|
||||
RateLimitUserRPS float64
|
||||
RateLimitUserBurst int
|
||||
RateLimitTenantRPS float64
|
||||
RateLimitTenantBurst int
|
||||
RateLimitDeviceRPS float64
|
||||
RateLimitDeviceBurst int
|
||||
ProviderStartRPS float64
|
||||
ProviderStartBurst int
|
||||
ProviderMaxActiveTasks int
|
||||
DeviceLocalSecret string
|
||||
DeviceSecretDirectory string
|
||||
DeviceClockSkew time.Duration
|
||||
RTCAppID string
|
||||
RTCAppKey string
|
||||
RTCTokenIssuer string
|
||||
RTCTokenSecret string
|
||||
CursorSigningSecret string
|
||||
ShareTokenSecret string
|
||||
RTCTokenTTL time.Duration
|
||||
AllocationTTL time.Duration
|
||||
HeartbeatInterval int
|
||||
ProviderCallbackSecret string
|
||||
ProviderCallbackSkew time.Duration
|
||||
PlatformHealthSecret string
|
||||
PlatformHealthSkew time.Duration
|
||||
MockProviderBaseURL string
|
||||
MockProviderAPIKey string
|
||||
VoiceProvider string
|
||||
VolcRTCBaseURL string
|
||||
VolcAccessKeyID string
|
||||
VolcSecretAccessKey string
|
||||
VolcSessionToken string
|
||||
VolcRTCRegion string
|
||||
VolcRTCAPIVersion string
|
||||
VolcVoiceChatTemplate string
|
||||
ProviderRequestTimeout time.Duration
|
||||
ProviderFailureThreshold int
|
||||
ProviderCircuitCooldown time.Duration
|
||||
DependencyTimeout time.Duration
|
||||
ExternalProbeInterval time.Duration
|
||||
ShutdownTimeout time.Duration
|
||||
WorkerPollInterval time.Duration
|
||||
RecoveryScanInterval time.Duration
|
||||
RecoveryStartingAfter time.Duration
|
||||
RecoveryStoppingAfter time.Duration
|
||||
ObjectStoreEndpoint string
|
||||
ObjectStorePublic string
|
||||
ObjectStoreAccessKey string
|
||||
ObjectStoreSecretKey string
|
||||
ObjectStoreBucket string
|
||||
ObjectStoreRegion string
|
||||
ObjectStoreSecure bool
|
||||
ObjectStorePublicSecure bool
|
||||
ExportDownloadTTL time.Duration
|
||||
ExportObjectTTL time.Duration
|
||||
MediaLocalDeleteGrace time.Duration
|
||||
AlertWebhookURL string
|
||||
AlertWebhookSecret string
|
||||
AlertWebhookTimeout time.Duration
|
||||
ContentGenerator string
|
||||
ArkBaseURL string
|
||||
ArkAPIKey string
|
||||
ArkContentModel string
|
||||
ArkRequestTimeout time.Duration
|
||||
ContentSafetyProvider string
|
||||
ContentSafetyEndpoint string
|
||||
ContentSafetyAPIKey string
|
||||
ContentSafetyPolicyRef string
|
||||
ContentSafetyTimeout time.Duration
|
||||
EmbeddingProvider string
|
||||
ArkEmbeddingModel string
|
||||
ServiceName string
|
||||
Environment string
|
||||
LogLevel string
|
||||
HTTPAddr string
|
||||
DatabaseURL string
|
||||
RedisAddr string
|
||||
RedisPassword string
|
||||
RedisDB int
|
||||
AuthIssuerURL string
|
||||
AuthJWKSURL string
|
||||
AuthAudience string
|
||||
OTLPEndpoint string
|
||||
RateLimitRPS float64
|
||||
RateLimitBurst int
|
||||
RateLimitUserRPS float64
|
||||
RateLimitUserBurst int
|
||||
RateLimitTenantRPS float64
|
||||
RateLimitTenantBurst int
|
||||
RateLimitDeviceRPS float64
|
||||
RateLimitDeviceBurst int
|
||||
ProviderStartRPS float64
|
||||
ProviderStartBurst int
|
||||
ProviderMaxActiveTasks int
|
||||
DeviceLocalSecret string
|
||||
DeviceCredentialMasterKey string
|
||||
DeviceClockSkew time.Duration
|
||||
RTCAppID string
|
||||
RTCAppKey string
|
||||
RTCTokenIssuer string
|
||||
RTCTokenSecret string
|
||||
CursorSigningSecret string
|
||||
ShareTokenSecret string
|
||||
RTCTokenTTL time.Duration
|
||||
AllocationTTL time.Duration
|
||||
HeartbeatInterval int
|
||||
ProviderCallbackSecret string
|
||||
ProviderCallbackSkew time.Duration
|
||||
PlatformHealthSecret string
|
||||
PlatformHealthSkew time.Duration
|
||||
MockProviderBaseURL string
|
||||
MockProviderAPIKey string
|
||||
VoiceProvider string
|
||||
VolcRTCBaseURL string
|
||||
VolcAccessKeyID string
|
||||
VolcSecretAccessKey string
|
||||
VolcSessionToken string
|
||||
VolcRTCRegion string
|
||||
VolcRTCAPIVersion string
|
||||
VolcVoiceChatTemplate string
|
||||
ProviderRequestTimeout time.Duration
|
||||
ProviderFailureThreshold int
|
||||
ProviderCircuitCooldown time.Duration
|
||||
DependencyTimeout time.Duration
|
||||
ExternalProbeInterval time.Duration
|
||||
ShutdownTimeout time.Duration
|
||||
WorkerPollInterval time.Duration
|
||||
RecoveryScanInterval time.Duration
|
||||
RecoveryStartingAfter time.Duration
|
||||
RecoveryStoppingAfter time.Duration
|
||||
ObjectStoreEndpoint string
|
||||
ObjectStorePublic string
|
||||
ObjectStoreAccessKey string
|
||||
ObjectStoreSecretKey string
|
||||
ObjectStoreBucket string
|
||||
ObjectStoreRegion string
|
||||
ObjectStoreSecure bool
|
||||
ObjectStorePublicSecure bool
|
||||
ExportDownloadTTL time.Duration
|
||||
ExportObjectTTL time.Duration
|
||||
MediaLocalDeleteGrace time.Duration
|
||||
AlertWebhookURL string
|
||||
AlertWebhookSecret string
|
||||
AlertWebhookTimeout time.Duration
|
||||
ContentGenerator string
|
||||
ArkBaseURL string
|
||||
ArkAPIKey string
|
||||
ArkContentModel string
|
||||
ArkRequestTimeout time.Duration
|
||||
ContentSafetyProvider string
|
||||
ContentSafetyEndpoint string
|
||||
ContentSafetyAPIKey string
|
||||
ContentSafetyPolicyRef string
|
||||
ContentSafetyTimeout time.Duration
|
||||
EmbeddingProvider string
|
||||
ArkEmbeddingModel string
|
||||
MemoryToolBaseURL string
|
||||
MemoryToolSigningSecret string
|
||||
MemoryToolTokenTTL time.Duration
|
||||
MemoryToolRateRPS float64
|
||||
MemoryToolRateBurst int
|
||||
ProviderMemoryMode string
|
||||
ProviderMemoryBaseURL string
|
||||
ProviderMemoryAPIKey string
|
||||
ProviderMemoryTimeout time.Duration
|
||||
}
|
||||
|
||||
func Load(serviceName string) (Config, error) {
|
||||
@@ -198,6 +208,14 @@ func Load(serviceName string) (Config, error) {
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
providerMemoryTimeout, err := durationEnv("PROVIDER_MEMORY_TIMEOUT", 5*time.Second)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
memoryToolTokenTTL, err := durationEnv("MEMORY_TOOL_TOKEN_TTL", 4*time.Hour)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
objectStoreSecure, err := boolEnv("OBJECT_STORE_SECURE", false)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
@@ -208,15 +226,16 @@ func Load(serviceName string) (Config, error) {
|
||||
}
|
||||
environment := stringEnv("APP_ENV", EnvironmentLocal)
|
||||
secretValues, err := loadSecretValues(
|
||||
"DATABASE_URL", "REDIS_PASSWORD", "DEVICE_LOCAL_SECRET", "RTC_APP_KEY", "RTC_TOKEN_SIGNING_SECRET",
|
||||
"DATABASE_URL", "REDIS_PASSWORD", "DEVICE_LOCAL_SECRET", "DEVICE_CREDENTIAL_MASTER_KEY", "RTC_APP_KEY", "RTC_TOKEN_SIGNING_SECRET",
|
||||
"CURSOR_SIGNING_SECRET", "SHARE_TOKEN_SIGNING_SECRET", "PROVIDER_CALLBACK_SECRET", "PLATFORM_HEALTH_CALLBACK_SECRET",
|
||||
"MOCK_PROVIDER_API_KEY", "VOLC_ACCESS_KEY_ID", "VOLC_SECRET_ACCESS_KEY", "VOLC_SESSION_TOKEN",
|
||||
"OBJECT_STORE_ACCESS_KEY", "OBJECT_STORE_SECRET_KEY", "ALERT_WEBHOOK_SECRET", "ARK_API_KEY", "CONTENT_SAFETY_API_KEY",
|
||||
"OBJECT_STORE_ACCESS_KEY", "OBJECT_STORE_SECRET_KEY", "ALERT_WEBHOOK_SECRET", "ARK_API_KEY", "CONTENT_SAFETY_API_KEY", "MEMORY_TOOL_SIGNING_SECRET", "PROVIDER_MEMORY_API_KEY",
|
||||
)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
deviceLocalSecret := secretValues["DEVICE_LOCAL_SECRET"]
|
||||
deviceCredentialMasterKey := secretValues["DEVICE_CREDENTIAL_MASTER_KEY"]
|
||||
rtcTokenSecret := secretValues["RTC_TOKEN_SIGNING_SECRET"]
|
||||
cursorSigningSecret := secretValues["CURSOR_SIGNING_SECRET"]
|
||||
shareTokenSecret := secretValues["SHARE_TOKEN_SIGNING_SECRET"]
|
||||
@@ -230,6 +249,9 @@ func Load(serviceName string) (Config, error) {
|
||||
if deviceLocalSecret == "" && serviceName == "api" && (environment == EnvironmentLocal || environment == EnvironmentTest) {
|
||||
deviceLocalSecret = "local-simulated-device-secret-32-bytes-minimum"
|
||||
}
|
||||
if deviceCredentialMasterKey == "" && serviceName == "api" && (environment == EnvironmentLocal || environment == EnvironmentTest) {
|
||||
deviceCredentialMasterKey = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
}
|
||||
if rtcTokenSecret == "" && serviceName == "api" && (environment == EnvironmentLocal || environment == EnvironmentTest) {
|
||||
rtcTokenSecret = "local-simulated-rtc-token-secret-32-bytes-minimum"
|
||||
}
|
||||
@@ -239,6 +261,10 @@ func Load(serviceName string) (Config, error) {
|
||||
if shareTokenSecret == "" && serviceName == "api" && (environment == EnvironmentLocal || environment == EnvironmentTest) {
|
||||
shareTokenSecret = "local-share-token-signing-secret-32-bytes-minimum"
|
||||
}
|
||||
memoryToolSigningSecret := secretValues["MEMORY_TOOL_SIGNING_SECRET"]
|
||||
if memoryToolSigningSecret == "" && (serviceName == "api" || serviceName == "worker") && (environment == EnvironmentLocal || environment == EnvironmentTest) {
|
||||
memoryToolSigningSecret = "local-memory-tool-signing-secret-32-bytes-minimum"
|
||||
}
|
||||
if providerCallbackSecret == "" && serviceName == "callbacks" && (environment == EnvironmentLocal || environment == EnvironmentTest) {
|
||||
providerCallbackSecret = "local-provider-callback-secret-32-bytes-minimum"
|
||||
}
|
||||
@@ -264,78 +290,85 @@ func Load(serviceName string) (Config, error) {
|
||||
}
|
||||
|
||||
cfg := Config{
|
||||
ServiceName: serviceName,
|
||||
Environment: environment,
|
||||
LogLevel: stringEnv("LOG_LEVEL", "info"),
|
||||
HTTPAddr: stringEnv("HTTP_ADDR", defaultHTTPAddr(serviceName)),
|
||||
DatabaseURL: secretDefault(secretValues["DATABASE_URL"], "postgres://voice:voice_dev_only@localhost:55432/voice_platform?sslmode=disable"),
|
||||
RedisAddr: stringEnv("REDIS_ADDR", "localhost:56379"),
|
||||
RedisPassword: secretValues["REDIS_PASSWORD"],
|
||||
RedisDB: redisDB,
|
||||
AuthIssuerURL: stringEnv("AUTH_ISSUER_URL", "http://localhost:58180/realms/voice-local"),
|
||||
AuthJWKSURL: stringEnv("AUTH_JWKS_URL", "http://localhost:58180/realms/voice-local/protocol/openid-connect/certs"),
|
||||
AuthAudience: stringEnv("AUTH_AUDIENCE", "voice-platform-web"),
|
||||
OTLPEndpoint: stringEnvAllowEmpty("OTEL_EXPORTER_OTLP_ENDPOINT", "localhost:54317"),
|
||||
DependencyTimeout: dependencyTimeout,
|
||||
ExternalProbeInterval: externalProbeInterval,
|
||||
ShutdownTimeout: shutdownTimeout,
|
||||
WorkerPollInterval: pollInterval,
|
||||
RecoveryScanInterval: recoveryScanInterval,
|
||||
RecoveryStartingAfter: recoveryStartingAfter,
|
||||
RecoveryStoppingAfter: recoveryStoppingAfter,
|
||||
DeviceLocalSecret: deviceLocalSecret,
|
||||
DeviceSecretDirectory: strings.TrimSpace(os.Getenv("DEVICE_SECRET_DIRECTORY")),
|
||||
DeviceClockSkew: deviceClockSkew,
|
||||
RTCAppID: stringEnv("RTC_APP_ID", "local-public-rtc-app"),
|
||||
RTCAppKey: secretValues["RTC_APP_KEY"],
|
||||
RTCTokenIssuer: stringEnv("RTC_TOKEN_ISSUER", "local"),
|
||||
RTCTokenSecret: rtcTokenSecret,
|
||||
CursorSigningSecret: cursorSigningSecret,
|
||||
ShareTokenSecret: shareTokenSecret,
|
||||
RTCTokenTTL: rtcTokenTTL,
|
||||
AllocationTTL: allocationTTL,
|
||||
ProviderCallbackSecret: providerCallbackSecret,
|
||||
ProviderCallbackSkew: providerCallbackSkew,
|
||||
PlatformHealthSecret: secretValues["PLATFORM_HEALTH_CALLBACK_SECRET"],
|
||||
PlatformHealthSkew: platformHealthSkew,
|
||||
MockProviderBaseURL: stringEnv("MOCK_PROVIDER_BASE_URL", "http://localhost:59200"),
|
||||
MockProviderAPIKey: secretDefault(secretValues["MOCK_PROVIDER_API_KEY"], "local-mock-provider-key"),
|
||||
VoiceProvider: stringEnv("VOICE_PROVIDER", "mock"),
|
||||
VolcRTCBaseURL: stringEnv("VOLC_RTC_BASE_URL", "https://rtc.volcengineapi.com"),
|
||||
VolcAccessKeyID: secretValues["VOLC_ACCESS_KEY_ID"],
|
||||
VolcSecretAccessKey: secretValues["VOLC_SECRET_ACCESS_KEY"],
|
||||
VolcSessionToken: secretValues["VOLC_SESSION_TOKEN"],
|
||||
VolcRTCRegion: stringEnv("VOLC_RTC_REGION", "cn-north-1"),
|
||||
VolcRTCAPIVersion: stringEnv("VOLC_RTC_API_VERSION", "2024-12-01"),
|
||||
VolcVoiceChatTemplate: strings.TrimSpace(os.Getenv("VOLC_VOICE_CHAT_TEMPLATE_FILE")),
|
||||
ProviderRequestTimeout: providerRequestTimeout,
|
||||
ProviderCircuitCooldown: providerCircuitCooldown,
|
||||
ObjectStoreEndpoint: objectStoreEndpoint,
|
||||
ObjectStorePublic: objectStorePublic,
|
||||
ObjectStoreAccessKey: objectStoreAccessKey,
|
||||
ObjectStoreSecretKey: objectStoreSecretKey,
|
||||
ObjectStoreBucket: objectStoreBucket,
|
||||
ObjectStoreRegion: objectStoreRegion,
|
||||
ObjectStoreSecure: objectStoreSecure,
|
||||
ObjectStorePublicSecure: objectStorePublicSecure,
|
||||
ExportDownloadTTL: exportDownloadTTL,
|
||||
ExportObjectTTL: exportObjectTTL,
|
||||
MediaLocalDeleteGrace: mediaLocalDeleteGrace,
|
||||
AlertWebhookURL: strings.TrimSpace(os.Getenv("ALERT_WEBHOOK_URL")),
|
||||
AlertWebhookSecret: secretValues["ALERT_WEBHOOK_SECRET"],
|
||||
AlertWebhookTimeout: alertWebhookTimeout,
|
||||
ContentGenerator: stringEnv("CONTENT_GENERATOR", "local"),
|
||||
ArkBaseURL: stringEnv("ARK_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3"),
|
||||
ArkAPIKey: secretValues["ARK_API_KEY"],
|
||||
ArkContentModel: strings.TrimSpace(os.Getenv("ARK_CONTENT_MODEL")),
|
||||
ArkRequestTimeout: arkRequestTimeout,
|
||||
ContentSafetyProvider: stringEnv("CONTENT_SAFETY_PROVIDER", "local"),
|
||||
ContentSafetyEndpoint: strings.TrimSpace(os.Getenv("CONTENT_SAFETY_ENDPOINT")),
|
||||
ContentSafetyAPIKey: secretValues["CONTENT_SAFETY_API_KEY"],
|
||||
ContentSafetyPolicyRef: strings.TrimSpace(os.Getenv("CONTENT_SAFETY_POLICY_REF")),
|
||||
ContentSafetyTimeout: contentSafetyTimeout,
|
||||
EmbeddingProvider: stringEnv("EMBEDDING_PROVIDER", "local"),
|
||||
ArkEmbeddingModel: strings.TrimSpace(os.Getenv("ARK_EMBEDDING_MODEL")),
|
||||
ServiceName: serviceName,
|
||||
Environment: environment,
|
||||
LogLevel: stringEnv("LOG_LEVEL", "info"),
|
||||
HTTPAddr: stringEnv("HTTP_ADDR", defaultHTTPAddr(serviceName)),
|
||||
DatabaseURL: secretDefault(secretValues["DATABASE_URL"], "postgres://voice:voice_dev_only@localhost:55432/voice_platform?sslmode=disable"),
|
||||
RedisAddr: stringEnv("REDIS_ADDR", "localhost:56379"),
|
||||
RedisPassword: secretValues["REDIS_PASSWORD"],
|
||||
RedisDB: redisDB,
|
||||
AuthIssuerURL: stringEnv("AUTH_ISSUER_URL", "http://localhost:58180/realms/voice-local"),
|
||||
AuthJWKSURL: stringEnv("AUTH_JWKS_URL", "http://localhost:58180/realms/voice-local/protocol/openid-connect/certs"),
|
||||
AuthAudience: stringEnv("AUTH_AUDIENCE", "voice-platform-web"),
|
||||
OTLPEndpoint: stringEnvAllowEmpty("OTEL_EXPORTER_OTLP_ENDPOINT", "localhost:54317"),
|
||||
DependencyTimeout: dependencyTimeout,
|
||||
ExternalProbeInterval: externalProbeInterval,
|
||||
ShutdownTimeout: shutdownTimeout,
|
||||
WorkerPollInterval: pollInterval,
|
||||
RecoveryScanInterval: recoveryScanInterval,
|
||||
RecoveryStartingAfter: recoveryStartingAfter,
|
||||
RecoveryStoppingAfter: recoveryStoppingAfter,
|
||||
DeviceLocalSecret: deviceLocalSecret,
|
||||
DeviceCredentialMasterKey: deviceCredentialMasterKey,
|
||||
DeviceClockSkew: deviceClockSkew,
|
||||
RTCAppID: stringEnv("RTC_APP_ID", "local-public-rtc-app"),
|
||||
RTCAppKey: secretValues["RTC_APP_KEY"],
|
||||
RTCTokenIssuer: stringEnv("RTC_TOKEN_ISSUER", "local"),
|
||||
RTCTokenSecret: rtcTokenSecret,
|
||||
CursorSigningSecret: cursorSigningSecret,
|
||||
ShareTokenSecret: shareTokenSecret,
|
||||
RTCTokenTTL: rtcTokenTTL,
|
||||
AllocationTTL: allocationTTL,
|
||||
ProviderCallbackSecret: providerCallbackSecret,
|
||||
ProviderCallbackSkew: providerCallbackSkew,
|
||||
PlatformHealthSecret: secretValues["PLATFORM_HEALTH_CALLBACK_SECRET"],
|
||||
PlatformHealthSkew: platformHealthSkew,
|
||||
MockProviderBaseURL: stringEnv("MOCK_PROVIDER_BASE_URL", "http://localhost:59200"),
|
||||
MockProviderAPIKey: secretDefault(secretValues["MOCK_PROVIDER_API_KEY"], "local-mock-provider-key"),
|
||||
VoiceProvider: stringEnv("VOICE_PROVIDER", "mock"),
|
||||
VolcRTCBaseURL: stringEnv("VOLC_RTC_BASE_URL", "https://rtc.volcengineapi.com"),
|
||||
VolcAccessKeyID: secretValues["VOLC_ACCESS_KEY_ID"],
|
||||
VolcSecretAccessKey: secretValues["VOLC_SECRET_ACCESS_KEY"],
|
||||
VolcSessionToken: secretValues["VOLC_SESSION_TOKEN"],
|
||||
VolcRTCRegion: stringEnv("VOLC_RTC_REGION", "cn-north-1"),
|
||||
VolcRTCAPIVersion: stringEnv("VOLC_RTC_API_VERSION", "2024-12-01"),
|
||||
VolcVoiceChatTemplate: strings.TrimSpace(os.Getenv("VOLC_VOICE_CHAT_TEMPLATE_FILE")),
|
||||
ProviderRequestTimeout: providerRequestTimeout,
|
||||
ProviderCircuitCooldown: providerCircuitCooldown,
|
||||
ObjectStoreEndpoint: objectStoreEndpoint,
|
||||
ObjectStorePublic: objectStorePublic,
|
||||
ObjectStoreAccessKey: objectStoreAccessKey,
|
||||
ObjectStoreSecretKey: objectStoreSecretKey,
|
||||
ObjectStoreBucket: objectStoreBucket,
|
||||
ObjectStoreRegion: objectStoreRegion,
|
||||
ObjectStoreSecure: objectStoreSecure,
|
||||
ObjectStorePublicSecure: objectStorePublicSecure,
|
||||
ExportDownloadTTL: exportDownloadTTL,
|
||||
ExportObjectTTL: exportObjectTTL,
|
||||
MediaLocalDeleteGrace: mediaLocalDeleteGrace,
|
||||
AlertWebhookURL: strings.TrimSpace(os.Getenv("ALERT_WEBHOOK_URL")),
|
||||
AlertWebhookSecret: secretValues["ALERT_WEBHOOK_SECRET"],
|
||||
AlertWebhookTimeout: alertWebhookTimeout,
|
||||
ContentGenerator: stringEnv("CONTENT_GENERATOR", "local"),
|
||||
ArkBaseURL: stringEnv("ARK_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3"),
|
||||
ArkAPIKey: secretValues["ARK_API_KEY"],
|
||||
ArkContentModel: strings.TrimSpace(os.Getenv("ARK_CONTENT_MODEL")),
|
||||
ArkRequestTimeout: arkRequestTimeout,
|
||||
ContentSafetyProvider: stringEnv("CONTENT_SAFETY_PROVIDER", "local"),
|
||||
ContentSafetyEndpoint: strings.TrimSpace(os.Getenv("CONTENT_SAFETY_ENDPOINT")),
|
||||
ContentSafetyAPIKey: secretValues["CONTENT_SAFETY_API_KEY"],
|
||||
ContentSafetyPolicyRef: strings.TrimSpace(os.Getenv("CONTENT_SAFETY_POLICY_REF")),
|
||||
ContentSafetyTimeout: contentSafetyTimeout,
|
||||
EmbeddingProvider: stringEnv("EMBEDDING_PROVIDER", "local"),
|
||||
ArkEmbeddingModel: strings.TrimSpace(os.Getenv("ARK_EMBEDDING_MODEL")),
|
||||
MemoryToolBaseURL: strings.TrimSpace(os.Getenv("MEMORY_TOOL_BASE_URL")),
|
||||
MemoryToolSigningSecret: memoryToolSigningSecret,
|
||||
MemoryToolTokenTTL: memoryToolTokenTTL,
|
||||
ProviderMemoryMode: stringEnv("PROVIDER_MEMORY_MODE", "disabled"),
|
||||
ProviderMemoryBaseURL: strings.TrimSpace(os.Getenv("PROVIDER_MEMORY_BASE_URL")),
|
||||
ProviderMemoryAPIKey: secretValues["PROVIDER_MEMORY_API_KEY"],
|
||||
ProviderMemoryTimeout: providerMemoryTimeout,
|
||||
}
|
||||
cfg.RateLimitRPS, err = floatEnv("RATE_LIMIT_RPS", 50)
|
||||
if err != nil {
|
||||
@@ -381,6 +414,14 @@ func Load(serviceName string) (Config, error) {
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.MemoryToolRateRPS, err = floatEnv("MEMORY_TOOL_RATE_RPS", 2)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.MemoryToolRateBurst, err = intEnv("MEMORY_TOOL_RATE_BURST", 5)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.HeartbeatInterval, err = intEnv("HEARTBEAT_INTERVAL_SECONDS", 15)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
@@ -427,14 +468,15 @@ func (c Config) Validate() error {
|
||||
c.RateLimitUserRPS <= 0 || c.RateLimitUserBurst <= 0 ||
|
||||
c.RateLimitTenantRPS <= 0 || c.RateLimitTenantBurst <= 0 ||
|
||||
c.RateLimitDeviceRPS <= 0 || c.RateLimitDeviceBurst <= 0 ||
|
||||
c.ProviderStartRPS <= 0 || c.ProviderStartBurst <= 0 || c.ProviderMaxActiveTasks <= 0 {
|
||||
c.ProviderStartRPS <= 0 || c.ProviderStartBurst <= 0 || c.ProviderMaxActiveTasks <= 0 ||
|
||||
c.MemoryToolRateRPS <= 0 || c.MemoryToolRateBurst <= 0 {
|
||||
return errors.New("rate limits, bursts and provider task capacity must be positive")
|
||||
}
|
||||
if c.ServiceName == "api" && c.DeviceSecretDirectory == "" && len(c.DeviceLocalSecret) < 32 {
|
||||
return errors.New("DEVICE_LOCAL_SECRET must contain at least 32 characters when DEVICE_SECRET_DIRECTORY is not configured")
|
||||
}
|
||||
if c.ServiceName == "api" && c.DeviceSecretDirectory != "" && !filepath.IsAbs(c.DeviceSecretDirectory) {
|
||||
return errors.New("DEVICE_SECRET_DIRECTORY must be an absolute path")
|
||||
if c.ServiceName == "api" {
|
||||
decodedMasterKey, err := hex.DecodeString(c.DeviceCredentialMasterKey)
|
||||
if err != nil || len(decodedMasterKey) != 32 {
|
||||
return errors.New("DEVICE_CREDENTIAL_MASTER_KEY must be 32 bytes encoded as 64 hexadecimal characters")
|
||||
}
|
||||
}
|
||||
if c.DeviceClockSkew <= 0 {
|
||||
return errors.New("DEVICE_CLOCK_SKEW must be positive")
|
||||
@@ -459,6 +501,18 @@ func (c Config) Validate() error {
|
||||
if c.ServiceName == "api" && len(c.ShareTokenSecret) < 32 {
|
||||
return errors.New("SHARE_TOKEN_SIGNING_SECRET must contain at least 32 characters")
|
||||
}
|
||||
if (c.ServiceName == "api" || c.ServiceName == "worker") && (len(c.MemoryToolSigningSecret) < 32 || c.MemoryToolTokenTTL <= 0) {
|
||||
return errors.New("MEMORY_TOOL_SIGNING_SECRET must contain at least 32 characters and token TTL must be positive")
|
||||
}
|
||||
if c.MemoryToolBaseURL != "" && !isAbsoluteHTTPURL(c.MemoryToolBaseURL) {
|
||||
return errors.New("MEMORY_TOOL_BASE_URL must be an absolute HTTP(S) URL")
|
||||
}
|
||||
if c.ProviderMemoryMode != "disabled" && c.ProviderMemoryMode != "managed_http" {
|
||||
return errors.New("PROVIDER_MEMORY_MODE must be disabled or managed_http")
|
||||
}
|
||||
if (c.ServiceName == "api" || c.ServiceName == "worker") && c.ProviderMemoryMode == "managed_http" && (!isAbsoluteHTTPURL(c.ProviderMemoryBaseURL) || c.ProviderMemoryAPIKey == "" || c.ProviderMemoryTimeout <= 0) {
|
||||
return errors.New("managed provider memory requires an HTTP(S) base URL, API key and positive timeout")
|
||||
}
|
||||
if c.RTCAppID == "" || c.RTCTokenTTL <= 0 || c.AllocationTTL <= 0 || c.HeartbeatInterval <= 0 {
|
||||
return errors.New("RTC app, token TTL, allocation TTL and heartbeat interval must be valid")
|
||||
}
|
||||
@@ -570,8 +624,8 @@ func (c Config) validateProduction() error {
|
||||
}
|
||||
|
||||
if c.ServiceName == "api" {
|
||||
if c.DeviceSecretDirectory == "" {
|
||||
return errors.New("production API must use DEVICE_SECRET_DIRECTORY for per-device credentials")
|
||||
if c.DeviceCredentialMasterKey == "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" {
|
||||
return errors.New("production API must use a non-default DEVICE_CREDENTIAL_MASTER_KEY")
|
||||
}
|
||||
if isPlaceholderSecret(c.CursorSigningSecret) || isPlaceholderSecret(c.ShareTokenSecret) {
|
||||
return errors.New("production API signing secrets must not use local or example values")
|
||||
@@ -579,6 +633,12 @@ func (c Config) validateProduction() error {
|
||||
if c.CursorSigningSecret == c.ShareTokenSecret {
|
||||
return errors.New("production API signing secrets must be distinct")
|
||||
}
|
||||
if isPlaceholderSecret(c.MemoryToolSigningSecret) || c.MemoryToolSigningSecret == c.CursorSigningSecret || c.MemoryToolSigningSecret == c.ShareTokenSecret {
|
||||
return errors.New("production memory tool signing secret must be non-placeholder and distinct")
|
||||
}
|
||||
if c.MemoryToolBaseURL != "" && !isHTTPSURL(c.MemoryToolBaseURL) {
|
||||
return errors.New("production memory tool URL must use HTTPS")
|
||||
}
|
||||
if isLocalValue(c.RTCAppID) || c.RTCTokenIssuer != "volcengine" || isPlaceholderSecret(c.RTCAppKey) {
|
||||
return errors.New("production RTC credentials must use a real app ID, Volcengine token issuer and non-placeholder app key")
|
||||
}
|
||||
@@ -610,6 +670,12 @@ func (c Config) validateProduction() error {
|
||||
}
|
||||
}
|
||||
if c.ServiceName == "api" || c.ServiceName == "worker" {
|
||||
if isPlaceholderSecret(c.MemoryToolSigningSecret) {
|
||||
return errors.New("production memory tool signing secret must be non-placeholder")
|
||||
}
|
||||
if c.ProviderMemoryMode == "managed_http" && (!isHTTPSURL(c.ProviderMemoryBaseURL) || isLocalValue(c.ProviderMemoryBaseURL) || isPlaceholderSecret(c.ProviderMemoryAPIKey)) {
|
||||
return errors.New("production provider memory must use managed HTTPS and a non-placeholder API key")
|
||||
}
|
||||
if !c.ObjectStoreSecure || !c.ObjectStorePublicSecure {
|
||||
return errors.New("production object storage must use TLS")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user