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 OracleGLOBAL_SPOOLER(INFOCAD_TEST38) e ne governa la macchina a stati. Il client è il servizio WCFApplicationService.svc(shell CASSANDRA/IEM); nessun ORM (stored procedureRPS_*invocate via DALExecute*StoredProcedureconOracle.DataAccess.Client).Sistema: Infocad (Descor) — backend Oracle
INFOCAD_TEST38(identità/tenant risolti cross-schema suASPNET_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_QUERYsono citati come<PROC> src:NNsecondo la numerazioneUSER_SOURCE, già verificata in sola lettura nel flusso pilota FLOW-EXP-001 (catena WCF → Remoting → servizio → DAL → SP confermata suUSER_SOURCE,USER_DEPENDENCIES,USER_TAB_COLUMNS,USER_OBJECTS). L'esistenza di tabella/sequence/trigger è confermata sul catalogo (docs/_generated/database-catalog.json:INFOCAD_TEST38→object_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 SPRPS_*non ri-verificano grant/ruolo né appartenenza dell'ID_SPOOLERal 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: CleanExport → RPS_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_LASTQUERY ⇒ NO_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.svcesegue per prima cosarequest.UserName = ValidateToken(token: request.UserName).UserName.ValidateTokendecripta il token, invocaMemberShipProviderController().CheckUser(token)e, se l'utente non esiste, sollevaAuthenticationException("Username is wrong or not exist!"). LoUserNameusato 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(chiamateValidateTokeninExportData/ExportDocument/ExportImagesData/ExportDocumentsData/ExportDocumentsDataZip); implementazioneInfocadWeb/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
(
HasUserGranto simili): l'unico presidio è l'esistenza dell'utente inValidateToken. Inoltre i servizi raggiunti via .NET Remoting (ExportService,DataViewService) e le stored procedureRPS_*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/Grantnei metodi di export —ApplicationService.svc.cs:147-208(grep negativo); registrazione RemotingInfocadServer/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 colonnaSTATUS(NUMBER) è la macchina a stati:0= in coda (impostato all'INSERT dalMERGE),1= in esecuzione (impostato dal reader all'avvio),2= completato (a fine job, conFILENAME). Nel codice ispezionato compaiono solo i valori1e2inSetSpooler_Status(7 occorrenze ciascuno tra i reader) e0come chiave/valore d'INSERT nelMERGE. - Tipo: state-transition · Enforcement: mixed (BL reader + DB) · Confidence: VERIFIED
- Evidenza (codice): avvio
→1InfocadServer/ExportService/Deployment/DataView/DataViewExportReader.cs:51,DataViewExportTable.cs:49,ImagesExportReader.cs:53; completamento→2DataViewDataReaderJob.cs:206,ImagesDataReaderJob.cs:225,DocumentsPDFJob.cs:190,DataViewDataTableJob.cs:196. - Evidenza (DB): INSERT
STATUS=0RPS_SETSPOOLER_LASTQUERY src:29-32; UPDATESTATUSRPS_SETSPOOLER_STATUS src:7-9. - Flag: magic numbers (
0/1/2non nominati da costanti). Nessuno stato di errore normato: un job fallito non transita a uno stato dedicato (resta1se non arriva mai a2).
BR-EXP-004 — Una sola richiesta pendente per utente (MERGE idempotente con sovrascrittura)
- Regola: la registrazione job usa un
MERGE INTO GLOBAL_SPOOLERcon 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 INSERTsrc:29-32, WHEN MATCHED UPDATEsrc:33-34). - Flag: probabile perdita richiesta / race: due export avviati a distanza ravvicinata dallo
stesso utente collassano su un'unica riga; il secondo
SetSpooler_LastQuerysovrascriveEXPORTDATAprima che il primo job legga la riga conRPS_GETSPOOLER_INFO.
BR-EXP-005 — Scadenza job a 24 ore
- Regola: all'INSERT il job riceve
STARTDATE = SYSDATEedEXPIREDATE = 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 (
+1giorno hardcoded, nessun parametro di configurazione).
BR-EXP-006 — Cleanup dei job scaduti (file + riga)
- Regola:
CleanExport(username)legge i job scaduti dell'utente viaRPS_GETEXPIREDSPOOLERS, per ciascuno elimina il file su disco (UserPath\FILENAME) e poi la riga viaRPS_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 diRPS_SETSPOOLER_LASTQUERY; è assegnato da un trigger suGLOBAL_SPOOLERche attinge alla sequenceSEQ_GLOBAL_SPOOLER. - Tipo: calculation · Enforcement: DB · Confidence: SUPPORTED
- Evidenza (DB/catalogo):
INFOCAD_TEST38.object_names_by_type→TABLE: GLOBAL_SPOOLER,TRIGGER: GLOBAL_SPOOLER,SEQUENCE: SEQ_GLOBAL_SPOOLER,INDEX: PK_GLOBAL_SPOOLER(docs/_generated/database-catalog.json); assenza di assegnazioneID_SPOOLERinRPS_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(eRPS_GETSPOOLER_INFO) risolve l'USERID(RAW) dell'utente conSELECT … INTOsuASPNET_TEST38.ORA_ASPNET_USERS/ORA_ASPNET_APPLICATIONS, filtrando perLOWEREDUSERNAMEeLOWER(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; dipendenzeUSER_DEPENDENCIES→ASPNET_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 USERIDdiRPS_SETSPOOLER_LASTQUERYsollevaNO_DATA_FOUNDnon gestito ⇒ nessuna riga scritta ed eccezione propagata. Lato servizioSetSpooler_LastQuerycattura, logga e ri-lancia (throw;), quindi la funzione non ritornafalse: l'eccezione risale al metodo WCF (SOAP fault), non produce ilreturn -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 handlerNO_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_INFOinvece gestisceNO_DATA_FOUNDrestituendo un cursore con-100(src:34-36), asimmetria di gestione.
BR-EXP-010 — Aggiornamento stato con preservazione condizionale del filename
- Regola:
RPS_SETSPOOLER_STATUSesegueUPDATE GLOBAL_SPOOLER SET STATUS=:PSTATUS, FILENAME = CASE WHEN :PFILENAME IS NOT NULL THEN :PFILENAME ELSE FILENAME END WHERE ID_SPOOLER=:PIDSPOOLER: passandoPFILENAMEvuoto/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→1conString.Emptye→2con 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) calcolaround(count/total*100, 2)e lo scrive; a fine ciclo (se non abortito) imposta100. - Tipo: calculation · Enforcement: BL · Confidence: VERIFIED
- Evidenza (codice):
DataViewDataReaderJob.cs:158,166-170,192(soglia 200); soglie 100 inMaintenanceDataReaderJob.cs:121eDocumentsExportDataReaderJob.cs:165; SPRPS_SETSPOOLER_PROGRESSviaExportService.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 daDeleteSpooler_ByID/cleanup) il job impostaaborted = true, loggaEXPORT_STOPPEDe interrompe l'elaborazione senza portare lo stato a2. - 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 comeExportName + "_" + DateTime.Nowcon separatori (\ / : spazio) rimossi + estensione.xlsx. SeFileNameè già valorizzato,InitSpreadSheetritornafalsee 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), prendeFILENAME, e se non vuoto restituisceKeyValuePair<filename, bytes>leggendo il file daUserPathdell'utente passato; seFILENAMEè vuoto o il file non esiste ritorna una coppia vuota (nullbytes). - 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
UserPathcostruito dausernamepassato, 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 soloID_SPOOLERsenza verificare che appartenga al chiamante.DeleteSpooler_ByIDricava loUSERNAMEproprietario 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); interfacciaIExportService.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; nessunUSERIDnelWHEREdiRPS_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_QUERYsvuota e ripopola la tempDOCS_IDDOCUMENT_TEMP_EXPORTper l'utente (DELETE byUSER_NAME+ INSERT id documenti), costruisce la SELECT di export suDOCS_DOCUMENT_EXPORT, quindi chiamaRPS_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(callRPS_SETSPOOLER_LASTQUERY). - Evidenza (codice):
InfocadServer/DocumentDAL/OracleODP/Document_DAL.vb:3358-3368; ingresso WCFApplicationService.svc.cs:156-166(ExportDocument).
BR-EXP-018 — Conteggio righe (EXPORTTOTAL) via SQL dinamico condizionale
- Regola: in
RPS_SETSPOOLER_LASTQUERY, sePKEYS(MYINTTABLE) è valorizzato, il totale righe è calcolato conEXECUTE IMMEDIATE 'SELECT COUNT(1) FROM (…)'e memorizzato inEXPORTTOTAL; è 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(EXPORTTOTALnell'INSERT). - Flag: SQL dinamico su query costruita a monte (
EXPORTDATA/PSQLCLOB) ⇒ superficie di injection dipendente dalla provenienza del SQL (open question del flusso: chi valorizzaPSQL).
BR-EXP-019 — Gestione errori: -1 in registrazione, prosecuzione silente per item
- Regola: i metodi WCF ritornano
-1quandoctrl.SetSpooler_LastQuery(...)èfalse(registrazione fallita). Durante l'elaborazione, un'eccezione sul singolo item è catturata, loggata comeEXPORT_FAILEDe il ciclo prosegue: il job può quindi completare aSTATUS=2pur 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 itemDataViewDataReaderJob.cs:161-185(catch che logga e continua), completamento:206. - Flag: export parziale mascherato: il conteggio elaborato può essere
< EXPORTTOTALsenza 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.GetObjectsu…/ExportService.rem), registratoSingleCallinStart.vb. All'interno del servizio Windows i job aggiornano stato/progress istanziando direttamentenew ExportService()in-process (non via Remoting), sfruttando cheExportService : MarshalByRefObject. - Tipo: architecture · Enforcement: BL · Confidence: VERIFIED
- Evidenza (codice): proxy
InfocadServer/ExportServiceControllers/ExportServiceController.cs:17; registrazioneInfocadServer/Business/Start.vb:999; in-processDataViewDataReaderJob.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_SPOOLERespone la colonnaISPUBLIC(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
ISPUBLICinUSER_TAB_COLUMNSdiGLOBAL_SPOOLER; assenza di riferimenti nel corpoRPS_SETSPOOLER_LASTQUERY src:25-34eRPS_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:
STATUS0/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).