Documentation
¶
Index ¶
Constants ¶
const DefaultUIClientID = "memory-ui"
DefaultUIClientID is the client_id assigned to the web UI's public PKCE OAuth client when MEMORY_UI_CLIENT_ID is unset on an OAuth-enabled instance. It keeps /ui/config.json from ever advertising an empty client and gives the boot-time seed (internal/authletstore.SeedUIClient) a stable id to register.
Variables ¶
This section is empty.
Functions ¶
func ParseAllowedDomains ¶
ParseAllowedDomains splits a comma-separated SIGNUP_ALLOWED_DOMAINS spec into a normalized allow-list: each entry lowercased and trimmed, empties dropped. An empty/whitespace-only spec yields nil (len 0), which callers treat as "public" — any verified identity may self-provision.
func ParseTenantDefaults ¶
func ParseTenantDefaults(spec string) (models.TenantDefaults, error)
ParseTenantDefaults parses "staleness=off,duplicate_guard=false,cleanup_scan_enabled=false" into a models.TenantDefaults, overlaying set keys on top of the built-in safe bundle (models.BaselineTenantDefaults). Empty = the safe bundle; whitespace-tolerant, case-insensitive; unknown keys or invalid values error.
Types ¶
type Config ¶
type Config struct {
DatabaseURL string `env:"DATABASE_URL" envDefault:"postgres://memory:memory@localhost:5432/memory?sslmode=disable"`
ServerAddr string `env:"SERVER_ADDR" envDefault:":8080"`
LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
// Embedding provider: "ollama", "gcp", "openai", "aws", or "fake". Default
// dimension matches the default model (ollama nomic-embed-text=768) so a stock
// deploy works (audit #12). For OpenAI text-embedding-3-*, also the output size.
EmbeddingProvider string `env:"EMBEDDING_PROVIDER" envDefault:"ollama"`
EmbeddingDimensions int `env:"EMBEDDING_DIMENSIONS" envDefault:"768"`
// Ollama
OllamaURL string `env:"OLLAMA_URL" envDefault:"http://localhost:11434"`
OllamaModel string `env:"OLLAMA_MODEL" envDefault:"nomic-embed-text"`
// GCP Vertex AI
GCPProject string `env:"GCP_PROJECT"`
GCPLocation string `env:"GCP_LOCATION" envDefault:"us-central1"`
GCPModel string `env:"GCP_EMBEDDING_MODEL" envDefault:"text-embedding-005"`
// OpenAI-compatible — any /v1/embeddings endpoint (OpenAI, Azure, vLLM, TEI,
// etc). APIKey optional (self-hosted often ignores it); BaseURL is the API root.
OpenAIBaseURL string `env:"OPENAI_BASE_URL" envDefault:"https://api.openai.com/v1"`
OpenAIAPIKey string `env:"OPENAI_API_KEY"`
OpenAIModel string `env:"OPENAI_EMBEDDING_MODEL"`
// AWS Bedrock. Credentials resolve from the standard AWS chain (env vars,
// shared config, IAM role) — never from these fields. Region + model only.
AWSRegion string `env:"AWS_REGION"`
AWSModel string `env:"AWS_EMBEDDING_MODEL"`
// Admin
AdminAllowedEmails string `env:"ADMIN_ALLOWED_EMAILS"`
// Cleanup pipeline — nightly lint scan populates cleanup_queue with
// near-duplicate candidates; TELEGRAM_* posts a per-scan summary. All knobs
// optional (empty disables the feature).
CleanupIntervalHours int `env:"CLEANUP_INTERVAL_HOURS" envDefault:"24"`
CleanupEnabled bool `env:"CLEANUP_ENABLED" envDefault:"true"`
TelegramBotToken string `env:"TELEGRAM_BOT_TOKEN"`
TelegramChatID string `env:"TELEGRAM_CHAT_ID"`
// DeadKeyTTLDays: a nightly sweep hard-deletes API keys that have been dead
// (revoked or expired) for longer than this, so retired keys stop cluttering
// listings. 0 disables the sweep; keys are then removed only via manual Delete.
DeadKeyTTLDays int `env:"DEAD_KEY_TTL_DAYS" envDefault:"7"`
// Retention sweep — archives docs unverified past multiplier × the doc_type
// staleness threshold, then hard-deletes deleteGraceDays after archiving. Only
// for staleness_mode=hard tenants. Both must be >= 1: below 1 collapses the
// cutoffs and would mass hard-delete live data (Load rejects; retainTenant also guards).
RetentionMultiplier int `env:"RETENTION_MULTIPLIER" envDefault:"3"`
DeleteGraceDays int `env:"RETENTION_DELETE_GRACE_DAYS" envDefault:"30"`
// HTTP hardening. MaxRequestBytes caps request bodies (0 disables). RateLimit*
// is a token-bucket throttle over the auth+write surface (RPS <= 0 disables).
// RateLimitTrustedProxyDepth is how many trusted reverse-proxy/CDN hops sit in
// front: 0 (default) trusts none and keys on RemoteAddr (X-Forwarded-For is
// ignored, unspoofable); N>=1 keys on the Nth-from-last X-Forwarded-For entry.
MaxRequestBytes int64 `env:"MAX_REQUEST_BYTES" envDefault:"1048576"`
RateLimitRPS float64 `env:"RATE_LIMIT_RPS" envDefault:"20"`
RateLimitBurst int `env:"RATE_LIMIT_BURST" envDefault:"40"`
RateLimitTrustedProxyDepth int `env:"RATE_LIMIT_TRUSTED_PROXY_DEPTH" envDefault:"0"`
// Tenant-toggle defaults. Raw spec from env, overridable via --opts;
// ParseTenantDefaults yields the typed models.TenantDefaults applied at
// AutoMigrate and tenant-create time.
TenantDefaultsSpec string `env:"MEMORY_DEFAULT_OPTS"`
TenantDefaults models.TenantDefaults
// SelfServicePolicy is the global default self-service gate: "open" (default)
// lets any member edit tenant toggles and an owner self-create API keys;
// "admin_only" raises both to admin. A nullable per-tenant column overrides
// it. Validated at load — unknown values are rejected.
SelfServicePolicy string `env:"MEMORY_SELF_SERVICE_POLICY" envDefault:"open"`
// authlet — OAuth 2.1 / OIDC AS for /mcp. AuthletMasterKey is a 32-byte hex
// key encrypting AS signing material at rest. GoogleClient* identify memory-mcp
// to Google (upstream IdP). Both Google envs set = opt into authlet: Setup must
// succeed at boot (any error fatal). Unset = /mcp is API-key-only, authlet skipped.
AuthletMasterKey string `env:"AUTHLET_MASTER_KEY"`
GoogleClientID string `env:"MEMORY_MCP_GOOGLE_CLIENT_ID"`
GoogleClientSecret string `env:"MEMORY_MCP_GOOGLE_CLIENT_SECRET"`
// UIClientID is the pre-registered public PKCE OAuth client the web UI uses
// (redirect_uri = PublicBaseURL + "/ui"). Non-secret; served to the page.
UIClientID string `env:"MEMORY_UI_CLIENT_ID"`
// SIGNUP_ALLOWED_DOMAINS gates self-serve tenant provisioning: a
// comma-separated allow-list of email domains (e.g. "example.com,acme.org")
// whose verified identities may auto-provision a personal tenant on first
// login. Entries are lowercased and trimmed at load into SignupAllowedDomains.
// Empty/unset ⇒ empty slice, meaning PUBLIC (any verified identity may
// self-provision) — see design decision 2.
SignupAllowedDomainsSpec string `env:"SIGNUP_ALLOWED_DOMAINS"`
SignupAllowedDomains []string
// PublicBaseURL is the external origin (scheme+host, no path/trailing slash),
// e.g. "https://mem.example.org". Anchors the authlet issuer/audience/PRM/
// callback URLs and the UI OAuth config. REQUIRED (absolute http(s)) when the
// authlet path is enabled; unused by the API-key-only path.
PublicBaseURL string `env:"PUBLIC_BASE_URL"`
// Reset — MemoryReset is a boot-time signal (never a route) that re-arms
// bootstrap by clearing the admin-key set only. The first-run bootstrap token
// is no longer configured via env: cmd/server/main.go generates and logs it on
// an un-bootstrapped instance (design D1; see MemoryService.BootstrapToken).
MemoryReset bool `env:"MEMORY_RESET"`
// Import jobs — bounds on the async document-import path. MaxUploadBytes caps
// the archive accepted by POST /api/admin/import (default 32 MiB).
// WorkerConcurrency bounds the in-process worker draining import_jobs.
ImportMaxUploadBytes int64 `env:"IMPORT_MAX_UPLOAD_BYTES" envDefault:"33554432"`
ImportWorkerConcurrency int `env:"IMPORT_WORKER_CONCURRENCY" envDefault:"1"`
}
func (*Config) AuthletEnabled ¶
AuthletEnabled reports whether both Google client envs are set (opt-in to the authlet OAuth path). When true, callers must require authletas.Setup to succeed.
func (*Config) EmbeddingCfg ¶
func (c *Config) EmbeddingCfg() service.EmbeddingConfig
EmbeddingCfg converts config fields into a service.EmbeddingConfig.
func (*Config) EmbeddingModel ¶
EmbeddingModel returns the active provider's model id. With EmbeddingProvider it fingerprints the corpus's embedding identity for the migration guard (audit #13/#16).