Files
gw-triage/knowledge/zeus.md
2026-07-04 18:58:25 +02:00

15 KiB
Raw Permalink Blame History

System identity

Zeus is the .NET 8 multi-service platform powering the GrowingWay property-rental product. Owner: Giuseppe. Area keys: backend, backoffice, infra.

Three deployable services:

  • zeus_auth — Auth, User, Policy, Devices, Settings gRPC APIs (host auth.{DOMAIN})
  • zeus_property — Announcement, Booking, Chat, Review, Notification gRPC APIs + SignalR payment and chat hubs (host property.{DOMAIN})
  • zeus_admin — Blazor Server backoffice dashboard (host admin.{DOMAIN})

Infrastructure: nginx edge (SNI/L4 passthrough on :443) → per-env nginx web (TLS termination, L7 host-header routing) → backend containers. Redis for SignalR session registries. PostgreSQL (remote, never touch locally). Google Cloud Storage for images. Stripe for payments. Ermes (external gRPC) for SMS.

User-visible surfaces

zeus_admin (backoffice) pages — URL : nav label : heading

  • / : Home : Panoramica — summary: host count, annunci count, media annunci/host
  • /Users : Users — backoffice account management
  • /support-levels : Livelli Supporto : Livelli di Supporto — RBAC for support operators
  • /Policy : Policy — policy types and versions
  • /amenities : Servizi : Gestione Servizi — amenity categories and types
  • /tags : Announcement Tags : Gestione Tag Annunci
  • /reviews : Recensioni : Recensioni — review parameters
  • /Verifications : Verifiche Utenti : Richieste di Verifica — KYC queue (fronte/retro documento + selfie)
  • /Hosts : Host : Host — host list; columns: Nome, Cognome, Email, Telefono, Città, Annunci, Referral, Verifica, Registrato il, Azioni
  • /Hosts/{id} — host detail: Dati Personali, Stripe onboarding, announcements, bookings, availability block, referrals
  • /Announcements/{id} — annuncio detail: Titolo, Descrizione, Meta Descrizione, Indirizzo
  • /Bookings : Prenotazioni : Prenotazioni — columns: Stato, Pagamento, Guest, Host, Check-in, Check-out, Importo, Prossima cattura, Creata
  • /Bookings/{id} : Prenotazione — sections: Dettagli prenotazione, Sessione di pagamento, Tentativi; actions: Cattura ora / Ripianifica / Force Accept / Force Reject / Force Cancel
  • /Guests : Guest — guest user list
  • /support/chats : Chat Supporto : Chat Supporto — columns: Nome, Cognome, ID Utente, Ultima attività
  • /support/chats/{userId} — live support chat conversation
  • /reports : Segnalazioni : Segnalazioni — chat-report moderation; columns: Segnalante, Segnalato, Motivo, Stato (Open / Reviewed / Dismissed), Data, Azioni; "Bloccata" chip on blocked conversations; action "Blocca conversazione"
  • /support : Apri sessione di supporto / Sessione di supporto attiva — operator enters user's Codice Supporto; session becomes active after user acceptance
  • /support/user : Utente Target — data view for active support-session user

zeus_property gRPC services (app-facing)

GuestAnnouncementService (browse/search listings), GuestBookingService (Book, RetryPayment, CancelBooking, GetSummary), GuestChatService (SendMessage, GetMessages, RequestSupportChat, ReportUser, BlockUser), GuestReviewService, GuestNotificationService (ListNotifications, MarkNotificationRead), GuestReceiptService, GuestFeedbackService, HostPropertyService (listing CRUD, image upload), HostBookingService (ConfirmReservation, ghost bookings), HostOnboardingService (Stripe Connect), HostReferralService (referral code get/set).

SignalR hubs: /api/guest/payments (PaymentHub — BindSession → IssuePayment → Success/Failed callbacks), /api/guest/chat (ChatHub — real-time delivery).

zeus_auth gRPC services

AuthAuthenticationService (Register, Login, ConfirmPhoneNumber, Refresh, RecoverPassword, VerifyConfirmationCode), AuthUserService (profile, KYC upload + submit), AuthPolicyService (SubscribeToPolicy, streaming updates), AuthDevicesService, AuthSettingsService, AuthLogService (Flutter log ingest), PrivacyService (account deletion).

Error fingerprints

Errors surface as gRPC status codes (and mapped HTTP codes for transcoding). The Flutter app displays the localized message field from the gRPC Status detail. HTTP-transcoded errors carry headers X-Error: true and X-Error-Message: <KEY> with statusCode 400/401/403/404/409/429/500/503.

Localized error strings (it-IT / en-US) — from Zeus.Errors/errors.json

Key it-IT en-US
UNHANDLED "Abbiamo riscontrato un errore inaspettato. Riprova più tardi." "We encountered an unexpected error. Please try again later."
INTERNAL_ERROR "Qualcosa è andato storto. Riprova più tardi." "Something went wrong. Please try again later."
WRONG_PASSWORD "La password inserita non è corretta." "The password you entered is incorrect."
INVALID_CONFIRMATION_CODE "Il codice di verifica inserito è incorretto o scaduto." "The verification code you entered is incorrect or has expired."
SMS_SERVICE_UNAVAILABLE "Stiamo avendo problemi nell'invio degli SMS. Riprova più tardi." "We're having trouble sending text messages right now. Please try again later."
INVALID_ACCESS_TOKEN "La tua sessione è scaduta. Effettua nuovamente l'accesso." "Your session has expired. Please log in again."
DUPLICATE_EMAIL "Questo indirizzo email è già associato a un altro account." "This email address is already associated with another account."
DUPLICATE_PHONE_NUMBER "Questo numero di telefono è già associato a un altro account." "This phone number is already associated with another account."
ANNOUCEMENT_NOT_FOUND (sic) "Abbiamo riscontrato un errore nel recuperarti questo annuncio" "We're having trouble getting this announcement."
APARTMENT_UNAVAILABLE "Questo appartamento non è più disponibile." "This apartment is no longer available."
PRICE_CHANGED "Il prezzo per questo appartamento è cambiato." "The price for this apartment has changed."
PAYMENT_FAILED "Il pagamento non è andato a buon fine. Riprova." "The payment was unsuccessful. Please try again."
UNBOUND_PAYMENT_SESSION "Qualcosa è andato storto. Riprova più tardi." "Something went wrong. Please try again later."
TOO_MANY_CODE_REQUESTED "Sono stati richiesti troppi codici per questo numero di telefono oggi." "Too many codes were requested for this phone number today."
TERMS_NOT_ACCEPTED "Devi accettare i termini e le condizioni per continuare." "You must accept the terms and conditions to continue."
NO_HOST_DATA_FOUND "Configurazione host non trovata. Completa il processo di registrazione." "Host configuration not found. Please complete the onboarding process."
HOST_ONLY_METHOD "Quest'operazione è accessibile solo ai nostri host" "This operation can only be performed by our hosts"
ANNOUNCEMENT_HAS_NO_IMAGES "Aggiungi almeno un'immagine a questo annuncio." "Please add at least one image to this announcement."
InvalidImage "L'immagine fornita non è valida." "The image provided is not valid."
CHAT_BLOCKED "Non puoi inviare messaggi in questa conversazione." "You can't send messages in this conversation."
CANNOT_CHAT_WITH_SELF "Non puoi avviare una chat con te stesso." "You can't start a chat with yourself."
BOOKING_NOT_COMPLETED "Puoi recensire una prenotazione solo dopo che il soggiorno è completato." "You can only review a booking after the stay is completed."
ANNOUNCEMENT_ALREADY_REVIEWED "Hai già recensito questo annuncio." "You have already reviewed this stay."
INVALID_REFERRAL_CODE "Questo codice invito non esiste. Controllalo e riprova." "This referral code doesn't exist. Please check it and try again."
INVALID_REFERRAL_CODE_FORMAT "Il codice invito deve contenere da 4 a 16 lettere o numeri." "A referral code must be 4-16 letters or numbers."
REFERRAL_CODE_TAKEN "Questo codice invito è già in uso. Scegline un altro." "This referral code is already in use. Please choose another one."
MISSING_RECAPTCHA_TOKEN "Completa il captcha e riprova." "Please complete the captcha challenge and try again."
INVALID_RECAPTCHA_TOKEN "La validazione del captcha non e riuscita. Riprova." (sic) "Captcha validation failed. Please try again."

Admin-only (Zeus.Admin/errors.json):

Key it en
INVALID_SUPPORT_CODE "Il codice di supporto inserito non è valido" "The support code is not valid"
UNAUTHORIZED_SUPPORT_REQUEST "Questa richiesta non è ancora stata accettata" "This request has not yet been accepted"

gRPC status codes and infrastructure errors

Scenario gRPC status Code
Backend container down / nginx upstream fail Unavailable 14
DB unreachable (first call) Internal 13
Unhandled exception Internal 13
Auth failure / expired JWT Unauthenticated 16
Validation errors InvalidArgument 3
Rate limit (OTP flood / SMS flood) ResourceExhausted 8
State-guard violations FailedPrecondition 9
Stripe payment declined Aborted 10

Payment SignalR failure codes: Failed(code) where code is a Stripe string (card_declined, insufficient_funds, amount_mismatch) or a Zeus key (PAYMENT_FAILED, UNBOUND_PAYMENT_SESSION). These raw codes reach the Flutter app directly — they are NOT localized by the server.

TLS failure appears as CERTIFICATE_VERIFY_FAILED or HandshakeException in Flutter logs (not a Zeus error; see infra).

Symptom → area heuristics

  • payment stuck / perpetually "processing" after booking confirmation → backend (Stripe webhook not processed; check StripeWebhookController logs for signature failure)
  • "Il pagamento non è andato a buon fine" before card entry → backend (PAYMENT_SESSION_CLOSED or UNBOUND_PAYMENT_SESSION; admin may have force-cancelled the session)
  • payment Failed callback with Stripe code (card_declined, insufficient_funds) → backend (Stripe declined; retry flow in app is correct)
  • chat messages sent but other party never receives → backend (check SendMessage gRPC response + Redis chat registry; SetOnline may have expired)
  • "Non puoi inviare messaggi in questa conversazione" → backend (CHAT_BLOCKED — conversation blocked by moderation; check backoffice Segnalazioni for a "Bloccata" chip; unblock is an admin action)
  • OTP / SMS login code not arriving → backend (Ermes SMS service; key SMS_SERVICE_UNAVAILABLE)
  • OTP code rejected as wrong or expired → backend (INVALID_CONFIRMATION_CODE)
  • registration rejected for existing email/phone → backend (DUPLICATE_EMAIL / DUPLICATE_PHONE_NUMBER)
  • captcha error at login/registration → backend (missing/invalid x-recaptcha-token; frequent after app-side token expiry — if the challenge never appears, app-shared)
  • referral code rejected ("Questo codice invito non esiste" / "già in uso") → backend (HostReferralService validation)
  • wrong or missing data shown in app with correct layout → backend (data model or repository issue)
  • announcement detail missing, showing error toast → backend (ANNOUCEMENT_NOT_FOUND)
  • booking dates show as unavailable despite being free → backend (APARTMENT_UNAVAILABLE — availability row state)
  • "La tua sessione è scaduta" in the middle of a session (not at launch) → backend (INVALID_ACCESS_TOKEN returned by server; JWT refresh failed)
  • host onboarding "Completa il processo di registrazione" on every login → backend (NO_HOST_DATA_FOUND — HostData row missing)
  • notification badge count never resets → backend (MarkNotificationRead failing server-side, e.g. stale notification ID)
  • user cannot leave a review after a stay → backend (BOOKING_NOT_COMPLETED — booking not yet Completed — or ANNOUNCEMENT_ALREADY_REVIEWED)
  • admin dashboard page errors, wrong data in grids, action buttons fail → backoffice
  • admin support code rejected ("Il codice di supporto inserito non è valido") → backoffice
  • Referral column in Hosts grid empty or wrong count → backoffice (grid query; referral data itself is backend)
  • site / app entirely unreachable, no HTTP response at all → infra (nginx.edge or docker stack down; TCP connection refused on :443/:80)
  • 502 from nginx, gRPC status 14 "Unavailable" → infra (upstream container crash)
  • TLS certificate warning or CERTIFICATE_VERIFY_FAILEDinfra (Let's Encrypt cert expired or nginx misconfigured)
  • visual glitches, overflow stripes, layout overflow, misaligned widgets → app-shared (Flutter rendering; not Zeus)
  • platform-specific crash on Android or iOS (no network call) → app-android / app-ios

Domain glossary

Italian term System concept
Annuncio / Annunci Announcement entity; listing published by a host
Host A user who completed Stripe onboarding; can publish annunci
Ospite / Guest A user making a booking
Prenotazione / Prenotazioni BookingOrder entity
Prenotazione fantasma / ghost booking Host-created date block for externally-sourced bookings (Airbnb, phone)
Check-in / Check-out Arrival and departure dates on a booking
Sessione di pagamento PaymentSession — Stripe PaymentIntent/SetupIntent lifecycle; statuses: Ongoing, AwaitingCapture, Succeeded, Failed, Cancelled
Segnalazione / Segnalazioni ChatReport — chat moderation report; statuses: Open, Reviewed, Dismissed
Conversazione bloccata / Blocca conversazione Admin moderation block on a chat; users get CHAT_BLOCKED
Verifica / Verifiche Utenti VerificationRequest — KYC identity check; statuses: Draft, Pending, Approved, Rejected
Recensione / Recensioni AnnouncementReview — post-stay review; only possible after booking Completed
Servizi Amenities (wifi, parking, …); GuestAmenityService
Notifica In-app notification; GuestNotificationService
Codice Supporto Short-lived code user reads aloud to operator to start a support session
Sessione di supporto Admin operator impersonation session for support
Livelli di Supporto RBAC levels for admin operators
Codice invito / referral Referral code; HostReferralService; 416 alphanumeric chars
Cattura / Cattura ora Stripe delayed capture; admin action on booking detail
Panoramica Admin dashboard home

Not mine

  • Visual rendering artifacts, overflow widgets, clipped text, wrong font size → app-shared
  • "Sessione scaduta" toast at app launch with no network request in logs → app-shared (Flutter JWT expiry check done locally — no server call)
  • Search map shows no results despite listings existing (no gRPC error) → app-shared (Flutter map range / filter state)
  • Chat messages in wrong order or duplicated → app-shared (Flutter merge of historical stream + SignalR without dedup)
  • Announcement images load as blank (HTTP 200 from GCS) → app-shared (Flutter image widget render failure; HTTP 403 = expired GCS URL = backend)
  • Host calendar shows wrong blocked dates after refresh → app-shared (stale local cache; re-calling GetReservations returns correct data)
  • Android-specific crash, iOS-specific crash → app-android / app-ios
  • Store deployment failures, app binary issues → app-android / app-ios
  • Push notification delivery on device (FCM/APNs) → app-shared (not Zeus; Zeus only stores tokens via AuthDevicesService)