feat(signatures): UI completa do módulo + rate limiting em rotas públicas
Fecha as duas pendências da leva anterior (módulo de Assinatura Eletrônica): tela de backoffice para gerenciar envelopes (criação, envio, cancelamento, checkpoint/finalização, auditoria) e as duas páginas públicas (/assinar/:token, /verificar/:verificationId). Backend: novos endpoints de streaming de PDF (documento congelado e PDF final consolidado, autenticados e via token público) que faltavam para a UI funcionar — o signatário não tinha como ver o próprio documento antes de confirmar leitura. Rate limiting (guard próprio, em memória, chaves por IP e por token) em todas as rotas sem sessão: auth (login/mfa/forgot-password/reset-password/refresh/logout) e todo o fluxo público de assinatura/verificação. Suíte: 77/77 verdes. pnpm turbo run typecheck build: 28/28. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -167,6 +167,15 @@ describe("signature envelopes — full lifecycle", () => {
|
||||
documentId = res.body.documents[0].id;
|
||||
});
|
||||
|
||||
it("downloads the frozen document PDF via the authenticated backoffice route", async () => {
|
||||
const res = await agent(app)
|
||||
.get(`/api/v1/signature-envelopes/${envelopeId}/documents/${documentId}/pdf`)
|
||||
.set(...bearer(admin.accessToken))
|
||||
.expect(200);
|
||||
expect(res.headers["content-type"]).toBe("application/pdf");
|
||||
expect(res.body.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("rejects creation for a company with no legal representative", async () => {
|
||||
const bareCompany = await agent(app)
|
||||
.post("/api/v1/companies")
|
||||
@@ -207,6 +216,8 @@ describe("signature envelopes — full lifecycle", () => {
|
||||
expect(state.body.signer.status).toBe("VIEWED");
|
||||
expect(state.body.documents).toHaveLength(1);
|
||||
|
||||
const pdf = await agent(app).get(`/api/v1/public-signature/${token}/documents/${documentId}/pdf`).expect(200);
|
||||
expect(pdf.headers["content-type"]).toBe("application/pdf");
|
||||
await agent(app).post(`/api/v1/public-signature/${token}/documents/${documentId}/confirm-read`).expect(201);
|
||||
await agent(app).post(`/api/v1/public-signature/${token}/confirm-data`).expect(201);
|
||||
await agent(app).post(`/api/v1/public-signature/${token}/consent`).expect(201);
|
||||
@@ -285,6 +296,15 @@ describe("signature envelopes — full lifecycle", () => {
|
||||
expect(sendMailMock.mock.calls[0]![0].to).toBe(contratanteEmail);
|
||||
});
|
||||
|
||||
it("downloads the final consolidated PDF via the authenticated backoffice route", async () => {
|
||||
const res = await agent(app)
|
||||
.get(`/api/v1/signature-envelopes/${envelopeId}/final-pdf`)
|
||||
.set(...bearer(admin.accessToken))
|
||||
.expect(200);
|
||||
expect(res.headers["content-type"]).toBe("application/pdf");
|
||||
expect(res.body.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("public verify endpoint confirms integrity for the completed envelope", async () => {
|
||||
const res = await agent(app).get(`/api/v1/public-verify/${verificationId}`).expect(200);
|
||||
expect(res.body.integrityValid).toBe(true);
|
||||
|
||||
Reference in New Issue
Block a user