十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

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

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/codegraphcodegraph 是一个预索引代码知识图谱工具会自动在代码变更时同步更新供 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 签名密钥是部署 secretD1 数据库 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是承重墙。若为falseCloudflare 会在 Worker 执行之前直接返回匹配的静态文件这意味着任何人都可以通过猜文件名拿到仪表盘 HTML。设为true后每一个请求都会先进入 src/index.ts 的主fetch处理器只有认证通过才会代理到env.ASSETS。README 中的路由表完整列出了哪些路径对谁开放路由认证说明GET /login公开密码表单。已登录则 302 到/POST /login公开按 IP 限流成功后写入会话 CookiePOST /logout公开清除 CookieGET /robots.txt公开Disallow: /GET /api/*需要JSON无会话时返回401其他所有路由需要静态资产来自public/无会话时 302 到/logintelemetry-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-cache和vary: cookie确保登录后的页面永远不落入共享缓存src/index.ts L220–L227。3. 读 API全量端点参考src/api.ts 是仪表盘唯一的读 API 实现约 800 行涵盖 8 个端点。每个端点都遵循以下通用规则源自 README 与 src/api.ts只读 GET会话门控统一以?fromYYYY-MM-DDtoYYYY-MM-DD含端点UTC 日为范围超过 366 天的范围会被截断并在响应的range.clamped字段中标注响应为 Chart.js 格式labels[] datasets[]并附带rows[]供显示数字表格使用非法输入返回400 消息绝不猜测图表数据带Cache-Control: private, max-age300telemetry-dashboard/README.md 的端点表如下这里逐行对照 src/api.ts 的常量加以说明端点回答什么源码常量/api/meta数据实际存在的日期范围前端以latest_day为锚避免图表终止于尚未写入 rollup 的那天MAX_RANGE_DAYS 366,RETENTION_DAYS 14src/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维度分布os、arch、codegraph_version、node_major、language、file_count_bucket、duration_bucket、target、scope、kind、name、client_name、name_error可选event、metriccount\|machines、limitDIMS记录src/api.ts L160-L184DEFAULT_BREAKDOWN_LIMIT 12MAX_BREAKDOWN_LIMIT 50/api/activation?window7安装 → 首次索引漏斗 每日比率DEFAULT_ACTIVATION_WINDOW 7MAX_ACTIVATION_WINDOW 30src/api.ts L36-L37/api/retentionDay 0–14 队列曲线范围内首次出现的机器RETENTION_DAYS 14src/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–L743.2 时间序列SERIES注册表src/api.ts L324–L368 定义了一个SERIES记录每个条目包含标题、系列标签和 SQL。所有固定时间序列都读取 rollup 表daily_event_counts、daily_machines、machine_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–L559Other 折叠逻辑 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: false和incomplete_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 签名 Cookietelemetry-dashboard/src/auth.ts179 行实现了整个认证逻辑。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): Promiseboolean { 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_PASSWORD或SESSION_SECRET任一缺失直接返回false拒绝所有请求——而不是默认放行。4.2 Cookie 结构与验证流程src/auth.ts L97–L107 的issueSession构建 Cookie// src/auth.ts L97–L107 export async function issueSession(env: Env): Promisestring { 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; SameSiteLax; Path/; Max-Age${SESSION_TTL_SECONDS}; }hasValidSessionsrc/auth.ts L109–L140的验证流程检查两个 secret 均存在从 Cookie 头读取cg_admin_session值在第一个.处分割 token验证签名先检查长度再timingSafeEqual解码 payload校验版本号和exp时间戳比对 payload 中的pw与当前密码的指纹——这是轮转即下线的核心4.3 密码指纹与轮转src/auth.ts L85–L89 的passwordFingerprint生成密码的非可逆标记// src/auth.ts L85–L89 async function passwordFingerprint(password: string): Promisestring { 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 原生的ratelimitsratelimits: [ { name: LOGIN_RATE_LIMITER, namespace_id: 2001, simple: { limit: 5, period: 60 } } ]src/index.ts L143–L158 的loginRateLimitOk以cf-connecting-ip为键调用限流器。注释特别注明与 ingest worker从不读取客户端 IP不同此处读取 IP 仅作为限流键不存储、不记录、不转发。限流器本身故障时打开失败fail open密码仍然是必需的第二道防线。4.5 同源 POST 检查src/auth.ts L161–L179 的isSameOriginPost是登录提交的 CSRF 防线与SameSiteLax形成双重保险。一个微妙点被注释专门解释Chromium 在页面带有Referrer-Policy: no-referrer头时同源表单提交会发送Origin: null——这不是来自外部站点而是未归属必须被接受否则会锁定所有 Chromium 用户的登录表单。5. 安全响应头src/index.ts L34–L53 的securityHeaders为每个响应注入// src/index.ts L34–L53 function securityHeaders(styleNonce?: string): Recordstring, 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 列出两项前置部署账户下存在getcodegraph.com的 zone自定义域名自动配 DNS 证书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 deploypackage.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): Promiseboolean { 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_days、machine_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.sh54 条断言——认证门禁的回归网未认证请求无法到达任何内容页面、API 和静态资产Cookie 持久且标记正确HttpOnly; Secure; SameSiteLax翻转/截断/伪造的 Cookie 全部被拒绝暴力破解受限轮转密码使现有会话失效README 建议修改 src/auth.ts 或 src/index.ts 的路由表后运行smoke-api.sh98 条断言——对照 fixture 数据验证每个端点的数字12 台机器、10 天小到每个期望值都可以手工推导而非记录自一次通过的运行也覆盖无聊的一半非法维度、畸形日期、范围倒置、范围过宽render-check.mjs79 条断言——浏览器面板验证使用机器上已安装的 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 classmasthead div h1codegraph telemetry/h1 p classsubtitleAnonymous usage from the public engine, straight out of D1./p /div form methodpost action/logout button typesubmit classsecondarySign out/button /form /header section classfilters idfilters aria-labelTime range div classfilter-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/由dev和deploy脚本链式调用README 解释了三个理由版本由 lockfile 锁定运行时不依赖第三方 originCSP 保持script-src selfpublic/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 配置出无 DOMtelemetry-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 中的多个段落揭示了这个项目的核心设计哲学可以归纳为几条原则最小安全面两个 secret、一个 HMAC 签名 Cookie、无会话存储、无用户表——对两个人来说最简但真正安全的东西。失败关闭半配置的部署拒绝所有请求而非降级为开放访问。诚实的数字不将机器日悄悄呈现为用户数不将未完成转化的队列尾部画成悬崖并称之为下降。rollup 优先所有面板从永久保留的daily_*rollup 表读取只有激活漏斗因语义需要读原始事件并如实说明其可见范围受限。参数化 SQL查询串中的任何值从不拼接到 SQL维度和指标通过封闭注册表查找非法值返回400。可复现测试手工推导的 fixture 数字、独立的测试端口、浏览器侧对真实 Chart.js 实例的断言——三层测试各自覆盖对方看不到的失败模式。颜色经过验证调色板不是凭眼睛挑选而是对实际图表表面白色跑数据可视化验证器结果记录在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),仅供参考
返回列表