FindProductSummary and FindColorDetail aggregate pan.position via GROUP_CONCAT
with a LEFT JOIN. When a product has no pans the join produces all-NULL rows,
causing GROUP_CONCAT to return NULL, which cannot be scanned into a Go string —
making the entire summary query fail silently and the frontend show an empty table.
Fix: wrap both GROUP_CONCAT(pan.position) calls with COALESCE(..., '').
Also removes CostPrice from the generated InvProduct model (field dropped from schema).
Adds integration tests TestFindProductSummaryNoPans and TestFindColorDetailNoPans
to guard against this class of NULL-scan regression.
The entrypoint.sh was writing the rendered config back to the same
directory as the source, which fails when the config is mounted from
a Kubernetes ConfigMap (read-only filesystem). Write to /tmp instead.
Co-Authored-By: Claude <noreply@anthropic.com>
- Clear default passwords in all service configs and local dev YAMLs
- Add entrypoint.sh with envsubst to resolve ${ENV} vars in go-zero YAML
- Update Dockerfiles to install gettext and use entrypoint
- Update docker-compose to pass secrets via environment and require via ${VAR:?...}
- Add .gitignore rules for .env files, add .env.example template
Co-Authored-By: Claude <noreply@anthropic.com>
Alpine CDN unreachable from DinD containers. Switch to
mirrors.aliyun.com for both builder and runtime stages.
Co-Authored-By: Claude <noreply@anthropic.com>
Docker Hub and proxy.golang.org unreachable from k3s cluster (GFW).
Switch Dockerfiles to Harbor base images and goproxy.cn.
Co-Authored-By: Claude <noreply@anthropic.com>
Set DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH for k8s runner
DinD sidecar communication. Add 'until docker info' wait loop to
ensure daemon is ready before build starts.
Co-Authored-By: Claude <noreply@anthropic.com>
Build 3 muyu services (gateway, system-rpc, inventory-rpc)
as Docker images and push to Harbor registry.
Co-Authored-By: Claude <noreply@anthropic.com>
Align origin/main with upstream/main (GitHub). The two branches
diverged due to pre-rebase vs post-rebase merge commits for the
k8s-amd64-dockerfiles feature.
Includes: multi-stage Go compilation Dockerfiles, pan-bolt
inventory features, CRM relations, Excel import tooling,
proto/gRPC updates, migration scripts, and tools/ directory.
Excludes deploy/bin/ pre-compiled binaries (arm64, not needed
for amd64 K3s cluster; builds use multi-stage Dockerfiles now).
WHY: existing Dockerfiles copied pre-compiled arm64 binaries which cannot
run on the amd64 K3s cluster (exec format error). Also fixed port conflicts
when running muyu alongside iloom in docker-compose.
HOW:
- rewrite 3 Dockerfiles (system/inventory/gateway) to multi-stage builds
using golang:1.24-alpine with CGO_ENABLED=0 GOARCH=amd64
- parameterize host ports in docker-compose to avoid conflicts (3306->13306,
6379->16379, 8080->18080)
- fix inv_product unique key from product_name-only to composite
(product_name, spec, color) to allow same-name products with different specs
- add X-Token to Authorization header middleware in gateway for
iloom frontend compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- JWT claims extended with tenantId; login enforces strict tenant verification
- AuthorityMiddleware: tenant scope check + Casbin path permission + anti-spoofing
- CRM relation API (upstream/downstream one-hop, create/update/history, full graph)
- CrmRepo backed by PostgreSQL with $N placeholders
- gRPC tenant propagation via UnaryClientInterceptor (x-tenant-id metadata)
- All legacy tables (12) gain tenant_id column with indexes
- All model queries inject WHERE tenant_id filter
- Casbin gorm-adapter downgraded to v3.28.0 for v2 compatibility
- GraphSyncWorker (Kafka -> Neo4j) with idempotent MERGE
- Full graph API restricted to admin role only
- Database migrations for MySQL (CRM tables + tenant columns) and PostgreSQL (CRM init)
- Docker Compose: added postgres service to main stack, graph stack with Kafka/Debezium/Neo4j
Made-with: Cursor