# EnvelopeGenerator - Agent Guide ## Must Read First - **`COPILOT_CONTEXT.md`** - Architecture, coordinate systems, migration status - **`FORM_APPLICATION_CONTEXT.md`** - Legacy VB.NET features to migrate ## Active Architecture (Post-Migration) **Frontend:** Blazor Auto (Server+WASM hybrid) - **WebUI** (Server): `@rendermode InteractiveServer` - PDF viewers requiring DevExpress backend - **WebUI.Client** (WASM): `@rendermode InteractiveWebAssembly` - Login, dashboards, business logic **Backend:** EnvelopeGenerator.API (ASP.NET Core 8.0) **Proxy:** YARP in WebUI routes `/api/*` → `localhost:8088` (API) ### Deprecated Projects - DO NOT USE - `EnvelopeGenerator.ReceiverUI` - Pure WASM (migrated to WebUI) - `EnvelopeGenerator.Web` - Razor Pages (replaced by WebUI) - **VB.NET projects** (`Form`, `Service`, `BBTests`) - Legacy, read-only for reference ## Development Commands ### Run Both Projects (Required) ```powershell # Terminal 1 - API Backend cd EnvelopeGenerator.API dotnet run # Terminal 2 - Blazor Frontend cd EnvelopeGenerator.WebUI\EnvelopeGenerator.WebUI dotnet run ``` **Critical:** Both must run simultaneously. WebUI proxy forwards `/api/*` to API. ### Build ```powershell dotnet build EnvelopeGenerator.sln ``` ## Project Boundaries ``` EnvelopeGenerator.Domain/ # Entities (Envelope, Receiver, Document, etc.) EnvelopeGenerator.Application/ # MediatR CQRS (Commands, Queries, Handlers) EnvelopeGenerator.Infrastructure/ # EF Core, SQL executors, repositories EnvelopeGenerator.API/ # Controllers, endpoints EnvelopeGenerator.WebUI/ # Server-side Blazor components ├─ Components/Pages/ # @rendermode InteractiveServer EnvelopeGenerator.WebUI.Client/ # Client-side WASM components ├─ Pages/ # @rendermode InteractiveWebAssembly ├─ Services/ # HTTP API clients ├─ Models/ # DTOs ``` ## Route Structure (Critical) | Route | File Location | Render Mode | Purpose | |-------|--------------|-------------|---------| | `/` | `WebUI.Client/Pages/Index.razor` | WASM | Landing page | | `/sender/login` | `WebUI.Client/Pages/LoginSenderPage.razor` | WASM | Sender auth | | `/sender` | `WebUI.Client/Pages/EnvelopeSenderPage.razor` | WASM | Sender dashboard | | `/envelope/login/{key}` | `WebUI.Client/Pages/LoginReceiverPage.razor` | WASM | Receiver auth | | `/envelope/{key}` | `WebUI/Components/Pages/EnvelopeReceiverPage.razor` | **Server** | PDF viewer + signing | **Rule:** PDF viewers MUST use `@rendermode InteractiveServer` (DevExpress backend requirement). Everything else uses WASM. ## Coordinate System (CRITICAL) **Database stores INCHES** (GdPicture14 native). Origin: top-left, Y-axis down. ### Conversions ```csharp // Database (INCHES) → PDF Points float points = inches * 72; // Database (INCHES) → DevExpress DX float dx = inches * 100; // PDF.js Pixels → Database (INCHES) float inches = (pixelX / canvasWidth) * pageWidthInches; ``` **A4 Page:** 8.27" wide × 11.69" tall = 595pt × 842pt **Signature Field Size:** 1.77" × 1.96" (FIXED, do not change) **Evidence:** See `COPILOT_CONTEXT.md` lines 158-185, `EnvelopeGenerator.Form/frmFieldEditor.vb` ## API Architecture Quirks ### Monolithic Endpoint (Avoid for UI) `POST /api/EnvelopeReceiver` - Creates envelope+document+receivers+fields atomically. - **Use case:** External API consumers - **Not suitable for:** Step-by-step UI workflow (no draft support, no partial updates) ### Missing Granular Endpoints (Need to Create) ``` POST /api/Envelope/draft # Create draft envelope PUT /api/Envelope/{id} # Update metadata DELETE /api/Envelope/{id} # Delete with reason POST /api/Envelope/{id}/document # Upload PDF POST /api/Envelope/{id}/receivers # Add receiver POST /api/Envelope/{id}/signature-fields # Place signature field POST /api/Envelope/{id}/send # Send to receivers ``` See `FORM_APPLICATION_CONTEXT.md` for detailed workflow requirements. ## Status Color Coding Form app uses DevExpress `CustomDrawCell`. WebUI needs CSS: ```css .envelope-row.status-partly-signed { background-color: #81C784; } /* GREEN_300 */ .envelope-row.status-queued, .envelope-row.status-sent { background-color: #FFB74D; } /* ORANGE_300 */ .envelope-row.status-completed { background-color: #81C784; } .envelope-row.status-deleted, .envelope-row.status-rejected { background-color: #E57373; } /* RED_300 */ ``` ## Configuration ### YARP Proxy (`WebUI/yarp.json`) Routes `/api/*`, `/swagger/*`, `/openapi/*`, `/scalar/*` → `https://localhost:8088` ### PDF.js Settings (`WebUI/wwwroot/appsettings.json`) ```json { "PdfViewerOptions": { "ThumbnailBaseScale": 0.75, "ThumbnailEnableHiDPI": true, "MainCanvasEnableHiDPI": true, "ZoomStepPercentage": 5 } } ``` ### API Config (`API/appsettings.json`) - `ConnectionStrings:Default` - SQL Server DB - `AllowedOrigins` - CORS (includes `http://localhost:5131`, `http://localhost:7192`) - `Cache:SignatureCacheExpiration` - Signature persistence timeout - `PSPDFKitLicenseKey` - **DEPRECATED** (use PDF.js instead) ## Migration Status ### Complete ✅ - Receiver login/authentication - PDF viewing with PDF.js (HiDPI, zoom, thumbnails) - Signature capture (draw/type/image) - Signature caching (Redis/SQL) - Sender login ### Missing (High Priority) ❌ - Sender dashboard (`/sender`) - Empty stub - Envelope editor (`/sender/envelope/{id}`) - Signature field placement tool (PDF.js + draggable overlays) - Granular API endpoints (draft, receivers, fields) - Master-detail grids for receivers/history ## Common Mistakes (DO NOT REPEAT) | Mistake | Why Wrong | |---------|-----------| | Using iText7 in receiver pages | GPL license issue. Use PDF.js overlays. | | Using PSPDFKit | Removed from architecture. Use PDF.js + DevExpress. | | `@rendermode InteractiveWebAssembly` on PDF viewers | DevExpress DxPdfViewer requires server-side rendering. | | Hardcoded quality in PDF.js | Use `appsettings.json` `PdfViewerOptions`. | | Coordinates in points/pixels for DB | Database uses INCHES. Convert before save. | | `BottomMarginBand` for signatures | Repeats on every page. Use `DetailBand`. | ## Testing **No automated tests exist yet.** Manual testing workflow: 1. Start API (`dotnet run` in `EnvelopeGenerator.API`) 2. Start WebUI (`dotnet run` in `EnvelopeGenerator.WebUI\EnvelopeGenerator.WebUI`) 3. Navigate to `https://localhost:5131` (or check console output for port) 4. Test sender login at `/sender/login` 5. Test receiver flow at `/envelope/login/{envelopeKey}` ## Database **SQL Server** (DD_ECM) - Connection string in `API/appsettings.json` - EF Core migrations NOT used (manual SQL scripts) - Stored procedures: `PRSIG_*` prefix **Key Tables:** - `TBSIG_ENVELOPE` - Envelope metadata - `TBSIG_ENVELOPE_RECEIVER` - Receiver assignments - `TBSIG_DOC_RECEIVER_ELEMENT` - Signature fields (X, Y in INCHES) - `TBSIG_RECEIVER` - Receiver registry - `TBSIG_DOCUMENT` - PDF binary data - `TBSIG_ENVELOPE_HISTORY` - Audit trail ## DevExpress **License:** Commercial (v25.2.3) **Components Used:** - `DxGrid` - Master-detail grids - `DxPdfViewer` - Server-side PDF rendering - `DxPopup` - Modal dialogs - `DxToolbar` - Action bars - `DxFormLayout` - Forms **Theme:** Blazing Berry (default) ## JavaScript Interop **PDF Viewer:** `wwwroot/js/pdf-viewer.js` ```javascript window.pdfViewer = { initialize(canvasId, pdfDataUrl, dotNetRef), renderPage(num), renderSignatureButtons(signatures, pageNum, dotNetRef), applySignature(signatureId, dataUrl, fullName, position, place), zoomIn(), zoomOut(), dispose() } ``` **Signature Pad:** `wwwroot/js/receiver-signature.js` ```javascript window.receiverSignature = { initializeDrawPad(canvasId, dotNetRef), getSignatureDataUrl(canvasId), clearPad(canvasId) } ``` ## Multi-Envelope Support Receivers can login to **multiple envelopes simultaneously** via per-envelope cookies: ``` AuthTokenSignFLOWReceiver.{envelopeKey} ``` Each envelope maintains independent authentication state. ## External Dependencies **CDN:** - PDF.js 3.11.174: `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js` **NuGet (WebUI.Client):** - `DevExpress.Blazor.*` 25.2.3 - `SkiaSharp.*` 3.119.1 (WASM rendering) **External Services:** - LDAP/AD authentication (optional) - GTX Messaging (SMS 2FA) - Email dispatcher (signFlow) ## Environment Variables None required. All config in `appsettings.json`. **Local dev ports:** - API: `https://localhost:8088` - WebUI: `https://localhost:5131` or `http://localhost:7192`