docs:CHANGELOG 补 2026-06-16 浏览器免重登 + 2026-06-15 PWA / Safari 修复

- 浏览器免重登:HttpOnly cookie + 服务端 web_sessions 会话表 + refresh_token
  AES-256-GCM 落盘 + 7 天滑动失活 + 设备名随会话持久化 + striped 锁防多 tab
  并发 refresh;前端 store 移除 refreshToken 字段;prod 强制 CDROP_SESSION_SECRET(e51666c)
- PWA 安装支持 + Safari OAuth 回跳卡顿(改整页跳转)修复(5c28ddf / 7082ccc /
  af754dc / 8f550ad)
- HTML 与 md twin 同步,build.sh 重建 CHANGELOG.html
This commit is contained in:
2026-06-16 01:11:43 +08:00
parent 19f8f7588e
commit b414c57b6a
2 changed files with 89 additions and 8 deletions
+47 -6
View File
@@ -1,11 +1,11 @@
<!-- built with theme=dracula, mode=report, at=2026-06-14T13:40:18Z -->
<!-- built with theme=dracula, mode=report, at=2026-06-15T17:11:18Z -->
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>cdrop — Changelog</title>
<meta name="generated-at" content="2026-06-14">
<meta name="generated-at" content="2026-06-16">
<meta name="source" content="cdrop · docs branch">
<style>
/* ---------- Core tokens ----------
@@ -2522,7 +2522,7 @@ main > *:nth-child(n+6) { animation-delay: 0.46s; }
<div class="meta">
<h1>cdrop — Changelog</h1>
<p class="subtitle">时间倒序。细粒度迭代见 git 历史;本档只记录结构性 / 行为性变更与重要 fix。</p>
<p class="timestamp"><time>2026-06-14</time> · <span>docs branch</span></p>
<p class="timestamp"><time>2026-06-16</time> · <span>docs branch</span></p>
</div>
<div class="actions">
<button class="btn" type="button" data-action="export-md" title="Copy Markdown to clipboard">Copy MD</button>
@@ -2537,6 +2537,28 @@ main > *:nth-child(n+6) { animation-delay: 0.46s; }
<p class="lede">本 Changelog 自 2026-05-22 起以 HTML 格式维护。此前之变更可从 main 分支 <code>git log</code> 取得;下表为近期较显著之 commit。</p>
<h2>2026-06-16 — 浏览器免重登 + 设备名持久化</h2>
<p>浏览器端不再每次重启都要重新登录;长寿命 refresh_token 从此完全不进 JS,改由服务端 HttpOnly cookie 会话持有。对长寿命凭据而言比原先(refresh_token 在 JS 内存、开页期 XSS 可读)严格更安全。</p>
<ul>
<li><strong>服务端会话表 + cookie</strong>:新增 <code>web_sessions</code> 表(sqlc)。<code>/auth/exchange</code> 换完 token 后建会话并下发 cookie<code>HttpOnly; Secure; SameSite=Lax; Path=/api/auth</code>),响应体不再回传 refresh_tokenrefresh_token 以 AES-256-GCM 落盘(密钥取自 <code>CDROP_SESSION_SECRET</code>,在 env、不在库内),cookie 只放不透明随机串、表 id 存其 SHA-256 —— DB 单独泄露既换不出可用 cookie、也解不出 token</li>
<li><strong>开机静默免重登</strong><code>/auth/refresh</code> 改为 cookie 驱动(7 天滑动失活)—— 这条同时就是开机静默免重登路径,前端首屏渲染前 <code>bootstrapAuth</code> 用 cookie 续期,命中直接进已登录态、避免登录页闪现;新增 <code>/auth/logout</code>(删会话 + 清 cookie)、<code>/auth/device</code>(写设备名入会话)</li>
<li><strong>设备名持久化</strong>:设备名随会话存,开机 refresh 带回前端,抗 iOS PWA 存储清除 —— localStorage 被驱逐也能恢复,不再误跳设置页</li>
<li><strong>多 tab 并发 refresh 防护</strong>:同一用户多 tab 共享一个 cookie → 一个 refresh_token,加 striped per-session 锁串行化并发 refresh,防一次性 refresh_token 被花两次而把用户从所有 tab 一起登出</li>
<li><strong>凭据面收紧</strong>:前端 store 彻底移除 <code>refreshToken</code> 字段,浏览器侧长寿命凭据不再触及 JS。CSRF 由 SameSite=Lax + Origin 校验双保险。桌面端不受影响(自有 loopback flow + 系统密钥库,不碰这两端点)</li>
<li><strong>部署要求</strong>prod 须设 <code>CDROP_SESSION_SECRET</code>(任意长度高熵串,内部 SHA-256 派生 AES-256 密钥),缺则拒启动</li>
<li>commit <code>e51666c</code></li>
</ul>
<h2>2026-06-15 — PWA 安装支持 + Safari OAuth 回跳卡顿修复</h2>
<ul>
<li><strong>PWA 安装支持</strong>:web 可「添加到主屏幕」独立启动(manifest + iOS meta + 同源静态壳 service worker)。SW 绝不拦截 <code>/api</code>(SSE / 剪贴板 / 中继需活连接)、亦不拦导航;PKCE verifier 改 <code>localStorage</code>,使独立 PWA 在 OAuth 回跳重启上下文后仍能完成登录。面向用户短名统一小写 <code>cdrop</code></li>
<li><strong>Safari OAuth 回跳卡顿修复</strong>Safari / iOS PWA 从 IdP 回跳登录后,<code>setup.js</code> 与头像约 2 分钟拿不到连接(Chrome 正常)。根因是 <code>oauth.callback</code> 登录成功后用路由软导航,复用了 OAuth 流程遗留的 HTTP 连接,这些连接在 Safari 下卡死后续资源请求;改为整页跳转(<code>window.location.replace</code>)拿全新连接绕开。曾误判 service worker / h3 为主因,均已排除</li>
<li>commit <code>5c28ddf</code>PWA 安装)/ <code>7082ccc</code>(短名)/ <code>af754dc</code> · <code>8f550ad</code>Safari 修复)</li>
</ul>
<h2>2026-06-14 — 安全加固:中继会话防耗尽 + 令牌入系统密钥库 + 鉴权 / 限流多项收紧</h2>
<p>多 agent 安全审计后的一轮加固,按信任模型(信任账号所有者 + 服务端;不信任跨用户 / 网络 hop peer / 本机其他软件)逐项收紧。</p>
@@ -2630,6 +2652,24 @@ main > *:nth-child(n+6) { animation-delay: 0.46s; }
时间倒序。细粒度迭代见 git 历史;本档只记录结构性 / 行为性变更与重要 fix。
## 2026-06-16 — 浏览器免重登 + 设备名持久化
浏览器端不再每次重启都要重新登录;长寿命 refresh_token 完全不进 JS,改由服务端 HttpOnly cookie 会话持有(比原先 refresh_token 在 JS 内存严格更安全)。
- **服务端会话表 + cookie**:新增 `web_sessions` 表(sqlc)。`/auth/exchange` 建会话并下发 `HttpOnly; Secure; SameSite=Lax; Path=/api/auth` cookie,响应体不再回传 refresh_tokenrefresh_token 以 AES-256-GCM 落盘(密钥 `CDROP_SESSION_SECRET`,在 env、不在库内),cookie 只放不透明随机串、表 id 存其 SHA-256 —— DB 单独泄露既换不出可用 cookie、也解不出 token
- **开机静默免重登**`/auth/refresh` 改 cookie 驱动(7 天滑动失活),前端首屏前 `bootstrapAuth` 续期、命中直接进已登录态;新增 `/auth/logout`、`/auth/device`(写设备名入会话)
- **设备名持久化**:设备名随会话存,开机 refresh 带回前端,抗 iOS PWA 存储清除(localStorage 被驱逐也能恢复、不再误跳设置页)
- **多 tab 并发 refresh 防护**:多 tab 共享一个 cookie → 一个 refresh_tokenstriped per-session 锁串行化并发 refresh,防一次性 token 被花两次而全端登出
- **凭据面收紧**store 移除 `refreshToken` 字段(浏览器侧长寿命凭据不再触及 JS);CSRF 由 SameSite=Lax + Origin 校验双保险。桌面端不受影响
- **部署要求**prod 须设 `CDROP_SESSION_SECRET`(任意长度高熵串),缺则拒启动
- commit `e51666c`
## 2026-06-15 — PWA 安装支持 + Safari OAuth 回跳卡顿修复
- **PWA 安装支持**:web 可「添加到主屏幕」独立启动(manifest + iOS meta + 同源静态壳 SW)。SW 绝不拦截 `/api`、亦不拦导航;PKCE verifier 改 `localStorage`,使独立 PWA 在 OAuth 回跳重启上下文后仍能完成登录。短名统一小写 `cdrop`
- **Safari OAuth 回跳卡顿修复**Safari / iOS PWA 回跳登录后 `setup.js` 与头像约 2 分钟拿不到连接(Chrome 正常)。根因是 `oauth.callback` 成功后路由软导航复用了 OAuth 流程遗留的 HTTP 连接、在 Safari 下卡死后续资源;改为整页跳转(`window.location.replace`)拿全新连接绕开
- commit `5c28ddf`PWA/ `7082ccc`(短名)/ `af754dc` · `8f550ad`Safari 修复)
## 2026-06-14 — 安全加固:中继会话防耗尽 + 令牌入系统密钥库 + 鉴权 / 限流多项收紧
多 agent 安全审计后的一轮加固,按信任模型(信任账号所有者 + 服务端;不信任跨用户 / 网络 hop peer / 本机其他软件)逐项收紧。
@@ -5018,9 +5058,10 @@ window.__JUZHEN_PUNCT__="quanjiao";window.__JUZHEN_JUSTIFY_ATOMS__=true;window._
renderMath();
wrapFlexTitleText();
/* 一般模式於 init 立即排版。__JUZHEN_DEFER__academic 由 build.sh 設)令此處
跳過,改由該模式 behavior.js Paged.js preview() 完成後對成品頁呼叫
__juzhenRun__——關鍵:Paged.js chunker 對 inline-block 原子量測失準(分頁前
排版會致窄欄散架),故先以純文字分頁、再於定版頁上加排版原子。 */
跳過,改由該模式 behavior.js 在編號/目錄/正文標記完成後、Paged.js preview()
**之前**手動呼叫 __juzhenRun__——使 Paged.js 直接以聚珍後的最終幾何分頁(每頁
自然填滿、末行齊滿、無需分頁後斷縫修復)。整頁寬單欄下 chunker 正確量度聚珍
inline-block 原子,無散架。 */
if (!window.__JUZHEN_DEFER__) { runJuzhen(); }
/* ========== Feature: code-block — behavior =================================
+42 -2
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>cdrop — Changelog</title>
<meta name="generated-at" content="2026-06-14">
<meta name="generated-at" content="2026-06-16">
<meta name="source" content="cdrop · docs branch">
<!-- RUNTIME_CSS -->
</head>
@@ -14,7 +14,7 @@
<div class="meta">
<h1>cdrop — Changelog</h1>
<p class="subtitle">时间倒序。细粒度迭代见 git 历史;本档只记录结构性 / 行为性变更与重要 fix。</p>
<p class="timestamp"><time>2026-06-14</time> · <span>docs branch</span></p>
<p class="timestamp"><time>2026-06-16</time> · <span>docs branch</span></p>
</div>
<div class="actions">
<!-- ACTIONS -->
@@ -25,6 +25,28 @@
<p class="lede">本 Changelog 自 2026-05-22 起以 HTML 格式维护。此前之变更可从 main 分支 <code>git log</code> 取得;下表为近期较显著之 commit。</p>
<h2>2026-06-16 — 浏览器免重登 + 设备名持久化</h2>
<p>浏览器端不再每次重启都要重新登录;长寿命 refresh_token 从此完全不进 JS,改由服务端 HttpOnly cookie 会话持有。对长寿命凭据而言比原先(refresh_token 在 JS 内存、开页期 XSS 可读)严格更安全。</p>
<ul>
<li><strong>服务端会话表 + cookie</strong>:新增 <code>web_sessions</code> 表(sqlc)。<code>/auth/exchange</code> 换完 token 后建会话并下发 cookie<code>HttpOnly; Secure; SameSite=Lax; Path=/api/auth</code>),响应体不再回传 refresh_tokenrefresh_token 以 AES-256-GCM 落盘(密钥取自 <code>CDROP_SESSION_SECRET</code>,在 env、不在库内),cookie 只放不透明随机串、表 id 存其 SHA-256 —— DB 单独泄露既换不出可用 cookie、也解不出 token</li>
<li><strong>开机静默免重登</strong><code>/auth/refresh</code> 改为 cookie 驱动(7 天滑动失活)—— 这条同时就是开机静默免重登路径,前端首屏渲染前 <code>bootstrapAuth</code> 用 cookie 续期,命中直接进已登录态、避免登录页闪现;新增 <code>/auth/logout</code>(删会话 + 清 cookie)、<code>/auth/device</code>(写设备名入会话)</li>
<li><strong>设备名持久化</strong>:设备名随会话存,开机 refresh 带回前端,抗 iOS PWA 存储清除 —— localStorage 被驱逐也能恢复,不再误跳设置页</li>
<li><strong>多 tab 并发 refresh 防护</strong>:同一用户多 tab 共享一个 cookie → 一个 refresh_token,加 striped per-session 锁串行化并发 refresh,防一次性 refresh_token 被花两次而把用户从所有 tab 一起登出</li>
<li><strong>凭据面收紧</strong>:前端 store 彻底移除 <code>refreshToken</code> 字段,浏览器侧长寿命凭据不再触及 JS。CSRF 由 SameSite=Lax + Origin 校验双保险。桌面端不受影响(自有 loopback flow + 系统密钥库,不碰这两端点)</li>
<li><strong>部署要求</strong>prod 须设 <code>CDROP_SESSION_SECRET</code>(任意长度高熵串,内部 SHA-256 派生 AES-256 密钥),缺则拒启动</li>
<li>commit <code>e51666c</code></li>
</ul>
<h2>2026-06-15 — PWA 安装支持 + Safari OAuth 回跳卡顿修复</h2>
<ul>
<li><strong>PWA 安装支持</strong>:web 可「添加到主屏幕」独立启动(manifest + iOS meta + 同源静态壳 service worker)。SW 绝不拦截 <code>/api</code>(SSE / 剪贴板 / 中继需活连接)、亦不拦导航;PKCE verifier 改 <code>localStorage</code>,使独立 PWA 在 OAuth 回跳重启上下文后仍能完成登录。面向用户短名统一小写 <code>cdrop</code></li>
<li><strong>Safari OAuth 回跳卡顿修复</strong>Safari / iOS PWA 从 IdP 回跳登录后,<code>setup.js</code> 与头像约 2 分钟拿不到连接(Chrome 正常)。根因是 <code>oauth.callback</code> 登录成功后用路由软导航,复用了 OAuth 流程遗留的 HTTP 连接,这些连接在 Safari 下卡死后续资源请求;改为整页跳转(<code>window.location.replace</code>)拿全新连接绕开。曾误判 service worker / h3 为主因,均已排除</li>
<li>commit <code>5c28ddf</code>PWA 安装)/ <code>7082ccc</code>(短名)/ <code>af754dc</code> · <code>8f550ad</code>Safari 修复)</li>
</ul>
<h2>2026-06-14 — 安全加固:中继会话防耗尽 + 令牌入系统密钥库 + 鉴权 / 限流多项收紧</h2>
<p>多 agent 安全审计后的一轮加固,按信任模型(信任账号所有者 + 服务端;不信任跨用户 / 网络 hop peer / 本机其他软件)逐项收紧。</p>
@@ -102,6 +124,24 @@
时间倒序细粒度迭代见 git 历史本档只记录结构性 / 行为性变更与重要 fix
## 2026-06-16 浏览器免重登 + 设备名持久化
浏览器端不再每次重启都要重新登录长寿命 refresh_token 完全不进 JS改由服务端 HttpOnly cookie 会话持有比原先 refresh_token JS 内存严格更安全
- **服务端会话表 + cookie**新增 `web_sessions` sqlc`/auth/exchange` 建会话并下发 `HttpOnly; Secure; SameSite=Lax; Path=/api/auth` cookie响应体不再回传 refresh_tokenrefresh_token AES-256-GCM 落盘密钥 `CDROP_SESSION_SECRET` env不在库内cookie 只放不透明随机串 id 存其 SHA-256 DB 单独泄露既换不出可用 cookie也解不出 token
- **开机静默免重登**`/auth/refresh` cookie 驱动7 天滑动失活前端首屏前 `bootstrapAuth` 续期命中直接进已登录态新增 `/auth/logout``/auth/device`写设备名入会话
- **设备名持久化**设备名随会话存开机 refresh 带回前端 iOS PWA 存储清除localStorage 被驱逐也能恢复不再误跳设置页
- ** tab 并发 refresh 防护** tab 共享一个 cookie 一个 refresh_tokenstriped per-session 锁串行化并发 refresh防一次性 token 被花两次而全端登出
- **凭据面收紧**store 移除 `refreshToken` 字段浏览器侧长寿命凭据不再触及 JSCSRF SameSite=Lax + Origin 校验双保险桌面端不受影响
- **部署要求**prod 须设 `CDROP_SESSION_SECRET`任意长度高熵串缺则拒启动
- commit `e51666c`
## 2026-06-15 PWA 安装支持 + Safari OAuth 回跳卡顿修复
- **PWA 安装支持**web 添加到主屏幕独立启动manifest + iOS meta + 同源静态壳 SWSW 绝不拦截 `/api`亦不拦导航PKCE verifier `localStorage`使独立 PWA OAuth 回跳重启上下文后仍能完成登录短名统一小写 `cdrop`
- **Safari OAuth 回跳卡顿修复**Safari / iOS PWA 回跳登录后 `setup.js` 与头像约 2 分钟拿不到连接Chrome 正常根因是 `oauth.callback` 成功后路由软导航复用了 OAuth 流程遗留的 HTTP 连接 Safari 下卡死后续资源改为整页跳转`window.location.replace`拿全新连接绕开
- commit `5c28ddf`PWA/ `7082ccc`短名/ `af754dc` · `8f550ad`Safari 修复
## 2026-06-14 安全加固中继会话防耗尽 + 令牌入系统密钥库 + 鉴权 / 限流多项收紧
agent 安全审计后的一轮加固按信任模型信任账号所有者 + 服务端不信任跨用户 / 网络 hop peer / 本机其他软件逐项收紧