feat(backend): 挂载 /v1 API + 实现 nodes/connect 端到端

- 新增 internal/dpcred 包,统一 DeriveHy2Password + DefaultFlow
  agentd 与 HTTP connect handler 共享同一实现
- 新增迁移 000011:nodes 表拆分 reality_prk 私钥 / reality_pbk 公钥
  reality_short_id;修正 handler_grpc.go 使用私钥字段
- 新增迁移 000012:connect_credentials 持久化凭证
  实现 CredentialsForNode 修复 agent 重连 resync 原先返回空的桩
- 扩展 NodeStore 接口:ListUp / EntitlementForUser /
  PersistCredential / DeleteCredential;同步 grpc_test.go mock
- 新增 httpapi/nodes.go:GET /nodes、POST /nodes/id/connect
  Hub.Push + PersistCredential + 渲染完整 sing-box client 配置 JSON
  POST /nodes/id/disconnect
- 新增 httpapi/account.go:GET /me、GET /plans、GET /notices
- 新增 httpapi/clientconfig.go:BuildClientConfig 服务端渲染
- 重写 cmd/server/main.go:手写 chi public/protected 分组
  nodes.Service/Hub 在 main 构造并共享;SMTPMailer/LogMailer

go build ./... && go vet ./... && go test ./... 全部通过

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-15 23:09:56 +08:00
parent b35bfe10dc
commit cadd527680
14 changed files with 1017 additions and 149 deletions
+11 -1
View File
@@ -106,9 +106,19 @@ func (h *Handler) Register(ctx context.Context, req *agentv1.RegisterRequest) (*
}
// Populate inbound configs from the nodes row.
if node.RealityPBK != "" {
// reality_prk is the PRIVATE key the agent's VLESS inbound needs;
// reality_pbk is the PUBLIC key sent to clients in the connect config.
if node.RealityPRK != "" {
snap.Reality = &agentv1.RealityInbound{
PrivateKey: node.RealityPRK,
ShortID: node.RealityShortID,
ServerName: node.RealitySNI,
}
} else if node.RealityPBK != "" {
// Fallback for nodes seeded before migration 000011: use pbk field.
snap.Reality = &agentv1.RealityInbound{
PrivateKey: node.RealityPBK,
ShortID: node.RealityShortID,
ServerName: node.RealitySNI,
}
}