Skip to content

fix(selfhost): fail preflight on half-configured ledger anchoring instead of silently skipping it - #9771

Merged
loopover-orb[bot] merged 1 commit into
mainfrom
fix/anchor-config-preflight
Jul 29, 2026
Merged

fix(selfhost): fail preflight on half-configured ledger anchoring instead of silently skipping it#9771
loopover-orb[bot] merged 1 commit into
mainfrom
fix/anchor-config-preflight

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Anchoring has nine LOOPOVER_LEDGER_ANCHOR_* vars, all documented in env.d.ts and all genuinely read — and not one appeared in any self-host preflight or config-lint. An operator got zero boot-time guidance.

That matters more than a normal missing-config warning because the failure is completely silent: runScheduledLedgerAnchor logs ledger_anchor_skipped_unconfigured and returns (ledger-anchor-scheduler.ts:113-121), while the job keeps firing every ~2 minutes doing two queries and nothing else.

And the stakes are higher than they look: a self-host container already runs the anchor scheduler (src/index.ts:145src/server.ts:1322-1339processJob directly, bypassing the hosted ack-and-drop) and already has a populated decision_ledger. It is genuinely one keypair away from real anchoring, and nothing tells the operator that.

Closes #9769

What changed

Anchoring stays opt-in. Configuring none of it is deliberately not a problem — preflightEnv's problems are fatal (assertSelfHostPreflight throws), and turning an optional feature into a boot requirement would be a worse bug than the one being fixed. There's an invariant test pinning that so a future edit can't quietly do it.

What now fails preflight is partial configuration — every case of which silently disables anchoring while looking configured:

Case Why it's silent today
published keys, no private half scheduler skips; nothing surfaces
private key, nothing published anchors would be unverifiable; scheduler skips
key list parses to zero usable entries malformed JSON and entries missing a required field are both dropped silently by parseAnchorPublicKeys
no entry with notAfter: null, or more than one currentAnchorKey fails closed on an ambiguous rotation rather than guessing which key signs
git owner/repo with no installation id no write token can be minted, so job-dispatch resolves submitGit to null and the backend is skipped
non-positive-integer installation id, or half a git target same silent skip

The key checks call the real parseAnchorPublicKeys/currentAnchorKey rather than re-validating the shape locally, so preflight can never disagree with what the scheduler will actually do. A second hand-written copy of those rules is precisely how this drifts apart again.

Validation

Check Result
Patch coverage 80 changed lines, 0 uncovered, 0 partial branches
selfhost-preflight suite 39 tests pass (10 new)
typecheck · ui:typecheck · selfhost:validate-observability · selfhost:env-reference:check · git diff --check all clean

The ambiguous-rotation case is worth calling out as a test: two entries with notAfter: null is the one an operator is most likely to create during a rotation, and it fails closed at runtime with no message.

Regenerated artifact

apps/loopover-ui/src/lib/selfhost-env-reference.ts — required, since preflight now reads these vars under src/selfhost/**. Worth naming as a side benefit rather than noise: all five anchor vars now appear in the generated operator-facing env documentation for the first time, which is itself part of the problem #9769 describes.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (e.g. Closes #123) — a linked open issue is required for every contributor PR.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks.
  • Visible UI changes include a UI Evidence section below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. SVG screenshots are not used as review evidence. Review-only screenshots or recordings are not committed to the repository.
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs.

This reads key metadata only — keyId, publicKeySpki, notBefore/notAfter — and never the private key's contents, only whether it is set. No key material reaches a preflight message; every message names the variable and the consequence. The only rendered output is the generated env-reference table, which lists variable names and the file that reads them, so there is no UI Evidence table.

Notes

Decision-independent by design: this is correct under every option on #9719, including the one where anchoring stays a per-deployment capability and the hosted list stays empty on purpose.

…tead of silently skipping it

Anchoring has nine LOOPOVER_LEDGER_ANCHOR_* vars, all documented in env.d.ts and
all genuinely read, and not one of them appeared in any self-host preflight or
config-lint. An operator got zero boot-time guidance.

That matters more than a normal missing-config warning because the failure is
completely silent: runScheduledLedgerAnchor logs ledger_anchor_skipped_unconfigured
and returns, while the job keeps firing every couple of minutes doing two queries
and nothing else. A self-host container DOES run the scheduler and DOES have a
populated decision_ledger, so it is genuinely one keypair away from working -- and
nothing tells the operator that.

Anchoring stays OPT-IN: configuring none of it is deliberately not a problem, and
there is an invariant test pinning that so a future edit cannot turn an optional
feature into a boot requirement. What now fails preflight is PARTIAL
configuration, every case of which silently disables anchoring while looking
configured:

  - a published key list with no private half, or a private key with nothing
    published (anchors would be unverifiable)
  - a key list that parses to zero usable entries -- malformed JSON and entries
    missing a required field are both dropped silently at runtime
  - no entry with notAfter: null, or MORE than one: currentAnchorKey fails closed
    on an ambiguous rotation rather than guessing which key signs
  - a git owner/repo without an installation id (no write token can be minted, so
    job-dispatch resolves submitGit to null), a non-positive-integer id, or half a
    git target

The key checks call the real parseAnchorPublicKeys/currentAnchorKey rather than
re-validating the shape locally, so preflight can never disagree with what the
scheduler will actually do -- a second hand-written copy of those rules is exactly
how this drifts back apart.

Regenerating the self-host env reference is a side benefit worth naming: because
preflight now reads these vars under src/selfhost/**, all five appear in the
generated operator-facing env documentation for the first time.

Closes #9769
@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-29 07:53:29 UTC

3 files · 1 AI reviewer · no blockers · readiness 98/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This adds a new `checkLedgerAnchorConfig` preflight check that flags partial/ambiguous ledger-anchor configuration (published key without private half, private key without published keys, key lists that parse to zero usable entries, ambiguous/missing current signing key, and half-configured git anchor targets) while correctly leaving fully-unconfigured anchoring alone. It reuses the real `parseAnchorPublicKeys`/`currentAnchorKey` from `../review/ledger-anchor` rather than re-implementing validation, which keeps preflight from disagreeing with runtime behavior, and the invariant test (`preflightEnv(base)` returns `ok:true`) pins the opt-in requirement so a future edit can't turn this into a boot-blocking requirement. The `selfhost-env-reference.ts` additions are a generated-looking table update consistent with the new vars, and the test suite exercises every branch (both key/private-key directions, malformed JSON, zero/ambiguous open-ended keys, git owner/repo/installation-id combinations) with concrete assertions on `.var` and `.message`.

Nits — 6 non-blocking
  • src/selfhost/preflight.ts: the `apps/loopover-ui/src/lib/selfhost-env-reference.ts` file is marked 'Generated by scripts/gen-selfhost-env-reference.ts. Do not edit manually.' — confirm the diff's additions were produced by rerunning the generator rather than hand-edited, since a hand-edit could silently drift from the generator's actual output on the next regen.
  • src/selfhost/preflight.ts:135 (git installation-id regex `/^[1-9][0-9]*$/`) rejects a leading-zero id like "042" even though GitHub installation IDs are plain decimal numbers that could theoretically be typed with a leading zero — low risk, but worth confirming this matches how the id is sourced elsewhere.
  • The `checkLedgerAnchorConfig` function nests four independent concern blocks (keys/private-key pair, key-list parse, git owner/repo, installation id) in one function — consider splitting into two functions (rekor-keys vs git-target) for readability, though current length is still manageable.
  • Consider extracting the git-target validation (owner/repo/installation-id) into its own helper, e.g. `checkLedgerAnchorGitTarget`, to reduce nesting depth flagged in review tooling and make each concern independently testable.
  • If `LOOPOVER_LEDGER_ANCHOR_GIT_INSTALLATION_ID` is ever sourced as a string with a leading zero from an operator's env file, verify that's an intentional rejection rather than an oversight of the `[1-9][0-9]*` regex.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #9769
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 14 registered-repo PR(s), 13 merged, 370 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 14 PR(s), 370 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: significant
Linked issue satisfaction

Partially addressed
The PR adds solid preflight coverage for LOOPOVER_LEDGER_ANCHOR_KEYS/_PRIVATE_KEY and the git owner/repo/installation-id trio, matching the issue's 'partially configured' cases and its three-state design, but it never touches src/selfhost/config-lint.ts (explicitly named in the issue) and doesn't address LOOPOVER_LEDGER_ANCHOR_REPORT_TOKEN or the git BRANCH/PATH vars, so part of the nine-var scope

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: not available
  • Official Gittensor activity: 14 PR(s), 370 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 1 step in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
loopover-ui 36d88f0 Commit Preview URL

Branch Preview URL
Jul 29 2026, 07:36 AM

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bundle Report

Changes will decrease total bundle size by 20.36kB (-0.26%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
loopover-ui 7.81MB -20.36kB (-0.26%) ⬇️

Affected Assets, Files, and Routes:

view changes for bundle: loopover-ui

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/add-scalar-classes-LF8tiZnL.js (New) 2.16MB 2.16MB 100.0% 🚀
assets/tanstack-vendor-vA4ZhtEl.js (New) 915.66kB 915.66kB 100.0% 🚀
openapi.json -1.34kB 717.11kB -0.19%
assets/docs.fumadocs-spike-api-reference-CEx9Bhmh.js (New) 443.45kB 443.45kB 100.0% 🚀
assets/AgentScalarChatInterface.vue-D6xHIxnb.js (New) 201.7kB 201.7kB 100.0% 🚀
assets/modal-CzICDv21.js (New) 184.5kB 184.5kB 100.0% 🚀
assets/client-DRZqOCal.js (New) 151.47kB 151.47kB 100.0% 🚀
assets/self-hosting-configuration-BsNvoh6W.js (New) 102.71kB 102.71kB 100.0% 🚀
assets/maintainer-panel-D6DJJ8oQ.js (New) 78.99kB 78.99kB 100.0% 🚀
assets/what-you-can-verify-O9XQoPIZ.js (New) 54.77kB 54.77kB 100.0% 🚀
assets/routes-DFZGEuJC.js (New) 35.96kB 35.96kB 100.0% 🚀
assets/owner-panel-cAjNXT9x.js (New) 27.97kB 27.97kB 100.0% 🚀
assets/app-AbPpNPTG.js (New) 25.78kB 25.78kB 100.0% 🚀
assets/ui-vendor-CvH_QZEK.js (New) 24.57kB 24.57kB 100.0% 🚀
assets/miner-panel-DNGD6qtd.js (New) 20.24kB 20.24kB 100.0% 🚀
assets/app.runs-DmrTxbsK.js (New) 20.22kB 20.22kB 100.0% 🚀
assets/api._op-bFGwHlO5.js (New) 17.57kB 17.57kB 100.0% 🚀
assets/self-hosting-docs-audit-CAsAoXzM.js (New) 16.6kB 16.6kB 100.0% 🚀
assets/docs._slug-pclZy9kj.js (New) 15.52kB 15.52kB 100.0% 🚀
assets/playground-panel-G6uFe85R.js (New) 14.42kB 14.42kB 100.0% 🚀
assets/fairness-DQy82wRG.js (New) 12.16kB 12.16kB 100.0% 🚀
assets/app.audit-Cm7QDeqh.js (New) 10.08kB 10.08kB 100.0% 🚀
assets/app.config-generator-zEeX1qxU.js (New) 10.06kB 10.06kB 100.0% 🚀
assets/maintainers-CQrj63KJ.js (New) 8.06kB 8.06kB 100.0% 🚀
assets/miners-DujWdley.js (New) 7.91kB 7.91kB 100.0% 🚀
assets/agents-DmkaV2Al.js (New) 7.74kB 7.74kB 100.0% 🚀
assets/commands-panel-Ci_U_QLY.js (New) 6.65kB 6.65kB 100.0% 🚀
assets/maintainer-workflow-Co176aeo.js (New) 6.52kB 6.52kB 100.0% 🚀
assets/digest-panel-DYMdWyRd.js (New) 6.15kB 6.15kB 100.0% 🚀
assets/repos._owner._repo.quality-DWQk6EXV.js (New) 6.14kB 6.14kB 100.0% 🚀
assets/docs-nav-DLLS2MPK.js (New) 6.01kB 6.01kB 100.0% 🚀
assets/docs.index-CCkoMxCM.js (New) 5.95kB 5.95kB 100.0% 🚀
assets/api.index-D3t90Q_k.js (New) 4.7kB 4.7kB 100.0% 🚀
assets/docs-BGmnsj4F.js (New) 2.7kB 2.7kB 100.0% 🚀
assets/api-QmaNT7rj.js (New) 2.69kB 2.69kB 100.0% 🚀
assets/docs-page-nmxLsvfi.js (New) 2.1kB 2.1kB 100.0% 🚀
assets/table-VuZPaB5X.js (New) 1.75kB 1.75kB 100.0% 🚀
assets/app.workbench-DK3K9AVr.js (New) 1.58kB 1.58kB 100.0% 🚀
assets/tabs-D3DE-LDe.js (New) 1.39kB 1.39kB 100.0% 🚀
assets/app.repos-D2X_zWoX.js (New) 1.07kB 1.07kB 100.0% 🚀
assets/input-BGtO1-g3.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/file-cog-C28RPaeA.js (New) 758 bytes 758 bytes 100.0% 🚀
assets/app.maintainer-Cd7C0SCD.js (New) 502 bytes 502 bytes 100.0% 🚀
assets/app.owner-C8fPCYHk.js (New) 474 bytes 474 bytes 100.0% 🚀
assets/app.commands-BGFxBPGP.js (New) 455 bytes 455 bytes 100.0% 🚀
assets/app.playground-f4f8vSO3.js (New) 442 bytes 442 bytes 100.0% 🚀
assets/index-BQzfdamm.js (New) 438 bytes 438 bytes 100.0% 🚀
assets/app.digest-DMmN-PHP.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/eye-off-YBMYDOHH.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/app.miner-Dg6ZAGoc.js (New) 422 bytes 422 bytes 100.0% 🚀
assets/key-round-BlVF69H4.js (New) 355 bytes 355 bytes 100.0% 🚀
assets/bot-BWusECpz.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/trash-2-D0ohB0pS.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/save-CIsWGdJQ.js (New) 327 bytes 327 bytes 100.0% 🚀
assets/git-pull-request-arrow-BJpa1UHu.js (New) 321 bytes 321 bytes 100.0% 🚀
assets/list-checks-CSVk9L2b.js (New) 279 bytes 279 bytes 100.0% 🚀
assets/compass-Cfl6kBjQ.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/history-BUbnAzuJ.js (New) 237 bytes 237 bytes 100.0% 🚀
assets/message-square-nj928M-r.js (New) 233 bytes 233 bytes 100.0% 🚀
assets/lock-Vl6AimlL.js (New) 206 bytes 206 bytes 100.0% 🚀
assets/rotate-cw-DiAxrW7O.js (New) 201 bytes 201 bytes 100.0% 🚀
assets/play-Dt0iDqKI.js (New) 190 bytes 190 bytes 100.0% 🚀
assets/circle-check-CmpJ9gJ5.js (New) 178 bytes 178 bytes 100.0% 🚀
assets/search-BiPF6Tfv.js (New) 174 bytes 174 bytes 100.0% 🚀
assets/add-scalar-classes-DZONjfDm.js (Deleted) -2.16MB 0 bytes -100.0% 🗑️
assets/tanstack-vendor-s4YLO76L.js (Deleted) -916.33kB 0 bytes -100.0% 🗑️
assets/docs.fumadocs-spike-api-reference-uMNOEYo9.js (Deleted) -443.45kB 0 bytes -100.0% 🗑️
assets/AgentScalarChatInterface.vue-D5X5QWfl.js (Deleted) -201.7kB 0 bytes -100.0% 🗑️
assets/modal-DhBTptaB.js (Deleted) -184.5kB 0 bytes -100.0% 🗑️
assets/client-vrM1QUQ-.js (Deleted) -151.47kB 0 bytes -100.0% 🗑️
assets/self-hosting-configuration-CZNNH3OE.js (Deleted) -115.98kB 0 bytes -100.0% 🗑️
assets/maintainer-panel-CtEf8X4K.js (Deleted) -78.99kB 0 bytes -100.0% 🗑️
assets/what-you-can-verify-DRZe7pNw.js (Deleted) -59.84kB 0 bytes -100.0% 🗑️
assets/routes-C3N9fdVV.js (Deleted) -35.96kB 0 bytes -100.0% 🗑️
assets/owner-panel-CoNjc27T.js (Deleted) -27.97kB 0 bytes -100.0% 🗑️
assets/app-D6anuP4_.js (Deleted) -25.78kB 0 bytes -100.0% 🗑️
assets/ui-vendor-DoIjjHMU.js (Deleted) -24.57kB 0 bytes -100.0% 🗑️
assets/miner-panel-oCQMDO7L.js (Deleted) -20.24kB 0 bytes -100.0% 🗑️
assets/app.runs-BtZWbpsP.js (Deleted) -20.22kB 0 bytes -100.0% 🗑️
assets/api._op-D6-WfXWl.js (Deleted) -17.57kB 0 bytes -100.0% 🗑️
assets/self-hosting-docs-audit-BUddCv36.js (Deleted) -16.6kB 0 bytes -100.0% 🗑️
assets/docs._slug-D8HkrQHG.js (Deleted) -15.52kB 0 bytes -100.0% 🗑️
assets/playground-panel-C7IC392B.js (Deleted) -14.42kB 0 bytes -100.0% 🗑️
assets/fairness-DUM_FKM7.js (Deleted) -12.16kB 0 bytes -100.0% 🗑️
assets/app.audit-VsgFiC16.js (Deleted) -10.08kB 0 bytes -100.0% 🗑️
assets/app.config-generator-CosSJkNI.js (Deleted) -10.06kB 0 bytes -100.0% 🗑️
assets/maintainers-CF2qPk8F.js (Deleted) -8.06kB 0 bytes -100.0% 🗑️
assets/miners-6FkILotw.js (Deleted) -7.91kB 0 bytes -100.0% 🗑️
assets/agents-DtJ5KCtQ.js (Deleted) -7.74kB 0 bytes -100.0% 🗑️
assets/commands-panel-EHqfW70C.js (Deleted) -6.65kB 0 bytes -100.0% 🗑️
assets/maintainer-workflow-BNWHOPqX.js (Deleted) -6.52kB 0 bytes -100.0% 🗑️
assets/digest-panel-CODBmjmn.js (Deleted) -6.15kB 0 bytes -100.0% 🗑️
assets/repos._owner._repo.quality-BuSizVG7.js (Deleted) -6.14kB 0 bytes -100.0% 🗑️
assets/docs-nav-Dvxhkc0i.js (Deleted) -6.01kB 0 bytes -100.0% 🗑️
assets/docs.index-Mc1jyIsE.js (Deleted) -5.95kB 0 bytes -100.0% 🗑️
assets/api.index-C_a__Z06.js (Deleted) -4.7kB 0 bytes -100.0% 🗑️
assets/docs-lVtEn1JX.js (Deleted) -2.7kB 0 bytes -100.0% 🗑️
assets/api-BCfnvGkA.js (Deleted) -2.69kB 0 bytes -100.0% 🗑️
assets/docs-page-MQCYFk8V.js (Deleted) -2.1kB 0 bytes -100.0% 🗑️
assets/table-Bzf4-z4N.js (Deleted) -1.75kB 0 bytes -100.0% 🗑️
assets/app.workbench-CPdd7K7P.js (Deleted) -1.58kB 0 bytes -100.0% 🗑️
assets/tabs-Qo9J3xzj.js (Deleted) -1.39kB 0 bytes -100.0% 🗑️
assets/app.repos-C8OpDE-X.js (Deleted) -1.07kB 0 bytes -100.0% 🗑️
assets/input-BvS_WXsB.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/file-cog-DYEh7oYZ.js (Deleted) -758 bytes 0 bytes -100.0% 🗑️
assets/app.maintainer-BFalmtYv.js (Deleted) -502 bytes 0 bytes -100.0% 🗑️
assets/app.owner-BbeCL0qj.js (Deleted) -474 bytes 0 bytes -100.0% 🗑️
assets/app.commands-CwrUETnY.js (Deleted) -455 bytes 0 bytes -100.0% 🗑️
assets/app.playground-DF-TwiJE.js (Deleted) -442 bytes 0 bytes -100.0% 🗑️
assets/index-DP9EBBQ_.js (Deleted) -438 bytes 0 bytes -100.0% 🗑️
assets/app.digest-BFR11FrD.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/eye-off-9W2g4l9-.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/app.miner-C5DlyFlX.js (Deleted) -422 bytes 0 bytes -100.0% 🗑️
assets/key-round-ByLd4ArU.js (Deleted) -355 bytes 0 bytes -100.0% 🗑️
assets/bot-BsB4zXvR.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/trash-2-CipOVcb4.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/save-BaKQamSK.js (Deleted) -327 bytes 0 bytes -100.0% 🗑️
assets/git-pull-request-arrow-j3syHqZn.js (Deleted) -321 bytes 0 bytes -100.0% 🗑️
assets/list-checks-DqzHzH2m.js (Deleted) -279 bytes 0 bytes -100.0% 🗑️
assets/compass-DRH3DWqg.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/history-Bd1R_QwD.js (Deleted) -237 bytes 0 bytes -100.0% 🗑️
assets/message-square-COPM2G8y.js (Deleted) -233 bytes 0 bytes -100.0% 🗑️
assets/lock-DetVN0Cp.js (Deleted) -206 bytes 0 bytes -100.0% 🗑️
assets/rotate-cw-B_E2f4TQ.js (Deleted) -201 bytes 0 bytes -100.0% 🗑️
assets/play-CdkJq3Ia.js (Deleted) -190 bytes 0 bytes -100.0% 🗑️
assets/circle-check-BngWXlNH.js (Deleted) -178 bytes 0 bytes -100.0% 🗑️
assets/search-pjFEWBBy.js (Deleted) -174 bytes 0 bytes -100.0% 🗑️

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.47%. Comparing base (e5cc2cd) to head (36d88f0).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9771      +/-   ##
==========================================
- Coverage   90.28%   89.47%   -0.82%     
==========================================
  Files         907      907              
  Lines      113363   113388      +25     
  Branches    26892    26902      +10     
==========================================
- Hits       102349   101450     -899     
- Misses       9683    10849    +1166     
+ Partials     1331     1089     -242     
Flag Coverage Δ
backend 94.07% <100.00%> (-1.48%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/selfhost/preflight.ts 100.00% <100.00%> (ø)

... and 3 files with indirect coverage changes

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 81cecee into main Jul 29, 2026
11 checks passed
@loopover-orb
loopover-orb Bot deleted the fix/anchor-config-preflight branch July 29, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

anchors: self-host preflight and config-lint say nothing about the nine LOOPOVER_LEDGER_ANCHOR_* vars

1 participant