Skip to content

HYPERFLEET-1370 - refactor: introduce typed container for API server dependencies#309

Open
kuudori wants to merge 1 commit into
openshift-hyperfleet:mainfrom
kuudori:HYPERFLEET-1370-refactor-typed-container
Open

HYPERFLEET-1370 - refactor: introduce typed container for API server dependencies#309
kuudori wants to merge 1 commit into
openshift-hyperfleet:mainfrom
kuudori:HYPERFLEET-1370-refactor-typed-container

Conversation

@kuudori

@kuudori kuudori commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace plugin-based route registration (plugins/entities, adapterStatus, generic, resources) with a typed Container (cmd/hyperfleet-api/container) that lazily constructs and caches DAOs, services, and handlers via constructor injection
  • Refactor APIServer to take injected cfg and handler via its constructor instead of reaching into the global environments.Environment() singleton
  • Split router middleware into public (/openapi, /openapi.html, metadata) vs protected (auth + schema validation + transaction) subrouters, so public docs endpoints are never wrapped by auth/transaction middleware
  • Simplify JWTHandler to a multi-issuer, mux.MiddlewareFunc-based design, dropping the old PublicPaths/Next self-contained handler
  • Add a TODO(HYPERFLEET-1371) marking the remaining environments.Environment() callers (health_server.go, metrics_server.go) for follow-up once the environments/ package is removed

Test plan

  • make verify-all (go vet, gofmt, unit tests) passes
  • TestNewRouter_PublicVsProtectedMiddleware (new) verifies public routes bypass both apiMiddleware and protectedMiddleware, while registered routes are gated by both — confirmed it fails against the pre-fix router wiring and passes against the fix
  • TestContainerCachesDAOsAndServices updated to use BeIdenticalTo for genuine pointer-identity caching checks
  • Existing integration tests (test/integration/clusters_test.go, test/integration/openapi_test.go) continue to cover the public/protected boundary end-to-end under the default JWT-enabled config

@openshift-ci
openshift-ci Bot requested review from ldornele and tirthct July 23, 2026 14:56
@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign vkareh for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 3e628ecc-0160-4888-acf3-dca26e4400a5

📥 Commits

Reviewing files that changed from the base of the PR and between ba90d60 and 6731593.

📒 Files selected for processing (33)
  • AGENTS.md
  • CLAUDE.md
  • CONTRIBUTING.md
  • README.md
  • cmd/hyperfleet-api/container/auth.go
  • cmd/hyperfleet-api/container/container.go
  • cmd/hyperfleet-api/container/container_test.go
  • cmd/hyperfleet-api/container/daos.go
  • cmd/hyperfleet-api/container/services.go
  • cmd/hyperfleet-api/container/validation.go
  • cmd/hyperfleet-api/main.go
  • cmd/hyperfleet-api/servecmd/api_server.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • cmd/hyperfleet-api/server/api_server.go
  • cmd/hyperfleet-api/server/api_server_test.go
  • cmd/hyperfleet-api/server/routes.go
  • cmd/hyperfleet-api/server/routes_entities.go
  • cmd/hyperfleet-api/server/routes_entities_test.go
  • cmd/hyperfleet-api/server/routes_test.go
  • cmd/hyperfleet-api/server/server.go
  • pkg/auth/jwt_handler.go
  • pkg/auth/jwt_handler_test.go
  • pkg/config/server.go
  • pkg/handlers/resource_handler.go
  • plugins/CLAUDE.md
  • plugins/adapterStatus/plugin.go
  • plugins/generic/plugin.go
  • plugins/resources/plugin.go
  • test/factories/clusters.go
  • test/factories/factory.go
  • test/factories/node_pools.go
  • test/helper.go
  • test/integration/resource_helpers.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)
💤 Files with no reviewable changes (5)
  • cmd/hyperfleet-api/main.go
  • plugins/CLAUDE.md
  • plugins/resources/plugin.go
  • plugins/adapterStatus/plugin.go
  • plugins/generic/plugin.go
🚧 Files skipped from review as they are similar to previous changes (23)
  • cmd/hyperfleet-api/container/auth.go
  • cmd/hyperfleet-api/servecmd/api_server.go
  • cmd/hyperfleet-api/container/container_test.go
  • cmd/hyperfleet-api/container/validation.go
  • cmd/hyperfleet-api/server/server.go
  • test/factories/factory.go
  • test/integration/resource_helpers.go
  • pkg/handlers/resource_handler.go
  • cmd/hyperfleet-api/container/services.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • cmd/hyperfleet-api/container/daos.go
  • pkg/config/server.go
  • cmd/hyperfleet-api/server/routes_test.go
  • cmd/hyperfleet-api/container/container.go
  • cmd/hyperfleet-api/server/routes_entities_test.go
  • test/factories/clusters.go
  • cmd/hyperfleet-api/server/api_server_test.go
  • cmd/hyperfleet-api/server/routes_entities.go
  • cmd/hyperfleet-api/server/routes.go
  • pkg/auth/jwt_handler.go
  • test/helper.go
  • cmd/hyperfleet-api/server/api_server.go
  • pkg/auth/jwt_handler_test.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Updated API server startup to use explicit dependency wiring.
    • Refreshed routing to clearly separate public and protected endpoints, including OpenAPI endpoints and the middleware chain behavior.
  • Bug Fixes
    • Improved shutdown sequence to close auth-managed resources before telemetry and database teardown.
    • Enhanced error reporting when OpenAPI/route setup fails.
    • JWT authentication is now applied consistently only to protected routes.
  • Tests
    • Added/updated HTTP vs HTTPS, middleware/auth gating, routing boundary, and lazy initialization/caching coverage.

Walkthrough

The API now uses a lazy dependency container, explicit middleware and route registrars, injected server configuration, and middleware-based JWT validation. Startup and integration tests obtain services and servers from the container, while plugin initialization and service locators are removed. Documentation and configuration accessors reflect the new composition model.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ServeCommand
  participant Container
  participant BuildAPIServer
  participant Router
  participant APIServer
  ServeCommand->>Container: construct with config and session factory
  ServeCommand->>BuildAPIServer: provide container services
  BuildAPIServer->>Router: build middleware and route registrars
  Router-->>BuildAPIServer: return configured router
  BuildAPIServer->>APIServer: inject config and router
  ServeCommand->>APIServer: start serving
Loading

Suggested reviewers: ldornele, tirthct

🚥 Pre-merge checks | ✅ 9 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
No Pii Or Sensitive Data In Logs ⚠️ Warning pkg/auth/jwt_handler.go logs raw JWKS URLs/CA paths; URLs can include credentials/internal hosts, and errors propagate them to logs (CWE-532). Redact URL userinfo/hostnames and avoid logging CA paths; log an issuer ID or hashed source instead, and keep propagated errors free of raw config values.
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: introducing a typed container for API server dependencies.
Description check ✅ Passed The description directly covers the container refactor, server injection, middleware split, JWT changes, and follow-up TODO.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Sec-02: Secrets In Log Output ✅ Passed No CWE-532 issue: non-test log statements don’t field/interpolate token/password/credential/secret.
No Hardcoded Secrets ✅ Passed No new CWE-798/CWE-321 hardcoded secrets or embedded-credential URLs in the PR delta; only an existing test fixture key/password appears in test/helper.go.
No Weak Cryptography ✅ Passed No CWE-327/CWE-208 issues: PR uses RS256 and standard libs; no MD5/DES/RC4/SHA1 security use, custom crypto, or secret comparisons found.
No Injection Vectors ✅ Passed No CWE-78/79/89/502 sink appears in changed non-test code; only benign fmt.Sprintf in logs/panic and route strings.
No Privileged Containers ✅ Passed No manifest/Helm/Dockerfile changes; diff is Go/docs only and shows no privileged flags. CWE-250/CWE-284 not introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Comment @coderabbitai help to get the list of available commands.

@hyperfleet-ci-bot

hyperfleet-ci-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

Risk Score: 5 — risk/high

Signal Detail Points
PR size 1457 lines (>500) +2
Sensitive paths cmd/ +2
Test coverage Missing tests for: cmd/hyperfleet-api cmd/hyperfleet-api/servecmd pkg/config pkg/handlers plugins/adapterStatus plugins/generic plugins/resources test test/factories test/integration +1

Computed by hyperfleet-risk-scorer

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
cmd/hyperfleet-api/server/api_server_test.go (1)

111-115: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

InsecureSkipVerify disables cert-chain/hostname validation (CWE-295).

Flagged by both OpenGrep and ast-grep. You already generate the self-signed cert in writeSelfSignedCert — build an x509.CertPool from it and set RootCAs instead of skipping verification entirely, and add MinVersion: tls.VersionTLS13.

🔒 Proposed fix
+	certPool := x509.NewCertPool()
+	certPEM, err := os.ReadFile(certFile)
+	Expect(err).NotTo(HaveOccurred())
+	Expect(certPool.AppendCertsFromPEM(certPEM)).To(BeTrue())
+
 	client := &http.Client{
 		Transport: &http.Transport{
-			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+			TLSClientConfig: &tls.Config{RootCAs: certPool, MinVersion: tls.VersionTLS13},
 		},
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/hyperfleet-api/server/api_server_test.go` around lines 111 - 115, Update
the HTTP client TLS configuration in the test to avoid InsecureSkipVerify: build
an x509.CertPool from the certificate generated by writeSelfSignedCert, assign
it to RootCAs, and set MinVersion to tls.VersionTLS13 while preserving trusted
self-signed certificate validation.

Source: Linters/SAST tools

pkg/auth/jwt_handler.go (1)

106-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Middleware is near the QUAL-03 branching/length threshold.

5+ distinct branch points (empty header, non-Bearer scheme, parse failure w/ expired precedence, terminal expired/invalid, no-credentials) in one closure. Extract the per-validator match loop into a helper (e.g. matchValidator(r *http.Request) (*jwt.Token, config.JWTIssuerConfig, error, bool)) returning either a matched token or the sticky "expired" error, keeping Middleware itself as thin dispatch + handleError calls.

As per path instructions, "Functions >50 lines or >5 branching paths — flag for decomposition."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/auth/jwt_handler.go` around lines 106 - 155, Decompose the validator
iteration from JWTHandler.Middleware into a helper such as matchValidator that
evaluates headers and parsers, returns the matched token and issuer
configuration, or the sticky expired/validation error plus whether a non-Bearer
header was seen. Keep Middleware focused on invoking the helper, dispatching
successful requests, and preserving the existing handleError behavior and error
precedence.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/hyperfleet-api/server/routes.go`:
- Around line 48-54: Make authentication outermost on protected routes: in
cmd/hyperfleet-api/server/routes.go:48-54, register protectedMiddleware before
apiMiddleware so JWT and caller identity run before schema validation or
db.TransactionMiddleware. In cmd/hyperfleet-api/container/container.go:163-180,
adjust the middleware grouping consistently so transaction/schema middleware is
excluded from unauthenticated paths while authenticated requests still reach
db.TransactionMiddleware.

In `@test/integration/resource_helpers.go`:
- Line 15: Update the integration setup around test.RegisterIntegration(t) to
preserve and check its returned error before dereferencing h.Container. Fail the
test immediately with the original error when registration fails, then continue
to ResourceService only for a successful registration; ensure all error returns
in this setup are checked.

---

Nitpick comments:
In `@cmd/hyperfleet-api/server/api_server_test.go`:
- Around line 111-115: Update the HTTP client TLS configuration in the test to
avoid InsecureSkipVerify: build an x509.CertPool from the certificate generated
by writeSelfSignedCert, assign it to RootCAs, and set MinVersion to
tls.VersionTLS13 while preserving trusted self-signed certificate validation.

In `@pkg/auth/jwt_handler.go`:
- Around line 106-155: Decompose the validator iteration from
JWTHandler.Middleware into a helper such as matchValidator that evaluates
headers and parsers, returns the matched token and issuer configuration, or the
sticky expired/validation error plus whether a non-Bearer header was seen. Keep
Middleware focused on invoking the helper, dispatching successful requests, and
preserving the existing handleError behavior and error precedence.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 63920e6b-ce80-41f8-aa45-a382cb43ee94

📥 Commits

Reviewing files that changed from the base of the PR and between 913cd01 and 24bb5ee.

📒 Files selected for processing (24)
  • cmd/hyperfleet-api/container/container.go
  • cmd/hyperfleet-api/container/container_test.go
  • cmd/hyperfleet-api/main.go
  • cmd/hyperfleet-api/servecmd/cmd.go
  • cmd/hyperfleet-api/server/api_server.go
  • cmd/hyperfleet-api/server/api_server_test.go
  • cmd/hyperfleet-api/server/routes.go
  • cmd/hyperfleet-api/server/routes_entities.go
  • cmd/hyperfleet-api/server/routes_entities_test.go
  • cmd/hyperfleet-api/server/routes_test.go
  • cmd/hyperfleet-api/server/server.go
  • pkg/auth/jwt_handler.go
  • pkg/auth/jwt_handler_test.go
  • pkg/config/server.go
  • pkg/handlers/resource_handler.go
  • plugins/CLAUDE.md
  • plugins/adapterStatus/plugin.go
  • plugins/generic/plugin.go
  • plugins/resources/plugin.go
  • test/factories/clusters.go
  • test/factories/factory.go
  • test/factories/node_pools.go
  • test/helper.go
  • test/integration/resource_helpers.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)
💤 Files with no reviewable changes (5)
  • plugins/CLAUDE.md
  • plugins/resources/plugin.go
  • plugins/generic/plugin.go
  • plugins/adapterStatus/plugin.go
  • cmd/hyperfleet-api/main.go

Comment thread cmd/hyperfleet-api/server/routes.go
Comment thread test/integration/resource_helpers.go
@kuudori
kuudori force-pushed the HYPERFLEET-1370-refactor-typed-container branch from 24bb5ee to b06edbb Compare July 23, 2026 16:04
@Ruclo

Ruclo commented Jul 24, 2026

Copy link
Copy Markdown

@kuudori The container abstraction is nice but wouldn't it make more sense to have it store only the dependencies ? so without APIServer, JWTHandler and SchemaValidator ? The APIServer could be created somewhere in cmd/hyperfleet-api/server/. What do you think?

@kuudori
kuudori force-pushed the HYPERFLEET-1370-refactor-typed-container branch from b06edbb to ba90d60 Compare July 26, 2026 21:29
…dependencies

Replace the plugin-based route registration (plugins/entities,
adapterStatus, generic, resources) with a typed Container
(cmd/hyperfleet-api/container) that lazily constructs and caches DAOs,
services, and handlers via constructor injection instead of a global
environments singleton.

- Add Container with lazy-cached DAO/service/handler accessors and an
  APIServer(tracingEnabled) builder
- Move entity route registration into cmd/hyperfleet-api/server
  (routes_entities.go, renamed from plugins/entities/plugin.go)
- Refactor APIServer to take injected cfg and handler via its
  constructor rather than reaching into environments.Environment()
- Split router middleware into public (metadata/openapi) vs protected
  (auth + transaction) subrouters so JWT, schema-validation, and
  transaction middleware never wrap the public docs endpoints
- Simplify JWTHandler to a multi-issuer, mux.MiddlewareFunc-based
  design, dropping the old PublicPaths/Next self-contained handler
- Add unit coverage: container_test.go, api_server_test.go, and
  routes_test.go (asserts public routes bypass middleware while
  protected routes are gated by it)
@kuudori
kuudori force-pushed the HYPERFLEET-1370-refactor-typed-container branch from ba90d60 to 6731593 Compare July 27, 2026 00:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants