Skip to content

fix(connections): mount connection routes in the HTTP server#17

Merged
dealako merged 5 commits into
mainfrom
fix/LFXV2-2556-mount-connection-routes
Jul 14, 2026
Merged

fix(connections): mount connection routes in the HTTP server#17
dealako merged 5 commits into
mainfrom
fix/LFXV2-2556-mount-connection-routes

Conversation

@mrautela365

Copy link
Copy Markdown
Contributor

The connection service is wired in the DI container (PR #9) but was never mounted in the HTTP muxer, so every /projects/{projectId}/connection-* route returned 404 in the running binary even though the handlers existed.

This mounts the generated connection server, guarded on cont.Connections (which is non-nil even without a database — nil repo → typed 503 rather than a bare 404).

Why it slipped through: an unmounted Goa service still compiles as dead code, so go build/tests pass. Introduced when PR #9 was reconstructed onto main and server.go was not among the cherry-picked files.

LFXV2-2556

🤖 Generated with Claude Code

@mrautela365 mrautela365 requested a review from a team as a code owner July 9, 2026 18:15
Copilot AI review requested due to automatic review settings July 9, 2026 18:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a wiring gap where the connection service was registered in the DI container (from PR #9) but never mounted in the HTTP muxer, causing all /projects/{projectId}/connection-* routes to return a bare 404 in the running binary. It mounts the generated connections Goa server, guarded on cont.Connections, so the routes are served (returning the typed 503 when the DB is unavailable rather than 404).

Changes:

  • Build connection endpoints from cont.Connections and apply the debug payload-logging middleware when cfg.Debug is set.
  • Thread connEndpoints through handleHTTPServer and mount the generated connections server on the shared muxer, reusing the existing error handler.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

MRashad26
MRashad26 previously approved these changes Jul 9, 2026
Copilot AI review requested due to automatic review settings July 10, 2026 22:52
@mrautela365 mrautela365 force-pushed the fix/LFXV2-2556-mount-connection-routes branch from 9d4fe78 to 61acc37 Compare July 10, 2026 22:52
@mrautela365 mrautela365 requested a review from a team as a code owner July 10, 2026 22:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread cmd/campaign-service/server.go Outdated
@mrautela365

Copy link
Copy Markdown
Contributor Author

Rebased onto main to pick up #24's MegaLinter/gitleaks fix — the previous red MegaLinter run predated that merge. Single commit, no conflicts; required checks (License Header, DCO, Build and Test) green. Ready for review.

Copilot AI review requested due to automatic review settings July 10, 2026 23:45
@mrautela365 mrautela365 force-pushed the fix/LFXV2-2556-mount-connection-routes branch from 61acc37 to 3035f9f Compare July 10, 2026 23:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment thread cmd/campaign-service/server.go Outdated
Comment thread docs/knowledge/code/cmd-campaign-service.md Outdated
Copilot AI review requested due to automatic review settings July 10, 2026 23:50
@mrautela365 mrautela365 force-pushed the fix/LFXV2-2556-mount-connection-routes branch from 3035f9f to 42bcb1f Compare July 10, 2026 23:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 11, 2026 00:21
@mrautela365 mrautela365 force-pushed the fix/LFXV2-2556-mount-connection-routes branch from 42bcb1f to 90dbef1 Compare July 11, 2026 00:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@MRashad26 MRashad26 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Inline findings below.

Comment thread cmd/campaign-service/server.go Outdated
mrautela365 added a commit that referenced this pull request Jul 13, 2026
…(PR #17)

Per Rashad's review: the `if cont.Connections != nil` guard before building the
connection endpoints was always true (NewContainer wires Connections in both the
DB and no-DB paths), so it was dead code that could mask a mis-wired container —
callers would silently skip mounting the connection routes and serve 404s
instead of failing at startup. Construct the endpoints unconditionally and return
an explicit error if Connections is unexpectedly nil, so a mis-wire crashes
loudly at startup.

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 13, 2026 15:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread cmd/campaign-service/server.go Outdated
mrautela365 added a commit that referenced this pull request Jul 13, 2026
…ver (PR #17)

The prior fix made StartServer fail loudly on a nil Connections service, but
handleHTTPServer still had `if connEndpoints != nil { mount }`, reintroducing the
same silent-404 failure mode. connEndpoints is now always non-nil (StartServer
guarantees it), so mount unconditionally and fail loudly if it's ever nil rather
than silently skipping the connection routes.

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 13, 2026 15:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment thread cmd/campaign-service/server.go Outdated
Comment thread docs/knowledge/code/cmd-campaign-service.md Outdated
mrautela365 added a commit that referenced this pull request Jul 13, 2026
debug.HTTP() in clue v1.2.1 does not log headers/statuses — it only propagates
the runtime /debug toggle into the request context. Correct the server.go
comment and the OKF cmd doc, which both wrongly described it as HTTP logging.

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 13, 2026 15:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

mrautela365 and others added 4 commits July 13, 2026 16:05
The connection service was wired in the DI container but never mounted in the
HTTP muxer, so every /projects/{projectId}/connection-* route returned 404 in
the running binary even though the handlers existed. Mount the generated
connection server (guarded on cont.Connections, which is non-nil even without a
database so the routes return the typed 503 rather than a bare 404).

Not caught earlier because the unmounted service still compiles as dead code.

LFXV2-2556

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
…(PR #17)

Per Rashad's review: the `if cont.Connections != nil` guard before building the
connection endpoints was always true (NewContainer wires Connections in both the
DB and no-DB paths), so it was dead code that could mask a mis-wired container —
callers would silently skip mounting the connection routes and serve 404s
instead of failing at startup. Construct the endpoints unconditionally and return
an explicit error if Connections is unexpectedly nil, so a mis-wire crashes
loudly at startup.

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
…ver (PR #17)

The prior fix made StartServer fail loudly on a nil Connections service, but
handleHTTPServer still had `if connEndpoints != nil { mount }`, reintroducing the
same silent-404 failure mode. connEndpoints is now always non-nil (StartServer
guarantees it), so mount unconditionally and fail loudly if it's ever nil rather
than silently skipping the connection routes.

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
debug.HTTP() in clue v1.2.1 does not log headers/statuses — it only propagates
the runtime /debug toggle into the request context. Correct the server.go
comment and the OKF cmd doc, which both wrongly described it as HTTP logging.

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 13, 2026 23:06
@mrautela365 mrautela365 force-pushed the fix/LFXV2-2556-mount-connection-routes branch from 5466690 to 1986fef Compare July 13, 2026 23:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

dealako
dealako previously approved these changes Jul 13, 2026

@dealako dealako 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.

Hi @mrautela365 👋 — reviewed the final state of this PR after the full round of iteration with @MRashad26 and Copilot.

Overall impression: Tight, well-scoped fix for a genuine wiring bug — the connection service was DI-wired but never mounted, so every /projects/{projectId}/connection-* route 404'd in the running binary despite compiling. The mount is correct, and the PR thread shows careful, evidence-driven iteration: the always-true nil-guard was replaced with a fail-loud posture end-to-end, debug.LogPayloads() was removed entirely (it would have leaked bearer tokens + plaintext provider credentials), and the debug.HTTP() comment was corrected to match clue v1.2.1's actual behavior. I independently verified all three claims against the code.

Verification I ran:

  • connsvcsvr.New(connEndpoints, mux, decoder, encoder, eh, nil) matches the generated 6-arg constructor; the koHTTPDir args the svc server needs are correctly omitted (connections serves no OpenAPI files).
  • NewContainer sets Connections non-nil in both the DB (container.go:91) and no-DB (container.go:57) paths; nil-repo mode returns a typed 503 via ensureAvailable(), not a 404 — covered by TestNilRepo_ReturnsServiceUnavailable.
  • Auth isn't bypassed by mounting: JWT is baked into the generated endpoints (a.JWTAuth), not the HTTP layer, and ConnectionService implements the Auther interface.
  • debug.LogPayloads() has zero live invocations repo-wide (comment-only). go build ./cmd/... clean; all CI checks green; mergeable.

Structured issue count:

  • 🔴 Blocking: 0
  • 🟡 Minor: 1 — no automated test locks in the route mount (the exact regression class this PR fixes).
  • ⚪ Nit: 1 — the connEndpoints == nil guard in handleHTTPServer is statically unreachable.
  • ❔ Question: 0

Final decision:Approved with minor comments. Nothing here blocks merge — CI is green, every prior reviewer thread is resolved, and the security posture is clean. The one item worth a follow-up (not this PR) is a lightweight mount test; details inline.

Comment thread cmd/campaign-service/server.go
Comment thread cmd/campaign-service/server.go
…17)

Address @dealako's [minor] review note that nothing automated guarded the
invariant this PR establishes (connection routes are reachable) — a future
deletion of the connsvcsvr.Mount call would compile and silently reintroduce
the 404 regression.

- server.go: extracted mux construction + both service mounts into a buildMux()
  seam returning the goahttp.Muxer; handleHTTPServer now calls it. The
  fail-loud nil-connEndpoints guard is retained as intentional defense-in-depth
  against a future refactor introducing a second caller (per the review).
- server_test.go (new): TestConnectionRoutesAreMounted asserts a known
  connection route (POST /projects/{id}/connection-google-ads) and a campaign
  route (/livez) resolve to a real handler (non-404, using the no-DB services
  which return 503); TestBuildMuxNilConnEndpointsFailsLoud covers the guard.

Verified: gofmt, check-headers, go build, go vet, golangci-lint (0 issues),
go test -race ./cmd/... (pass).

Signed-off-by: Misha Rautela <mrautela@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 13, 2026 23:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@dealako dealako 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.

Thanks for the fast turnaround, @mrautela365 👏 — you closed out both items from the prior round cleanly, and in the best possible way.

👏 Nice work:

  • Extracted the exact buildMux seam I suggested and added TestConnectionRoutesAreMounted, which asserts POST /projects/{id}/connection-google-ads (and /livez) resolve to a real handler — any non-404 proves the mount. I verified this genuinely locks the invariant: stubbing out connsvcsvr.Mount with a no-op makes the test fail with a 404, and restoring it passes. That's exactly the regression guard the PR was missing.
  • Turned my dead-guard nit into a tested invariant rather than deleting it. Moving the connEndpoints == nil check into buildMux (which the new TestBuildMuxNilConnEndpointsFailsLoud calls directly) means the fail-loud guard is now exercised instead of statically unreachable — a genuinely better resolution than removing it.

Revision tracking:

  • Resolved — [minor] no automated mount test → buildMux seam + TestConnectionRoutesAreMounted (82d6b0a). Mutation-verified.
  • Resolved — [nit] unreachable nil-guard → relocated into buildMux and now covered by TestBuildMuxNilConnEndpointsFailsLoud (82d6b0a).

New-diff review: The buildMux extraction is behavior-identical — same mux, same mount order, same middleware chain (RequestID → Debug-gated debug.HTTP()otelhttp) applied by handleHTTPServer to the returned mux, same fail-loud posture. ctx/cfg/endpoints/connEndpoints all still used; no orphaned imports or params (go vet clean). The test uses only synthetic data (proj-123, {} body) — no PII, no secrets, and it makes no positive auth claim, so it can't mask an auth gap. go build ./cmd/..., go test ./cmd/campaign-service/..., and go vet ./cmd/... all pass; all CI checks green; still mergeable. Both my security and code-quality passes came back clean, and Copilot's review of this commit generated no new comments.

Structured issue count (all open items):

  • 🔴 Blocking: 0
  • 🟡 Minor: 0
  • ⚪ Nit: 0 (a couple of purely cosmetic, take-it-or-leave-it observations inline — not worth a revision on their own)

Final decision:Approved. Both prior findings are fully resolved, the fix is well-tested, and there are no new issues. Ship it.

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
rec := httptest.NewRecorder()
req := httptest.NewRequest(tc.method, tc.path, strings.NewReader("{}"))

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.

[nit] Cosmetic only — take-it-or-leave-it. The table sets a JSON body (strings.NewReader("{}")) and Content-Type: application/json for every case, including the GET /livez health row, which ignores the body. Harmless (it still returns 200), just slightly incongruous for a GET probe. Optional: set the body/content-type per-case, or add a one-line comment noting connsvcsvr.Mount is all-or-nothing so a single sentinel route is sufficient to detect a dropped mount. Neither is worth a revision.

@dealako dealako merged commit f5689b9 into main Jul 14, 2026
11 checks passed
@dealako dealako deleted the fix/LFXV2-2556-mount-connection-routes branch July 14, 2026 00:14
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.

4 participants