mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
docs: document roles, invites, audit log and self-signup
- configuration.md (en/zh): ALLOW_SELF_SIGNUP, AUDIT_RETENTION_DAYS, member schema, role table, invite/self-signup sections, invite KV key, audit_logs D1 table, new admin endpoints - deployment.md (en/zh): migration list through 0005 - README (en/zh) and AGENTS.md: access model, invites, audit log - config.example.yaml: members example; .env.example: new variables - .gitignore: ignore local saas-roadmap.md
This commit is contained in:
parent
11b74aa82a
commit
ce9f6147f1
10 changed files with 184 additions and 76 deletions
|
|
@ -30,6 +30,8 @@ WebHooker requires several secrets to function. For local development, store the
|
|||
| `TELEGRAM_RICH_HEADER_HOST` | Base URL of an external rich-header service; when unset, the built-in `GET /api/richheader` serves the Telegram avatar card | Built-in `/api/richheader` |
|
||||
| `BASE_URL` | Public URL for OAuth callbacks | `http://localhost:8787` |
|
||||
| `ADMIN_USER_IDS` | Comma-separated GitHub user IDs (or logins) allowed to access the Web UI | Disabled |
|
||||
| `ALLOW_SELF_SIGNUP` | When enabled (`1`/`true`), GitHub users without any group access get a personal group on first login instead of `403` | Disabled |
|
||||
| `AUDIT_RETENTION_DAYS` | Audit-log retention in days for the scheduled cleanup | `90` |
|
||||
|
||||
## Webhook Providers
|
||||
|
||||
|
|
@ -48,26 +50,31 @@ WebHooker ships with a built-in config console at `/admin` for managing routes i
|
|||
|
||||
### Setup
|
||||
|
||||
1. Configure `ADMIN_USER_IDS` with the GitHub user IDs allowed to manage routes. Logins are also accepted, e.g. `ADMIN_USER_IDS=12345,RhenCloud`. If unset, the console is disabled.
|
||||
1. Configure `ADMIN_USER_IDS` with the GitHub user IDs allowed to manage everything. Logins are also accepted, e.g. `ADMIN_USER_IDS=12345,RhenCloud`. If unset, the console is disabled (unless `ALLOW_SELF_SIGNUP` is enabled).
|
||||
2. Open `/admin` and sign in with GitHub.
|
||||
3. Only users in the whitelist receive a session cookie; everyone else gets `403`.
|
||||
3. Users without any access get `403`, except when `ALLOW_SELF_SIGNUP=1` (they receive a personal group) or when they follow a group [invite link](#invites).
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
| ---------------------------------- | --------------------------------------- |
|
||||
| `GET /admin` | Config console UI |
|
||||
| `GET /admin/login` | Start GitHub OAuth sign-in |
|
||||
| `GET /admin/logout` | Destroy session |
|
||||
| `GET /admin/api/me` | Current session, scope, and groups |
|
||||
| `GET /admin/api/routes` | List routes (admin only) |
|
||||
| `PUT /admin/api/routes` | Replace routes (admin only) |
|
||||
| `GET /admin/api/groups` | List groups (scoped to access) |
|
||||
| `PUT /admin/api/groups` | Replace groups (super admin only) |
|
||||
| `GET /admin/api/groups/:id/routes` | List a group's routes |
|
||||
| `PUT /admin/api/groups/:id/routes` | Replace a group's routes |
|
||||
| `GET /admin/api/logs` | Send logs (scoped to accessible routes) |
|
||||
| `GET /admin/api/logs/:id` | Single send-log entry (scoped) |
|
||||
| Endpoint | Description |
|
||||
| ----------------------------------------- | -------------------------------------------- |
|
||||
| `GET /admin` | Config console UI |
|
||||
| `GET /admin/login` | Start GitHub OAuth sign-in |
|
||||
| `GET /admin/logout` | Destroy session |
|
||||
| `GET /admin/invite?token=…` | Accept a group invite (browser page) |
|
||||
| `GET /admin/api/me` | Current session, scope, groups, and roles |
|
||||
| `GET /admin/api/routes` | List routes (scoped to access) |
|
||||
| `PUT /admin/api/routes` | Replace routes (owner/admin per group) |
|
||||
| `GET /admin/api/groups` | List groups + the signed-in user's role each |
|
||||
| `PUT /admin/api/groups` | Replace groups (super: all; owner: own only) |
|
||||
| `GET /admin/api/groups/:id/routes` | List a group's routes |
|
||||
| `PUT /admin/api/groups/:id/routes` | Replace a group's routes (owner/admin) |
|
||||
| `GET /admin/api/logs` | Send logs (scoped to accessible routes) |
|
||||
| `GET /admin/api/logs/:id` | Single send-log entry (scoped) |
|
||||
| `POST /admin/api/groups/:id/invites` | Create an invite link (owner) |
|
||||
| `GET /admin/api/groups/:id/invites` | List pending invites (owner) |
|
||||
| `DELETE /admin/api/invites/:token` | Revoke an invite (owner) |
|
||||
| `GET /admin/api/audit` | Audit log (scoped to accessible groups) |
|
||||
|
||||
The console lets you add, edit, delete, and toggle routes. Saved routes are written to KV `config:routes` immediately and the config cache is invalidated so the webhook pipeline picks them up on the next run.
|
||||
|
||||
|
|
@ -167,29 +174,53 @@ Routes belong to groups. Groups scope admin access and can restrict which events
|
|||
{
|
||||
"id": "backend-team",
|
||||
"name": "Backend Team",
|
||||
"adminIds": ["rhencloud"],
|
||||
"members": [
|
||||
{ "login": "rhencloud", "role": "owner" },
|
||||
{ "login": "octobot", "role": "admin" },
|
||||
{ "login": "reader", "role": "viewer" }
|
||||
],
|
||||
"owners": ["myorg"],
|
||||
"providers": ["github", "gitea"]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | -------- | -------- | ------------------------------------------------------------------------- |
|
||||
| `id` | string | Yes | Lowercase id (`a-z0-9`, `-`); referenced by each route's `groupId` |
|
||||
| `name` | string | Yes | Human-readable group name |
|
||||
| `adminIds` | string[] | Yes | GitHub user IDs or logins who may manage this group's routes |
|
||||
| `owners` | string[] | No | Org/user logins whose events are accepted into this group; empty = all |
|
||||
| `providers` | string[] | No | Source platforms allowed into this group (`github`, `gitea`); empty = all |
|
||||
| `emoji` | boolean | No | Whether to include emoji in this group's messages (default `true`) |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | -------- | -------- | ---------------------------------------------------------------------------- |
|
||||
| `id` | string | Yes | Lowercase id (`a-z0-9`, `-`); referenced by each route's `groupId` |
|
||||
| `name` | string | Yes | Human-readable group name |
|
||||
| `members` | object[] | No | `{ login, role }` entries; role is `owner`, `admin`, or `viewer` |
|
||||
| `adminIds` | string[] | No | Deprecated legacy field; treated as `members` with role `owner` when present |
|
||||
| `owners` | string[] | No | Org/user logins whose events are accepted into this group; empty = all |
|
||||
| `providers` | string[] | No | Source platforms allowed into this group (`github`, `gitea`); empty = all |
|
||||
| `emoji` | boolean | No | Whether to include emoji in this group's messages (default `true`) |
|
||||
|
||||
### Roles
|
||||
|
||||
Every group member has one of three roles. Super admins (`ADMIN_USER_IDS`) always bypass them.
|
||||
|
||||
| Role | View routes/logs | Edit routes | Manage members & invites | Edit group settings |
|
||||
| -------- | ---------------- | ----------- | ------------------------ | ------------------- |
|
||||
| `owner` | ✓ | ✓ | ✓ | ✓ (except `owners`) |
|
||||
| `admin` | ✓ | ✓ | ✗ | ✗ |
|
||||
| `viewer` | ✓ (read-only) | ✗ | ✗ | ✗ |
|
||||
|
||||
### Access Model
|
||||
|
||||
- **Super admins** (`ADMIN_USER_IDS`) see and edit every group and all routes.
|
||||
- **Group admins** (`adminIds`) only see and edit the groups they manage; submitting a route outside their groups returns `403`.
|
||||
- **Super admins** (`ADMIN_USER_IDS`) see and edit every group and all routes; only they can edit a group's `owners` list.
|
||||
- **Owners** manage their group's routes, members, invites, name, `emoji`, and `providers`. They cannot remove the last owner or demote themselves when no other owner remains.
|
||||
- **Admins** edit routes inside their groups and view logs; **viewers** get a read-only console.
|
||||
- Group admin endpoints operate on a single group at a time via `/admin/api/groups/:id/routes`; `groupId` is forced from the path parameter.
|
||||
- The `owners` list restricts which event actors (sender logins) the group's routes will dispatch at all.
|
||||
- The `providers` list restricts which forge's events (`github`, `gitea`) the group's routes will dispatch. This lets you keep GitHub and Gitea groups separate even when org/user names collide.
|
||||
|
||||
### Invites
|
||||
|
||||
Owners (and super admins) can create single-use invite links valid for 7 days from the group's _Members_ panel. Accepting an invite adds the user with the invited role (`admin` or `viewer` — never `owner`); an existing `viewer` is upgraded to `admin`. Invites are stored in KV as `invite:{token}`.
|
||||
|
||||
### Self Sign-up
|
||||
|
||||
With `ALLOW_SELF_SIGNUP=1`, a GitHub user who has no group access gets a personal group (`u-{userId}`, owned by them) on first login instead of a `403`. This is the entry point for a fully self-service SaaS install; disable it to keep the console invite-only.
|
||||
|
||||
## Filter Types
|
||||
|
||||
See the [Filter Tutorial](./filters) for a hands-on guide with worked examples.
|
||||
|
|
@ -230,6 +261,7 @@ Filters accept either a single string or an array of strings:
|
|||
| `token:{userId}` | `{ userId, accessToken, expiresAt, refreshToken? }` | 0.9 × token expiry |
|
||||
| `token-reverse:{sha256}` | User id for reverse lookup by token | 0.9 × token expiry |
|
||||
| `state:{hex}` | `{ redirectTo, expiresAt, discordUserId?, telegramUserId?, telegramChatId? }` | 600 seconds |
|
||||
| `invite:{token}` | `{ groupId, role, expiresAt, createdBy, note? }` | 7 days |
|
||||
| `delivery:{id}` | Webhook delivery id (dedup marker) | 300 seconds |
|
||||
| `msg:{routeId}:{key}:{target}` | Message id tracking for in-place updates (e.g. `workflow_run`) | 7 days |
|
||||
| `cmd:guild:{id}` | Guild id whose commands were registered (dedup) | Permanent |
|
||||
|
|
@ -239,10 +271,13 @@ Filters accept either a single string or an array of strings:
|
|||
|
||||
## D1 Storage Layout
|
||||
|
||||
The D1 database (`DB` binding, database `webhooker`) holds three tables:
|
||||
The D1 database (`DB` binding, database `webhooker`) holds four tables:
|
||||
|
||||
| Table | Purpose |
|
||||
| ---------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `send_logs` | One row per dispatch attempt (route id, event, target, ok/error, duration, error code, detail) |
|
||||
| `audit_logs` | One row per admin operation (login/logout, group/route/member/invite changes) |
|
||||
| `discord_links` | Maps `discord_user_id` → `github_user_id` for `/gh` Discord commands |
|
||||
| `telegram_links` | Maps `telegram_user_id` → `github_user_id` for `/gh` Telegram commands |
|
||||
|
||||
`audit_logs` is pruned automatically by the scheduled trigger after `AUDIT_RETENTION_DAYS` (default 90).
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ If the database already has these tables/columns (e.g. previously migrated with
|
|||
npx wrangler d1 execute webhooker --remote --file ./migrations/0001_init.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0002_log_detail.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0003_telegram_links.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0004_add_group_id.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0005_audit_logs.sql
|
||||
```
|
||||
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
| --------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------- |
|
||||
| `BASE_URL` | OAuth 回调的公开 URL | `http://localhost:8787` |
|
||||
| `ADMIN_USER_IDS` | 允许访问 WebUI 的 GitHub 用户 ID(或登录名),逗号分隔 | 未设置时 WebUI 关闭 |
|
||||
| `ALLOW_SELF_SIGNUP` | 开启(`1`/`true`)后,没有任何分组权限的 GitHub 用户首次登录会自动获得个人分组而非 403 | 关闭 |
|
||||
| `AUDIT_RETENTION_DAYS` | 定时清理时审计日志的保留天数 | `90` |
|
||||
| `DISCORD_PUBLIC_KEY` | Discord 应用的公钥(开发者门户获取),交互功能必需 | 未设置时交互返回 401 |
|
||||
| `DISCORD_APPLICATION_ID` | Discord 应用 ID;省略时自动获取 | 自动获取 |
|
||||
| `TELEGRAM_WEBHOOK_SECRET` | `POST /telegram/webhook` 验签密钥(X-Telegram-Bot-Api-Secret-Token) | 未设置时不校验 |
|
||||
|
|
@ -48,26 +50,31 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
|
||||
### 设置
|
||||
|
||||
1. 配置 `ADMIN_USER_IDS`,填写允许管理路由的 GitHub 用户 ID,也支持登录名,例如 `ADMIN_USER_IDS=12345,RhenCloud`。未设置时控制台禁用。
|
||||
1. 配置 `ADMIN_USER_IDS`,填写允许管理路由的 GitHub 用户 ID,也支持登录名,例如 `ADMIN_USER_IDS=12345,RhenCloud`。未设置时控制台禁用(除非开启 `ALLOW_SELF_SIGNUP`)。
|
||||
2. 打开 `/admin` 并使用 GitHub 登录。
|
||||
3. 只有白名单中的用户会获得会话 Cookie;其他人收到 `403`。
|
||||
3. 没有任何权限的用户收到 `403`,除非开启 `ALLOW_SELF_SIGNUP=1`(自动获得个人分组)或通过分组[邀请链接](#邀请)加入。
|
||||
|
||||
### 端点
|
||||
|
||||
| 端点 | 说明 |
|
||||
| ---------------------------------- | ---------------------------- |
|
||||
| `GET /admin` | 配置控制台页面 |
|
||||
| `GET /admin/login` | 开始 GitHub OAuth 登录 |
|
||||
| `GET /admin/logout` | 销毁会话 |
|
||||
| `GET /admin/api/me` | 当前会话、权限范围和分组 |
|
||||
| `GET /admin/api/routes` | 列出路由(仅管理员) |
|
||||
| `PUT /admin/api/routes` | 替换路由(仅管理员) |
|
||||
| `GET /admin/api/groups` | 列出分组(按权限过滤) |
|
||||
| `PUT /admin/api/groups` | 替换分组(仅超级管理员) |
|
||||
| `GET /admin/api/groups/:id/routes` | 列出某分组的路由 |
|
||||
| `PUT /admin/api/groups/:id/routes` | 替换某分组的路由 |
|
||||
| `GET /admin/api/logs` | 发送日志(按可访问路由过滤) |
|
||||
| `GET /admin/api/logs/:id` | 单条发送日志(按权限过滤) |
|
||||
| 端点 | 说明 |
|
||||
| ------------------------------------- | ------------------------------------ |
|
||||
| `GET /admin` | 配置控制台页面 |
|
||||
| `GET /admin/login` | 开始 GitHub OAuth 登录 |
|
||||
| `GET /admin/logout` | 销毁会话 |
|
||||
| `GET /admin/invite?token=…` | 接受分组邀请(浏览器页面) |
|
||||
| `GET /admin/api/me` | 当前会话、权限范围、分组和角色 |
|
||||
| `GET /admin/api/routes` | 列出路由(按权限过滤) |
|
||||
| `PUT /admin/api/routes` | 替换路由(按分组 owner/admin 权限) |
|
||||
| `GET /admin/api/groups` | 列出分组 + 当前用户在各组的角色 |
|
||||
| `PUT /admin/api/groups` | 替换分组(超管全量;owner 仅自己的组) |
|
||||
| `GET /admin/api/groups/:id/routes` | 列出某分组的路由 |
|
||||
| `PUT /admin/api/groups/:id/routes` | 替换某分组的路由(owner/admin) |
|
||||
| `GET /admin/api/logs` | 发送日志(按可访问路由过滤) |
|
||||
| `GET /admin/api/logs/:id` | 单条发送日志(按权限过滤) |
|
||||
| `POST /admin/api/groups/:id/invites` | 创建邀请链接(owner) |
|
||||
| `GET /admin/api/groups/:id/invites` | 列出待接受邀请(owner) |
|
||||
| `DELETE /admin/api/invites/:token` | 撤销邀请(owner) |
|
||||
| `GET /admin/api/audit` | 审计日志(按可访问分组过滤) |
|
||||
|
||||
控制台支持新增、编辑、删除和开关路由。保存后立即写入 KV `config:routes` 并使配置缓存失效,下一次 webhook 处理即会生效。
|
||||
|
||||
|
|
@ -167,29 +174,53 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
{
|
||||
"id": "backend-team",
|
||||
"name": "后端团队",
|
||||
"adminIds": ["rhencloud"],
|
||||
"members": [
|
||||
{ "login": "rhencloud", "role": "owner" },
|
||||
{ "login": "octobot", "role": "admin" },
|
||||
{ "login": "reader", "role": "viewer" }
|
||||
],
|
||||
"owners": ["myorg"],
|
||||
"providers": ["github", "gitea"]
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| ----------- | -------- | ---- | ----------------------------------------------------------- |
|
||||
| `id` | string | 是 | 小写 id(`a-z0-9`、`-`),由每条路由的 `groupId` 引用 |
|
||||
| `name` | string | 是 | 可读的分组名称 |
|
||||
| `adminIds` | string[] | 是 | 可管理该分组路由的 GitHub 用户 ID 或登录名 |
|
||||
| `owners` | string[] | 否 | 允许事件进入该分组的组织/用户登录名;为空表示不限制 |
|
||||
| `providers` | string[] | 否 | 允许进入该分组的来源平台(`github`、`gitea`);为空表示全部 |
|
||||
| `emoji` | boolean | 否 | 是否在该分组消息中显示 emoji(默认 `true`) |
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| ----------- | -------- | ---- | ------------------------------------------------------------------ |
|
||||
| `id` | string | 是 | 小写 id(`a-z0-9`、`-`),由每条路由的 `groupId` 引用 |
|
||||
| `name` | string | 是 | 可读的分组名称 |
|
||||
| `members` | object[] | 否 | `{ login, role }` 列表;角色为 `owner`、`admin` 或 `viewer` |
|
||||
| `adminIds` | string[] | 否 | 已废弃的旧字段;存在时按 role 为 `owner` 的成员处理 |
|
||||
| `owners` | string[] | 否 | 允许事件进入该分组的组织/用户登录名;为空表示不限制 |
|
||||
| `providers` | string[] | 否 | 允许进入该分组的来源平台(`github`、`gitea`);为空表示全部 |
|
||||
| `emoji` | boolean | 否 | 是否在该分组消息中显示 emoji(默认 `true`) |
|
||||
|
||||
### 角色
|
||||
|
||||
每个分组成员拥有三种角色之一。超级管理员(`ADMIN_USER_IDS`)始终绕过角色限制。
|
||||
|
||||
| 角色 | 查看路由/日志 | 编辑路由 | 管理成员与邀请 | 编辑分组设置 |
|
||||
| -------- | ------------- | -------- | -------------- | ------------ |
|
||||
| `owner` | ✓ | ✓ | ✓ | ✓(`owners` 除外) |
|
||||
| `admin` | ✓ | ✓ | ✗ | ✗ |
|
||||
| `viewer` | ✓(只读) | ✗ | ✗ | ✗ |
|
||||
|
||||
### 权限模型
|
||||
|
||||
- **超级管理员**(`ADMIN_USER_IDS`)可查看和编辑所有分组及全部路由。
|
||||
- **分组管理员**(`adminIds`)只能查看和编辑其管理的分组;提交其分组之外的路由返回 `403`。
|
||||
- **超级管理员**(`ADMIN_USER_IDS`)可查看和编辑所有分组及全部路由;只有他们能修改分组的 `owners` 列表。
|
||||
- **owner** 管理本组的路由、成员、邀请、名称、`emoji` 与 `providers`;不能移除最后一位 owner,也没有其他 owner 时不能把自己降级。
|
||||
- **admin** 可编辑本组路由并查看日志;**viewer** 只读控制台。
|
||||
- 分组管理端点通过 `/admin/api/groups/:id/routes` 一次只操作一个分组;`groupId` 由路径参数强制指定。
|
||||
- `owners` 列表限定哪些事件参与者(发送者登录名)的事件会被该分组的路由投递。
|
||||
- `providers` 列表限定哪个 forge(`github`、`gitea`)的事件会被该分组的路由投递。即使组织/用户同名,也可以借此将 GitHub 与 Gitea 分组区分开。
|
||||
|
||||
### 邀请
|
||||
|
||||
owner(及超级管理员)可在分组的「成员」面板创建一次性邀请链接,7 天内有效。接受邀请后用户以邀请角色(`admin` 或 `viewer`,绝不授予 `owner`)加入;已有的 `viewer` 会被升级为 `admin`。邀请存储在 KV `invite:{token}`。
|
||||
|
||||
### 自助注册
|
||||
|
||||
开启 `ALLOW_SELF_SIGNUP=1` 后,没有分组权限的 GitHub 用户首次登录会获得一个由自己担任 owner 的个人分组(`u-{userId}`),而不是 `403`。这是全自助 SaaS 部署的入口;关闭它则控制台保持仅邀请制。
|
||||
|
||||
## 过滤器类型
|
||||
|
||||
实操指南见[过滤器教程](./filters),包含完整示例。
|
||||
|
|
@ -230,6 +261,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
| `token:{userId}` | `{ userId, accessToken, expiresAt, refreshToken? }` | 0.9 × Token 有效期 |
|
||||
| `token-reverse:{sha256}` | 用于按 Token 反查的用户 id | 0.9 × Token 有效期 |
|
||||
| `state:{hex}` | `{ redirectTo, expiresAt, discordUserId?, telegramUserId?, telegramChatId? }` | 600 秒 |
|
||||
| `invite:{token}` | `{ groupId, role, expiresAt, createdBy, note? }` | 7 天 |
|
||||
| `delivery:{id}` | Webhook 投递 id(去重标记) | 300 秒 |
|
||||
| `msg:{routeId}:{key}:{target}` | 原地更新用消息 id 追踪(如 `workflow_run`) | 7 天 |
|
||||
| `cmd:guild:{id}` | 已注册命令的服务器 id(去重标记) | 永久 |
|
||||
|
|
@ -239,10 +271,13 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
|
||||
## D1 存储布局
|
||||
|
||||
D1 数据库(`DB` 绑定,数据库 `webhooker`)包含三张表:
|
||||
D1 数据库(`DB` 绑定,数据库 `webhooker`)包含四张表:
|
||||
|
||||
| 表 | 用途 |
|
||||
| ---------------- | ---------------------------------------------------------------------- |
|
||||
| `send_logs` | 每次分发尝试一行(路由 id、事件、目标、成功/失败、耗时、错误码、详情) |
|
||||
| `audit_logs` | 每次管理操作一行(登录/登出、分组/路由/成员/邀请变更) |
|
||||
| `discord_links` | 映射 `discord_user_id` → `github_user_id`,用于 Discord `/gh` 命令 |
|
||||
| `telegram_links` | 映射 `telegram_user_id` → `github_user_id`,用于 Telegram `/gh` 命令 |
|
||||
|
||||
`audit_logs` 由定时触发器按 `AUDIT_RETENTION_DAYS`(默认 90)自动清理。
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ npm run db:migrate # 将迁移应用到本地(Miniflare)数据库
|
|||
npx wrangler d1 execute webhooker --remote --file ./migrations/0001_init.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0002_log_detail.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0003_telegram_links.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0004_add_group_id.sql
|
||||
npx wrangler d1 execute webhooker --remote --file ./migrations/0005_audit_logs.sql
|
||||
```
|
||||
|
||||
:::
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue