Ivan's Blog
项目实践

Oidrune

Oidrune 是一个由运营者控制的 GitHub Actions 通知中继:它验证短期 GitHub OIDC 身份,只接受已批准来源的 workflow completion event,并把调用方提供的规范化正文投递到一个运营者控制的 Telegram destination。

  • README content contract
  • GitHub Actions scheduling
  • GitHub reusable workflow

目录

技术栈

运行与交付

CI 工作流
  • ci-main.yml
  • ci-pr.yml
  • notify.yml
  • oidrune-smoke.yml
  • release.yml
能力标记
  • bun_lock
  • github_actions
  • package_json
JSON

Purpose

Oidrune 是一个由运营者控制的 GitHub Actions 通知中继:它验证短期 GitHub OIDC 身份,只接受已批准来源的 workflow completion event,并把调用方提供的规范化正文投递到一个运营者控制的 Telegram destination。主要消费者是希望在不复制 Telegram/Oidrune 静态凭据的情况下接入发布或 CI 通知的 GitHub repositories,以及负责管理来源、可信 workflow release、投递失败和 operator console 的运营者(README.md、PRODUCT.md、docs/specs/oidrune-mvp/SPEC.md)。

Oidrune 不替调用方发布、回滚、取消或修改 GitHub release,也不是 generic webhook broker、multi-destination broadcaster 或自建账号系统;它把 source admission、durable handoff、Telegram delivery 和 operator administration 分开(PRODUCT.md、CONTEXT.md、docs/specs/oidrune-mvp/SPEC.md)。

README Content Requirements / Contract

这份 contract 是 Oidrune README 的可复用验收面:README 的产品说明、双语同步、Quick Start、Actions 集成、异步交付、文档地图、License 和 preview 边界必须逐条可审查,不能只用“产品优先”或“安全集成”概括。

R1 Product-first entry

  • Requirement: 先说明产品是什么、目标使用者和明确非目标,再放少量能识别真实产品的 dark/light preview;README 不得先用 marketing asset、海报或 logo proof 代替产品边界。
  • Verification: README.md 与 README.zh-CN.md 在 # Oidrune 后先定义 GitHub Actions 到 Telegram 的 operator-controlled relay、无调用方静态凭据和非 generic broker 边界,随后才出现 preview;PRODUCT.md 提供 primary user 与 non-goals 的交叉证据。

R2 Bilingual parity

  • Requirement: README.md 与 README.zh-CN.md 顶部互链,并同步产品边界、Quick Start、delivery semantics、部署责任、文档真相源地图和 License 链接;同步不只意味着翻译标题。
  • Verification: 两个 README 的顶部语言链接和主要章节顺序一致,产品、投递、接入、开发、部署、发布、文档与 License 内容可逐项对照(README.md、README.zh-CN.md)。

R3 Safe Quick Start

  • Requirement: Quick Start 必须使用仓库真实命令,明确 Bun >=1.4.0、bun install 和 bunx vite --config vite.demo.config.ts deterministic demo command,并说明 demo 不访问 Cloudflare Access、D1、Queues 或 Telegram;公开 snapshot、catalog、Topic report、candidate report 和 search payload 不得复制 loopback 地址、本机绝对路径或私有部署地址。
  • Verification: package.json 的 package manager、Bun engine 和 vite.demo.config.ts 支持这些命令;README 明确 demo 的外部服务边界;本 playbook 只保存无地址的命令和相对证据路径(README.md、README.zh-CN.md、package.json、vite.demo.config.ts)。

R4 Secretless GitHub Actions contract

  • Requirement: 示例必须明确 if: always()、needs、id-token: write、受信任发布对应的 full commit SHA、由 needs.<job>.result 推导的 outcome、完整 caller-provided summary 和成对的 gateway_url / oidc_audience override inputs;调用方 job 不传 secrets:,partial gateway pair 必须在请求 OIDC token 前拒绝。
  • Verification: README 展示核心 final notify job;docs/notify-example.md 展示完整 gateway pair 和 summary 语义;.github/workflows/notify.yml 定义全部 inputs、OIDC 权限、pair validation 和 no-secrets 调用边界。

R5 Durable handoff semantics

  • Requirement: 202 Accepted 必须明确表示事件已经持久化交接到 Oidrune 的 delivery path,只表示 durable handoff,不表示 Telegram 已完成投递;Queue retry、dead letter 和 operator visibility 不能被省略。
  • Verification: README 的 delivery sequence、HTTP contract 和 durable delivery ADR 共同声明 202 与 Telegram delivery completion 是两个不同状态(README.md、README.zh-CN.md、docs/specs/oidrune-mvp/contracts/http.md、docs/adr/0002-durable-asynchronous-delivery.md)。

R6 Documentation truth-source map

  • Requirement: README 文档地图必须明确每个真相源的职责:PRODUCT.md 管产品范围、目标用户和非目标;CONTEXT.md 管领域语言和禁用混淆词;Spec 管长期行为契约;IMPLEMENTATION.md 管实现覆盖与 rollout;HTTP contract 管请求/响应和状态语义;ADR 管持久的不可逆取舍;quality gates 管 merge/release policy;docs/specs/README.md 管 spec hierarchy 和 SPEC.md / IMPLEMENTATION.md / HISTORY.md 的关系。
  • Verification: README 的 More docs 链接覆盖产品、领域、Spec、Implementation、HTTP 和 quality gates;docs/specs/README.md、ADR 目录和 quality-gate source 补足 hierarchy、取舍与门禁职责,快照将这张地图作为可复用 contract 保留(README.md、PRODUCT.md、CONTEXT.md、docs/specs/README.md、docs/specs/oidrune-mvp/SPEC.md、docs/specs/oidrune-mvp/IMPLEMENTATION.md、docs/specs/oidrune-mvp/contracts/http.md、docs/adr/、docs/quality-gates.md)。
  • Requirement: README 文档地图之后必须提供可点击的 MIT License 链接,且链接指向仓库中的 LICENSE。
  • Verification: 两份 README 的文档章节之后都保留 [MIT License](./LICENSE)(README.md、README.zh-CN.md、LICENSE)。

R8 Preview and marketing boundary

  • Requirement: README 可以保留有限、具有产品识别价值的 preview,但不应堆叠或枚举 posters、social cards、logo proof 等营销素材目录;这些素材不能成为产品说明、文档地图或验收证据的替代品。
  • Verification: 源 README 只在产品边界之后保留一组 dark/light preview;docs/marketing/ 与 logo proof 仅作为源仓库资产事实,不进入公开 playbook 的目录型内容或产品标签(README.md、README.zh-CN.md、docs/marketing/、docs/specs/oidrune-mvp/assets/logo/proof/)。

Contract status

R1–R8 已按公开 Oidrune main 基线 4b5901a8827731ea06a05211dc6edf06e46783bc 与稳定发布 v0.1.18 逐项复核;其中 R4 的成对 override 细节由 README、配套 workflow example 和 checked-in reusable workflow 共同提供。公开 playbook 的投影额外通过 public release scan,拒绝 loopback 地址、本机路径、私有部署地址和 secret-like values。

Taxonomy

  • Tags: README content contract, GitHub Actions scheduling, GitHub reusable workflow

Repository map

  • Entrypoints: README.md 与 README.zh-CN.md 是双语入口并在顶部互链;src/worker/ 提供 OIDC ingress、admin API、Queue consumer 和 delivery logic;src/console/ 提供 same-origin operator console 与 deterministic local demo;docs/notify-example.md 提供 caller integration example。
  • Important directories: migrations/ 保存 D1 schema migrations;.github/workflows/ 保存 reusable notification、CI、release、deploy 与 smoke workflows;docs/specs/ 保存长期 spec、实现状态和局部历史;docs/adr/ 保存不可逆设计取舍;docs/quality-gates.md 与 .github/quality-gates.json 保存 merge/release policy source。
  • Published surfaces: Worker Static Assets 承载 console build;Cloudflare Worker、D1、delivery Queue、dead-letter Queue、replay-protection Durable Object、Cloudflare Access 和 Telegram delivery 共同构成部署面(README.md、wrangler.jsonc、docs/specs/oidrune-mvp/IMPLEMENTATION.md)。当前仓库证据不支持把它描述为独立 docs-site 或文档发布项目。
  • Ownership boundaries: caller repository 只提供 full-SHA reusable workflow、id-token: write 和 caller-owned summary;Oidrune 管理 admission、durable handoff、Telegram destination 和 operator policy;Cloudflare/GitHub deployment metadata、Access policy、Operator identity 与 Worker secrets 属于仓库外配置(README.md、docs/specs/oidrune-mvp/contracts/http.md、docs/specs/oidrune-mvp/IMPLEMENTATION.md)。

Runtime and delivery

  • Local quick start: 要求 Bun >=1.4.0,执行 bun install 后运行 bunx vite --config vite.demo.config.ts 即可启动 deterministic console demo;该 demo 不访问 Cloudflare Access、D1、Queues 或 Telegram。公开 playbook 只保留可执行命令,不发布 demo 的本地地址(README.md、README.zh-CN.md)。
  • Build and package: package.json 以 Bun 作为 package manager;bun run check、bun run typecheck、bun run test:unit、bun run test:integration、bun run build、bun run test:e2e 和聚合命令 bun run quality 分别覆盖格式/静态检查、类型、单测、Worker integration、构建和 console E2E(package.json、.github/workflows/ci-pr.yml)。
  • Release / deploy: Release 只接受从 main 手动 dispatch 的一个 release_target,支持 patch、minor、major 或 final X.Y.Z;它从最新已验证 stable Release 解析版本,创建或复用 durable Draft Release identity,发布同一 identity,然后自动进入独立 Deploy 阶段,最后才把同一 source SHA promote 为 trusted workflow release(docs/adr/0008-manual-version-release-delivery.md、.github/release-contract.json、docs/quality-gates.md)。
  • Smoke path: .github/workflows/oidrune-smoke.yml 是显式手动入口,调用 SHA-pinned reusable workflow,要求 public gateway 返回 202,再验证同一 run_id 与 caller-provided summary 在 D1 中达到 delivered;它验证已配置部署的端到端路径,但不需要 caller repository secret(README.md、.github/workflows/oidrune-smoke.yml)。
  • External configuration boundary: Cloudflare resources、Access policy、GitHub Ruleset、Telegram target、Worker secrets、deployment metadata 和 operator identity 是 deployment-time inputs;它们可以被实现文档列为待配置事项,但不能被快照写成已完成的外部 alignment,也不能把真实部署标识复制到公开索引(docs/specs/oidrune-mvp/IMPLEMENTATION.md、docs/quality-gates.md)。

Architecture notes

  • Data flow: caller 的 final notify job 请求短期 GitHub OIDC token,调用 full-SHA notify.yml;Worker 验证 issuer/signature/audience/claims、source allowlist、trusted workflow SHA、replay guard 和 normalized summary,写入 D1 并 enqueue 后返回 202 Accepted;Queue consumer 负责 Telegram retry,耗尽后进入 DLQ、audit records 和 operator console(README.md、docs/specs/oidrune-mvp/SPEC.md、docs/adr/0002-durable-asynchronous-delivery.md)。
  • Async contract: 202 Accepted 只表示事件已经完成 durable handoff,不表示 Telegram delivery 已完成;on_gateway_failure: warn 或 fail 只影响 notification job,不能改变已经完成的 release,且 caller-provided summary 是最终正文(README.md、docs/specs/oidrune-mvp/contracts/http.md、docs/notify-example.md)。
  • API / workflow boundaries: POST /v1/events/workflow-completed 是公开但 OIDC-authenticated 的 ingress;/api/admin/* 由 Cloudflare Access 保护;notify.yml 的 inputs 包含 outcome、summary、on_gateway_failure 以及成对的 gateway override inputs,caller 不传 secrets:(docs/specs/oidrune-mvp/contracts/http.md、docs/notify-example.md)。
  • Storage and delivery: D1 保存 normalized events、delivery attempts、release snapshots、trusted workflow releases 和 audit trail;Queue/DLQ 提供 at-least-once handoff,Durable Object 负责 OIDC jti replay protection,delivery claim lease 限制同一事件的 active Telegram attempt(docs/specs/oidrune-mvp/IMPLEMENTATION.md、docs/adr/0002-durable-asynchronous-delivery.md、docs/adr/0005-leased-delivery-claims.md)。
  • Gateway selection: HTTPS endpoint 与 OIDC audience 是不可分割的 gateway selection pair;explicit workflow pair 优先于 caller Variables pair,再回退到 Default Gateway,partial pair 在请求 OIDC token 前拒绝(CONTEXT.md、docs/notify-example.md、.github/workflows/notify.yml)。

Workflow and quality gates

  • Tests and CI: CI PR 并行执行 Biome check、TypeScript typecheck、unit tests、Worker integration、dependency scan、Worker build 和 console E2E,quality job 只有在全部 predecessor 成功时才通过;CI Main 在 main push 后重复生产相关检查(.github/workflows/ci-pr.yml、.github/workflows/ci-main.yml)。
  • Repository gate contract: docs/quality-gates.md 与 .github/quality-gates.json 声明 main PR-only、verified signatures、full-SHA Actions、quality required check 和无 waiver;这些 checked-in 文件证明 intended policy,不等于已完成 GitHub Ruleset live alignment(docs/quality-gates.md、.github/quality-gates.json)。
  • Release gates: Release 验证当前 main source、CI Main、stable baseline、tag/release ownership、reservation 和 same-identity recovery;Deploy 对同一发布身份部署并验证 route boundary;PR labels 与 workflow run numbers 不决定发布(docs/adr/0008-manual-version-release-delivery.md、docs/specs/oidrune-mvp/IMPLEMENTATION.md、.github/release-contract.json)。
  • Failure visibility: 独立的 Release Failure Notification reusable workflow 对 validation、reservation、Release 和 Deploy failure 发送 metadata-only context;通知失败不应被写成 release 或 deployment 成功,202 也不应被误读为 Telegram delivery success(docs/quality-gates.md、.github/release-contract.json、docs/specs/oidrune-mvp/contracts/http.md)。

Reusable decisions

  • README 内容要求以本节 R1–R8 为 canonical contract;Reusable decisions 只保留可推广的结论,避免用概括性 prose 取代可审查条目(README.md、README.zh-CN.md、projects/oidrune.md)。
  • 文档真相源要按消费者分层:产品范围看 PRODUCT.md,领域术语看 CONTEXT.md,长期行为看 docs/specs/oidrune-mvp/SPEC.md,实现和 rollout 看 IMPLEMENTATION.md,协议看 contracts/http.md,持久取舍看 docs/adr/,门禁看 docs/quality-gates.md,主题 hierarchy 看 docs/specs/README.md(README.md、docs/specs/README.md)。
  • Manual Version Release Delivery 的默认边界是一个 owner-provided target、trusted stable baseline、durable reservation、同一 source identity 的 Release/Deploy 和 same-identity recovery;版本不能从 PR label、merge 顺序或 workflow run number 推导,部署失败不能静默分配 successor(docs/adr/0008-manual-version-release-delivery.md、.github/release-contract.json)。
  • License 应在 README 文档地图之后保留可点击的 MIT License 链接;public entrypoint 不应让用户猜测许可证文件位置(README.md、README.zh-CN.md、LICENSE)。

Risks and open questions

  • docs/specs/oidrune-mvp/IMPLEMENTATION.md 一方面记录 MVP source、validation suites、reusable workflow 和 CI 已在仓库中实现,另一方面保留“尚未初始化源码或外部资源”的 catalog note;快照因此把 checked-in implementation 与 external provisioning 分开记录,不把后者宣称为已完成。
  • docs/specs/README.md 的 Implementation 栏仍写着 未开始,与 IMPLEMENTATION.md 和当前 source tree 不一致;这是文档治理风险,应由 Oidrune 后续维护者在源仓库内修正,不能由本次 playbook 入库替它改写。
  • docs/quality-gates.md、.github/quality-gates.json 和 workflows 能证明 intended contract 与执行入口,但不能单独证明 GitHub Ruleset、verified-signature enforcement、Cloudflare Access、Telegram destination 或生产 smoke test 已完成;这些是需要 owner 授权的外部检查。
  • 当前 release 实现是 Manual Version Release Delivery;PR label release 只在 release contract 的排除项和 ADR 的反例中出现,不能作为 Oidrune 的当前 Topic 标签或发布方案。
  • 生产部署需要 Cloudflare、GitHub Ruleset、Access、Telegram 和 secrets 等外部配置;公开 snapshot、catalog、Topic reports 与 search payload 只能保留责任边界和仓库相对证据,不应写入 deployment identifiers、operator identities、tokens、loopback 地址、私有路径或敏感部署地址。

Evidence index

  • README.md
  • README.zh-CN.md
  • PRODUCT.md
  • CONTEXT.md
  • LICENSE
  • package.json
  • wrangler.jsonc
  • docs/decision-memo.md
  • docs/notify-example.md
  • docs/quality-gates.md
  • docs/specs/README.md
  • docs/specs/oidrune-mvp/SPEC.md
  • docs/specs/oidrune-mvp/IMPLEMENTATION.md
  • docs/specs/oidrune-mvp/contracts/http.md
  • docs/adr/0002-durable-asynchronous-delivery.md
  • docs/adr/0005-leased-delivery-claims.md
  • docs/adr/0006-portable-gateway-selection.md
  • docs/adr/0008-manual-version-release-delivery.md
  • .github/quality-gates.json
  • .github/release-contract.json
  • .github/workflows/ci-pr.yml
  • .github/workflows/ci-main.yml
  • .github/workflows/notify.yml
  • .github/workflows/oidrune-smoke.yml
  • .github/workflows/release.yml
  • https://github.com/IvanLi-CN/oidrune/tree/4b5901a8827731ea06a05211dc6edf06e46783bc
  • https://github.com/IvanLi-CN/oidrune/releases/tag/v0.1.18