assinafy 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2a0b97db3a9ad302307e31bccf8f06751fe310dd253417bb129ad921b0a4b3f
4
- data.tar.gz: 94eb893e22a78777a0b4102d572e274e0f22c5b50cd3768d348f2deac69541ab
3
+ metadata.gz: 83473f4fd075a7c665a16ee6ea6c38c64c548927930221d24ecd468cce1f4203
4
+ data.tar.gz: 57c81beb685fe09baf9de80eb36abc628d224952b2b08e582d19e24ecb402c16
5
5
  SHA512:
6
- metadata.gz: 43838b1c27e22fc5210a8e877a4e1897f50030a6e32801cf490f101de6d18805ed79bff013120801ce90ab53369531142bf678cbe0e04f543139aa72790bab11
7
- data.tar.gz: f0e442b567d84643b2237ec21edf5b59de9155268451986dcdcc19f841ccf1514e1fd11e112fedc0ff1b8c04439feb411fec7ec37bc06128a86409996745798e
6
+ metadata.gz: dda868b4808b8885693edc57d8825eaf25a31dd628395180f651bd479a2b59ced524205683900812aa61654b2e79a7c69a110ca8c99c54ea084f21ea3515640a
7
+ data.tar.gz: ba6c518504f42fddaa0f9cfe4f58b0bfe6e23a83255f2cee5ef1a76551fba72b628f8ea448ba93b24201b055fd41c2ee95882534c3eedfb334f49a5b23cb5439
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to the `assinafy` Ruby gem are documented here.
4
4
 
5
+ ## [2.0.1] - 2026-10-19
6
+
7
+ ### Fixed
8
+
9
+ - Assignment creation and cost estimation reject `DigitalCertificate` signers unless the assignment method is
10
+ `virtual`, before an unsignable collect assignment can invite the signer or consume credits. The local
11
+ `ValidationError` exposes the stable code `digital_certificate_requires_virtual` in `errors[:code]`.
12
+
5
13
  ## [2.0.0] - 2026-10-16
6
14
 
7
15
  ### Added
data/README.en.md CHANGED
@@ -394,9 +394,11 @@ the missing side is inferred from the other, and when both are omitted both defa
394
394
  - The certificate charge appears in the cost breakdown under the code `SignatureDigitalCertificate`. Resending a
395
395
  notification charges the notification again.
396
396
  - `DigitalCertificate` needs the Digital Certificate account feature (Standard and Pro plans), a CPF or CNPJ in the
397
- signer's `government_id`, and the signer alone in its signing step. A CPF requires that person's certificate (an
398
- e-CPF, or an e-CNPJ naming them as legal representative); a CNPJ requires an e-CNPJ for that company, from any of
399
- its representatives.
397
+ signer's `government_id`, a `method: 'virtual'` assignment, and the signer alone in its signing step. A collect
398
+ assignment, including one inferred from a template with positioned signer fields, cannot use certificate
399
+ signing. Direct assignment creation and estimation reject it with `ValidationError` code
400
+ `digital_certificate_requires_virtual`. A CPF requires that person's certificate (an e-CPF, or an e-CNPJ naming
401
+ them as legal representative); a CNPJ requires an e-CNPJ for that company, from any of its representatives.
400
402
  - `AssignmentResource::VERIFICATION_METHODS` and `::NOTIFICATION_METHODS` publish the enums. `build_payload`
401
403
  validates values, pairings, and `step` locally, so a typo fails before the request is sent.
402
404
 
@@ -433,10 +435,11 @@ assignment = client.assignments.create(
433
435
  assignment['signing_urls'] # => [{ 'signer_id' => 'signer-id', 'url' => 'https://.../sign/...' }, ...]
434
436
  ```
435
437
 
436
- `virtual` has no positioned fields; `collect` adds `entries` of positioned fields (see
437
- [Assignments](#assignments)). Both require a non-empty `signers` array. Steps are all-or-none, positive, and
438
- contiguous from 1; equal steps sign in parallel, and each step is notified when the previous one finishes. A
439
- certificate signer is alone in its step. Deadlines are zoned ISO 8601 and at least one hour ahead.
438
+ `virtual` has no positioned fields and is required for `DigitalCertificate`; `collect` adds `entries` of
439
+ positioned fields (see [Assignments](#assignments)). Both require a non-empty `signers` array. Steps are
440
+ all-or-none, positive, and contiguous from 1; equal steps sign in parallel, and each step is notified when the
441
+ previous one finishes. A certificate signer is alone in its step. Deadlines are zoned ISO 8601 and at least one
442
+ hour ahead.
440
443
 
441
444
  For a template, bind one distinct existing signer to each role and create the document and assignment together:
442
445
 
data/README.md CHANGED
@@ -531,9 +531,12 @@ dois, ambos assumem `Email`.
531
531
  ### Certificado digital ICP-Brasil (A1/A3)
532
532
 
533
533
  Exige o recurso **Certificado Digital** na conta (planos Standard e Pro), CPF ou CNPJ em
534
- `government_id` do signatário, e que cada signatário por certificado esteja **sozinho no seu
535
- passo**. Um CPF exige o certificado daquela pessoa (e-CPF, ou e-CNPJ que a nomeie como
536
- representante legal); um CNPJ exige um e-CNPJ da empresa, de qualquer um de seus representantes.
534
+ `government_id` do signatário, assignment com `method: 'virtual'` e que cada signatário por certificado esteja
535
+ **sozinho no seu passo**. Um assignment `collect`, inclusive quando inferido de um template com campos de
536
+ signatário posicionados, não aceita certificado digital. A criação e a estimativa diretas levantam
537
+ `ValidationError` com o código estável `digital_certificate_requires_virtual`. Um CPF exige o certificado daquela
538
+ pessoa (e-CPF, ou e-CNPJ que a nomeie como representante legal); um CNPJ exige um e-CNPJ da empresa, de qualquer
539
+ um de seus representantes.
537
540
 
538
541
  ---
539
542
 
@@ -308,9 +308,15 @@ on top of its notification, shown in cost estimates under the breakdown code `Si
308
308
 
309
309
  `DigitalCertificate` has the signer sign with their own ICP-Brasil certificate (A1 or A3) through the Web PKI
310
310
  browser extension, producing a qualified PAdES signature. It requires the Digital Certificate account feature, a
311
- CPF or CNPJ in the signer's `government_id` (accepted by both `SignerResource#create` and `#update`), and that the
312
- signer is alone in its signing step. A CPF requires that person's certificate (an e-CPF, or an e-CNPJ naming them
313
- as legal representative); a CNPJ requires an e-CNPJ for that company, from any of its representatives.
311
+ CPF or CNPJ in the signer's `government_id` (accepted by both `SignerResource#create` and `#update`), a
312
+ `method: 'virtual'` assignment, and that the signer is alone in its signing step. `AssignmentResource#create` and
313
+ `#estimate_cost` reject any other assignment method with `ValidationError`; its stable
314
+ `errors[:code]` is `digital_certificate_requires_virtual`. A CPF requires that person's certificate (an e-CPF, or
315
+ an e-CNPJ naming them as legal representative); a CNPJ requires an e-CNPJ for that company, from any of its
316
+ representatives.
317
+
318
+ A template with positioned signer fields creates a collect assignment, so it cannot be used with a
319
+ `DigitalCertificate` signer. Use a template without positioned signer fields for certificate signing.
314
320
 
315
321
  Certificate signers complete the signature in Assinafy's hosted signing flow, reached through the assignment's
316
322
  `signing_urls`. The SDK does not wrap the two-step Web PKI handshake (`/signers/certificate/start`,
@@ -11,6 +11,7 @@ module Assinafy
11
11
  class AssignmentResource < BaseResource
12
12
  OPTIONAL_FIELDS = %i[message expires_at copy_receivers].freeze
13
13
  METHODS = %w[virtual collect].freeze
14
+ DIGITAL_CERTIFICATE_REQUIRES_VIRTUAL = 'digital_certificate_requires_virtual'
14
15
 
15
16
  # How a signer's identity is verified before they may sign, set per signer
16
17
  # on the assignment. When omitted it is inferred from
@@ -24,7 +25,7 @@ module Assinafy
24
25
  # certificate (A1 or A3), producing a qualified PAdES signature.
25
26
  # Requires the Digital Certificate feature, a CPF or CNPJ in the
26
27
  # signer's `government_id`, and that the signer is alone in its signing
27
- # step. Charged 0.5 credits per signer on top of its notification
28
+ # step on a virtual assignment. Charged 0.5 credits per signer on top of its notification
28
29
  # (breakdown code `SignatureDigitalCertificate`). A CPF requires that person's
29
30
  # certificate (an e-CPF, or an e-CNPJ naming them as legal
30
31
  # representative); a CNPJ requires an e-CNPJ for that company, from any
@@ -124,6 +125,7 @@ module Assinafy
124
125
 
125
126
  result = { method: method }
126
127
  normalised = signers.map { |ref| normalise_signer_ref(ref, options) }
128
+ validate_certificate_method!(method, normalised)
127
129
  validate_signing_steps!(normalised)
128
130
  result[:signers] = normalised unless normalised.empty?
129
131
  OPTIONAL_FIELDS.each { |key| result[key] = p[key] if p[key] }
@@ -254,6 +256,16 @@ module Assinafy
254
256
  raise ValidationError.new('notification_methods must match the verification_method')
255
257
  end
256
258
 
259
+ def validate_certificate_method!(method, signers)
260
+ return if method == 'virtual'
261
+ return unless signers.any? { |signer| signer[:verification_method] == 'DigitalCertificate' }
262
+
263
+ raise ValidationError.new(
264
+ 'DigitalCertificate signers require method: virtual',
265
+ { code: DIGITAL_CERTIFICATE_REQUIRES_VIRTUAL, method: method }
266
+ )
267
+ end
268
+
257
269
  def validate_signing_steps!(signers)
258
270
  steps = signers.map { |signer| signer[:step] }
259
271
  contiguous = steps.compact.uniq.sort.each_with_index.all? { |step, index| step == index + 1 }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Assinafy
4
- VERSION = '2.0.0'
4
+ VERSION = '2.0.1'
5
5
  USER_AGENT = "Assinafy-Ruby-SDK/v#{VERSION}".freeze
6
6
  end
data/sig/assinafy.rbs CHANGED
@@ -336,6 +336,7 @@ module Assinafy
336
336
  METHODS: Array[String]
337
337
  VERIFICATION_METHODS: Array[String]
338
338
  NOTIFICATION_METHODS: Array[String]
339
+ DIGITAL_CERTIFICATE_REQUIRES_VIRTUAL: String
339
340
  SIGN_ITEM_KEY_MAP: Hash[String, String]
340
341
  IDENTITY_REVIEW_IMAGES: Array[String]
341
342
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: assinafy
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Assinafy SDK Contributors