diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ba0a6eb --- /dev/null +++ b/.env.example @@ -0,0 +1,76 @@ +# ============================================================= +# 环境变量清单(模板) +# +# 用法:复制成 .env,按需修改,然后由启动脚本注入。 +# cp .env.example .env +# +# 注意:本工程**不会自动读取 .env 文件**(未引入 dotenv), +# Spring Boot 只认进程环境变量。所以 .env 必须被"加载"进去: +# +# Linux/macOS: set -a; . ./.env; set +a; java -jar target/aomin-gateway-*.jar +# Windows cmd: for /f "usebackq tokens=1,* delims==" %i in (".env") do set %i=%j +# 容器: docker compose --env-file .env up -d +# +# 真实的 .env **不入库**(.gitignore 已挡)。本文件只放占位值。 +# 新增变量时同步本文件,否则接手的人不知道要配什么。 +# ============================================================= + +# ---------- 数据库 ---------- +# DB_PASS 是唯一必填项。留空或缺失时应用立即退出(退出码 1), +# 不会带空口令去连库,也不会回退到任何内置口令。填了真实值也别提交。 +DB_PASS= +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_NAME=aomin_dev +# 开发机常用 root;生产必须换成只有 DML 权限的业务账号 +DB_USER=root + +# ---------- Redis(仅作锁与缓存,非数据源) ---------- +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 + +# ---------- 日志 ---------- +LOG_DIR=./logs + +# ---------- 内部接口鉴权(/internal/**) ---------- +# 默认关闭签名校验,仅靠来源网络闸防护。上线前必须改为 true。 +GATEWAY_AUTH_ENABLED=false +# 共享密钥。J-00 §1.2 的签名公式里 key 就是它。 +# 当前值是占位值,生产必须替换;留空则签名校验必然失败。 +GATEWAY_TOKEN= +# 来源网络闸,与签名开关独立,默认开。 +# 签名可以晚点开,网络闸必须一开始就有——两个都关,/internal/** 就是裸奔。 +GATEWAY_NETWORK_GUARD=true + +# ---------- 业务安全 ---------- +# 家属端 token 的签名密钥。占位值 dev-only-change-me-2026 仅用于本机。 +BIZ_TOKEN_SECRET= +# 身份证等 PII 字段的加密密钥。占位值 dev-only-pii-key-2026 仅用于本机。 +# 换密钥会导致已入库的密文无法解密,上线后不要再改。 +BIZ_PII_KEY= + +# ---------- 短信 ---------- +# demo=true 时不真发短信,只落库并在响应里回显验证码 +BIZ_SMS_DEMO=true +BIZ_SMS_ECHO=true +# 同一手机号在此窗口内的短信合并为一条 +BIZ_SMS_MERGE_SECONDS=60 + +# ---------- 演示数据 ---------- +# true 会向数据库播种演示账号与样例数据。**生产环境严禁开启。** +BIZ_DEMO_ENABLED=false + +# ---------- 告警 ---------- +# 单条告警最大重试次数 +ALARM_MAX_TRY=3 +# 同一设备此窗口内的推送合并为一次 +ALARM_PUSH_MERGE_SECONDS=5 + +# ---------- 分区维护 ---------- +# 定时任务,依赖 Redis 取锁;Redis 不可用时跳过并告警,不影响告警主链 +PARTITION_MAINTAIN_ENABLED=true + +# ---------- 设备模拟器(demo/sim,仅本地联调用) ---------- +# 不属于后端配置,只被 sim_device.py 读取 +SIM_BASE=http://127.0.0.1:8080 +SIM_PORT=9901 diff --git a/.gitignore b/.gitignore index 1db21e1..ea37281 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,13 @@ out/ *.ear # ---------- 本地配置(可能含口令,绝不入库) ---------- +# 真实的 .env 一律不入库;但"变量清单"模板必须入库, +# 否则接手的人不知道要配哪些变量。模板里只放占位值,不放真实值。 .env .env.* +!.env.example +!.env.sample +!.env.template *.local.yml application-local.yml application-*-local.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index d788ea5..a82ac45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ --- +## [Unreleased] + +### Added + +- `.env.example`:20 个环境变量的清单模板(数据库、Redis、日志、内部接口鉴权、业务密钥、短信、演示数据、告警、分区维护、设备模拟器),每项注明默认值与是否必须替换。真实 `.env` 不入库。 + +### Fixed + +- `.gitignore` 的 `.env.*` 会把 `.env.example` 一并排除,导致变量清单无法入库。已加 `!.env.example`(以及 `.sample`、`.template`)例外。 + +--- + ## [V1.9-baseline] - 2026-11-13 首次入库,对应周工交付的 `SEC-Z-01 清理后` 源码包。 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f6fcf09..6a58a37 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,6 +59,8 @@ rawRef 指向不存在的行时,原先抛 NPE 被全局兜底成 500, | 运行产物 | 日志、`*.jsonl`、证据 `raw/`、截图 | | 公司无关资料 | 员工绩效、客户名单、采购函、其他项目报价 | +**唯一例外是 `.env.example`。** 它是变量清单模板,必须入库——不入库接手的人就不知道要配哪些变量,只能去翻 `application.yml` 逐个猜。模板里只放占位值,真实值填在本地 `.env` 里。新增环境变量时同步更新它,否则清单很快就不准了。 + `.gitignore` 已经覆盖上述路径,但**它只挡新增,不挡已提交**。加文件前先 `git status` 看一眼。 判断标准很简单:**这个文件一旦公开,会不会造成损失?** 会,就不要放进来。Git 的历史是追加式的,删除只影响最新版本,历史里那份永远在。 diff --git a/README.md b/README.md index d259381..e9e4671 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ │ ├── handover/ 交付与安全清理材料(Z-01/Z-02) │ ├── contract/ 接口契约:J-00 规格、OpenAPI、内部五接口、状态机 │ └── reference/ 原始交付包指纹与迁移脚本哈希 +├── .env.example 环境变量清单模板(20 项,真实 .env 不入库) ├── .gitattributes 行尾与二进制策略 ├── .editorconfig 缩进与编码 ├── CHANGELOG.md 版本记录 @@ -52,15 +53,21 @@ cd aomin-gateway mvn -DskipTests clean package # 产物:target/aomin-gateway-0.0.1-SNAPSHOT.jar -# 2) 启动(DB_PASS 必填,缺失时应用立即退出,不会回退到任何内置口令) -export DB_PASS='<口令>' -export DB_USER=aomin -java -jar target/aomin-gateway-0.0.1-SNAPSHOT.jar --server.port=8080 --server.address=0.0.0.0 +# 2) 配置环境变量(20 个变量的清单见仓库根 .env.example) +cd .. +cp .env.example .env # 把 DB_PASS 填上,其余按需改 +set -a; . ./.env; set +a # 工程不会自动读 .env,必须加载进进程环境 -# 3) 自检 +# 3) 启动(DB_PASS 必填,缺失时应用立即退出,不会回退到任何内置口令) +export DB_USER=aomin +java -jar aomin-gateway/target/aomin-gateway-0.0.1-SNAPSHOT.jar --server.port=8080 --server.address=0.0.0.0 + +# 4) 自检 curl -s http://127.0.0.1:8080/health ``` +`.env.example` 是变量清单模板,含数据库、Redis、内部接口鉴权、业务密钥、短信、告警、分区维护、模拟器共 20 项,每项都注明默认值与是否必须替换。真实的 `.env` 不入库。 + 正常返回需同时满足 `db: connected`、`tables: 87`、`flyway: 1.0.28`、`status: UP`。 建库、环境变量、systemd 单元、Flyway 校验和不符的处理,全部在 [`aomin-gateway/README.md`](aomin-gateway/README.md)。 diff --git a/SECURITY.md b/SECURITY.md index 431f7bd..b8444c0 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -15,6 +15,8 @@ 口令、token、AK/SK、私钥与证书、`.env` 与 `*.local.yml`、含口令的截图、真实的第三方服务密钥。 +**模板文件 `.env.example` 是例外**:它只含变量名与占位值,必须入库,否则接手的人不知道要配哪些变量。往模板里填真实值就不再是模板了。 + 完整清单与目录约定见 [`CONTRIBUTING.md`](CONTRIBUTING.md) 第三节。 ## 三、发现泄露后的处置顺序