Files
wehub-resource-sync 426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00
..

Certification trust anchor

certification-public-key.pem is the Ed25519 public key that the develop→main promotion gate trusts. A certification.json (produced by bun run --cwd packages/evidence certify:sign) is a signed claim that a holder of the matching private key reviewed a specific evidence bundle for a specific commit. Verification logic lives in packages/evidence/src/certify/sign.ts; the CI workflow must stay a thin caller of certify:verify and perform no verification logic of its own (#14546 / #14547).

Trusted key fingerprint: 3ac9e3e625a9ed2f (first 16 hex of sha256 over the SPKI DER). packages/evidence/src/certify/committed-key.test.ts asserts the committed PEM matches this fingerprint, so an accidental or malicious pem swap fails the test suite as well as review. This key was provisioned during the epic #14541 bootstrap; its private half lives in the ELIZA_CERT_SIGNING_KEY repo secret. Rotation (procedure below) is cheap and may be performed at any time by the repo owner — merging a PR that replaces the pem and this fingerprint is the act of trusting a new key. There is deliberately no default trust anchor in code: certify:verify requires an explicit --pubkey.

Trust model — binding rules for the CI gate (#14547)

  • Read the public key from the BASE branch (main), never from the PR head. The gate must check out main's copy of this file (e.g. git show origin/main:.github/certification/certification-public-key.pem) and pass it via --pubkey. If the gate read the key from the PR head, an attacker could swap the key and a matching self-signed certification in a single PR and the gate would happily verify their own signature. Key changes only become trusted after they land on main through review.
  • The private key is never in the repo. It lives only in the ELIZA_CERT_SIGNING_KEY secret (PEM or base64-wrapped PEM) on the signing runner, and in the local env/keychain of authorized certifiers. No tool in this repo writes a private key to disk; certify:keygen prints it only under the explicit --print-private-key flag.
  • What a valid signature proves: a keyholder signed exactly these verdicts over exactly this bundle manifest (bundleSha) for exactly this commit. What it does not prove: that the review was diligent. That is why the reviewer identity ({kind, id, model?}) is part of the signed payload and must be surfaced in the gate's check summary.

Verify contract (what the workflow calls)

bun run --cwd packages/evidence certify:verify -- \
  --cert <path/to/certification.json> \
  --bundle <bundle-dir> \
  --pubkey <base-branch-checkout>/.github/certification/certification-public-key.pem \
  --expected-commit <cert.commit> \
  --max-age-hours 72 \
  --required-tier full \
  [--requirements <requirements.json>] \
  --json

Exit 0 iff valid. --json prints the full report on stdout, including failures: [{code, message, context}] with distinct codes (schema-invalid | unsigned | bad-signature | wrong-key | stale | commit-mismatch | bundle-tampered | verdict-failures | verdict-incomplete | tier-insufficient); all detectable failures are reported together, not first-failure-only.

For the required develop→main gate, --bundle is mandatory. Without the bundle, verification can only prove that the JSON was signed by the trusted key; it cannot prove the signed bundleSha matches real artifacts, that every mechanically-derived lane/analysis subject was reviewed, or that verdict evidence paths actually exist. Omitting --bundle is only for detached signature inspection, never for promotion. With a bundle, verification also re-runs the mechanical rollup: mechanically non-pass subjects may be signed as fail or waived with notes, but never omitted or signed as pass.

Key rotation

  1. An authorized engineer runs bun run --cwd packages/evidence certify:keygen -- --print-private-key on a trusted machine (never in CI logs).
  2. Open a PR replacing certification-public-key.pem and the fingerprint in this README. The PR must be reviewed and merged to main like any other change — merging it is the act of trusting the new key.
  3. Update the ELIZA_CERT_SIGNING_KEY repo secret (and any local certifier copies) to the new private key.
  4. Certifications signed by the old key stop verifying the moment the new public key is on main (wrong-key). Re-certify in-flight promotions.

Compromise response is the same procedure, performed immediately; the old key needs no explicit revocation because the gate trusts exactly one key — the one on main.

The CI gate (#14547): certification-verify.yml

.github/workflows/certification-verify.yml runs on every non-draft PR targeting main and is the promotion gate. What it does, in order:

  1. Checks out the PR head commit (not the synthetic merge ref) and reads the trusted public key from the base branch per the trust model above.
  2. Locates the certification and bundle: certification.json committed at the repo root of the promotion branch and the signed evidence bundle committed at evidence/bundle/. Missing either file = red, with remediation instructions in the check summary. The gate always passes --bundle evidence/bundle so artifact integrity, rollup completeness, and signed evidence-path membership are re-derived from the committed bundle.
  3. Runs scripts/certification/check-commit-drift.mjs: the certified commit must equal the PR head, or be an ancestor whose diff to head touches only the docs/template allowlist — docs/**, packages/docs/**, any *.md, plus the certification artifacts themselves (certification.json, evidence/bundle/** — those necessarily land after the signed commit and are protected by the signature and bundleSha, not by the drift rule). Any other source, workflow, policy, or config drift = re-certify.
  4. Runs certify:verify (the contract above) with --expected-commit <cert.commit> --max-age-hours 72 --required-tier full.
  5. Writes a check summary with the reviewer identity, tier, age, signed verdict table (waived rows surfaced with notes), drifted paths, trusted key fingerprint, and every failure code verbatim. Verification only — the gate never performs evidence review.

Branch protection (admins)

Add the required status check verify-certification (the job name in certification-verify.yml) to main's branch protection. This is a manual admin step — the workflow does not (and must not) edit branch protection. Keep the name stable; renaming the job orphans the required check and blocks every promotion. The companion certification-verify-selftest job is CI for the gate's own plumbing (runs only on PRs touching it) and must not be made a required check.

Bootstrap: until this directory's public key and packages/evidence exist on main, the gate fails closed on every promotion PR ("no trusted public key on main"). The first promotion that carries the certification stack to main needs a one-time admin bypass; every promotion after it is fully gated.

Residual risk (accepted): pull_request-triggered workflows execute the PR's own merged workflow definition, so a promotion PR that edits the gate files could neuter the check. The drift check refuses to allowlist those paths, the diff is plainly visible to the human merger, and promotion PRs are human-reviewed by definition. Hardening to pull_request_target (base branch runs the workflow) is a possible follow-up.

Remediation runbook (gate is red)

  1. Preferred: dispatch the vast certification workflow for the promoted commit; it produces the bundle, review, and signed certification.json.

  2. Local fallback (requires a certifier holding ELIZA_CERT_SIGNING_KEY):

    bun run --cwd packages/evidence bundle:create -- --tier full
    bun run --cwd packages/evidence certify:rollup -- --bundle <bundle-dir> --out verdicts.json
    # review verdicts.json by hand — waivers require notes
    bun run --cwd packages/evidence certify:sign -- --bundle <bundle-dir> \
      --verdicts verdicts.json --reviewer-id <you> --reviewer-kind human
    cp <bundle-dir>/certification.json ./certification.json  # commit on the promotion branch
    rm -rf evidence/bundle && mkdir -p evidence && cp -R <bundle-dir> evidence/bundle
    
  3. stale (>72h) or commit-mismatch/drift failures always mean the same thing: re-run certification at the current head. There is no override flag by design.

Break-glass (emergencies)

Push to main is a production deploy, so the gate must be watertight — but it must not brick emergencies. The break-glass path is not a code path: a repository admin bypasses the required certification-verify check via branch-protection admin override. Every such bypass is visible in the GitHub audit log; there is deliberately no in-repo flag, env var, or alternate verification mode that skips signature checks. The required check being bypassed is verify-certification (see the CI gate section above) — that is the exact string admins bypass and auditors grep for.