Replace local password authentication with the organization user-service, personalize the chat interface from the returned profile, and run the complete interface stack in minikube with access at http://localhost:3000.
The deployed user-service exposes POST /api/user/auth and accepts:
{
"identifier": "login-or-email",
"password": "plaintext-at-authentication-time"
}
A successful response is a safe user profile containing numeric id, login, full_name, position, email, last_name, first_name, middle_name, roles, is_active, created_at, and updated_at. It never contains a password or password hash. Invalid or inactive users produce 401.
The browser continues to call only POST /api/auth/login on the chat application. The login route calls ${USER_SERVICE_URL}/api/user/auth from the server with JSON { identifier, password }. Browser code never calls user-service directly and does not learn its internal URL.
On successful authentication, the chat application validates the full upstream profile and upserts a local user projection. The projection preserves a UUID primary key for existing chat foreign keys and stores a unique external service ID plus profile fields. No password or password hash from the external service is stored. Existing legacy local users remain readable, but local password authentication is removed.
The application issues its existing HS256 JWT with a 24-hour lifetime. Its subject is the local UUID and its claims include the email. /api/auth/me verifies the JWT against the local projection and returns the current stored profile. A later login refreshes changed profile fields from user-service.
Add a migration that:
users.password_hash nullable for external identities;external_user_id bigint UNIQUE, login, full_name, position, first_name, last_name, middle_name, and roles jsonb;last_model_id and the UUID id unchanged;external_user_id, email, login, full name, first name, last name, position, and roles for new external users.The repository exposes a single upsert operation keyed by external_user_id. It updates profile fields and updated_at, preserves the local UUID and last_model_id, and returns the complete local identity.
400.401 maps to the existing generic 401 login response without exposing upstream details.503.Cache-Control: no-store remains on auth responses.USER_SERVICE_URL is a required server-only environment variable and is normalized to avoid duplicate slashes.Extend AuthIdentity with externalUserId, login, fullName, position, firstName, lastName, middleName, and roles.
The login form label and autocomplete behavior support either login or email. The sidebar displays initials derived from first and last name, the full name, position, email, and compact role badges. The empty chat state greets the user by first name. Mobile and desktop layouts use the same profile component. Missing optional middle name does not create empty punctuation or spacing.
All resources run in namespace aegida-services:
user-service and user-service-postgres remain unchanged;ai-control-chat-ui Deployment and ClusterIP Service expose port 3000;USER_SERVICE_URL=http://user-service.aegida-services.svc.cluster.local:8080, database/S3 endpoints, Gateway mock mode, and non-secret application values;The image is built for minikube with a deterministic local tag and imagePullPolicy: IfNotPresent. Startup uses the existing entrypoint to wait/retry for dependencies, apply migrations, seed only legacy development data when explicitly enabled, ensure the private attachment bucket, then start Next.js. Kubernetes readiness and liveness probes use a lightweight application health endpoint.
After rollout succeeds, run:
kubectl -n aegida-services port-forward service/ai-control-chat-ui 3000:3000
The interface is then available at http://localhost:3000. This is intentionally workstation-local rather than a public internet endpoint. The handoff includes the port-forward process status and exact stop/restart commands.
401, and safe 503 behavior.kubectl apply --dry-run=client or server-side dry run where available./api/auth/me, and confirms the returned personalized profile.