@@ -13,10 +13,15 @@ This project showcases how traditional recruitment processes can be enhanced wit
1313- ** Two-Stage Verification** :
1414 - Initial PID verification (required for all applications)
1515 - Optional extras verification (diploma/seafarer certificates)
16+ - ** Document Signing with QES** : Sign employment contracts using Qualified Electronic Signatures (eIDAS QES)
17+ - Professional PDF contract generation with pdf-lib
18+ - SHA-256 document hashing for integrity verification
19+ - EUDI Wallet-based signing with qualified certificates
20+ - Real-time signing status polling
1621- ** Multi-Device Support** : Same-device deep links and cross-device QR code flows
1722- ** Independent Credential Tracking** : Each verified credential has its own transaction and status
1823- ** Credential Management** : Receive verifiable employment credentials in wallet
19- - ** Real-Time Polling** : 1-second polling intervals for verification status updates
24+ - ** Real-Time Polling** : 1.5 -second polling intervals for verification and signing status updates
2025- ** Professional Branding** : Consistent European Commission and EUDI Wallet branding
2126- ** Modern UI** : Clean, responsive Material-UI design with accessibility features
2227
@@ -40,10 +45,12 @@ This project showcases how traditional recruitment processes can be enhanced wit
4045
4146### Digital Identity & Security
4247
43- - ** JOSE** - JSON Web Token handling
48+ - ** JOSE** - JSON Web Token handling (JWT signing with ES256)
4449- ** CBOR-X** - Efficient credential encoding/decoding
4550- ** JKS-JS** - Java KeyStore integration
4651- ** QRCode** - QR code generation for verification flows
52+ - ** pdf-lib** - Professional PDF generation for contracts
53+ - ** crypto** - SHA-256 document hashing and cryptographic operations
4754
4855### Development Tools
4956
@@ -200,18 +207,31 @@ User → Next.js Page → API Route → Service → Repository → Database
200207src/
201208├── app/ # Next.js App Router
202209│ ├── api/ # API routes
203- │ │ └── applications/ # Application-related endpoints
204- │ │ ├── create/ # POST: Create new applications
205- │ │ ├── verification/[id]/ # GET: PID verification status polling
206- │ │ ├── verification-extras/[id]/ # GET: Extras verification status polling
207- │ │ ├── qr/[id]/ # GET: Generate PID verification QR code
208- │ │ ├── qr-extras/[id]/ # GET: Generate extras verification QR code
209- │ │ ├── qr-issue/[id]/ # GET: Generate credential offer QR code
210- │ │ └── [id]/
211- │ │ ├── extras/ # POST: Request additional credentials
212- │ │ └── issue-receipt/ # POST: Issue application receipt credential
210+ │ │ ├── applications/ # Application-related endpoints
211+ │ │ │ ├── create/ # POST: Create new applications
212+ │ │ │ ├── verification/[id]/ # GET: PID verification status polling
213+ │ │ │ ├── verification-extras/[id]/ # GET: Extras verification status polling
214+ │ │ │ ├── signing-status/[id]/ # GET: Document signing status polling
215+ │ │ │ ├── qr/[id]/ # GET: Generate PID verification QR code
216+ │ │ │ ├── qr-extras/[id]/ # GET: Generate extras verification QR code
217+ │ │ │ ├── qr-sign/[id]/ # GET: Generate document signing QR code
218+ │ │ │ ├── qr-issue/[id]/ # GET: Generate credential offer QR code
219+ │ │ │ └── [id]/
220+ │ │ │ ├── extras/ # POST: Request additional credentials
221+ │ │ │ ├── sign-document/ # POST: Initiate contract signing
222+ │ │ │ └── issue-receipt/ # POST: Issue application receipt credential
223+ │ │ ├── documents/[state]/ # GET: Serve PDF documents for signing
224+ │ │ ├── request.jwt/[state]/ # GET: Retrieve JWT signing request
225+ │ │ └── signed-document/[state]/ # POST: Receive signed documents from wallet
213226│ ├── jobs/ # Job listing and detail pages
214227│ ├── applications/ # Application management and status pages
228+ │ │ └── [id]/
229+ │ │ ├── page.tsx # PID verification QR display
230+ │ │ ├── callback/ # Verification callback handler
231+ │ │ ├── confirmation/ # Post-verification confirmation
232+ │ │ ├── extras/ # Additional credentials QR display
233+ │ │ ├── sign-contract/ # Contract signing QR display
234+ │ │ └── employee/ # Credential issuance QR display
215235│ ├── layout.tsx # Root layout with providers
216236│ └── page.tsx # Homepage (redirects to /jobs)
217237├── components/ # Reusable UI components
228248│ │ ├── issuance/ # Credential issuance domain
229249│ │ │ └── EmployeeCredentialService.ts # Employee credential data builder
230250│ │ ├── signing/ # Document signing domain
231- │ │ │ └── DocumentSigningService.ts # QES document signing workflows
251+ │ │ │ ├── DocumentSigningService.ts # QES signing workflow orchestration
252+ │ │ │ ├── ContractPdfGeneratorService.ts # Professional PDF generation
253+ │ │ │ └── DocumentHashService.ts # SHA-256 hashing & verification
232254│ │ ├── ApplicationService.ts # Main application workflow orchestrator
233255│ │ ├── JobService.ts # Job posting operations
234256│ │ ├── VerifierService.ts # EUDI verifier API integration
240262│ │ ├── ApplicationRepository.ts # Application lifecycle management
241263│ │ ├── JobRepository.ts # Job CRUD operations
242264│ │ ├── CredentialRepository.ts # Issued credentials tracking
243- │ │ └── VerifiedCredentialRepository.ts # Verified credentials from wallet
265+ │ │ ├── VerifiedCredentialRepository.ts # Verified credentials from wallet
266+ │ │ └── SignedDocumentRepository.ts # Signed documents (optimized queries)
244267│ ├── schemas/ # Input Validation (Zod)
245268│ │ ├── application.ts # Application creation, verification schemas
246269│ │ └── job.ts # Job validation schemas
@@ -257,10 +280,13 @@ src/
257280└── theme.ts # Material-UI theme configuration
258281
259282prisma/
260- ├── schema.prisma # Database schema (JobPosting, Application, IssuedCredential, VerifiedCredential)
283+ ├── schema.prisma # Database schema (JobPosting, Application, IssuedCredential, VerifiedCredential, SignedDocument )
261284├── migrations/ # Database migration history
262285└── seed.ts # Database seeding script
263286
287+ scripts/ # Testing and utility scripts
288+ └── clear-signed-documents.ts # Database cleanup for signed documents
289+
264290development/ # Development utilities and scripts
265291
266292env.ts # Environment variable validation and types
@@ -290,7 +316,9 @@ Services are now organized into domain-specific modules for better separation of
290316- ** Issuance Services** (` /services/issuance/ ` ):
291317 - ` EmployeeCredentialService ` : Builds employee credential data for issuance
292318- ** Signing Services** (` /services/signing/ ` ):
293- - ` DocumentSigningService ` : Handles document signing workflows with qualified electronic signatures (QES)
319+ - ` DocumentSigningService ` : Orchestrates QES document signing workflows and prepares EUDI signing requests
320+ - ` ContractPdfGeneratorService ` : Generates professional PDF employment contracts using pdf-lib
321+ - ` DocumentHashService ` : Calculates and verifies SHA-256 document hashes for integrity
294322- ** Core Services** :
295323 - ` ApplicationService ` : Orchestrates the complete application workflow (creation → verification → issuance)
296324 - ` VerifierService ` : EUDI verifier API integration
@@ -306,6 +334,7 @@ Services are now organized into domain-specific modules for better separation of
306334 - ` JobRepository ` : Job posting CRUD operations
307335 - ` CredentialRepository ` : Issued credentials tracking (for wallet claims)
308336 - ` VerifiedCredentialRepository ` : Verified credentials from wallet (PID, Diploma, Seafarer)
337+ - ` SignedDocumentRepository ` : Document signing sessions and signed contracts (optimized to avoid ArrayBuffer detachment)
309338- ** Schemas** : Zod-based input validation with decorator support
310339- ** Types** : EUDI-specific type definitions and JWT structures
311340
@@ -352,10 +381,10 @@ Each verified credential is tracked independently with status: `PENDING → VERI
352381 - ** EUDI Branding** : European Commission and EUDI Wallet logos
353382 - ** Personal Data** : Shows all extracted information from PID
354383 - ** Credential Status** : Visual chips showing verified PID credential
355- - ** Additional Information Section** : If job requires diploma/seafarer certificate:
356- - User can choose to provide additional credentials
357- - "Provide Diploma", "Provide Seafarer Certificate", or "Provide Both" buttons
358- - Optional - user can skip and proceed to credential issuance
384+ - ** Additional Information Section** :
385+ - ** Option 1 ** : Provide additional credentials (diploma/seafarer certificates) - Optional
386+ - ** Option 2 ** : Sign employment contract with QES - Proceeds to contract signing
387+ - ** Option 3 ** : Skip to credential issuance - Direct to employee ID issuance
359388
360389### 4. Additional Credentials Verification (Optional)
361390
@@ -365,7 +394,26 @@ Each verified credential is tracked independently with status: `PENDING → VERI
365394- ** Polling** : Application polls extras verification endpoint every 1 second
366395- ** Return to Confirmation** : After successful verification, redirects back to confirmation page
367396
368- ### 5. Application Receipt Issuance
397+ ### 5. Contract Signing with QES (Optional)
398+
399+ - ** Sign Contract Page** (` /applications/[id]/sign-contract ` ): Document signing workflow
400+ - ** PDF Generation** : Professional employment contract generated with pdf-lib
401+ - ** Document Display** : QR code for EUDI Wallet to access signing request
402+ - ** Signing Process** :
403+ 1 . Application initiates signing by calling ` /api/applications/[id]/sign-document `
404+ 2 . PDF contract generated with candidate and job details
405+ 3 . SHA-256 hash calculated for document integrity
406+ 4 . ` SignedDocument ` record created with state UUID and document content
407+ 5 . JWT signing request created with document hash and location
408+ 6 . User scans QR code with EUDI Wallet
409+ 7 . Wallet retrieves document from ` /api/documents/[state] `
410+ 8 . Wallet signs document with qualified certificate
411+ 9 . Signed document posted back to ` /api/signed-document/[state] `
412+ - ** Real-Time Polling** : Status updates every 1.5 seconds via ` /api/applications/signing-status/[id] `
413+ - ** Success Flow** : Redirects to confirmation page showing "Issue Employee ID" button
414+ - ** Error Handling** : Toast notification with retry option on signing failure
415+
416+ ### 6. Application Receipt Issuance
369417
370418- ** Employee Page** (` /applications/[id]/employee ` ): Final step
371419- ** Credential Offer** : QR code for receiving employment credential
@@ -388,6 +436,30 @@ npm run lint # Run ESLint
388436npx prisma studio # Open Prisma Studio (database GUI)
389437npx prisma generate # Regenerate Prisma client
390438npx prisma db push # Push schema changes to database
439+
440+ # Testing & Utilities
441+
442+ ```
443+
444+ ### Testing Document Signing
445+
446+ You can test the document signing endpoints manually with curl:
447+
448+ ``` bash
449+ # Create signing session
450+ curl -X POST http://localhost:3000/api/applications/{id}/sign-document
451+
452+ # Download PDF document
453+ curl http://localhost:3000/api/documents/{state} -o contract.pdf
454+
455+ # Retrieve JWT signing request (debug)
456+ curl http://localhost:3000/api/request.jwt/{state}/debug
457+
458+ # Check signing status
459+ curl http://localhost:3000/api/applications/signing-status/{id}
460+
461+ # Clear all signed documents (cleanup utility)
462+ npx tsx scripts/clear-signed-documents.ts
391463```
392464
393465### Code Quality
@@ -422,6 +494,15 @@ The application integrates with EUDI-compliant verifier and issuer services:
422494- ` GET /api/applications/verification-extras/{id} ` - Poll extras verification status
423495- ` GET /api/applications/qr-extras/{id} ` - Generate extras verification QR code
424496
497+ #### Document Signing
498+
499+ - ` POST /api/applications/{id}/sign-document ` - Initiate contract signing (generates PDF, creates signing session)
500+ - ` GET /api/applications/qr-sign/{id} ` - Generate document signing QR code
501+ - ` GET /api/applications/signing-status/{id} ` - Poll document signing status
502+ - ` GET /api/request.jwt/{state} ` - Retrieve JWT signing request for wallet
503+ - ` GET /api/documents/{state} ` - Serve PDF document for signing
504+ - ` POST /api/signed-document/{state} ` - Receive signed document from wallet
505+
425506#### Credential Issuance
426507
427508- ` GET /api/applications/qr-issue/{id} ` - Generate credential offer QR code
@@ -451,7 +532,16 @@ The application integrates with EUDI-compliant verifier and issuer services:
451532
452533- Tracks application lifecycle: ` CREATED → VERIFIED → ISSUED `
453534- Stores candidate personal data from PID verification
454- - Relations: JobPosting, IssuedCredentials, VerifiedCredentials
535+ - Relations: JobPosting, IssuedCredentials, VerifiedCredentials, SignedDocuments
536+
537+ #### SignedDocument
538+
539+ - Tracks document signing sessions and signed contracts
540+ - Fields: documentHash (SHA-256), documentType, documentLabel, documentContent (Bytes)
541+ - Transaction tracking: state (UUID), nonce (replay protection)
542+ - Signature data: documentWithSignature (signed PDF), signatureObject, signerCertificate
543+ - Status: ` PENDING → SIGNED ` or ` FAILED `
544+ - ** Optimization** : Repository excludes large binary fields by default to prevent ArrayBuffer detachment issues
455545
456546#### VerifiedCredential
457547
0 commit comments