verifiabl-issuer 0.4.0 → 0.5.0

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: d049c2b4efee0761f9172022bee306456bc6e77d8223081196c027d289f88c48
4
- data.tar.gz: b43694a8fa98216ddb558f3f63fc9c47f7a6c5740e6f47fd9c187a78f60fe437
3
+ metadata.gz: 136cf6c7ac5d993f41d75c2f441cbea8329aef35ae57edadc70d3530dc8850dc
4
+ data.tar.gz: e48d77fc6c7c06e77a4b58702bdd618dac3589a15428bbbc62abf5e3f3551821
5
5
  SHA512:
6
- metadata.gz: 961b1387f5420386fa996309dfdf8c3b237879a6c350d31072a34a42d6a54bcc289f205fd81cae3a12da225a1f060b7fdebee1aa43ccc36ed1662b58c2a24682
7
- data.tar.gz: 9f72f1055910e0725e340510d888fe8e271613c762cf72d39061fb9703b93d7b647af63d2558f45cbadf1832214736c0a2574d31caa338901d0cdb588f58a2a3
6
+ metadata.gz: dd7911d0a278a7998ea615cfac226b999bfd386af07bfe4ab03628330711eb9568a61fe0ec0089f638c0f2602d9f5ff69897d9ceffbee4fe54fd8330fceb8e6b
7
+ data.tar.gz: 1543207b85bb2e61c53625fc2a610a9b99d4c0dc1b560165e79456725ab07000b62a8e7354dc2b817a44b7e53b13815373388b81480d53fa19ca5b6e3a7f6584
data/CHANGELOG.md CHANGED
@@ -4,6 +4,38 @@ All notable changes to the Verifiabl Ruby SDK will be documented in this file.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [0.5.0] - 2026-10-09
8
+
9
+ ### Added
10
+
11
+ - AU2 `lump_sum` earnings lines accept `lump_sum_type`
12
+ (`PayslipCodes::Australian::LUMP_SUM_TYPES`: `a_redundancy` for STP lump sum
13
+ A type R, `a_other` for A type T, `b`, `d` or `e`), and a new `etp` line takes
14
+ `etp_type` (`PayslipCodes::Australian::ETP_TYPES`: `redundancy` for ETP code
15
+ R, `other` for O, `redundancy_split` for S, `other_split` for P,
16
+ `death_dependant` for D, `death_non_dependant` for N,
17
+ `death_non_dependant_split` for B or `death_trustee` for T) and
18
+ `etp_component` (`PayslipCodes::Australian::ETP_COMPONENTS`: `taxable` or
19
+ `tax_free`). Send the taxable and tax-free components as separate `etp`
20
+ lines; tax withheld from an ETP is part of `paygw`. Lump sum W stays
21
+ `return_to_work`, and lump sum U stays `paid_leave` with
22
+ `unused_on_termination`. The gem sends a `lump_sum` line without a type, and
23
+ the API accepts that for now. It will require `lump_sum_type` before
24
+ production, once every issuer is on an SDK release with the lump sum codes.
25
+
26
+ ### Removed
27
+
28
+ - **Breaking:** removed `au.payslip.v1` and `nz.payslip.v1` registration
29
+ validation. The gem no longer requires `period_start` for those schemas; it
30
+ sends them like any other schema without a field tree, and the issuer API
31
+ rejects them. Send `au.payslip.v2` instead, for example with
32
+ `Verifiabl::Issuer.prepare_australian_v2_payslip`.
33
+ - **Breaking:** removed the P2 PII writer `Verifiabl::Issuer.format_pii`.
34
+ Verifiabl now accepts only the AU2 and NZ2 PII formats from issuers. Use
35
+ `prepare_australian_v2_payslip` or `prepare_new_zealand_v2_payslip`, or for
36
+ low-level use `format_australian_pii` or `format_new_zealand_pii` with
37
+ `encrypt_pii`. Payslips already issued with P1 or P2 still verify.
38
+
7
39
  ## [0.4.0] - 2026-10-07
8
40
 
9
41
  - Add `layout: :horizontal` to local SVG and PNG rendering, with the QR on the
data/README.md CHANGED
@@ -9,7 +9,7 @@ client, RBS signatures, and packed-gem consumer qualification.
9
9
  Add the stable release to your bundle:
10
10
 
11
11
  ```ruby
12
- gem "verifiabl-issuer", "0.4.0"
12
+ gem "verifiabl-issuer", "0.5.0"
13
13
  ```
14
14
 
15
15
  Then run `bundle install`.
@@ -220,10 +220,12 @@ nz::LEAVE_BALANCE_UNITS # => ["hours", "days", "weeks"]
220
220
  ```
221
221
 
222
222
  `EARNINGS_TYPES`, `PAID_LEAVE_TYPES` and `ALLOWANCE_TYPES` are available for
223
- both jurisdictions. Use their strings in your normal payslip hash; the lists
224
- do not restrict input or add local enum/variant validation. The API may
225
- accept a new code before this gem is updated. Printed-text fields such as
226
- `tax_code` and `pay_cycle` are not code sets.
223
+ both jurisdictions. An AU2 `lump_sum` line takes a `lump_sum_type` from
224
+ `LUMP_SUM_TYPES`, and an `etp` line takes an `etp_type` from `ETP_TYPES` and
225
+ an `etp_component` from `ETP_COMPONENTS`. Use their strings in your normal
226
+ payslip hash; the lists do not restrict input or add local enum/variant
227
+ validation. The API may accept a new code before this gem is updated.
228
+ Printed-text fields such as `tax_code` and `pay_cycle` are not code sets.
227
229
 
228
230
  ### Self-managed barcode flow
229
231
 
@@ -425,13 +427,16 @@ failures raise `TransportError`. Request and error messages never include the su
425
427
 
426
428
  ## Offline protocol primitives
427
429
 
428
- Format and encrypt PII locally. The plaintext must never be logged or sent to Verifiabl:
430
+ Most integrations should use the v2 preparation helpers. To select the schema and formatter
431
+ yourself, format and encrypt PII locally with `format_australian_pii` (AU2, for `au.payslip.v2`) or
432
+ `format_new_zealand_pii` (NZ2, for `nz.payslip.v2`). The plaintext must never be logged or sent to
433
+ Verifiabl:
429
434
 
430
435
  ```ruby
431
- plaintext = Verifiabl::Issuer.format_pii(
436
+ plaintext = Verifiabl::Issuer.format_australian_pii(
432
437
  employee_name: "Jane Doe",
433
438
  employer_abn: "53004085616",
434
- address: "12 Example St, Sydney NSW 2000"
439
+ address: {lines: ["12 Example St"], suburb: "Sydney", state_or_territory: "NSW", postcode: "2000"}
435
440
  )
436
441
 
437
442
  encrypted = Verifiabl::Issuer.encrypt_pii(plaintext, provider_encryption_key)
@@ -30,7 +30,10 @@
30
30
  "rate": "decimal",
31
31
  "ytd_amount": "decimal",
32
32
  "allowance_type": null,
33
- "other_category": null
33
+ "other_category": null,
34
+ "lump_sum_type": null,
35
+ "etp_type": null,
36
+ "etp_component": null
34
37
  }
35
38
  ],
36
39
  "salary_sacrifice": [
@@ -7,8 +7,8 @@ module Verifiabl
7
7
  module PayslipCodes
8
8
  module Australian
9
9
  EARNINGS_TYPES = %w[
10
- paid_leave allowance ordinary overtime bonus_commission directors_fees
11
- lump_sum return_to_work other
10
+ paid_leave allowance lump_sum etp ordinary overtime
11
+ bonus_commission directors_fees return_to_work other
12
12
  ].map!(&:freeze).freeze
13
13
 
14
14
  PAID_LEAVE_TYPES = %w[
@@ -24,6 +24,19 @@ module Verifiabl
24
24
  home_office non_deductible transport_fares uniform private_vehicle general
25
25
  ].map!(&:freeze).freeze
26
26
 
27
+ LUMP_SUM_TYPES = %w[
28
+ a_redundancy a_other b d e
29
+ ].map!(&:freeze).freeze
30
+
31
+ ETP_TYPES = %w[
32
+ redundancy other redundancy_split other_split death_dependant death_non_dependant
33
+ death_non_dependant_split death_trustee
34
+ ].map!(&:freeze).freeze
35
+
36
+ ETP_COMPONENTS = %w[
37
+ taxable tax_free
38
+ ].map!(&:freeze).freeze
39
+
27
40
  PAY_FREQUENCIES = %w[
28
41
  weekly fortnightly monthly quarterly four_weekly semi_monthly
29
42
  ].map!(&:freeze).freeze
@@ -6,16 +6,12 @@ require_relative "generated/jurisdiction_pii_profiles"
6
6
  module Verifiabl
7
7
  module Issuer
8
8
  module Pii
9
- FIELD_ORDER = %i[
10
- employee_name position department employer_abn bsb account_number account_name address
11
- ].freeze
12
9
  AUSTRALIAN_FIELD_ORDER = JurisdictionPiiProfiles::AUSTRALIAN_FIELD_ORDER
13
10
  NEW_ZEALAND_FIELD_ORDER = JurisdictionPiiProfiles::NEW_ZEALAND_FIELD_ORDER
14
- PROFILE_ID = PiiTextProfile::PROFILE_ID
15
11
  AUSTRALIAN_PROFILE_ID = JurisdictionPiiProfiles::AUSTRALIAN_PROFILE_ID
16
12
  NEW_ZEALAND_PROFILE_ID = JurisdictionPiiProfiles::NEW_ZEALAND_PROFILE_ID
17
13
  PROFILE_UNICODE_VERSION = PiiTextProfile::UNICODE_VERSION
18
- PAYLOAD_MAX_BYTES = PiiTextProfile::PAYLOAD_MAX_BYTES
14
+ PAYLOAD_MAX_BYTES = JurisdictionPiiProfiles::PAYLOAD_MAX_BYTES
19
15
  FORMAT_CHARACTER_RANGES = PiiTextProfile::FORMAT_CHARACTER_RANGES
20
16
 
21
17
  Violation = Data.define(:field, :reason)
@@ -43,16 +39,8 @@ module Verifiabl
43
39
 
44
40
  module_function
45
41
 
46
- # Formats employee PII into the current P2 plaintext wire format. The
47
- # returned value must be encrypted before it is persisted or embedded.
48
- def format(fields)
49
- validate_fields!(fields)
50
- values, violations = normalize_values(fields)
51
- raise ValidationError, violations unless violations.empty?
52
-
53
- format_profile("P2", FIELD_ORDER.map { |field| values.fetch(field) })
54
- end
55
-
42
+ # Formats Australian employee PII as AU2 plaintext. The returned value
43
+ # must be encrypted before it is persisted or embedded.
56
44
  def format_australian(fields)
57
45
  allowed = %i[
58
46
  employee_name position department employer_name employer_abn bsb account_number account_name address
@@ -69,6 +57,8 @@ module Verifiabl
69
57
  format_profile(JurisdictionPiiProfiles::AUSTRALIAN_MARKER, AUSTRALIAN_FIELD_ORDER.map { |field| wire_values.fetch(field) })
70
58
  end
71
59
 
60
+ # Formats New Zealand employee PII as NZ2 plaintext. The returned value
61
+ # must be encrypted before it is persisted or embedded.
72
62
  def format_new_zealand(fields)
73
63
  allowed = %i[
74
64
  employee_name ird_number position department employer_name account_number account_name address
@@ -83,7 +73,7 @@ module Verifiabl
83
73
  format_profile(JurisdictionPiiProfiles::NEW_ZEALAND_MARKER, NEW_ZEALAND_FIELD_ORDER.map { |field| wire_values.fetch(field) })
84
74
  end
85
75
 
86
- def validate_fields!(fields, allowed = FIELD_ORDER)
76
+ def validate_fields!(fields, allowed)
87
77
  raise ArgumentError, "fields must be a Hash" unless fields.is_a?(Hash)
88
78
 
89
79
  normalized_keys = fields.keys.map do |key|
@@ -95,11 +85,6 @@ module Verifiabl
95
85
  end
96
86
  private_class_method :validate_fields!
97
87
 
98
- def normalize_values(fields)
99
- normalize_named_values(fields, FIELD_ORDER)
100
- end
101
- private_class_method :normalize_values
102
-
103
88
  def normalize_named_values(fields, names)
104
89
  names.each_with_object([{}, []]) do |field, (values, violations)|
105
90
  value, violation = normalize_value(field, field_value(fields, field))
@@ -155,8 +140,9 @@ module Verifiabl
155
140
 
156
141
  def format_profile(version, segments)
157
142
  plaintext = "#{version}|#{segments.join("|")}"
158
- limit = (version == "P2") ? PAYLOAD_MAX_BYTES : JurisdictionPiiProfiles::PAYLOAD_MAX_BYTES
159
- raise RangeError, "#{version} plaintext exceeds #{limit} UTF-8 bytes" if plaintext.bytesize > limit
143
+ if plaintext.bytesize > PAYLOAD_MAX_BYTES
144
+ raise RangeError, "#{version} plaintext exceeds #{PAYLOAD_MAX_BYTES} UTF-8 bytes"
145
+ end
160
146
 
161
147
  plaintext
162
148
  end
@@ -57,9 +57,6 @@ module Verifiabl
57
57
 
58
58
  def validate_payslip_non_pii!(schema, payslip_non_pii)
59
59
  raise ArgumentError, "payslip_non_pii must be a Hash" unless payslip_non_pii.is_a?(Hash)
60
- if %w[au.payslip.v1 nz.payslip.v1].include?(schema) && !key?(payslip_non_pii, :period_start)
61
- raise ArgumentError, "period_start is required for #{schema}"
62
- end
63
60
  validate_iso_date!(value(payslip_non_pii, :period_start), "period_start") if key?(payslip_non_pii, :period_start)
64
61
  validate_iso_date!(value(payslip_non_pii, :period_end), "period_end") if key?(payslip_non_pii, :period_end)
65
62
  validate_v2_currency!(payslip_non_pii) if [AUSTRALIAN_PAYSLIP_V2_SCHEMA, NEW_ZEALAND_PAYSLIP_V2_SCHEMA].include?(schema)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Verifiabl
4
4
  module Issuer
5
- VERSION = "0.4.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
@@ -21,10 +21,6 @@ require_relative "issuer/version"
21
21
  module Verifiabl
22
22
  module Issuer
23
23
  class << self
24
- def format_pii(fields)
25
- Pii.format(fields)
26
- end
27
-
28
24
  def format_australian_pii(fields)
29
25
  Pii.format_australian(fields)
30
26
  end
@@ -11,6 +11,9 @@ module Verifiabl
11
11
  PAID_LEAVE_TYPES: Array[String]
12
12
  ALLOWANCE_TYPES: Array[String]
13
13
  OTHER_ALLOWANCE_CATEGORIES: Array[String]
14
+ LUMP_SUM_TYPES: Array[String]
15
+ ETP_TYPES: Array[String]
16
+ ETP_COMPONENTS: Array[String]
14
17
  PAY_FREQUENCIES: Array[String]
15
18
  end
16
19
 
@@ -57,7 +60,6 @@ module Verifiabl
57
60
  ?address: new_zealand_address?
58
61
  }
59
62
 
60
- def self.format_pii: (Hash[Symbol | String, String?]) -> String
61
63
  def self.format_australian_pii: (australian_pii_fields) -> String
62
64
  def self.format_new_zealand_pii: (new_zealand_pii_fields) -> String
63
65
  def self.prepare_australian_v2_payslip: (pii: australian_pii_fields, payslip_non_pii: Hash[Symbol | String, untyped], issued_at: String | Time, key: binary, ?verifiabl_reference: String) -> PreparedV2Payslip
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verifiabl-issuer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Verifiabl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-06 00:00:00.000000000 Z
11
+ date: 2026-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64