Skip to main content

System and audit tables

Two system-domain tables. Aivory has no schema_migrations-style bookkeeping table — migrations run as embedded schema + idempotent ALTERs + backfill marker rows inside settings (see the overview's migration section).

settings — global key/value configuration

Most runtime configuration lives here, not in environment variables — saved from the admin UI it takes effect on the next request without restart; across replicas it invalidates via the Redis cfg:invalidate channel (cmd/api/main.go:82-90). 3 columns.

ColumnTypeNullableDefaultNotes
keyTEXTno (PK)configuration key
valueTEXTnoJSON-encoded: "true" carries quotes; arrays/objects likewise. Bare text and JSON values are not interchangeable
updated_atINTEGER → BIGINTnonow()last write time

Boot-seeded keys (store.Seed, store.go:1118-1232)

All seeded via INSERT INTO settings(key, value) VALUES(?, ?) ON CONFLICT(key) DO NOTHING (store.go:1220) — admin edits are never overwritten. Values shown as JSON literals:

KeySeed valueMeaning
default_model_id, task_model_id, title_model_id, file_route_model_id, context_compaction_model_id, tool_route_model_id, image_prompt_model_id, verify_model_id""Model-policy slots (Model policy admin page); all empty = chat is non-functional
rag_full_text_threshold8000Documents at/below this estimated token count are injected in full; above it they are vectorized and chunk-retrieved
rag_top_k8retrieved chunk count
rag_dynamic_topkfalsetake every chunk above the similarity threshold instead
rag_similarity_threshold0.5cosine cutoff for dynamic mode
rag_rerank_enabled / rag_rerank_api_url / rag_rerank_api_key / rag_rerank_modelfalse / "" / "" / ""optional OpenAI-format reranking (independent of chat channels, knowledge-base retrieval only)
credit_preflight_enabledtrueestimate prompt tokens before generation and refuse if the user cannot afford the turn
keep_recent_rounds6rounds kept verbatim by compaction
summary_max_tokens8192summary block token cap
compaction_request_max_tokens32768compaction request cap
context_compaction_prompt""custom compaction prompt
compaction_token_trigger32000automatic compaction trigger
compaction_token_cap80000compaction ceiling
compaction_token_target_percentage60post-compaction target share
compaction_retention_percentage40retention share
compaction_enabledtrueautomatic compaction switch
memory_enabledtruelong-term memory switch
daily_message_limit / daily_image_limitfrom DAILY_MESSAGE_LIMIT(200) / IMAGE_DAILY_LIMIT(30)daily quota seeds
daily_token_limit0daily token cap (0 = unlimited; backs the daily_token windows in quota_ledger)
max_concurrent_generations3per-user concurrent generations
password_login_enabledtrueallow password logins
auth_entry_mode"login_page"login entry form factor
auth_default_provider_id""default social login provider
oauth_initial_password_policy"required"whether OAuth-created accounts must set a password
oauth_auto_provision_enabledtrueauto-create accounts on first OAuth login
signup_opentrueregistration open
email_verification_requiredfalsenew accounts start as users.status='pending' when on
email_domain_whitelist""registration domain allowlist
register_ip_daily_limit0accounts per client IP per day (0 = unlimited)
register_captcha_required / login_captcha_requiredfalseslider-puzzle captcha gates
credits_per_usd01 USD of model cost = N credits; 0 disables credits platform-wide
settlement_currency"USD"single administrator-chosen currency for user-facing prices
card_purchase_url""external card-purchase link
disabled_tools[]platform-disabled built-in tool ids
sandbox_base_url / sandbox_api_key"" / ""sandbox sidecar connection (admin page can override the env values)
storage_provider"local"object storage backend: local / s3 / aliyun_oss ("" = off)
storage_archive_ttl_days30sandbox workspace archive retention (0 = keep forever)
max_image_upload_mb5image upload soft cap (MAX_UPLOAD_BYTES stays the absolute ceiling)
moderation_keywords / moderation_model_id / moderation_categories / moderation_message[] / "" / 7 default categories / default copycontent moderation word list, model, and blocked-message text
log_full_requests / log_errors_only / log_request_bodiesfalse / true / truelogging privacy switches (govern usage_logs.request_* retention)
announcement{"enabled":false,"title":"","body":"","image_url":"","remember_dismiss":true,"require_read":false,"updated_at":0} (seed default, store.go:1218)the single global notice (image_url non-empty = image notice; updated_at doubles as the dismiss version stamp)

In addition, the one-time backfill/cleanup idempotency markers are rows of this very table (the complete set: oauth_pwset_backfill_v1, msg_search_text_backfill_v1, user_sort_order_backfill_v1, user_onboarded_backfill_v1, user_group_billing_prices_backfill_v2, message_feedback_backfill_v1, daily_token_quota_ledger_backfill_v1, user_tool_mode_settings_cleanup_v1) — they are Aivory's "migration bookkeeping". Retired keys are deleted by migration (summary_target_percent, summary_merge_max_tokens, store.go:32-35,469).

Known stale code comment

store.go:1176-1177 describes register_captcha_required as an "arithmetic captcha (text math question)"; the actual implementation is a slider-puzzle captcha (/api/public/captcha, internal/api/captcha.go). Behavior wins over the comment.

pending_storage_cleanup — delete-purge queue

The pre-deletion manifest of the async account purge (§8.1-A). 3 columns.

ColumnTypeNullableDefaultNotes
pathTEXTno (PK)object-storage key / local path awaiting physical unlink (the PK doubles as the dedupe)
user_idTEXTnoowning user. Deliberately no FK — the user row may already be gone while the manifest must survive
created_atINTEGER → BIGINTnonow()registration time
  • Protocol: register paths first → run destructive SQL → unlink bytes and delete rows one by one; whatever remains is swept at startup. The table being non-empty at any moment only means a previous physical purge was interrupted; an app restart converges it (operational SQL example 8 in the overview).