Reorganize repo: backend/, deploy/, docs/ layout + AGENTS.md

Restructure the monorepo into clear top-level directories:
- backend/: Go module root (cmd, internal, pkg, configs, migrations,
  docs/swagger, scripts, tests, go.mod, Makefile, .air.toml)
- deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd
- docs/: project documentation + reports/ (moved from repo root)
- AGENTS.md: new AI coding-agent guide at repo root

Update all references to the new layout:
- Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root)
- docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile,
  env_file ../../.env, volume mounts ../../backend:/app
- deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile
- CI: working-directory: backend for go commands, file deploy/docker/Dockerfile,
  coverage path backend/coverage.out, health_check backend/scripts/
- backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../
- README: architecture tree, quickstart, config paths updated

Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh,
gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to
preserve history. Build, vet, SQLite tests, and docker compose config verified.
This commit is contained in:
2026-07-07 14:44:12 +08:00
parent d4ef996f49
commit aeddedf2a3
1348 changed files with 176 additions and 57 deletions
+19
View File
@@ -0,0 +1,19 @@
# GoChat Development Environment Overrides
# Reference: Chatwoot config/environments/development.rb
server:
mode: "debug"
database:
name: "gochat_dev"
log_level: "info"
log:
level: "debug"
format: "console"
worker:
concurrency: 5
redis:
channel_prefix: "gochat_dev"
+29
View File
@@ -0,0 +1,29 @@
# GoChat Production Environment Overrides
# Reference: Chatwoot config/environments/production.rb
server:
mode: "release"
cors:
# PRODUCTION: Must specify exact origins or wildcard patterns.
# NEVER leave empty in production — empty + non-debug = no CORS allowed.
allowed_origins:
- "https://app.yourdomain.com"
- "https://admin.yourdomain.com"
- "*.yourdomain.com" # matches any subdomain
allow_credentials: true # needed for JWT cookie-based auth
max_age: 86400
database:
name: "gochat_production"
pool_max: 20
log_level: "warn"
log:
level: "info"
format: "json"
worker:
concurrency: 10
redis:
channel_prefix: "gochat_production"
+72
View File
@@ -0,0 +1,72 @@
server:
host: "0.0.0.0"
port: 3000
mode: "debug" # debug, release, test
cors:
allowed_origins: [] # empty = Allow-Origin:* in debug mode; production must list exact origins
# Examples:
# - "https://app.example.com"
# - "*.example.com"
allowed_methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
allowed_headers: ["Origin", "Content-Type", "Accept", "Authorization", "X-Account-ID", "access-token", "client", "uid", "token-type", "expiry"]
expose_headers: ["Content-Length", "access-token", "client", "uid", "token-type", "expiry"]
allow_credentials: false # set to true only if you need cookies/auth headers
max_age: 86400 # preflight cache duration in seconds
database:
host: "localhost"
port: 5432
user: "gochat"
password: "gochat_dev"
dbname: "gochat_dev"
sslmode: "disable"
max_idle_conns: 10
max_open_conns: 100
conn_max_lifetime: 3600 # seconds
run_migrations: false # set to true to auto-run migrations on startup
migrations_path: "migrations"
redis:
host: "localhost"
port: 6379
password: ""
db: 0
pool_size: 50
jwt:
secret: "gochat_dev_secret_change_in_production"
expiry_hours: 72
log:
level: "debug" # debug, info, warn, error
format: "json" # json, text
rate_limit:
enabled: true
requests_per_minute: 100 # max requests per client IP per window
window_seconds: 60 # sliding window duration in seconds
search:
# Chatwoot parity target. Use "db" only for explicit local fallback.
engine: "meilisearch"
host: "http://localhost:7700"
api_key: ""
index_prefix: "gochat_"
timeout_seconds: 5
saml:
enabled: false # SAML 2.0 SSO — enable for enterprise IdP integration
# IdP metadata: provide URL or inline XML (URL preferred for auto-refresh)
idp_metadata_url: "" # e.g. "https://idp.example.com/metadata"
idp_metadata_xml: "" # fallback: paste IdP metadata XML here
sp_entity_id: "https://gochat.example.com/saml" # our SP entity ID
acs_url: "https://gochat.example.com/api/v1/saml/acs" # Assertion Consumer Service URL
# SP key/certificate: PEM format (required for signed AuthnRequest + response validation)
sp_private_key: "" # path or inline PEM — generate with: openssl genrsa -out sp.key 2048
sp_certificate: "" # path or inline PEM — generate with: openssl req -new -x509 -key sp.key -out sp.crt
clock_drift_tolerance: 180 # seconds of allowed clock drift for NotOnOrAfter validation
attribute_map:
email: "email" # SAML attribute → GoChat email field
display_name: "displayName" # SAML attribute → GoChat name field
first_name: "firstName" # SAML attribute → first name component
last_name: "lastName" # SAML attribute → last name component
+65
View File
@@ -0,0 +1,65 @@
# GoChat Fluentd Configuration
# Reference: Chatwoot production uses structured JSON logging
# This config collects logs from gochat containers and forwards to outputs
<source>
@type tail
path /var/log/gochat/*.log
pos_file /var/log/fluentd/gochat.log.pos
tag gochat.app
<parse>
@type json
time_key timestamp
time_format %Y-%m-%dT%H:%M:%S.%NZ
keep_time_key true
</parse>
</source>
<source>
@type tail
path /var/log/gochat/worker.log
pos_file /var/log/fluentd/gochat-worker.log.pos
tag gochat.worker
<parse>
@type json
time_key timestamp
time_format %Y-%m-%dT%H:%M:%S.%NZ
keep_time_key true
</parse>
</source>
# Docker container logs via systemd/journald
<source>
@type systemd
filters [{ "_COMM": "docker" }]
tag docker
</source>
# ---- Outputs ----
# Console output for development
<match gochat.**>
@type stdout
</match>
# Production: send to Elasticsearch or Loki
# Uncomment based on your backend:
#
# <match gochat.**>
# @type elasticsearch
# host elasticsearch
# port 9200
# logstash_format true
# logstash_prefix gochat
# <buffer>
# @type file
# path /var/log/fluentd/buffers/gochat
# flush_interval 5s
# </buffer>
# </match>
#
# <match gochat.**>
# @type loki
# url http://loki:3100
# labels { "app": "gochat", "environment": "production" }
# </match>
+84
View File
@@ -0,0 +1,84 @@
# GoChat Prometheus Alert Rules
# Reference: Chatwoot production monitoring with Sidekiq queue alerts
# Adjust thresholds based on your deployment scale
groups:
- name: gochat-app
rules:
# Application down
- alert: GoChatAppDown
expr: up{job="gochat"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "GoChat application is down"
description: "GoChat instance {{ $labels.instance }} has been down for more than 1 minute."
# High error rate
- alert: GoChatHighErrorRate
expr: rate(http_requests_total{job="gochat", status=~"5.."}[5m]) / rate(http_requests_total{job="gochat"}[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "GoChat error rate above 5%"
description: "Error rate is {{ $value | humanizePercentage }} over the last 5 minutes."
# High memory usage
- alert: GoChatHighMemory
expr: gochat_go_memory_alloc_bytes / (1024 * 1024) > 400
for: 5m
labels:
severity: warning
annotations:
summary: "GoChat memory usage above 400MB"
description: "Memory allocation is {{ $value }}MB."
# Too many goroutines
- alert: GoChatHighGoroutines
expr: gochat_go_goroutines > 1000
for: 5m
labels:
severity: warning
annotations:
summary: "GoChat goroutine count above 1000"
description: "{{ $value }} goroutines running."
- name: gochat-infra
rules:
# PostgreSQL down
- alert: GoChatPostgresDown
expr: up{job="gochat-postgres"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "PostgreSQL is down"
# Redis down
- alert: GoChatRedisDown
expr: up{job="gochat-redis"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Redis is down"
# Redis memory approaching limit
- alert: GoChatRedisMemoryHigh
expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "Redis memory usage above 80%"
# PostgreSQL connections exhausted
- alert: GoChatPostgresConnectionsHigh
expr: pg_stat_activity_count / pg_settings_max_connections > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "PostgreSQL connection usage above 80%"
+30
View File
@@ -0,0 +1,30 @@
# GoChat Redis Configuration
# Reference: Chatwoot production Redis uses appendonly + maxmemory policies
# This file is for standalone Redis deployment; compose uses command-line flags
# ---- Persistence ----
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# ---- Memory ----
maxmemory 512mb
maxmemory-policy allkeys-lru
# ---- Security ----
requirepass ${REDIS_PASSWORD}
# ---- Networking ----
bind 0.0.0.0
port 6379
timeout 300
# ---- Logging ----
loglevel notice
logfile ""
# ---- Performance ----
save 900 1
save 300 10
save 60 10000