# AdCloud Server 面向开发者和 coding agent 的广告云埋点与广告推送后端。使用 FastAPI 开发,Python 依赖和虚拟环境统一由 **uv** 管理。 已实现 `/v1` Gateway 路由、匿名身份签发、ID 映射图谱、可信身份 Stitch、稀疏画像及历史事件回溯。 画像可按部署设置选择关系库读取或 Cassandra 宽表投影;身份图谱保持关系库事务一致性。 广告业务目前仅有路由探测,尚未实现投放引擎。邮箱/手机号 OTP 和具体 OAuth 登录需要由调用方接入验证。 ## 本地开发(无需安装数据库服务) ```sh uv sync --locked uv run python scripts/init_local_env.py uv run uvicorn adcloud_server.main:app --reload --host 127.0.0.1 --port 8000 ``` 初始化脚本生成被 Git 忽略的 `.env`,权限 0600,包含本地开发所需随机 secret,不输出 secret 值,不覆盖已有文件。 SQLite 数据存放于 `.data/`,同样不提交。身份服务缺少 IDENTITY_SECRET 时返回 503,系统健康接口仍可用。 环境变量优先于 `.env`。生产 HTTPS 部署将 `COOKIE_SECURE` 设置为 true。 - 系统健康检查:`http://localhost:8000/health` - API 文档:`http://localhost:8000/docs` - OpenAPI:`http://localhost:8000/openapi.json` 另一个终端可运行 `uv run python scripts/demo_identity.py`,演示匿名访问、埋点、临时画像、模拟验证后 Stitch 及继承结果。 演示脚本使用合成的已验证身份,不代替实际 OTP/OAuth 校验。 ## HTTP Gateway ```text HTTPS :443 (Nginx,终止 TLS) ├── /v1/events/* → 事件接收、历史查询 ├── /v1/users/* → 稀疏用户画像 ├── /v1/ads/* → 广告业务模块(待实现) ├── /v1/identity/* → 匿名 ID、解析、拼接与图谱 └── /v1/... → 后续业务模块 ↓ FastAPI 127.0.0.1:8000 ``` 各模块当前共用一个进程,独立注册在 `api/v1/router.py` 中;Nginx 为各域预留独立 upstream。 未知路由返回 404、不支持的方法返回 405。保留各模块 `/health` 探测以及旧系统 `/health`。 默认 CORS 允许 localhost:3000、5173、5174,启用 credentials;匿名写请求检查浏览器 Origin。 `deploy/nginx.conf.example` 放在 Nginx `http {}` 上下文,替换域名和证书路径后在部署环境执行 `nginx -t`。 精确匹配 `/v1/events` 防止 POST 被重定向为带尾斜杠路径,所有转发保留 `/v1`、业务前缀和查询参数。 配置未在本机部署或验证,未启动 443、未申请证书。API 文档仅通过内部地址访问。 ## Identity Resolution / Stitching 详见 [身份图谱与存储配置](docs/identity.md),包含接口、合并策略、共享设备处理和 PostgreSQL / Cassandra 部署选择。 - Cookie / token 只证明匿名设备持有,不能自行提交 `verified=true` 合并账户。 - Stitch、图谱、画像读写和历史查询仅允许携带 SERVICE_TOKEN 的可信后端。 - 匿名事件保留原始 ID,通过 alias 在合并后即时归入 Master ID。 - PostgreSQL JSONB / SQLite JSON 省略空属性;Cassandra 可选宽表投影通过事务 outbox 同步和故障重试。 - 图谱主库始终是关系库,不提供纯 Cassandra、HBase 或 Bigtable 图谱实现。 ## 检查 ```sh uv run pytest uv run ruff check . uv run ruff format --check . ``` 默认测试使用临时 SQLite 和可恢复的投影替身,不安装、不启动数据库服务。 PostgreSQL、Cassandra 联调入口默认跳过,等提供专用测试环境后使用: ```sh uv sync --locked --extra postgres --extra cassandra ``` - 设置 `ADCLOUD_TEST_POSTGRES_URL` 为专用测试 PostgreSQL 的 SQLAlchemy URL,然后运行 `uv run --extra postgres pytest tests/test_postgres.py`。 - 设置 `ADCLOUD_TEST_CASSANDRA_HOSTS`、`ADCLOUD_TEST_CASSANDRA_KEYSPACE` 和可选的 PORT、USERNAME、PASSWORD、TLS、CA_FILE,同前缀环境变量配置;先在专用集群应用 `deploy/cassandra.cql`,再运行 `uv run --extra cassandra pytest tests/test_cassandra.py`。 联调测试使用独立随机租户,不自动创建 Cassandra 集群。PostgreSQL 测试会创建初始表并保留测试租户数据,需使用专用测试数据库。