logiSA 2.0 / DOCS

Design baseline · 24 SEP 2026 · 10 / 23

TDD · 9Router & model connection

Current behavior · Local admin UI, provider connections and production model proxy.

Hai đường đi khác nhau: dashboard quản trị embedded 9Router qua http://127.0.0.1:20128; Quarkus runtime gọi model qua gateway proxy /internal/v1/models/chat-completions với ROUTER_API_KEY. Tài khoản admin/cookie của local 9Router không phải API key dùng bởi production model proxy.

Phạm vi chức năng hiện có

01Operator UIExpress authenticated /api/nine-router/*
02Local Router admin APICookie session cho connections/models/OAuth/usage
03Quarkus model portText/vision request + X-Internal-Token
04TS gateway proxyBearer ROUTER_API_KEY → upstream 9Router

Preconditions

Admin API qua Dashboard

EndpointHành viFailure behavior
GET /api/nine-router/statusHealth probe local /api/health, timeout 3 giây; trả online/latency/port/gatewayUrl và version string hardcoded.Offline/error → online=false; health không test credential/provider/model.
GET /api/nine-router/connectionsLấy /api/providers, trả {connections}.Service lỗi → 500 + connections rỗng.
POST /api/nine-router/connectionsForward body provider/name/apiKey/defaultModel/priority tới local API; trả success/result.Service/provider validation lỗi → 500; route hiện không có schema validation riêng.
DELETE /api/nine-router/connections/:idForward ID encoded và xóa connection trong 9Router.Lỗi → 500.
GET /api/nine-router/models?search=&provider=Lấy toàn bộ models rồi lọc provider/name/model/alias ở Express; trả {models}.Lỗi → 500 + models rỗng. Catalog chưa phải probe inference.
GET /api/nine-router/usageForward usage stats của embedded router.Lỗi → 500.
POST /api/nine-router/test-chatBody yêu cầu prompt; model mặc định gpt-4o-mini; trả text/model/elapsedMs/usage + success.Prompt rỗng → 400; upstream error → 500.
GET /api/nine-router/oauth/:provider/authorizeLấy OAuth auth URL; redirect mặc định tùy provider (Codex khác provider còn lại).Lỗi → 500.
POST /api/nine-router/oauth/:provider/exchangeĐổi authorization code/state/verifier thành connection.Lỗi → 500.
GET /api/nine-router/oauth/:provider/device-code / POST …/pollBắt đầu/poll OAuth device flow.Lỗi → 500.

Request flow và error mapping

Các admin methods, gồm test-chat, dùng helper request: nếu chưa có cookie, POST password để lấy set-cookie; sau đó gửi cookie tới local API. Khi response 401, xóa cookie cục bộ, đăng nhập lại một lần rồi retry request một lần. Response non-2xx trở thành exception hiển thị qua Express 500. Status probe không đăng nhập.

Production path: Quarkus RestModelProviderAdapter gọi ModelGatewayClient với JSON-compatible chat completion và internal token. Gateway kiểm tra token và body object, rồi RouterAdapter POST {ROUTER_BASE_URL}/chat/completions với Bearer key, timeout 60 giây. Upstream non-2xx hoặc lỗi parse/network được gateway log, client nhận 502 model_provider_failed; key không trả ra response.

BoundarySuccessError / limitation
Browser → Express admin APIUser cookie, JSON; UI cập nhật cards/list/toast.Unauthenticated /api bị 401; nhưng provider/OAuth input validation phần lớn delegated cho 9Router.
Express service → embedded 9Router adminCookie-authenticated /api/providers, /api/models, /api/usage/stats, /api/oauth/*.Network/timeout/HTTP error thành error message; helper request không có timeout riêng.
Quarkus → TS gateway model proxyInternal token + chat-completion JSON.Sai token 401; thiếu router/key 503; body không object 400; upstream/model error 502.
TS gateway → upstream 9RouterBearer ROUTER_API_KEY, JSON; timeout 60s; trả JSON completion.Non-2xx error nội bộ, gateway log và response tổng quát 502. Response 2xx rỗng thành {}.
Finding đã được sửa trong source: testChat() nay gọi cùng helper request() như API admin, gửi cookie 9Router từ server-side login và thử login/retry một lần sau 401. Có unit test giả lập cookie hết hạn; kết quả test suite được ghi sau khi chạy.

Current TDD scenarios

IDScenario / expected observable behaviorEvidence status
NR-01Không có embedded router: status online=false; UI hiển thị gián đoạn.Có source behavior; thiếu unit test service cho status/network timeout.
NR-02Local router mở: health probe trả online=true và latency; không suy ra model available.Có source behavior; test health boundary đề xuất.
NR-03Admin/completion API call không có cookie tự login; 401 sẽ login lại và retry đúng một lần.Có test source: backend/dashboard-bff/tests/nineRouterService.test.ts cho test-chat cookie + re-login.
NR-04Sai password/local auth: error được trả từ route; không leak cookie.Có source behavior; dedicated redaction/secret test đề xuất.
NR-05List connections/models/usage thành công phản chiếu response router; search/provider filter chỉ lọc catalog.Có source behavior; test UI/API coverage cần bổ sung nếu contract quan trọng.
NR-06Add/delete provider và OAuth authorize/exchange/device-code/poll forward đúng provider + payload.Có source behavior; không có integration test chuyên biệt được thấy.
NR-07Test-chat thiếu prompt trả 400; completion hợp lệ gửi cookie và trả first choice content/model/usage.Có test source cho service cookie; route 400 được source xác nhận.
NR-08Production request thiếu ROUTER_API_KEY → 503 model_provider_not_configured.Có test không được tìm thấy; behavior nằm tại server startup/wiring.
NR-09Production request invalid JSON shape → 400; internal token thiếu/sai → 401.Gateway contract có test auth patterns; test route model cần bổ sung.
NR-10Upstream 9Router non-2xx/timeout/invalid JSON → client thấy 502 tổng quát, không thấy key.Source-derived; cần adapter test bằng fetch mock.
NR-11Provider/model không có credential/quyền hoặc vision capability sai → completion lỗi thay vì catalog label làm bằng chứng.No deterministic test fixture/provider sandbox contract; runtime acceptance cần model probe.
NR-12Chọn model trong catalog chỉ điền form; chỉ sau save settings mới là model cấu hình core.Có UI source và dashboard test pattern; không chứng minh request live thành công.

Kết quả test và bước xác nhận

Bộ kiểm traKết quảPhạm vi được chứng minh
bun run app:typecheckPASSTypeScript cho service và Dashboard.
bun run app:testPASS · 40/40Có dedicated service test cho test-chat cookie và retry sau 401; không bao phủ production inference.

Service test chạy với mock fetch. Chưa có inference acceptance trên embedded 9Router đang chạy hoặc provider credential thật.

Test design đề xuất cho lần sửa kế tiếp

  1. Mock local router: assert login request body, cookie extraction, cookie attached to admin API, một lần re-login sau 401, không có retry vô hạn.
  2. Mock `/v1/chat/completions`: xác nhận Authorization contract; nếu endpoint dùng API key, test key/cookie được gửi từ server-side secret source và UI không thể trả credential.
  3. Test Express route auth (401), prompt validation (400), status timeout/offline, provider CRUD error mapping và OAuth payload forwarding.
  4. Test gateway model proxy: auth, no provider, malformed request, upstream 4xx/5xx, timeout, response pass-through, secret redaction.
  5. Integration acceptance có credential thật cần test riêng theo model/provider, text và image riêng, schema/usage và timeout; catalog caps.vision chỉ là metadata.

Khoảng trống và không được suy diễn

Source of truth để bảo trì

backend/dashboard-bff/services/nineRouterService.ts; provider/admin routes trong backend/dashboard-bff/server.ts; UI controller frontend/current/app.js và markup frontend/current/index.html; production adapter gateway/adapters/router.ts, gateway/server.ts; Quarkus ModelGatewayClient.java, RestModelProviderAdapter.java, RestVisionProviderAdapter.java; gateway/README.md. Related tests gồm backend/dashboard-bff/tests/nineRouterService.test.ts (cookie + re-login), backend/dashboard-bff/tests/quarkusDashboard.test.ts (UI/model selection shape), và gateway/tests/gateway.test.ts (gateway auth/HTTP boundary). Các Express routes, gateway production proxy, và live provider inference chưa được kiểm thử end-to-end.

logiSA 2.0 · Public development cookbook · Design target; implementation status in Delivery.