fix: make tunnel webhook mounts recoverable - #502
Draft
PerishCode wants to merge 1 commit into
Draft
Conversation
quangdang46
reviewed
Jun 21, 2026
quangdang46
left a comment
There was a problem hiding this comment.
Hermes QA Report | PR #502
Verdict: COMMENT β Code changes are clean and well-structured. Design follows AGENTS.md guidelines. Blocked on required @oracle review per PR body.
Quality Gates
| Check | Result |
|---|---|
go vet ./... |
β PASS |
go build ./... |
β PASS |
go test ./internal/runtime/... |
β PASS (all tunnel/webhook tests) |
| Targeted tunnel/webhook tests | β PASS |
Code Review Summary
Positives:
- Clean HMAC-SHA256 mount ID derivation from repo+secret β deterministic, stable, properly handles empty secrets
findReusableTunnelHookcorrectly guards against duplicate adoption (error on multiple mount-marked hooks) and rejects plain legacy URL matches outrightreconcileRecordedTunnelHookextraction keeps the logic readable and testable- ADR 0006, docs/configuration.md, and docs/users-guide.md all updated to document the new mount-marker recovery path
- All existing tests updated to expect mount-marked URLs β no regressions
Design compliance: Authority is grounded in the local HMAC secret, not agent output or remote state inference. Trade-off (query marker in URL, list-before-create latency, new recovery branch) is documented. Matches AGENTS.md requirements.
Merge blocker: PR body requests @oracle review for this authority-bearing change. Oracle review must complete before merge.
Recommendation: Code ready. Merge after @oracle review approval.
Reviewed at 2026-06-21 from Hermes QA cron.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
looper_mountmarker to tunnel webhook managed URLs, derived from the local per-repo HMAC secretAuthority
The authority for re-recording a tunnel webhook is the locally held per-repo HMAC secret, materialized as a deterministic
looper_mountmarker in the GitHub hook URL. It is not the agent output and not a generic remote hook shape; plain URL, name, events, or user-supplied hook ids still do not authorize adoption.Trade-off
This prevents Looper from creating duplicate tunnel webhooks when the SQLite row is lost but the local secret survives. The cost is a visible opaque query marker in managed URLs, one
gh api repos/:repo/hookslist before first create, and a new recovery branch to keep in sync with the existing hook-id lifecycle. A simpler plain-URL adoption rule was rejected because it cannot prove Looper ownership and would repeat the unsafe direction from #487.This is authority-bearing and should receive
@oraclereview before merge.Validation
go test ./internal/runtimego vet ./...go build ./...go test ./...was run; it failed only ininternal/agentexecutor timeout tests (TestExecutorStartSanitizesChildEnvAndUsesWorkingDirectory,TestExecutorFallsBackAfterFailedNativeResumeAttempt,TestExecutorNativeResumeFailureAfterAttachDoesNotFallback), whileinternal/runtimeand the remaining completed packages passed.