Vai al contenuto
v26.3

Self-Service-Onboarding (Architettura)

Il Self-Service-Onboarding consente a potenziali clienti di configurare da soli, senza contatto commerciale, una propria istanza cloud DiKAS – a scelta come test gratuito (Trial) oppure direttamente come istanza live a pagamento. Questa pagina descrive l'architettura tecnica, la configurazione e i meccanismi di sicurezza. La visuale dell'utente finale è descritta in Registrazione online.

Disattivato per impostazione predefinita (Dark-Rollout)

Il funnel pubblico è protetto dal flag SelfServiceSignupEnabled ed è spento nello stato di consegna. Finché il flag è false, tutti gli endpoint pubblici restituiscono 404. Prima di un'attivazione vanno soddisfatti i punti elencati in Prima dell'attivazione.

Panoramica

Il processo è costituito da un wizard frontend pubblico e da una serie di endpoint backend anonimi. Il provisioning vero e proprio passa attraverso lo stesso ILicenseProvisioningService utilizzato anche dal percorso Portale e dal percorso Trial.

Ambito Posizione
Wizard frontend Rotta /signup (PublicOnboardingWizardComponent, app dikas-web)
Conferma Magic Link Rotta /signup/verify
Endpoint backend /api/v1/onboarding/public/* e /api/v1/trial/start
Feature pack Dikas.Features.Licensing

Il wizard guida attraverso sette passaggi: PacchettoTSE (Cloud vs. Swissbit) → Account (e-mail, senza password tramite Magic Link) → Dati aziendaliNome online (sottodominio) → Diritto e pagamentoCompletato (URL dell'istanza e credenziali di accesso).

Feature flag SelfServiceSignupEnabled

Il flag è una proprietà del documento singleton OperationalConfig (ID fisso operationalconfig) ed è modificabile solo tramite il database o l'interfaccia Admin – non esiste alcuna variabile d'ambiente per questo.

OperationalConfig.SelfServiceSignupEnabled  (bool, Default: false)

Ogni endpoint pubblico richiama prima CheckSelfServiceEnabledAsync() e risponde con 404 Not Found finché il flag è false. Il funnel resta così invisibile finché non viene attivato consapevolmente.

Endpoint pubblici

Tutti gli endpoint sono [AllowAnonymous] e protetti dal flag nonché dalle misure anti-abuso.

Metodo & percorso Scopo
POST /api/v1/onboarding/public/orders Creare un ordine bozza anonimo (restituisce un token d'ordine segreto)
PUT /api/v1/onboarding/public/orders/{id} Aggiornare la bozza (vincolata al token)
POST /api/v1/onboarding/public/orders/{id}/reserve-name Riservare temporaneamente il nome online
POST /api/v1/onboarding/public/register Creare un cliente senza password, inviare il Magic Link
POST /api/v1/onboarding/public/orders/{id}/bind Collegare l'ordine all'account verificato tramite Magic Link ([Authorize])
POST /api/v1/onboarding/public/payment/set Creare un SetupIntent/PaymentIntent Stripe (restituisce ClientSecret)
POST /api/v1/onboarding/public/payment/webhook Webhook Stripe (conferma di pagamento)
POST /api/v1/onboarding/public/orders/{id}/submit Effettuare il provisioning dell'istanza
GET /api/v1/onboarding/public/payment-config Publishable Key Stripe per il frontend
POST /api/v1/trial/start Trial self-service diretto (senza ordine/account portale)

Sicurezza / anti-abuso

Poiché ogni provisioning genera costi reali (COGS), sono attivi diversi livelli di protezione indipendenti tra loro:

  • Honeypot – un campo di modulo nascosto; se compilato, viene rifiutato silenziosamente con 202 Accepted (nessun provisioning).
  • Limitatore di errori per IP – ritardo esponenziale, blocco dopo 10 errori (1 h) ovvero 20 errori (24 h).
  • Quota di provisioning per IP e 24 h (MaxPublicProvisionsPerIpPer24h, default 3). Si applica sia al submit pubblico sia all'avvio del Trial e non viene azzerata in caso di successo. Se la quota viene superata, l'endpoint risponde con 429 (code: SIGNUP_RATE_LIMITED).
  • Quota di invio e-mail per IP e ora (MaxPublicEmailSendsPerIpPerHour, default 5) contro il Magic-Link-bombing.
  • Magic Link invece della classica conferma via e-mail; il clic verifica l'indirizzo e restituisce un JWT del portale, con cui l'ordine viene collegato.
  • IP client reale – dietro l'ingress, l'IP di origine viene determinato tramite ForwardedHeaders. Le reti attendibili (KnownNetworks) devono essere impostate nel deployment sul CIDR del cluster, altrimenti la quota per IP collassa.

Quote in memoria

Le quote vengono mantenute in memoria (finestra temporale scorrevole). Con più istanze dietro un load balancer, ogni istanza conta per sé; in tal caso occorre prevedere una sticky session o una cache condivisa.

Configurazione

Le opzioni vengono caricate dalla sezione Onboarding (OnboardingOptions). Tutti i valori hanno default sensati nel codice; sovrascrivibili tramite variabile d'ambiente con doppio underscore.

Chiave Default Significato
Onboarding__MaxPublicProvisionsPerIpPer24h 3 Max. provisioning per IP / 24 h (submit + Trial)
Onboarding__MaxPublicEmailSendsPerIpPerHour 5 Max. e-mail Magic Link per IP / ora
Onboarding__RequireEmailVerifyBeforeProvision true (Portale) Imporre la conferma e-mail prima del provisioning
Onboarding__RequireOnlinePaymentForNonTrial false (Portale) Per i non-Trial imporre un pagamento online reale

Pagamento

Il pagamento passa tramite Stripe su un conto DiKAS centrale (non per singolo mandante).

Chiave Significato
Signup__Stripe__SecretKey Stripe Secret Key (attiva il connettore di pagamento reale)
Signup__Stripe__PublishableKey Publishable Key per il frontend
Signup__Stripe__WebhookSecret Segreto di firma per il webhook

Senza SecretKey impostata è attivo un connettore nullo (Dev/Test). I valori di OnboardingPaymentMethod: SepaLastschrift = 1, StripeSetupIntent = 2 (Trial-first, salvare il metodo di pagamento), StripePaymentIntent = 3 (Pay-first, pagamento immediato).

Ciclo di vita e pulizia

Due servizi in background mantengono il funnel pulito:

Ordini abbandonati

OnboardingCleanupService (giornaliero) rimuove gli ordini abbandonati/non pagati che sono inattivi da più di 14 giorni (CleanupAbandonedOnboardingsCommand, configurabile) – incluse le bozze pubbliche anonime orfane (senza cliente collegato) – e libera nuovamente la loro riserva del nome online. Gli ordini con provisioning effettuato/pagati restano intatti.

Trial scaduti (Dry-Run, dark)

TrialDeprovisioningService è un servizio costruito volutamente in modo prudente:

  • Trova i Trial scaduti il cui periodo di tolleranza (GraceDays, default 30) dopo la fine del Trial è trascorso (IsTrial = true ed EndDate oltre il periodo; le licenze convertite/pagate con IsTrial = false non vengono mai considerate).
  • In DRY-RUN si limita a registrare quali database del tenant ({DatabasePrefix}_maindb, {DatabasePrefix}_gastrocurrent) un successivo run live eliminerebbenon elimina nulla.
  • È completamente disattivato per default e gira solo con TrialDeprovision__Enabled=true.
Chiave Default Significato
TrialDeprovision__Enabled false Interruttore principale; false = il servizio non gira affatto
TrialDeprovision__GraceDays 30 Periodo di tolleranza in giorni dopo la fine del Trial

L'eliminazione reale del DB non è implementata

L'effettiva eliminazione dei database dei mandanti è volutamente non cablata. Richiede un'autorizzazione esplicita nonché una mappatura verificata dei nomi dei database e dovrebbe essere coordinata con l'applicazione della scadenza (fine Trial → blocco → esportazione).

Audit

Ogni provisioning viene protocollato tramite IAuditLogger ed è visibile nella vista di audit dell'operatore (GET /api/v1/audit/logs/{date}, solo ruolo Admin):

Evento Trigger
TRIAL_PROVISIONED Avvio riuscito di un Trial (con nome online, ID licenza, durata)
TRIAL_CONVERTED_PAID Conversione di un Trial in una licenza a pagamento

Timestamp e IP client provengono dalla request; nei Trial anonimi come utente compare -. Le credenziali di accesso non vengono scritte nell'audit.

Prima dell'attivazione

Prima che SelfServiceSignupEnabled venga mai impostato su true:

  • ForwardedHeaders:KnownNetworks nel deploy di produzione impostato sul CIDR reale del cluster (altrimenti la quota per IP è inefficace).
  • Chiavi Stripe (Signup__Stripe__*) impostate – altrimenti un pagamento „subito live" con un provider reale sarebbe gratuito.
  • Invio del Magic Link e /signup/verify cablati in modo continuo.
  • Flag attivato in OperationalConfig.