admin
|
10cf36ecee
|
鉴权并入 Auth Broker:委派设备会话统一模型 + 四端迁移
后端(委托 Auth Broker,路径 A):
- 删自建鉴权(OIDC exchange / 自签会话 / step-up / shortcut / web_sessions / accounts),cdrop 不再存任何凭证;鉴权中间件改读边缘注入的 X-Auth-Subject/Scope/Meta/Name/Roles 头(dev 旁路保留);Claims 加 Tier() / Guest()
- internal/brokerclient:mint / revoke(带 X-Broker-App)/ refresh / ListSessions(R1 列举),直连内网、吊销幂等
统一会话模型“委派设备会话”(Delegated Device Sessions):
- 每个客户端(浏览器 / 桌面 / 扫码设备)=一条带 meta(device_id) + label 的 broker 机器会话;Broker 作设备会话唯一注册表(R1 按用户+app 列举 + R2 按 (user,app,meta) 幂等铸造),cdrop 退化为薄覆盖层、不再自存权威会话表
- 新增代铸端点 POST /api/auth/device-session:凭边缘已验明的 X-Auth-Subject 委托 broker 铸 / 轮换设备会话(meta=device_id、按调用方 tier 防越权、sameOrigin CSRF、per-IP 限流);R2 幂等保证同一 device_id 重登原地轮换、不堆重复设备
- 会话列表=R1 权威 + 叠加 type(本地缓存)/ online(Hub presence,按设备名)/ current(meta 匹配本请求 X-Auth-Meta)+ 过滤 meta=""(device-authorize 引导会话残留);devices 表降级为 type/presence 薄缓存(非会话权威),device_id 主键、upsert 按 user 限定
- 吊销按 device_id → 缓存优先 / R1 兜底解析 sid → broker 吊销 + X-Broker-App;扫码登录保留三密钥编排,collect 改委托 broker 铸 + 落缓存行
Web 前端:
- 登录走 broker 全局 SSO 代跳(/api/auth/login 302);bootstrap 经 /api/me 注入身份后代铸设备会话(稳定 device_id 存 localStorage、Web Locks 跨 tab 串行防重复铸造);refresh 走 /api/auth/refresh
- 设备管理按 device_id;改名=同 device_id 重代铸(R2 原地轮换换 label、不产生重复行);登录页反应式守卫修登录回环
- 去 OIDC PKCE / step-up(删 oauth.callback / stepUp)
桌面客户端(Wails):
- loopback PKCE(RFC 8252)改指 broker 设备授权流(/device/authorize + /device/token)拿引导令牌,再代铸出带 meta 的托管设备会话——与浏览器同模型、同管理、同吊销;身份取自代铸响应(修“显示名显示为 UUID”);refresh 保留显示名;稳定 device_id 入桌面配置
iOS 客户端(arch A,原生 SwiftUI + 离屏无头 WebView 引擎 + 原生↔JS 桥):
- 引擎 / 文件管理 / 设备管理 / 应用图标 / 本地化(此前实现,随本次落入版本库)
- 鉴权=引擎自刷(boot 注入 refresh_token)+ broker 轮换经 sessionRotated 回报原生更新 Keychain;去 cookie 同步;Session 加 refreshToken / deviceId
实时 / 健壮性:
- presence 走 Hub union(设备表行 ∪ 表外实时连接,按名去重、live-only 标在线)
- Hub 通道 close 一律在写锁内、非阻塞 send 一律在读锁内,消除 close-vs-send 闭通道 send panic(revoke 每次 Kick 后该路径变热)
配置 / 删旧栈:
- config 改 broker 接入(CDROP_BROKER_* / CDROP_PUBLIC_URL / 按档 TTL),prod 强校验 broker 配置 + PUBLIC_URL(CSRF Origin 守卫不失效)
- 删 auth.go / selftoken.go / shortcut.go / jwks.go + 三表(web_sessions / accounts / shortcut_tokens)及验证链;.env.example / compose.snippet.yaml / Caddyfile.snippet 更新为 broker 模型(人机分流 + 公开端点放行 + X-Auth-Meta 透传)
- 测试全重写:QR / 会话含 mock broker(R1 列举 + R2 幂等);hub 加 close-vs-send 并发回归;config 加 prod 必填校验
|
2026-06-26 22:10:19 +08:00 |
|
admin
|
90a3790a98
|
扫码登录:cdrop 自签会话原语 + 薄账户层 + 受限访客 + 2FA step-up
身份仍源自 OAuth provider(user_id = OIDC sub),cdrop 在其上自维护一薄层:
自签会话令牌 + accounts 表,并新增扫码快速登录。实施蓝本见 AUTH.md。
后端 · 自签会话原语
- web_sessions 加 kind/scope/granted_by 列(bootstrap 幂等迁移);既有 oidc
会话行为不变,新增 self(滑动续期)/ guest(受限·不续)两类
- cdrop 自签 HS256 会话 access token,密钥派生自 SESSION_SECRET,与落盘 AES、
shortcut HS256 三密钥域隔离;jwtauth.verifySelfToken 无状态校验、靠 typ 区分
- requireFullSession 守卫:guest 会话不得改账号 / 再批准设备 / 签长效 token
- /auth/refresh 按 kind 分流:self/guest 纯自签、不触 IdP
后端 · 扫码登录(internal/httpapi/qr.go)
- qr/start・status・request・approve・deny 五端点 + login_requests 表 + reaper
- 三密钥分离:QR 仅含批准信息,会话只投递给持私有 poll_secret 的原设备
(偷拍 QR 者无 poll_secret 领不到会话、未登录批不了准)
- 会话在新设备侧领取(cookie 不经手机)、单次消费、短 TTL
后端 · 薄账户层与 2FA step-up
- accounts 表(键 sub,不含任何凭证):exchange/refresh upsert match_key /
显示名 / 头像 / roles,供显示与未来管理员开启迁移标记时跨源关联
- step-up(默认关):开启后 qr/approve 要求新鲜 prompt=login 授权码,后端就地
换 id_token、JWKS 验签 + auth_time 窗口 + sub 匹配,provider 2FA 于此往返强制
前端(web/)
- 显码页 /link/new + 批准页 /link + net/qr.ts,对齐 Theme B、复用 AuthShell
与聚珍排版管线、零新全局样式
- step-up 再认证流:批准前跑 prompt=login PKCE,回调分叉(不消费一次性 code、
独立 state key)后带 step_up_code/verifier 调 approve
- 三语 i18n qr.*;新增 qrcode 依赖
修复 · clipboard sweeper(早已提交的损坏)
- ClearExpiredClipboards 因 clipboard.sql 全角注释触发 sqlc 1.31 多字节偏移
bug,生成 SQL 被截断为「UPDATE clipboard_state SET content =」,sweeper 运行
期报「incomplete input」、过期剪贴板内容从未清除(短 TTL 暴露保护失效)
- 注释改纯 ASCII 并加 bug 警告,重生成得完整 SQL;prod 已验证 sweeper 由 ERROR
转为正常清理(cleared count=1)
构建
- .dockerignore:排除本地 node_modules 等,避免宿主原生二进制污染镜像内 vite 构建
- Dockerfile.base:GOPROXY 改为可经 --build-arg 覆盖(默认仍官方代理,受限网络
构建时传区域镜像即可,仓库不固化区域值)
文档
- 新增 AUTH.md(账户与登录实施蓝本);README 特性;.env.example /
compose.snippet 增配置项(QR / 自签会话 TTL / step-up / match_claim)
测试
- 自签 token 密钥域隔离、扫码端到端(领取 / 单次 / poll_secret 校验 / deny /
step-up 门)、extractIdentity、web_sessions 升级迁移
|
2026-06-21 22:43:36 +08:00 |
|
admin
|
92a03aeafd
|
推送通知:Web Push(网页 / PWA)+ 桌面原生通知
页面 / PWA 关闭、或桌面窗口非前台时,收到文件、消息、传输完成 / 失败以系统通知提醒。
判定统一为「页面打开走应用内提示,否则系统通知」,三端各自落地;网页端的判定直接复用
Hub.SendTo 的投递结果,零额外状态。
- Web Push(VAPID,账号无关):服务端 internal/push.Sender 在事件未经 SSE 投递到目标
设备时(即该设备页面已关)发推送,文案按订阅 locale 在服务端渲染(中简 / 中繁 / 英)、
404 / 410 自动清理死订阅;新增 push_subscriptions 表(含 locale,主键为 endpoint 的
SHA-256 以幂等 upsert)+ /api/push/{vapid-key, subscribe POST/DELETE} 端点
- 事件挂接:transfer:incoming / message(离线返 202,文本随推送送达)/ transfer:state
DONE|FAILED,均未投递才推
- 配置 CDROP_VAPID_PUBLIC_KEY / CDROP_VAPID_PRIVATE_KEY(半对即拒启动,都空则推送惰性
关闭)+ just vapid-keygen 生成工具(cmd/vapidgen)
- 前端:service worker 加 push / notificationclick(仍不拦截 /api 与导航);net/push.ts
订阅管理 + push store slice + 设置页「推送通知」面板(仅浏览器 / PWA);登录后 resyncPush
把既有订阅重新登记到当前用户,换用户 / endpoint 轮换 / 切换语言皆自愈
- 桌面原生通知:platform/notify_{darwin,windows,other}.go + notify_darwin.m,仅窗口非
前台时弹原生通知(macOS UNUserNotificationCenter,未签名时安全空操作、待签名后显示;
Windows go-toast 即用);app.go ShowNotification 绑定,前端 notifyNativeIfBackground
复用 hub 事件分发 + 客户端本地化
- 文档:README / .env.example / compose 模板补 CDROP_VAPID_* 配置
注:sqlc v1.31.1 对 query 文件里的多字节字符会错位偏移、生成损坏 SQL,故 query 注释保持纯
ASCII(文件内留有警示)。
|
2026-06-18 16:56:47 +08:00 |
|
admin
|
e903b03afe
|
docs:补充浏览器免重登 + CDROP_SESSION_SECRET 配置
- README:已落地补「浏览器免重登 + PWA」一项;prod 配置清单新增
CDROP_SESSION_SECRET(prod 强制非空,缺则拒启动)
- .env.example、docker/compose.snippet.yaml:补 CDROP_SESSION_SECRET 模板项
|
2026-06-16 01:08:05 +08:00 |
|
admin
|
f21fa5b5e8
|
cdrop — 跨 OS 剪贴板与文件传输服务
Commilitia Drop:自托管的跨设备剪贴板同步与点对点文件传输。
- 后端 Go(chi / SQLite WAL / SSE Hub / WebRTC signaling + 状态机 / Relay ring buffer),编译进单个 distroless 镜像(前端 go:embed)。
- 前端 React + TanStack Router + Zustand,自实现 SSE + WebRTC P2P,NAT 受阻时回退服务端中继;聚珍(Juzhen)CJK 综合排版。
- 桌面端 Wails v2(macOS / Windows),瘦客户端复用 web。
- 鉴权 OIDC PKCE(自建 Casdoor 等),refresh_token 信封加密存系统密钥库;iOS Shortcut 用 HS256 scoped token。
架构文档与变更记录见 docs 分支(PROJECT_BRIEF / FRONTEND_DESIGN / CHANGELOG)。
本次为公开发布初始提交:完整开发历史(含部署细节)留存于私有归档,公开仓库自此干净起步。
|
2026-06-15 21:38:28 +08:00 |
|