feat(config): add config/default.yaml with full default settings
Adds a documented YAML configuration covering every typed section in `lib/config/src/`. Field names match the struct definitions (snake_case), sections with `#[serde(deny_unknown_fields)]` (chat, gateway, live) are minimal. Comments document the loader behaviour, APP__SECTION__FIELD env override convention, and the config-rs feature flag needed for YAML.
zhenyi committed
Added config/default.yaml config/default.yaml +428 −0 View config/default.yaml
@@ -0,0 +1,428 @@
1# =============================================================================
2# Default configuration for the untitled workspace.
3#
4# File format / loader:
5# * This file is loaded by `config_rs::Config::File::with_name(...)`. The
6# workspace's `config-rs` dependency is currently enabled with `features
7# = ["toml"]` only, so to consume this YAML you must either:
8# - enable the `yaml` feature on the `config-rs` crate in the workspace
9# Cargo.toml (preferred), and pass the path to a loader, e.g.
10# ConfigLoader::new().config_file("config/default.yaml").load()
11# - or convert this file to TOML and load `config.toml` (the default
12# the loader already looks for).
13# * Field names match the structs in `lib/config/src/*.rs` (snake_case).
14# Sections that use `#[serde(deny_unknown_fields)]` (`chat`, `gateway`,
15# `live`) will reject any extra key — keep these blocks minimal.
16#
17# Override at runtime via environment variables using the loader's
18# `APP__SECTION__FIELD` convention (separator is `__`, prefix is `APP`).
19# Examples:
20# APP__DB__PRIMARY__URL=postgres://...
21# APP__JWT__ACCESS_TTL=15m
22# APP__GIT_SSH__PORT=2222
23#
24# All fields have working defaults in code; this file only needs to override
25# the ones you want different from the in-code defaults. Keys you omit fall
26# back to those defaults.
27# =============================================================================
28
29# -----------------------------------------------------------------------------
30# Primary relational database (Postgres).
31# `replicas` is a read-replica pool; leave empty when not using one.
32# -----------------------------------------------------------------------------
33db:
34 primary:
35 url: "postgres://untitled:untitled@127.0.0.1:5432/untitled"
36 max_connections: 20
37 min_connections: 2
38 max_lifetime: 1800 # seconds
39 idle_timeout: 600 # seconds
40 acquire_timeout: 5 # seconds
41 schema: null
42 application_name: "gitdataai"
43 replicas: []
44 max_connections_total: 100
45 query_timeout: 30 # seconds
46 auto_migrate: true
47 sqlx_logging: false
48 slow_query_threshold_ms: 500
49
50# -----------------------------------------------------------------------------
51# Redis used for cache, queue coordination, rate limiting, presence, etc.
52# -----------------------------------------------------------------------------
53cache:
54 urls:
55 - "redis://127.0.0.1:6379"
56 mode: "Single" # Single | Cluster | Sentinel (PascalCase variants)
57 connection_timeout_ms: 2000
58 response_timeout_ms: 5000
59 password: null
60 database: 0
61
62# -----------------------------------------------------------------------------
63# In-process LRU cache (moka). Optional on-disk spill is disabled by default.
64# -----------------------------------------------------------------------------
65app_cache:
66 enabled: true
67 ttl_seconds: 300
68 max_capacity: 10000
69 max_size: 50000000 # bytes
70 enable_disk: false
71 disk_path: null
72 disk_cache_max_size: 200000000
73 disk_cache_max_capacity: 100000
74
75# -----------------------------------------------------------------------------
76# Kafka (rdkafka) producer/consumer settings shared by every queue consumer.
77# `topic_prefix` is prepended to every domain topic.
78# -----------------------------------------------------------------------------
79queue:
80 enabled: true
81 brokers: "127.0.0.1:9092"
82 client_id: "untitled"
83 topic_prefix: "untitled"
84 default_group_id: "untitled"
85 message_timeout_ms: 5000
86 session_timeout_ms: 10000
87 auto_offset_reset: "earliest" # earliest | latest | none
88 producer_compression: "lz4" # none | gzip | snappy | lz4 | zstd
89 producer_acks: "all" # 0 | 1 | all
90 publish_queue_timeout_ms: 1000
91 subscribe_max_retries: 3
92 subscribe_graceful_shutdown_ms: 5000
93 additional_properties: {}
94
95# -----------------------------------------------------------------------------
96# Outbound SMTP for transactional email (verification codes, digests, etc.).
97# -----------------------------------------------------------------------------
98email:
99 enabled: true
100 smtp_host: "127.0.0.1"
101 smtp_port: 587
102 smtp_username: null
103 smtp_password: null
104 from_address: "no-reply@example.com"
105 from_name: "No Reply"
106 connection_timeout_ms: 5000
107 response_timeout_ms: 10000
108 template_dir: null
109 default_locale: "en"
110 max_attachment_bytes: 26214400 # 25 MiB
111 subscriber_group_id: "email-service"
112 auto_offset_reset: "earliest"
113
114# -----------------------------------------------------------------------------
115# Blob storage backend (avatars, attachments, exports).
116# `backend` selects between `local` and `s3` blocks.
117# -----------------------------------------------------------------------------
118storage:
119 backend: "local" # local | s3
120 local:
121 root_dir: "./storage"
122 s3:
123 endpoint: null
124 region: "us-east-1"
125 bucket: ""
126 access_key_id: null
127 secret_access_key: null
128 prefix: null
129 allow_http: false
130
131# -----------------------------------------------------------------------------
132# JWT signing parameters. Durations accept seconds (`900`), a number (`15m`),
133# or `seconds.nanoseconds` (`900.0`).
134# `hmac_secret` / private key material is read at runtime — keep the placeholder
135# here and inject the real value via env (`APP__JWT__...`).
136# -----------------------------------------------------------------------------
137jwt:
138 issuer: "untitled"
139 audience: "untitled-api"
140 access_ttl: "15m"
141 refresh_ttl: "30d"
142 grace_window: "5m"
143 clock_skew_seconds: 60
144 default_grace_duration: "7d"
145 default_key_pair_algorithm: "EdDSA"
146
147# -----------------------------------------------------------------------------
148# Password policy, cookies, OAuth, agreements.
149# OAuth provider blocks are nullable; leave null when the provider is unused.
150# -----------------------------------------------------------------------------
151auth:
152 password_policy:
153 min_length: 8
154 require_upper: true
155 require_lower: true
156 require_digit: true
157 require_symbol: false
158 verify_code_ttl_secs: 600
159 verify_code_len: 6
160 reset_token_ttl_secs: 1800
161 reset_token_bytes: 32
162 cookie_name_prefix: "auth_"
163 cookie_secure: true
164 cookie_same_site: "Strict"
165 cookie_domain: null
166 oauth_state_ttl_secs: 300
167 email_code_rate_limit_secs: 60
168 max_verify_attempts: 5
169 auto_register_agreements: []
170 oauth:
171 google: null
172 github: null
173 apple: null
174 agreements:
175 terms:
176 key: "terms"
177 version: "0.1.0"
178 updated_at: "1970-01-01T00:00:00Z"
179 title: "Terms (placeholder)"
180 content_md: |
181 # Terms
182 This document is a placeholder. Please replace before production.
183 privacy:
184 key: "privacy"
185 version: "0.1.0"
186 updated_at: "1970-01-01T00:00:00Z"
187 title: "Privacy (placeholder)"
188 content_md: |
189 # Privacy
190 This document is a placeholder. Please replace before production.
191
192# -----------------------------------------------------------------------------
193# Proof-of-work challenge used to throttle anonymous traffic.
194# `hmac_secret` must be injected via env in production.
195# -----------------------------------------------------------------------------
196pow:
197 hmac_secret: ""
198 algorithm: "PBKDF2/SHA-256"
199 cost: 100000
200 key_length: 32
201 key_prefix: "00"
202 memory_cost: null
203 parallelism: null
204 challenge_ttl: "5m"
205
206# -----------------------------------------------------------------------------
207# Limits / defaults for the issues tracker.
208# -----------------------------------------------------------------------------
209issues:
210 max_pagination: 100
211 default_pagination: 20
212 max_title_len: 255
213 max_body_len: 65535
214 max_collection_name_len: 100
215 max_label_name_len: 50
216 max_label_color_len: 7
217 max_milestone_title_len: 100
218 max_milestone_description_len: 1024
219 max_comment_len: 65535
220 default_collection_name: "default"
221 max_reaction_emoji_len: 32
222 max_attachment_size_bytes: 10485760 # 10 MiB
223 max_dependency_label_len: 100
224 max_event_content_len: 4096
225
226# -----------------------------------------------------------------------------
227# Project cache TTLs and pagination caps.
228# -----------------------------------------------------------------------------
229project:
230 cache_ttl_project_secs: 300
231 cache_ttl_member_role_secs: 60
232 cache_ttl_favorites_secs: 600
233 default_page_size: 20
234 max_page_size: 100
235
236# -----------------------------------------------------------------------------
237# Repository (git) limits and storage roots. Paths must be non-empty — the
238# loader rejects empty git/lfs roots via AppConfig::validate.
239# -----------------------------------------------------------------------------
240repo:
241 max_pagination: 100
242 default_pagination: 20
243 max_repo_name_len: 100
244 max_description_len: 512
245 max_website_len: 256
246 max_topic_len: 35
247 max_branch_name_len: 100
248 max_tag_name_len: 100
249 max_release_body_len: 65535
250 default_branch: "main"
251 default_object_format: "sha1"
252 git_storage_root: "/var/lib/repo/git"
253 lfs_storage_root: "/var/lib/repo/lfs"
254 branch_protection_priority_max: 10000
255 max_topics_per_repo: 25
256 max_pr_title_len: 255
257 max_pr_body_len: 65535
258
259# -----------------------------------------------------------------------------
260# Spaces (workspaces / orgs) limits.
261# -----------------------------------------------------------------------------
262space:
263 max_pagination: 100
264 default_pagination: 20
265 max_space_name_len: 64
266 max_space_desc_len: 512
267 max_role_name_len: 64
268 max_alias_name_len: 64
269 max_invite_email_len: 320
270 max_channel_name_len: 64
271 max_topic_len: 256
272 max_purpose_len: 512
273 invite_expiry_hours: 24
274
275# -----------------------------------------------------------------------------
276# User profiles, rate limits, deletion grace.
277# `default_visibility` is `public | registered_only | members_only | private`.
278# -----------------------------------------------------------------------------
279user:
280 max_profile_pagination: 100
281 default_profile_pagination: 20
282 max_username_len: 64
283 min_username_len: 1
284 max_display_name_len: 64
285 max_bio_len: 512
286 max_pronouns_len: 32
287 max_website_len: 256
288 max_location_len: 128
289 max_company_len: 128
290 max_meme_name_len: 64
291 max_recovery_codes: 10
292 access_key_token_bytes: 32
293 ssh_key_max_per_user: 50
294 deletion_grace_days: 14
295 follow_rate_limit_secs: 60
296 block_rate_limit_secs: 60
297 report_rate_limit_secs: 300
298 notifications_unread_cache_ttl_secs: 3600
299 default_visibility: "registered_only"
300 default_locale: "en"
301 default_timezone: "UTC"
302
303# -----------------------------------------------------------------------------
304# Payment provider integration (Airwallex).
305# -----------------------------------------------------------------------------
306payment:
307 currency: "CNY"
308 max_pagination: 100
309 airwallex:
310 base_url: ""
311 client_id: ""
312 api_key: ""
313 webhook_secret: ""
314
315# -----------------------------------------------------------------------------
316# Global rate-limit defaults.
317# -----------------------------------------------------------------------------
318rate_limit:
319 default_limit: 100
320 window_secs: 60
321 cookie_name: "rl_id"
322 cookie_secure: true
323
324# -----------------------------------------------------------------------------
325# Meilisearch settings.
326# -----------------------------------------------------------------------------
327search:
328 enabled: true
329 host: "http://127.0.0.1:7700"
330 api_key: null # master/admin key; null is allowed for local dev
331 index_prefix: "untitled"
332 default_primary_key: "id"
333 batch_size: 1000
334 task_wait_timeout_ms: 30000
335 task_poll_interval_ms: 50
336
337# -----------------------------------------------------------------------------
338# Chat / live-chat messaging (storagelayer + glayer).
339# `topic_prefix` MUST equal `gateway.topic_prefix` below — enforced at startup.
340# This struct uses `deny_unknown_fields`; do not add keys that aren't listed.
341# -----------------------------------------------------------------------------
342chat:
343 enabled: true
344 topic_prefix: "chat"
345 room_group_id: "chat.room.v1"
346 user_group_id: "chat.user.v1"
347 user_view_group_id: "chat.user.view.v1"
348 live_group_id: "chat.live.v1"
349 dedup_ttl_seconds: 86400
350 idempotency_ttl_seconds: 86400
351 upload_ttl_seconds: 3600
352 presence_ttl_seconds: 120
353 unread_ttl_seconds: 2592000
354
355# -----------------------------------------------------------------------------
356# WebSocket gateway (presence, typing, push). `deny_unknown_fields`.
357# -----------------------------------------------------------------------------
358gateway:
359 ws_heartbeat_interval_seconds: 30
360 ws_idle_timeout_seconds: 120
361 ws_auth_timeout_seconds: 10
362 max_connections_per_user: 8
363 subscriber_id: "chat.gateway"
364 topic_prefix: "chat" # must equal chat.topic_prefix above
365 upload_presign_ttl_seconds: 900
366 typing_debounce_seconds: 2
367
368# -----------------------------------------------------------------------------
369# Live streaming backend (third-party SaaS). Disabled by default.
370# `deny_unknown_fields` — keep the key list minimal.
371# -----------------------------------------------------------------------------
372live:
373 enabled: false
374 base_url: ""
375 api_key: ""
376 api_secret: ""
377 webhook_secret: ""
378 room_token_ttl_seconds: 600
379 empty_timeout_seconds: 300
380
381# -----------------------------------------------------------------------------
382# GitSmart: HTTP smart-protocol server (clone/fetch/push, LFS).
383# -----------------------------------------------------------------------------
384git_smart:
385 bind_addr: "0.0.0.0"
386 port: 8080
387 git_storage_root: "/var/lib/repo/git"
388 lfs_storage_root: "/var/lib/repo/lfs"
389 object_cache_prefix: "gitsmart"
390 object_cache_ttl: 300
391 max_lfs_object_size: 1073741824 # 1 GiB
392
393# -----------------------------------------------------------------------------
394# GitSsh: SSH server for git+ssh transport.
395# Inactivity / keepalive durations are seconds (plain integer) per
396# `deserialize_std_duration` (also accepts `{ secs, nanos }`).
397# -----------------------------------------------------------------------------
398git_ssh:
399 bind_addr: "0.0.0.0"
400 port: 2222
401 host_key_path: "/etc/gitssh/ssh_host_ed25519_key"
402 git_storage_root: "/var/lib/repo/git"
403 max_sessions: 32
404 banner: null
405 auth_rejection_time: 1 # seconds
406 inactivity_timeout: 300 # seconds
407 keepalive_interval: 30 # seconds
408 keepalive_max: 3
409
410# -----------------------------------------------------------------------------
411# Git authentication policy.
412# -----------------------------------------------------------------------------
413git_auth:
414 allow_anonymous_read: false
415
416# -----------------------------------------------------------------------------
417# Git sync workers (Kafka-driven background re-sync).
418# -----------------------------------------------------------------------------
419git_sync:
420 queue_topic: "gta.git.sync"
421 dlq_topic: "gta.git.sync.dlq"
422 group_id: "git-sync-workers"
423 concurrency: 4
424 lock_ttl_secs: 300
425 max_commits_per_sync: 10000
426 max_lock_retries: 5
427 language_timeout_secs: 30
428 max_languages: 50
No newline at end of file