- CI/CD GitLab (.gitlab-ci.yml): verify -> test -> build -> publish -> deploy cu health-gate (/api/v3/health/all) + rollback manual - Publicare pe retele sociale (LinkedIn/Facebook) din Analysis History (social.ts, linkedin.ts, facebook.ts, SocialPostModal) - Specificatii OpenAPI: agent-v3 (87 op.) si didi-framework (287 op.) - Matrice testare acceptanta beneficiar + script dovezi API - Fix nginx SSL: redirect port 3001 (error_page 497, absolute_redirect off) - Adrese interne inlocuite cu hostname-uri generice (.local)
537 lines
21 KiB
YAML
537 lines
21 KiB
YAML
_format_version: "3.0"
|
|
_info:
|
|
select_tags:
|
|
- product:didi
|
|
- env:prod
|
|
defaults:
|
|
route:
|
|
# Routes accept both HTTP and HTTPS (matches cluster pattern for lege365/rafai/etc).
|
|
# HAProxy LB terminates TLS at edge, forwards HTTP to Kong DP — Kong must accept HTTP
|
|
# internally or it returns 426 "Please use HTTPS protocol".
|
|
protocols: [http, https]
|
|
|
|
# ============================================================
|
|
# DIDI tenant configuration for shared Kong cluster
|
|
# Cluster CP: kong-cp.local:8001 | DP1: kong-dp1.local | DP2: kong-dp2.local | LB: kong-lb.local
|
|
# Hosts: didi365.eu (public) + www.didi365.eu + localhost (internal alias)
|
|
# Upstreams: didi.local (DIDI host) on exposed ports
|
|
# Plugins are applied per-service (NOT global) — cluster shared with lege365/rafai/biddie/notify
|
|
# ============================================================
|
|
|
|
# ============================================================
|
|
# CONSUMERS — JWT issuers preserved from local Kong (Keycloak realm didi-clients)
|
|
# ============================================================
|
|
consumers:
|
|
- username: didi-keycloak-users
|
|
custom_id: didi-keycloak-users
|
|
tags: [product:didi, env:prod]
|
|
jwt_secrets:
|
|
- algorithm: RS256
|
|
key: https://localhost/auth/realms/didi-clients
|
|
secret: 1qG51hpfTte1TGQzcAhKWjVkXsMWNIun
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlpv0lfjAFPGV4hLK6jp6
|
|
EsVlxax2nPA9I2IzGwNUIK8AsKwC9qu+737jarsjewx3ya/0s1uDP0ilbdh+wEzW
|
|
Do/8jjWd0DxgTxMxCTS7DU07UZKXJWGc/Z+ansUPUcjqJ+uLTdu331z7ajK2FIZF
|
|
7yYH2WgjzApF6YSMx/dqybp/bdmBrvsPDGv1EJK4a72jV3P86WCW4ZDax2Qayw1t
|
|
iKnO3+o6xvyoVSMeVJbs9ArjpAldueMLfTZqYBSmWe/rlBSIMWYkKTSgS+pdakez
|
|
G71qs2RcSkI+GxlfJw0DJA8TfSjol6zc+EIUtAYG0pwwAqPB2PvkxMoDbL2UDkZE
|
|
/wIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
- algorithm: RS256
|
|
key: https://didi365.eu/auth/realms/didi-clients
|
|
secret: IS8AJNbvC3taNROALc4bHslsZnSKELQD
|
|
rsa_public_key: |
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlpv0lfjAFPGV4hLK6jp6
|
|
EsVlxax2nPA9I2IzGwNUIK8AsKwC9qu+737jarsjewx3ya/0s1uDP0ilbdh+wEzW
|
|
Do/8jjWd0DxgTxMxCTS7DU07UZKXJWGc/Z+ansUPUcjqJ+uLTdu331z7ajK2FIZF
|
|
7yYH2WgjzApF6YSMx/dqybp/bdmBrvsPDGv1EJK4a72jV3P86WCW4ZDax2Qayw1t
|
|
iKnO3+o6xvyoVSMeVJbs9ArjpAldueMLfTZqYBSmWe/rlBSIMWYkKTSgS+pdakez
|
|
G71qs2RcSkI+GxlfJw0DJA8TfSjol6zc+EIUtAYG0pwwAqPB2PvkxMoDbL2UDkZE
|
|
/wIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
# SSO cluster (sso.local) — added 2026-04-29 after migration la Keycloak SSO public.
|
|
# Same RSA public key (realm exported/imported from local with key preserved).
|
|
- algorithm: RS256
|
|
key: https://sso.local/realms/didi-clients
|
|
secret: lEyVoR2eXLgWmQQ5q6fZRbCkVJhSaTuB
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlpv0lfjAFPGV4hLK6jp6
|
|
EsVlxax2nPA9I2IzGwNUIK8AsKwC9qu+737jarsjewx3ya/0s1uDP0ilbdh+wEzW
|
|
Do/8jjWd0DxgTxMxCTS7DU07UZKXJWGc/Z+ansUPUcjqJ+uLTdu331z7ajK2FIZF
|
|
7yYH2WgjzApF6YSMx/dqybp/bdmBrvsPDGv1EJK4a72jV3P86WCW4ZDax2Qayw1t
|
|
iKnO3+o6xvyoVSMeVJbs9ArjpAldueMLfTZqYBSmWe/rlBSIMWYkKTSgS+pdakez
|
|
G71qs2RcSkI+GxlfJw0DJA8TfSjol6zc+EIUtAYG0pwwAqPB2PvkxMoDbL2UDkZE
|
|
/wIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
# Internal SSO host (used during transition; also kept for proxy fallback paths)
|
|
- algorithm: RS256
|
|
key: https://sso-admin.local/realms/didi-clients
|
|
secret: kPwQjA4nFsUzMxRyV8tDeBcGhJlOvIuS
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlpv0lfjAFPGV4hLK6jp6
|
|
EsVlxax2nPA9I2IzGwNUIK8AsKwC9qu+737jarsjewx3ya/0s1uDP0ilbdh+wEzW
|
|
Do/8jjWd0DxgTxMxCTS7DU07UZKXJWGc/Z+ansUPUcjqJ+uLTdu331z7ajK2FIZF
|
|
7yYH2WgjzApF6YSMx/dqybp/bdmBrvsPDGv1EJK4a72jV3P86WCW4ZDax2Qayw1t
|
|
iKnO3+o6xvyoVSMeVJbs9ArjpAldueMLfTZqYBSmWe/rlBSIMWYkKTSgS+pdakez
|
|
G71qs2RcSkI+GxlfJw0DJA8TfSjol6zc+EIUtAYG0pwwAqPB2PvkxMoDbL2UDkZE
|
|
/wIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
# didi-admins realm — admin-dashboard SPA auth (added 2026-05-04)
|
|
# Different RSA key than didi-clients (separate realm).
|
|
- algorithm: RS256
|
|
key: https://didi365.eu/auth/realms/didi-admins
|
|
secret: aDmInS001PuBlIcEdge2026May04PaSsKonGvErY
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkcx2UE88P4j4XzWQ/bsd
|
|
0C69xZuxo/VXvhyKPj/t7u6ILIpD3/KL0sI0Ei4ZOlfjZ8PHmmEhWVwOYRCyhxgN
|
|
aq5EMk4MKmUJ0KZd6pixvufKp8ddnI/xKdUROLbdzEHSxP251uHUUCYzpsKYisZ7
|
|
t6UidWgDBDrcU42YsV4OggvPlvemtQKFawv0CpQ7BLhyTm2WUD4iq7H17OEI975i
|
|
ocC7Zqrk9itl2o0w8x9fSMOyMgsEafkVQ/KIuZA1/kKugtpG9eyYE49RFH7iQZd9
|
|
KmQow/XDxtKHfaLi1CEU4X2fHCThMWKdRQeK8N1n6qS+yanygcYJlUf8FKybgRxZ
|
|
NwIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
- algorithm: RS256
|
|
key: https://sso.local/realms/didi-admins
|
|
secret: aDmInS002SsOcLuStEr2026May04PaSsKonGvErY
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkcx2UE88P4j4XzWQ/bsd
|
|
0C69xZuxo/VXvhyKPj/t7u6ILIpD3/KL0sI0Ei4ZOlfjZ8PHmmEhWVwOYRCyhxgN
|
|
aq5EMk4MKmUJ0KZd6pixvufKp8ddnI/xKdUROLbdzEHSxP251uHUUCYzpsKYisZ7
|
|
t6UidWgDBDrcU42YsV4OggvPlvemtQKFawv0CpQ7BLhyTm2WUD4iq7H17OEI975i
|
|
ocC7Zqrk9itl2o0w8x9fSMOyMgsEafkVQ/KIuZA1/kKugtpG9eyYE49RFH7iQZd9
|
|
KmQow/XDxtKHfaLi1CEU4X2fHCThMWKdRQeK8N1n6qS+yanygcYJlUf8FKybgRxZ
|
|
NwIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
- algorithm: RS256
|
|
key: https://sso-admin.local/realms/didi-admins
|
|
secret: aDmInS003LoCaLcLuStEr2026May04PaSsKonGv
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkcx2UE88P4j4XzWQ/bsd
|
|
0C69xZuxo/VXvhyKPj/t7u6ILIpD3/KL0sI0Ei4ZOlfjZ8PHmmEhWVwOYRCyhxgN
|
|
aq5EMk4MKmUJ0KZd6pixvufKp8ddnI/xKdUROLbdzEHSxP251uHUUCYzpsKYisZ7
|
|
t6UidWgDBDrcU42YsV4OggvPlvemtQKFawv0CpQ7BLhyTm2WUD4iq7H17OEI975i
|
|
ocC7Zqrk9itl2o0w8x9fSMOyMgsEafkVQ/KIuZA1/kKugtpG9eyYE49RFH7iQZd9
|
|
KmQow/XDxtKHfaLi1CEU4X2fHCThMWKdRQeK8N1n6qS+yanygcYJlUf8FKybgRxZ
|
|
NwIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
- algorithm: RS256
|
|
key: https://localhost/auth/realms/didi-admins
|
|
secret: aDmInS004DiDi11LoCaL2026May04PaSsKonGvE
|
|
rsa_public_key: |-
|
|
-----BEGIN PUBLIC KEY-----
|
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkcx2UE88P4j4XzWQ/bsd
|
|
0C69xZuxo/VXvhyKPj/t7u6ILIpD3/KL0sI0Ei4ZOlfjZ8PHmmEhWVwOYRCyhxgN
|
|
aq5EMk4MKmUJ0KZd6pixvufKp8ddnI/xKdUROLbdzEHSxP251uHUUCYzpsKYisZ7
|
|
t6UidWgDBDrcU42YsV4OggvPlvemtQKFawv0CpQ7BLhyTm2WUD4iq7H17OEI975i
|
|
ocC7Zqrk9itl2o0w8x9fSMOyMgsEafkVQ/KIuZA1/kKugtpG9eyYE49RFH7iQZd9
|
|
KmQow/XDxtKHfaLi1CEU4X2fHCThMWKdRQeK8N1n6qS+yanygcYJlUf8FKybgRxZ
|
|
NwIDAQAB
|
|
-----END PUBLIC KEY-----
|
|
|
|
# ============================================================
|
|
# SERVICES (4 consolidated from 9 local) + ROUTES + PER-SERVICE PLUGINS
|
|
# ============================================================
|
|
services:
|
|
|
|
# ----------------------------------------------------------
|
|
# SERVICE 1: didi-agent-v3 (was: agent-api + agent-v3 + agent-v3-api)
|
|
# ----------------------------------------------------------
|
|
- name: didi-agent-v3
|
|
protocol: http
|
|
host: didi.local
|
|
port: 24803
|
|
retries: 5
|
|
connect_timeout: 60000
|
|
write_timeout: 660000
|
|
read_timeout: 660000
|
|
tags: [product:didi, env:prod, kind:api]
|
|
plugins:
|
|
- name: cors
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
# chrome-extension://* and moz-extension://* required for browser extension API
|
|
origins: [https://didi365.eu, https://www.didi365.eu, "chrome-extension://[a-z]+", "moz-extension://[a-z0-9-]+"]
|
|
methods: [GET, POST, PUT, DELETE, OPTIONS, PATCH]
|
|
# X-API-Key header required for extension auth
|
|
headers: [Accept, Authorization, Content-Type, X-Request-ID, X-API-Key]
|
|
exposed_headers: [X-Request-ID]
|
|
credentials: true
|
|
max_age: 3600
|
|
preflight_continue: false
|
|
- name: request-size-limiting
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
allowed_payload_size: 104857600
|
|
size_unit: bytes
|
|
require_content_length: false
|
|
- name: response-transformer
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
add:
|
|
headers: ["X-Gateway:DIDI-Kong-Cluster", "X-API-Version:2.0"]
|
|
remove:
|
|
headers: [Server, Via]
|
|
- name: correlation-id
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
header_name: X-Request-ID
|
|
generator: uuid
|
|
echo_downstream: true
|
|
routes:
|
|
# JWT-protected endpoints
|
|
- name: didi-agent-abort
|
|
paths: [/api/abort]
|
|
methods: [POST, OPTIONS]
|
|
hosts: &didi-hosts [didi365.eu, www.didi365.eu, localhost]
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: &jwt-config
|
|
key_claim_name: iss
|
|
claims_to_verify: [exp]
|
|
header_names: [authorization]
|
|
uri_param_names: [jwt]
|
|
run_on_preflight: true
|
|
secret_is_base64: false
|
|
maximum_expiration: 0
|
|
- name: didi-agent-admin-services
|
|
paths: [/api/v1/admin/services]
|
|
methods: [GET, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-analysis
|
|
paths: [/api/analysis]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-analyze
|
|
paths: [/api/analyze]
|
|
methods: [POST, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-jobs
|
|
paths: [/api/v1/jobs]
|
|
methods: [GET, POST, DELETE, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-pipelines
|
|
paths: [/api/pipelines]
|
|
methods: [GET, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-progress
|
|
paths: [/api/progress]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-sessions
|
|
paths: [/api/sessions]
|
|
methods: [GET, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-storage
|
|
paths: [/api/storage]
|
|
methods: [GET, POST, DELETE, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-subscriptions-v1
|
|
# Legacy v1 endpoint on agent-v3 (current v2 is on framework-api)
|
|
paths: [/api/v1/subscriptions]
|
|
methods: [GET, POST, DELETE, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, legacy:v1]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-agent-upload
|
|
paths: [/api/upload]
|
|
methods: [POST, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
# Public endpoints (no JWT)
|
|
- name: didi-agent-health
|
|
# Local had strip_path=true: /agent/health -> "/" on agent-v3 (root, returns 200)
|
|
paths: [/agent/health]
|
|
methods: [GET, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: true
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true]
|
|
- name: didi-agent-status
|
|
paths: [/api/status]
|
|
methods: [GET, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true]
|
|
- name: didi-agent-media-public
|
|
# Public media playback proxy (range-supported, served by agent-v3 itself)
|
|
paths: [/api/v3/media/file]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true]
|
|
- name: didi-agent-v3-prefix
|
|
# Edge nginx forwards /agent-v3/* here. Local Kong stripped the prefix
|
|
# (e.g. /agent-v3/api/v3/health -> /api/v3/health on agent-v3).
|
|
# Local had JWT plugin on this route — preserved here to match security model.
|
|
paths: [/agent-v3]
|
|
hosts: *didi-hosts
|
|
strip_path: true
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
# Browser extension API endpoints — NO JWT (X-API-Key validated in agent-v3).
|
|
# All four routes share the same request-transformer pattern + rate-limit.
|
|
# Regex paths (~ prefix) with `$` anchor prevent /analyze matching /analyze-async.
|
|
|
|
- name: didi-agent-extension-analyze
|
|
# Sync analyze (legacy — small text only, hits Cloudflare 100s timeout otherwise)
|
|
paths: [~/agent-v3/api/v3/pipeline/extension/analyze$]
|
|
methods: [POST, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true, auth:api-key]
|
|
plugins:
|
|
- name: request-transformer
|
|
config:
|
|
replace:
|
|
uri: /api/v3/pipeline/extension/analyze
|
|
- name: rate-limiting
|
|
config: &ext-rate-limit
|
|
minute: 30
|
|
hour: 500
|
|
policy: local
|
|
limit_by: header
|
|
header_name: X-API-Key
|
|
fault_tolerant: true
|
|
hide_client_headers: false
|
|
error_code: 429
|
|
error_message: "API rate limit exceeded"
|
|
|
|
- name: didi-agent-extension-analyze-async
|
|
# Async dispatch — returns 202 + session_id (used by extension for all flows)
|
|
paths: [~/agent-v3/api/v3/pipeline/extension/analyze-async$]
|
|
methods: [POST, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true, auth:api-key]
|
|
plugins:
|
|
- name: request-transformer
|
|
config:
|
|
replace:
|
|
uri: /api/v3/pipeline/extension/analyze-async
|
|
- name: rate-limiting
|
|
config: *ext-rate-limit
|
|
|
|
- name: didi-agent-extension-upload
|
|
# Multipart media upload (screenshot/video) — multer expects "file" field
|
|
paths: [~/agent-v3/api/v3/pipeline/extension/upload$]
|
|
methods: [POST, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true, auth:api-key]
|
|
plugins:
|
|
- name: request-transformer
|
|
config:
|
|
replace:
|
|
uri: /api/v3/pipeline/extension/upload
|
|
- name: rate-limiting
|
|
config: *ext-rate-limit
|
|
|
|
- name: didi-agent-extension-status
|
|
# Polling endpoint with sessionId capture — rewrite preserves the UUID
|
|
paths: ['~/agent-v3/api/v3/pipeline/extension/status/(?<sid>[\w-]+)$']
|
|
methods: [GET, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true, auth:api-key]
|
|
plugins:
|
|
- name: request-transformer
|
|
config:
|
|
replace:
|
|
uri: /api/v3/pipeline/extension/status/$(uri_captures.sid)
|
|
- name: rate-limiting
|
|
config:
|
|
# Polling can hit this every 2s — bump per-minute limit
|
|
minute: 120
|
|
hour: 2000
|
|
policy: local
|
|
limit_by: header
|
|
header_name: X-API-Key
|
|
fault_tolerant: true
|
|
hide_client_headers: false
|
|
error_code: 429
|
|
error_message: "Polling rate limit exceeded"
|
|
|
|
# ----------------------------------------------------------
|
|
# SERVICE 2: didi-framework (was: framework-api + didi-framework)
|
|
# ----------------------------------------------------------
|
|
- name: didi-framework
|
|
protocol: http
|
|
host: didi.local
|
|
port: 3005
|
|
retries: 5
|
|
connect_timeout: 60000
|
|
write_timeout: 60000
|
|
read_timeout: 60000
|
|
tags: [product:didi, env:prod, kind:api]
|
|
plugins:
|
|
- name: cors
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
origins: [https://didi365.eu, https://www.didi365.eu]
|
|
methods: [GET, POST, PUT, DELETE, OPTIONS, PATCH]
|
|
headers: [Accept, Authorization, Content-Type, X-Request-ID]
|
|
exposed_headers: [X-Request-ID]
|
|
credentials: true
|
|
max_age: 3600
|
|
preflight_continue: false
|
|
- name: request-size-limiting
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
allowed_payload_size: 104857600
|
|
size_unit: bytes
|
|
require_content_length: false
|
|
- name: response-transformer
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
add:
|
|
headers: ["X-Gateway:DIDI-Kong-Cluster", "X-API-Version:2.0"]
|
|
remove:
|
|
headers: [Server, Via]
|
|
- name: correlation-id
|
|
tags: [product:didi, env:prod]
|
|
config:
|
|
header_name: X-Request-ID
|
|
generator: uuid
|
|
echo_downstream: true
|
|
routes:
|
|
- name: didi-framework-auth
|
|
paths: [/api/auth]
|
|
methods: [GET, POST, PUT, DELETE, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-framework-auth-verify-email
|
|
# PUBLIC route — must beat /api/auth (JWT) on priority
|
|
paths: [/api/auth/verify-email]
|
|
methods: [GET, POST]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
regex_priority: 100
|
|
tags: [product:didi, env:prod, public:true]
|
|
- name: didi-framework-history
|
|
paths: [/api/history]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-framework-subscriptions
|
|
# Current /api/subscriptions endpoint (v2). Legacy /api/v1/subscriptions is on agent-v3.
|
|
paths: [/api/subscriptions]
|
|
methods: [GET, POST, DELETE, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
plugins:
|
|
- name: jwt
|
|
config: *jwt-config
|
|
- name: didi-framework-waitlist
|
|
# PUBLIC waitlist signup. Local Kong had this duplicated (one with JWT, one without).
|
|
# Keeping no-JWT version — public signup is correct behavior.
|
|
paths: [/api/waitlist]
|
|
methods: [GET, POST, DELETE, OPTIONS]
|
|
hosts: *didi-hosts
|
|
strip_path: false
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod, public:true]
|
|
- name: didi-framework-direct
|
|
# Legacy /framework prefix — local had strip_path=true so /framework/api/X -> /api/X on framework
|
|
paths: [/framework]
|
|
hosts: *didi-hosts
|
|
strip_path: true
|
|
preserve_host: true
|
|
tags: [product:didi, env:prod]
|
|
|
|
# ----------------------------------------------------------
|
|
# NOTE: didi-admin NOT migrated — internal-only (VPN access to didi.local directly).
|
|
# Will be revisited after admin nginx is replaced with simpler setup.
|
|
# ----------------------------------------------------------
|
|
|
|
# ----------------------------------------------------------
|
|
# NOTE: didi-keycloak service REMOVED 2026-04-29.
|
|
# DIDI now uses the external SSO cluster (https://sso.local/realms/didi-clients) directly
|
|
# — SPA goes browser→sso.local, no proxy through cluster Kong needed.
|
|
# JWT consumer didi-keycloak-users still validates tokens for SSO issuer.
|
|
# ----------------------------------------------------------
|