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

资讯详情

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

OpenSEO 的 AI 代码评审体系:基于 Greptile 的架构约束、安全边界与双数据库工程纪律

OpenSEO 的 AI 代码评审体系:基于 Greptile 的架构约束、安全边界与双数据库工程纪律 OpenSEO 的 AI 代码评审体系基于 Greptile 的架构约束、安全边界与双数据库工程纪律【免费下载链接】open-seoOpen source alternative to Semrush and Ahrefs项目地址: https://gitcode.com/GitHub_Trending/op/open-seo本文以 OpenSEO 仓库中的 .greptile/rules.md 为主体结合配套的 config.json 与 files.json完整拆解该项目如何把评审立场、后端分层、计费与多租户授权、SSRF 防护、SQLite/Postgres 双方言持久化等工程约束沉淀为一套可被 AI 评审 AgentGreptile逐条执行、且能被仓库源码逐项印证的规则体系。读完本文你可以掌握一个真实 SaaS 项目如何为 LLM 代码评审编写规则即文档的上下文文件以及 OpenSEO 每一条高严重度规则背后对应的具体实现路径。一、为什么评审规则本身就是一个工程文件OpenSEO 是一个开源的 Semrush/Ahrefs 替代品关键词研究、域名概览、排名追踪、站点审计、反链分析等它接收外部贡献包括未经测试的编码 Agent 输出。.greptile/rules.md 开篇就定下基调Review posture在相关调用路径和测试支撑之前把变更行为视为不可信。这份文档不是泛泛的贡献指南而是一份写给 AI 评审系统的评审上下文它告诉评审器该优先抓什么问题正确性、安全、授权、计费、数据丢失、可移植性、用户可见回归不该抱怨什么命名偏好、文件组织、memoization、无关清理以及哪些看起来是漏洞的情况其实是刻意设计详见第六节。.greptile/目录由三个文件构成三者分工明确文件职责关键内容rules.md全局评审立场与架构默认值自然语言评审姿态、简单性与先例、后端分层流、TS 运行时校验、TanStack/React 规范、安全边界、误报控制config.json机器可执行的评审参数与 10 条带作用域的规则strictness: 2、commentTypes: [logic, syntax]、ignorePatterns、逐条id/rule/scope/severityfiles.json评审时必看的规范文件索引20 个锚点文件及其description与scope让评审器先读正解再评 diffconfig.json 顶部的全局配置值得逐字段看strictness: 2与commentTypes: [logic, syntax]评审强度与评论类型白名单——只关注逻辑与语法层面的实质问题这也与 rules.md 中不要重复 Prettier/TypeScript/Oxlint/Knip 等工具已经能确定性地发现的问题相呼应。ignorePatterns忽略生成物src/routeTree.gen.ts、web/src/routeTree.gen.ts、worker-configuration.d.ts、drizzle/meta/**、drizzle-pg/meta/**与 rules.md 的Generated and special-case files一节互为镜像。10 条规则每条都有id如tenant-resource-scope、scopeglob 列表规则只在触碰这些路径时生效与severityhigh/medium这是规则即文档能真正被执行的关键每条规则都被收窄到它真正管辖的文件边界内避免评审器对着无关 diff 刷屏。files.json 则回答了评审时该以哪些文件为准绳。它登记的锚点包括src/serverFunctions/middleware.ts已建立的认证与活跃项目上下文中间件src/server/mcp/project-auth.tsMCP handler 的规范项目授权包装器src/db/schema-parity.test.ts跨方言结构保证与机械 DB 守卫并诚实注明通过该测试并不证明语义级查询或迁移可移植性src/db/runBatch.ts、src/server/workflows/pgStep.ts、src/db/pg/client.ts、src/server/lib/dataforseo/client.ts、src/server/billing/subscription.ts、src/server/lib/audit/url-policy.ts、src/server/mcp/instrumentation.ts、src/server/mcp/output-schemas.ts 等。其中 envelope.ts 的描述甚至直接嵌入了已知缺陷说明parseTaskItems 目前在已计费 payload 的条目校验失败时会丢弃计费元数据不要将该路径当作先例——这与 rules.md 末尾对同一债务的声明一致形成文档间交叉引用。二、config.json 十条作用域规则逐条拆解rules.md 给出的是默认立场config.json 的 10 条规则则是可执行的具体判据。以下按严重度分组说明scope 均为仓库根目录相对路径2.1 多租户与授权hightenant-resource-scope在每个外部信任边界先建立授权再分发——用户端点走 session 中间件项目作用域的 MCP handler 走withMcpProjectAuth回调与 webhook 走签名 state 或已验证的 provider 签名公开路由需要显式书面决策。项目作用域的 server function 使用requireProjectContext 已校验的projectId以调用方可控资源 ID 为键的读/写必须把已验证的 project/organization/user 带进查询或先通过规范父级查找授权。永远不要信任客户端提供的 organization、user 或 billing 身份。postgres-entrypoint-scope任何能无环境请求作用域地触达 provider-aware Drizzledb的 Worker、定时任务、Durable Object 方法必须自建withPgClientWorkflow 步骤必须用pgStep裸step.do只允许出现在pgStep内部。禁止假设AsyncLocalStorage作用域能跨 Workflow 步骤或 DO 回调存活。atomic-multi-write部分完成会破坏不变量时用runBatch且所有语句必须从tx回调构建executeInBatches只用于每个已提交块本身安全或幂等的工作它不是 all-or-nothing硬性并发/容量准入必须用数据库约束或事务性条件写而非 count-then-act为 D1 给大型inArray/批量参数列表设界可重试的 Workflow 写需要确定性 ID、稳定唯一键或冲突安全 upsert。2.2 计费正确性highbillable-dataforseo-seam所有可计费的 hosted DataForSEO 调用必须经过createDataforseoClient携带组织计费上下文当已计费响应随后解析/校验失败时必须保留 provider 计费路径与成本元数据保证计量照常发生缓存命中与 provider 未计费的失败不收费。自托管调用、免费地点数据、使用 SDK 模型的测试、排队的task_get收集是刻意的例外。billing-fails-closed每条可计费 hosted provider 路径在付费执行前检查组织信用额度执行后经既定共享 helper 计量 provider 报告的花费门禁失败即阻断付费调用授权失败直接终止请求禁止使用可能把活检查会拒绝的访问/花费授权掉的过期阳性缓存重试或 Workflow 重放不得漏计或重复计费。2.3 SSRF 与输出安全high/mediumuntrusted-outbound-url抓取用户派生的初始目标前先normalizeAndValidateStartUrl并手动处理重定向每次直接跟随的跳转必须在下一次 fetch 前重新校验审计爬虫放入 crawl frontier 的每个已发现链接/sitemap 条目/重定向目标必须通过isCrawlableUrl 同域 robots 策略对不可信 URL 永远不使用自动重定向跟随。固定 provider URL 豁免 SSRF 筛查但仍遵守共享客户端的超时/重试/错误策略。safe-external-links来自 API、爬虫、LLM 或 provider 数据的可点击 URL客户端必须使用getSafeExternalUrl、ExternalUrlCell、SafeExternalLink或共享 Markdown 渲染器不得用裸href或临时方案式 scheme 正则渲染。2.4 数据建模与行为证据mediumnormalized-product-data关系与可独立查询、受限或演进的产品概念存规范化表 外键 连接表不得为省 join 把关系 ID 塞进 JSON/分隔文本不透明的 provider payload、不可变历史、缓存、有界非关系值数组除外。dual-dialect-persistence手改 schema 必须同步更新 SQLite 与 Postgres 两侧定义与生成的迁移保持表、列、可空性、默认值、约束、索引、外键语义等价查询、裸 SQL、时间戳比较、冲突处理、数据库错误分类必须双 provider 可用或显式分支。behavior-evidence改动授权、计费计量、持久化/查询行为、schema/迁移、provider 序列化、Workflow 重试/状态迁移、URL/搜索/查询行为的变更除非已有测试直接覆盖该分支或失败模式否则必须附聚焦的行为测试bug fix 应能复现旧失败评论必须点名具体未测行为与可能失败而不是对测试型/文案型/生成物型/纯类型变更索要测试。三、后端分层server function → service → repository → dbrules.md 给出的默认后端流原文代码块完整保留TanStack server function - service - repository - provider-aware db/schema各层职责边界server function拥有认证中间件、Zod 输入校验、已验证上下文注入、仅传输层的响应整形service拥有业务规则、provider/cache/Workflow 编排并在适当时把 provider 或领域失败翻译为应用错误repository拥有 Drizzle 持久化与查询行为不得把新数据库/provider 编排直接写进src/serverFunctions/**不得为纯 provider 或纯计算功能建空 repository。仓库源码与这条规则严格对齐。src/serverFunctions/middleware.ts 里globalServerFunctionMiddleware [errorHandlingMiddleware, ensureUserMiddleware]全局两层中间件先统一错误处理再确保用户上下文requireAuthenticatedContext用ensuredUserContextSchemaZod对上下文做safeParse失败即抛AppError(INTERNAL_ERROR)——这正是server function 拥有 Zod 校验与已验证上下文注入的落地requireProjectContext在上层基础上断言project存在并把projectId注入上下文供后续 repository 查询携带项目作用域使用。而config.json中tenant-resource-scope规则引用的withMcpProjectAuth实现于 src/server/mcp/project-auth.ts它用ProjectService.getProjectForOrganization(auth.organizationId, projectId)把调用方提供的projectId对照 token 所属组织做硬门禁查不到即抛FORBIDDEN并顺带复用该行构建billing上下文注释明确不要依赖 service 抛错而是断言结果这样即使 service 错误行为变化它仍是硬门禁。错误翻译规则在源码中同样有据可查内部 provider/领域代码可以使用聚焦的 typed error如 src/server/lib/errors.ts 的AppErrorservice 负责翻译server-function 中间件与裸路由 handler 负责客户端安全的 wire 响应对显式相互独立的条目部分成功可接受但失败必须可见——授权、计费、校验与必须写仍然 fail closed。四、双方言持久化一套 repository 写两种数据库OpenSEO 同时支持 Cloudflare D1SQLite与 Postgres自托管这是 rules.md 与 config.json 着墨最多的可移植性主题。规范 barrel src/db/schema.ts 的注释把机制讲得很清楚repository 从这里导入表定义与 provider-aware 的db从而两种后端各写一次类型恒定为 SQLite 定义运行时值取当前 provider 的展开对象src/db/schema-parity.test.ts 断言两个方言 schema 结构互换同表/列/可空/主键/唯一索引这是把 Postgres schema 单次 cast 变健全的前提——注释还特别指出 Postgres schema 是唯一不由db:generate重新生成的结构产物parity 测试就是它的漂移守卫。与规则配套的锚点文件scripts/migrate-d1-to-postgres.tsD1→Postgres 的运营期复制与转换假设生成物目录 drizzle/43 个迁移与 drizzle-pg/21 个迁移及其meta/**快照——这些快照被ignorePatterns忽略但 rules.md 明确要求生成的迁移 SQL 仍需语义评审。rules.md 还给出了一个反直觉的时间戳事实专治评审误报SQLite 与 Postgres 手写时间戳都是文本但数据库默认值并非逐字节相同SQLite 用空格分隔值Postgres 用 ISO 文本。不要强加所有存储时间戳都是 ISO的假规则对照当前 provider 的格式评审比较、写入与迁移。这正是由代码结构推断的内容要谨慎表达的反面教材——评审器若不了解这一点会批量制造假阳性。五、MCP 工具链授权、计量与输出校验三件套rules.md 对 MCP 有两条硬约束项目作用域的 MCP handler 使用withMcpProjectAuth复用既有 serviceMCP 独有能力可以直接调用已认证且已计量的共享 provider seam而不是新造一次性 service。每个 MCP 工具必须经instrumentMcpToolHandler注册不得绕过共享错误捕获、计时、计费元数据与输出 schema 校验注册裸 handler。对应锚点 src/server/mcp/instrumentation.ts 与 src/server/mcp/output-schemas.ts。rules.md 里一段很细的 TypeScript 规则就出自这里凡是经 MCPstructuredContent透传外部 SDK 类实例的输出必须用looseObjectOutputSchema普通纯对象 map 仍可用z.record。计费的单一 seam设计落在 src/server/lib/dataforseo/client.tscreateDataforseoClient(customer)返回各 section 的meter(...)包装函数每个包装在执行前走assertUsageCreditsAvailable类门禁、执行后经trackUsageCreditSpend计量来自 src/server/billing/subscription.ts与billing-fails-closed规则一一对应调用方可在输入里传creditFeature覆盖默认 credit feature例如 MCP 工具把花费记到自己头上fetcher 只读命名字段所以忽略多余字段loadDataforseoSections是 DataForSEO 子树的单一懒加载边界把约 3MB 的 SDK 隔离在首个 API 调用之后——评审器读 diff 时能理解为什么 section 模块不能静态导入。files.json 对 src/server/billing/autumn.ts 的描述补充了重试纪律单一懒加载 Autumn 客户端以及对非幂等 track 调用受限的重试策略——重试是否会双计费正是billing-fails-closed明文盯防的失败模式。六、Cloudflare 无服务器运行时withPgClient 与 pgSteppostgres-entrypoint-scope规则high的动机在 src/server/workflows/pgStep.ts 的注释里写得非常透彻Cloudflare Workflows 在每个步骤回调自己的执行上下文中运行——步骤独立持久化并可在新的调用中恢复所以withPgClient围绕run()打开的AsyncLocalStorage作用域不会传播进步骤。每个触达 DB 的步骤必须自己开客户端。D1 模式下withPgClient是 no-op等价于普通step.do客户端是懒的postgres-js 首次查询才连接因此包一个实际不触 DB 的步骤零成本。pgStep就是对step.do的薄包装step.do(name, config, () withPgClient(fn))并保留Rpc.SerializableT约束保证步骤结果可序列化。请求作用域 Postgres 客户端与withPgClient契约定义在 src/db/pg/client.ts。批量写入语义则由 src/db/runBatch.ts 承载它是atomic-multi-write规则的物理基础runBatch(build)D1 路径用d1Db.batch([...])单条原子有序调用Postgres 路径在db.transaction内按数组顺序逐条执行以对齐 D1 的顺序语义关键警示写在 JSDoc 里语句必须用回调给的tx构建而不是模块级db否则在 Postgres 上会落在事务外DB_BATCH_SIZE 100的原因D1 单语句绑定参数上限约 100批量必须设界Postgres 放宽但同一无害executeInBatches按 100 切块、每块原子执行——规则文本明确它是块块安全/幂等语义而非 all-or-nothing。七、安全边界的实现落点rules.md Security boundaries 一节的四条要求在仓库中都能找到对应实现规则要求实现落点webhook 签名在解析/变更之前对 raw body 校验重放幂等src/server/billing/svix.ts 与 src/server/billing/autumn-webhook.tsOAuth state 签名、过期、回调绑定除非 Better Auth 等成熟库持有该不变量provider token 静态加密src/lib/auth-options.ts、src/lib/auth-config.ts秘密只经运行时环境 helper 或 Workers bindings 读取import.meta.env仅限类型化公开/构建期值绝不把秘密暴露给客户端/构建期 APIsrc/server/lib/runtime-env.ts、src/lib/auth-mode.tsisHostedClientAuthMode明确是构建期AUTH_MODE契约新出站目标、带秘密请求、认证与计费变更需人工安全评审config.json 中untrusted-outbound-url、billable-dataforseo-seam、billing-fails-closed的 scope 覆盖SSRF 策略的核心实现在 src/server/lib/audit/url-policy.tsBLOCKED_HOSTSlocalhost、GCPmetadata.google.internal、169.254.169.254、Cloudflare Workers 的100.100.100.200元数据端点与内网后缀.local、.internal、.home.arpa等硬编码拦截isPrivateIpv4覆盖 10/8、127/8、0/8、169.254/16、172.16/12、192.168/16、100.64/10、198.18-19/15、224/4并专门处理::ffff:IPv6 映射 IPv4 的绕过形态——untrusted-outbound-url规则要求重定向必须重新校验正是为了对抗这类 DNS/跳转逃逸。客户端侧则由 src/client/components/SafeExternalLink.tsx、src/client/components/Markdown.tsx 及表格 URL 组件统一渲染不可信外部链接对应safe-external-links规则。部署模式deployment modes也是安全评审的前提知识src/lib/auth-mode.ts 的AUTH_MODES [cloudflare_access, local_noauth, hosted]与 rules.md 的Deployment modes一节逐字对应——local_noauth是刻意可信的本地模式、暴露到公网才不安全没有登录本身不是漏洞hosted 模式使用 Better Auth 组织级 Autumn 计费自托管模式用操作者自己的 provider key 并刻意绕过 Autumn。无效AUTH_MODE取值会 fail-closed 回退到cloudflare_access并console.error告警这也是从源码结构看评审器理解误报边界所需的事实。八、误报控制badseo 夹具、双 workspace 与已知债务False-positive controls 一节是这份评审上下文最有辨识度的部分逐条给出评审器别乱叫的判据badseo/**是刻意做坏的 SEO 夹具站badseo/ 有独立 README 与 fixtures 目录。它的 SEO 缺陷是故意的除非变更破坏了声明的夹具行为否则不应作为缺陷上报。web/**是独立的营销/文档 workspace有自己的构建与依赖版本web/package.json、web/pnpm-lock.yaml。跨边界复制 API 或 schema 前先检查各 workspace 已安装库的主版本——这是 monorepo 评审中最常见的跨版本误报来源。生成物与特例不要要求手改生成路由树routeTree.gen.ts、worker-configuration.d.ts或 Drizzle 元数据快照Better Auth schema 按方言生成但内含必须手工恢复的索引由 parity 测试守卫重新生成必须保留这些索引迁移 SQL 即使元数据被忽略也要语义评审。存量债务不是先例一些现有文件绕过偏好分层、使用手动前端状态或含 provider 特定假设——不要把例外复制到新代码但也不要索要无关重构只有当贡献引入、扩大或依赖了该风险行为时才评论。parseTaskItems已知债务当前 DataForSEO 信封在已计费 payload 的条目校验失败时会丢失计费元数据src/server/lib/dataforseo/envelope.ts。这是已知债务而非安全错误处理先例——files.json 对该文件的描述与 rules.md 末尾的声明互相印证确保评审器在两个入口读到同一结论。配合 rules.md 开头的负向清单不要求无关清理、不重复 lint/格式化意见、命名与抽象偏好除非引入具体成本否则属 nitpick整套体系实现了高严重度问题抓得狠风格问题管住嘴的评审经济学。九、方法论小结这套评审上下文做对了什么从 rules.md config.json files.json 的三文件结构可以提炼出对为 LLM 评审 Agent 编写仓库上下文有直接参考价值的设计规则必须可定位每条规则绑定scopeglobconfig.json或点名具体文件rules.md 直接引用src/server/mcp/output-schemas.ts这类路径评审器与人类读者都能一跳到达证据先读正解再评 difffiles.json 把 20 个规范锚点登记为必读文件并在 description 里写明该文件承载的契约含已知缺陷警示等价于给评审器发了标准答案误报控制与正向规则等量齐观deployment modes、badseo 夹具、双 workspace 版本差异、方言时间戳格式、已知债务——这些看似问题实为设计的条目占用了与正向规则相当的篇幅是抑制 AI 评审噪声的关键计费与安全使用 fail-closed 语义授权、计费、校验、必须写一律失败即终止重试/Workflow 重放不得漏计量或双计费——这条语义在 subscription.ts、client.ts、svix.ts 中都有实现落点对生成物诚实生成快照被忽略、但生成的 SQL 仍要求语义评审parity 测试被明确定位为Postgres schema 的漂移守卫而非可移植性证明——文件描述里连测试的局限都提前写明。适用前提与限制本文描述的是当前仓库的评审配置与实现状态规则与源码可能随项目演进漂移若你在自己的项目借鉴该模式建议同步维护 rules.md立场、config.json可执行判据、files.json锚点索引三层并像本项目一样让每一处规则声明都能在一个文件路径内被验证。【免费下载链接】open-seoOpen source alternative to Semrush and Ahrefs项目地址: https://gitcode.com/GitHub_Trending/op/open-seo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表