Compare commits

..

5 Commits

Author SHA1 Message Date
john 753c1eec23 fix(scheduled-task): forward worker env to sandbox MCP
Memind CI / Test, build, and release guards (push) Successful in 6m3s
goosed stdio MCPs do not inherit Portal env, so scheduled_task_create
always reported worker disabled even when H5_REMINDER_WORKER_ENABLED=1.
Forward worker flags in sandboxMcpEnvs and add a regression test.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 20:49:36 +08:00
john 62fbea0936 docs: 登记 feature/md-admin-domain 分支闭环
Memind CI / Test, build, and release guards (push) Successful in 4m37s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 17:41:20 +08:00
john 871688550e docs(analytics): 管理后台域名改为 md.tkmind.cn
Memind CI / Test, build, and release guards (push) Has been cancelled
同步 Analytics 发布 runbook 与 admin 默认 PUBLIC_HOST,与 memind_adm 生产入口一致。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 17:38:31 +08:00
john d570856cbd docs: register feature/analytics-release-docs branch disposition
Memind CI / Test, build, and release guards (push) Failing after 1m46s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 16:33:19 +08:00
john 8348ce3625 docs: add analytics release runbook and 105 Umami topology
Memind CI / Test, build, and release guards (push) Has been cancelled
Cross-repo publish order for memind-analytics, Portal, and memind_adm;
update platform and 105 operations docs for systemd artifact deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 16:21:57 +08:00
13 changed files with 274 additions and 15 deletions
+3 -3
View File
@@ -215,7 +215,7 @@ H5_PUBLIC_BASE_URL=http://127.0.0.1:5173
# 登录仍在主域完成;后台凭 H5_COOKIE_DOMAIN=.tkmind.cn 共享的会话 Cookie 鉴权(生产务必设置)。 # 登录仍在主域完成;后台凭 H5_COOKIE_DOMAIN=.tkmind.cn 共享的会话 Cookie 鉴权(生产务必设置)。
ADMIN_PORT=8082 ADMIN_PORT=8082
ADMIN_HOST=127.0.0.1 ADMIN_HOST=127.0.0.1
ADMIN_PUBLIC_HOST=gadm.tkmind.cn ADMIN_PUBLIC_HOST=md.tkmind.cn
# 本进程挂载哪些控制台(可拆分架构):admin=平台超管, ops=广场运营。 # 本进程挂载哪些控制台(可拆分架构):admin=平台超管, ops=广场运营。
# 默认两者合一;将来拆成两个进程时,A 实例设 admin、B 实例设 ops,路由代码无需改动。 # 默认两者合一;将来拆成两个进程时,A 实例设 admin、B 实例设 ops,路由代码无需改动。
@@ -223,9 +223,9 @@ ADMIN_PUBLIC_HOST=gadm.tkmind.cn
# 每控制台独立网络护栏(逗号分隔;留空=放开。支持精确 IP 与 CIDR)。 # 每控制台独立网络护栏(逗号分隔;留空=放开。支持精确 IP 与 CIDR)。
# 超管面建议收得最紧(仅内网/VPN),广场运营可放宽给审核团队网段。 # 超管面建议收得最紧(仅内网/VPN),广场运营可放宽给审核团队网段。
# ADMIN_API_ALLOWED_HOSTS=gadm.tkmind.cn # ADMIN_API_ALLOWED_HOSTS=md.tkmind.cn
# ADMIN_API_IP_ALLOWLIST=10.0.0.0/8,127.0.0.1 # ADMIN_API_IP_ALLOWLIST=10.0.0.0/8,127.0.0.1
# OPS_API_ALLOWED_HOSTS=gadm.tkmind.cn # OPS_API_ALLOWED_HOSTS=md.tkmind.cn
# OPS_API_IP_ALLOWLIST= # OPS_API_IP_ALLOWLIST=
# 多用户系统(MySQL 配置后启用;未配置时回退到 H5_ACCESS_PASSWORD # 多用户系统(MySQL 配置后启用;未配置时回退到 H5_ACCESS_PASSWORD
+2 -2
View File
@@ -101,14 +101,14 @@ Cursor 额外加载:`.cursor/rules/mindspace-publish-chat-finish-guards.mdc`
## 仓库惯例 ## 仓库惯例
- 本地开发:`pnpm dev`(见 [README.md](README.md) - 本地开发:`pnpm dev`(见 [README.md](README.md)
- 访问统计:**仅 Umami**Rybbit 已退役,见 [docs/analytics-platform.md](docs/analytics-platform.md)[docs/local-analytics.md](docs/local-analytics.md) - 访问统计:**仅 Umami**Rybbit 已退役,见 [docs/analytics-platform.md](docs/analytics-platform.md)[docs/local-analytics.md](docs/local-analytics.md)、**[docs/analytics-release-runbook.md](docs/analytics-release-runbook.md)**105 / 103 发布顺序)
- Page Data API:见 [docs/page-data-api-usage.md](docs/page-data-api-usage.md);改动相关路径后执行 `npm run verify:page-data` - Page Data API:见 [docs/page-data-api-usage.md](docs/page-data-api-usage.md);改动相关路径后执行 `npm run verify:page-data`
- 生产隔离:[docs/service-isolation-runbook.md](docs/service-isolation-runbook.md) - 生产隔离:[docs/service-isolation-runbook.md](docs/service-isolation-runbook.md)
- 发版须 Git commit,禁止本机直 `rsync``103/105` - 发版须 Git commit,禁止本机直 `rsync``103/105`
## 必读:管理后台 UI 边界(memind_adm 5174 ## 必读:管理后台 UI 边界(memind_adm 5174
**平台管理后台的前端 UI 只能在独立仓库 `memind_adm`(本地 5174 / 生产 gadm)开发,禁止在 Memind 本仓库的 `ops/`(约 3002)新增管理功能。** **平台管理后台的前端 UI 只能在独立仓库 `memind_adm`(本地 5174 / 生产 [md.tkmind.cn](https://md.tkmind.cn))开发,禁止在 Memind 本仓库的 `ops/`(约 3002)新增管理功能。**
| 层级 | 位置 | 说明 | | 层级 | 位置 | 说明 |
|------|------|------| |------|------|------|
+7 -7
View File
@@ -15,10 +15,10 @@ test('parseList splits, trims, and drops empties', () => {
}); });
test('hostAllowed: empty list allows all, otherwise matches hostname ignoring port/case', () => { test('hostAllowed: empty list allows all, otherwise matches hostname ignoring port/case', () => {
assert.equal(hostAllowed('gadm.tkmind.cn:8082', []), true); assert.equal(hostAllowed('md.tkmind.cn:8082', []), true);
assert.equal(hostAllowed('GADM.tkmind.cn', ['gadm.tkmind.cn']), true); assert.equal(hostAllowed('MD.tkmind.cn', ['md.tkmind.cn']), true);
assert.equal(hostAllowed('evil.example.com', ['gadm.tkmind.cn']), false); assert.equal(hostAllowed('evil.example.com', ['md.tkmind.cn']), false);
assert.equal(hostAllowed('gadm.tkmind.cn:443', ['gadm.tkmind.cn', 'localhost']), true); assert.equal(hostAllowed('md.tkmind.cn:443', ['md.tkmind.cn', 'localhost']), true);
}); });
test('ipMatches: exact and IPv4-mapped IPv6', () => { test('ipMatches: exact and IPv4-mapped IPv6', () => {
@@ -48,7 +48,7 @@ test('buildNetworkGuard returns null when nothing configured', () => {
test('buildNetworkGuard denies on host then ip, allows when both pass', () => { test('buildNetworkGuard denies on host then ip, allows when both pass', () => {
const guard = buildNetworkGuard({ const guard = buildNetworkGuard({
allowedHosts: ['gadm.tkmind.cn'], allowedHosts: ['md.tkmind.cn'],
ipAllowlist: ['10.0.0.0/8'], ipAllowlist: ['10.0.0.0/8'],
onDeny: (_res, _req, reason) => `deny:${reason}`, onDeny: (_res, _req, reason) => `deny:${reason}`,
}); });
@@ -60,8 +60,8 @@ test('buildNetworkGuard denies on host then ip, allows when both pass', () => {
}; };
assert.equal(guard(mk('evil.com', '10.1.1.1'), {}, next), 'deny:host'); assert.equal(guard(mk('evil.com', '10.1.1.1'), {}, next), 'deny:host');
assert.equal(guard(mk('gadm.tkmind.cn', '8.8.8.8'), {}, next), 'deny:ip'); assert.equal(guard(mk('md.tkmind.cn', '8.8.8.8'), {}, next), 'deny:ip');
assert.equal(nexted, false); assert.equal(nexted, false);
guard(mk('gadm.tkmind.cn', '10.1.1.1'), {}, next); guard(mk('md.tkmind.cn', '10.1.1.1'), {}, next);
assert.equal(nexted, true); assert.equal(nexted, true);
}); });
+2 -2
View File
@@ -5,7 +5,7 @@
// Serves the platform super-admin API (/admin-api/*) and the plaza operations // Serves the platform super-admin API (/admin-api/*) and the plaza operations
// console API (/api/ops/v1/*) on its own port, isolated from the public // console API (/api/ops/v1/*) on its own port, isolated from the public
// user-facing server (server.mjs). In production this is fronted by // user-facing server (server.mjs). In production this is fronted by
// gadm.tkmind.cn; in dev the ops SPA (:3002) proxies to it directly. // md.tkmind.cn; in dev the ops SPA (:3002) proxies to it directly.
// //
// It trusts the shared session cookie (H5_COOKIE_DOMAIN=.tkmind.cn), so login // It trusts the shared session cookie (H5_COOKIE_DOMAIN=.tkmind.cn), so login
// continues to happen on the main app domain — this process only reads the // continues to happen on the main app domain — this process only reads the
@@ -43,7 +43,7 @@ loadEnvFile(path.join(__dirname, '.env'));
const PORT = Number(process.env.ADMIN_PORT ?? 8082); const PORT = Number(process.env.ADMIN_PORT ?? 8082);
const HOST = process.env.ADMIN_HOST ?? '127.0.0.1'; const HOST = process.env.ADMIN_HOST ?? '127.0.0.1';
const PUBLIC_HOST = process.env.ADMIN_PUBLIC_HOST ?? 'gadm.tkmind.cn'; const PUBLIC_HOST = process.env.ADMIN_PUBLIC_HOST ?? 'md.tkmind.cn';
const getToken = (req) => parseCookies(req.get('cookie'))[USER_COOKIE]; const getToken = (req) => parseCookies(req.get('cookie'))[USER_COOKIE];
+8
View File
@@ -606,6 +606,14 @@ function sandboxMcpEnvs(sandboxMcp, mcpTools) {
envs[key] = String(value).trim(); envs[key] = String(value).trim();
} }
} }
// goosed stdio MCPs do not inherit Portal env; forward worker flags so
// scheduled_task_create can report the same enablement as server.mjs.
for (const key of ['H5_REMINDER_WORKER_ENABLED', 'H5_SCHEDULED_TASK_WORKER_ENABLED']) {
const value = process.env[key];
if (value != null && String(value).trim() !== '') {
envs[key] = String(value).trim();
}
}
if (mcpTools.includes('generate_image')) { if (mcpTools.includes('generate_image')) {
if (sandboxMcp.agentApiBaseUrl) { if (sandboxMcp.agentApiBaseUrl) {
envs.MINDSPACE_AGENT_API_BASE_URL = sandboxMcp.agentApiBaseUrl; envs.MINDSPACE_AGENT_API_BASE_URL = sandboxMcp.agentApiBaseUrl;
+25
View File
@@ -507,6 +507,31 @@ test('static_publish with sandboxMcp uses stdio sandbox-fs extension instead of
assert.ok(!allTools.includes('shell'), 'shell should not be exposed'); assert.ok(!allTools.includes('shell'), 'shell should not be exposed');
}); });
test('sandboxMcpEnvs forwards scheduled task worker flags from portal env', () => {
const previousReminder = process.env.H5_REMINDER_WORKER_ENABLED;
const previousScheduled = process.env.H5_SCHEDULED_TASK_WORKER_ENABLED;
process.env.H5_REMINDER_WORKER_ENABLED = '1';
delete process.env.H5_SCHEDULED_TASK_WORKER_ENABLED;
try {
const caps = { ...DEFAULT_USER_CAPABILITIES, static_publish: true };
const policy = buildAgentExtensionPolicy(caps, {
sandboxMcp: {
serverPath: '/opt/portal/mindspace-sandbox-mcp.mjs',
sandboxRoot: '/opt/h5/MindSpace/abc123',
},
});
const sandboxExt = policy.extensionOverrides.find((ext) => ext.name === 'sandbox-fs');
assert.ok(sandboxExt);
assert.equal(sandboxExt.envs.H5_REMINDER_WORKER_ENABLED, '1');
assert.equal(sandboxExt.envs.H5_SCHEDULED_TASK_WORKER_ENABLED, undefined);
} finally {
if (previousReminder === undefined) delete process.env.H5_REMINDER_WORKER_ENABLED;
else process.env.H5_REMINDER_WORKER_ENABLED = previousReminder;
if (previousScheduled === undefined) delete process.env.H5_SCHEDULED_TASK_WORKER_ENABLED;
else process.env.H5_SCHEDULED_TASK_WORKER_ENABLED = previousScheduled;
}
});
test('sandboxMcp emits a scoped logical workspace token only for a bound session', () => { test('sandboxMcp emits a scoped logical workspace token only for a bound session', () => {
const secret = const secret =
'mindspace-mcp-policy-secret-1234'; 'mindspace-mcp-policy-secret-1234';
+25
View File
@@ -11,6 +11,7 @@
| 定位 | 云侧入口 / 代理 / 历史链路,不承担可写业务数据主存储 | | 定位 | 云侧入口 / 代理 / 历史链路,不承担可写业务数据主存储 |
| H5 运行目录 | `/root/tkmind_go/ui/h5` | | H5 运行目录 | `/root/tkmind_go/ui/h5` |
| Plaza 运行目录 | `/root/tkmind_go/ui/plaza` | | Plaza 运行目录 | `/root/tkmind_go/ui/plaza` |
| **Umami Analytics** | `/opt/memind-analytics`systemd + 原生 artifact,见下节) |
| 数据真身 | 在 `103`MindSpace、users、data 等),见 [103/105 升级记录](103-105-upgrade-runbook-2026-06-26.md) | | 数据真身 | 在 `103`MindSpace、users、data 等),见 [103/105 升级记录](103-105-upgrade-runbook-2026-06-26.md) |
本地开发仓库是 `/Users/john/Project/Memind`;生产 runtime 发布目标是 `103` 本地开发仓库是 `/Users/john/Project/Memind`;生产 runtime 发布目标是 `103`
@@ -56,6 +57,29 @@
**不要**使用已停用的 `rsync_to_server.sh` 或直接 rsync 到 `105` 作为常规发布手段(见 `PRODUCTION_RELEASE_RULES.md`)。 **不要**使用已停用的 `rsync_to_server.sh` 或直接 rsync 到 `105` 作为常规发布手段(见 `PRODUCTION_RELEASE_RULES.md`)。
## 105 Umami Analytics`/opt/memind-analytics`
Memind 访问统计(Umami)独立部署在 105**不是** Portal H5 目录的一部分。
| 项 | 说明 |
|----|------|
| 公网 | `https://fxi.tkmind.cn` |
| 进程 | `systemctl status memind-analytics-umami` |
| 数据库 | Docker Compose 仅 `db``127.0.0.1:55432` |
| 发布 | 在 **memind-analytics** 仓库执行 `bash scripts/release-umami-105.sh --yes` |
| 文档 | memind-analytics `deploy/105-runbook.md`Memind [analytics-release-runbook.md](analytics-release-runbook.md) |
**禁止** SSH 到 105 手改 `/opt/memind-analytics/live` 内文件或 overlay;变更必须来自 memind-analytics Git 发布。
验收:
```bash
ssh root@120.26.184.105 '
systemctl is-active memind-analytics-umami
curl -sf http://127.0.0.1:3100/api/heartbeat
'
```
## 105 Portal runtime 发布 ## 105 Portal runtime 发布
`105` 上当前 H5 由 `systemd` 服务 `goose-h5` 运行,真实目录是: `105` 上当前 H5 由 `systemd` 服务 `goose-h5` 运行,真实目录是:
@@ -196,5 +220,6 @@ ssh root@120.26.184.105 "sed -i \"s/M广场/M发现/\" /root/tkmind_go/ui/h5/scr
## 相关文档 ## 相关文档
- [生产 / 测试 / 预览隔离规程](service-isolation-runbook.md) - [生产 / 测试 / 预览隔离规程](service-isolation-runbook.md)
- [Analytics / SEO·GEO 发布 Runbook](analytics-release-runbook.md)
- [Portal 无源码迁移说明](no-source-portal-migration.md) - [Portal 无源码迁移说明](no-source-portal-migration.md)
- [103/105 一次性升级实施记录](103-105-upgrade-runbook-2026-06-26.md) - [103/105 一次性升级实施记录](103-105-upgrade-runbook-2026-06-26.md)
+13
View File
@@ -35,3 +35,16 @@ Memind 公开页与生成页的真实用户访问统计 **仅使用 Umami**`m
| **Memind** | tracker 注入、discovery 分类、Umami 代理 | | **Memind** | tracker 注入、discovery 分类、Umami 代理 |
| **memind-analytics** | Umami 定制部署、`memind-pages` APIoverlay 在 `deploy/umami/overlay/` | | **memind-analytics** | Umami 定制部署、`memind-pages` APIoverlay 在 `deploy/umami/overlay/` |
| **memind_adm** | Analytics 配置、SEO/GEO 看板、Umami SSO | | **memind_adm** | Analytics 配置、SEO/GEO 看板、Umami SSO |
## 生产发布
跨仓库顺序与命令见 **[analytics-release-runbook.md](analytics-release-runbook.md)**。
| 步骤 | 仓库 | 命令 |
|------|------|------|
| 1 | memind-analytics | `bash scripts/release-umami-105.sh --yes` |
| 2 | Memind103 Portal | `bash scripts/release-portal-runtime-prod.sh --yes` |
| 3 | memind_adm103 · md.tkmind.cn | `bash scripts/release-prod.sh --yes` |
105 Umami 细节见 memind-analytics 仓库 `deploy/105-runbook.md`
md.tkmind.cn Analytics 环境变量见 memind_adm `docs/analytics-deploy.md`
+131
View File
@@ -0,0 +1,131 @@
# Analytics / SEO·GEO 生产发布 Runbook
跨仓库发布顺序与命令速查。统计平台说明见 [analytics-platform.md](analytics-platform.md)。
## 架构(2026-08 起)
```text
公开页 / H5
-> Memind /analytics/* 代理
-> 105 Umamisystemd + 原生 artifact127.0.0.1:3100
-> PostgreSQL(仅 db 容器,127.0.0.1:55432
memind_adm SEO/GEO 看板
-> /admin-api/analytics/seo-geo-pages
-> 105 Umami memind-pages APIoverlay
```
**已废弃:** Rybbit105 上 Docker 编译 Umami 镜像;Docker 跑 Umami 应用容器(`docker-umami` profile 仅遗留)。
## 推荐发布顺序
| 顺序 | 仓库 | 何时必须发 | 命令 |
|------|------|------------|------|
| 1 | **memind-analytics** | 改了 `deploy/umami/overlay/``memind-pages` API | `bash scripts/release-umami-105.sh --yes` |
| 2 | **Memind** | 改了 discovery 埋点、Umami 代理、公开页 delivery | `bash scripts/release-portal-runtime-prod.sh` |
| 3 | **memind_adm** | 改了 SEO/GEO 看板、Analytics 配置页、Umami 代理 | `bash scripts/release-prod.sh --yes` |
只改 overlay / API 时,发 **105** 即可;只改 adm 看板 UI 时,发 **103 md.tkmind.cnmemind_adm** 即可。
Memind discovery 字段(`discovery_channel` 等)未上线前,adm 看板可能暂无 SEO/GEO 分列数据。
## 1. 105 Umamimemind-analytics
工作目录:本机 `memind-analytics` 仓库(或 worktree `memind-analytics-release-main`)。
```bash
bash scripts/release-umami-105.sh --yes
```
脚本会:
1. 打包部署文件上传到 `105:/opt/memind-analytics/incoming/`
2. **在 105 原生** `pnpm install`(复用 `node_modules` 缓存)+ `pnpm run build-docker`
3. 产出 artifact → `/opt/memind-analytics/releases/umami-<release_id>/`
4. `backup/backup.sh` 备份 PostgreSQL
5. 切换 `/opt/memind-analytics/live` symlink`systemctl restart memind-analytics-umami`
### 监控(SSH 断开不影响构建)
```bash
ssh root@120.26.184.105 tail -f /opt/memind-analytics/.build/build-<release_id>.log
# 或
ssh root@120.26.184.105 tail -f /opt/memind-analytics/.build/release-<release_id>.log
```
### 验收
```bash
ssh root@120.26.184.105 '
systemctl is-active memind-analytics-umami
curl -sf http://127.0.0.1:3100/api/heartbeat
readlink /opt/memind-analytics/live
'
```
公网:`https://fxi.tkmind.cn/api/heartbeat`
详细路径、回滚与 nginx 见 **memind-analytics** 仓库 [`deploy/105-runbook.md`](https://git.tkmind.cn/tkmind/memind-analytics/src/branch/main/deploy/105-runbook.md)。
## 2. 103 PortalMemind
```bash
cd /Users/john/Project/Memind
bash scripts/check-release-ready.sh # 发布闸门
bash scripts/release-portal-runtime-prod.sh --yes
```
与 Analytics 相关的 Memind 改动通常包括:
- `mindspace-analytics-discovery.mjs` — SEO/GEO 分类
- `mindspace-analytics.mjs` — 事件维度
- Portal `/analytics/*` 反代
本地环境变量见 [local-analytics.md](local-analytics.md)。
## 3. 103 管理后台(memind_adm
```bash
cd /Users/john/Project/memind_adm
bash scripts/release-prod.sh --yes
```
### 生产 `.env`Analytics 相关)
```env
# SEO/GEO 看板拉 Umami memind-pages API 所需(105 SSO-only 时用 MEMIND_UMAMI_SSO_SECRET
MEMIND_UMAMI_SSO_SECRET=<与 105 .env 一致>
UMAMI_SSO_USERNAME=admin
UMAMI_URL=https://fxi.tkmind.cn # 可选,默认 http://127.0.0.1:3100
UMAMI_WEBSITE_ID=<Memind 公共页面 Website ID>
H5_PUBLIC_BASE_URL=https://md.tkmind.cn
```
103 需能访问 105 Umami(内网或配置的 `UMAMI_URL`)。
### 验收
1. [md.tkmind.cn/analytics](https://md.tkmind.cn/analytics) → **Analytics 配置** → 「打开 Umami 分析后台」可 SSO 登录
2. [md.tkmind.cn/analytics/seo-geo](https://md.tkmind.cn/analytics/seo-geo) → **SEO / GEO 流量** → 表格加载无 SSO/凭证错误
3. 抽样对比 Umami「所有生成页面明细」与 adm 看板列口径一致
详见 memind_adm [`docs/analytics-deploy.md`](../memind_adm/docs/analytics-deploy.md)。
## 常见问题
| 现象 | 处理 |
|------|------|
| 105 构建 `check-db` 失败 | 应使用 `build-docker`(已写入 `build-umami-artifact.sh`),勿改回 `pnpm build` |
| `Umami database is not running` | 使用 `backup/backup.sh`,不要用根目录旧版 `backup.sh` |
| 105 构建很慢 | 首次 install+compile 约 2040 分钟;后续 overlay 小改可复用 `node_modules` |
| adm SEO/GEO 看板空 | 确认 Memind discovery 已发布且有真实 SEO/GEO 流量 |
| Rybbit 相关报错 | 已退役,删除遗留 env/文档引用,见 [analytics-platform.md](analytics-platform.md) |
## 相关文档
| 文档 | 内容 |
|------|------|
| [analytics-platform.md](analytics-platform.md) | 平台边界、字段口径、Rybbit 退役 |
| [local-analytics.md](local-analytics.md) | 本地 Umami 与 Memind env |
| [105-server-operations.md](105-server-operations.md) | 105 运维边界(含 `/opt/memind-analytics` |
| memind-analytics `README.md` | Umami 仓库运维与 overlay |
| memind_adm `docs/analytics-deploy.md` | md.tkmind.cn Analytics / SEO·GEO 配置 |
+52
View File
@@ -13,6 +13,33 @@
- 远端功能分支默认在闭环后删除;发布和审计依据使用 `main` commit、tag、CI 记录或 runtime manifest,不使用功能分支名。 - 远端功能分支默认在闭环后删除;发布和审计依据使用 `main` commit、tag、CI 记录或 runtime manifest,不使用功能分支名。
- 这类保留分支必须在本文件登记清楚:分支名、最终 HEAD、进入 `origin/main` 的提交、验证摘要,以及“禁止再次引用”的状态。 - 这类保留分支必须在本文件登记清楚:分支名、最终 HEAD、进入 `origin/main` 的提交、验证摘要,以及“禁止再次引用”的状态。
## `feature/md-admin-domain`Memind + memind_adm
**状态:禁止再次引用。改动已提交并进入 `origin/main`,该分支保留仅用于只读追溯,不是待合并开发分支。**
审计日期:2026-08-11
分支 HEAD`8716885`Memind)、`0da7f04`memind_adm
`origin/main` 对应提交:同上
### 原始用途
- 管理后台公网域名从 `gadm.tkmind.cn` 更正为 `md.tkmind.cn`
- 文档与 nginx 示例明确 **105 反代 → 103 memind_adm**5174/8085
- memind_adm 默认 `VITE_BASE_PATH=/`,使 `/analytics/seo-geo` 在根路径可访问
### 生产发布
| 仓库 | release_id |
|------|------------|
| memind_adm | `20260810-173922-0da7f04` |
| 105 nginx | `md.tkmind.cn.conf` 已 reload |
### 验证摘要
- `https://md.tkmind.cn/analytics/seo-geo` → 200
- 103 `8085/health` → ok5174 `base=/`
- `/ops/analytics/seo-geo` → 301 到 `/analytics/seo-geo`
## `feature/fix-rybbit-publication-tracking` ## `feature/fix-rybbit-publication-tracking`
**状态:禁止再次引用。改动已提交并进入 `origin/main`,该分支保留仅用于只读追溯,不是待合并开发分支。** **状态:禁止再次引用。改动已提交并进入 `origin/main`,该分支保留仅用于只读追溯,不是待合并开发分支。**
@@ -454,3 +481,28 @@ Portal,避免在线修改稳定 `.env`,并确保稳定 8081 与其他用户
- 保留本地分支名用于审计追溯。 - 保留本地分支名用于审计追溯。
- **不要** merge、cherry-pick 或从该分支构建 runtime/artifact。 - **不要** merge、cherry-pick 或从该分支构建 runtime/artifact。
- 103 生产依据 `44121df` / release manifest `20260805-095542-44121df` - 103 生产依据 `44121df` / release manifest `20260805-095542-44121df`
## `feature/analytics-release-docs`
**状态:禁止再次引用。改动已提交并进入 `origin/main`,该分支保留仅用于只读追溯。**
审计日期:2026-08-11
分支 HEAD`8348ce3`
`origin/main` 对应提交:`8348ce3`
### 原始用途
补充 Analytics / SEO·GEO 跨仓库发布文档:105 Umami 原生 artifact + systemd 拓扑、发布顺序、Memind 与 memind_adm 链接。
### 验证摘要
- 文档-only;无 runtime 变更
- memind-analytics 文档已 push 至 `main` @ `24f67b0`
- memind_adm 文档已 merge 至 `main` @ `a67d5a1`
### 最终处置
- 保留本地分支名用于审计追溯。
- **不要** merge、cherry-pick 或从该分支继续开发。
- 后续 Analytics 发布以 `docs/analytics-release-runbook.md` 为准。
+3
View File
@@ -35,4 +35,7 @@ MEMIND_PRODUCT_ANALYTICS_WEBSITE_ID=<product-website-id>
- **memind_adm → Analytics 配置**Umami Website ID、密钥、SSO 入口 - **memind_adm → Analytics 配置**Umami Website ID、密钥、SSO 入口
- **memind_adm → SEO / GEO 流量**:按页监控搜索引擎 / 生成式引擎来源访问 - **memind_adm → SEO / GEO 流量**:按页监控搜索引擎 / 生成式引擎来源访问
生产发布与环境变量见 memind_adm [`docs/analytics-deploy.md`](../../memind_adm/docs/analytics-deploy.md)。
跨仓库发布顺序见 [analytics-release-runbook.md](analytics-release-runbook.md)。
Analytics 服务 fail-open:未配置或 Umami 不可用时,页面生成与交付不受影响。勿向终端用户暴露 Umami 控制台。 Analytics 服务 fail-open:未配置或 Umami 不可用时,页面生成与交付不受影响。勿向终端用户暴露 Umami 控制台。
+2
View File
@@ -21,6 +21,8 @@
- `105``103` 的关键差异是: - `105``103` 的关键差异是:
`105` 为 Linux 环境,**不要携带本机 Mac 的 `node_modules`**;应在 `105` 切换前本机执行 `npm install --omit=dev --no-package-lock` `105` 为 Linux 环境,**不要携带本机 Mac 的 `node_modules`**;应在 `105` 切换前本机执行 `npm install --omit=dev --no-package-lock`
Umami Analytics105 `/opt/memind-analytics`)是**独立发布链**,不走 Portal runtime 脚本。见 [analytics-release-runbook.md](analytics-release-runbook.md)。
## 唯一入口 ## 唯一入口
```bash ```bash
+1 -1
View File
@@ -2,7 +2,7 @@
> **重要:本目录不再接受新的管理后台功能开发。** > **重要:本目录不再接受新的管理后台功能开发。**
> >
> 所有平台管理后台 UI(用户、计费、图片额度、策略、模型中心等)必须在独立仓库 **`memind_adm`** 中实现,本地开发端口 **5174**(生产 gadm),API 端口 **8085**。 > 所有平台管理后台 UI(用户、计费、图片额度、策略、模型中心等)必须在独立仓库 **`memind_adm`** 中实现,本地开发端口 **5174**(生产 [md.tkmind.cn](https://md.tkmind.cn)),API 端口 **8085**。
> >
> 本目录(Memind `ops/`,本地约 **3002**)仅保留 **Plaza 运营**相关页面(审核、精选、创作者等)及历史遗留的超级管理路由;**不得**在此新增页面、导航项或 API 客户端。 > 本目录(Memind `ops/`,本地约 **3002**)仅保留 **Plaza 运营**相关页面(审核、精选、创作者等)及历史遗留的超级管理路由;**不得**在此新增页面、导航项或 API 客户端。