The DevOps admin preHandler read 'auth' as '(request as any).auth'.
The proper Fastify pattern is 'declare module' augmentation in
@bytelyst/fastify-auth, but the inline cast through 'unknown' is
sufficient for now and avoids touching the shared auth package.
Changed:
- 'const auth = (request as any).auth;' \u2192
'const auth = (request as unknown as { auth?: { role?: string } }).auth;'
Inline comment notes the cleaner 'declare module' alternative.
Final ecosystem state:
scripts/check-rule-violations.sh: 0 findings across all rules \u2713
web-hardcoded-hex: 0 \u2713
b5-hardcoded-product-id: 0 \u2713
b4-console-log: 0 \u2713
b4-swift-print: 0 \u2713
b4-python-print: 0 \u2713
ts-any-type: 0 \u2713
b7-emoji-in-code: 0 \u2713
The platform-service build was failing with 3 unrelated TS errors,
surfaced while running the Gitea outdated-package detector earlier
in this session:
src/server.ts(18,8): Cannot find module '@bytelyst/devops/server'
src/server.ts(318,61): Property 'cosmosEndpoint' does not exist on type 'ProductIdentity'
src/server.ts(321,42): Property 'platformServiceUrl' does not exist on type 'ProductIdentity'
Root causes (two distinct bugs):
1. Stale install. '@bytelyst/devops' was already declared as
'workspace:*' in services/platform-service/package.json (line 24),
but node_modules/@bytelyst/devops/ did not exist. Re-running
'pnpm install' at the workspace root materialised the symlink.
2. Variable shadowing. In the GET /devops/info handler the code
declared a local 'const config' from loadProductIdentity() that
shadowed the module-level 'config' (env vars) imported from
'./lib/config.js' at line 112. The author then tried to read
'config.cosmosEndpoint' and 'config.platformServiceUrl' off the
ProductIdentity, where those keys never exist:
ProductIdentity = {
productId, displayName, licensePrefix, configDirName,
envVarPrefix, bundleIdSuffix, packageName
}
The intended values live on the env config:
config.COSMOS_ENDPOINT (Zod-validated, required at boot)
config.HOST + config.PORT (defaults '0.0.0.0' / 4003)
There is no 'platformServiceUrl' field anywhere in the codebase —
it only appeared in this single buggy line. Reconstructed as
'\${HOST}:\${PORT}' which is the URL admins would use to reach
this service for the devops/info diagnostic dashboard.
Fix (services/platform-service/src/server.ts:310-339):
- Rename local 'const config' to 'const productIdentity' to break
the shadowing.
- Use productIdentity.productId for the devops productId field.
- Use config.COSMOS_ENDPOINT (the env config) for the cosmos
dependency health check URL.
- Use `http://${config.HOST}:${config.PORT}` for the extra
platformServiceUrl field.
- Add a doc comment block explaining the two-config distinction
so future contributors don't reintroduce the shadow.
Verified:
pnpm --filter @lysnrai/platform-service build OK (0 errors)
pnpm --filter @lysnrai/platform-service test 1511/1512 pass
The 1 remaining failure (src/modules/products/cache.test.ts line 104,
'returns all cached products' expects 2 products but got 3) is a
PRE-EXISTING product-registry test drift on main, verified by
stashing this commit's changes and re-running the same test against
the unmodified tree. It will be addressed separately.
- Add @bytelyst/devops backend endpoints to platform-service
- Add /api/devops/version (public) and /api/devops/info (admin) endpoints
- Add /devops page to admin-web using @bytelyst/devops/ui DevopsPanel
- Add devops link to admin web sidebar navigation
- Add build metadata and runtime information display
- Follow trading web devops pattern
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Phase 0 from DASHBOARD_UI_COVERAGE_ROADMAP:
- Register ai-diagnostics routes in server.ts (671-line module was never mounted)
- Add 6 hidden pages to admin sidebar-nav.tsx:
Debug Sessions, Health Dashboard, Extraction, Experiments,
Predictive, AI Diagnostics
- /users was already in sidebar (no change needed)
- Kill switch verified: already per-product via productId query param
- Admin sidebar now has 33 items (was 27)
- GET /auth/mfa/totp/secret — retrieve decrypted TOTP secret for auth app
- POST /auth/mfa/push/create, GET /pending, POST /:id/respond, GET /:id/status
- POST /auth/qr/create, POST /auth/qr/confirm, GET /auth/qr/:id/status
- Kotlin SDK: getTotpSecret, getPendingApprovals, respondToApproval, confirmQrLogin
- Swift SDK: getTotpSecret, getPendingApprovals, respondToApproval, confirmQrLogin
- All 53 auth tests passing