Table of Contents

BR-EXP — Regole di business del dominio ExportService / Spooler

Regole di business estratte dal flusso pilota FLOW-EXP-001 (registrazione/ciclo di vita di un job di export asincrono) e dai sorgenti correlati. ExportService è il servizio Windows (host .NET Remoting, endpoint ExportService.rem / DataViewExportService.rem) che materializza ogni richiesta di esportazione come riga di spooler nella tabella Oracle GLOBAL_SPOOLER (INFOCAD_TEST38) e ne governa la macchina a stati. Il client è il servizio WCF ApplicationService.svc (shell CASSANDRA/IEM); nessun ORM (stored procedure RPS_* invocate via DAL Execute*StoredProcedure con Oracle.DataAccess.Client).

Sistema: Infocad (Descor) — backend Oracle INFOCAD_TEST38 (identità/tenant risolti cross-schema su ASPNET_TEST38), ASP.NET Web Forms + WCF (C#), business layer server risolto via .NET Remoting (ExportService : MarshalByRefObject), job di export (DataView, Images, Maintenance, Documents PDF/ZIP) eseguiti nel servizio Windows.

Le regole sono classificate per tipo, enforcement point (UI / BL / DB / mixed) e confidence (VERIFIED / SUPPORTED / INFERRED). Gli identificatori tecnici NON sono tradotti.

Note di metodo e provenienza dell'evidenza

  • Evidenza di codice: percorsi relativi alla radice del repository (es. InfocadServer/ExportService/ExportService.cs:312). Letti direttamente sui sorgenti.
  • Evidenza DB: i corpi delle procedure RPS_*/DOC_INSERTSPOOLER_QUERY sono citati come <PROC> src:NN secondo la numerazione USER_SOURCE, già verificata in sola lettura nel flusso pilota FLOW-EXP-001 (catena WCF → Remoting → servizio → DAL → SP confermata su USER_SOURCE, USER_DEPENDENCIES, USER_TAB_COLUMNS, USER_OBJECTS). L'esistenza di tabella/sequence/trigger è confermata sul catalogo (docs/_generated/database-catalog.json: INFOCAD_TEST38object_names_by_type). Nessuna lettura di dati applicativi, nessuna DML/DDL.
  • Pattern di sicurezza TD-008: il gate d'accesso vive nel client WCF (ValidateToken); i servizi esposti via .NET Remoting (ExportService, DataViewService) e le SP RPS_* non ri-verificano grant/ruolo né appartenenza dell'ID_SPOOLER al chiamante — vedi BR-EXP-002/016.

Registro delle regole (register)

id regola tipo enforcement conf
BR-EXP-001 Ogni metodo di export WCF impone ValidateToken (decrypt token → CheckUser; utente inesistente ⇒ AuthenticationException) permission mixed VERIFIED
BR-EXP-002 Nessun grant/ruolo specifico sul path di export: solo esistenza utente; Remoting/SP non ri-verificano (TD-008) permission UI-only SUPPORTED
BR-EXP-003 Modello a spooler asincrono: ogni export è una riga GLOBAL_SPOOLER con macchina a stati STATUS 0→1→2 state-transition mixed VERIFIED
BR-EXP-004 Una sola richiesta pendente per utente: MERGE su chiave (USERID, STATUS=0); una nuova richiesta sovrascrive la riga in coda business-rule DB VERIFIED
BR-EXP-005 Scadenza job a 24h: EXPIREDATE = SYSDATE + 1 all'INSERT calculation (date) DB VERIFIED
BR-EXP-006 Cleanup job scaduti: CleanExportRPS_GETEXPIREDSPOOLERS + elimina file poi RPS_DELETESPOOLER_BYID state-transition mixed VERIFIED
BR-EXP-007 ID_SPOOLER assegnato da SEQ_GLOBAL_SPOOLER via TRIGGER (non nel corpo RPS_SETSPOOLER_LASTQUERY) calculation DB SUPPORTED
BR-EXP-008 Risoluzione identità/tenant: USERID (RAW) da ASPNET_TEST38 filtrando LOWER(USER) (schema applicativo) + LOWEREDUSERNAME permission (multi-tenant) DB VERIFIED
BR-EXP-009 Utente inesistente in RPS_SETSPOOLER_LASTQUERYNO_DATA_FOUND non gestito ⇒ eccezione propagata (rethrow), NON return false/-1 validation mixed VERIFIED
BR-EXP-010 Aggiornamento stato: RPS_SETSPOOLER_STATUS SET STATUS=:PSTATUS, FILENAME=COALESCE(:PFILENAME,FILENAME) per ID_SPOOLER state-transition DB VERIFIED
BR-EXP-011 Progress: SetSpooler_Progress(0) a inizio, aggiornato ogni 200 righe (DataView) / 100 (Maint/Doc), 100 a fine calculation BL VERIFIED
BR-EXP-012 Cancellazione cooperativa: ogni 500 righe verifica esistenza riga spooler; se assente ⇒ abort export state-transition (hidden) BL VERIFIED
BR-EXP-013 Nome file: ExportName + "_" + timestamp sanitizzato + ".xlsx"; se FileName già valorizzato InitSpreadSheet ritorna false (non ri-genera) calculation BL VERIFIED
BR-EXP-014 Export immagini/PDF: al completamento il FILENAME è forzato a estensione .zip calculation BL VERIFIED
BR-EXP-015 Download: ExportFileBytes(username,id) legge FILENAME per id e serve i bytes da UserPath dell'utente; vuoto se FILENAME nullo o file assente business-rule BL VERIFIED
BR-EXP-016 DeleteSpooler_ByID/GetSpooler_Status/GetSpooler_Progress/GetSpooler_DataByID operano per ID_SPOOLER senza verifica di appartenenza al chiamante (IDOR) security mixed SUPPORTED
BR-EXP-017 Path documenti: DOC_INSERTSPOOLER_QUERY svuota+ripopola DOCS_IDDOCUMENT_TEMP_EXPORT per utente e chiama RPS_SETSPOOLER_LASTQUERY con EXPORTNAME='DOCUMENT' state-transition DB VERIFIED
BR-EXP-018 Conteggio righe (EXPORTTOTAL): calcolato in RPS_SETSPOOLER_LASTQUERY via EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM (…)' solo se PKEYS valorizzato calculation DB VERIFIED
BR-EXP-019 Errore export WCF ⇒ return -1 (quando SetSpooler_LastQuery è false); i reader loggano EXPORT_FAILED per item ma proseguono (export parziale con STATUS=2) state-transition mixed VERIFIED
BR-EXP-020 Trasporto .NET Remoting SingleCall client→servizio; job aggiornano lo stato con ExportService in-process (_ctrl = new ExportService()) architecture BL VERIFIED
BR-EXP-021 Colonna ISPUBLIC presente in GLOBAL_SPOOLER ma non impostata da alcuna SP del dominio ispezionata hidden-flag DB INFERRED

Dettaglio delle regole

BR-EXP-001 — Autenticazione a token obbligatoria all'ingresso WCF

  • Regola: ogni metodo di export di ApplicationService.svc esegue per prima cosa request.UserName = ValidateToken(token: request.UserName).UserName. ValidateToken decripta il token, invoca MemberShipProviderController().CheckUser(token) e, se l'utente non esiste, solleva AuthenticationException("Username is wrong or not exist!"). Lo UserName usato a valle è quello risolto/validato, non quello grezzo di richiesta.
  • Tipo: permission · Enforcement: mixed (WCF + provider) · Confidence: VERIFIED
  • Evidenza (codice): InfocadWeb/WebMachine/CASSANDRA/WebServices/ApplicationService.svc.cs:149,157,170,184,198 (chiamate ValidateToken in ExportData/ExportDocument/ExportImagesData/ExportDocumentsData/ExportDocumentsDataZip); implementazione InfocadWeb/WebMachine/CASSANDRA/Authentication/CassandraWCF.cs:40-92 (decrypt token :44, CheckUser :72, throw :91).

BR-EXP-002 — Nessun grant di funzione sul path di export (solo esistenza utente)

  • Regola: sul percorso di export non è invocato alcun controllo di grant/ruolo specifico (HasUserGrant o simili): l'unico presidio è l'esistenza dell'utente in ValidateToken. Inoltre i servizi raggiunti via .NET Remoting (ExportService, DataViewService) e le stored procedure RPS_* non ri-verificano l'autorizzazione (pattern TD-008): chi raggiunge l'endpoint Remoting o la SP con uno username valido opera senza ulteriori controlli.
  • Tipo: permission · Enforcement: UI-only (gate solo nel client WCF) · Confidence: SUPPORTED
  • Evidenza (codice): nessuna occorrenza di HasUserGrant/Grant nei metodi di export — ApplicationService.svc.cs:147-208 (grep negativo); registrazione Remoting InfocadServer/Business/Start.vb:999.
  • Flag: UI-only / TD-008. Un chiamante che parli direttamente il canale Remoting (…/ExportService.rem) o la SP bypassa il gate token. Presidio di ruolo fine assente sul dominio export.

BR-EXP-003 — Modello a spooler asincrono con macchina a stati STATUS 0→1→2

  • Regola: ogni export è persistito come riga di GLOBAL_SPOOLER. La colonna STATUS (NUMBER) è la macchina a stati: 0 = in coda (impostato all'INSERT dal MERGE), 1 = in esecuzione (impostato dal reader all'avvio), 2 = completato (a fine job, con FILENAME). Nel codice ispezionato compaiono solo i valori 1 e 2 in SetSpooler_Status (7 occorrenze ciascuno tra i reader) e 0 come chiave/valore d'INSERT nel MERGE.
  • Tipo: state-transition · Enforcement: mixed (BL reader + DB) · Confidence: VERIFIED
  • Evidenza (codice): avvio →1 InfocadServer/ExportService/Deployment/DataView/DataViewExportReader.cs:51, DataViewExportTable.cs:49, ImagesExportReader.cs:53; completamento →2 DataViewDataReaderJob.cs:206, ImagesDataReaderJob.cs:225, DocumentsPDFJob.cs:190, DataViewDataTableJob.cs:196.
  • Evidenza (DB): INSERT STATUS=0 RPS_SETSPOOLER_LASTQUERY src:29-32; UPDATE STATUS RPS_SETSPOOLER_STATUS src:7-9.
  • Flag: magic numbers (0/1/2 non nominati da costanti). Nessuno stato di errore normato: un job fallito non transita a uno stato dedicato (resta 1 se non arriva mai a 2).

BR-EXP-004 — Una sola richiesta pendente per utente (MERGE idempotente con sovrascrittura)

  • Regola: la registrazione job usa un MERGE INTO GLOBAL_SPOOLER con chiave (USERID = V_UIDRAW AND STATUS = 0): se non esiste riga in coda ⇒ INSERT nuova (STATUS=0); se esiste ⇒ UPDATE dei campi export (EXPORTNAME/EXPORTDATA/EXPORTKEYS/EXPORTTOTAL). Garantisce una sola riga in coda per utente, ma una nuova richiesta mentre una è pendente sovrascrive la precedente invece di accodarla.
  • Tipo: business-rule · Enforcement: DB · Confidence: VERIFIED
  • Evidenza (DB): RPS_SETSPOOLER_LASTQUERY src:25-34 (ON (USERID=V_UIDRAW AND STATUS=0), WHEN NOT MATCHED INSERT src:29-32, WHEN MATCHED UPDATE src:33-34).
  • Flag: probabile perdita richiesta / race: due export avviati a distanza ravvicinata dallo stesso utente collassano su un'unica riga; il secondo SetSpooler_LastQuery sovrascrive EXPORTDATA prima che il primo job legga la riga con RPS_GETSPOOLER_INFO.

BR-EXP-005 — Scadenza job a 24 ore

  • Regola: all'INSERT il job riceve STARTDATE = SYSDATE ed EXPIREDATE = SYSDATE + 1 (24 ore): scaduto, diventa candidato al cleanup.
  • Tipo: calculation (date logic) · Enforcement: DB · Confidence: VERIFIED
  • Evidenza (DB): RPS_SETSPOOLER_LASTQUERY src:32 (STARTDATE=SYSDATE, EXPIREDATE=SYSDATE+1).
  • Flag: date logic / magic number (+1 giorno hardcoded, nessun parametro di configurazione).

BR-EXP-006 — Cleanup dei job scaduti (file + riga)

  • Regola: CleanExport(username) legge i job scaduti dell'utente via RPS_GETEXPIREDSPOOLERS, per ciascuno elimina il file su disco (UserPath\FILENAME) e poi la riga via RPS_DELETESPOOLER_BYID.
  • Tipo: state-transition · Enforcement: mixed (BL file + DB) · Confidence: VERIFIED
  • Evidenza (codice): InfocadServer/ExportService/ExportService.cs:32-67 (query :41, delete file :57-58, RPS_DELETESPOOLER_BYID :61).
  • Flag: probabile defect (off-by-one): il loop è for (int ix = 0; ix < dt.Rows.Count - 1; ix++) (ExportService.cs:50) ⇒ l'ultima riga scaduta non viene mai ripulita (file e record residui).

BR-EXP-007 — ID_SPOOLER da sequence via trigger

  • Regola: ID_SPOOLER (NUMBER, PK) non è valorizzato nel corpo di RPS_SETSPOOLER_LASTQUERY; è assegnato da un trigger su GLOBAL_SPOOLER che attinge alla sequence SEQ_GLOBAL_SPOOLER.
  • Tipo: calculation · Enforcement: DB · Confidence: SUPPORTED
  • Evidenza (DB/catalogo): INFOCAD_TEST38.object_names_by_typeTABLE: GLOBAL_SPOOLER, TRIGGER: GLOBAL_SPOOLER, SEQUENCE: SEQ_GLOBAL_SPOOLER, INDEX: PK_GLOBAL_SPOOLER (docs/_generated/database-catalog.json); assenza di assegnazione ID_SPOOLER in RPS_SETSPOOLER_LASTQUERY src:29-32.
  • Flag: corpo del trigger non ispezionato (open question del flusso) ⇒ SUPPORTED, non VERIFIED.

BR-EXP-008 — Risoluzione identità e isolamento per tenant/applicazione

  • Regola: RPS_SETSPOOLER_LASTQUERY (e RPS_GETSPOOLER_INFO) risolve l'USERID (RAW) dell'utente con SELECT … INTO su ASPNET_TEST38.ORA_ASPNET_USERS/ORA_ASPNET_APPLICATIONS, filtrando per LOWEREDUSERNAME e LOWER(USER) (schema Oracle applicativo corrente) ⇒ isolamento per applicazione/tenant.
  • Tipo: permission (multi-tenant) · Enforcement: DB · Confidence: VERIFIED
  • Evidenza (DB): RPS_SETSPOOLER_LASTQUERY src:17-23; RPS_GETSPOOLER_INFO src:8-14; dipendenze USER_DEPENDENCIESASPNET_TEST38.ORA_ASPNET_USERS/ORA_ASPNET_APPLICATIONS.

BR-EXP-009 — Utente inesistente: NO_DATA_FOUND non gestito, eccezione propagata

  • Regola: se l'utente non è risolto, il SELECT … INTO USERID di RPS_SETSPOOLER_LASTQUERY solleva NO_DATA_FOUND non gestito ⇒ nessuna riga scritta ed eccezione propagata. Lato servizio SetSpooler_LastQuery cattura, logga e ri-lancia (throw;), quindi la funzione non ritorna false: l'eccezione risale al metodo WCF (SOAP fault), non produce il return -1.
  • Tipo: validation · Enforcement: mixed (DB + BL) · Confidence: VERIFIED
  • Evidenza (codice): ExportService.cs:314-318 (catch { LogException(ex); throw; }).
  • Evidenza (DB): RPS_SETSPOOLER_LASTQUERY src:17-23 (SELECT … INTO, nessun handler NO_DATA_FOUND).
  • Flag: discrepanza con la documentazione di flusso (che ipotizzava false/return -1): il path effettivo per utente inesistente è eccezione non mascherata. RPS_GETSPOOLER_INFO invece gestisce NO_DATA_FOUND restituendo un cursore con -100 (src:34-36), asimmetria di gestione.

BR-EXP-010 — Aggiornamento stato con preservazione condizionale del filename

  • Regola: RPS_SETSPOOLER_STATUS esegue UPDATE GLOBAL_SPOOLER SET STATUS=:PSTATUS, FILENAME = CASE WHEN :PFILENAME IS NOT NULL THEN :PFILENAME ELSE FILENAME END WHERE ID_SPOOLER=:PIDSPOOLER: passando PFILENAME vuoto/NULL (transizione →1) il filename esistente è preservato; a completamento (→2) viene scritto il nome file prodotto.
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED
  • Evidenza (DB): RPS_SETSPOOLER_STATUS src:7-9.
  • Evidenza (codice): ExportService.cs:344-358; chiamate →1 con String.Empty e →2 con filename (BR-EXP-003).

BR-EXP-011 — Reporting di avanzamento (progress) a soglie fisse

  • Regola: il job imposta SetSpooler_Progress(0) prima del ciclo, poi ogni 200 righe (DataView/Images) o 100 (Maintenance/Documents) calcola round(count/total*100, 2) e lo scrive; a fine ciclo (se non abortito) imposta 100.
  • Tipo: calculation · Enforcement: BL · Confidence: VERIFIED
  • Evidenza (codice): DataViewDataReaderJob.cs:158,166-170,192 (soglia 200); soglie 100 in MaintenanceDataReaderJob.cs:121 e DocumentsExportDataReaderJob.cs:165; SP RPS_SETSPOOLER_PROGRESS via ExportService.cs:390-402.
  • Flag: magic numbers (200/100/500) non centralizzati; soglie diverse per tipo di export.

BR-EXP-012 — Cancellazione cooperativa via polling della riga di spooler

  • Regola: ogni 500 righe il job rilegge la propria riga (GetSpooler_DataByID); se la riga non esiste più (es. cancellata da DeleteSpooler_ByID/cleanup) il job imposta aborted = true, logga EXPORT_STOPPED e interrompe l'elaborazione senza portare lo stato a 2.
  • Tipo: state-transition (meccanismo nascosto) · Enforcement: BL · Confidence: VERIFIED
  • Evidenza (codice): DataViewDataReaderJob.cs:172-180 (check ogni 500), :190-193 (skip progress 100 se abortito).
  • Flag: hidden flag / abort implicito: la cancellazione del job è il canale di stop; se abortito il job resta in STATUS=1 (nessuno stato "annullato").

BR-EXP-013 — Naming del file di export e guardia InitSpreadSheet

  • Regola: se FileName è vuoto viene generato come ExportName + "_" + DateTime.Now con separatori (\ / : spazio) rimossi + estensione .xlsx. Se FileName è già valorizzato, InitSpreadSheet ritorna false e non ri-crea il documento.
  • Tipo: calculation · Enforcement: BL · Confidence: VERIFIED
  • Evidenza (codice): DataViewDataReaderJob.cs:52-61 (generazione :56, guardia :58-59).
  • Flag: timestamp derivato da DateTime.Now.ToString() (cultura locale del servizio) ⇒ nome file dipendente dalla locale del server.

BR-EXP-014 — Estensione .zip forzata per export immagini e PDF

  • Regola: per l'export immagini e per l'export PDF il file finale è un archivio: al completamento il FILENAME è impostato con estensione .zip (immagini: sostituzione .xlsx.zip; PDF: ChangeExtension(ExportName, ".zip")).
  • Tipo: calculation · Enforcement: BL · Confidence: VERIFIED
  • Evidenza (codice): ImagesDataReaderJob.cs:225 (SetSpooler_Status(id, 2, FileName.Replace(".xlsx", ".zip"))); DocumentsPDFJob.cs:64 (ChangeExtension(ExportName, ".zip")), :190 (SetSpooler_Status(id, 2, FileName)).

BR-EXP-015 — Download del file di export

  • Regola: ExportFileBytes(username, idspooler) legge la riga per id (GetSpooler_DataByID), prende FILENAME, e se non vuoto restituisce KeyValuePair<filename, bytes> leggendo il file da UserPath dell'utente passato; se FILENAME è vuoto o il file non esiste ritorna una coppia vuota (null bytes).
  • Tipo: business-rule · Enforcement: BL · Confidence: VERIFIED
  • Evidenza (codice): ExportService.cs:70-102 (lettura riga :81, guardia filename :89-90, ReadAllBytes :96).
  • Flag: il file è cercato in UserPath costruito da username passato, mentre la riga è recuperata per id senza filtro utente ⇒ la protezione è di fatto solo il path; vedi BR-EXP-016.

BR-EXP-016 — Operazioni per ID_SPOOLER senza verifica di appartenenza (IDOR)

  • Regola: DeleteSpooler_ByID(id), GetSpooler_Status(id), GetSpooler_Progress(id), GetSpooler_DataByID(id), GetSpooler_QueryByID(id) operano sul solo ID_SPOOLER senza verificare che appartenga al chiamante. DeleteSpooler_ByID ricava lo USERNAME proprietario dalla riga stessa (r["USERNAME"]) per costruire il path del file da eliminare, poi cancella la riga.
  • Tipo: security · Enforcement: mixed (BL + DB) · Confidence: SUPPORTED
  • Evidenza (codice): ExportService.cs:412-440 (delete: username dalla riga :431, delete file :435-436, RPS_DELETESPOOLER_BYID :440); interfaccia IExportService.cs:26,30,34 (firme per solo id).
  • Flag: probabile IDOR: chi conosce/indovina un ID_SPOOLER (interi progressivi da sequence, BR-EXP-007) può cancellare o interrogare job altrui; nessun USERID nel WHERE di RPS_DELETESPOOLER_BYID. Aggravato dall'assenza di grant sul path Remoting (BR-EXP-002).

BR-EXP-017 — Path documenti: temp table + registrazione job "DOCUMENT"

  • Regola: per l'export documenti (Excel) DOC_INSERTSPOOLER_QUERY svuota e ripopola la temp DOCS_IDDOCUMENT_TEMP_EXPORT per l'utente (DELETE by USER_NAME + INSERT id documenti), costruisce la SELECT di export su DOCS_DOCUMENT_EXPORT, quindi chiama RPS_SETSPOOLER_LASTQUERY(PUSERNAME, 'DOCUMENT', <SQL>, NULL, PCOUNT) registrando il job.
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED
  • Evidenza (DB): DOC_INSERTSPOOLER_QUERY src:12-13 (DELETE temp), src:20-21 (INSERT id), src:25-48 (SELECT export), src:50 (call RPS_SETSPOOLER_LASTQUERY).
  • Evidenza (codice): InfocadServer/DocumentDAL/OracleODP/Document_DAL.vb:3358-3368; ingresso WCF ApplicationService.svc.cs:156-166 (ExportDocument).

BR-EXP-018 — Conteggio righe (EXPORTTOTAL) via SQL dinamico condizionale

  • Regola: in RPS_SETSPOOLER_LASTQUERY, se PKEYS (MYINTTABLE) è valorizzato, il totale righe è calcolato con EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM (…)' e memorizzato in EXPORTTOTAL; è la base del calcolo di progress (BR-EXP-011).
  • Tipo: calculation · Enforcement: DB · Confidence: VERIFIED
  • Evidenza (DB): RPS_SETSPOOLER_LASTQUERY src:12-15 (count dinamico), src:29-32 (EXPORTTOTAL nell'INSERT).
  • Flag: SQL dinamico su query costruita a monte (EXPORTDATA/PSQL CLOB) ⇒ superficie di injection dipendente dalla provenienza del SQL (open question del flusso: chi valorizza PSQL).

BR-EXP-019 — Gestione errori: -1 in registrazione, prosecuzione silente per item

  • Regola: i metodi WCF ritornano -1 quando ctrl.SetSpooler_LastQuery(...) è false (registrazione fallita). Durante l'elaborazione, un'eccezione sul singolo item è catturata, loggata come EXPORT_FAILED e il ciclo prosegue: il job può quindi completare a STATUS=2 pur avendo saltato righe (export parziale silente).
  • Tipo: state-transition · Enforcement: mixed · Confidence: VERIFIED
  • Evidenza (codice): ApplicationService.svc.cs:175-179,189-193,203-207 (return -1); prosecuzione per item DataViewDataReaderJob.cs:161-185 (catch che logga e continua), completamento :206.
  • Flag: export parziale mascherato: il conteggio elaborato può essere < EXPORTTOTAL senza che lo stato lo segnali.

BR-EXP-020 — Trasporto Remoting SingleCall e servizio in-process nei job

  • Regola: il client (WCF) raggiunge il servizio via .NET Remoting (Activator.GetObject su …/ExportService.rem), registrato SingleCall in Start.vb. All'interno del servizio Windows i job aggiornano stato/progress istanziando direttamente new ExportService() in-process (non via Remoting), sfruttando che ExportService : MarshalByRefObject.
  • Tipo: architecture · Enforcement: BL · Confidence: VERIFIED
  • Evidenza (codice): proxy InfocadServer/ExportServiceControllers/ExportServiceController.cs:17; registrazione InfocadServer/Business/Start.vb:999; in-process DataViewDataReaderJob.cs:45 (_ctrl = new ExportService()).
  • Flag: la doppia natura (Remoting per il client, in-process per i job) implica che i job non attraversano alcun gate (coerente con BR-EXP-002/TD-008).

BR-EXP-021 — Colonna ISPUBLIC presente ma non gestita

  • Regola: GLOBAL_SPOOLER espone la colonna ISPUBLIC (NUMBER), ma nessuna delle SP del dominio ispezionate (RPS_SETSPOOLER_LASTQUERY/_STATUS/_PROGRESS, RPS_GETSPOOLER_*) la valorizza o la legge nel path di export.
  • Tipo: hidden-flag · Enforcement: DB · Confidence: INFERRED
  • Evidenza (DB): colonna ISPUBLIC in USER_TAB_COLUMNS di GLOBAL_SPOOLER; assenza di riferimenti nel corpo RPS_SETSPOOLER_LASTQUERY src:25-34 e RPS_SETSPOOLER_STATUS src:7-9.
  • Flag: flag nascosto/residuo — probabile funzionalità di condivisione export non attiva sul path corrente (candidata a verifica su altre SP/UI fuori dominio).

Sintesi flag trasversali

  • UI-only / TD-008: BR-EXP-002, BR-EXP-016, BR-EXP-020 — il gate d'accesso è nel client WCF; il canale Remoting e le SP non ri-verificano autorizzazione né ownership dell'ID_SPOOLER.
  • Probabili defect: BR-EXP-006 (loop cleanup off-by-one, ultima riga mai ripulita), BR-EXP-016 (IDOR su operazioni per id), BR-EXP-004 (sovrascrittura/race sulla riga in coda), BR-EXP-009 (asimmetria di gestione NO_DATA_FOUND + discrepanza con la doc di flusso), BR-EXP-019 (export parziale silente).
  • Magic numbers / date logic: STATUS 0/1/2 (BR-EXP-003), SYSDATE+1 = 24h (BR-EXP-005), soglie progress/abort 200/100/500 (BR-EXP-011/012).
  • Hidden flags: BR-EXP-012 (abort via cancellazione riga), BR-EXP-021 (ISPUBLIC).
  • Customer variants: nessuna regola risulta specifica di un singolo cliente — comportamento standard di prodotto (nessun ramo condizionato a tenant/cliente nel codice ispezionato oltre all'isolamento per applicazione di BR-EXP-008).