{ "version": 1, "description": "Pingora shadow gateway routes that must stay aligned with the current Genarrative Nginx production/development templates before any public cutover.", "routes": [ { "id": "acme_challenge", "samplePath": "/.well-known/acme-challenge/token", "expect": { "kind": "static", "root": "acme", "mode": "exact" }, "nginx": { "production": [ "location /.well-known/acme-challenge/", "root /var/www/html;" ] }, "docs": [ "`/.well-known/acme-challenge/*`" ] }, { "id": "shadow_probe", "samplePath": "/__genarrative_pingora/healthz", "expect": { "kind": "shadow_probe" }, "docs": [ "`/__genarrative_pingora/healthz`" ] }, { "id": "admin_redirect", "samplePath": "/admin", "expect": { "kind": "redirect_permanent", "location": "/admin/" }, "nginx": { "production": [ "location = /admin", "return 301 /admin/;" ], "development": [ "location = /admin", "return 301 /admin/;" ] }, "docs": [ "`/admin`", "301 到 `/admin/`" ] }, { "id": "admin_api_proxy", "samplePath": "/admin/api/users", "expect": { "kind": "proxy", "target": "api", "bodyLimit": null, "protectionClass": "admin_api" }, "nginx": { "production": [ "location ^~ /admin/api/", "proxy_pass http://genarrative_api/admin/api/;", "limit_conn genarrative_api_conn 64;", "limit_req zone=genarrative_admin_rps burst=16 nodelay;" ], "development": [ "location ^~ /admin/api/", "proxy_pass http://genarrative_api/admin/api/;", "limit_conn genarrative_api_conn 64;", "limit_req zone=genarrative_admin_rps burst=16 nodelay;" ] }, "docs": [ "`/admin/api/*`" ] }, { "id": "admin_assets", "samplePath": "/admin/assets/index.js", "expect": { "kind": "static", "root": "web", "mode": "exact" }, "nginx": { "production": [ "location ^~ /admin/assets/", "try_files $uri =404;" ], "development": [ "location ^~ /admin/assets/", "try_files $uri =404;" ] }, "docs": [ "`/admin/assets/*`" ] }, { "id": "admin_spa_fallback", "samplePath": "/admin/settings", "expect": { "kind": "static", "root": "web", "mode": "spa_fallback" }, "nginx": { "production": [ "location ^~ /admin/", "try_files $uri $uri/ /admin/index.html;" ], "development": [ "location ^~ /admin/", "try_files $uri $uri/ /admin/index.html;" ] }, "docs": [ "`/admin/*`" ] }, { "id": "web_assets", "samplePath": "/assets/app.js", "expect": { "kind": "static", "root": "web", "mode": "exact" }, "nginx": { "production": [ "location ^~ /assets/", "try_files $uri =404;" ], "development": [ "location ^~ /assets/", "try_files $uri =404;" ] }, "docs": [ "`/assets/*`" ] }, { "id": "generic_api_proxy", "samplePath": "/api/assets/history", "expect": { "kind": "proxy", "target": "api", "bodyLimit": "default", "protectionClass": "api" }, "nginx": { "production": [ "location ~ ^/api(?:/|$)", "client_max_body_size 64m;", "limit_conn genarrative_api_conn 64;", "limit_req zone=genarrative_api_rps burst=64 nodelay;", "add_header X-Accel-Buffering no always;" ], "development": [ "location ~ ^/api(?:/|$)", "client_max_body_size 64m;", "limit_conn genarrative_api_conn 64;", "limit_req zone=genarrative_api_rps burst=64 nodelay;", "add_header X-Accel-Buffering no always;" ] }, "docs": [ "`/api`、`/api/*`" ] }, { "id": "spacetime_subscribe", "samplePath": "/v1/database/genarrative/subscribe", "expect": { "kind": "proxy", "target": "spacetime", "bodyLimit": null, "protectionClass": "spacetime" }, "nginx": { "production": [ "location ~ ^/v1/database/[^/]+/subscribe$", "proxy_pass http://127.0.0.1:3101;", "proxy_set_header Upgrade $http_upgrade;", "proxy_set_header Connection \"Upgrade\";", "proxy_read_timeout 3600s;" ], "development": [ "location ~ ^/v1/database/[^/]+/subscribe$", "proxy_pass http://127.0.0.1:3101;", "proxy_set_header Upgrade $http_upgrade;", "proxy_set_header Connection \"Upgrade\";", "proxy_read_timeout 3600s;" ] }, "docs": [ "`/v1/database/{db}/subscribe`" ] }, { "id": "spacetime_identity", "samplePath": "/v1/identity", "expect": { "kind": "proxy", "target": "spacetime", "bodyLimit": null, "protectionClass": "spacetime" }, "nginx": { "production": [ "location ^~ /v1/identity", "proxy_pass http://127.0.0.1:3101;", "proxy_set_header Upgrade $http_upgrade;", "proxy_set_header Connection \"Upgrade\";" ], "development": [ "location ^~ /v1/identity", "proxy_pass http://127.0.0.1:3101;", "proxy_set_header Upgrade $http_upgrade;", "proxy_set_header Connection \"Upgrade\";" ] }, "docs": [ "`/v1/identity*`" ] }, { "id": "v1_forbidden", "samplePath": "/v1/ping", "expect": { "kind": "not_found" }, "nginx": { "production": [ "location ^~ /v1/", "return 404;" ], "development": [ "location ^~ /v1/", "return 404;" ] }, "docs": [ "`/v1/*`" ] }, { "id": "healthz_forbidden", "samplePath": "/healthz", "expect": { "kind": "not_found" }, "nginx": { "production": [ "location ~ ^/(generated-|healthz|readyz)", "return 404;" ], "development": [ "location ~ ^/(generated-|healthz|readyz)", "return 404;" ] }, "docs": [ "`/healthz*`" ] }, { "id": "readyz_forbidden", "samplePath": "/readyz", "expect": { "kind": "not_found" }, "nginx": { "production": [ "location ~ ^/(generated-|healthz|readyz)", "return 404;" ], "development": [ "location ~ ^/(generated-|healthz|readyz)", "return 404;" ] }, "docs": [ "`/readyz*`" ] }, { "id": "generated_assets_forbidden", "samplePath": "/generated-puzzle-assets/foo.webp", "expect": { "kind": "not_found" }, "nginx": { "production": [ "location ~ ^/(generated-|healthz|readyz)", "return 404;" ], "development": [ "location ~ ^/(generated-|healthz|readyz)", "return 404;" ] }, "docs": [ "`/generated-*`" ] }, { "id": "web_spa_fallback", "samplePath": "/project", "expect": { "kind": "static", "root": "web", "mode": "spa_fallback" }, "nginx": { "production": [ "# BEGIN GENARRATIVE MAIN SPA ROUTES", "try_files $uri /index.html =404;" ], "development": [ "# BEGIN GENARRATIVE MAIN SPA ROUTES", "try_files $uri /index.html =404;" ] }, "docs": [ "主站 SPA allowlist", "失败回退 `/index.html`" ] }, { "id": "profile_spa_fallback", "samplePath": "/profile", "expect": { "kind": "static", "root": "web", "mode": "spa_fallback" }, "nginx": { "production": [ "# BEGIN GENARRATIVE MAIN SPA ROUTES", "try_files $uri /index.html =404;" ], "development": [ "# BEGIN GENARRATIVE MAIN SPA ROUTES", "try_files $uri /index.html =404;" ] }, "docs": [ "主站 SPA allowlist", "失败回退 `/index.html`" ] }, { "id": "web_spa_case_trailing_slash", "samplePath": "/PROJECT/", "expect": { "kind": "static", "root": "web", "mode": "spa_fallback" }, "nginx": { "production": [ "location ~*", "try_files $uri /index.html =404;" ], "development": [ "location ~*", "try_files $uri /index.html =404;" ] }, "docs": [ "大小写不敏感", "一个尾部斜杠" ] }, { "id": "web_unknown_path_exact", "samplePath": "/some/spa/path", "expect": { "kind": "static", "root": "web", "mode": "exact" }, "nginx": { "production": [ "location /", "try_files $uri $uri/ =404;" ], "development": [ "location /", "try_files $uri $uri/ =404;" ] }, "docs": [ "其它 Web 路径", "缺失时返回真实 404" ] }, { "id": "creation_unknown_path_exact", "samplePath": "/creation/not-exist", "expect": { "kind": "static", "root": "web", "mode": "exact" }, "nginx": { "production": [ "try_files $uri $uri/ =404;" ], "development": [ "try_files $uri $uri/ =404;" ] }, "docs": [ "`/creation/not-exist`" ] }, { "id": "runtime_unknown_path_exact", "samplePath": "/runtime/not-exist", "expect": { "kind": "static", "root": "web", "mode": "exact" }, "nginx": { "production": [ "try_files $uri $uri/ =404;" ], "development": [ "try_files $uri $uri/ =404;" ] }, "docs": [ "`/runtime/not-exist`" ] }, { "id": "puzzle_unknown_path_exact", "samplePath": "/puzzle/not-exist", "expect": { "kind": "static", "root": "web", "mode": "exact" }, "nginx": { "production": [ "try_files $uri $uri/ =404;" ], "development": [ "try_files $uri $uri/ =404;" ] }, "docs": [ "`/puzzle/not-exist`" ] } ] }