Credential lifecycle
Issuance
When an operator submits a credential, Certiva synchronously:- Generates a unique
verificationId(e.g.vrf_2f9a0cdbe7c1) and a shortverificationCode(e.g.CERT-A1B2C3). - Computes a SHA-256 registry hash of the credential record.
- Builds a compact QR payload encoding the verification reference.
- Generates a public
verificationUrland aqrCodeUri. - Stores the QR image and credential metadata in Cloudflare R2 (or local filesystem in development).
- Writes the credential to the PostgreSQL registry with
anchorStatus: PENDING.
credentialAnchor job from the BullMQ queue, signs the credential hash with the issuer wallet, and submits a transaction to the CredentialRegistry smart contract on Polygon Amoy. Once confirmed, the credential record is updated to anchorStatus: ANCHORED with txHash and blockNumber.
Credentials are immediately verifiable after issuance — blockchain anchoring is non-blocking.
Verification results
Revocation
Revoked credentials remain in the registry permanently. They returnresult: REVOKED on verification instead of being deleted. Every revocation requires a reason:
Verification modes
CORE_REGISTRY
The standard mode. The verifier presents averificationCode, scans a QR code, or visits the verificationUrl. Certiva looks up the credential by its verificationCode or verificationId and returns the registry record.
SECURE_PDF
The verifier uploads the credential PDF. Certiva computes its SHA-256 hash and compares it against the storedCredentialDocumentProof record. A byte-level match returns VALID; any modification returns INVALID.
Document integrity proof
Independent of credentials, institutions can register a SHA-256 proof for any document:- The operator uploads a file via
POST /api/document-proofs. - Certiva hashes the file and stores a
SecureDocumentProofrecord — the source file is discarded. - The operator shares the returned
verificationCodeor QR code with document holders. - Verifiers submit the same document to
POST /api/document-proofs/verify/document. - Certiva hashes the submission and compares it to the stored record.
Batch issuance
Batch issuance processes a CSV file asynchronously via BullMQ:- Operator uploads CSV to
POST /api/credentials/bulk. - An
issuancequeue job is created and the API returns abatchIdimmediately. - The worker processes rows with 5 concurrent workers, generating all assets per credential.
- Failed rows are retried via the
retryqueue. - Progress and per-row results are tracked in an
IssuanceBatchrecord, readable atGET /api/batches/:id.
Blockchain anchoring
Blockchain anchoring is optional (controlled byBLOCKCHAIN_ENABLED) and works as a secondary integrity layer:
- Only the credential hash is stored on-chain — no personal data, student IDs, PDFs, or private metadata.
- The
CredentialRegistrySolidity contract on Polygon Amoy exposesanchorCredential(),revokeCredential(), andverifyCredential(). - The worker uses the issuer wallet (
ISSUER_WALLET) signed byPRIVATE_KEYto submit transactions. - Anchoring is non-blocking:
anchorStatusstarts asPENDINGand transitions toANCHOREDafter the transaction is confirmed. - Blockchain-specific audit logs are available at
GET /api/audit/blockchain.
Admin role hierarchy
Ownership constraints
- The last active
OWNERaccount cannot be deleted, disabled, or demoted. - Only an
OWNERcan elevate another admin toOWNER. - Non-
OWNERadmins cannot modify or deleteOWNERaccounts. - Admins with any historical activity can only be disabled, not deleted.
Audit trail
Every significant action produces anAuditLog entry. The log is append-only — no update or delete endpoint exists. Tracked actions include:
LOGIN_SUCCESS,LOGIN_FAILURE,LOGOUTCREDENTIAL_ISSUED,CREDENTIAL_REVOKED,CREDENTIAL_DELETEDDOCUMENT_PROOF_CREATED,DOCUMENT_PROOF_DELETEDADMIN_CREATED,ADMIN_UPDATED,ADMIN_DELETED,ADMIN_DISABLEDSETTINGS_UPDATED,FORBIDDEN_ATTEMPT
Storage
Asset storage (QR images, credential metadata) is abstracted behind aStorageService with two drivers: