mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
feat(cordis): add OpenFlare Cordis 架构改造设计
docs(changelog): 修正表述笔误
refactor(cordis): 磁盘缓存改用上上游能力并清理本地副本
按上游/下游归属规约:类型断言守卫已回流 Wavelet(f3d85d5,附回归用例),
本仓库删除 OpenFlare/plugins/server/pkg/cache 整包并改 import 到
Wavelet/pkg/cache/disk,同步后与上游零漂移。
验证:go build 通过;go test ./... exit 0(137 包 ok);256 条路由对拍与
232 条 swagger 操作均零差异;make build-all 四进制;前端零改动。
docs(cordis): 记录 T1 清理结果与五个复用阻塞点
refactor(cordis): server 复用上游 pkg 能力并删除等价本地副本
按上游/下游归属规约清理重复实现,删除 7 个与上游等价的本地包并改 import:
shared/response→pkg/response、pkg/{logger,mail,trace,httppool,cache/ram}→
上游同名包、infra/persistence/batchwriter→pkg/batchwriter。逐项核过差异:
httppool 逐字节相同;logger 的 Config 字段完全一致;response 的 7 个 Abort*
一致;cache/ram 换过去顺带把裸 go 变回带 panic 恢复的 util.Go。
两处非等价差异按语义处理:
- batchwriter.Stats 与 status DTO 原为类型别名,改为消费侧逐字段转换,
避免 model 反向依赖基础设施类型;
- 上游 pkg/idgen 要求显式 Init(本地副本为懒加载自动初始化),本次保留本地
副本,待与 infra 初始化一并迁移(已登记在清理计划)。
验证:go build 通过;go test ./... exit 0(138 包 ok);256 条路由对拍零差异;
make swagger 232 条操作零增减,且归一化后与旧文档深度相等——差异仅为
response.Any / logger.LogEntry 两个定义名随包路径改名,接口形状未变。
chore(cordis): 回流内核与 pkg/util 通用能力并清理 vendoring 污染
按新增的上游/下游归属规约:HandleRaw/BasePath 与版本比较、网络、格式化助手
属通用能力,已提交到 Wavelet 分支 feat/cordis-router-raw-routes,本仓库改为
纯同步获取(pkg/util 已零漂移),补丁登记保留至上游合并。
同时修掉我此前 git add -A 造成的污染:首次 vendoring 把上游工作区里被
gitignore 的运行期产物一起提交进来(upload 的 diskcache 缓存块 650 个与
driver_http/dist 前端构建物 380 个,共 12872 行/1030 文件)。sync-upstream.sh
现显式排除 uploads/dist/data/*.db,.gitignore 补上对应兜底规则。
AGENTS.md 增加上游/下游改动归属规约,并把仍指向前 Cordis 布局的硬性约束
(internal/router + Serve、internal/repository/logstore、internal/platform/bootstrap、
internal/cmd)改到当前插件路径。
验证:go build 通过;go test ./... exit 0(144 包 ok);make swagger 232 条
操作与基线逐条一致;make build-all 四进制;gofmt 干净。
feat(cordis): server 插件化并改由内核挂载控制面路由
新增 plugins/server/plugin.go:Apply 以 ctx.Router().Group(app.api_prefix)
声明根级与 /v1 全部路由;33 个注册函数由 *gin.RouterGroup 改为
core.RouterExtension,RegisterCollection 改用内核新增的 HandleRaw 保留
尾部斜杠变体,AdminMiddlewares 返回 []any(Go 不允许把 []T 展开为 ...any)。
删除 router.Serve 与 registerRoutes,装配根改为 core.App +
driver_http.New(WithEngine(router.BuildEngine())),监听、信号与优雅退出归内核;
前端 SPA 的 NoRoute 兜底因内核暂无贡献点而保留在引擎层。
路由保真证据:plugin_parity_test 对拍 baseline/routes-engine.txt 的 256 条
(方法 路径) 零差异;go test ./... exit 0(144 包 ok,含真实 handler 的
openflare/integration 用例走同一条挂载路径);make swagger 232 条操作与基线
逐条一致;golangci-lint 0 issues;make build-all 四进制;embed_frontend
标签编译通过;前端零改动。
已知待补:带 Redis 的实机 HTTP 冒烟(本机 6379 未启动,session store 与
改造前一样在建店阶段即 fatal),以及 bootstrap 的任务/设置/迁移注册迁入 Apply。
feat(core): RouterExtension 增加 HandleRaw 与 BasePath 以保真尾部斜杠路由
server 插件化的前置:Handle 经 cleanPath 会剥掉尾部斜杠,无法表达
/resource 与 /resource/ 两条不同路由,而 OpenFlare 有 20 个历史 list
端点两者都注册且部署关闭了 RedirectTrailingSlash,缺失即 404。新增
HandleRaw 与 BasePath(作用域包装器同样登记反注册),补 extpoints 用例;
并把 router.Serve 拆出 BuildEngine 以便交给 driver_http.WithEngine 复用,
新增路由表导出 harness,固化 256 条 (方法 路径) 基线供插件化对拍。
上游补丁登记于 backend/OpenFlare/upstream-patches.md,同步脚本改为按目录
前缀输出差异并在同步后提醒确认补丁是否仍在。
验证:go build 通过;go test ./... exit 0(143 包 ok);gofmt 干净。
docs(cordis): 记录 server 插件接入内核的可行路径与内核能力缺口
feat(cordis): agent/relay/flared 落地为内核驱动插件
三个边缘守护进程各新增 plugin.go,实现 core.Plugin + core.Driver
(自定义 DriverType 与同名 profile),装配与生命周期从 main 迁入
Apply/Start/Stop:Apply 负责 JSON 配置加载、运行环境与用户确保、
openresty/frps/frpc 管理器与各服务装配;Start 以 util.Go 拉起阻塞式
runner 与 GeoIP 周期更新;Stop 收敛主循环结果并在超时时报错而非静默。
入口改为 core.NewApp(core.WithProfile(...)) + Prepare/Run,保持
-config 旗标、默认路径、退出码与启动/停止日志不变。
验证:go build 通过;go test ./... exit 0(143 包 ok,含 3 个插件身份
与配置失败路径测试);make build-all 四进制产出;三进制实跑缺失配置
均 exit 1 且错误链保留 load {agent,relay,flared} config 原因;gofmt 干净。
refactor(cordis): 按功能职责拆分为 4 个插件与 share 共享层
backend/OpenFlare 不再平铺遗留分层,改为 plugins/{server,agent,relay,flared}
加 share/:控制面业务(openflare/admin/oauth/user/upload/cap/config/health 与
repository/model/infra/router 等支撑层)归 server;三个边缘守护进程各自成插件;
被两个以上插件消费的 protocol/geoip/wsclient/render/pagesarchive/edge 归 share。
同时把 pkg/util 与 buildinfo 合并回上游 pkg(上游已覆盖全部符号,仅 8 个函数与
2 个类型为 OpenFlare 独有,已一并迁入),装配根统一到 backend/cmd(含三个 daemon
入口),Dockerfile 与 release 工作流的构建路径和 -X 注入路径同步更新。
验证:go build 通过;go test ./... exit 0(141 包 ok);make swagger exit 0 且
232 条 API 操作与基线逐条一致;make build-all 产出 4 进制;-X 注入经二进制
strings 实测生效;日志后端直连门禁改写为按 server 插件业务域扫描并在扫描数为 0
时报错(防门禁静默失效);前端零改动。
feat(cordis): 落地 backend/share 共享层与上游同步脚本
跨插件共享资源(控制消息协议、GeoIP+iputil、边缘守护进程日志)从下游包
移入 backend/share,并声明其只能依赖 core/pkg 与标准/第三方库,禁止反向
引用下游业务与具体插件实现;新增 scripts/sync-upstream.sh 只覆盖
backend/{core,pkg,plugins},同步后 --check 报告零差异,证明与上游逐字一致。
go build 通过,go test ./... exit 0(142 包 ok),前端零改动。
refactor(cordis): 采用与 Wavelet 同构的单模块布局并引入上游内核
按上游结构落位:backend/{core,pkg,plugins} 为 Wavelet 上游拷贝,OpenFlare
全部业务收拢到上游 downstream 所对应的位置 backend/OpenFlare/,模块名保持
Wavelet 以保证上游 import 路径逐字一致、同步零改写;三个 daemon 入口移至
backend/OpenFlare/cmd,backend/cmd 与 main.go 作为控制面装配根。
行为不变:go build 通过,142 个测试包全绿(含上游插件测试),232 条 API
操作与改造前逐条一致,四进制产物正常,前端零改动。swagger 暂只扫描下游代码,
待 P4 挂载上游路由后再纳入 plugins/。
style: 修正模块路径改写导致的 import 分组排序漂移
refactor(layout): Go 代码迁入 backend/ 并将模块名简化为 OpenFlare
对齐上游 Wavelet 的仓库布局,为以第二 module 形态 vendoring Cordis 内核与
平台插件做准备:模块路径整体改写为 OpenFlare,Go 目标加 cd backend,
swaggo 产物移至 backend/docs 并把 json/yaml 复制回 docs/ 供站点消费,
Dockerfile 与 release 工作流的构建目录、ldflags 模块路径同步更新。
行为保持不变:232 条路由与改造前逐条一致,95 个测试包全绿,
四进制产物正常,前端零改动。
chore(cordis): 落地改造计划与 schema/路由基线
新增 legacy_dump_test 迁移快照 harness:在临时 sqlite 库上按生产顺序
(goose.UpTo → zone 导入 → goose.Up)跑完 76 个历史迁移并导出 schema 与
版本序列,作为改造前后一致性门禁的唯一事实来源。同时记录 232 条路由清单
与 foundation 实施计划。
docs(cordis): add OpenFlare Cordis 架构改造设计
明确上游以第二 module 形态 vendoring 进 backend/Wavelet、4 个插件
(server/agent/relay/flared) 全部装载内核,并规定保留 76 个历史 goose
迁移 + 一次性版本 stamp 桥接的迁移方案,配套三方 schema 一致性门禁,
确保已部署库不重跑历史、不丢数据。
This commit is contained in:
@@ -10,6 +10,14 @@ sidebar: false
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### 💄 其他/体验
|
||||
|
||||
- 后端代码整体迁入 `backend/`,与上游 Wavelet 的仓库布局对齐(Cordis 插件化改造第一阶段),模块名保持 `Wavelet` 以保证上游包路径逐字一致。构建、测试、镜像与发布链路已同步调整,`make build-all` / `make dev` / `make swagger` 等本地命令用法不变;HTTP 接口与控制台行为均无变化。
|
||||
- 引入上游 Cordis 微内核与平台插件到 `backend/{core,pkg,plugins}`(与上游逐字一致,可用 `scripts/sync-upstream.sh` 重复同步),并新增 `backend/OpenFlare/share/` 承载多插件共享资源(控制消息协议、GeoIP、边缘日志)。此阶段仅落位结构与共享层,尚未改变运行时行为。
|
||||
- 下游代码按功能职责拆为 `server`/`agent`/`relay`/`flared` 四个插件与 `backend/OpenFlare/share` 共享层;三个边缘守护进程改由 Cordis 内核装配启动(profile `agent`/`relay`/`flared`),`-config` 旗标、默认配置路径、退出码与启动日志保持原样。
|
||||
- 控制台 API 改由 Cordis 内核提供服务:`server` 插件以声明式路由注册,HTTP 监听与优雅退出交给内核的 http 驱动。全部 256 条路由(含 20 条带尾部斜杠的历史列表接口)与改造前逐条一致,232 条对外 API 操作无变化。
|
||||
|
||||
- 清理与上游 Wavelet 重复的平台实现:响应封装、日志、邮件、链路追踪、HTTP 连接池、内存/磁盘缓存、批量写入等 8 个本地副本删除并改为使用上游能力(约 600 行重复代码消失,接口形状与文档定义完全一致);顺带把磁盘缓存的类型断言健壮性修复回流上游。
|
||||
## [v3.5.4] - 2026-08-29
|
||||
|
||||
### ✨ 新功能
|
||||
|
||||
@@ -78,7 +78,7 @@ OpenResty (Agent, TLS/WAF)
|
||||
## 组件架构与分工
|
||||
|
||||
### 1. Server (控制面)
|
||||
仓库根目录的 Go 后端(模块 `github.com/Rain-kl/Wavelet`)是 OpenFlare 控制面,基于 Wavelet 全栈脚手架构建:
|
||||
仓库根目录的 Go 后端(模块 `OpenFlare`)是 OpenFlare 控制面,基于 Wavelet 全栈脚手架构建:
|
||||
* 提供管理端 REST API(`/api/v1/d/*`),通过 **Session Cookie** 鉴权,可选 `X-Access-Token` 访问令牌。
|
||||
* 边缘节点协议走 `/api/v1/agent|relay|tunnel/*`,分别使用 `X-Agent-Token` / `X-Tunnel-Token` 鉴权。
|
||||
* 包含配置编译器(Compiler),将数据库中的规则、证书与全局参数统一编译为不可变的配置快照及 OpenResty 物理配置文件文本。
|
||||
|
||||
@@ -70,7 +70,7 @@ OpenFlare 适合需要统一管理多台 OpenResty 代理节点的团队,具
|
||||
|
||||
## 仓库结构
|
||||
|
||||
OpenFlare 已收敛为**单 monorepo**(Go 模块 `github.com/Rain-kl/Wavelet`)。控制面 Server 与边缘组件(Agent、Relay、OpenFlared)共享同一仓库,业务代码按 Wavelet `internal/apps/` 领域模块组织。
|
||||
OpenFlare 已收敛为**单 monorepo**(Go 模块 `OpenFlare`)。控制面 Server 与边缘组件(Agent、Relay、OpenFlared)共享同一仓库,业务代码按 Wavelet `internal/apps/` 领域模块组织。
|
||||
|
||||
在贡献代码时,请严格遵守以下物理分层与目录分工:
|
||||
|
||||
|
||||
-21150
File diff suppressed because it is too large
Load Diff
@@ -78,7 +78,7 @@ OpenResty (Agent, TLS/WAF)
|
||||
## Component Architecture and Division
|
||||
|
||||
### 1. Server (control plane)
|
||||
The Go backend at the repo root (module `github.com/Rain-kl/Wavelet`) is the OpenFlare control plane, built on the Wavelet full-stack scaffold:
|
||||
The Go backend at the repo root (module `OpenFlare`) is the OpenFlare control plane, built on the Wavelet full-stack scaffold:
|
||||
* Provides admin REST APIs (`/api/v1/d/*`) authenticated via **Session Cookie**, with optional `X-Access-Token`.
|
||||
* Edge node protocols go through `/api/v1/agent|relay|tunnel/*`, authenticated with `X-Agent-Token` / `X-Tunnel-Token` respectively.
|
||||
* Contains the config Compiler, uniformly compiling DB rules, certs, and global params into immutable config snapshots and OpenResty physical config file text.
|
||||
|
||||
@@ -70,7 +70,7 @@ When developing and contributing code, **you must strictly follow** these busine
|
||||
|
||||
## Repository Structure
|
||||
|
||||
OpenFlare has converged to a **single monorepo** (Go module `github.com/Rain-kl/Wavelet`). The control-plane Server and edge components (Agent, Relay, OpenFlared) share the repo, organized by Wavelet `internal/apps/` domain modules.
|
||||
OpenFlare has converged to a **single monorepo** (Go module `OpenFlare`). The control-plane Server and edge components (Agent, Relay, OpenFlared) share the repo, organized by Wavelet `internal/apps/` domain modules.
|
||||
|
||||
When contributing code, strictly follow this physical layering and directory division:
|
||||
|
||||
|
||||
@@ -0,0 +1,620 @@
|
||||
# OpenFlare Cordis 基础改造实施计划(P0–P3)
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 把 OpenFlare 后端迁入 `backend/` 双 module 结构、以 vendoring 方式引入 Wavelet Cordis 上游与 `share` 共享层,并在不改动任何已部署数据库语义的前提下完成 per-plugin 迁移与版本 stamp 桥接。
|
||||
|
||||
**Architecture:** `backend/`(module `OpenFlare`)持有 4 个业务插件与装配根;`backend/Wavelet/`(module `Wavelet`)为上游原样拷贝,`replace` + `go.work` 实现单命令构建。迁移引擎自持 `w_schema_versions(plugin_id, version_id)`,历史 76 链以 plugin id `openflare/legacy` 保真注册,桥接逐行搬运 `goose_db_version` 状态,并保留 Go 侧 zone 导入钩子。
|
||||
|
||||
**Tech Stack:** Go 1.25、Gin、GORM、PostgreSQL/SQLite、ClickHouse(独立链,不动)、goose v3、Cobra、Viper。
|
||||
|
||||
**规格来源:** `docs/superpowers/specs/2026-08-29-openflare-cordis-refactor-design.md`
|
||||
|
||||
**后续计划:** P4(server 插件)、P5(agent/relay/flared 插件)、P6(平台分叉回流)、P7/P8(工具链与加固)各出独立 plan,依赖本 plan 产出的骨架与门禁。
|
||||
|
||||
---
|
||||
|
||||
## 进度与布局修正(2026-08-29 执行中更新)
|
||||
|
||||
**已完成**
|
||||
- Task 1 基线:`docs/superpowers/specs/baseline/{schema-A.sql,versions-A.txt,routes.txt}`,由 `backend/OpenFlare/infra/persistence/migrator/legacy_dump_test.go` 产出(`OF_DUMP_SCHEMA` / `OF_DUMP_VERSIONS` 触发,A 路 43 表、版本止于 `202608090003`)。
|
||||
- Task 2 布局:Go 树已入 `backend/`(提交 `f6dd7988`)。
|
||||
|
||||
**Task 3 / Task 4 作废原命令,改为**:与 Wavelet **同构的单 module**(提交 `9bf0b2de`)——`backend/{core,pkg,plugins}` 为上游拷贝,下游业务整体位于 `backend/OpenFlare/`(占据上游 `backend/downstream` 的位置),模块名保持 `Wavelet`。因此不再有 `go.work`、`replace`、第二 go.mod。
|
||||
|
||||
- Task 3 剩余动作:仅需 `scripts/sync-upstream.sh`(覆盖 `backend/{core,pkg,plugins}`,排除 `share`、`OpenFlare`)与上游 `scripts/check_cordis_architecture.sh` 接入。
|
||||
- Task 4 改为:新建 `backend/share/`(import `Wavelet/share/...`)并写入所有权声明;把跨插件共享资源 `pkg/{protocol,geoip,wsclient}`、`apps/edge/logging` 移入;退役与上游重复的 `OpenFlare/pkg/{logger,trace,mail,httppool}` 与 `OpenFlare/{buildinfo,testhelper}`(已核实上游覆盖除 `util` 与 `testhelper.SetupLogStoresForTest` 外的全部符号);`OpenFlare/pkg/util` 的 8 个仅存函数与 `IdentifiableTimeRecord`/`VersionInfo` 合并进上游 `pkg/util`。
|
||||
- 已实测门禁:`go build ./...` 通过、`go test ./...` exit 0(142 包 ok)、`make swagger` exit 0(232 条操作与基线逐条一致)、`make build-all` 四进制产出、`frontend/` 零改动。
|
||||
- 遗留待办:swaggo 暂 `--exclude plugins,core`,Task 4/P4 需连带解除该排除。
|
||||
|
||||
## 关键事实(执行前必读,均已核实)
|
||||
|
||||
- 历史链:`internal/infra/persistence/migrator/goose/{postgres,sqlite}` 各 76 个文件,终版 `202608090003_add_log_indexes.sql`;版本表为 goose 默认 `goose_db_version`。ClickHouse 链独立:`goose/clickhouse` 14 文件 + `goose_clickhouse_version`。
|
||||
- **历史链含 Go 侧数据迁移**:`migrator.Migrate()`(`internal/infra/persistence/migrator/migrator.go:91-103`)先 `goose.UpTo(202607120002)`,再在版本窗口 `[202607120002, 202607130001)` 内执行 `zone.ImportLegacyTx`,最后 `goose.Up()`。改造后该钩子必须仍然生效,且判断依据改为 `w_schema_versions` 中 `openflare/legacy` 的 max version。
|
||||
- 另有 PG 序列修复 `resyncGooseVersionSequence`(同文件 `:158-183`)与迁移后 `clearSystemConfigCache`(`:185-189`),两者必须保留。
|
||||
- 上游迁移引擎实现位于 `Wavelet/backend/cmd/app.go:112-360`(`sharedStore` + `gooseEngine`),`core.MigrationEngine` 为公开接口,OpenFlare 需自持一份实现(放 `OpenFlare/internal/platform/migration`),不可依赖上游 `cmd` 包内未导出符号。
|
||||
- `MigrationEntry.Dir` 被上游引擎忽略;目录基名必须为 `postgres`/`sqlite`。goose 会给每个 plugin_id 插入哨兵 `version_id=0`。
|
||||
- 内核:`core.Profile("agent")` 合法(未知 profile 原样透传);`App.Run` 始终阻塞在信号;长生命周期服务用 `ctx.RegisterDriver` + `ctx.OnDispose`。
|
||||
- 全仓 476 个 `.go` 文件引用 `github.com/Rain-kl/Wavelet`,且**无任何非 import 出现**(已验证),模块路径替换可全局进行。
|
||||
- 前端 `frontend/` 禁止改动;`//go:embed all:dist` 位于 `internal/router/root/frontend.go:18`,dist 由 `make build-embedded` 拷入。
|
||||
|
||||
## 文件结构(本计划涉及)
|
||||
|
||||
| 动作 | 路径 | 职责 |
|
||||
| :-- | :-- | :-- |
|
||||
| Create | `backend/`(git mv 而来) | Go 代码根 |
|
||||
| Modify | `backend/go.mod` | `module OpenFlare` + `require/replace Wavelet` |
|
||||
| Create | `backend/go.work` | 本地双 module 一体构建 |
|
||||
| Create | `backend/Wavelet/**` | 上游拷贝(`core`、`plugins`、`pkg`、`scripts`、`go.mod`) |
|
||||
| Create | `backend/Wavelet/share/{protocol,wsclient,geoip,edge}/` | 跨插件共享资源(OpenFlare 所有,同步排除) |
|
||||
| Create | `backend/Wavelet/share/README.md` | 所有权与同步排除声明 |
|
||||
| Create | `backend/internal/platform/migration/{store,engine,bridge,lock}.go` | 迁移引擎、桥接、锁 |
|
||||
| Create | `backend/plugins/server/migrations/{postgres,sqlite}/*.sql` | 76×2 历史链原样保真 |
|
||||
| Create | `backend/cmd/migrate-audit/main.go` | 三方 schema 一致性门禁工具 |
|
||||
| Create | `scripts/sync-upstream.sh` | 上游同步(排除 `share/`) |
|
||||
| Modify | `Makefile`、`docker/Dockerfile*`、`.github/workflows/*` | 路径切至 `backend/`、ldflags 模块路径 |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: 基线快照(P0)
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/superpowers/specs/baseline/routes.txt`
|
||||
- Create: `docs/superpowers/specs/baseline/go-test.txt`
|
||||
|
||||
- [ ] **Step 1: 导出改造前路由与测试基线**
|
||||
|
||||
```bash
|
||||
cd /Users/ryan/Code/Go/OpenFlare-cordis
|
||||
mkdir -p docs/superpowers/specs/baseline
|
||||
python3 -c "import json;d=json.load(open('docs/swagger.json'));print('\n'.join(sorted(f'{m.upper()} {p}' for p,v in d.get('paths',{}).items() for m in v)))" > docs/superpowers/specs/baseline/routes.txt
|
||||
go test ./... > docs/superpowers/specs/baseline/go-test.txt 2>&1; echo "exit=$?"
|
||||
```
|
||||
Expected: `exit=0`,`routes.txt` 非空。
|
||||
|
||||
- [ ] **Step 2: 生成 A 路 schema 基线(改造前二进制,供 Task 9 对拍)**
|
||||
|
||||
```bash
|
||||
go build -o /tmp/of-baseline-server .
|
||||
OF_DB_PATH=/tmp/of-baseline-a.db timeout 25 /tmp/of-baseline-server api >/tmp/of-a.log 2>&1 || true
|
||||
sqlite3 /tmp/of-baseline-a.db "SELECT name,sql FROM sqlite_master WHERE type='table' ORDER BY name;" > docs/superpowers/specs/baseline/schema-A.sql
|
||||
sqlite3 /tmp/of-baseline-a.db "SELECT version FROM goose_db_version WHERE is_applied=1 ORDER BY version;" > docs/superpowers/specs/baseline/versions-A.txt
|
||||
```
|
||||
Expected: `schema-A.sql` 含 `w_users`、`of_zones`;`versions-A.txt` 末行为 `202608090003`。
|
||||
|
||||
- [ ] **Step 3: 提交基线**
|
||||
|
||||
```bash
|
||||
git add docs/superpowers/specs/baseline && git commit -m "chore(cordis): 记录改造前 schema 与路由基线"
|
||||
```
|
||||
|
||||
## Task 2: Go 树迁入 `backend/` 并改 module 名(P1)
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/**`(全部 Go 文件)、`Makefile`、`docker/*`、`.github/workflows/*`
|
||||
|
||||
- [ ] **Step 1: 移动文件(保留 git 历史)**
|
||||
|
||||
```bash
|
||||
mkdir -p backend
|
||||
git mv cmd internal pkg main.go go.mod go.sum backend/
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 改 module 名并重写全部 import 路径**
|
||||
|
||||
```bash
|
||||
perl -pi -e 's{^module github\.com/Rain-kl/Wavelet$}{module OpenFlare}' backend/go.mod
|
||||
grep -rl 'github.com/Rain-kl/Wavelet' --include='*.go' backend | xargs perl -pi -e 's{\bgithub\.com/Rain-kl/Wavelet\b}{OpenFlare}g'
|
||||
grep -rl 'github.com/Rain-kl/Wavelet' --include='*.yml' --include='Dockerfile*' Makefile .github docker | xargs perl -pi -e 's{github\.com/Rain-kl/Wavelet}{OpenFlare}g'
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Makefile 全部 Go 目标切到 `backend/`(对齐 Wavelet 惯例)**
|
||||
|
||||
`MODULE := $(shell cd backend && go list -m)`;每个含 `go ` 命令的目标前缀 `cd backend &&`;`swagger` 输出目录仍为仓库根 `docs/`(`swag init -g backend/main.go -o docs --dir backend`),确保 `frontend` 消费路径不变。
|
||||
|
||||
- [ ] **Step 4: 修正内嵌与 ldflags 路径**
|
||||
|
||||
`build-embedded` 中前端导出物拷贝目标改为 `backend/internal/router/root/dist`;`.github/workflows/build-release.yml` 三处 `-X 'OpenFlare/plugins/{agent,relay,flared}/config.Version=...'` 在 Task 12 前暂以 `OpenFlare/internal/apps/...` 为准(P5 再随插件落位改一次),并全部加 `working-directory: backend`。
|
||||
|
||||
- [ ] **Step 5: 验证编译与测试未回归**
|
||||
|
||||
```bash
|
||||
cd backend && go build ./... && go test ./... 2>&1 | tail -5
|
||||
```
|
||||
Expected: build 无输出;test 与 `docs/superpowers/specs/baseline/go-test.txt` 同结果(exit 0)。
|
||||
|
||||
- [ ] **Step 6: 验证 A 路 schema 仍一致(移动未改变行为)**
|
||||
|
||||
重跑 Task 1 Step 2(输出改 `schema-A2.sql`、`versions-A2.txt`)并 `diff -u` 两个 schema 文件。
|
||||
Expected: diff 为空。
|
||||
|
||||
- [ ] **Step 7: 提交**
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "refactor(layout): Go 代码迁入 backend/ 并将模块名简化为 OpenFlare"
|
||||
```
|
||||
|
||||
## Task 3: Vendoring 上游为第二 module(P2)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/Wavelet/**`、`backend/Wavelet/go.mod`、`backend/go.work`、`scripts/sync-upstream.sh`
|
||||
|
||||
- [ ] **Step 1: 拷入上游内核与插件(排除上游装配根与运行期产物)**
|
||||
|
||||
```bash
|
||||
cd /Users/ryan/Code/Go/OpenFlare-cordis/backend
|
||||
mkdir -p Wavelet
|
||||
rsync -a --delete --exclude data --exclude uploads --exclude docs --exclude cmd --exclude main.go --exclude downstream \
|
||||
/Users/ryan/Code/Go/Wavelet/backend/ Wavelet/
|
||||
```
|
||||
Expected: `Wavelet/core`、`Wavelet/plugins/{drivers,infra,domain}`、`Wavelet/pkg`、`Wavelet/scripts`、`Wavelet/go.mod` 存在。
|
||||
|
||||
- [ ] **Step 2: 建立双 module 关联**
|
||||
|
||||
```bash
|
||||
printf 'go 1.25.7\n\nuse (\n\t.\n\t./Wavelet\n)\n' > go.work
|
||||
perl -pi -e 's{^go \d.*$}{go 1.25.7\n\nrequire Wavelet v0.0.0\n\nreplace Wavelet => ./Wavelet}' go.mod
|
||||
go work sync && go build ./... && cd Wavelet && go build ./... && cd ..
|
||||
```
|
||||
Expected: 两次 `go build ./...` 均无输出。若 `replace` 插入位置与 go.mod 现有语句冲突,手工将 `require Wavelet v0.0.0` / `replace Wavelet => ./Wavelet` 置于 `go` 指令之后。
|
||||
|
||||
- [ ] **Step 3: 写同步脚本(`share/` 永不覆盖)**
|
||||
|
||||
```bash
|
||||
cat > ../scripts/sync-upstream.sh <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
# 从 Wavelet 上游同步内核与插件;share/ 由 OpenFlare 拥有,显式排除。
|
||||
set -euo pipefail
|
||||
SRC="${1:-/Users/ryan/Code/Go/Wavelet/backend}"
|
||||
DST="$(cd "$(dirname "$0")/../backend/Wavelet" && pwd)"
|
||||
rsync -a --delete \
|
||||
--exclude 'data' --exclude 'uploads' --exclude 'docs' --exclude 'cmd' \
|
||||
--exclude 'main.go' --exclude 'downstream' --exclude 'share' \
|
||||
"$SRC/" "$DST/"
|
||||
echo "synced upstream -> $DST (share/ preserved)"
|
||||
SH
|
||||
chmod +x ../scripts/sync-upstream.sh
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 验证 `go.mod` 中上游依赖不丢失**
|
||||
|
||||
`go build ./...` 若报 `missing go.sum entry`,执行 `go mod tidy && cd Wavelet && go mod tidy && cd .. && go build ./...`。
|
||||
Expected: 构建通过。
|
||||
|
||||
- [ ] **Step 5: 提交**
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "feat(cordis): 以第二 module 形态 vendoring Wavelet 内核与平台插件"
|
||||
```
|
||||
|
||||
## Task 4: `share` 共享层(P2,G3)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/Wavelet/share/{protocol,wsclient,geoip,edge}/`、`backend/Wavelet/share/README.md`
|
||||
|
||||
- [ ] **Step 1: 建立所有权声明**
|
||||
|
||||
```bash
|
||||
mkdir -p Wavelet/share
|
||||
cat > Wavelet/share/README.md <<'MD'
|
||||
# share — 跨插件共享资源层
|
||||
|
||||
本目录由 **OpenFlare 拥有**,不属于 Wavelet 上游同步范围(`scripts/sync-upstream.sh` 显式排除)。
|
||||
|
||||
用途:被 `server` 与 `agent`/`relay`/`flared` 中两个及以上插件共同消费、且无法放入
|
||||
`Wavelet/pkg/`(禁止 import 业务代码)或插件内部(禁止插件互相 import)的资源。
|
||||
MD
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 迁移四个真正跨插件的资源包**
|
||||
|
||||
```bash
|
||||
mkdir -p Wavelet/share/{protocol,wsclient,geoip,edge}
|
||||
git mv pkg/protocol Wavelet/share/protocol
|
||||
git mv pkg/wsclient Wavelet/share/wsclient
|
||||
git mv pkg/geoip Wavelet/share/geoip
|
||||
git mv internal/apps/edge/logging Wavelet/share/edge/logging
|
||||
grep -rl 'OpenFlare/pkg/protocol\|OpenFlare/pkg/wsclient\|OpenFlare/pkg/geoip\|OpenFlare/internal/apps/edge/logging' --include='*.go' . \
|
||||
| xargs perl -pi -e 's{OpenFlare/pkg/(protocol|wsclient|geoip)}{Wavelet/share/$1}g; s{OpenFlare/internal/apps/edge/logging}{Wavelet/share/edge/logging}g'
|
||||
go build ./...
|
||||
```
|
||||
Expected: 构建通过。
|
||||
|
||||
- [ ] **Step 3: 消除 `pkg` 与上游 `Wavelet/pkg` 的重复**
|
||||
|
||||
对每个 OpenFlare 保留包,先比对符号集,再决定归属:
|
||||
|
||||
```bash
|
||||
for p in util logger trace cache mail response idgen ginutil httppool buildinfo testhelper; do
|
||||
echo "=== $p: openflare-only symbols ==="
|
||||
comm -23 <(grep -rhoE '^func [A-Z][A-Za-z0-9_]*' OpenFlare/pkg/$p/*.go 2>/dev/null | awk '{print $2}' | sort -u) \
|
||||
<(grep -rhoE '^func [A-Z][A-Za-z0-9_]*' Wavelet/pkg/$p/*.go 2>/dev/null | awk '{print $2}' | sort -u)
|
||||
done
|
||||
```
|
||||
- 上游同名包**已覆盖**的符号 → 删除 OpenFlare 副本,import 改指 `Wavelet/pkg/...`。
|
||||
- 仅 OpenFlare 需要的符号(如 `util.Go`、`util.EscapeLike`、`util.DummyCheckPassword`)→ 追加到 `Wavelet/pkg/<p>/openflare.go`(OpenFlare 拥有该 fork,P6 回流上游),再删除 OpenFlare 副本。
|
||||
- `pkg/cap`、`pkg/push`、`pkg/render`、`pkg/pagesarchive` → 与上游有交集者归 `Wavelet/pkg`,纯边缘共享者归 `Wavelet/share`。
|
||||
每迁一包后 `go build ./... && go test ./...`,全部完成后提交。
|
||||
|
||||
- [ ] **Step 4: 验证共享层被真实使用并提交**
|
||||
|
||||
```bash
|
||||
grep -rn 'Wavelet/share' --include='*.go' plugins internal cmd 2>/dev/null | head -5
|
||||
go build ./... && git add -A && git commit -m "feat(cordis): 新增 Wavelet/share 跨插件共享层并收敛重复 pkg 实现"
|
||||
```
|
||||
Expected: 至少 server 与一个 daemon 路径 import `Wavelet/share/...`。
|
||||
|
||||
## Task 5: 迁移引擎骨架(P3)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/internal/platform/migration/store.go`(自持 `sharedStore`)
|
||||
- Create: `backend/internal/platform/migration/engine.go`(实现 `core.MigrationEngine`)
|
||||
- Test: `backend/internal/platform/migration/store_test.go`
|
||||
|
||||
- [ ] **Step 1: 写失败测试——版本表 DDL 与上游逐字节一致**
|
||||
|
||||
```go
|
||||
func TestSharedStoreDDLMatchesUpstream(t *testing.T) {
|
||||
for _, dialect := range []string{"sqlite3", "postgres"} {
|
||||
s := &sharedStore{pluginID: "t", dialect: dialect}
|
||||
db, err := sql.Open("sqlite", ":memory:")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { _ = db.Close() })
|
||||
require.NoError(t, s.CreateVersionTable(context.Background(), db))
|
||||
var got string
|
||||
require.NoError(t, db.QueryRow("SELECT sql FROM sqlite_master WHERE name='w_schema_versions'").Scan(&got))
|
||||
require.Contains(t, got, "plugin_id")
|
||||
require.Contains(t, got, "version_id")
|
||||
require.Contains(t, got, "PRIMARY KEY (plugin_id, version_id)")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 运行验证失败**
|
||||
|
||||
Run: `cd backend && go test ./internal/platform/migration/ -run TestSharedStoreDDLMatchesUpstream -v`
|
||||
Expected: FAIL(`sharedStore` 未定义)。
|
||||
|
||||
- [ ] **Step 3: 从上游移植 `sharedStore`**
|
||||
|
||||
将 `Wavelet/backend/cmd/app.go:142-240` 的 `sharedStore`(`Tablename`/`CreateVersionTable`/`Insert`/`Delete`/`GetMigration`/`GetLatestVersion`/`ListMigrations`/`placeholder`)整段复制到 `store.go`,仅改包名与注释;DDL 字符串**一字不动**。
|
||||
Run: `go test ./internal/platform/migration/ -run TestSharedStoreDDLMatchesUpstream`
|
||||
Expected: PASS。
|
||||
|
||||
- [ ] **Step 4: 写失败测试——历史链按 plugin id 独立计数**
|
||||
|
||||
```go
|
||||
func TestLegacyPluginResumesFromStampedMax(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db, err := sql.Open("sqlite", filepath.Join(dir, "t.db"))
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = db.Close() }()
|
||||
s := &sharedStore{pluginID: LegacyPluginID, dialect: "sqlite3"}
|
||||
ctx := context.Background()
|
||||
require.NoError(t, s.CreateVersionTable(ctx, db))
|
||||
require.NoError(t, s.Insert(ctx, db, goosedb.InsertRequest{Version: 202608090003}))
|
||||
got, err := s.GetLatestVersion(ctx, db)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(202608090003), got)
|
||||
}
|
||||
```
|
||||
Run: `go test ./internal/platform/migration/ -run TestLegacyPluginResumesFromStampedMax`
|
||||
Expected: FAIL(`LegacyPluginID` 未定义)。
|
||||
|
||||
- [ ] **Step 5: 实现引擎**
|
||||
|
||||
```go
|
||||
// LegacyPluginID 是 OpenFlare 76 个历史 goose 文件的归属标识。
|
||||
const LegacyPluginID = "openflare/legacy"
|
||||
|
||||
const (
|
||||
zoneImportSQLVersion int64 = 202607120002
|
||||
zoneDropLegacySQLVersion int64 = 202607130001
|
||||
)
|
||||
```
|
||||
`engine.go` 以上游 `gooseEngine.Migrate`(`cmd/app.go:243-306`)为基线,差异仅两处:
|
||||
1. 遍历 `entries` 时,`entry.PluginID == LegacyPluginID` 走三段式:`provider.Up` 到 `zoneImportSQLVersion` → 若 `store.GetLatestVersion` 落在 `[zoneImportSQLVersion, zoneDropLegacySQLVersion)` 则在事务内执行 `zone.ImportLegacyTx` → 继续 `provider.Up` 至末尾;
|
||||
2. 引擎入口先调用 `resyncGooseVersionSequence(sqlDB)`(自 `migrator.go:158-183` 原样移植,改收 `*sql.DB` 与方言参数),并在全部 entry 完成后调用 `clearSystemConfigCache`。
|
||||
|
||||
Run: `go test ./internal/platform/migration/ -v`
|
||||
Expected: PASS。
|
||||
|
||||
- [ ] **Step 6: 提交**
|
||||
|
||||
```bash
|
||||
git add backend/internal/platform/migration && git commit -m "feat(migration): 自持 w_schema_versions 引擎并保留 zone 导入钩子"
|
||||
```
|
||||
|
||||
## Task 6: 历史链归属与注册(P3)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/internal/platform/migration/legacy/migrations/{postgres,sqlite}`(76×2 文件)
|
||||
- Modify: `backend/plugins/server/plugin.go`(`ctx.Migrations().Register(LegacyPluginID, legacyFS)`)
|
||||
|
||||
- [ ] **Step 1: 原样保真移动 SQL**
|
||||
|
||||
```bash
|
||||
mkdir -p internal/platform/migration/legacy/migrations
|
||||
git mv internal/infra/persistence/migrator/goose/postgres internal/platform/migration/legacy/migrations/postgres
|
||||
git mv internal/infra/persistence/migrator/goose/sqlite internal/platform/migration/legacy/migrations/sqlite
|
||||
git mv internal/infra/persistence/migrator/goose/clickhouse internal/platform/migration/legacy/migrations-clickhouse
|
||||
```
|
||||
Expected: `git diff --stat -M HEAD~1 -- '*/*.sql'` 显示纯 rename,零内容变更。
|
||||
|
||||
- [ ] **Step 2: embed 并注册**
|
||||
|
||||
```go
|
||||
//go:embed legacy/migrations/postgres/*.sql legacy/migrations/sqlite/*.sql
|
||||
var legacyFS embed.FS
|
||||
```
|
||||
ClickHouse 目录**不放**在 `migrations/` 下(避免被 `findMigrationFS` 的 `postgres|sqlite` 目录探测命中),继续由既有 `MigrateClickHouse` + `goose_clickhouse_version` 驱动,行为与改造前完全一致。
|
||||
|
||||
- [ ] **Step 3: 校验双方言文件集合一致**
|
||||
|
||||
```bash
|
||||
diff <(ls internal/platform/migration/legacy/migrations/postgres) \
|
||||
<(ls internal/platform/migration/legacy/migrations/sqlite)
|
||||
```
|
||||
Expected: 无差异(否则 `version_id` 会跨方言漂移)。
|
||||
|
||||
- [ ] **Step 4: 构建并提交**
|
||||
|
||||
`go build ./... && go test ./...` → PASS 后
|
||||
```bash
|
||||
git add -A && git commit -m "refactor(migration): 历史 goose 链原样归入 openflare/legacy 插件标识"
|
||||
```
|
||||
|
||||
## Task 7: 版本 stamp 桥接(P3)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/internal/platform/migration/bridge.go`
|
||||
- Create: `backend/internal/platform/migration/lock.go`
|
||||
- Test: `backend/internal/platform/migration/bridge_test.go`
|
||||
|
||||
- [ ] **Step 1: 写失败测试——老库逐行搬运且不重复执行**
|
||||
|
||||
```go
|
||||
func TestBridgeCopiesLegacyVersions(t *testing.T) {
|
||||
db, err := sql.Open("sqlite", filepath.Join(t.TempDir(), "old.db"))
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = db.Close() }()
|
||||
_, err = db.Exec(`CREATE TABLE goose_db_version (id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
version_id INTEGER NOT NULL, is_applied INTEGER NOT NULL, timestamp DATETIME)`)
|
||||
require.NoError(t, err)
|
||||
_, err = db.Exec(`INSERT INTO goose_db_version (version_id,is_applied) VALUES
|
||||
(202606090001,1),(202607120002,1),(202608090003,1),(202608100001,0)`)
|
||||
require.NoError(t, err)
|
||||
|
||||
n, err := Bridge(context.Background(), db, "sqlite3")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 3, n) // 仅 is_applied=1 行被搬运
|
||||
|
||||
again, err := Bridge(context.Background(), db, "sqlite3")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, again) // 幂等
|
||||
|
||||
var maxV int64
|
||||
require.NoError(t, db.QueryRow(
|
||||
"SELECT MAX(version_id) FROM w_schema_versions WHERE plugin_id='openflare/legacy'").Scan(&maxV))
|
||||
require.Equal(t, int64(202608090003), maxV)
|
||||
}
|
||||
```
|
||||
Run: `go test ./internal/platform/migration/ -run TestBridgeCopiesLegacyVersions`
|
||||
Expected: FAIL(`Bridge` 未定义)。
|
||||
|
||||
- [ ] **Step 2: 实现 `Bridge`**
|
||||
|
||||
要点:以 `SELECT version_id FROM goose_db_version WHERE is_applied=1` 为源(表不存在则直接返回 0,视为新库);`INSERT INTO w_schema_versions (plugin_id, version_id) VALUES (?, ?) ON CONFLICT (plugin_id, version_id) DO NOTHING` 逐行写入 `openflare/legacy`,并以 `RowsAffected` 汇总真实新增数;同时补写哨兵 `0`。占位符沿用 `sharedStore.placeholder`。**禁止**读写任何业务表。
|
||||
|
||||
- [ ] **Step 3: 写失败测试——迁移期互斥锁**
|
||||
|
||||
```go
|
||||
func TestMigrationLockIsExclusive(t *testing.T) {
|
||||
db, err := sql.Open("sqlite", filepath.Join(t.TempDir(), "l.db"))
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = db.Close() }()
|
||||
unlock, err := LockMigration(context.Background(), db, "sqlite3")
|
||||
require.NoError(t, err)
|
||||
_, err2 := db.Exec("INSERT INTO w_schema_versions VALUES ('x',1,'2026-01-01')")
|
||||
require.Error(t, err2) // 锁持有期间其他写者被阻塞/失败
|
||||
require.NoError(t, unlock())
|
||||
_, err3 := db.Exec("INSERT INTO w_schema_versions VALUES ('x',1,'2026-01-01')")
|
||||
require.NoError(t, err3)
|
||||
}
|
||||
```
|
||||
Expected: 先 FAIL(`LockMigration` 未定义),实现后 PASS。
|
||||
|
||||
- [ ] **Step 4: 实现 `LockMigration`**
|
||||
|
||||
PG:`SELECT pg_advisory_lock($1)` / `pg_advisory_unlock($1)`(固定 key 常量);SQLite:`PRAGMA busy_timeout` + 单写者事务(`BEGIN IMMEDIATE`)。返回 `func() error` 解锁,上游无 session locker,此处补齐多节点竞争保护。
|
||||
|
||||
- [ ] **Step 5: 接入装配根**
|
||||
|
||||
`Engine.Migrate` 开头:`unlock, err := LockMigration(...)`、`defer unlock()`;`Bridge(...)` 紧随 `CreateVersionTable` 之后、遍历 `entries` 之前。
|
||||
|
||||
- [ ] **Step 6: 全量测试并提交**
|
||||
|
||||
```bash
|
||||
go test ./internal/platform/migration/ -race && go test ./... && git add -A && git commit -m "feat(migration): 一次性 goose_db_version 到 w_schema_versions 桥接与迁移互斥锁"
|
||||
```
|
||||
|
||||
## Task 8: 上游插件初建与对齐(P3)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/Wavelet/plugins/domain/*/migrations/{postgres,sqlite}/00002_openflare_align.sql`(仅在确有缺口时)
|
||||
- Test: `backend/internal/platform/migration/parity_test.go`
|
||||
|
||||
- [ ] **Step 1: 列出对齐缺口(只读探测,不写库)**
|
||||
|
||||
```sql
|
||||
-- 对 A 路基线库执行,逐表比对上游模型期望列
|
||||
SELECT table_name, column_name FROM information_schema.columns
|
||||
WHERE table_name LIKE 'w\_%' ORDER BY table_name, column_name;
|
||||
```
|
||||
Expected: 产出「上游需要但现库缺失」的列/表清单;`w_message_channels`、`w_message_bindings`、`w_message_pairing_codes` 应出现在“缺失表”中(OpenFlare 无 bot 渠道表)。
|
||||
|
||||
- [ ] **Step 2: 缺口只以追加式迁移补齐**
|
||||
|
||||
```sql
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
ALTER TABLE w_users ADD COLUMN IF NOT EXISTS need_change_password BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
-- +goose StatementEnd
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
SELECT 1;
|
||||
-- +goose StatementEnd
|
||||
```
|
||||
`Down` 一律写成 no-op(禁止 DROP,避免回滚破坏现网数据)。sqlite 方言无 `ADD COLUMN IF NOT EXISTS`,需拆为独立文件并按上游惯例手写 sqlite 版本(不接受条件 SQL)。
|
||||
|
||||
- [ ] **Step 3: 一致性检查(B 路 vs A 路,复用 Task 1 的 dump harness)**
|
||||
|
||||
`legacydump_test.go` 通过环境变量 `OF_DUMP_SCHEMA=<输出路径>` 触发,把「当前 embed 内的全部 SQL」应用到 `t.TempDir()` 的临时 sqlite 库并导出表/索引定义。B 路 = 迁移文件已全部就位后的 dump:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
OF_DUMP_SCHEMA=/tmp/of-b.sql go test ./internal/platform/migration/legacy -run DumpFreshSchema
|
||||
diff -u docs/superpowers/specs/baseline/schema-A.sql /tmp/of-b.sql
|
||||
```
|
||||
Run: 上述 diff 命令
|
||||
Expected: 初期 FAIL 并逐表列出漂移(缺失的 `ADD COLUMN`、被 align 迁移改动的列);补齐 align 迁移后 diff 为空。
|
||||
|
||||
- [ ] **Step 4: 提交**
|
||||
|
||||
```bash
|
||||
git add -A && git commit -m "fix(migration): 追加式 align 迁移使全新安装与升级路径 schema 收敛"
|
||||
```
|
||||
|
||||
## Task 9: 三方一致性门禁工具(P3 验收)
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/cmd/migrate-audit/main.go`
|
||||
- Modify: `Makefile`(`migrate-audit` 目标)
|
||||
|
||||
- [ ] **Step 1: 实现只读 dump 与 diff CLI**
|
||||
|
||||
```go
|
||||
// dump: sqlite -> SELECT name,sql FROM sqlite_master WHERE type IN ('table','index') ORDER BY name;
|
||||
// postgres-> information_schema.columns + pg_indexes ORDER BY 1,2
|
||||
// mode: A=基线文件 B=全新生成 C=恢复 A 后再跑一次
|
||||
func main() {
|
||||
mode := flag.String("mode", "B", "A|B|C")
|
||||
dialect := flag.String("dialect", "sqlite3", "sqlite3|postgres")
|
||||
out := flag.String("out", "", "dump 输出路径")
|
||||
flag.Parse()
|
||||
// 1) 临时目录一律 os.MkdirTemp("", "of-audit-"),禁止写源码树
|
||||
// 2) B: 空库 -> bridge(no-op) -> Engine.Migrate(entries)
|
||||
// 3) C: 复制 A 的 db 文件 -> bridge(stamp) -> Engine.Migrate -> 断言 results 为空
|
||||
// 4) 输出规范化 dump 到 --out,交由 Makefile 的 diff 判定
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Makefile 目标与期望输出**
|
||||
|
||||
```make
|
||||
migrate-audit:
|
||||
cd backend && go run ./cmd/migrate-audit --mode B --out /tmp/of-b.sql
|
||||
cd backend && go run ./cmd/migrate-audit --mode C --base docs/superpowers/specs/baseline/schema-A.sql --out /tmp/of-c.sql
|
||||
diff -u docs/superpowers/specs/baseline/schema-A.sql /tmp/of-b.sql
|
||||
@sqlite3 /tmp/of-c.db "SELECT count(*) FROM w_schema_versions" >/dev/null
|
||||
@grep -q 'no-op' /tmp/of-c.log && echo "MIGRATION PARITY OK"
|
||||
```
|
||||
Expected: `make migrate-audit` 两个 diff 全空并打印 `MIGRATION PARITY OK`。
|
||||
|
||||
- [ ] **Step 3: 提交并在 changelog 记录**
|
||||
|
||||
`docs/changelog/index.md` 的 `[Unreleased]` 增补:迁移改为按插件版本表 `w_schema_versions` 管理,已部署库通过一次性桥接保持不重跑。
|
||||
|
||||
## Task 10: 架构门禁与 CI 收口(P3 收尾)
|
||||
|
||||
- [ ] **Step 1: 接入上游架构检查脚本**
|
||||
|
||||
`make arch-check` → `bash backend/Wavelet/scripts/check_cordis_architecture.sh`,并按 OpenFlare 布局增补 `backend/plugins` 与 `backend/Wavelet/share` 两条扫描根。
|
||||
Expected: 首次运行对 P3 范围(尚无 4 插件)通过。
|
||||
|
||||
- [ ] **Step 2: 四二进制构建回归 + code-check + format**
|
||||
|
||||
```bash
|
||||
make build-backend && make code-check && make format
|
||||
cd backend && go test -race ./... && go test -shuffle=on ./...
|
||||
```
|
||||
Expected: 全部 exit 0;`-shuffle=on` 无顺序依赖失败。
|
||||
|
||||
- [ ] **Step 3: 前端零改动断言与提交**
|
||||
|
||||
```bash
|
||||
git diff --name-only main...HEAD -- frontend/ | tee /tmp/fe.diff
|
||||
test ! -s /tmp/fe.diff && echo "FRONTEND UNTOUCHED"
|
||||
git add -A && git commit -m "chore(ci): cordis 布局路径门禁与迁移一致性检查接入"
|
||||
```
|
||||
Expected: 打印 `FRONTEND UNTOUCHED`。
|
||||
|
||||
---
|
||||
|
||||
## 完成定义(本计划)
|
||||
|
||||
- `backend/` 双 module 构建通过;`Wavelet/` 与上游差异仅 `share/` 与被显式记录的回流项。
|
||||
- `make migrate-audit` 三方 diff 为空;已部署库升级演练零 SQL 变更。
|
||||
- `go test -race ./...`、`-shuffle=on`、`make code-check` 全绿;`frontend/` 零改动。
|
||||
- 4 个插件与 daemon 内核化由 P4/P5 承接,本计划不含业务路由迁移。
|
||||
|
||||
---
|
||||
|
||||
## 附录 A:server 插件接入内核的可行路径(P4 前置调查结论)
|
||||
|
||||
调查上游 `core` 与 `plugins/drivers/driver_http` 后确认:`ctx.Router().Use` **不会**作用到
|
||||
gin engine(只把中间件摊平进 `RouteDefinition`),且以下 OpenFlare 现有 engine 级行为
|
||||
在内核中没有插件级贡献点:
|
||||
|
||||
| 需求 | 现状 | 出处 |
|
||||
| :-- | :-- | :-- |
|
||||
| `RedirectTrailingSlash = false` | 内核无处设置(全仓 0 命中) | `router/router.go:42-43` |
|
||||
| 自有 CORS / logger 分级 / session cookie 语义与 fatal 策略 | 硬编码在 `driver_http/engine.go` | `router.go:45-79` |
|
||||
| Next.js 静态导出 NoRoute(含动态页 shell 回退) | 被 `registerFrontend` 占用且缺该回退 | `router/root/frontend.go:104-111` |
|
||||
| `http.Server` 读写字节超时 / TLS | 仅 `ReadHeaderTimeout` | `router.go:83-87` |
|
||||
| 绑定成功后回调 `onStarted` | 无驱动级回调 | `router.go:89-95` |
|
||||
| 路由前缀取自 `app.api_prefix` | `ctx.Router()` 只收字面量 | `config.example.yaml:18` |
|
||||
|
||||
**结论:不改上游即可闭合——`driver_http.New(driver_http.WithEngine(自建 engine))` 已存在。**
|
||||
装配根(`backend/cmd`)负责构造 gin engine(保留 Recovery/CORS/session/otelgin/
|
||||
RedirectTrailingSlash/NoRoute 与超时),把 engine 交给 http 驱动;`server` 插件的
|
||||
`Apply` 只做 `ctx.Router().Group(...)` 声明式路由注册。其余两点:
|
||||
|
||||
- `onStarted` 改由 `ctx.Events().On("app:ready")` + `ctx.Driver(core.DriverTypeHTTP).Addr()` 提供;
|
||||
启动横幅在 `app.Run()` 前后打印,不再依赖回调。
|
||||
- 免鉴权路径:**保留 OpenFlare 自有 `oauth.LoginRequired()`(不查白名单)**,语义与今天一致。
|
||||
注意内核 `ctx.Router().RegisterWhitelist` 目前是**空转**(`driver_http.SetWhitelist`/
|
||||
`IsPathWhitelisted` 无非测试调用方),不得依赖它放行——否则会 401。
|
||||
|
||||
待办:以上三项(engine 中间件贡献点、NoRoute 贡献点、白名单真正生效)应回流上游 Wavelet,
|
||||
届时可去掉 `WithEngine` 例外。契约校验仍以 `docs/superpowers/specs/baseline/routes.txt`
|
||||
的 232 条 **操作**(方法×路径,`.Any()` 计 7)为准,与代码内 215 个注册调用点不矛盾。
|
||||
|
||||
## 附录 B:server 插件化已就位件与剩余步骤
|
||||
|
||||
**已落地并验证**
|
||||
- `router.BuildEngine()` 从 `Serve()` 中抽出(仅构造引擎与中间件,不监听),`Serve()` 复用它,行为不变。
|
||||
- `router/routes_dump_test.go`:以 `OF_DUMP_ROUTES=<path>` 导出现存注册路径的 **(方法 路径) 全集**,
|
||||
已固化基线 `docs/superpowers/specs/baseline/routes-engine.txt`:**256 条**(含 20 条尾部斜杠变体,
|
||||
全为 `GET /api/v1/d/*`)。这是 server 插件化唯一的路由对拍基准(232 是 swagger 操作数,
|
||||
二者差异来自斜杠变体与 `Any` 展开,不是矛盾)。
|
||||
- 内核补丁:`RouterExtension` 新增 `HandleRaw`(保留尾部斜杠)与 `BasePath`,作用域包装器同步实现并登记反注册;
|
||||
用例 `core/extpoints/router_raw_test.go` 覆盖;补丁登记在 `backend/OpenFlare/upstream-patches.md`,
|
||||
`sync-upstream.sh` 同步后会打印需确认的补丁文件。
|
||||
|
||||
**剩余步骤(按序,每步都要过对拍)**
|
||||
1. `openflare/apiutil.RegisterCollection` 改用 `route.Handle(method,"")` + `route.HandleRaw(method,"/")`
|
||||
(取代 `route.BasePath()` 的 gin 用法与 `[]gin.HandlerFunc`→`[]any` 转换)。
|
||||
2. `router/root`:`RegisterDefaultRootRoutes`/`RegisterCustomRootRoutes` 参数改 `core.RouterExtension`;
|
||||
`RegisterFrontend`(`NoRoute` + 静态资源,含 Next.js 动态 shell 回退)保留在引擎层,由 `BuildEngine()` 调用。
|
||||
3. 33 个 `*gin.RouterGroup` 注册函数改 `core.RouterExtension`(本轮已验证方法面只需
|
||||
GET/POST/PUT/DELETE/Group/Use,且无人接收返回值),随后删除 `registerRoutes()`。
|
||||
4. 新增 `OpenFlare/plugins/server/plugin.go`:`Name()="server"`,`Apply(ctx)` 内以
|
||||
`ctx.Router().Group(config.Config.App.APIPrefix)` 复刻 `registerRoutes` 的树
|
||||
(`/api` → `/v1` → v1/user/admin/openflare;根级 4 条走注册表绝对路径)。
|
||||
5. 装配根切换:`cmd/{api,all}.go` 改为 `core.NewApp(core.WithProfile(...))` +
|
||||
`app.Use(server.New())` + `app.Use(driver_http.New(driver_http.WithEngine(router.BuildEngine())))`,
|
||||
启动横幅改挂 `ctx.Events().On("app:ready")` 并用 `httpDrv.Addr()` 取实际监听地址;
|
||||
`otel_trace.Shutdown`/`bootstrap.Stop` 迁入 `ctx.OnDispose`,删除 `Serve()` 自带的信号循环。
|
||||
6. 对拍:新测试把插件注册表产出的 (方法 路径) 集合与 `routes-engine.txt` 逐条比对,
|
||||
差异必须为空;再实跑 server(sqlite)`curl` 健康检查、一个免鉴权端点与一个需鉴权端点(期望 401)。
|
||||
@@ -0,0 +1,98 @@
|
||||
# server 插件复用上游能力清理计划
|
||||
|
||||
**目标**:`backend/OpenFlare/plugins/server` 里大量能力上游 Wavelet 已提供,删除本地副本改为复用;
|
||||
按规约判定归属——通用能力回流上游,OpenFlare 业务留在插件内。
|
||||
|
||||
**事实基线**:`server` 实测 **68,117** 行非测试 Go 代码(早先记的 29.6k 只是 `openflare/` 一个域)。
|
||||
路由契约冻结基准:`docs/superpowers/specs/baseline/routes-engine.txt`(256 条 方法+路径)与
|
||||
`routes.txt`(232 条 swagger 操作),由 `plugin_parity_test.go` 逐条把守。
|
||||
|
||||
## 关键防线(先读,否则会做错)
|
||||
|
||||
直接挂上游插件**会破坏契约**,以下差异必须逐项处理,不允许“上游有就换”:
|
||||
|
||||
1. **验证码门禁丢失**:OF 在 `POST /api/v1/user/{login,register,send-email-code}` 上挂了
|
||||
`cap.VerifyMiddleware`(`router/v1/user.go:71-73`),上游 `domain/user` 没有该门禁
|
||||
(`user/plugin.go:126-129`)。直接替换=安全回归。
|
||||
2. **路径变化**:`/api/cap/{challenge,redeem}`(OF,挂在 `/api` 组)vs `/api/v1/cap/*`(上游,且多一个 `GET`);
|
||||
`GET /api/health` vs `/healthz` + `/api/healthz`;`/api/v1/upload` 的 `GET /my`、`PUT /:id`、
|
||||
`GET /download/:id`、`POST /download/batch` vs 上游 `GET ""`、`POST /batch-download`;
|
||||
OF 独有 `GET /api/v1/user/self`。
|
||||
3. **公共配置响应体不同**:`GET /api/v1/config/public` 路径相同但 JSON 字段不同,SPA 直接消费。
|
||||
4. 上游额外需要表 `w_message_channels` / `w_message_bindings` / `w_message_pairing_codes`(OF 库中不存在)。
|
||||
除此之外 13 张共享 `w_*` 表**列级零差异**;唯一缺口 `w_access_tokens.description/expires_at` 上游 Go 模型也未使用,非阻塞。
|
||||
|
||||
## 判定清单
|
||||
|
||||
| 包 | 行数 | 上游对应 | 判定 |
|
||||
| :-- | --: | :-- | :-- |
|
||||
| `shared/response` | 142 | `pkg/response` | 删(7/7 `Abort*` 逐字一致,仅风格差异) |
|
||||
| `pkg/logger` | 382 | `pkg/logger` | 删(`Config` 字段完全一致) |
|
||||
| `pkg/mail` | 266 | `pkg/mail` | 删 |
|
||||
| `pkg/httppool` | 106 | `pkg/httppool` | 删(逐字节相同) |
|
||||
| `pkg/trace` | 148 | `pkg/trace` | 删(差异仅默认 tracer 名,由 `app.app_name`/`otel.tracer_name` 决定) |
|
||||
| `pkg/cache/ram` | 305 | `pkg/cache/ram` | 删(OF 用裸 `go`,上游用 `util.Go`,换过去是修复) |
|
||||
| `infra/persistence/idgen` | 47 | `pkg/idgen` | 删(上游为超集) |
|
||||
| `infra/persistence/batchwriter` | 337 | `pkg/batchwriter` | 删 |
|
||||
| `listener` | 42 | `core/events.go Subscribe[T]` | 删,改事件订阅 |
|
||||
| `testhelper` | 479 | `pkg/testhelper` | 合并,仅留 `SetupLogStoresForTest` |
|
||||
| `pkg/cache/disk` | 412 | `pkg/cache/disk` | 先回流 OF 的 5 处类型断言 `ok` 守卫(通用健壮性修复),再删本地副本 |
|
||||
| `pkg/cap` | 511 | `plugins/domain/cap/pow` | **不能直接复用**(跨插件 import 被禁)。二选一:pow 提取到上游 `pkg/pow`,或留 `server` 内并放弃“复用” |
|
||||
| `infra/objectstore`、`infra/diskcache` | 1,058 | `plugins/infra/storage/*` | 改走 `contracts.StorageService`/上游 infra(P6) |
|
||||
| `infra/task`(worker/scheduler/handlers) | 1,125 | `plugins/drivers/driver_asynq_*` | 换内核驱动(P6) |
|
||||
| `infra/config`(全局 `Config` 单例) | 444 | `core/config.go` + `plugins/infra/config` | 改 `ctx.Config().Bind`(P6,18 处引用) |
|
||||
| `infra/persistence`(DB/Redis 初始化) | 639 | `plugins/infra/database` | 换 `contracts.DBService`(P6) |
|
||||
| `infra/persistence/migrator` | 298 | `w_schema_versions` + 每插件迁移 | 见 foundation 计划 P3(含历史 stamp 桥接) |
|
||||
| `repository/logstore` | 3,286 | `plugins/domain/risk_control/logstore` | 近似分叉:合并并保留 OF 的 `AccessLogStore`/`ObservabilityStore` 接口 |
|
||||
| `repository/analytics` | 2,848 | 同上(仅用户访问日志半边) | 合并半边;`node_*` 与 CH 维护上游没有,留 `server` |
|
||||
| `repository`、`model` | 8,527 | 各上游域插件内 | 拆分:`w_*` 部分随 P6 归上游,`of_*` 留 `server` |
|
||||
| `oauth`、`user`、`admin`、`upload`、`cap`、`config`、`health` | ~7,600 | `plugins/domain/{auth,user,admin,upload,cap,system}` | **受“关键防线”约束**,逐端点判定后合并,禁止整体替换 |
|
||||
| `admin/push` | 1,776 | `plugins/domain/message_gateway` | 合并并保留 OF 的 `RegisterBuiltInEvent`/`RegisterChannelDefinition`/`SyncEvents` 钩子 |
|
||||
| `admin/updater` | 832 | 上游仅 `GetUpdateStatus/ApplyUpdate` | OF 的 Prepare/Apply/Finish 三段式为业务能力,保留 |
|
||||
| `openflare/`(27 子包) | 29,678 | 无 | 保留(产品逻辑);`apiutil` 与 `integration/githubrelease` 若被多插件消费再移 `share` |
|
||||
| `router`、`router/root`、`router/v1` | 1,242 | `core/extpoints` + `driver_http` | 保留为接线层,直至上游具备引擎中间件与 NoRoute 贡献点 |
|
||||
|
||||
## 执行顺序
|
||||
|
||||
1. **T1 纯风格差异**(`shared/response`、`pkg/{logger,mail,httppool,trace,cache/ram}`、
|
||||
`infra/persistence/{idgen,batchwriter}`):改 import → 删本地副本 → 全量门禁。
|
||||
2. **T2 `listener` 改事件订阅**、`testhelper` 合并。
|
||||
3. **T3 `pkg/cache/disk` 断言守卫回流上游**,再删本地副本。
|
||||
4. **T4 基础设施换内核**(`infra/config` → `ctx.Config()`;`infra/persistence` → `contracts.DBService`;
|
||||
`infra/task` → asynq 驱动):与 P3/P4b 合并推进。
|
||||
5. **T5 平台域逐个合并**(oauth/user/admin/upload/cap/config/health/push):每个域先列差异
|
||||
(路由、门禁、响应体、表列),差异以 `server` 内薄封装或回流上游解决,逐域过 256 条对拍。
|
||||
6. **T6 `repository`/`model` 按表所有权拆分**:`w_*` 归上游,`of_*` 留 `server`。
|
||||
|
||||
每步完成判据:`go build ./...` + `go test ./...` 全绿 + `plugin_parity_test` 零差异 +
|
||||
`make swagger` 232 条零差异 + `golangci-lint` 0 issues + `frontend/` 零改动。
|
||||
|
||||
## 执行记录与阻塞点
|
||||
|
||||
### T1 已完成(提交 `0adbfc1a`)
|
||||
|
||||
删除并改用上游:`shared/response`→`pkg/response`、`pkg/{logger,mail,trace,httppool,cache/ram}`、
|
||||
`infra/persistence/batchwriter`→`pkg/batchwriter`。共 7 个本地包消失,`go test` 包数 144→138。
|
||||
|
||||
证据:256 条路由对拍零差异;232 条 swagger 操作零增减,且**把两个随包路径改名的定义
|
||||
(`…shared_response.Any`→`response.Any`、`…pkg_logger.LogEntry`→`logger.LogEntry`)归一化后,
|
||||
新旧 swagger.json 深度相等**——即接口形状完全未变。`$ref` 名由 Go 包路径派生,属生成物命名变化。
|
||||
|
||||
### 新发现的阻塞点(勿重复踩)
|
||||
|
||||
1. **`pkg/idgen` 暂不能换**:上游 `pkg/idgen` 要求先 `Init(nodeID)` 否则 panic
|
||||
(`idgen: Init must be called before generating IDs`),而 OpenFlare 副本是懒初始化。
|
||||
5 个 push/user 用例直接 panic。必须与 T4(`infra/config`、`infra/persistence` 改走
|
||||
`ctx.Config()`/`contracts.DBService`)一起做,在 bootstrap 阶段显式 `Init`。
|
||||
2. **`pkg/cap` 不能“复用上游”**:上游 pow 实现在 `plugins/domain/cap/pow` 里,
|
||||
跨插件 import 被架构门禁禁止。合规出路二选一:把 pow 提取为上游 `pkg/pow`(通用能力,
|
||||
按规约回流 Wavelet 后两边共用),或承认它是 server 的业务实现留在插件内。
|
||||
3. **`listener` 需先有内核上下文**:`core.Subscribe[T](bus, topic, fn)` 要 `*core.EventBus` 实例,
|
||||
而调用方(`oauth/handler_callback.go`、`user/routers.go`、`admin/push/custom_events/*`)都在
|
||||
内核之外、手上没有 `*core.Context`。现在改只会把全局变量从包级切片挪到包级总线。
|
||||
待 `server` 的 `Apply`/bootstrap 拿到 ctx 后随 T4 一起做。
|
||||
4. **`pkg/trace` 覆盖缺口(非本次引入)**:核实后上游与 OpenFlare 副本都是 4 个同名文件、
|
||||
都**没有**测试文件,因此删除本地副本没有降低覆盖率。要补测试应直接补在上游 `backend/pkg/trace/`。
|
||||
5. **`pkg/cache/disk` 已完成**:5 处类型断言的 `ok` 守卫按规约回流上游
|
||||
(Wavelet `f3d85d5`,附 `cache_corruption_test.go`:去掉守卫即 panic、加上守卫 4 用例全过),
|
||||
上游的 `Default()` 全局实例保留(下游不使用它,不构成行为差异);本地副本已删除。
|
||||
@@ -0,0 +1,236 @@
|
||||
# OpenFlare Cordis 架构改造设计
|
||||
|
||||
- **文档类型**: 架构设计 / 改造规范(Spec)
|
||||
- **日期**: 2026-08-29
|
||||
- **范围**: OpenFlare 后端全量迁移到 Wavelet Cordis 插件化架构
|
||||
- **上游参照**: `/Users/ryan/Code/Go/Wavelet`(`backend/`,module `Wavelet`)
|
||||
- **改造基线**: OpenFlare `main` @ `9f79fb99`(v3.5.4),工作分支 `cordis`
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与不可协商约束
|
||||
|
||||
| # | 约束 | 验证方式 |
|
||||
| :-- | :-- | :-- |
|
||||
| G1 | OpenFlare 改造为 Cordis 架构,上游包名为 `Wavelet` | `backend/Wavelet/` 与上游逐字节一致(`share/` 除外);`go build ./...` 通过 |
|
||||
| G2 | OpenFlare 功能收敛为 **4 个插件**:`server`、`agent`、`relay`、`flared` | `backend/plugins/` 下仅此 4 个目录,均实现 `core.Plugin` |
|
||||
| G3 | 在上游树内创建 `share` 包承载跨插件共享资源 | `backend/Wavelet/share/` 存在且被 4 个插件至少两处 import |
|
||||
| G4 | **不修改前端** | `git diff --name-only main...cordis -- frontend/` 为空 |
|
||||
| G5 | 数据库迁移谨慎:已部署库不重跑历史、不丢数据、零破坏性变更 | 三方 schema 一致性门禁(§5.4) |
|
||||
| G6 | 既有 HTTP 契约不变(前端与 API 消费者零感知) | 路由清单 diff + swagger 对拍 |
|
||||
| G7 | 边缘三进制的 CLI 形态不变(`-config` 默认路径、退出码、日志格式) | 启动冒烟 + 现有测试保持绿 |
|
||||
|
||||
## 1.5 布局修正(v1.1,取代 §3 与 §4 中的路径描述)
|
||||
|
||||
初版设计提出的「`backend/` + `backend/Wavelet/` 双 module、OpenFlare 插件放 `backend/plugins/`」已被否定。
|
||||
**采用与 Wavelet 完全同构的单 module 布局**(已落地,提交 `9bf0b2de`):
|
||||
|
||||
```
|
||||
backend/ module Wavelet(与上游同名,上游 import 路径逐字一致)
|
||||
├── main.go cmd/ 控制面装配根(server)
|
||||
├── core/ 【上游】微内核 + contracts + extpoints
|
||||
├── pkg/ 【上游】通用库(禁止 import plugins)
|
||||
├── plugins/{drivers,infra,domain}/ 【上游】平台插件
|
||||
├── docs/ swaggo 产物(json/yaml 复制回根 docs/ 供站点消费)
|
||||
├── share/ 【新增 G3】跨插件共享资源层
|
||||
└── OpenFlare/ 【下游】占据上游 backend/downstream 的位置
|
||||
├── cmd/{agent,relay,flared}/ 三个 daemon 入口(package main)
|
||||
└── plugins/{server,agent,relay,flared}/ 【G2】4 个业务插件
|
||||
```
|
||||
|
||||
约束更新:
|
||||
- 上游同步 = 覆盖 `backend/{core,pkg,plugins}`,零 import 改写;`OpenFlare/` 与 `share/` 永不被覆盖。
|
||||
- OpenFlare 现有代码(apps/repository/model/infra/router/shared/…)暂整体驻留 `backend/OpenFlare/**`,由 P4/P5 逐个搬入 `backend/OpenFlare/plugins/<插件>`;搬完后 `backend/OpenFlare` 下不再保留平铺的遗留层。
|
||||
- 装配根在 `backend/cmd`(模块内非 internal 路径),因此下游树不得使用 `internal/`(已在本次落地时展平)。
|
||||
- 平台表由上游 `plugins/domain/*` 拥有,业务表 `of_*` 由 `OpenFlare/plugins/server` 拥有;§5 迁移方案不变,仅历史链落点改为 `backend/OpenFlare/plugins/server/migrations/{postgres,sqlite}`。
|
||||
|
||||
落地验证(实测,非推断):`go build ./...` 通过;`go test ./...` exit 0 且 142 个包 ok(含上游插件测试);`make swagger` exit 0 且 232 条 API 操作与改造前基线逐条一致;`make build-all` 产出 4 个二进制;`git status --short -- frontend/` 为空。
|
||||
上游 `plugins`、`core` 暂从 swaggo 扫描中排除(其包名 `model`、`disk` 与下游遗留注解的裸名引用冲突),P4 挂载上游路由时随 `OpenFlare/model` 展平一并解除。
|
||||
|
||||
## 2. 已核实的事实基线(设计前提,非推测)
|
||||
|
||||
1. **OpenFlare 是 Cordis 之前的 Wavelet 分叉**:`go.mod` module 路径即 `github.com/Rain-kl/Wavelet`;`internal/apps/` 同时含继承自 Wavelet 的平台应用(admin/oauth/user/upload/cap/config/health)与 OpenFlare 自有业务(openflare 29.6k 行、agent 7.4k、edge 1.5k、relay 1.0k、flared 0.9k)。Go 代码总量 151,473 行,209 个测试文件。
|
||||
2. **表前缀双轨**:平台表沿用 `w_*`(OpenFlare 的 76 迁移已在其上分叉),业务表 `of_*`(28 张)。上游 `w_*` 表宇宙 17 张,且上游含 `w_message_channels`/`w_message_bindings`/`w_message_pairing_codes`(OpenFlare 无)→ **双向分叉**。
|
||||
3. **内核支持非 HTTP 形态**(`Wavelet/backend/core`):
|
||||
- `normalizeProfile`(app.go:684)对未知 profile 字符串原样透传;`matchesProfile`(app.go:668)`default` 分支做字符串相等比较 → `core.Profile("agent")` 仅启动 `DriverType("agent")` 的驱动。
|
||||
- `App.Run`(app.go:600-613)**始终**阻塞在 `signal.NotifyContext`;即使零驱动匹配也会阻塞 → 插件自身禁止阻塞。
|
||||
- `Profile` 枚举仅 api/worker/schedule/all;驱动仅在 `Start` 中按 profile 过滤(app.go:487-494),插件 `Apply`、IoC、事件、配置在各 profile 下行为一致。
|
||||
- 长生命周期服务标准写法(`plugins/drivers/driver_inproc_worker/plugin.go:118-151`):`Apply` 内保存 coreCtx → `core.Provide` → `ctx.OnDispose(...)` → `ctx.RegisterDriver(p)`;`Stop` 逆序(LIFO)调用并受 `shutdownTimeout` 约束。
|
||||
- `RunMigrations()`(app.go:414-433)在无 `MigrationEngine` 且容器无该服务时返回 nil → 无 DB 的 daemon 合法。
|
||||
- DI 真实 API 为包级函数 `core.Provide[T](ctx, svc)` / `core.Inject[T](ctx)` / `core.Using[T](ctx, fn)` / `core.When[T](ctx, fn)`;`Context` **没有** `Provide/DB/Cache/Logger/Storage/DistLock` 方法( cookbook 中的 `ctx.DB()` 写法为文档性简化,且内核无 DistLock 能力)。
|
||||
4. **迁移子系统现状**:
|
||||
- `w_schema_versions(plugin_id, version_id, applied_at)` 的 DDL 来自 Go(`Wavelet/backend/cmd/app.go:142-153`),**没有** SQL 文件创建它;插入使用 `ON CONFLICT DO NOTHING`。
|
||||
- `sharedStore` 未实现 `TableExists` → goose 回退探测失败后会给每个 plugin_id 插入哨兵 `version_id = 0` 行(幂等、良性,但桥接必须知道)。
|
||||
- 版本号解析:goose `NumericComponent` 取文件名首个 `_` 之前部分按十进制 int64 解析,须 ≥1;`2026MMDDNNNN` 与 `00001` 均合法;同一 plugin_id 内重复版本号致命。
|
||||
- `findMigrationFS`(app.go:309-358)按目录名 `postgres`/`sqlite` 探测,**注册时传入的 `Dir` 参数被忽略** → 目录基名必须是 `postgres`/`sqlite`。
|
||||
- 方言选择:`ctx.Config().Bool("database.enabled", false)` → postgres,否则 sqlite3;无 `WithSessionLocker` → **多节点并发迁移无保护**(上游未解)。
|
||||
- 上游 `risk_control/logstore/migrations-clickhouse/00001_initial.sql` 是**未被 embed、无处应用**的孤儿文件。
|
||||
- **上游不存在任何历史库基线/stamp 能力**(无 migrate 命令、无 `--baseline`),桥接为 OpenFlare 自有产物。
|
||||
5. **`backend/` 化的路径耦合点**(Phase 1 必须一并处理):
|
||||
- `internal/router/root/frontend.go:18` `//go:embed all:dist`(前端导出物被 Go 包内嵌);
|
||||
- `.github/workflows/build-release.yml` 三处 `-X 'github.com/Rain-kl/Wavelet/internal/apps/{agent,relay,flared}/config.Version'` 与 `./cmd/*/main.go` 构建路径;
|
||||
- `Makefile` 的 `build-embedded` / `build-backend` / `cross-build` / `swagger` / `code-check` / `dev-*`;
|
||||
- `docker/` 四个镜像的构建上下文与 COPY 路径;`config.example.yaml`、`config/clickhouse`、`.env.example` 的读取路径。
|
||||
|
||||
## 3. 目标仓库布局
|
||||
|
||||
```
|
||||
OpenFlare/
|
||||
├── backend/ # Go 代码根,module OpenFlare
|
||||
│ ├── go.mod # require Wavelet + replace Wavelet => ./Wavelet
|
||||
│ ├── go.work # 本地一体构建(use . ./Wavelet)
|
||||
│ ├── Wavelet/ # 【上游】从 Wavelet/backend 原样拷入
|
||||
│ │ ├── go.mod # module Wavelet
|
||||
│ │ ├── core/ # 微内核(零业务)
|
||||
│ │ ├── core/contracts/ # 跨插件契约(纯 Interface + DTO)
|
||||
│ │ ├── core/extpoints/ # 扩展点(Router/Task/Schedule/Migration/Setting/Config/Driver)
|
||||
│ │ ├── plugins/drivers/ # driver_http / asynq_* / inproc_*
|
||||
│ │ ├── plugins/infra/ # database / cache / cache_memory / config / logger / storage
|
||||
│ │ ├── plugins/domain/ # admin / user / auth / message_gateway / risk_control / upload / cap / system
|
||||
│ │ ├── pkg/ # 上游通用库(禁止 import plugins)
|
||||
│ │ ├── scripts/check_cordis_architecture.sh
|
||||
│ │ └── share/ # 【G3 新增】跨插件共享资源层,OpenFlare 所有
|
||||
│ ├── plugins/ # 【G2】OpenFlare 的 4 个插件
|
||||
│ │ ├── server/ # 控制面:of_* 业务域 + 边缘接入 API
|
||||
│ │ ├── agent/ # 边缘 nginx/WAF 代理守护
|
||||
│ │ ├── relay/ # frps 中继守护
|
||||
│ │ └── flared/ # frpc 隧道客户端守护
|
||||
│ ├── cmd/ # 装配根:root/server/agent/relay/flared/bridge
|
||||
│ ├── main.go # server 入口(swagger 注释保留原位)
|
||||
│ └── internal/ # 仅保留非业务基础设施(迁移桥接、构建信息)
|
||||
├── frontend/ # 【不修改】
|
||||
├── docs/ # VitePress + swagger 产物路径不变
|
||||
├── docker/ Makefile .github/ # 路径改写至 backend/
|
||||
└── config.example.yaml # 位置不变(新增 plugins.* 节点)
|
||||
```
|
||||
|
||||
### 3.1 双 module 而非单 module 的理由
|
||||
|
||||
上游树内 import 保持 `Wavelet/core`、`Wavelet/plugins/...` 逐字节等于上游仓库,同步 = `rsync --delete` + 一条 `replace` 指令,无需任何 import 改写。单 module 方案(`OpenFlare/Wavelet/core`)每次同步都要全量重写 import,同步成本随上游演进线性上升,且必然产生漂移。以 Go module 依赖引用上游(不拷代码)被否,因为 OpenFlare 已分叉平台代码,需先在 `backend/Wavelet/` 内落地再回流。
|
||||
|
||||
### 3.2 `share` 的落点与所有权
|
||||
|
||||
`share` 建在上游 module 内(`Wavelet/share/...`),因为:`Wavelet/pkg/` 禁止 import 业务代码,而 `protocol`、`wsclient`、edge 日志/状态机、`geoip` 等资源**同时被 server 与三个 daemon 消费**;Cordis 规则禁止插件互相 import,故必须存在一个双方都可见的中立层。
|
||||
|
||||
**所有权声明**(写入 `backend/Wavelet/share/README.md`):`share/` 由 OpenFlare 拥有,同步脚本 `scripts/sync-upstream.sh` 显式排除该目录;上游同步仅覆盖 `core/`、`plugins/`、`pkg/`、`scripts/`。此决定的代价是 `share/` 不能从上游获得更新——这是刻意选择,且是唯一需要否定的子决策(备选:落点 `backend/share/`,import `OpenFlare/share/...`,其余设计不变)。
|
||||
|
||||
### 3.3 模块与命名
|
||||
|
||||
- OpenFlare module 路径:`OpenFlare`(对齐上游 `module Wavelet` 的简化命名惯例)。
|
||||
- 插件 ID 与目录名同名:`server` / `agent` / `relay` / `flared`。
|
||||
- 表所有权:`of_*` 全部归 `server`;`w_*` 归各上游平台插件;`w_schema_versions` 归装配根。
|
||||
- 插件内部分层:一律采用模式 2(`plugin.go` + `handler/ service/ repository/ model/ errs/ migrations/`),子包内文件按业务实体命名,禁止 `handlers_*` 平铺。
|
||||
|
||||
## 4. 插件设计
|
||||
|
||||
### 4.1 `server`
|
||||
|
||||
装配 profile:`api` / `worker` / `schedule` / `all`(与上游语义一致)。挂载上游 infra(database、cache 或 cache_memory、logger、storage)、8 个上游 domain 插件、`driver_http` + asynq/inproc 驱动对,再挂 `server` 插件。
|
||||
|
||||
`server` 插件职责:
|
||||
- 路由:`ctx.Router().Group("/api/v1/...")` 自包含注册 OpenFlare 业务路由;免鉴权路径(边缘节点接入、健康探针、OAuth 回调)由本插件 `RegisterWhitelist` 主动声明,杜绝误拦截。
|
||||
- 任务/调度:`ctx.Task().Register` / `ctx.Schedule().RegisterCron`(迁移现有 `internal/platform/bootstrap` 的显式装配)。
|
||||
- 设置:`ctx.Settings().Register`(迁移现有动态设置声明)。
|
||||
- 契约:向平台暴露 `contracts.*` 之外不新增跨插件事务;OpenFlare 自有能力经 `server` 单入口暴露。
|
||||
- 迁移:`of_*` 全量 + 历史链(§5)。
|
||||
|
||||
内部按子域分包:`zone / cloudflare / pages / waf / node / proxy_route / dns / acme / tls / edge_control / config_version / health`,每子域内部遵循 handler→service→repository→model 单向依赖。
|
||||
|
||||
### 4.2 `agent` / `relay` / `flared`
|
||||
|
||||
同一模式,各自实现 `core.Plugin` + `core.Driver`:
|
||||
|
||||
```go
|
||||
func (p *Plugin) Name() string { return "agent" }
|
||||
func (p *Plugin) Type() core.DriverType { return core.DriverType("agent") }
|
||||
func (p *Plugin) Apply(ctx *core.Context) error {
|
||||
if err := ctx.Config().Bind("agent", &p.cfg); err != nil { return err } // JSON 配置经 ConfigSource 适配
|
||||
core.Provide[contracts.LoggerService](ctx, lg)
|
||||
ctx.OnDispose(func() error { return p.stop() })
|
||||
return ctx.RegisterDriver(p)
|
||||
}
|
||||
func (p *Plugin) Start(ctx context.Context) error { /* util.Go 启动 heartbeat/sync/updater,select ctx.Done() */ }
|
||||
func (p *Plugin) Stop(ctx context.Context) error { /* 收敛 frpc/frps 子进程与 ws 连接 */ }
|
||||
```
|
||||
|
||||
- 入口 `cmd/agent/main.go` → `core.NewApp(core.WithProfile(core.Profile("agent")), core.WithConfigSource(jsonSource))` + `app.Use(agent.New())`;**不挂** http/database/cache/asynq 驱动。
|
||||
- JSON 配置文件(`agent.json`/`relay.json`/`flared.json`)通过实现 `extpoints.ConfigSource`(`Lookup/LookupEnv/Describe`)接入,优先级:env 覆盖 → 文件 → default,与上游 `plugins/infra/config` 的解析优先级一致;`-config` 旗标与默认路径不变。
|
||||
- 三者共享的 protocol / wsclient / edge logging / state 迁入 `Wavelet/share/`;`internal/apps/edge/` 消失(其内容分别归入 `share` 与 daemon 插件)。
|
||||
- 裸 `go func()` 一律经 `util.Go`(架构门禁禁止裸 go)。
|
||||
|
||||
## 5. 数据库迁移方案(G5)
|
||||
|
||||
### 5.1 历史链保真
|
||||
|
||||
`goose/postgres`(76)与 `goose/sqlite`(76)文件**逐字节原样**迁入 `backend/plugins/server/migrations/{postgres,sqlite}/`,文件名、序号、内容不改;ClickHouse 链(14,含 `goose_clickhouse_version` 版本表)与其现有 `MigrateClickHouse` 路径**完全保持不动**,不并入 `w_schema_versions`(语义不同、且上游 CH 文件为孤儿,不引入其语义)。
|
||||
|
||||
### 5.2 插件初建与对齐
|
||||
|
||||
- 上游平台插件的 `00001_initial.sql` 保留:全部 `CREATE TABLE IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS` / seed `ON CONFLICT DO NOTHING` → 在 OpenFlare 老库上只补建上游新增表(如 `w_message_channels`),已存在表自动跳过。
|
||||
- 若上游模型需要 OpenFlare 现库缺失的列,**只允许**在对应插件的 `migrations/{postgres,sqlite}/00002_openflare_align.sql` 追加(`ADD COLUMN` / `CREATE INDEX IF NOT EXISTS`)。全链路禁止 `DROP TABLE` / `DROP COLUMN` / `TRUNCATE`。
|
||||
- 双方言目录必须文件名与版本号一一对应,否则 PG 与 sqlite 的 `version_id` 漂移。
|
||||
|
||||
### 5.3 一次性桥接(`cmd/bridge`,启动前置)
|
||||
|
||||
1. 以与上游 `cmd/app.go:142-153` **逐字节一致**的 DDL 建 `w_schema_versions`(保证上游 `CreateVersionTable` 的 `IF NOT EXISTS` 成为 no-op)。
|
||||
2. 取 PG advisory lock(`pg_advisory_lock(key)`)/ sqlite 依赖单写者,补齐上游缺失的并发保护。
|
||||
3. 若存在老库版本表(`goose_db_version` / OpenFlare 现名)且 `w_schema_versions` 无 `openflare/legacy` 记录:写入 `(openflare/legacy, 0)` 哨兵与 `(openflare/legacy, MAX(老库已应用版本))`,全部 `ON CONFLICT DO NOTHING`。
|
||||
4. 桥接幂等:重复执行零变更;老库此后**永不重跑**历史链,新库正常跑完整链后收敛到同一 schema。
|
||||
5. 桥接仅由 server 装配根在 `app.RunMigrations()` 之前调用一次;agent/relay/flared 不涉及(无 DB)。
|
||||
|
||||
### 5.4 三方一致性门禁(不可跳过)
|
||||
|
||||
| 路径 | 构造方式 | 断言 |
|
||||
| :-- | :-- | :-- |
|
||||
| A(基线) | 改造前 `main` 二进制在全新 sqlite/PG 上跑完 76 链 | dump `information_schema` + seed 行数 |
|
||||
| B(新架构全新安装) | 桥接 + 历史链 + 各插件 initial/align | 与 A **逐项 diff 为空** |
|
||||
| C(升级路径) | 恢复 A 的库文件后再启动一次新架构 | schema diff 为空,且本次启动**零 SQL 变更**(迁移结果集为空) |
|
||||
|
||||
工具:`backend/cmd/migrate-audit`(导 dump 与 diff,只读、不写源码树,临时目录用 `t.TempDir()`)。任一路径失败即视为改造未完成,禁止合并。
|
||||
|
||||
## 6. 前端与 API 契约(G4/G6)
|
||||
|
||||
`frontend/` 零改动(`git diff --name-only main...cordis -- frontend/` 必须为空)。内嵌物路径由 `Makefile` 的 `build-embedded` 负责:前端导出物仍拷到 `backend/internal/router/root/dist`(或迁移后对应包目录),`//go:embed all:dist` 随包位置同步。
|
||||
|
||||
服务端 HTTP 契约保持:路径、`{error_msg,data}` 信封、分页 `{total,results}`、成功 200 / 失败 `Abort*` 语义、swagger 产物路径(`docs/swagger.json|yaml`)。验收:改造前后各跑一次 `swag init`,对拍 `paths` 键集合必须一致(新增路径允许,删改不允许)。
|
||||
|
||||
## 7. 工具链、CI 与文档
|
||||
|
||||
- `Makefile`:Go 目标切到 `backend/`;新增 `sync-upstream`、`migrate-audit`、`arch-check`。
|
||||
- `.github/workflows`:4 个 build-image 工作流的构建上下文/`Dockerfile` COPY 路径、`build-release.yml` 的 `./cmd/*/main.go` 与三处 `-X` ldflags 模块路径(改为 `OpenFlare/plugins/{agent,relay,flared}/config.Version`)。
|
||||
- 门禁移植:`backend/Wavelet/scripts/check_cordis_architecture.sh`(core 不 import gin/gorm/asynq;pkg 不 import plugins;插件间不互相 import;禁 AutoMigrate;禁裸 go)在 OpenFlare `backend/` 下纳入 `make code-check`。
|
||||
- 文档:中文文档同步(不同步英文);`docs/changelog/index.md` 的 `[Unreleased]` 记录用户可读变更。
|
||||
|
||||
## 8. 分期执行计划(每期终点:`go build ./...` 通过 + 209 测试文件绿)
|
||||
|
||||
| 期 | 交付 | 验证 |
|
||||
| :-- | :-- | :-- |
|
||||
| P0 | 基线测量:构建/测试记录、A 路 schema dump、路由清单快照 | 存档于 `docs/superpowers/specs/baseline/` |
|
||||
| P1 | Go 树 `git mv` 入 `backend/`,module 改 `OpenFlare`,import 全量改写,Makefile/CI/Docker 路径 | `go build ./...`、四二进制产出、swagger diff 为空 |
|
||||
| P2 | 上游 vendoring 成 `backend/Wavelet/`(第二 module)+ `share/` 骨架 + 同步脚本 | `go work sync`、`go build ./...`、架构门禁通过 |
|
||||
| P3 | 迁移子系统:`w_schema_versions` 引擎接入、桥接、历史链归属、align 迁移、`migrate-audit` | **§5.4 三方 diff 全空** |
|
||||
| P4 | `server` 插件化:`apps/openflare` + health/config/edge 控制面 → 插件子包 + 扩展点注册 | 路由对拍 + 业务测试绿 |
|
||||
| P5 | `agent`/`relay`/`flared` 插件化 + `share` 落地(protocol/wsclient/edge) | 三 daemon 实跑冒烟 + JSON 配置兼容 |
|
||||
| P6 | 平台分叉审计与回流:OpenFlare 对 admin/oauth/user/upload/cap/push 的定制逐项移植进 `backend/Wavelet/` | 分叉清单逐项关闭,无静默丢功能 |
|
||||
| P7 | 工具链/CI/文档/changelog | `make code-check`、`make format` |
|
||||
| P8 | 加固:`go test -race ./...`、`-shuffle=on`、四 profile 实跑、老库升级演练 | 全绿方可声明完成 |
|
||||
|
||||
依赖:P3 依赖 P2;P4/P5 依赖 P2、P3;P6 可与 P4 并行但须在同一期收口。
|
||||
|
||||
## 9. 风险与对策
|
||||
|
||||
1. **fresh 安装与升级路径 schema 漂移**(桥接最大风险,`CREATE TABLE IF NOT EXISTS` 会静默保留旧表)→ §5.4 三方 diff 门禁 + `migrate-audit` 常驻 CI。
|
||||
2. **平台分叉被静默丢弃**(OpenFlare 的 admin/oauth/push 定制)→ P6 强制逐项清单,禁止以"上游没有"为由删除行为。
|
||||
3. **多节点同时迁移竞争**(上游无 session locker)→ 桥接与迁移阶段 advisory lock。
|
||||
4. **29.6k 行业务塞进单插件导致不可维护**→ `server` 内部按子域物理分包(§4.1),插件数保持 4 不变。
|
||||
5. **CI/Docker 路径漏改导致发布链断裂**(release 工作流含硬编码 ldflags 模块路径)→ P1 一次性收口并跑 dry-run 构建。
|
||||
6. **规模**:151k 行、166 迁移文件,上游自身耗时 100+ 提交 → 分期增量、每期可编译可测;不以"部分完成"冒充目标达成。
|
||||
|
||||
## 10. 已定决策(可在复审时否定)
|
||||
|
||||
- 布局:镜像 `backend/`,上游为第二 module(用户选定)。
|
||||
- 插件边界:每二进制 = 1 插件,四者全部走内核(用户选定)。
|
||||
- 迁移:保留历史 + 版本 stamp 桥接(用户选定)。
|
||||
- `share` 落点:`backend/Wavelet/share/`,OpenFlare 所有、同步排除(本设计采纳,备选见 §3.2)。
|
||||
- 桥接粒度:stamp 至 `MAX(已应用版本)` 而非逐条 76 行(版本号语义为「≤ max 即已应用」,逐条无额外收益且放大漂移面)。
|
||||
- ClickHouse:保持既有 `goose_clickhouse_version` 独立链,不并入插件版本表。
|
||||
@@ -0,0 +1,256 @@
|
||||
DELETE /api/v1/admin/auth-sources/:id
|
||||
DELETE /api/v1/admin/push/channels/:id
|
||||
DELETE /api/v1/admin/push/events/:id
|
||||
DELETE /api/v1/admin/tasks/schedules/:id
|
||||
DELETE /api/v1/admin/templates/:key
|
||||
DELETE /api/v1/admin/uploads/:id
|
||||
DELETE /api/v1/admin/users/:id
|
||||
DELETE /api/v1/upload/:id
|
||||
DELETE /api/v1/user/access-tokens/:id
|
||||
GET /api/health
|
||||
GET /api/swagger/*any
|
||||
GET /api/v1/admin/auth-sources
|
||||
GET /api/v1/admin/cache/status
|
||||
GET /api/v1/admin/db-export
|
||||
GET /api/v1/admin/db-info
|
||||
GET /api/v1/admin/db-manage/overview
|
||||
GET /api/v1/admin/db-manage/table-data
|
||||
GET /api/v1/admin/db-manage/tables
|
||||
GET /api/v1/admin/logs
|
||||
GET /api/v1/admin/logs/access
|
||||
GET /api/v1/admin/logs/analytics
|
||||
GET /api/v1/admin/logs/ws
|
||||
GET /api/v1/admin/push/channels
|
||||
GET /api/v1/admin/push/channels/definitions
|
||||
GET /api/v1/admin/push/events
|
||||
GET /api/v1/admin/push/events/builtin
|
||||
GET /api/v1/admin/push/histories
|
||||
GET /api/v1/admin/status
|
||||
GET /api/v1/admin/status/log-database
|
||||
GET /api/v1/admin/system-configs
|
||||
GET /api/v1/admin/system-configs/:key
|
||||
GET /api/v1/admin/tasks/executions
|
||||
GET /api/v1/admin/tasks/executions/:id
|
||||
GET /api/v1/admin/tasks/schedules
|
||||
GET /api/v1/admin/tasks/types
|
||||
GET /api/v1/admin/templates
|
||||
GET /api/v1/admin/templates/:key
|
||||
GET /api/v1/admin/update
|
||||
GET /api/v1/admin/uploads
|
||||
GET /api/v1/admin/uploads/download/:id
|
||||
GET /api/v1/admin/uploads/stats
|
||||
GET /api/v1/admin/uploads/types
|
||||
GET /api/v1/admin/users
|
||||
GET /api/v1/admin/users/:id
|
||||
GET /api/v1/agent/config-versions/active
|
||||
GET /api/v1/agent/pages/deployments/:deployment_id/hash
|
||||
GET /api/v1/agent/pages/deployments/:deployment_id/package
|
||||
GET /api/v1/agent/pages/projects/:project_id/latest/hash
|
||||
GET /api/v1/agent/pages/projects/:project_id/latest/package
|
||||
GET /api/v1/agent/ws
|
||||
GET /api/v1/config/public
|
||||
GET /api/v1/d/access-logs
|
||||
GET /api/v1/d/access-logs/
|
||||
GET /api/v1/d/access-logs/folds
|
||||
GET /api/v1/d/access-logs/folds/ip-summary
|
||||
GET /api/v1/d/access-logs/ip-summary
|
||||
GET /api/v1/d/access-logs/ip-summary/analysis
|
||||
GET /api/v1/d/access-logs/ip-summary/trend
|
||||
GET /api/v1/d/access-logs/overview
|
||||
GET /api/v1/d/acme-accounts/default
|
||||
GET /api/v1/d/apply-logs
|
||||
GET /api/v1/d/apply-logs/
|
||||
GET /api/v1/d/cloudflare/connection
|
||||
GET /api/v1/d/cloudflare/domains/available
|
||||
GET /api/v1/d/cloudflare/groups
|
||||
GET /api/v1/d/cloudflare/groups/
|
||||
GET /api/v1/d/cloudflare/groups/:id
|
||||
GET /api/v1/d/cloudflare/groups/:id/members
|
||||
GET /api/v1/d/cloudflare/overview
|
||||
GET /api/v1/d/config-versions
|
||||
GET /api/v1/d/config-versions/
|
||||
GET /api/v1/d/config-versions/:id
|
||||
GET /api/v1/d/config-versions/active
|
||||
GET /api/v1/d/config-versions/diff
|
||||
GET /api/v1/d/config-versions/preview
|
||||
GET /api/v1/d/dashboard/overview
|
||||
GET /api/v1/d/dns-accounts
|
||||
GET /api/v1/d/dns-accounts/
|
||||
GET /api/v1/d/nodes
|
||||
GET /api/v1/d/nodes/
|
||||
GET /api/v1/d/nodes/:id/agent-release
|
||||
GET /api/v1/d/nodes/:id/observability
|
||||
GET /api/v1/d/nodes/bootstrap-token
|
||||
GET /api/v1/d/option
|
||||
GET /api/v1/d/option/
|
||||
GET /api/v1/d/origins
|
||||
GET /api/v1/d/origins/
|
||||
GET /api/v1/d/origins/:id
|
||||
GET /api/v1/d/pages
|
||||
GET /api/v1/d/pages/
|
||||
GET /api/v1/d/pages/:id
|
||||
GET /api/v1/d/pages/:id/deployments
|
||||
GET /api/v1/d/pages/:id/source
|
||||
GET /api/v1/d/pages/deployments/:deployment_id/files
|
||||
GET /api/v1/d/proxy-routes
|
||||
GET /api/v1/d/proxy-routes/
|
||||
GET /api/v1/d/proxy-routes/:id
|
||||
GET /api/v1/d/status
|
||||
GET /api/v1/d/tls-certificates
|
||||
GET /api/v1/d/tls-certificates/
|
||||
GET /api/v1/d/tls-certificates/:id
|
||||
GET /api/v1/d/tls-certificates/:id/content
|
||||
GET /api/v1/d/waf/ip-groups
|
||||
GET /api/v1/d/waf/ip-groups/:id
|
||||
GET /api/v1/d/waf/rule-groups
|
||||
GET /api/v1/d/waf/rule-groups/:id
|
||||
GET /api/v1/d/waf/sites/:route_id/rule-groups
|
||||
GET /api/v1/d/zones
|
||||
GET /api/v1/d/zones/
|
||||
GET /api/v1/d/zones/:id/overview
|
||||
GET /api/v1/d/zones/:id/stats
|
||||
GET /api/v1/oauth/:source/authorize
|
||||
GET /api/v1/oauth/external-accounts
|
||||
GET /api/v1/oauth/login
|
||||
GET /api/v1/oauth/logout
|
||||
GET /api/v1/oauth/sources
|
||||
GET /api/v1/oauth/user-info
|
||||
GET /api/v1/relay/ws
|
||||
GET /api/v1/tunnel/config/active
|
||||
GET /api/v1/tunnel/ws
|
||||
GET /api/v1/upload/download/:id
|
||||
GET /api/v1/upload/my
|
||||
GET /api/v1/user-info
|
||||
GET /api/v1/user/access-tokens
|
||||
GET /api/v1/user/logout
|
||||
GET /api/v1/user/self
|
||||
GET /f/:id
|
||||
GET /robots.txt
|
||||
POST /api/cap/challenge
|
||||
POST /api/cap/redeem
|
||||
POST /api/v1/admin/auth-sources
|
||||
POST /api/v1/admin/cache/clear
|
||||
POST /api/v1/admin/cache/config
|
||||
POST /api/v1/admin/db-manage/query
|
||||
POST /api/v1/admin/push/channels
|
||||
POST /api/v1/admin/push/channels/test
|
||||
POST /api/v1/admin/push/events
|
||||
POST /api/v1/admin/push/events/:id/toggle
|
||||
POST /api/v1/admin/push/test
|
||||
POST /api/v1/admin/system-configs
|
||||
POST /api/v1/admin/system-configs/smtp/test
|
||||
POST /api/v1/admin/tasks/dispatch
|
||||
POST /api/v1/admin/tasks/executions/:id/retry
|
||||
POST /api/v1/admin/tasks/schedules
|
||||
POST /api/v1/admin/templates
|
||||
POST /api/v1/admin/update/apply
|
||||
POST /api/v1/admin/uploads/download/batch
|
||||
POST /api/v1/admin/users
|
||||
POST /api/v1/agent/apply-logs
|
||||
POST /api/v1/agent/nodes/heartbeat
|
||||
POST /api/v1/agent/nodes/register
|
||||
POST /api/v1/agent/waf/ip-groups/sync
|
||||
POST /api/v1/d/access-logs/cleanup
|
||||
POST /api/v1/d/apply-logs/cleanup
|
||||
POST /api/v1/d/cloudflare/connection/clear
|
||||
POST /api/v1/d/cloudflare/connection/verify
|
||||
POST /api/v1/d/cloudflare/groups
|
||||
POST /api/v1/d/cloudflare/groups/
|
||||
POST /api/v1/d/cloudflare/groups/:id/delete
|
||||
POST /api/v1/d/cloudflare/groups/:id/members
|
||||
POST /api/v1/d/cloudflare/groups/:id/members/:memberId/remove
|
||||
POST /api/v1/d/cloudflare/groups/:id/members/:memberId/sync
|
||||
POST /api/v1/d/cloudflare/groups/:id/members/:memberId/update
|
||||
POST /api/v1/d/cloudflare/groups/:id/sync
|
||||
POST /api/v1/d/cloudflare/groups/:id/update
|
||||
POST /api/v1/d/config-versions/:id/activate
|
||||
POST /api/v1/d/config-versions/cleanup
|
||||
POST /api/v1/d/config-versions/publish
|
||||
POST /api/v1/d/dns-accounts
|
||||
POST /api/v1/d/dns-accounts/
|
||||
POST /api/v1/d/dns-accounts/:id/delete
|
||||
POST /api/v1/d/dns-accounts/:id/update
|
||||
POST /api/v1/d/nodes
|
||||
POST /api/v1/d/nodes/
|
||||
POST /api/v1/d/nodes/:id/agent-update
|
||||
POST /api/v1/d/nodes/:id/delete
|
||||
POST /api/v1/d/nodes/:id/force-sync
|
||||
POST /api/v1/d/nodes/:id/observability/cleanup
|
||||
POST /api/v1/d/nodes/:id/openresty-restart
|
||||
POST /api/v1/d/nodes/:id/update
|
||||
POST /api/v1/d/nodes/bootstrap-token/rotate
|
||||
POST /api/v1/d/option/geoip/lookup
|
||||
POST /api/v1/d/option/update
|
||||
POST /api/v1/d/option/update-batch
|
||||
POST /api/v1/d/origins
|
||||
POST /api/v1/d/origins/
|
||||
POST /api/v1/d/origins/:id/delete
|
||||
POST /api/v1/d/origins/:id/update
|
||||
POST /api/v1/d/pages
|
||||
POST /api/v1/d/pages/
|
||||
POST /api/v1/d/pages/:id/delete
|
||||
POST /api/v1/d/pages/:id/deployments/:deployment_id/activate
|
||||
POST /api/v1/d/pages/:id/deployments/:deployment_id/delete
|
||||
POST /api/v1/d/pages/:id/deployments/upload
|
||||
POST /api/v1/d/pages/:id/deployments/upload-from-url
|
||||
POST /api/v1/d/pages/:id/source/check
|
||||
POST /api/v1/d/pages/:id/source/delete
|
||||
POST /api/v1/d/pages/:id/source/sync
|
||||
POST /api/v1/d/pages/:id/source/update
|
||||
POST /api/v1/d/pages/:id/update
|
||||
POST /api/v1/d/proxy-routes
|
||||
POST /api/v1/d/proxy-routes/
|
||||
POST /api/v1/d/proxy-routes/:id/delete
|
||||
POST /api/v1/d/proxy-routes/:id/update
|
||||
POST /api/v1/d/tls-certificates
|
||||
POST /api/v1/d/tls-certificates/
|
||||
POST /api/v1/d/tls-certificates/:id/convert-acme
|
||||
POST /api/v1/d/tls-certificates/:id/delete
|
||||
POST /api/v1/d/tls-certificates/:id/renew
|
||||
POST /api/v1/d/tls-certificates/:id/update
|
||||
POST /api/v1/d/tls-certificates/:id/update-acme
|
||||
POST /api/v1/d/tls-certificates/apply
|
||||
POST /api/v1/d/tls-certificates/import-file
|
||||
POST /api/v1/d/uptimekuma/sync
|
||||
POST /api/v1/d/waf/ip-groups
|
||||
POST /api/v1/d/waf/ip-groups/:id/delete
|
||||
POST /api/v1/d/waf/ip-groups/:id/sync
|
||||
POST /api/v1/d/waf/ip-groups/:id/update
|
||||
POST /api/v1/d/waf/ip-groups/test
|
||||
POST /api/v1/d/waf/rule-groups
|
||||
POST /api/v1/d/waf/rule-groups/:id/delete
|
||||
POST /api/v1/d/waf/rule-groups/:id/graph
|
||||
POST /api/v1/d/waf/rule-groups/:id/meta
|
||||
POST /api/v1/d/waf/sites/:route_id/rule-groups
|
||||
POST /api/v1/d/zones
|
||||
POST /api/v1/d/zones/
|
||||
POST /api/v1/d/zones/:id/delete
|
||||
POST /api/v1/d/zones/:id/domains
|
||||
POST /api/v1/d/zones/:id/domains/:domainId/delete
|
||||
POST /api/v1/d/zones/:id/domains/:domainId/update
|
||||
POST /api/v1/d/zones/:id/update
|
||||
POST /api/v1/oauth/callback
|
||||
POST /api/v1/oauth/external-accounts/:id/delete
|
||||
POST /api/v1/relay/heartbeat
|
||||
POST /api/v1/tunnel/apply-log
|
||||
POST /api/v1/tunnel/heartbeat
|
||||
POST /api/v1/upload
|
||||
POST /api/v1/upload/download/batch
|
||||
POST /api/v1/user/access-tokens
|
||||
POST /api/v1/user/access-tokens/:id/rotate
|
||||
POST /api/v1/user/change-password
|
||||
POST /api/v1/user/login
|
||||
POST /api/v1/user/register
|
||||
POST /api/v1/user/send-email-code
|
||||
PUT /api/v1/admin/auth-sources/:id
|
||||
PUT /api/v1/admin/auth-sources/:id/toggle
|
||||
PUT /api/v1/admin/push/channels/:id
|
||||
PUT /api/v1/admin/push/events/:id
|
||||
PUT /api/v1/admin/system-configs/:key
|
||||
PUT /api/v1/admin/tasks/schedules/:id
|
||||
PUT /api/v1/admin/templates/:key
|
||||
PUT /api/v1/admin/users/:id
|
||||
PUT /api/v1/admin/users/:id/status
|
||||
PUT /api/v1/d/cloudflare/connection
|
||||
PUT /api/v1/upload/:id
|
||||
PUT /api/v1/user/profile
|
||||
@@ -0,0 +1,232 @@
|
||||
DELETE /api/v1/admin/auth-sources/{id}
|
||||
DELETE /api/v1/admin/push/channels/{id}
|
||||
DELETE /api/v1/admin/push/events/{id}
|
||||
DELETE /api/v1/admin/tasks/schedules/{id}
|
||||
DELETE /api/v1/admin/templates/{key}
|
||||
DELETE /api/v1/admin/uploads/{id}
|
||||
DELETE /api/v1/admin/users/{id}
|
||||
DELETE /api/v1/upload/{id}
|
||||
DELETE /api/v1/user/access-tokens/{id}
|
||||
GET /api/health
|
||||
GET /api/v1/admin/auth-sources
|
||||
GET /api/v1/admin/cache/status
|
||||
GET /api/v1/admin/db-export
|
||||
GET /api/v1/admin/db-info
|
||||
GET /api/v1/admin/db-manage/overview
|
||||
GET /api/v1/admin/db-manage/tables
|
||||
GET /api/v1/admin/logs
|
||||
GET /api/v1/admin/logs/access
|
||||
GET /api/v1/admin/logs/analytics
|
||||
GET /api/v1/admin/logs/ws
|
||||
GET /api/v1/admin/push/channels
|
||||
GET /api/v1/admin/push/channels/definitions
|
||||
GET /api/v1/admin/push/events
|
||||
GET /api/v1/admin/push/events/builtin
|
||||
GET /api/v1/admin/push/histories
|
||||
GET /api/v1/admin/status
|
||||
GET /api/v1/admin/status/log-database
|
||||
GET /api/v1/admin/system-configs
|
||||
GET /api/v1/admin/system-configs/{key}
|
||||
GET /api/v1/admin/tasks/executions
|
||||
GET /api/v1/admin/tasks/executions/{id}
|
||||
GET /api/v1/admin/tasks/schedules
|
||||
GET /api/v1/admin/tasks/types
|
||||
GET /api/v1/admin/templates
|
||||
GET /api/v1/admin/templates/{key}
|
||||
GET /api/v1/admin/update
|
||||
GET /api/v1/admin/uploads
|
||||
GET /api/v1/admin/uploads/download/{id}
|
||||
GET /api/v1/admin/uploads/stats
|
||||
GET /api/v1/admin/uploads/types
|
||||
GET /api/v1/admin/users
|
||||
GET /api/v1/admin/users/{id}
|
||||
GET /api/v1/agent/config-versions/active
|
||||
GET /api/v1/agent/pages/deployments/{deployment_id}/hash
|
||||
GET /api/v1/agent/pages/deployments/{deployment_id}/package
|
||||
GET /api/v1/agent/pages/projects/{project_id}/latest/hash
|
||||
GET /api/v1/agent/pages/projects/{project_id}/latest/package
|
||||
GET /api/v1/agent/ws
|
||||
GET /api/v1/config/public
|
||||
GET /api/v1/d/access-logs
|
||||
GET /api/v1/d/access-logs/folds
|
||||
GET /api/v1/d/access-logs/folds/ip-summary
|
||||
GET /api/v1/d/access-logs/ip-summary
|
||||
GET /api/v1/d/access-logs/ip-summary/analysis
|
||||
GET /api/v1/d/access-logs/ip-summary/trend
|
||||
GET /api/v1/d/access-logs/overview
|
||||
GET /api/v1/d/acme-accounts/default
|
||||
GET /api/v1/d/apply-logs
|
||||
GET /api/v1/d/cloudflare/connection
|
||||
GET /api/v1/d/cloudflare/domains/available
|
||||
GET /api/v1/d/cloudflare/groups
|
||||
GET /api/v1/d/cloudflare/groups/{id}
|
||||
GET /api/v1/d/cloudflare/groups/{id}/members
|
||||
GET /api/v1/d/cloudflare/overview
|
||||
GET /api/v1/d/config-versions
|
||||
GET /api/v1/d/config-versions/active
|
||||
GET /api/v1/d/config-versions/diff
|
||||
GET /api/v1/d/config-versions/preview
|
||||
GET /api/v1/d/config-versions/{id}
|
||||
GET /api/v1/d/dashboard/overview
|
||||
GET /api/v1/d/dns-accounts
|
||||
GET /api/v1/d/nodes
|
||||
GET /api/v1/d/nodes/bootstrap-token
|
||||
GET /api/v1/d/nodes/{id}/agent-release
|
||||
GET /api/v1/d/nodes/{id}/observability
|
||||
GET /api/v1/d/option
|
||||
GET /api/v1/d/origins
|
||||
GET /api/v1/d/origins/{id}
|
||||
GET /api/v1/d/pages
|
||||
GET /api/v1/d/pages/deployments/{deployment_id}/files
|
||||
GET /api/v1/d/pages/{id}
|
||||
GET /api/v1/d/pages/{id}/deployments
|
||||
GET /api/v1/d/pages/{id}/source
|
||||
GET /api/v1/d/proxy-routes
|
||||
GET /api/v1/d/proxy-routes/{id}
|
||||
GET /api/v1/d/status
|
||||
GET /api/v1/d/tls-certificates
|
||||
GET /api/v1/d/tls-certificates/{id}
|
||||
GET /api/v1/d/tls-certificates/{id}/content
|
||||
GET /api/v1/d/waf/ip-groups
|
||||
GET /api/v1/d/waf/ip-groups/{id}
|
||||
GET /api/v1/d/waf/rule-groups
|
||||
GET /api/v1/d/waf/rule-groups/{id}
|
||||
GET /api/v1/d/waf/sites/{route_id}/rule-groups
|
||||
GET /api/v1/d/zones
|
||||
GET /api/v1/d/zones/{id}/overview
|
||||
GET /api/v1/d/zones/{id}/stats
|
||||
GET /api/v1/oauth/external-accounts
|
||||
GET /api/v1/oauth/login
|
||||
GET /api/v1/oauth/logout
|
||||
GET /api/v1/oauth/sources
|
||||
GET /api/v1/oauth/user-info
|
||||
GET /api/v1/oauth/{source}/authorize
|
||||
GET /api/v1/relay/ws
|
||||
GET /api/v1/tunnel/config/active
|
||||
GET /api/v1/tunnel/ws
|
||||
GET /api/v1/upload/my
|
||||
GET /api/v1/user-info
|
||||
GET /api/v1/user/access-tokens
|
||||
GET /api/v1/user/logout
|
||||
GET /api/v1/user/self
|
||||
GET /f/{id}
|
||||
GET /robots.txt
|
||||
POST /api/cap/challenge
|
||||
POST /api/cap/redeem
|
||||
POST /api/v1/admin/auth-sources
|
||||
POST /api/v1/admin/cache/clear
|
||||
POST /api/v1/admin/cache/config
|
||||
POST /api/v1/admin/db-manage/query
|
||||
POST /api/v1/admin/push/channels
|
||||
POST /api/v1/admin/push/channels/test
|
||||
POST /api/v1/admin/push/events
|
||||
POST /api/v1/admin/push/events/{id}/toggle
|
||||
POST /api/v1/admin/push/test
|
||||
POST /api/v1/admin/system-configs
|
||||
POST /api/v1/admin/system-configs/smtp/test
|
||||
POST /api/v1/admin/tasks/dispatch
|
||||
POST /api/v1/admin/tasks/executions/{id}/retry
|
||||
POST /api/v1/admin/tasks/schedules
|
||||
POST /api/v1/admin/templates
|
||||
POST /api/v1/admin/update/apply
|
||||
POST /api/v1/admin/uploads/download/batch
|
||||
POST /api/v1/admin/users
|
||||
POST /api/v1/agent/apply-logs
|
||||
POST /api/v1/agent/nodes/heartbeat
|
||||
POST /api/v1/agent/nodes/register
|
||||
POST /api/v1/agent/waf/ip-groups/sync
|
||||
POST /api/v1/d/access-logs/cleanup
|
||||
POST /api/v1/d/apply-logs/cleanup
|
||||
POST /api/v1/d/cloudflare/connection/clear
|
||||
POST /api/v1/d/cloudflare/connection/verify
|
||||
POST /api/v1/d/cloudflare/groups
|
||||
POST /api/v1/d/cloudflare/groups/{id}/delete
|
||||
POST /api/v1/d/cloudflare/groups/{id}/members
|
||||
POST /api/v1/d/cloudflare/groups/{id}/members/{memberId}/remove
|
||||
POST /api/v1/d/cloudflare/groups/{id}/members/{memberId}/sync
|
||||
POST /api/v1/d/cloudflare/groups/{id}/members/{memberId}/update
|
||||
POST /api/v1/d/cloudflare/groups/{id}/sync
|
||||
POST /api/v1/d/cloudflare/groups/{id}/update
|
||||
POST /api/v1/d/config-versions/cleanup
|
||||
POST /api/v1/d/config-versions/publish
|
||||
POST /api/v1/d/config-versions/{id}/activate
|
||||
POST /api/v1/d/dns-accounts
|
||||
POST /api/v1/d/dns-accounts/{id}/delete
|
||||
POST /api/v1/d/dns-accounts/{id}/update
|
||||
POST /api/v1/d/nodes
|
||||
POST /api/v1/d/nodes/bootstrap-token/rotate
|
||||
POST /api/v1/d/nodes/{id}/agent-update
|
||||
POST /api/v1/d/nodes/{id}/delete
|
||||
POST /api/v1/d/nodes/{id}/force-sync
|
||||
POST /api/v1/d/nodes/{id}/observability/cleanup
|
||||
POST /api/v1/d/nodes/{id}/openresty-restart
|
||||
POST /api/v1/d/nodes/{id}/update
|
||||
POST /api/v1/d/option/geoip/lookup
|
||||
POST /api/v1/d/option/update
|
||||
POST /api/v1/d/option/update-batch
|
||||
POST /api/v1/d/origins
|
||||
POST /api/v1/d/origins/{id}/delete
|
||||
POST /api/v1/d/origins/{id}/update
|
||||
POST /api/v1/d/pages
|
||||
POST /api/v1/d/pages/{id}/delete
|
||||
POST /api/v1/d/pages/{id}/deployments/upload
|
||||
POST /api/v1/d/pages/{id}/deployments/upload-from-url
|
||||
POST /api/v1/d/pages/{id}/deployments/{deployment_id}/activate
|
||||
POST /api/v1/d/pages/{id}/deployments/{deployment_id}/delete
|
||||
POST /api/v1/d/pages/{id}/source/check
|
||||
POST /api/v1/d/pages/{id}/source/delete
|
||||
POST /api/v1/d/pages/{id}/source/sync
|
||||
POST /api/v1/d/pages/{id}/source/update
|
||||
POST /api/v1/d/pages/{id}/update
|
||||
POST /api/v1/d/proxy-routes
|
||||
POST /api/v1/d/proxy-routes/{id}/delete
|
||||
POST /api/v1/d/proxy-routes/{id}/update
|
||||
POST /api/v1/d/tls-certificates
|
||||
POST /api/v1/d/tls-certificates/apply
|
||||
POST /api/v1/d/tls-certificates/import-file
|
||||
POST /api/v1/d/tls-certificates/{id}/convert-acme
|
||||
POST /api/v1/d/tls-certificates/{id}/delete
|
||||
POST /api/v1/d/tls-certificates/{id}/renew
|
||||
POST /api/v1/d/tls-certificates/{id}/update
|
||||
POST /api/v1/d/tls-certificates/{id}/update-acme
|
||||
POST /api/v1/d/uptimekuma/sync
|
||||
POST /api/v1/d/waf/ip-groups
|
||||
POST /api/v1/d/waf/ip-groups/test
|
||||
POST /api/v1/d/waf/ip-groups/{id}/delete
|
||||
POST /api/v1/d/waf/ip-groups/{id}/sync
|
||||
POST /api/v1/d/waf/ip-groups/{id}/update
|
||||
POST /api/v1/d/waf/rule-groups
|
||||
POST /api/v1/d/waf/rule-groups/{id}/delete
|
||||
POST /api/v1/d/waf/rule-groups/{id}/graph
|
||||
POST /api/v1/d/waf/rule-groups/{id}/meta
|
||||
POST /api/v1/d/waf/sites/{route_id}/rule-groups
|
||||
POST /api/v1/d/zones
|
||||
POST /api/v1/d/zones/{id}/delete
|
||||
POST /api/v1/d/zones/{id}/domains
|
||||
POST /api/v1/d/zones/{id}/domains/{domainId}/delete
|
||||
POST /api/v1/d/zones/{id}/domains/{domainId}/update
|
||||
POST /api/v1/d/zones/{id}/update
|
||||
POST /api/v1/oauth/callback
|
||||
POST /api/v1/oauth/external-accounts/{id}/delete
|
||||
POST /api/v1/relay/heartbeat
|
||||
POST /api/v1/tunnel/apply-log
|
||||
POST /api/v1/tunnel/heartbeat
|
||||
POST /api/v1/upload
|
||||
POST /api/v1/user/access-tokens
|
||||
POST /api/v1/user/access-tokens/{id}/rotate
|
||||
POST /api/v1/user/change-password
|
||||
POST /api/v1/user/login
|
||||
POST /api/v1/user/register
|
||||
POST /api/v1/user/send-email-code
|
||||
PUT /api/v1/admin/auth-sources/{id}
|
||||
PUT /api/v1/admin/auth-sources/{id}/toggle
|
||||
PUT /api/v1/admin/push/channels/{id}
|
||||
PUT /api/v1/admin/push/events/{id}
|
||||
PUT /api/v1/admin/system-configs/{key}
|
||||
PUT /api/v1/admin/tasks/schedules/{id}
|
||||
PUT /api/v1/admin/templates/{key}
|
||||
PUT /api/v1/admin/users/{id}
|
||||
PUT /api/v1/admin/users/{id}/status
|
||||
PUT /api/v1/d/cloudflare/connection
|
||||
PUT /api/v1/upload/{id}
|
||||
PUT /api/v1/user/profile
|
||||
@@ -0,0 +1,785 @@
|
||||
-- index idx_of_apply_logs_created_at
|
||||
CREATE INDEX idx_of_apply_logs_created_at ON of_apply_logs(created_at);
|
||||
-- index idx_of_apply_logs_node_id
|
||||
CREATE INDEX idx_of_apply_logs_node_id ON of_apply_logs(node_id);
|
||||
-- index idx_of_cf_connections_dns_account_id
|
||||
CREATE INDEX idx_of_cf_connections_dns_account_id ON of_cf_connections (dns_account_id);
|
||||
-- index idx_of_cf_pointing_groups_active_node_id
|
||||
CREATE INDEX idx_of_cf_pointing_groups_active_node_id ON of_cf_pointing_groups (active_node_id);
|
||||
-- index idx_of_cf_pointing_groups_backup_node_id
|
||||
CREATE INDEX idx_of_cf_pointing_groups_backup_node_id ON of_cf_pointing_groups (backup_node_id);
|
||||
-- index idx_of_cf_pointing_groups_primary_node_id
|
||||
CREATE INDEX idx_of_cf_pointing_groups_primary_node_id ON of_cf_pointing_groups (primary_node_id);
|
||||
-- index idx_of_cf_pointing_members_group_id
|
||||
CREATE INDEX idx_of_cf_pointing_members_group_id ON of_cf_pointing_members (group_id);
|
||||
-- index idx_of_cf_pointing_members_zone_domain_id
|
||||
CREATE UNIQUE INDEX idx_of_cf_pointing_members_zone_domain_id ON of_cf_pointing_members (zone_domain_id);
|
||||
-- index idx_of_config_versions_is_active
|
||||
CREATE INDEX idx_of_config_versions_is_active ON of_config_versions (is_active);
|
||||
-- index idx_of_node_access_logs_host
|
||||
CREATE INDEX idx_of_node_access_logs_host ON of_node_access_logs (host, logged_at DESC);
|
||||
-- index idx_of_node_access_logs_host_lower
|
||||
CREATE INDEX idx_of_node_access_logs_host_lower ON of_node_access_logs (lower(trim(host)));
|
||||
-- index idx_of_node_access_logs_logged_at
|
||||
CREATE INDEX idx_of_node_access_logs_logged_at ON of_node_access_logs (logged_at DESC, id DESC);
|
||||
-- index idx_of_node_access_logs_node_id
|
||||
CREATE INDEX idx_of_node_access_logs_node_id ON of_node_access_logs (node_id, logged_at DESC);
|
||||
-- index idx_of_node_access_logs_remote_addr
|
||||
CREATE INDEX idx_of_node_access_logs_remote_addr ON of_node_access_logs (remote_addr, logged_at DESC);
|
||||
-- index idx_of_node_access_logs_status_code
|
||||
CREATE INDEX idx_of_node_access_logs_status_code ON of_node_access_logs (status_code, logged_at DESC);
|
||||
-- index idx_of_node_edge_health_node
|
||||
CREATE INDEX idx_of_node_edge_health_node ON of_node_edge_health (node_id, captured_at DESC);
|
||||
-- index idx_of_node_health_events_event_type
|
||||
CREATE INDEX idx_of_node_health_events_event_type ON of_node_health_events (event_type);
|
||||
-- index idx_of_node_health_events_first_triggered_at
|
||||
CREATE INDEX idx_of_node_health_events_first_triggered_at ON of_node_health_events (first_triggered_at);
|
||||
-- index idx_of_node_health_events_last_triggered_at
|
||||
CREATE INDEX idx_of_node_health_events_last_triggered_at ON of_node_health_events (last_triggered_at);
|
||||
-- index idx_of_node_health_events_node_id
|
||||
CREATE INDEX idx_of_node_health_events_node_id ON of_node_health_events (node_id);
|
||||
-- index idx_of_node_health_events_reported_at
|
||||
CREATE INDEX idx_of_node_health_events_reported_at ON of_node_health_events (reported_at);
|
||||
-- index idx_of_node_health_events_resolved_at
|
||||
CREATE INDEX idx_of_node_health_events_resolved_at ON of_node_health_events (resolved_at);
|
||||
-- index idx_of_node_health_events_status
|
||||
CREATE INDEX idx_of_node_health_events_status ON of_node_health_events (status);
|
||||
-- index idx_of_node_metric_snapshots_node
|
||||
CREATE INDEX idx_of_node_metric_snapshots_node ON of_node_metric_snapshots (node_id, captured_at DESC);
|
||||
-- index idx_of_node_obs_frpc_node
|
||||
CREATE INDEX idx_of_node_obs_frpc_node ON of_node_obs_frpc (node_id, captured_at DESC);
|
||||
-- index idx_of_node_obs_frps_node
|
||||
CREATE INDEX idx_of_node_obs_frps_node ON of_node_obs_frps (node_id, captured_at DESC);
|
||||
-- index idx_of_node_system_profiles_node_id
|
||||
CREATE UNIQUE INDEX idx_of_node_system_profiles_node_id ON of_node_system_profiles (node_id);
|
||||
-- index idx_of_node_system_profiles_reported_at
|
||||
CREATE INDEX idx_of_node_system_profiles_reported_at ON of_node_system_profiles (reported_at);
|
||||
-- index idx_of_nodes_access_token
|
||||
CREATE INDEX idx_of_nodes_access_token ON of_nodes (access_token);
|
||||
-- index idx_of_nodes_node_id
|
||||
CREATE UNIQUE INDEX idx_of_nodes_node_id ON of_nodes (node_id);
|
||||
-- index idx_of_origins_address
|
||||
CREATE UNIQUE INDEX idx_of_origins_address ON of_origins (address);
|
||||
-- index idx_of_pages_deployment_files_deployment_id
|
||||
CREATE INDEX idx_of_pages_deployment_files_deployment_id ON of_pages_deployment_files (deployment_id);
|
||||
-- index idx_of_pages_deployments_checksum
|
||||
CREATE INDEX idx_of_pages_deployments_checksum ON of_pages_deployments (checksum);
|
||||
-- index idx_of_pages_deployments_project_id
|
||||
CREATE INDEX idx_of_pages_deployments_project_id ON of_pages_deployments (project_id);
|
||||
-- index idx_of_pages_deployments_project_number
|
||||
CREATE UNIQUE INDEX idx_of_pages_deployments_project_number
|
||||
ON of_pages_deployments (project_id, deployment_number);
|
||||
-- index idx_of_pages_deployments_source_revision
|
||||
CREATE UNIQUE INDEX idx_of_pages_deployments_source_revision
|
||||
ON of_pages_deployments (project_id, source_identity, source_revision)
|
||||
WHERE source_identity IS NOT NULL AND source_revision IS NOT NULL;
|
||||
-- index idx_of_pages_deployments_status
|
||||
CREATE INDEX idx_of_pages_deployments_status ON of_pages_deployments (status);
|
||||
-- index idx_of_pages_deployments_upload_id
|
||||
CREATE INDEX idx_of_pages_deployments_upload_id ON of_pages_deployments (upload_id);
|
||||
-- index idx_of_pages_project_source_runtime_next_check_at
|
||||
CREATE INDEX idx_of_pages_project_source_runtime_next_check_at
|
||||
ON of_pages_project_source_runtime (next_check_at);
|
||||
-- index idx_of_pages_project_sources_project_id
|
||||
CREATE UNIQUE INDEX idx_of_pages_project_sources_project_id
|
||||
ON of_pages_project_sources (project_id);
|
||||
-- index idx_of_pages_projects_active_deployment_id
|
||||
CREATE INDEX idx_of_pages_projects_active_deployment_id ON of_pages_projects (active_deployment_id);
|
||||
-- index idx_of_pages_projects_slug
|
||||
CREATE UNIQUE INDEX idx_of_pages_projects_slug ON of_pages_projects (slug);
|
||||
-- index idx_of_proxy_routes_origin_id
|
||||
CREATE INDEX idx_of_proxy_routes_origin_id ON of_proxy_routes (origin_id);
|
||||
-- index idx_of_proxy_routes_pages_project_id
|
||||
CREATE INDEX idx_of_proxy_routes_pages_project_id ON of_proxy_routes (pages_project_id);
|
||||
-- index idx_of_proxy_routes_site_name
|
||||
CREATE UNIQUE INDEX idx_of_proxy_routes_site_name ON of_proxy_routes (site_name);
|
||||
-- index idx_of_proxy_routes_tunnel_node_id
|
||||
CREATE INDEX idx_of_proxy_routes_tunnel_node_id ON of_proxy_routes (tunnel_node_id);
|
||||
-- index idx_of_tls_certificates_name
|
||||
CREATE UNIQUE INDEX idx_of_tls_certificates_name ON of_tls_certificates (name);
|
||||
-- index idx_of_waf_group_route
|
||||
CREATE UNIQUE INDEX idx_of_waf_group_route ON of_waf_rule_group_bindings (rule_group_id, proxy_route_id);
|
||||
-- index idx_of_waf_ip_groups_next_sync_at
|
||||
CREATE INDEX idx_of_waf_ip_groups_next_sync_at ON of_waf_ip_groups (next_sync_at);
|
||||
-- index idx_of_waf_ip_groups_type
|
||||
CREATE INDEX idx_of_waf_ip_groups_type ON of_waf_ip_groups (type);
|
||||
-- index idx_of_waf_rule_group_bindings_proxy_route_id
|
||||
CREATE INDEX idx_of_waf_rule_group_bindings_proxy_route_id ON of_waf_rule_group_bindings (proxy_route_id);
|
||||
-- index idx_of_waf_rule_groups_is_global
|
||||
CREATE INDEX idx_of_waf_rule_groups_is_global ON of_waf_rule_groups (is_global);
|
||||
-- index idx_of_zone_domains_cert_id
|
||||
CREATE INDEX idx_of_zone_domains_cert_id ON of_zone_domains (cert_id);
|
||||
-- index idx_of_zone_domains_domain
|
||||
CREATE UNIQUE INDEX idx_of_zone_domains_domain ON of_zone_domains (domain);
|
||||
-- index idx_of_zone_domains_proxy_route_id
|
||||
CREATE INDEX idx_of_zone_domains_proxy_route_id ON of_zone_domains (proxy_route_id);
|
||||
-- index idx_of_zone_domains_zone_id
|
||||
CREATE INDEX idx_of_zone_domains_zone_id ON of_zone_domains (zone_id);
|
||||
-- index idx_of_zones_domain
|
||||
CREATE UNIQUE INDEX idx_of_zones_domain ON of_zones (domain);
|
||||
-- index idx_w_access_tokens_user_id
|
||||
CREATE INDEX idx_w_access_tokens_user_id ON w_access_tokens (user_id);
|
||||
-- index idx_w_auth_sources_is_active
|
||||
CREATE INDEX idx_w_auth_sources_is_active ON w_auth_sources (is_active);
|
||||
-- index idx_w_external_accounts_auth_source_id
|
||||
CREATE INDEX idx_w_external_accounts_auth_source_id ON w_external_accounts (auth_source_id);
|
||||
-- index idx_w_external_accounts_source_external
|
||||
CREATE UNIQUE INDEX idx_w_external_accounts_source_external ON w_external_accounts (auth_source_id, external_id);
|
||||
-- index idx_w_external_accounts_user_id
|
||||
CREATE INDEX idx_w_external_accounts_user_id ON w_external_accounts (user_id);
|
||||
-- index idx_w_push_channels_enabled
|
||||
CREATE INDEX idx_w_push_channels_enabled ON w_push_channels(enabled);
|
||||
-- index idx_w_push_channels_name
|
||||
CREATE INDEX idx_w_push_channels_name ON w_push_channels(name);
|
||||
-- index idx_w_push_events_enabled
|
||||
CREATE INDEX idx_w_push_events_enabled ON w_push_events(enabled);
|
||||
-- index idx_w_push_events_task_type
|
||||
CREATE INDEX idx_w_push_events_task_type ON w_push_events(task_type);
|
||||
-- index idx_w_push_histories_created
|
||||
CREATE INDEX idx_w_push_histories_created ON w_push_histories(created_at);
|
||||
-- index idx_w_push_histories_event
|
||||
CREATE INDEX idx_w_push_histories_event ON w_push_histories(event_key);
|
||||
-- index idx_w_schedules_is_active
|
||||
CREATE INDEX idx_w_schedules_is_active ON w_schedules (is_active);
|
||||
-- index idx_w_task_executions_created_at
|
||||
CREATE INDEX idx_w_task_executions_created_at ON w_task_executions (created_at);
|
||||
-- index idx_w_task_executions_started_at
|
||||
CREATE INDEX idx_w_task_executions_started_at ON w_task_executions (started_at);
|
||||
-- index idx_w_task_executions_status
|
||||
CREATE INDEX idx_w_task_executions_status ON w_task_executions (status);
|
||||
-- index idx_w_task_executions_task_type
|
||||
CREATE INDEX idx_w_task_executions_task_type ON w_task_executions (task_type);
|
||||
-- index idx_w_templates_created_at
|
||||
CREATE INDEX idx_w_templates_created_at ON w_templates (created_at);
|
||||
-- index idx_w_templates_is_system
|
||||
CREATE INDEX idx_w_templates_is_system ON w_templates (is_system);
|
||||
-- index idx_w_templates_updated_at
|
||||
CREATE INDEX idx_w_templates_updated_at ON w_templates (updated_at);
|
||||
-- index idx_w_uploads_file_path
|
||||
CREATE INDEX idx_w_uploads_file_path ON w_uploads (file_path);
|
||||
-- index idx_w_uploads_hash
|
||||
CREATE INDEX idx_w_uploads_hash ON w_uploads (hash);
|
||||
-- index idx_w_uploads_hash_file_size_status
|
||||
CREATE INDEX idx_w_uploads_hash_file_size_status ON w_uploads (hash, file_size, status);
|
||||
-- index idx_w_uploads_status_created_at
|
||||
CREATE INDEX idx_w_uploads_status_created_at ON w_uploads (status, created_at);
|
||||
-- index idx_w_uploads_type
|
||||
CREATE INDEX idx_w_uploads_type ON w_uploads (type);
|
||||
-- index idx_w_uploads_user_id
|
||||
CREATE INDEX idx_w_uploads_user_id ON w_uploads (user_id);
|
||||
-- index idx_w_user_access_logs_user_id
|
||||
CREATE INDEX idx_w_user_access_logs_user_id ON w_user_access_logs (user_id, created_at DESC);
|
||||
-- index idx_w_users_created_at
|
||||
CREATE INDEX idx_w_users_created_at ON w_users (created_at);
|
||||
-- index idx_w_users_email
|
||||
CREATE INDEX idx_w_users_email ON w_users (email);
|
||||
-- index idx_w_users_is_active
|
||||
CREATE INDEX idx_w_users_is_active ON w_users (is_active);
|
||||
-- index idx_w_users_last_login_at
|
||||
CREATE INDEX idx_w_users_last_login_at ON w_users (last_login_at);
|
||||
-- table of_acme_accounts
|
||||
CREATE TABLE of_acme_accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT NOT NULL DEFAULT '',
|
||||
url TEXT NOT NULL DEFAULT '',
|
||||
private_key TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_apply_logs
|
||||
CREATE TABLE of_apply_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL,
|
||||
version TEXT NOT NULL,
|
||||
result TEXT NOT NULL,
|
||||
message TEXT,
|
||||
checksum TEXT NOT NULL DEFAULT '',
|
||||
main_config_checksum TEXT NOT NULL DEFAULT '',
|
||||
route_config_checksum TEXT NOT NULL DEFAULT '',
|
||||
support_file_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL
|
||||
);
|
||||
-- table of_cf_connections
|
||||
CREATE TABLE of_cf_connections (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source TEXT NOT NULL DEFAULT '',
|
||||
dns_account_id INTEGER,
|
||||
authorization TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT '',
|
||||
verified_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_cf_pointing_groups
|
||||
CREATE TABLE of_cf_pointing_groups (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
primary_node_id INTEGER NOT NULL,
|
||||
backup_node_id INTEGER,
|
||||
active_node_id INTEGER NOT NULL,
|
||||
default_proxied BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_cf_pointing_members
|
||||
CREATE TABLE of_cf_pointing_members (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
group_id INTEGER NOT NULL,
|
||||
zone_domain_id INTEGER NOT NULL,
|
||||
proxied BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
cf_zone_id TEXT NOT NULL DEFAULT '',
|
||||
cf_record_id TEXT NOT NULL DEFAULT '',
|
||||
desired_ip TEXT NOT NULL DEFAULT '',
|
||||
sync_status TEXT NOT NULL DEFAULT 'pending',
|
||||
last_error TEXT NOT NULL DEFAULT '',
|
||||
synced_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_config_versions
|
||||
CREATE TABLE "of_config_versions" (
|
||||
version VARCHAR(32) PRIMARY KEY,
|
||||
snapshot_json TEXT NOT NULL,
|
||||
main_config TEXT NOT NULL DEFAULT '',
|
||||
rendered_config TEXT NOT NULL,
|
||||
support_files_json TEXT NOT NULL DEFAULT '[]',
|
||||
checksum VARCHAR(64) NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_by VARCHAR(64) NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_dns_accounts
|
||||
CREATE TABLE of_dns_accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
authorization TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_access_logs
|
||||
CREATE TABLE of_node_access_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL DEFAULT '',
|
||||
logged_at DATETIME NOT NULL,
|
||||
remote_addr TEXT NOT NULL DEFAULT '',
|
||||
region TEXT NOT NULL DEFAULT '',
|
||||
host TEXT NOT NULL DEFAULT '',
|
||||
path TEXT NOT NULL DEFAULT '',
|
||||
user_agent TEXT NOT NULL DEFAULT '',
|
||||
cache_status TEXT NOT NULL DEFAULT '',
|
||||
status_code INTEGER NOT NULL DEFAULT 0,
|
||||
bytes_sent INTEGER NOT NULL DEFAULT 0,
|
||||
request_length INTEGER NOT NULL DEFAULT 0,
|
||||
request_time_ms INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_edge_health
|
||||
CREATE TABLE of_node_edge_health (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL DEFAULT '',
|
||||
captured_at DATETIME NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT '',
|
||||
connections INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_health_events
|
||||
CREATE TABLE of_node_health_events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
severity TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
message TEXT,
|
||||
first_triggered_at DATETIME NOT NULL,
|
||||
last_triggered_at DATETIME NOT NULL,
|
||||
reported_at DATETIME NOT NULL,
|
||||
resolved_at DATETIME,
|
||||
metadata_json TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_metric_snapshots
|
||||
CREATE TABLE of_node_metric_snapshots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL DEFAULT '',
|
||||
captured_at DATETIME NOT NULL,
|
||||
cpu_usage_percent REAL NOT NULL DEFAULT 0,
|
||||
memory_used_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
memory_total_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
storage_used_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
storage_total_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
disk_read_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
disk_write_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
network_rx_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
network_tx_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_obs_frpc
|
||||
CREATE TABLE of_node_obs_frpc (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL DEFAULT '',
|
||||
captured_at DATETIME NOT NULL,
|
||||
tunnel_status TEXT NOT NULL DEFAULT '',
|
||||
connected_relays_count INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_obs_frps
|
||||
CREATE TABLE of_node_obs_frps (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL DEFAULT '',
|
||||
captured_at DATETIME NOT NULL,
|
||||
frps_connections INTEGER NOT NULL DEFAULT 0,
|
||||
frps_proxy_count INTEGER NOT NULL DEFAULT 0,
|
||||
frps_client_count INTEGER NOT NULL DEFAULT 0,
|
||||
frps_proxies TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_node_system_profiles
|
||||
CREATE TABLE of_node_system_profiles (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL,
|
||||
hostname TEXT NOT NULL DEFAULT '',
|
||||
os_name TEXT NOT NULL DEFAULT '',
|
||||
os_version TEXT NOT NULL DEFAULT '',
|
||||
kernel_version TEXT NOT NULL DEFAULT '',
|
||||
architecture TEXT NOT NULL DEFAULT '',
|
||||
cpu_model TEXT NOT NULL DEFAULT '',
|
||||
cpu_cores INTEGER NOT NULL DEFAULT 0,
|
||||
total_memory_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
total_disk_bytes INTEGER NOT NULL DEFAULT 0,
|
||||
uptime_seconds INTEGER NOT NULL DEFAULT 0,
|
||||
reported_at DATETIME NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_nodes
|
||||
CREATE TABLE of_nodes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
node_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
ip TEXT NOT NULL DEFAULT '',
|
||||
ip_manual_override INTEGER NOT NULL DEFAULT 0,
|
||||
geo_name TEXT NOT NULL DEFAULT '',
|
||||
geo_latitude REAL,
|
||||
geo_longitude REAL,
|
||||
geo_manual_override INTEGER NOT NULL DEFAULT 0,
|
||||
access_token TEXT NOT NULL DEFAULT '',
|
||||
auto_update_enabled INTEGER NOT NULL DEFAULT 0,
|
||||
update_requested INTEGER NOT NULL DEFAULT 0,
|
||||
update_channel TEXT NOT NULL DEFAULT 'stable',
|
||||
update_tag TEXT NOT NULL DEFAULT '',
|
||||
restart_openresty_requested INTEGER NOT NULL DEFAULT 0,
|
||||
version TEXT NOT NULL DEFAULT '',
|
||||
ext_version TEXT NOT NULL DEFAULT '',
|
||||
openresty_status TEXT NOT NULL DEFAULT 'unknown',
|
||||
openresty_message TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'offline',
|
||||
current_version TEXT NOT NULL DEFAULT '',
|
||||
last_seen_at DATETIME,
|
||||
last_error TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
node_type TEXT NOT NULL DEFAULT 'edge_node',
|
||||
relay_bind_port INTEGER NOT NULL DEFAULT 0,
|
||||
relay_vhost_http_port INTEGER NOT NULL DEFAULT 0,
|
||||
relay_auth_token TEXT NOT NULL DEFAULT '',
|
||||
relay_agent_access_addr TEXT NOT NULL DEFAULT '',
|
||||
relay_client_access_addr TEXT NOT NULL DEFAULT '',
|
||||
relay_client_proxy_url TEXT NOT NULL DEFAULT '',
|
||||
capabilities_json TEXT NOT NULL DEFAULT '[]',
|
||||
relay_status TEXT NOT NULL DEFAULT 'unknown',
|
||||
relay_web_server_enabled INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
-- table of_origins
|
||||
CREATE TABLE of_origins (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
address TEXT NOT NULL,
|
||||
remark TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_pages_deployment_files
|
||||
CREATE TABLE of_pages_deployment_files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
deployment_id INTEGER NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
size INTEGER NOT NULL DEFAULT 0,
|
||||
checksum TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_pages_deployments
|
||||
CREATE TABLE of_pages_deployments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL,
|
||||
deployment_number INTEGER NOT NULL,
|
||||
checksum TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'uploaded',
|
||||
artifact_path TEXT NOT NULL,
|
||||
file_count INTEGER NOT NULL DEFAULT 0,
|
||||
total_size INTEGER NOT NULL DEFAULT 0,
|
||||
created_by TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
activated_at DATETIME
|
||||
, upload_id INTEGER NOT NULL DEFAULT 0, source_type TEXT NOT NULL DEFAULT '', source_identity TEXT, source_revision TEXT, source_label TEXT NOT NULL DEFAULT '', source_meta TEXT NOT NULL DEFAULT '', trigger_type TEXT NOT NULL DEFAULT '');
|
||||
-- table of_pages_project_source_runtime
|
||||
CREATE TABLE of_pages_project_source_runtime (
|
||||
source_id INTEGER PRIMARY KEY,
|
||||
etag TEXT NOT NULL DEFAULT '',
|
||||
last_seen_revision TEXT NOT NULL DEFAULT '',
|
||||
last_seen_detail TEXT NOT NULL DEFAULT '',
|
||||
last_applied_revision TEXT NOT NULL DEFAULT '',
|
||||
last_applied_detail TEXT NOT NULL DEFAULT '',
|
||||
sync_status TEXT NOT NULL DEFAULT '',
|
||||
last_error TEXT NOT NULL DEFAULT '',
|
||||
last_checked_at DATETIME,
|
||||
last_synced_at DATETIME,
|
||||
next_check_at DATETIME,
|
||||
lease_expires_at DATETIME,
|
||||
lease_token TEXT NOT NULL DEFAULT '',
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_pages_project_sources
|
||||
CREATE TABLE of_pages_project_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL,
|
||||
source_type TEXT NOT NULL DEFAULT '',
|
||||
remote_url TEXT NOT NULL DEFAULT '',
|
||||
allow_insecure INTEGER NOT NULL DEFAULT 0,
|
||||
github_repository TEXT NOT NULL DEFAULT '',
|
||||
release_selector TEXT NOT NULL DEFAULT '',
|
||||
release_tag TEXT NOT NULL DEFAULT '',
|
||||
asset_name TEXT NOT NULL DEFAULT '',
|
||||
auto_update_enabled INTEGER NOT NULL DEFAULT 0,
|
||||
check_interval_minutes INTEGER NOT NULL DEFAULT 0,
|
||||
config_version INTEGER NOT NULL DEFAULT 0,
|
||||
source_identity TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_pages_projects
|
||||
CREATE TABLE of_pages_projects (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
spa_fallback_enabled INTEGER NOT NULL DEFAULT 0,
|
||||
spa_fallback_path TEXT NOT NULL DEFAULT '/index.html',
|
||||
api_proxy_enabled INTEGER NOT NULL DEFAULT 0,
|
||||
api_proxy_path TEXT NOT NULL DEFAULT '',
|
||||
api_proxy_pass TEXT NOT NULL DEFAULT '',
|
||||
api_proxy_rewrite TEXT NOT NULL DEFAULT '',
|
||||
active_deployment_id INTEGER,
|
||||
root_dir TEXT NOT NULL DEFAULT '',
|
||||
entry_file TEXT NOT NULL DEFAULT 'index.html',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
, content_config_version INTEGER NOT NULL DEFAULT 0);
|
||||
-- table of_proxy_routes
|
||||
CREATE TABLE "of_proxy_routes" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
site_name TEXT NOT NULL DEFAULT '',
|
||||
origin_id INTEGER,
|
||||
origin_url TEXT NOT NULL,
|
||||
origin_host TEXT NOT NULL DEFAULT '',
|
||||
upstreams TEXT NOT NULL DEFAULT '[]',
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
enable_https INTEGER NOT NULL DEFAULT 0,
|
||||
redirect_http INTEGER NOT NULL DEFAULT 0,
|
||||
limit_conn_per_server INTEGER NOT NULL DEFAULT 0,
|
||||
limit_conn_per_ip INTEGER NOT NULL DEFAULT 0,
|
||||
limit_rate TEXT NOT NULL DEFAULT '',
|
||||
cache_enabled INTEGER NOT NULL DEFAULT 0,
|
||||
cache_policy TEXT NOT NULL DEFAULT '',
|
||||
cache_rules TEXT NOT NULL DEFAULT '[]',
|
||||
custom_headers TEXT NOT NULL DEFAULT '[]',
|
||||
basic_auth_enabled INTEGER NOT NULL DEFAULT 0,
|
||||
basic_auth_username TEXT NOT NULL DEFAULT '',
|
||||
basic_auth_password TEXT NOT NULL DEFAULT '',
|
||||
upstream_type TEXT NOT NULL DEFAULT 'direct',
|
||||
tunnel_node_id INTEGER,
|
||||
tunnel_target_addr TEXT NOT NULL DEFAULT '',
|
||||
tunnel_target_protocol TEXT NOT NULL DEFAULT '',
|
||||
pages_project_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
, limit_req_per_ip VARCHAR(32) NOT NULL DEFAULT '');
|
||||
-- table of_tls_certificates
|
||||
CREATE TABLE of_tls_certificates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
cert_pem TEXT NOT NULL,
|
||||
key_pem TEXT NOT NULL,
|
||||
not_before DATETIME,
|
||||
not_after DATETIME,
|
||||
remark TEXT NOT NULL DEFAULT '',
|
||||
provider TEXT NOT NULL DEFAULT 'upload',
|
||||
acme_account_id INTEGER NOT NULL DEFAULT 0,
|
||||
dns_account_id INTEGER NOT NULL DEFAULT 0,
|
||||
key_algorithm TEXT NOT NULL DEFAULT '',
|
||||
auto_renew INTEGER NOT NULL DEFAULT 0,
|
||||
primary_domain TEXT NOT NULL DEFAULT '',
|
||||
other_domains TEXT NOT NULL DEFAULT '',
|
||||
disable_cname INTEGER NOT NULL DEFAULT 0,
|
||||
skip_dns INTEGER NOT NULL DEFAULT 0,
|
||||
dns1 TEXT NOT NULL DEFAULT '',
|
||||
dns2 TEXT NOT NULL DEFAULT '',
|
||||
apply_status TEXT NOT NULL DEFAULT 'ready',
|
||||
apply_message TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_waf_ip_groups
|
||||
CREATE TABLE of_waf_ip_groups (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
ip_list TEXT NOT NULL DEFAULT '[]',
|
||||
auto_config TEXT NOT NULL DEFAULT '{}',
|
||||
ext_ips TEXT NOT NULL DEFAULT '[]',
|
||||
subscription_url TEXT NOT NULL DEFAULT '',
|
||||
subscription_format TEXT NOT NULL DEFAULT 'text',
|
||||
subscription_mapping_rule TEXT NOT NULL DEFAULT '',
|
||||
sync_interval_minutes INTEGER NOT NULL DEFAULT 1440,
|
||||
last_synced_at DATETIME,
|
||||
next_sync_at DATETIME,
|
||||
last_sync_status TEXT NOT NULL DEFAULT '',
|
||||
last_sync_message TEXT NOT NULL DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_waf_rule_group_bindings
|
||||
CREATE TABLE of_waf_rule_group_bindings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
rule_group_id INTEGER NOT NULL,
|
||||
proxy_route_id INTEGER NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
, sequence INTEGER NOT NULL DEFAULT 0);
|
||||
-- table of_waf_rule_groups
|
||||
CREATE TABLE of_waf_rule_groups (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
is_global BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
, graph TEXT NOT NULL DEFAULT '', revision INTEGER NOT NULL DEFAULT 1);
|
||||
-- table of_zone_domains
|
||||
CREATE TABLE of_zone_domains (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
zone_id INTEGER NOT NULL,
|
||||
proxy_route_id INTEGER,
|
||||
domain TEXT NOT NULL,
|
||||
cert_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table of_zones
|
||||
CREATE TABLE of_zones (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
domain TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_access_tokens
|
||||
CREATE TABLE "w_access_tokens" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id BIGINT NOT NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
token_hash VARCHAR(64) NOT NULL UNIQUE,
|
||||
masked_token VARCHAR(64) NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
, is_admin BOOLEAN NOT NULL DEFAULT 0);
|
||||
-- table w_auth_sources
|
||||
CREATE TABLE "w_auth_sources" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(80) NOT NULL UNIQUE,
|
||||
type VARCHAR(20) NOT NULL,
|
||||
display_name VARCHAR(100),
|
||||
is_active BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
client_id VARCHAR(255),
|
||||
client_secret VARCHAR(1024),
|
||||
openid_discovery_url VARCHAR(1024),
|
||||
scopes VARCHAR(255),
|
||||
icon_url VARCHAR(1024),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_external_accounts
|
||||
CREATE TABLE "w_external_accounts" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
auth_source_id BIGINT,
|
||||
user_id BIGINT NOT NULL,
|
||||
external_id VARCHAR(255) NOT NULL,
|
||||
external_username VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_push_channels
|
||||
CREATE TABLE w_push_channels (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'custom',
|
||||
token TEXT,
|
||||
url TEXT NOT NULL,
|
||||
other TEXT NOT NULL,
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL
|
||||
);
|
||||
-- table w_push_events
|
||||
CREATE TABLE w_push_events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_key TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
channels TEXT NOT NULL,
|
||||
targets TEXT NOT NULL,
|
||||
template TEXT NOT NULL,
|
||||
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL
|
||||
, task_type VARCHAR(100) NOT NULL DEFAULT '');
|
||||
-- table w_push_histories
|
||||
CREATE TABLE w_push_histories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
event_key TEXT NOT NULL,
|
||||
channel TEXT NOT NULL,
|
||||
target TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
level TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
error_msg TEXT,
|
||||
created_at DATETIME NOT NULL
|
||||
);
|
||||
-- table w_schedules
|
||||
CREATE TABLE "w_schedules" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
task_type VARCHAR(64) NOT NULL,
|
||||
cron VARCHAR(64) NOT NULL,
|
||||
payload TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_schedules_backup_of_database_auto_cleanup
|
||||
CREATE TABLE w_schedules_backup_of_database_auto_cleanup(
|
||||
id INT,
|
||||
name TEXT,
|
||||
task_type TEXT,
|
||||
cron TEXT,
|
||||
payload TEXT,
|
||||
is_active NUM,
|
||||
created_at NUM,
|
||||
updated_at NUM
|
||||
);
|
||||
-- table w_system_configs
|
||||
CREATE TABLE "w_system_configs" (
|
||||
key VARCHAR(64) PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
type VARCHAR(32) NOT NULL DEFAULT 'system',
|
||||
visibility INTEGER NOT NULL DEFAULT 0,
|
||||
description VARCHAR(255),
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_task_executions
|
||||
CREATE TABLE "w_task_executions" (
|
||||
id BIGINT PRIMARY KEY,
|
||||
task_id VARCHAR(128) NOT NULL UNIQUE,
|
||||
task_type VARCHAR(64) NOT NULL,
|
||||
task_name VARCHAR(128),
|
||||
status VARCHAR(32) NOT NULL,
|
||||
retryable BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
max_retry INTEGER NOT NULL DEFAULT 0,
|
||||
retry_count INTEGER NOT NULL DEFAULT 0,
|
||||
log TEXT,
|
||||
error_message TEXT,
|
||||
result TEXT,
|
||||
started_at DATETIME,
|
||||
finished_at DATETIME,
|
||||
duration BIGINT,
|
||||
payload TEXT,
|
||||
triggered_by VARCHAR(32) NOT NULL DEFAULT 'system',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_templates
|
||||
CREATE TABLE "w_templates" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key VARCHAR(80) NOT NULL UNIQUE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
type VARCHAR(20) NOT NULL DEFAULT 'email',
|
||||
subject VARCHAR(255),
|
||||
content TEXT NOT NULL,
|
||||
description VARCHAR(255),
|
||||
is_system BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_upload_stats
|
||||
CREATE TABLE w_upload_stats (
|
||||
dimension VARCHAR(32) NOT NULL,
|
||||
stat_key VARCHAR(64) NOT NULL DEFAULT '',
|
||||
file_count BIGINT NOT NULL DEFAULT 0,
|
||||
file_size BIGINT NOT NULL DEFAULT 0,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (dimension, stat_key)
|
||||
);
|
||||
-- table w_uploads
|
||||
CREATE TABLE "w_uploads" (
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
file_name VARCHAR(255) NOT NULL,
|
||||
file_path VARCHAR(500) NOT NULL,
|
||||
file_size BIGINT NOT NULL,
|
||||
mime_type VARCHAR(100) NOT NULL,
|
||||
extension VARCHAR(50) NOT NULL,
|
||||
hash VARCHAR(64),
|
||||
type VARCHAR(50) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL,
|
||||
metadata JSON,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
, access_mode INTEGER NOT NULL DEFAULT 0);
|
||||
-- table w_user_access_logs
|
||||
CREATE TABLE w_user_access_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL DEFAULT 0,
|
||||
path TEXT NOT NULL DEFAULT '',
|
||||
method TEXT NOT NULL DEFAULT '',
|
||||
ip TEXT NOT NULL DEFAULT '',
|
||||
user_agent TEXT NOT NULL DEFAULT '',
|
||||
headers TEXT NOT NULL DEFAULT '',
|
||||
status INTEGER NOT NULL DEFAULT 0,
|
||||
latency INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- table w_users
|
||||
CREATE TABLE "w_users" (
|
||||
id BIGINT PRIMARY KEY,
|
||||
username VARCHAR(64) UNIQUE,
|
||||
password VARCHAR(255),
|
||||
nickname VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
avatar_url VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
is_admin BOOLEAN DEFAULT FALSE,
|
||||
bio VARCHAR(500),
|
||||
phone VARCHAR(32),
|
||||
gender VARCHAR(16),
|
||||
website VARCHAR(255),
|
||||
location VARCHAR(255),
|
||||
last_login_at DATETIME,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
-- total objects (excl. bookkeeping): 130
|
||||
@@ -0,0 +1,77 @@
|
||||
0
|
||||
202606050001
|
||||
202606090001
|
||||
202606100001
|
||||
202606100002
|
||||
202606110001
|
||||
202606110002
|
||||
202606110003
|
||||
202606110004
|
||||
202606110005
|
||||
202606120001
|
||||
202606120002
|
||||
202606130001
|
||||
202606130002
|
||||
202606130003
|
||||
202606140001
|
||||
202606140003
|
||||
202606140004
|
||||
202606140005
|
||||
202606150001
|
||||
202606160001
|
||||
202606170001
|
||||
202606170002
|
||||
202606170003
|
||||
202606180001
|
||||
202606190001
|
||||
202606190002
|
||||
202606190003
|
||||
202606190004
|
||||
202606190005
|
||||
202606190006
|
||||
202606190007
|
||||
202606190008
|
||||
202606190009
|
||||
202606190010
|
||||
202606190011
|
||||
202606190012
|
||||
202606190013
|
||||
202606190014
|
||||
202606200001
|
||||
202606200002
|
||||
202606200003
|
||||
202606200004
|
||||
202606200005
|
||||
202606200006
|
||||
202606200007
|
||||
202606220001
|
||||
202606220002
|
||||
202606220003
|
||||
202606220004
|
||||
202606220005
|
||||
202606270001
|
||||
202606300001
|
||||
202607120001
|
||||
202607120002
|
||||
202607130001
|
||||
202607140001
|
||||
202607150001
|
||||
202607150002
|
||||
202607150003
|
||||
202607170001
|
||||
202607180001
|
||||
202607190001
|
||||
202607190002
|
||||
202607190003
|
||||
202607200001
|
||||
202608040001
|
||||
202608060001
|
||||
202608060002
|
||||
202608070001
|
||||
202608070002
|
||||
202608080001
|
||||
202608080002
|
||||
202608080003
|
||||
202608090001
|
||||
202608090002
|
||||
202608090003
|
||||
+324
-324
@@ -50,7 +50,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_plugins_server_cap.ChallengeResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_plugins_server_cap.RedeemResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4515,7 +4515,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.PagesDeploymentHashResponse"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.PagesDeploymentHashResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4619,7 +4619,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.PagesProjectLatestHashResponse"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.PagesProjectLatestHashResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14253,7 +14253,7 @@
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "用户名或密码错误、帐号已禁用等",
|
||||
"description": "用户名或密码错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.Any"
|
||||
}
|
||||
@@ -14590,6 +14590,316 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Wavelet_OpenFlare_plugins_server_cap.ChallengeResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"challenge": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "integer"
|
||||
},
|
||||
"d": {
|
||||
"type": "integer"
|
||||
},
|
||||
"s": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"expires": {
|
||||
"description": "ms timestamp",
|
||||
"type": "integer"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_plugins_server_cap.RedeemResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"expires": {
|
||||
"type": "integer"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_plugins_server_model_analytics.ClickHouseOperationalStats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active_parts": {
|
||||
"type": "integer"
|
||||
},
|
||||
"async_insert_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"async_insert_queue": {
|
||||
"type": "integer"
|
||||
},
|
||||
"batch_writers": {
|
||||
"description": "BatchWriters reports in-process queue depth/drops/flush errors for CH writers.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/analytics.BatchWriterStats"
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"type": "string"
|
||||
},
|
||||
"pending_mutations": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_rows": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.ActiveConfigMeta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checksum": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.BufferedObservabilityRecord": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_logs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeAccessLog"
|
||||
}
|
||||
},
|
||||
"captured_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"edge_health": {
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeEdgeHealth"
|
||||
},
|
||||
"host_metrics": {
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeMetricSnapshot"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.NodeAccessLog": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bytes_sent": {
|
||||
"description": "body bytes = 已提供数据",
|
||||
"type": "integer"
|
||||
},
|
||||
"cache_status": {
|
||||
"description": "$upstream_cache_status",
|
||||
"type": "string"
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"logged_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"remote_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"request_length": {
|
||||
"description": "接收数据",
|
||||
"type": "integer"
|
||||
},
|
||||
"request_time_ms": {
|
||||
"description": "optional",
|
||||
"type": "integer"
|
||||
},
|
||||
"status_code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"user_agent": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.NodeEdgeHealth": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"captured_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"connections": {
|
||||
"type": "integer"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.NodeHealthEvent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"event_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"severity": {
|
||||
"type": "string"
|
||||
},
|
||||
"triggered_at_unix": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.NodeMetricSnapshot": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"captured_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"cpu_usage_percent": {
|
||||
"type": "number"
|
||||
},
|
||||
"disk_read_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"disk_write_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_total_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_used_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"storage_total_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"storage_used_bytes": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.NodeSystemProfile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"architecture": {
|
||||
"type": "string"
|
||||
},
|
||||
"cpu_cores": {
|
||||
"type": "integer"
|
||||
},
|
||||
"cpu_model": {
|
||||
"type": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"type": "string"
|
||||
},
|
||||
"kernel_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"os_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"os_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"reported_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_disk_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_memory_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"uptime_seconds": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.PagesDeploymentHashResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deployment_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.PagesProjectLatestHashResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deployment_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"file_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"package_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"project_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wavelet_OpenFlare_share_protocol.WAFIPGroup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checksum": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ip_list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"agent.ActiveConfigMeta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -14679,20 +14989,20 @@
|
||||
"access_logs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeAccessLog"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeAccessLog"
|
||||
}
|
||||
},
|
||||
"buffered": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.BufferedObservabilityRecord"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.BufferedObservabilityRecord"
|
||||
}
|
||||
},
|
||||
"current_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"edge_health": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeEdgeHealth"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeEdgeHealth"
|
||||
},
|
||||
"ext_version": {
|
||||
"type": "string"
|
||||
@@ -14700,11 +15010,11 @@
|
||||
"health_events": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeHealthEvent"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeHealthEvent"
|
||||
}
|
||||
},
|
||||
"host_metrics": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeMetricSnapshot"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeMetricSnapshot"
|
||||
},
|
||||
"ip": {
|
||||
"type": "string"
|
||||
@@ -14725,7 +15035,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"profile": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeSystemProfile"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.NodeSystemProfile"
|
||||
},
|
||||
"schema_version": {
|
||||
"type": "integer"
|
||||
@@ -14844,7 +15154,7 @@
|
||||
"groups": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.WAFIPGroup"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.WAFIPGroup"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15669,7 +15979,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active_config": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.ActiveConfigMeta"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_share_protocol.ActiveConfigMeta"
|
||||
},
|
||||
"tunnel_settings": {
|
||||
"$ref": "#/definitions/protocol.RelaySettings"
|
||||
@@ -15699,316 +16009,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"challenge": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "integer"
|
||||
},
|
||||
"d": {
|
||||
"type": "integer"
|
||||
},
|
||||
"s": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"expires": {
|
||||
"description": "ms timestamp",
|
||||
"type": "integer"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"expires": {
|
||||
"type": "integer"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_internal_model_analytics.ClickHouseOperationalStats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active_parts": {
|
||||
"type": "integer"
|
||||
},
|
||||
"async_insert_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"async_insert_queue": {
|
||||
"type": "integer"
|
||||
},
|
||||
"batch_writers": {
|
||||
"description": "BatchWriters reports in-process queue depth/drops/flush errors for CH writers.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/analytics.BatchWriterStats"
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"type": "string"
|
||||
},
|
||||
"pending_mutations": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_rows": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.ActiveConfigMeta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checksum": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.BufferedObservabilityRecord": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_logs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeAccessLog"
|
||||
}
|
||||
},
|
||||
"captured_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"edge_health": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeEdgeHealth"
|
||||
},
|
||||
"host_metrics": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeMetricSnapshot"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.NodeAccessLog": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bytes_sent": {
|
||||
"description": "body bytes = 已提供数据",
|
||||
"type": "integer"
|
||||
},
|
||||
"cache_status": {
|
||||
"description": "$upstream_cache_status",
|
||||
"type": "string"
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"logged_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"remote_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"request_length": {
|
||||
"description": "接收数据",
|
||||
"type": "integer"
|
||||
},
|
||||
"request_time_ms": {
|
||||
"description": "optional",
|
||||
"type": "integer"
|
||||
},
|
||||
"status_code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"user_agent": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.NodeEdgeHealth": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"captured_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"connections": {
|
||||
"type": "integer"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.NodeHealthEvent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"event_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"severity": {
|
||||
"type": "string"
|
||||
},
|
||||
"triggered_at_unix": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.NodeMetricSnapshot": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"captured_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"cpu_usage_percent": {
|
||||
"type": "number"
|
||||
},
|
||||
"disk_read_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"disk_write_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_total_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"memory_used_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"storage_total_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"storage_used_bytes": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.NodeSystemProfile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"architecture": {
|
||||
"type": "string"
|
||||
},
|
||||
"cpu_cores": {
|
||||
"type": "integer"
|
||||
},
|
||||
"cpu_model": {
|
||||
"type": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"type": "string"
|
||||
},
|
||||
"kernel_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"os_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"os_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"reported_at_unix": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_disk_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_memory_bytes": {
|
||||
"type": "integer"
|
||||
},
|
||||
"uptime_seconds": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.PagesDeploymentHashResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deployment_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.PagesProjectLatestHashResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deployment_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"file_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"package_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"project_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_Rain-kl_Wavelet_pkg_protocol.WAFIPGroup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"checksum": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ip_list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"handler.batchDownloadRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -19787,7 +19787,7 @@
|
||||
}
|
||||
},
|
||||
"clickhouse": {
|
||||
"$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_model_analytics.ClickHouseOperationalStats"
|
||||
"$ref": "#/definitions/Wavelet_OpenFlare_plugins_server_model_analytics.ClickHouseOperationalStats"
|
||||
},
|
||||
"migration": {
|
||||
"description": "idle | migrating",
|
||||
|
||||
+219
-219
@@ -1,5 +1,210 @@
|
||||
basePath: /
|
||||
definitions:
|
||||
Wavelet_OpenFlare_plugins_server_cap.ChallengeResponse:
|
||||
properties:
|
||||
challenge:
|
||||
properties:
|
||||
c:
|
||||
type: integer
|
||||
d:
|
||||
type: integer
|
||||
s:
|
||||
type: integer
|
||||
type: object
|
||||
expires:
|
||||
description: ms timestamp
|
||||
type: integer
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
Wavelet_OpenFlare_plugins_server_cap.RedeemResponse:
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
expires:
|
||||
type: integer
|
||||
success:
|
||||
type: boolean
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
Wavelet_OpenFlare_plugins_server_model_analytics.ClickHouseOperationalStats:
|
||||
properties:
|
||||
active_parts:
|
||||
type: integer
|
||||
async_insert_bytes:
|
||||
type: integer
|
||||
async_insert_queue:
|
||||
type: integer
|
||||
batch_writers:
|
||||
description: BatchWriters reports in-process queue depth/drops/flush errors
|
||||
for CH writers.
|
||||
items:
|
||||
$ref: '#/definitions/analytics.BatchWriterStats'
|
||||
type: array
|
||||
database:
|
||||
type: string
|
||||
pending_mutations:
|
||||
type: integer
|
||||
total_rows:
|
||||
type: integer
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.ActiveConfigMeta:
|
||||
properties:
|
||||
checksum:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.BufferedObservabilityRecord:
|
||||
properties:
|
||||
access_logs:
|
||||
items:
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeAccessLog'
|
||||
type: array
|
||||
captured_at_unix:
|
||||
type: integer
|
||||
edge_health:
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeEdgeHealth'
|
||||
host_metrics:
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeMetricSnapshot'
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.NodeAccessLog:
|
||||
properties:
|
||||
bytes_sent:
|
||||
description: body bytes = 已提供数据
|
||||
type: integer
|
||||
cache_status:
|
||||
description: $upstream_cache_status
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
logged_at_unix:
|
||||
type: integer
|
||||
path:
|
||||
type: string
|
||||
remote_addr:
|
||||
type: string
|
||||
request_length:
|
||||
description: 接收数据
|
||||
type: integer
|
||||
request_time_ms:
|
||||
description: optional
|
||||
type: integer
|
||||
status_code:
|
||||
type: integer
|
||||
user_agent:
|
||||
type: string
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.NodeEdgeHealth:
|
||||
properties:
|
||||
captured_at_unix:
|
||||
type: integer
|
||||
connections:
|
||||
type: integer
|
||||
message:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.NodeHealthEvent:
|
||||
properties:
|
||||
event_type:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
metadata:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
severity:
|
||||
type: string
|
||||
triggered_at_unix:
|
||||
type: integer
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.NodeMetricSnapshot:
|
||||
properties:
|
||||
captured_at_unix:
|
||||
type: integer
|
||||
cpu_usage_percent:
|
||||
type: number
|
||||
disk_read_bytes:
|
||||
type: integer
|
||||
disk_write_bytes:
|
||||
type: integer
|
||||
memory_total_bytes:
|
||||
type: integer
|
||||
memory_used_bytes:
|
||||
type: integer
|
||||
storage_total_bytes:
|
||||
type: integer
|
||||
storage_used_bytes:
|
||||
type: integer
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.NodeSystemProfile:
|
||||
properties:
|
||||
architecture:
|
||||
type: string
|
||||
cpu_cores:
|
||||
type: integer
|
||||
cpu_model:
|
||||
type: string
|
||||
hostname:
|
||||
type: string
|
||||
kernel_version:
|
||||
type: string
|
||||
os_name:
|
||||
type: string
|
||||
os_version:
|
||||
type: string
|
||||
reported_at_unix:
|
||||
type: integer
|
||||
total_disk_bytes:
|
||||
type: integer
|
||||
total_memory_bytes:
|
||||
type: integer
|
||||
uptime_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.PagesDeploymentHashResponse:
|
||||
properties:
|
||||
deployment_id:
|
||||
type: integer
|
||||
hash:
|
||||
type: string
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.PagesProjectLatestHashResponse:
|
||||
properties:
|
||||
deployment_id:
|
||||
type: integer
|
||||
file_count:
|
||||
type: integer
|
||||
hash:
|
||||
type: string
|
||||
package_size:
|
||||
type: integer
|
||||
project_id:
|
||||
type: integer
|
||||
total_size:
|
||||
type: integer
|
||||
type: object
|
||||
Wavelet_OpenFlare_share_protocol.WAFIPGroup:
|
||||
properties:
|
||||
checksum:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
id:
|
||||
type: integer
|
||||
ip_list:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
agent.ActiveConfigMeta:
|
||||
properties:
|
||||
checksum:
|
||||
@@ -58,24 +263,24 @@ definitions:
|
||||
properties:
|
||||
access_logs:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeAccessLog'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeAccessLog'
|
||||
type: array
|
||||
buffered:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.BufferedObservabilityRecord'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.BufferedObservabilityRecord'
|
||||
type: array
|
||||
current_version:
|
||||
type: string
|
||||
edge_health:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeEdgeHealth'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeEdgeHealth'
|
||||
ext_version:
|
||||
type: string
|
||||
health_events:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeHealthEvent'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeHealthEvent'
|
||||
type: array
|
||||
host_metrics:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeMetricSnapshot'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeMetricSnapshot'
|
||||
ip:
|
||||
type: string
|
||||
last_error:
|
||||
@@ -89,7 +294,7 @@ definitions:
|
||||
openresty_status:
|
||||
type: string
|
||||
profile:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeSystemProfile'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.NodeSystemProfile'
|
||||
schema_version:
|
||||
type: integer
|
||||
version:
|
||||
@@ -166,7 +371,7 @@ definitions:
|
||||
properties:
|
||||
groups:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.WAFIPGroup'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.WAFIPGroup'
|
||||
type: array
|
||||
type: object
|
||||
analytics.BatchWriterStats:
|
||||
@@ -708,7 +913,7 @@ definitions:
|
||||
flared.HeartbeatResponse:
|
||||
properties:
|
||||
active_config:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.ActiveConfigMeta'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.ActiveConfigMeta'
|
||||
tunnel_settings:
|
||||
$ref: '#/definitions/protocol.RelaySettings'
|
||||
type: object
|
||||
@@ -727,211 +932,6 @@ definitions:
|
||||
version:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse:
|
||||
properties:
|
||||
challenge:
|
||||
properties:
|
||||
c:
|
||||
type: integer
|
||||
d:
|
||||
type: integer
|
||||
s:
|
||||
type: integer
|
||||
type: object
|
||||
expires:
|
||||
description: ms timestamp
|
||||
type: integer
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse:
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
expires:
|
||||
type: integer
|
||||
success:
|
||||
type: boolean
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_internal_model_analytics.ClickHouseOperationalStats:
|
||||
properties:
|
||||
active_parts:
|
||||
type: integer
|
||||
async_insert_bytes:
|
||||
type: integer
|
||||
async_insert_queue:
|
||||
type: integer
|
||||
batch_writers:
|
||||
description: BatchWriters reports in-process queue depth/drops/flush errors
|
||||
for CH writers.
|
||||
items:
|
||||
$ref: '#/definitions/analytics.BatchWriterStats'
|
||||
type: array
|
||||
database:
|
||||
type: string
|
||||
pending_mutations:
|
||||
type: integer
|
||||
total_rows:
|
||||
type: integer
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.ActiveConfigMeta:
|
||||
properties:
|
||||
checksum:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.BufferedObservabilityRecord:
|
||||
properties:
|
||||
access_logs:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeAccessLog'
|
||||
type: array
|
||||
captured_at_unix:
|
||||
type: integer
|
||||
edge_health:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeEdgeHealth'
|
||||
host_metrics:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.NodeMetricSnapshot'
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.NodeAccessLog:
|
||||
properties:
|
||||
bytes_sent:
|
||||
description: body bytes = 已提供数据
|
||||
type: integer
|
||||
cache_status:
|
||||
description: $upstream_cache_status
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
logged_at_unix:
|
||||
type: integer
|
||||
path:
|
||||
type: string
|
||||
remote_addr:
|
||||
type: string
|
||||
request_length:
|
||||
description: 接收数据
|
||||
type: integer
|
||||
request_time_ms:
|
||||
description: optional
|
||||
type: integer
|
||||
status_code:
|
||||
type: integer
|
||||
user_agent:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.NodeEdgeHealth:
|
||||
properties:
|
||||
captured_at_unix:
|
||||
type: integer
|
||||
connections:
|
||||
type: integer
|
||||
message:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.NodeHealthEvent:
|
||||
properties:
|
||||
event_type:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
metadata:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
severity:
|
||||
type: string
|
||||
triggered_at_unix:
|
||||
type: integer
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.NodeMetricSnapshot:
|
||||
properties:
|
||||
captured_at_unix:
|
||||
type: integer
|
||||
cpu_usage_percent:
|
||||
type: number
|
||||
disk_read_bytes:
|
||||
type: integer
|
||||
disk_write_bytes:
|
||||
type: integer
|
||||
memory_total_bytes:
|
||||
type: integer
|
||||
memory_used_bytes:
|
||||
type: integer
|
||||
storage_total_bytes:
|
||||
type: integer
|
||||
storage_used_bytes:
|
||||
type: integer
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.NodeSystemProfile:
|
||||
properties:
|
||||
architecture:
|
||||
type: string
|
||||
cpu_cores:
|
||||
type: integer
|
||||
cpu_model:
|
||||
type: string
|
||||
hostname:
|
||||
type: string
|
||||
kernel_version:
|
||||
type: string
|
||||
os_name:
|
||||
type: string
|
||||
os_version:
|
||||
type: string
|
||||
reported_at_unix:
|
||||
type: integer
|
||||
total_disk_bytes:
|
||||
type: integer
|
||||
total_memory_bytes:
|
||||
type: integer
|
||||
uptime_seconds:
|
||||
type: integer
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.PagesDeploymentHashResponse:
|
||||
properties:
|
||||
deployment_id:
|
||||
type: integer
|
||||
hash:
|
||||
type: string
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.PagesProjectLatestHashResponse:
|
||||
properties:
|
||||
deployment_id:
|
||||
type: integer
|
||||
file_count:
|
||||
type: integer
|
||||
hash:
|
||||
type: string
|
||||
package_size:
|
||||
type: integer
|
||||
project_id:
|
||||
type: integer
|
||||
total_size:
|
||||
type: integer
|
||||
type: object
|
||||
github_com_Rain-kl_Wavelet_pkg_protocol.WAFIPGroup:
|
||||
properties:
|
||||
checksum:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
id:
|
||||
type: integer
|
||||
ip_list:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
handler.batchDownloadRequest:
|
||||
properties:
|
||||
ids:
|
||||
@@ -3433,7 +3433,7 @@ definitions:
|
||||
type: string
|
||||
type: array
|
||||
clickhouse:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_model_analytics.ClickHouseOperationalStats'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_plugins_server_model_analytics.ClickHouseOperationalStats'
|
||||
migration:
|
||||
description: idle | migrating
|
||||
type: string
|
||||
@@ -4357,7 +4357,7 @@ paths:
|
||||
- $ref: '#/definitions/response.Any'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.ChallengeResponse'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_plugins_server_cap.ChallengeResponse'
|
||||
type: object
|
||||
"500":
|
||||
description: 内部服务错误
|
||||
@@ -4388,7 +4388,7 @@ paths:
|
||||
- $ref: '#/definitions/response.Any'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_plugins_server_cap.RedeemResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: 参数错误或核销失败
|
||||
@@ -7026,7 +7026,7 @@ paths:
|
||||
- $ref: '#/definitions/response.Any'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.PagesDeploymentHashResponse'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.PagesDeploymentHashResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: 参数错误
|
||||
@@ -7089,7 +7089,7 @@ paths:
|
||||
- $ref: '#/definitions/response.Any'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/github_com_Rain-kl_Wavelet_pkg_protocol.PagesProjectLatestHashResponse'
|
||||
$ref: '#/definitions/Wavelet_OpenFlare_share_protocol.PagesProjectLatestHashResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: 参数错误
|
||||
@@ -12869,7 +12869,7 @@ paths:
|
||||
$ref: '#/definitions/oauth.BasicUserInfo'
|
||||
type: object
|
||||
"400":
|
||||
description: 用户名或密码错误、帐号已禁用等
|
||||
description: 用户名或密码错误
|
||||
schema:
|
||||
$ref: '#/definitions/response.Any'
|
||||
"500":
|
||||
|
||||
Reference in New Issue
Block a user