Updated SF-74-PLAN.md to document completed phases (6a–6e), including theme selection, dark mode, grid persistence, and logo placement. Highlighted pending tasks for phase 6f and clarified open questions. Revised MIGRATION_PLAN.md with deep analysis findings and detailed steps for migrating `EnvelopeGenerator.Service_legacy` to a modern C# Worker Service. Addressed connection string handling, Quartz version mismatch, and TempFiles architecture. Removed outdated markdown files from EnvelopeGenerator.sln and updated the solution structure for consistency. Fixed incorrect "Read and confirmed" label in Signature Certificate reports for "Read and Sign" envelopes. Added branching logic in `ReportItem.vb` and updated resource files. Resolved signature field formatting issues in finalized PDFs based on WISAG feedback. Added truncation logic in `PDFBurner.vb` and updated `PDFBurnerParams.vb` with per-field character limits.
13 KiB
EnvelopeGenerator - Agent Guide
Must Read First
COPILOT_CONTEXT.md- Architecture, coordinate systems, migration statusFORM_APPLICATION_CONTEXT.md- Legacy VB.NET features to migrate
Documentation Catalog
This section explains every markdown file in the repo: what it contains, why it exists, and when you need it. Read this before deciding which file to open.
Core Architecture Docs (Active — Always Relevant)
AGENTS.md ← you are here
What: Authoritative agent/copilot onboarding guide. Covers project structure, route table, render mode rules, coordinate system, API gaps, and common mistakes. Why it exists: Single source of truth for agents so they don't re-derive architecture from code on every session. When you need it: Always. Read first on every session. Maintenance: Update whenever project structure, routes, render modes, or naming conventions change.
COPILOT_CONTEXT.md
What: Deep-dive architecture reference. Covers the full Blazor Auto hybrid setup, authentication flows (JWT + cookies, per-envelope receiver tokens), service registration patterns, coordinate system proof, and an explicit "prefer Server/Server.Client over old WebUI/ReceiverUI" rule. Why it exists: Prevents agents from re-deriving or misinterpreting the hybrid SSR+WASM architecture. Also documents coordinate system evidence to prevent regressions (inches vs. points vs. pixels). When you need it:
- Implementing any new page or service
- Debugging auth/cookie issues
- Any coordinate conversion question
- Unsure which project a new file should go in Maintenance: Update when render mode assignments change, new auth schemes are added, or the coordinate system is touched.
FORM_APPLICATION_CONTEXT.md
What: Comprehensive reverse-engineering of the legacy VB.NET WinForms app (EnvelopeGenerator.Form). Documents every form (frmMain, frmEnvelopeEditor, frmFieldEditor, etc.), their UI layout, toolbar actions, data models, coordinate system, and a feature-by-feature migration mapping table to EnvelopeGenerator.Server.
Why it exists: The WinForms app is the functional specification for the sender-side web UI. It documents the full intended workflow that is being migrated to Blazor — especially the envelope creation, signature field placement, and dashboard features that are not yet implemented.
When you need it:
- Implementing any sender-side feature (
/sender,/sender/editor,/sender/envelope/{id}) - Understanding what a specific toolbar button or form should do
- Designing API endpoints for sender workflow
- Checking coordinate system behavior (INCHES proof is here)
Maintenance: Update the mapping table as features are implemented (change
❌ Not implemented→✅ Exists). Do not renameReceiverUIback — it was the old project name; current target isEnvelopeGenerator.Server.
RECEIVER_PDF_VIEWER_CONTEXT.md
What: Detailed technical reference for the receiver-side PDF viewer (EnvelopeReceiverPage.razor). Documents the PDF.js integration, signature button rendering, JS interop API (window.pdfViewer), signature capture flow, HiDPI/zoom/thumbnail config, and the full component lifecycle.
Why it exists: The receiver PDF viewer is the most complex component in the codebase. This doc prevents agents from misunderstanding the JS↔Blazor boundary, re-implementing already-solved problems (HiDPI, zoom, signature caching), or breaking the signing flow.
When you need it:
- Working on
EnvelopeReceiverPage.razororpdf-viewer.js - Adding new signature field rendering logic
- Debugging signature rendering, zoom, or thumbnail issues
- Implementing sender-side PDF.js overlay (signature field placement) — the receiver side is the reference implementation
Maintenance: Update when
pdf-viewer.jsAPI changes, new JS interop functions are added, or the signing flow is modified.
Deployment Docs
EnvelopeGenerator.Server/EnvelopeGenerator.Server/README.md
What: IIS publish and deployment guide for EnvelopeGenerator.Server. Covers why self-contained publish is required (WASM assembly version strictness), the exact dotnet publish command, IIS Application Pool settings (No Managed Code), directory structure after publish, and common deployment errors.
Why it exists: Blazor Auto (Server + WASM hybrid) has non-obvious deployment requirements that differ from a standard ASP.NET Core app. Forgetting self-contained publish or using the wrong app pool will break WASM loading in production.
When you need it:
- Deploying to IIS for the first time
- Troubleshooting 500 errors on production after deploy
- Setting up a new deployment environment Maintenance: Update if the publish target, IIS config, or runtime version changes.
Active Architecture (Post-Migration)
Frontend: Blazor Auto (Server+WASM hybrid)
- EnvelopeGenerator.Server (Server):
@rendermode InteractiveServer- PDF viewers requiring DevExpress backend - EnvelopeGenerator.Server.Client (WASM):
@rendermode InteractiveWebAssembly- Login, dashboards, business logic
Backend: EnvelopeGenerator.API (ASP.NET Core 8.0)
Proxy: YARP in EnvelopeGenerator.Server routes /api/* → localhost:8088 (API)
Deprecated Projects - DO NOT USE
EnvelopeGenerator.ReceiverUI- Pure WASM (migrated to Server)EnvelopeGenerator.Web- Razor Pages (replaced by Server)- VB.NET projects (
Form,Service,BBTests) - Legacy, read-only for reference
Development Commands
Run Both Projects (Required)
# Terminal 1 - API Backend
cd EnvelopeGenerator.API
dotnet run
# Terminal 2 - Blazor Frontend
cd EnvelopeGenerator.Server\EnvelopeGenerator.Server
dotnet run
Critical: Both must run simultaneously. EnvelopeGenerator.Server proxy forwards /api/* to API.
Build
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.Server/
EnvelopeGenerator.Server/ # Server-side Blazor components
├─ Components/Pages/ # @rendermode InteractiveServer
EnvelopeGenerator.Server.Client/ # Client-side WASM components
├─ Pages/ # @rendermode InteractiveWebAssembly
├─ Services/ # HTTP API clients
├─ Models/ # DTOs
Route Structure (Critical)
| Route | File Location | Render Mode | Purpose |
|---|---|---|---|
/ |
Server.Client/Pages/Index.razor |
WASM | Landing page |
/sender/login |
Server.Client/Pages/LoginSenderPage.razor |
WASM | Sender auth |
/sender |
Server/Components/Pages/EnvelopeSenderPage.razor |
Server | Sender dashboard |
/sender/editor |
Server/Components/Pages/EnvelopeSenderEditorPage.razor |
Server | Envelope editor + PDF viewer |
/envelope/login/{key} |
Server.Client/Pages/LoginReceiverPage.razor |
WASM | Receiver auth |
/envelope/{key} |
Server/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
// 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. EnvelopeGenerator.Server needs 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 (EnvelopeGenerator.Server/yarp.json)
Routes /api/*, /swagger/*, /openapi/*, /scalar/* → https://localhost:8088
PDF.js Settings (EnvelopeGenerator.Server/wwwroot/appsettings.json)
{
"PdfViewerOptions": {
"ThumbnailBaseScale": 0.75,
"ThumbnailEnableHiDPI": true,
"MainCanvasEnableHiDPI": true,
"ZoomStepPercentage": 5
}
}
API Config (API/appsettings.json)
ConnectionStrings:Default- SQL Server DBAllowedOrigins- CORS (includeshttp://localhost:5131,http://localhost:7192)Cache:SignatureCacheExpiration- Signature persistence timeoutPSPDFKitLicenseKey- 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:
- Start API (
dotnet runinEnvelopeGenerator.API) - Start EnvelopeGenerator.Server (
dotnet runinEnvelopeGenerator.Server\EnvelopeGenerator.Server) - Navigate to
https://localhost:5131(or check console output for port) - Test sender login at
/sender/login - 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 metadataTBSIG_ENVELOPE_RECEIVER- Receiver assignmentsTBSIG_DOC_RECEIVER_ELEMENT- Signature fields (X, Y in INCHES)TBSIG_RECEIVER- Receiver registryTBSIG_DOCUMENT- PDF binary dataTBSIG_ENVELOPE_HISTORY- Audit trail
DevExpress
License: Commercial (v25.2.3) Components Used:
DxGrid- Master-detail gridsDxPdfViewer- Server-side PDF renderingDxPopup- Modal dialogsDxToolbar- Action barsDxFormLayout- Forms
Theme: Blazing Berry (default)
JavaScript Interop
PDF Viewer: wwwroot/js/pdf-viewer.js
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
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 (Server.Client):
DevExpress.Blazor.*25.2.3SkiaSharp.*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:5131orhttp://localhost:7192