news 2026/9/7 2:50:58

codegraph 遥测仪表盘:基于 Cloudflare Worker 与 D1 的密码门禁式数据看板

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
codegraph 遥测仪表盘:基于 Cloudflare Worker 与 D1 的密码门禁式数据看板

codegraph 遥测仪表盘:基于 Cloudflare Worker 与 D1 的密码门禁式数据看板

【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph

codegraph 是一个预索引代码知识图谱工具,会自动在代码变更时同步更新,供 Claude Code、Codex、Gemini、Cursor 等 AI 编程助手以极少 token 调用本地工具。本文聚焦于 telemetry-dashboard —— codegraph 匿名遥测系统的只读展示层,它部署在stats.getcodegraph.com,将 telemetry-worker 写入 D1 的使用事件转换为图表。读完后,你将了解一个仅用两个 secret、一个 HMAC 签名 Cookie 即可实现"最简但安全"的密码门禁机制如何落地到生产,以及一套基于 Cloudflare Worker + D1 的零构建数据看板在 API 设计、本地种子测试与颜色可访问性上的完整工程实践。


1. 定位:telemetry 系统的只读展示层

codegraph 的遥测由两个 Worker 协作完成:

  • 写入方telemetry-worker:接收匿名使用事件,写入 Cloudflare D1 数据库,并运行 cron 做每日聚合(rollup)。
  • 展示方telemetry-dashboard(本文主体):只读 D1,将数据渲染为图表,供两个维护者在stats.getcodegraph.com上查看。

两个 Worker 都放在公开仓库中,原因相同:触碰遥测的代码,应当对采集它的用户开放阅读。telemetry-dashboard/README.md 中明确写道,目录内不含任何秘密——密码和 Cookie 签名密钥是部署 secret,D1 数据库 ID 是标识符而非凭据。

D1 绑定在 wrangler.jsonc 中以只读方式声明:

// wrangler.jsonc — D1 绑定(只读,迁移归属 telemetry-worker) "d1_databases": [ { "binding": "DB", "database_name": "codegraph-telemetry", "database_id": "5ed36dfb-d2d7-4e35-9e63-a1b99d0b1ed3" } ]

迁移由 telemetry-worker/migrations/ 负责,本 Worker 不执行任何 DDL。


2. 路由门禁:deny-by-default 与run_worker_first

整个仪表盘的安全基础来自 wrangler.jsonc 中的这一行:

"assets": { "directory": "./public", "binding": "ASSETS", "run_worker_first": true, "html_handling": "auto-trailing-slash", "not_found_handling": "none" }

wrangler.jsonc 中的注释直接点明:run_worker_first是"承重墙"。若为false,Cloudflare 会在 Worker 执行之前直接返回匹配的静态文件,这意味着任何人都可以通过猜文件名拿到仪表盘 HTML。设为true后,每一个请求都会先进入 src/index.ts 的主fetch处理器,只有认证通过才会代理到env.ASSETS

README 中的路由表完整列出了哪些路径对谁开放:

路由认证说明
GET /login公开密码表单。已登录则 302 到/
POST /login公开按 IP 限流;成功后写入会话 Cookie
POST /logout公开清除 Cookie
GET /robots.txt公开Disallow: /
GET /api/*需要JSON;无会话时返回401
其他所有路由需要静态资产(来自public/);无会话时 302 到/login

telemetry-dashboard/README.md 特别指出,登录页public/提供,而是由 Worker 内联渲染(见 src/login-page.ts),这样静态资产目录不需要做任何"这个文件是否公开"的判断。

src/index.ts 的主fetch处理器实现了完整的拒绝默认(deny-by-default)路由表:

// src/index.ts L236–L273(核心路由) if (isRead && url.pathname === '/robots.txt') return new Response(ROBOTS_TXT, ...); if (url.pathname === '/login') { if (isRead) return await handleLoginPage(env, request, url); if (method === 'POST') return await handleLoginSubmit(env, request); return new Response('method not allowed\n', { status: 405, ... }); } if (url.pathname === '/logout') { if (method !== 'POST') return new Response('method not allowed\n', { status: 405, ... }); if (!isSameOriginPost(request)) return new Response('bad request\n', { status: 400 }); return redirect('/login', { headers: { 'set-cookie': clearedSessionCookie() } }); } // 此后一切需要会话 const isApi = url.pathname === '/api' || url.pathname.startsWith('/api/'); if (!(await hasValidSession(env, request))) { return isApi ? json({ error: 'unauthorized' }, { status: 401 }) : loginRedirect(url); }

静态资产经过认证后返回时还会额外注入cache-control: private, no-cachevary: cookie,确保登录后的页面永远不落入共享缓存(src/index.ts L220–L227)。


3. 读 API:全量端点参考

src/api.ts 是仪表盘唯一的读 API 实现,约 800 行,涵盖 8 个端点。每个端点都遵循以下通用规则(源自 README 与 src/api.ts):

  • 只读 GET,会话门控
  • 统一以?from=YYYY-MM-DD&to=YYYY-MM-DD(含端点,UTC 日)为范围;超过 366 天的范围会被截断并在响应的range.clamped字段中标注
  • 响应为 Chart.js 格式(labels[] + datasets[]),并附带rows[]供"显示数字"表格使用
  • 非法输入返回400+ 消息,绝不猜测
  • 图表数据带Cache-Control: private, max-age=300

telemetry-dashboard/README.md 的端点表如下,这里逐行对照 src/api.ts 的常量加以说明:

端点回答什么源码常量
/api/meta数据实际存在的日期范围;前端以latest_day为锚,避免图表终止于尚未写入 rollup 的那天MAX_RANGE_DAYS = 366,RETENTION_DAYS = 14(src/api.ts L26, L34)
/api/summary大号数字:生产用户、活跃机器、新机器、安装/卸载、索引运行次数、工具调用次数
/api/timeseries?metric=日粒度时间序列,支持installs_uninstalls/new_installs/production_users/indexing_activity/tool_calls/duration_bucketsSERIES记录(src/api.ts L324-L368)
/api/breakdown?dim=维度分布:osarchcodegraph_versionnode_majorlanguagefile_count_bucketduration_buckettargetscopekindnameclient_namename_error;可选&event=&metric=count\|machines&limit=DIMS记录(src/api.ts L160-L184);DEFAULT_BREAKDOWN_LIMIT = 12MAX_BREAKDOWN_LIMIT = 50
/api/activation?window=7安装 → 首次索引漏斗 + 每日比率DEFAULT_ACTIVATION_WINDOW = 7MAX_ACTIVATION_WINDOW = 30(src/api.ts L36-L37)
/api/retentionDay 0–14 队列曲线(范围内首次出现的机器)RETENTION_DAYS = 14(src/api.ts L34)
/api/health存活检查 + 最新事件/rollup 日;不缓存
/api/session返回{ authenticated: true },前端用于检测是否已登录

3.1 范围解析:默认值与截断

parseRange 函数定义了范围解析的完整规则:

// src/api.ts L25–L27 const MAX_RANGE_DAYS = 366; const DEFAULT_RANGE_DAYS = 30; function parseRange(url: URL): Range | ApiResult { const rawTo = url.searchParams.get('to'); const rawFrom = url.searchParams.get('from'); if (rawTo !== null && !isValidDay(rawTo)) return fail('to must be YYYY-MM-DD'); if (rawFrom !== null && !isValidDay(rawFrom)) return fail('from must be YYYY-MM-DD'); const to = rawTo ?? utcDay(Date.now()); const from = rawFrom ?? addDays(to, -(DEFAULT_RANGE_DAYS - 1)); if (from > to) return fail('from must not be after to'); const requested = daysApart(from, to) + 1; const clamped = requested > MAX_RANGE_DAYS; return { from: clamped ? addDays(to, -(MAX_RANGE_DAYS - 1)) : from, to, days: clamped ? MAX_RANGE_DAYS : requested, clamped, }; }
  • 不传from/to时默认最近 30 天(以今天为终点)
  • 超过 366 天时,from向前移动至 366 天前的位置,并在响应中设置clamped: true
  • 日期格式严格校验为YYYY-MM-DD,且经过Date.parse回环验证,2026-02-31这类不存在的日期会被拒绝(src/api.ts L69–L74)

3.2 时间序列:SERIES注册表

src/api.ts L324–L368 定义了一个SERIES记录,每个条目包含标题、系列标签和 SQL。所有固定时间序列都读取 rollup 表(daily_event_countsdaily_machinesmachine_first_seen),保证即使原始事件已被清除,图表依然正确。

duration_buckets是唯一一个数据驱动的系列(src/api.ts L414–L457):它按duration_bucket维度展开,每条线对应一个时长桶,按固定桶顺序排列。固定桶['<10s', '10-60s', '1-5m', '5m+']始终出现在响应中——空桶显示为零,防止序数色阶被悄悄重编号。

3.3 维度分布:DIMS注册表与"Other"折叠

src/api.ts L160–L184 的DIMS记录定义了 13 个合法维度。README 指出?dim=不在其中的值会返回400,这防止了调用者通过dim参数"设计自己的 SQL 问题"。

对于排序为value_desc的维度,超过limit(默认 12)的值会被折叠进一个"Other"条目,而非截断——截断会悄悄改变面板总量含义。

// src/api.ts L548–L559("Other" 折叠逻辑) if (sorted.length > limit) { const head = sorted.slice(0, limit); const tail = sorted.slice(limit); ordered = [ ...head, { value: 'Other', count: tail.reduce((n, r) => n + r.count, 0), machines: tail.reduce((n, r) => n + r.machines, 0), }, ]; truncated = true; }

3.4 激活漏斗:唯一读取原始事件的端点

README 和 src/api.ts L589–L685 都明确说明,/api/activation是唯一读取原始events表的端点,原因是"这台机器是否运行过索引"不是日粒度聚合——它需要按机器做LEFT JOIN。因此它的可见范围受 ingest worker 的保留窗口限制,响应中的raw_events_from字段告诉调用者原始数据实际从哪天开始,UI 会如实说明,而非画出一条"看起来像转化率下降"的悬崖线。

队列键是machine_first_seen而非 install 事件:重新安装不会让机器重新进入漏斗,这就是为什么它衡量的是转化率而非安装事件比。

3.5 两个容易被误读的数字

README 专门设了一节来解释这两个概念,src/api.ts 的注释同样强调了它们:

① 机器日,而非用户。daily_dim_counts.machines是日粒度的,跨范围求和得到的是"机器日"而非独立机器数——一台机器在 10 天中活跃会被计 10 次。范围级的独立计数从 rollup 中根本不可恢复(需要原始事件,而已清除),因此面板将"机器日"标得清清楚楚,且只用于"占比"类型面板,那里这个区别不影响形状。内部max(machines)是另一层诚实:同一台机器一天内触发 install + index + usage_rollup,每种事件都带os维度,直接求和machines会三重计数;取当日单事件最大计数是 rollup 能给出的最接近下界。

② 近期队列尚未完成转化。昨天安装的机器还没有 7 天来运行索引,激活曲线的尾部是下限而非结果。API 用complete: falseincomplete_from标记这些天,面板会说明这一点,而非画出一条悬崖并称之为转化率下降。留存曲线做同样的事:Dayk只在实际有k天可回归的机器上测量。

// src/api.ts L642–L660(激活队列完成度标记) const boundsRow = firstOf<{ raw_from: string | null; raw_to: string | null }>(batch[1]); const latestRaw = boundsRow?.raw_to ?? utcDay(Date.now()); const incompleteFrom = addDays(latestRaw, -(window - 1)); const detail = labels.map((day) => { const row = byDay.get(day); const dayInstalls = row?.installs ?? 0; const dayActivated = row?.activated ?? 0; return { day, installs: dayInstalls, activated: dayActivated, rate: dayInstalls > 0 ? dayActivated / dayInstalls : null, complete: day < incompleteFrom, }; });

4. 会话机制:无状态 HMAC 签名 Cookie

telemetry-dashboard/src/auth.ts(179 行)实现了整个认证逻辑。README 的核心描述是:

密码以恒定时间比较(对 SHA-256 摘要,确保操作数长度一致且秘密信息不通过时序泄漏);Cookie 是签名断言——base64url(payload).base64url(HMAC-SHA256)——而非查找键;没有会话存储;ADMIN_PASSWORD轮转会使所有现有 Cookie 失效;登录尝试按 IP 限制为 5 次/分钟。

4.1 密码校验:恒定时间比较

src/auth.ts L77–L83 实现了恒定时间字符串相等:

// src/auth.ts L77–L83 async function equalsInConstantTime(a: string, b: string): Promise<boolean> { const [digestA, digestB] = await Promise.all([ crypto.subtle.digest('SHA-256', encoder.encode(a)), crypto.subtle.digest('SHA-256', encoder.encode(b)), ]); return crypto.subtle.timingSafeEqual(digestA, digestB); }

README 解释了两个设计决策:

  • 先取 SHA-256 摘要,使比较的操作数长度永远一致(timingSafeEqual在长度不匹配时会抛异常,而异常本身就会泄漏秘密长度)
  • 比较摘要而非明文,避免明文比较中的时序侧信道

checkPassword还有一道"半配置即关闭"的保护:src/auth.ts L91–L95 中,若ADMIN_PASSWORDSESSION_SECRET任一缺失,直接返回false,拒绝所有请求——而不是默认放行。

4.2 Cookie 结构与验证流程

src/auth.ts L97–L107 的issueSession构建 Cookie:

// src/auth.ts L97–L107 export async function issueSession(env: Env): Promise<string> { const now = Math.floor(Date.now() / 1000); const payload: SessionPayload = { v: SESSION_VERSION, // 1 iat: now, // 签发时间(秒) exp: now + SESSION_TTL_SECONDS, // 365 天 pw: await passwordFingerprint(env.ADMIN_PASSWORD), }; const encoded = base64UrlEncode(encoder.encode(JSON.stringify(payload))); return `${encoded}.${base64UrlEncode(await sign(env.SESSION_SECRET, encoded))}`; }

Cookie 的完整属性在 src/auth.ts L152–L155:

// src/auth.ts L152–L155 export function sessionCookie(token: string): string { return `${COOKIE_NAME}=${token}; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=${SESSION_TTL_SECONDS}`; }

hasValidSession(src/auth.ts L109–L140)的验证流程:

  1. 检查两个 secret 均存在
  2. 从 Cookie 头读取cg_admin_session
  3. 在第一个.处分割 token,验证签名(先检查长度,再timingSafeEqual
  4. 解码 payload,校验版本号和exp时间戳
  5. 比对 payload 中的pw与当前密码的指纹——这是轮转即下线的核心

4.3 密码指纹与轮转

src/auth.ts L85–L89 的passwordFingerprint生成密码的非可逆标记:

// src/auth.ts L85–L89 async function passwordFingerprint(password: string): Promise<string> { const digest = await crypto.subtle.digest('SHA-256', encoder.encode(`cg-admin-pw ${password}`)); return base64UrlEncode(new Uint8Array(digest).subarray(0, 8)); }

取 SHA-256 摘要的前 8 字节(64 位)做 base64url 编码。README 写道:"轮转ADMIN_PASSWORD使所有人下线——这就是撤销机制。"没有会话表、没有黑名单,密码变了,所有旧 Cookie 的pw字段就不再匹配。

4.4 登录限流

wrangler.jsonc L44–L50 声明了 Cloudflare Workers 原生的ratelimits

"ratelimits": [ { "name": "LOGIN_RATE_LIMITER", "namespace_id": "2001", "simple": { "limit": 5, "period": 60 } } ]

src/index.ts L143–L158 的loginRateLimitOkcf-connecting-ip为键调用限流器。注释特别注明:与 ingest worker(从不读取客户端 IP)不同,此处读取 IP 仅作为限流键,不存储、不记录、不转发。限流器本身故障时"打开失败"(fail open),密码仍然是必需的第二道防线。

4.5 同源 POST 检查

src/auth.ts L161–L179 的isSameOriginPost是登录提交的 CSRF 防线,与SameSite=Lax形成双重保险。一个微妙点被注释专门解释:Chromium 在页面带有Referrer-Policy: no-referrer头时,同源表单提交会发送Origin: null——这不是来自外部站点,而是"未归属",必须被接受,否则会锁定所有 Chromium 用户的登录表单。


5. 安全响应头

src/index.ts L34–L53 的securityHeaders为每个响应注入:

// src/index.ts L34–L53 function securityHeaders(styleNonce?: string): Record<string, string> { const styleSrc = styleNonce ? `'self' 'nonce-${styleNonce}'` : "'self'"; return { 'content-security-policy': [ "default-src 'none'", "script-src 'self'", `style-src ${styleSrc}`, "img-src 'self' data:", "font-src 'self'", "connect-src 'self'", "form-action 'self'", "base-uri 'none'", "frame-ancestors 'none'", ].join('; '), 'x-content-type-options': 'nosniff', 'x-frame-options': 'DENY', 'referrer-policy': 'no-referrer', 'cross-origin-opener-policy': 'same-origin', }; }

styleNonce仅用于内联样式的登录页;资产页面改为link样式表,不需要 nonce。Referrer-Policy: no-referrer同时服务于隐私和isSameOriginPost中的nullorigin 判断。


6. 部署:两个必填 Secret 与只读 D1 绑定

6.1 前置条件

README 列出两项前置:

  1. 部署账户下存在getcodegraph.com的 zone(自定义域名自动配 DNS + 证书)
  2. telemetry-worker 的 D1 数据库已创建

wrangler.jsonc L13 中workers_dev: false明确关闭了workers.dev子域——没有第二条未文档化的入口。

6.2 部署命令

cd telemetry-dashboard npm install npx wrangler login # 一次 npx wrangler secret put ADMIN_PASSWORD # 共享密码 npx wrangler secret put SESSION_SECRET # Cookie 签名密钥,例如 `openssl rand -base64 48` npm run deploy

package.json L10 中deploy脚本是npm run vendor && wrangler deploy——先执行 vendor 步骤再部署。

6.3 双 Secret 的失败关闭语义

README 强调:两个 secret 都是必填的,Worker 在任一缺失时拒绝所有请求,因此半配置的部署会失败关闭,而非变成开放仪表盘。这体现在 src/auth.ts L93 的checkPassword和 src/auth.ts L110 的hasValidSession中:

// src/auth.ts L91–L95 export async function checkPassword(env: Env, submitted: string): Promise<boolean> { if (!env.ADMIN_PASSWORD || !env.SESSION_SECRET) return false; return equalsInConstantTime(submitted, env.ADMIN_PASSWORD); }

6.4 轮转策略

  • 轮转SESSION_SECRET:使所有现有 Cookie 失效(HMAC 密钥变了,签名检查全部失败)
  • 轮转ADMIN_PASSWORD:通过密码指纹机制使所有 Cookie 失效(pw字段不再匹配)
  • 两者均通过wrangler secret put完成,无需重新部署 Worker 代码

7. 本地开发:fixture 种子与三层冒烟测试

7.1 本地种子数据

telemetry-dashboard/scripts/fixture.sql 是一个精心设计的测试数据集,覆盖 12 台机器、10 天(2026-07-01 至 2026-07-10)。文件头部注释逐台列出了每台机器的首次出现日期、操作系统、架构、版本、安装次数、索引日期和卸载时间:

-- id first os arch ver ci installs indexes on uninstalls -- m01 07-01 darwin arm64 1.4.0 0 local 07-01, 07-02, 07-04 -- m02 07-01 darwin arm64 1.4.0 0 global 07-01 -- m03 07-01 linux x64 1.4.0 0 local 07-03 -- m04 07-01 win32 x64 1.4.0 0 local never 07-06 -- ...(共 12 台)

关键设计:只有原始events行是手工编写的;machine_daysmachine_first_seen和三个daily_*rollup 都在文件底部用与 ingest/cron 相同的路径从原始事件派生,因此 fixture 永远不可能漂移到生产环境中不可能出现的状态。

package.json L13 的seed脚本将 fixture 加载到本地.wranglerD1,绝不影响远端。

7.2 本地开发流程

cp .dev.vars.example .dev.vars # 占位 secret;同时供 `wrangler types` 生成 Env npm run check # vendor + wrangler types + tsc --noEmit + deploy --dry-run npm run seed # 将 scripts/fixture.sql 加载到本地 D1 npm run dev # http://localhost:8787

.dev.vars.example 提供两个占位值,同时供wrangler types将 secret 类型包含进生成的Env接口。

7.3 三层冒烟测试

每个测试套件在独立端口上启动自己的临时wrangler dev,运行完自清理,可任意顺序执行(DASH_PORT可覆盖端口)。

smoke-auth.sh(54 条断言)——认证门禁的回归网:

  • 未认证请求无法到达任何内容(页面、API 和静态资产)
  • Cookie 持久且标记正确(HttpOnly; Secure; SameSite=Lax
  • 翻转/截断/伪造的 Cookie 全部被拒绝
  • 暴力破解受限
  • 轮转密码使现有会话失效
  • README 建议:修改 src/auth.ts 或 src/index.ts 的路由表后运行

smoke-api.sh(98 条断言)——对照 fixture 数据验证每个端点的数字:

  • 12 台机器、10 天,小到每个期望值都可以手工推导,而非记录自一次通过的运行
  • 也覆盖"无聊的一半":非法维度、畸形日期、范围倒置、范围过宽

render-check.mjs(79 条断言)——浏览器面板验证:

  • 使用机器上已安装的 Chromium(通过 DevTools 协议,不引入新依赖;无浏览器则跳过)
  • 读取每个 canvas 背后的实时 Chart.js 实例,将每个面板绑定的内容从 Node 侧请求同一端点进行比较
  • 这是唯一能捕获"面板绑定了错误维度"的测试——前两个套件看不到这一点
  • 同时驱动范围选择器并断言 console 干净,CSP 回归会导致构建失败
  • RENDER_SHOT=/tmp/dash.png npm run smoke:render写入全页截图——断言无法检查的内容(如标签碰撞)的唯一手段

README 对这套分工的解释是:render-check.mjs能导入与浏览器刚渲染的同一个面板注册表(public/panels.js),使期望值不可能与待测面板漂移。


8. 前端:零框架、零构建的静态面板

8.1 文件职责

README 对public/的四个文件的分工描述如下,public/index.html 确认了实际的 HTML 结构:

文件职责
public/index.html外壳:masthead、唯一一行过滤控件、空网格
public/panels.js面板注册表——数据进、图表配置出,无 DOM。添加面板只需一条注册项
public/theme.js调色板、格式器、每个面板继承的 Chart.js 默认值
public/app.js页面主体:范围选择器、每面板一次 fetch、加载/空/错误状态

public/index.html L15–L47 展示了页面骨架:

<header class="masthead"> <div> <h1>codegraph telemetry</h1> <p class="subtitle">Anonymous usage from the public engine, straight out of D1.</p> </div> <form method="post" action="/logout"> <button type="submit" class="secondary">Sign out</button> </form> </header> <section class="filters" id="filters" aria-label="Time range"> <div class="filter-group">// public/theme.js L3–L17(验证器结果) // categorical #a8342a,#2a6f9e,#17916a,#c98500 // lightness band PASS · chroma floor PASS · CVD separation PASS // (worst pair ΔE 8.7 protan, all 6 pairs) · normal-vision floor PASS (worst 15.1) // contrast PASS (all ≥ 3:1, so no panel depends on the relief rule) // // ordinal #d99a90,#c26a5c,#a3423a,#7a201a // monotone lightness PASS · adjacent ΔL PASS · light-end contrast 2.34:1 PASS // single hue PASS (spread 3°)

README 对两色的解释:

  • 分类色(识别哪个系列):#a8342a #2a6f9e #17916a #c98500——槽位 1 是品牌 oxblood 提升至可读亮度带的变体。通过所有门(包括所有成对色觉分离),无需对比度补偿。
  • 序数色(顺序本身即意义:运行时长、代码库大小):#d99a90 #c26a5c #a3423a #7a201a——单色相,浅到深,顺序在颜色中可见,无需图例。

名义柱状图统一使用槽位 1——按值着色会浪费识别通道重新编码柱长已展示的内容。README 的最后一条警告:若修改十六进制值,重新运行验证器——"看起来没问题"的红绿对在色盲(deuteranopia)下会坍缩。

8.4 第三方库 vendor 机制

wrangler.jsonc 中没有外部 origin 的 CDN 链接。package.json L7 的vendor脚本(node scripts/vendor-assets.mjs)将node_modules中的库复制到public/vendor/(由devdeploy脚本链式调用),README 解释了三个理由:

  1. 版本由 lockfile 锁定
  2. 运行时不依赖第三方 origin
  3. CSP 保持script-src 'self'

public/vendor/在 .gitignore 中——它是构建输出,不入库。


9. 关键源码文件导航

文件内容
telemetry-dashboard/src/index.ts主 Worker:路由表、安全头、登录/登出流程、静态资产代理
telemetry-dashboard/src/auth.ts恒定时间密码比较、HMAC Cookie 签发与验证、密码指纹、同源 POST 检查
telemetry-dashboard/src/api.ts8 个读 API 端点:范围解析、DIMS/SERIES注册表、breakdown、激活漏斗、留存曲线
telemetry-dashboard/src/login-page.ts内联登录页 HTML 渲染(含 nonce 样式块与 HTML 转义)
telemetry-dashboard/wrangler.jsoncrun_worker_first、D1 绑定、workers_dev: false、原生ratelimits配置
telemetry-dashboard/public/panels.js面板注册表:数据进、Chart.js 配置出,无 DOM
telemetry-dashboard/public/theme.js分类/序数调色板、Chart.js 默认值、验证器结果注释
telemetry-dashboard/public/app.js范围选择器、每面板一次 fetch、加载/空/错误状态
telemetry-dashboard/scripts/fixture.sql12 台机器 × 10 天的手工种子数据,rollup 由原始事件派生
telemetry-dashboard/scripts/smoke-auth.sh认证门禁回归测试(54 条断言)
telemetry-dashboard/scripts/smoke-api.shAPI 端点数值验证(98 条断言)
telemetry-dashboard/scripts/render-check.mjs浏览器面板渲染验证(79 条断言,DevTools 协议)

10. 设计决策小结

telemetry-dashboard/README.md 中的多个段落揭示了这个项目的核心设计哲学,可以归纳为几条原则:

  1. 最小安全面:两个 secret、一个 HMAC 签名 Cookie、无会话存储、无用户表——"对两个人来说,最简但真正安全的东西"。
  2. 失败关闭:半配置的部署拒绝所有请求,而非降级为开放访问。
  3. 诚实的数字:不将机器日悄悄呈现为用户数;不将未完成转化的队列尾部画成悬崖并称之为下降。
  4. rollup 优先:所有面板从永久保留的daily_*rollup 表读取,只有激活漏斗因语义需要读原始事件,并如实说明其可见范围受限。
  5. 参数化 SQL:查询串中的任何值从不拼接到 SQL;维度和指标通过封闭注册表查找,非法值返回400
  6. 可复现测试:手工推导的 fixture 数字、独立的测试端口、浏览器侧对真实 Chart.js 实例的断言——三层测试各自覆盖对方看不到的失败模式。
  7. 颜色经过验证:调色板不是凭眼睛挑选,而是对实际图表表面(白色)跑数据可视化验证器,结果记录在theme.js顶部注释中。

这套实践适用于任何需要在 Cloudflare 上部署一个密码门禁、只读、面向少量内部用户的数据看板的场景——从 D1 绑定到run_worker_first、从 HMAC Cookie 到 fixture 种子、从三层测试分工到色觉安全色阶,telemetry-dashboard 提供了完整的参考实现。

【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 2:50:34

JavaEE订餐系统课程设计实战:从数据库建模到部署答辩要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 2:49:37

多项式与有理函数:微积分预备的核心与Python验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 2:49:36

C++动态测试实战:从Google Test到ASan内存检测全攻略

简介&#xff1a;面向软件测试课程学习者与C开发者&#xff0c;该实验报告基于Parasoft C Test 9.2环境&#xff0c;完整演示了动态测试的实施流程。报告依次介绍动态测试方法、自动化单元测试用例生成与执行、自定义测试用例向导配置、基于CSV数据源批量创建测试用例&#xff…

作者头像 李华