Skip to content

feat(discovery-server): add read-only API for the Control Plane#304

Open
ron96g wants to merge 10 commits intomainfrom
feat/spy-server
Open

feat(discovery-server): add read-only API for the Control Plane#304
ron96g wants to merge 10 commits intomainfrom
feat/spy-server

Conversation

@ron96g
Copy link
Copy Markdown
Member

@ron96g ron96g commented Mar 31, 2026

Implement the Spy Server, a read-only HTTP API that provides a stable REST interface for querying Applications, ApiExposures, ApiSubscriptions, EventExposures, EventSubscriptions, and EventTypes.

Key components:

  • OpenAPI specs (application, stargate, event) with merged uber-openapi
  • GoFiber HTTP server with JWT/OAuth2 security and scope-based ACL
  • Read-only controllers and CRD-to-API response mappers for 6 resources
  • Kubernetes-backed in-memory stores (BadgerDB) populated by informers
  • Deprecated write endpoints returning HTTP 410 Gone (directing to Rover)
  • Pagination, structured logging (zap), and Viper-based configuration

ron96g and others added 2 commits March 31, 2026 11:16
Implement the Spy Server, a read-only HTTP API that provides a stable REST interface for querying Applications, ApiExposures, ApiSubscriptions, EventExposures, EventSubscriptions, and EventTypes.

Key components:
- OpenAPI specs (application, stargate, event) with merged uber-openapi
- GoFiber HTTP server with JWT/OAuth2 security and scope-based ACL
- Read-only controllers and CRD-to-API response mappers for 6 resources
- Kubernetes-backed in-memory stores (BadgerDB) populated by informers
- Deprecated write endpoints returning HTTP 410 Gone (directing to Rover)
- Pagination, structured logging (zap), and Viper-based configuration
Co-authored-by: stefan-ctrl <stefan-ctrl@users.noreply.github.com>
@ron96g ron96g marked this pull request as ready for review April 7, 2026 08:35
Copilot AI review requested due to automatic review settings April 7, 2026 08:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds the new spy-server module: a read-only REST API (Fiber) for querying Control Plane resources with OpenAPI validation, ACL/security middleware, CRD→API mappers, in-memory (Badger) stores, and accompanying tests/fixtures/deploy manifests.

Changes:

  • Introduces store container + pagination utilities and wires controllers/handlers/routes for 6 read-only resources (+ deprecated write endpoints returning 410).
  • Adds mappers (including status mapping) and broad controller/mapper test coverage with fixtures and snapshots.
  • Adds Kubernetes deployment/kustomize manifests and a new CI job to build/test the spy-server module.

Reviewed changes

Copilot reviewed 100 out of 118 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
spy-server/test/mocks/data/application.json Adds Application CRD fixture for tests
spy-server/test/mocks/data/apiSubscription.json Adds ApiSubscription CRD fixture for tests
spy-server/test/mocks/data/apiExposure.json Adds ApiExposure CRD fixture for tests
spy-server/pkg/store/suite_test.go Adds Ginkgo suite setup for store tests
spy-server/pkg/store/stores_secret_test.go Adds SecretStore integration tests for ApiExposure/ApiSubscription
spy-server/pkg/store/stores.go Adds Stores container + secret-wrapped stores + Badger/informer-backed store creation
spy-server/pkg/log/log.go Adds zap/logr logger initialization
spy-server/internal/server/server.go Adds server wiring: security middleware, OpenAPI validation, routes
spy-server/internal/server/eventtype_server.go Adds EventType HTTP handlers
spy-server/internal/server/eventsubscription_server.go Adds EventSubscription HTTP handlers
spy-server/internal/server/eventexposure_server.go Adds EventExposure HTTP handlers
spy-server/internal/server/deprecated.go Adds deprecated write endpoints returning 410 Gone
spy-server/internal/server/application_server.go Adds Application HTTP handlers
spy-server/internal/server/apisubscription_server.go Adds ApiSubscription HTTP handlers
spy-server/internal/server/apiexposure_server.go Adds ApiExposure HTTP handlers
spy-server/internal/pagination/pagination.go Adds cursor-drain + offset/limit pagination helpers
spy-server/internal/mapper/util_test.go Adds tests for ID parsing/namespace parsing/label verification utilities
spy-server/internal/mapper/util.go Adds namespace/id parsing utilities + application-label filtering helper
spy-server/internal/mapper/status/status_test.go Adds tests for status condition→API status mapping
spy-server/internal/mapper/status/status.go Adds Kubernetes conditions→API status mapping utilities
spy-server/internal/mapper/status/response_test.go Adds tests for mapping status response timestamps/overall status
spy-server/internal/mapper/status/response.go Adds mapper for ResourceStatusResponse
spy-server/internal/mapper/eventtype/out_test.go Adds EventType out-mapper tests
spy-server/internal/mapper/eventtype/out.go Adds EventType CRD→API mapper
spy-server/internal/mapper/eventsubscription/out_test.go Adds EventSubscription out-mapper tests (incl. reference resolution)
spy-server/internal/mapper/eventsubscription/out.go Adds EventSubscription CRD→API mapper
spy-server/internal/mapper/eventexposure/out_test.go Adds EventExposure out-mapper tests (incl. fallbacks)
spy-server/internal/mapper/eventexposure/out.go Adds EventExposure CRD→API mapper
spy-server/internal/mapper/application/out_test.go Adds Application out-mapper tests
spy-server/internal/mapper/application/out.go Adds Application CRD→API mapper
spy-server/internal/mapper/apisubscription/out.go Adds ApiSubscription CRD→API mapper (security, gateway URL, approval, etc.)
spy-server/internal/mapper/apiexposure/out_test.go Adds ApiExposure out-mapper tests
spy-server/internal/mapper/apiexposure/out.go Adds ApiExposure CRD→API mapper (upstreams, security, traffic, etc.)
spy-server/internal/controller/suite_controller_test.go Adds controller test harness with Fiber app + mock stores
spy-server/internal/controller/invalid_ids_test.go Adds negative tests for malformed IDs / label mismatch behavior
spy-server/internal/controller/eventtype_test.go Adds EventType controller endpoint tests + snapshots
spy-server/internal/controller/eventtype.go Adds EventType controller implementation
spy-server/internal/controller/eventsubscription_test.go Adds EventSubscription controller endpoint tests + snapshots
spy-server/internal/controller/eventsubscription.go Adds EventSubscription controller implementation
spy-server/internal/controller/eventexposure_test.go Adds EventExposure controller endpoint tests
spy-server/internal/controller/eventexposure.go Adds EventExposure controller implementation
spy-server/internal/controller/deprecated_test.go Adds tests ensuring deprecated write endpoints return 410
spy-server/internal/controller/application_test.go Adds Application controller endpoint tests + snapshots
spy-server/internal/controller/application.go Adds Application controller implementation
spy-server/internal/controller/apisubscription_test.go Adds ApiSubscription controller endpoint tests + snapshots
spy-server/internal/controller/apisubscription.go Adds ApiSubscription controller implementation
spy-server/internal/controller/apiexposure_test.go Adds ApiExposure controller endpoint tests
spy-server/internal/controller/apiexposure.go Adds ApiExposure controller implementation
spy-server/internal/controller/snapshots/eventtype_test.snap Adds snapshots for EventType endpoints
spy-server/internal/controller/snapshots/eventsubscription_test.snap Adds snapshots for EventSubscription endpoints
spy-server/internal/controller/snapshots/application_test.snap Adds snapshots for Application endpoints
spy-server/internal/controller/snapshots/apisubscription_test.snap Adds snapshots for ApiSubscription endpoints
spy-server/internal/config/config.go Adds Viper-based server config with defaults
spy-server/go.sum.license Adds license metadata for go.sum
spy-server/go.mod Adds spy-server Go module definition and dependencies
spy-server/docs/004_secret_manager/plan.md Adds secret-manager integration plan
spy-server/docs/002_event/plan.md Adds event resources plan (and notes current state)
spy-server/docs/001_application/plan.md Adds application resource plan
spy-server/config/server/server.yaml Adds Deployment/Service manifests for spy-server
spy-server/config/server/kustomization.yaml Adds kustomize wiring for server resources
spy-server/config/rbac/service_account.yaml Adds ServiceAccount for spy-server
spy-server/config/rbac/role_binding.yaml Adds ClusterRoleBinding for spy-server
spy-server/config/rbac/role.yaml Adds ClusterRole for read-only access to CRDs
spy-server/config/rbac/kustomization.yaml Adds kustomize wiring for RBAC resources
spy-server/config/prometheus/monitor.yaml Adds ServiceMonitor for metrics scraping
spy-server/config/prometheus/kustomization.yaml Adds kustomize wiring for prometheus resources
spy-server/config/kustomization.yaml Adds root kustomization referencing default
spy-server/config/ingress/kustomization.yaml Adds kustomize wiring for ingress
spy-server/config/ingress/ingress.yaml Adds Ingress manifest
spy-server/config/default/namespace_patch.yaml Adds namespace label patch for secret-manager integration
spy-server/config/default/metrics_service.yaml Adds dedicated metrics Service exposing port “http”
spy-server/config/default/kustomization.yaml Adds default kustomize overlay with env configMap + patches
spy-server/config/default/ingress_host_patch.yaml Adds patch to override ingress host
spy-server/config/default/deployment_patch.yaml Adds projected SA token + trust bundle mounts for secret-manager
spy-server/cmd/main.go Adds spy-server entrypoint wiring config/logging/stores/routes
spy-server/api/openapi-merge.json.license Adds license metadata for openapi merge config
spy-server/api/openapi-merge.json Adds OpenAPI merge config
spy-server/api/README.md Adds API generation docs
spy-server/api/Makefile Adds OpenAPI merge + codegen make target
spy-server/Makefile Adds build/test targets for spy-server
common-server/pkg/store/secrets/obfuscator_test.go Extends obfuscator tests to cover typed structs + nil handling
common-server/pkg/store/secrets/obfuscator.go Adds JSON fallback obfuscation path for typed structs
.github/workflows/ci.yaml Adds CI job for spy-server module

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

Comment on lines +64 to +75
b, err := json.Marshal(obj)
if err == nil {
b, err = o.ReplaceAllFromBytes(ctx, b, jsonPaths)
if err != nil {
return nil, errors.Wrap(err, "failed to obfuscate from json")
}
err = json.Unmarshal(b, &obj)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal obfuscated json")
}
return obj, nil
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

json.Unmarshal(b, &obj)unmarshals into aninterface{}and will decode intomap[string]any(not back into the original concrete struct type), so callers won’t get a typed result (and the newly added typed-struct test would fail). Prefer unmarshalling into a value of the same concrete type (e.g., ifobj` is a non-nil pointer, unmarshal into that pointer or into a freshly-allocated value of the same type and return it).

Copilot uses AI. Check for mistakes.
// RegisterRoutes sets up security middleware, OpenAPI validation, and all route handlers.
func (s *Server) RegisterRoutes(router fiber.Router) {
checkAccess := security.ConfigureSecurity(router, security.SecurityOpts{
Enabled: true,
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Security is always enabled here (Enabled: true) and ignores s.Config.Security.Enabled. This makes it impossible to disable auth/ACLs via configuration (e.g., local/dev), and contradicts the presence of security.enabled in config defaults. Use s.Config.Security.Enabled (and consider bypassing checkAccess usage when disabled) so runtime config actually controls behavior.

Suggested change
Enabled: true,
Enabled: s.Config.Security.Enabled,

Copilot uses AI. Check for mistakes.
scheme: http
selector:
matchLabels:
control-plane: spy-server
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This ServiceMonitor selector matches both spy-server-service (port name https) and spy-server-metrics-service (port name http) because both carry control-plane: spy-server. Prometheus will attempt to scrape services without a matching port name and you’ll get scrape errors for the non-matching Service. Tighten the selector (e.g., add a label unique to the metrics service) or align the port naming so the selected Service(s) expose the requested port name.

Suggested change
control-plane: spy-server
control-plane: spy-server
app.kubernetes.io/name: spy-server-metrics-service

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +15
- op: add
path: /spec/template/spec/volumes/0
value:
name: secretmgr-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 600
audience: secret-manager
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Using JSON6902 add at /volumes/0 twice is brittle and order-dependent (the second add will be inserted before the first, and both shift any existing volume at index 0). Prefer appending with /volumes/- or switching to a strategic-merge patch keyed by name to make the patch stable even if the base Deployment’s volume ordering changes.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +30
- op: add
path: /spec/template/spec/volumes/0
value:
name: trust-bundle
configMap:
name: secret-manager-trust-bundle
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Using JSON6902 add at /volumes/0 twice is brittle and order-dependent (the second add will be inserted before the first, and both shift any existing volume at index 0). Prefer appending with /volumes/- or switching to a strategic-merge patch keyed by name to make the patch stable even if the base Deployment’s volume ordering changes.

Copilot uses AI. Check for mistakes.
@stefan-ctrl stefan-ctrl self-assigned this Apr 7, 2026
@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@stefan-ctrl stefan-ctrl changed the title feat(spy-server): add read-only API for the Control Plane feat(discovery-server): add read-only API for the Control Plane Apr 8, 2026
Copy link
Copy Markdown
Member Author

@ron96g ron96g left a comment

Choose a reason for hiding this comment

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

Cant approve as I am also author but just a nitpick comment ;)


# Discovery Server

The Discovery Server (also known as the **Stargate API**) is a read-only HTTP API for the TARDIS Control Plane. It provides a stable, user-facing REST interface for querying the state of Applications, ApiExposures, ApiSubscriptions, EventExposures, EventSubscriptions, and EventTypes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

[nitpick] should avoid internal product names in docs "TARDIS".

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