Perspective V Docs

Kong Route and Service Mapping Guide

This guide documents the practical process used in this repository to:

Purpose

This guide documents the practical process used in this repository to:

  • add and update Kong services
  • add and update Kong routes
  • apply rewrites and plugins
  • map legacy Ocelot paths to Kong paths
  • validate behavior after changes

It reflects the current stack under:

  • runtime/stacks/infrastructure/gateway/kong-bootstrap-ocelot.sh
  • runtime/stacks/infrastructure/gateway/ocelot-to-kong-mapping.md

Architecture Overview

Request flow

  1. Client sends request to api.perspective-v.com.
  2. Kong matches a route by host + path + method + regex priority.
  3. Kong applies route/global plugins (rewrite, rate limit, auth, CORS).
  4. Kong forwards to an internal upstream service on Docker network (for example graph:5138, identity:62258).

Core concepts in this repo

  • Service: upstream target (host, port, protocol, optional path).
  • Route: public entry (hosts, paths, methods, regex_priority).
  • Rewrite plugin: maps incoming path to upstream path.
  • JWT plugin: attached only to protected routes.
  • Global CORS plugin: controls browser cross-origin behavior.

Source of Truth Files

Bootstrap automation

  • runtime/stacks/infrastructure/gateway/kong-bootstrap-ocelot.sh

This script is idempotent and performs upserts for:

  • services
  • routes
  • route plugins (rewrite/rate-limit/jwt)
  • global plugins (cors/correlation-id)
  • JWT consumer credential

Human-readable mapping

  • runtime/stacks/infrastructure/gateway/ocelot-to-kong-mapping.md

This file describes Ocelot-to-Kong parity and compatibility routes.

How Services Are Added

Service upsert function:

  • upsert_service(name, protocol, host, port, path)

Current examples:

  • identity-svc -> identity:62258
  • graph-svc -> graph:5138
  • pv-web-svc -> perspective-v.com:443
  • sms-svc -> schoolmanagement.perspective-v.com:443
  • syassociates-svc -> service.syassociates.pk:443

Add a new service

  1. Choose a unique service name ending in -svc.
  2. Point to internal Docker host when possible.
  3. Add one upsert_service line in the services section.
  4. Keep tag ocelot-migration for audit consistency.

How Routes Are Added

Route upsert function:

  • upsert_route(name, service_name, regex_priority, path_pattern, methods...)

Route matching controls:

  • hosts[] fixed to KONG_PROXY_HOST (default api.perspective-v.com)
  • paths[] regex-style path
  • methods[] explicit methods
  • regex_priority controls conflict resolution

Priority rules used here

  • More specific public compatibility routes use higher priority.
  • Catch-all protected routes use lower priority.
  • This prevents accidental fallthrough to JWT-protected routes.

Rewrite Strategy Used Here

Rewrite plugin function:

  • upsert_rewrite_plugin(route_name, rewritten_uri)

Typical patterns:

  • capture groups from regex path:
    • /api/v$(uri_captures.version)/$(uri_captures.endpoint)
  • fixed remap:
    • /swagger/1.0/swagger.json

Public vs Protected Routing Model

Protected

Protected routes receive JWT plugin (key_claim_name=iss, verify exp):

  • identity-protected
  • pv-web-protected
  • graph-protected
  • sms-protected
  • syassociates-private

Public

Public routes do not receive JWT plugin:

  • auth/login-like endpoints
  • docs/swagger compatibility
  • graph compatibility endpoints such as /graph/docs, /graph/resume, and gopher public API paths

Graph Mapping Model (Important)

The graph service in this repo follows this split:

  • UI paths are passthrough at plain paths (for example /resume, /gopher/*)
  • public docs paths are under /graph/docs
  • API paths are under /graph/v1/* (identity-style) and /graph/* compatibility paths

Kong mapping aligns with this:

  • /graph/docs and /graph/docs/* -> /docs* (public docs passthrough)
  • /graph/v1/* -> /api/v1/* (JWT-protected versioned API)
  • /resume -> /resume (UI passthrough)
  • /gopher/* -> /gopher* (UI passthrough)
  • /graph/gopher/* -> /graph/gopher/* (API paths)
  • /graph/resume public API route supports POST,OPTIONS

OPTIONS is required for browser CORS preflight.

CORS Configuration Model

Global CORS is managed by upsert_global_cors_plugin.

Origins

Configured by KONG_CORS_ALLOWED_ORIGINS.

Current required origins include:

  • https://console.perspective-v.com
  • https://hassan.taj.contact
  • https://hassantaj.github.io

Headers

Configured by KONG_CORS_ALLOWED_HEADERS.

Current required headers include:

  • Authorization
  • Content-Type
  • AppCode, appcode, APPCODE
  • apollographql-client-name
  • apollographql-client-version

Methods

Configured by KONG_CORS_ALLOWED_METHODS with OPTIONS included.

Step-by-Step: Add a New Route in This Repo

  1. Add or identify the upstream service in the services section.
  2. Add upsert_route(...) with:
    • unique route name
    • correct service
    • correct regex path
    • methods including OPTIONS if browser-facing
    • proper regex_priority
  3. Add upsert_rewrite_plugin(...) mapping inbound path to upstream path.
  4. Add rate limit plugin via upsert_rate_limit_plugin(route, second_limit).
  5. If protected, add upsert_jwt_route_plugin(route).
  6. Update mapping doc table in ocelot-to-kong-mapping.md.
  7. Run bootstrap apply.
  8. Validate with curl and browser preflight checks.

Applying Changes Safely

From runtime/stacks/infrastructure/gateway:

bash -n kong-bootstrap-ocelot.sh

Then apply with current live JWT secret loaded (or provided securely):

KONG_JWT_HMAC_SECRET="<current-secret>" ./kong-bootstrap-ocelot.sh

If env values are used:

set -a
source /home/repo/contabo-server-setup/runtime/environments/vps/infrastructure/gateway/.env
set +a
KONG_JWT_HMAC_SECRET="<current-secret>" ./kong-bootstrap-ocelot.sh

Validation Patterns

Route behavior

  • UI endpoints should return expected upstream behavior (not route-miss 404).
  • Public API endpoints should not fall through to protected JWT route.
  • /graph/docs must stay public and /graph/v1/* must stay JWT-protected.

CORS preflight

Example:

curl -ksS -D - -o /dev/null -X OPTIONS 'https://api.perspective-v.com/graph/resume' \
  -H 'Origin: https://console.perspective-v.com' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: apollographql-client-name,content-type'

Expect:

  • HTTP/2 200
  • access-control-allow-origin matches request origin
  • access-control-allow-headers includes Apollo headers
  • access-control-allow-methods includes OPTIONS

Common Failure Modes and Fixes

1) Browser CORS blocked on graph route

Causes:

  • origin not in global CORS origins
  • required request header missing in allowed headers
  • route does not include OPTIONS

Fix:

  • update KONG_CORS_ALLOWED_ORIGINS
  • update KONG_CORS_ALLOWED_HEADERS
  • ensure route methods include OPTIONS
  • reapply bootstrap (or patch route/plugin live)

2) Public route returns 401 JWT error

Cause:

  • request falls through to protected catch-all route.

Fix:

  • add explicit public route
  • raise regex priority above protected route

3) Public route returns 404 route miss

Cause:

  • route absent, wrong path regex, wrong host, or wrong rewrite.

Fix:

  • verify route inventory in Kong Admin
  • verify host/path regex and rewrite target

How This Repo Mapped Ocelot to Kong

  1. Enumerated Ocelot upstream/downstream entries.
  2. Created Kong service per backend target.
  3. Created Kong route per Ocelot upstream template.
  4. Applied request-transformer rewrites to downstream templates.
  5. Attached JWT only where Ocelot required bearer auth.
  6. Added second-based rate limits to approximate Ocelot period limits.
  7. Added compatibility routes to preserve existing client URLs.
  8. Added explicit graph/gopher public routes with higher priority.
  9. Added CORS allow-headers and origins required by browser/Apollo clients.

Operational Notes

  • Keep all route/plugin entities tagged ocelot-migration.
  • Prefer script-driven idempotent updates over ad-hoc manual mutations.
  • If emergency live patch is used, back-port the same change into bootstrap and mapping docs immediately.

Quick Checklist Before Closing a Kong Change

  • service exists and points to correct upstream
  • route exists with correct host/path/methods
  • OPTIONS included for browser-facing API routes
  • rewrite plugin maps to correct upstream URI
  • protected/public auth behavior verified
  • CORS origin/header/method preflight verified
  • mapping doc updated
  • state docs updated (accepted-suggestions, requirements, already-implemented, next-steps)

On this page