vehicles 0.6.1 → 0.8.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.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +164 -0
  3. data/CHANGELOG.md +274 -0
  4. data/README.md +55 -10
  5. data/data/PROVENANCE-vehicles.md +12 -0
  6. data/data/plates/PROVENANCE.md +5 -4
  7. data/data/plates/_decode/at-districts.yml +287 -0
  8. data/data/plates/_decode/ch-cantons.yml +110 -0
  9. data/data/plates/_decode/cn-issuing-offices.yml +463 -0
  10. data/data/plates/_decode/cn-provinces.yml +614 -0
  11. data/data/plates/_decode/cz-kraj.yml +159 -0
  12. data/data/plates/_decode/dk-serial-blocks.yml +327 -0
  13. data/data/plates/_decode/fr-departements.yml +191 -0
  14. data/data/plates/_decode/gb-age-identifiers.yml +170 -0
  15. data/data/plates/_decode/gb-memory-tags.yml +202 -0
  16. data/data/plates/_decode/gr-prefectures.yml +1408 -0
  17. data/data/plates/_decode/hr-cities.yml +315 -0
  18. data/data/plates/_decode/ie-counties.yml +227 -0
  19. data/data/plates/_decode/in-state-codes.yml +169 -0
  20. data/data/plates/_decode/is-districts-1938.yml +116 -0
  21. data/data/plates/_decode/it-provinces.yml +348 -0
  22. data/data/plates/_decode/jp-office-marks.yml +960 -0
  23. data/data/plates/_decode/jp-use-marks.yml +205 -0
  24. data/data/plates/_decode/kr-authority-marks.yml +146 -0
  25. data/data/plates/_decode/kr-use-syllables.yml +194 -0
  26. data/data/plates/_decode/lu-series-order.yml +638 -0
  27. data/data/plates/_decode/mx-entity-series.yml +380 -0
  28. data/data/plates/_decode/my-index-marks.yml +271 -0
  29. data/data/plates/_decode/no-counties-1913.yml +148 -0
  30. data/data/plates/_decode/no-districts.yml +901 -0
  31. data/data/plates/_decode/pl-powiats.yml +567 -0
  32. data/data/plates/_decode/pt-trailer-services.yml +96 -0
  33. data/data/plates/_decode/ro-counties.yml +213 -0
  34. data/data/plates/_decode/se-diplomatic.yml +220 -0
  35. data/data/plates/_decode/si-regions.yml +123 -0
  36. data/data/plates/_decode/sk-districts.yml +314 -0
  37. data/data/plates/_decode/th-registration-elements.yml +208 -0
  38. data/data/plates/_decode/ua-regions.yml +393 -0
  39. data/data/plates/_decode/za-licence-marks.yml +215 -0
  40. data/data/plates/_meta/classes.yml +1 -0
  41. data/data/plates/_meta/separators.yml +102 -0
  42. data/data/plates/ad.yml +961 -0
  43. data/data/plates/ar.yml +762 -0
  44. data/data/plates/at.yml +1424 -0
  45. data/data/plates/au-act.yml +472 -0
  46. data/data/plates/au-nsw.yml +282 -0
  47. data/data/plates/au-nt.yml +431 -0
  48. data/data/plates/au-qld.yml +272 -0
  49. data/data/plates/au-sa.yml +248 -0
  50. data/data/plates/au-tas.yml +302 -0
  51. data/data/plates/au-vic.yml +215 -0
  52. data/data/plates/au-wa.yml +309 -0
  53. data/data/plates/be.yml +1840 -0
  54. data/data/plates/br.yml +1152 -0
  55. data/data/plates/ca-ab.yml +430 -0
  56. data/data/plates/ca-bc.yml +697 -0
  57. data/data/plates/ca-mb.yml +499 -0
  58. data/data/plates/ca-nb.yml +537 -0
  59. data/data/plates/ca-nl.yml +743 -0
  60. data/data/plates/ca-ns.yml +808 -0
  61. data/data/plates/ca-nt.yml +610 -0
  62. data/data/plates/ca-nu.yml +280 -0
  63. data/data/plates/ca-on.yml +881 -0
  64. data/data/plates/ca-pe.yml +592 -0
  65. data/data/plates/ca-qc.yml +1036 -0
  66. data/data/plates/ca-sk.yml +256 -0
  67. data/data/plates/ca-yt.yml +656 -0
  68. data/data/plates/ch.yml +1273 -0
  69. data/data/plates/cn.yml +1431 -0
  70. data/data/plates/cy.yml +688 -0
  71. data/data/plates/cz.yml +1179 -0
  72. data/data/plates/de.yml +553 -118
  73. data/data/plates/dk.yml +1647 -0
  74. data/data/plates/ee.yml +1275 -0
  75. data/data/plates/es.yml +228 -32
  76. data/data/plates/fi.yml +1271 -0
  77. data/data/plates/fr.yml +1265 -0
  78. data/data/plates/gb.yml +1188 -0
  79. data/data/plates/gr.yml +721 -0
  80. data/data/plates/hr.yml +860 -0
  81. data/data/plates/hu.yml +959 -0
  82. data/data/plates/ie.yml +775 -0
  83. data/data/plates/in.yml +1172 -0
  84. data/data/plates/is.yml +667 -0
  85. data/data/plates/it.yml +1317 -0
  86. data/data/plates/jp.yml +3650 -0
  87. data/data/plates/kr.yml +1375 -0
  88. data/data/plates/li.yml +1010 -0
  89. data/data/plates/lt.yml +879 -0
  90. data/data/plates/lu.yml +842 -0
  91. data/data/plates/lv.yml +924 -0
  92. data/data/plates/mc.yml +1024 -0
  93. data/data/plates/mt.yml +854 -0
  94. data/data/plates/mx.yml +1372 -0
  95. data/data/plates/my.yml +685 -0
  96. data/data/plates/nl.yml +44 -0
  97. data/data/plates/no.yml +1018 -0
  98. data/data/plates/nz.yml +1699 -0
  99. data/data/plates/pl.yml +1296 -0
  100. data/data/plates/pt.yml +847 -0
  101. data/data/plates/ro.yml +785 -0
  102. data/data/plates/se.yml +1091 -0
  103. data/data/plates/si.yml +1105 -0
  104. data/data/plates/sk.yml +1439 -0
  105. data/data/plates/sm.yml +1119 -0
  106. data/data/plates/th.yml +1150 -0
  107. data/data/plates/ua.yml +1672 -0
  108. data/data/plates/us-ak.yml +763 -0
  109. data/data/plates/us-al.yml +457 -0
  110. data/data/plates/us-ar.yml +427 -0
  111. data/data/plates/us-as.yml +454 -0
  112. data/data/plates/us-az.yml +430 -0
  113. data/data/plates/us-ca.yml +892 -0
  114. data/data/plates/us-co.yml +452 -0
  115. data/data/plates/us-ct.yml +427 -0
  116. data/data/plates/us-dc.yml +614 -0
  117. data/data/plates/us-de.yml +551 -0
  118. data/data/plates/us-fl.yml +319 -96
  119. data/data/plates/us-ga.yml +644 -0
  120. data/data/plates/us-gu.yml +658 -0
  121. data/data/plates/us-hi.yml +585 -0
  122. data/data/plates/us-ia.yml +438 -0
  123. data/data/plates/us-id.yml +531 -0
  124. data/data/plates/us-il.yml +516 -0
  125. data/data/plates/us-in.yml +324 -0
  126. data/data/plates/us-ks.yml +351 -0
  127. data/data/plates/us-ky.yml +770 -0
  128. data/data/plates/us-la.yml +568 -0
  129. data/data/plates/us-ma.yml +379 -0
  130. data/data/plates/us-md.yml +536 -0
  131. data/data/plates/us-me.yml +445 -0
  132. data/data/plates/us-mi.yml +408 -0
  133. data/data/plates/us-mn.yml +411 -0
  134. data/data/plates/us-mo.yml +356 -0
  135. data/data/plates/us-mp.yml +402 -0
  136. data/data/plates/us-ms.yml +432 -0
  137. data/data/plates/us-mt.yml +619 -0
  138. data/data/plates/us-nc.yml +602 -0
  139. data/data/plates/us-nd.yml +419 -0
  140. data/data/plates/us-ne.yml +483 -0
  141. data/data/plates/us-nh.yml +394 -0
  142. data/data/plates/us-nj.yml +547 -0
  143. data/data/plates/us-nm.yml +574 -0
  144. data/data/plates/us-nv.yml +655 -0
  145. data/data/plates/us-ny.yml +592 -0
  146. data/data/plates/us-oh.yml +404 -0
  147. data/data/plates/us-ok.yml +513 -0
  148. data/data/plates/us-or.yml +392 -0
  149. data/data/plates/us-pa.yml +506 -0
  150. data/data/plates/us-pr.yml +507 -0
  151. data/data/plates/us-ri.yml +445 -0
  152. data/data/plates/us-sc.yml +605 -0
  153. data/data/plates/us-sd.yml +428 -0
  154. data/data/plates/us-tn.yml +471 -0
  155. data/data/plates/us-tx.yml +535 -0
  156. data/data/plates/us-ut.yml +384 -0
  157. data/data/plates/us-va.yml +567 -0
  158. data/data/plates/us-vi.yml +489 -0
  159. data/data/plates/us-vt.yml +458 -0
  160. data/data/plates/us-wa.yml +484 -0
  161. data/data/plates/us-wi.yml +509 -0
  162. data/data/plates/us-wv.yml +446 -0
  163. data/data/plates/us-wy.yml +523 -0
  164. data/data/plates/va.yml +604 -0
  165. data/data/plates/za.yml +1141 -0
  166. data/data/vehicles.json +160653 -105090
  167. data/lib/vehicles/configuration.rb +17 -3
  168. data/lib/vehicles/dataset.rb +73 -18
  169. data/lib/vehicles/fuzzy.rb +115 -0
  170. data/lib/vehicles/http.rb +48 -0
  171. data/lib/vehicles/make.rb +36 -6
  172. data/lib/vehicles/mcp_server.rb +5 -5
  173. data/lib/vehicles/model.rb +21 -2
  174. data/lib/vehicles/plates/series.rb +172 -18
  175. data/lib/vehicles/plates/template_fill.rb +188 -0
  176. data/lib/vehicles/plates/templates.rb +162 -0
  177. data/lib/vehicles/plates.rb +12 -0
  178. data/lib/vehicles/providers/hosted_provider.rb +28 -55
  179. data/lib/vehicles/validators/vehicle_make_validator.rb +3 -1
  180. data/lib/vehicles/validators/vehicle_model_validator.rb +1 -1
  181. data/lib/vehicles/version.rb +1 -1
  182. data/lib/vehicles.rb +32 -16
  183. data/rakelib/data_refresh.rake +109 -0
  184. data/rakelib/plates_refresh.rake +29 -0
  185. data/sig/vehicles.rbs +18 -0
  186. metadata +164 -2
@@ -0,0 +1,380 @@
1
+ # plates/_decode/mx-entity-series.yml — Mexico's ENTIDAD FEDERATIVA serial
2
+ # ranges: the table that turns a Mexican private plate into a state.
3
+ #
4
+ # WHAT THIS IS, AND WHY IT IS NOT A PREFIX TABLE. Mexico does not encode its
5
+ # states the way Germany encodes its districts. There is no district letter and
6
+ # no province suffix: the 32 entidades federativas issue out of ONE national
7
+ # serial space, and the state is recoverable only by asking WHICH RANGE the
8
+ # serial falls in. Those ranges are enacted, closed and primary — Apéndice "C"
9
+ # Normativo of NOM-001-SCT-2-2016 ("ESTABLECE LA ASIGNACIÓN DE SERIES POR
10
+ # ENTIDAD FEDERATIVA, LA CIUDAD DE MÉXICO Y LA SECRETARÍA, POR TIPO DE SERVICIO
11
+ # Y VEHÍCULO, MATRICULADOS EN LA REPÚBLICA MEXICANA"), read off the Diario
12
+ # Oficial de la Federación text of 24 June 2016. Every row below is that
13
+ # appendix.
14
+ #
15
+ # THE DECODE IS A RANGE COMPARISON, NOT A LOOKUP. `AAA-001-A` to `AFZ-999-Z`
16
+ # is Aguascalientes; `AGA-001-A` to `CYZ-999-Z` is Baja California. A consumer
17
+ # decodes by comparing the LETTER GROUP against the interval endpoints in the
18
+ # NOM's own collating order — and that order is NOT plain A-Z, because the same
19
+ # appendix forbids four letters outright:
20
+ #
21
+ # "NOTA: EN LOS CARACTERES ALFABÉTICOS NO DEBERÁN UTILIZARSE LAS LETRAS
22
+ # I, Ñ, O, Q."
23
+ #
24
+ # so the alphabet actually walked is A B C D E F G H J K L M N P R S T U V W X
25
+ # Y Z (23 letters). `alphabet:` below is that sequence, machine-readable, and a
26
+ # decoder that compares with a 26-letter alphabet will mis-assign every range
27
+ # that straddles a forbidden letter.
28
+ #
29
+ # FOUR CAUTIONS, all of them load-bearing:
30
+ #
31
+ # 1. RANGES ARE ALLOCATIONS, NOT OCCUPANCY. The NOM allocates Baja California
32
+ # 32,765,202 private-car combinations. Nobody has issued them. A range hit
33
+ # says "if this plate exists, it was issued by that state", never "this
34
+ # plate exists".
35
+ # 2. THE RANGES ARE PER SERVICE TYPE AND PER VEHICLE TYPE. The private-car
36
+ # table and the private-truck table are different serial spaces in different
37
+ # formats (AAA-000-A vs AA-0000-A); the border (fronterizo) tables are a
38
+ # third; the public-local tables a fourth. They are kept apart here for the
39
+ # same reason plates/_decode/it-provinces.yml keeps its two tables apart.
40
+ # 3. THE 2016 ALLOCATION REPLACED THE 2000 ONE. The Acuerdo of 25 September
41
+ # 2000 (DOF) carried its own per-entity assignment for the AAA-00-00 era;
42
+ # those ranges are NOT these ranges, and this file does not carry them.
43
+ # A pre-2016 Mexican plate does not decode through this table.
44
+ # 4. CIUDAD DE MÉXICO IS NOT IN THE STATE TABLE. It gets its own format
45
+ # (A00-AAA for private cars) and its own single range, listed separately
46
+ # below — which is why a CDMX plate can never collide with a state plate.
47
+ jurisdiction: mx
48
+ topic: entity-series
49
+ authority:
50
+ name: "Secretaría de Comunicaciones y Transportes — NOM-001-SCT-2-2016, Apéndice C Normativo"
51
+ url: "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016"
52
+ sources:
53
+ - "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # NOM-001-SCT-2-2016, Apéndice C Normativo — every range row below, verbatim, plus the note excluding I, Ñ, O and Q; accessed 2026-08-02"
54
+ - "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # Apéndice B Normativo, Tabla C — the character ORDER each range is expressed in (AAA-000-A private car, AA-0000-A private truck, A-000-AAA public-local car, A00-AAA-0 border private car)"
55
+ period: { start: 2016 }
56
+ period_evidence: enabling-instrument
57
+ period_note: >-
58
+ The allocation below is created by NOM-001-SCT-2-2016 itself, published in the
59
+ DOF on 24 June 2016 and in force sixty calendar days later (numeral 13:
60
+ "la presente Norma Oficial Mexicana entrará en vigor sesenta días naturales
61
+ contados a partir de la fecha de su publicación en el Diario Oficial de la
62
+ Federación") — 23 August 2016. The NOM's own recital says WHY it was needed:
63
+ the series assigned by the 2000 Acuerdo "se han agotado para algunos tipos de
64
+ servicio en diversas Entidades Federativas, la Ciudad de México y el
65
+ Autotransporte Federal, se hace necesario realizar una nueva asignación y
66
+ distribución de series, que evite la duplicidad de las mismas".
67
+
68
+ alphabet:
69
+ order: [A, B, C, D, E, F, G, H, J, K, L, M, N, P, R, S, T, U, V, W, X, Y, Z]
70
+ excluded: [I, "Ñ", O, Q]
71
+ source: "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # 'NOTA: EN LOS CARACTERES ALFABÉTICOS NO DEBERÁN UTILIZARSE LAS LETRAS I, Ñ, O, Q.' — repeated under every per-entity table in Apéndice C"
72
+ note: >-
73
+ Ñ is excluded by the NOM but is not in this dataset's serial alphabet
74
+ (plates/_meta/separators.yml) in the first place, so it never reaches a
75
+ regex; it is recorded because the NOM records it.
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # 1. TRANSPORTE PRIVADO, ENTIDADES FEDERATIVAS (non-border). Referenced by
79
+ # series mx-private-car-2016 (AAA-000-A) and mx-private-truck-2016
80
+ # (AA-0000-A).
81
+ # ---------------------------------------------------------------------------
82
+ private_entity:
83
+ - { code: MX-AGU, name: "Aguascalientes", car_from: "AAA-001-A", car_to: "AFZ-999-Z", car_allocated: 3170826, truck_from: "AA-0001-A", truck_to: "AF-9999-Z", truck_allocated: 1379862 }
84
+ - { code: MX-BCN, name: "Baja California", car_from: "AGA-001-A", car_to: "CYZ-999-Z", car_allocated: 32765202, truck_from: "AG-0001-A", truck_to: "CD-9999-Z", truck_allocated: 10118988 }
85
+ - { code: MX-BCS, name: "Baja California Sur", car_from: "CZA-001-A", car_to: "DEZ-999-Z", car_allocated: 3170826, truck_from: "CE-0001-A", truck_to: "CL-9999-Z", truck_allocated: 1609839 }
86
+ - { code: MX-CAM, name: "Campeche", car_from: "DFA-001-A", car_to: "DKZ-999-Z", car_allocated: 2642355, truck_from: "CM-0001-A", truck_to: "CU-9999-Z", truck_allocated: 1609839 }
87
+ - { code: MX-CHP, name: "Chiapas", car_from: "DLA-001-A", car_to: "DSZ-999-Z", car_allocated: 3170826, truck_from: "CV-0001-A", truck_to: "DC-9999-Z", truck_allocated: 1839816 }
88
+ - { code: MX-CHH, name: "Chihuahua", car_from: "DTA-001-A", car_to: "ETZ-999-Z", car_allocated: 12683304, truck_from: "DD-0001-A", truck_to: "EG-9999-Z", truck_allocated: 6209379 }
89
+ - { code: MX-COA, name: "Coahuila de Zaragoza", car_from: "EUA-001-A", car_to: "FPZ-999-Z", car_allocated: 10569420, truck_from: "EH-0001-A", truck_to: "FB-9999-Z", truck_allocated: 4139586 }
90
+ - { code: MX-COL, name: "Colima", car_from: "FRA-001-A", car_to: "FWZ-999-Z", car_allocated: 3170826, truck_from: "FC-0001-A", truck_to: "FJ-9999-Z", truck_allocated: 1609839 }
91
+ - { code: MX-DUR, name: "Durango", car_from: "FXA-001-A", car_to: "GFZ-999-Z", car_allocated: 4756239, truck_from: "FK-0001-A", truck_to: "FZ-9999-Z", truck_allocated: 3219678 }
92
+ - { code: MX-MEX, name: "México (Estado de)", car_from: "LGA-001-A", car_to: "PEZ-999-Z", car_allocated: 35936028, truck_from: "KL-0001-A", truck_to: "MS-9999-Z", truck_allocated: 11958804 }
93
+ - { code: MX-GUA, name: "Guanajuato", car_from: "GGA-001-A", car_to: "GYZ-999-Z", car_allocated: 8455536, truck_from: "FY-0001-A", truck_to: "GW-9999-Z", truck_allocated: 5059540 }
94
+ - { code: MX-GRO, name: "Guerrero", car_from: "GZA-001-A", car_to: "HFZ-999-Z", car_allocated: 3699297, truck_from: "GX-0001-A", truck_to: "HG-9999-Z", truck_allocated: 2299770 }
95
+ - { code: MX-HID, name: "Hidalgo", car_from: "HGA-001-A", car_to: "HRZ-999-Z", car_allocated: 4756239, truck_from: "HH-0001-A", truck_to: "HT-9999-Z", truck_allocated: 2299770 }
96
+ - { code: MX-JAL, name: "Jalisco", car_from: "HSA-001-A", car_to: "LFZ-999-Z", car_allocated: 31708260, truck_from: "HU-0001-A", truck_to: "KK-9999-Z", truck_allocated: 8969103 }
97
+ - { code: MX-MIC, name: "Michoacán de Ocampo", car_from: "PFA-001-A", car_to: "PUZ-999-Z", car_allocated: 6870123, truck_from: "MT-0001-A", truck_to: "NT-9999-Z", truck_allocated: 5519448 }
98
+ - { code: MX-MOR, name: "Morelos", car_from: "PVA-001-A", car_to: "RDZ-999-Z", car_allocated: 4756239, truck_from: "UN-0001-A", truck_to: "NZ-9999-Z", truck_allocated: 1379862 }
99
+ - { code: MX-NAY, name: "Nayarit", car_from: "REA-001-A", car_to: "RJZ-999-Z", car_allocated: 2642355, truck_from: "PA-0001-A", truck_to: "PG-9999-Z", truck_allocated: 1609839 }
100
+ - { code: MX-NLE, name: "Nuevo León", car_from: "RKA-001-A", car_to: "TGZ-999-Z", car_allocated: 23252724, truck_from: "PH-0001-A", truck_to: "RP-9999-Z", truck_allocated: 6899310 }
101
+ - { code: MX-OAX, name: "Oaxaca", car_from: "THA-001-A", car_to: "TMZ-999-Z", car_allocated: 2642355, truck_from: "RR-0001-A", truck_to: "RY-9999-Z", truck_allocated: 3679632 }
102
+ - { code: MX-PUE, name: "Puebla", car_from: "TNA-001-A", car_to: "UJZ-999-Z", car_allocated: 10569420, truck_from: "RZ-0001-A", truck_to: "SR-9999-Z", truck_allocated: 3679632 }
103
+ - { code: MX-QUE, name: "Querétaro", car_from: "UKA-001-A", car_to: "UPZ-999-Z", car_allocated: 2642355, truck_from: "SS-0001-A", truck_to: "SY-9999-Z", truck_allocated: 1609839 }
104
+ - { code: MX-ROO, name: "Quintana Roo", car_from: "URA-001-A", car_to: "UVZ-999-Z", car_allocated: 2642355, truck_from: "SZ-0001-A", truck_to: "TB-9999-Z", truck_allocated: 689931 }
105
+ - { code: MX-SLP, name: "San Luis Potosí", car_from: "UWA-001-A", car_to: "VEZ-999-Z", car_allocated: 4756239, truck_from: "TC-0001-A", truck_to: "TP-9999-Z", truck_allocated: 2759724 }
106
+ - { code: MX-SIN, name: "Sinaloa", car_from: "VFA-001-A", car_to: "VSZ-999-Z", car_allocated: 5813181, truck_from: "TR-0001-A", truck_to: "UL-9999-Z", truck_allocated: 4599540 }
107
+ - { code: MX-SON, name: "Sonora", car_from: "VTA-001-A", car_to: "WKZ-999-Z", car_allocated: 8984007, truck_from: "UM-0001-A", truck_to: "VK-9999-Z", truck_allocated: 5059494 }
108
+ - { code: MX-TAB, name: "Tabasco", car_from: "WLA-001-A", car_to: "WWZ-999-Z", car_allocated: 5284710, truck_from: "VL-0001-A", truck_to: "VT-9999-Z", truck_allocated: 1609839 }
109
+ - { code: MX-TAM, name: "Tamaulipas", car_from: "WXA-001-A", car_to: "XSZ-999-Z", car_allocated: 10040949, truck_from: "VU-0001-A", truck_to: "WX-9999-Z", truck_allocated: 6209379 }
110
+ - { code: MX-TLA, name: "Tlaxcala", car_from: "XTA-001-A", car_to: "XXZ-999-Z", car_allocated: 2642355, truck_from: "WY-0001-A", truck_to: "XE-9999-Z", truck_allocated: 1609839 }
111
+ - { code: MX-VER, name: "Veracruz de Ignacio de la Llave", car_from: "XYA-001-A", car_to: "YVZ-999-Z", car_allocated: 11097891, truck_from: "XF-0001-A", truck_to: "YM-9999-Z", truck_allocated: 6899310 }
112
+ - { code: MX-YUC, name: "Yucatán", car_from: "YWA-001-A", car_to: "ZCZ-999-Z", car_allocated: 3699297, truck_from: "YN-0001-A", truck_to: "YU-9999-Z", truck_allocated: 1379862 }
113
+ - { code: MX-ZAC, name: "Zacatecas", car_from: "ZDA-001-A", car_to: "ZHZ-999-Z", car_allocated: 2642355, truck_from: "YV-0001-A", truck_to: "ZJ-9999-Z", truck_allocated: 3219678 }
114
+
115
+ # ---------------------------------------------------------------------------
116
+ # 2. CIUDAD DE MÉXICO. Its own formats, its own single ranges — no overlap with
117
+ # the state table above is possible because the FORMATS differ.
118
+ # ---------------------------------------------------------------------------
119
+ private_cdmx:
120
+ - { code: MX-CMX, name: "Ciudad de México", vehicle: car, format: "A00-AAA", from: "A01-AAA", to: "Z99-ZZZ", allocated: 27704259 }
121
+ - { code: MX-CMX, name: "Ciudad de México", vehicle: truck, format: "A-000-AA", from: "A-001-AA", to: "Z-999-ZZ", allocated: 12154833 }
122
+ - { code: MX-CMX, name: "Ciudad de México", vehicle: bus, format: "00-AA-0", from: "01-AA-1", to: "99-ZZ-9", allocated: 471339 }
123
+ - { code: MX-CMX, name: "Ciudad de México", vehicle: trailer, format: "A-0A-00", from: "A-1A-01", to: "Z-9Z-99", allocated: 471339 }
124
+
125
+ # ---------------------------------------------------------------------------
126
+ # 3. TRANSPORTE PRIVADO FRONTERIZO — the BORDER-ZONE private series, a
127
+ # separate format (A00-AAA-0 for cars) issued only by the seven entities
128
+ # the NOM lists. Referenced by series mx-private-border-car-2016.
129
+ # ---------------------------------------------------------------------------
130
+ private_border:
131
+ - { code: MX-BCN, name: "Baja California", car_from: "A01-NRA-1", car_to: "Z99-NZZ-9", car_allocated: 4242051, truck_from: "ZJA-001-A", truck_to: "ZLC-999-Z", truck_allocated: 1125873, bus_from: "ZLD-001-A", bus_to: "ZLN-999-Z", trailer_from: "ZLP-001-A", trailer_to: "ZLZ-999-Z" }
132
+ - { code: MX-BCS, name: "Baja California Sur", car_from: "A01-PLA-1", car_to: "Z99-PRZ-9", car_allocated: 2356695, truck_from: "ZMA-001-A", truck_to: "ZNC-999-Z", truck_allocated: 597402, bus_from: "ZND-001-A", bus_to: "ZNN-999-Z", trailer_from: "ZNP-001-A", trailer_to: "ZNZ-999-Z" }
133
+ - { code: MX-COA, name: "Coahuila de Zaragoza", car_from: "A01-RAA-1", car_to: "Z99-REZ-9", car_allocated: 2356695, truck_from: "ZPA-001-A", truck_to: "ZRC-999-Z", truck_allocated: 597402, bus_from: "ZRD-001-A", bus_to: "ZRN-999-Z", trailer_from: "ZRP-001-A", trailer_to: "ZRZ-999-Z" }
134
+ - { code: MX-CHP, name: "Chiapas", car_from: "A01-RPA-1", car_to: "Z99-RTZ-9", car_allocated: 1885356, truck_from: "ZSA-001-A", truck_to: "ZST-999-Z", truck_allocated: 390609, bus_from: "ZSU-001-A", bus_to: "ZTD-999-Z", trailer_from: "ZTE-001-A", trailer_to: "ZTP-999-Z" }
135
+ - { code: MX-CHH, name: "Chihuahua", car_from: "A01-SAA-1", car_to: "Z99-SKZ-9", car_allocated: 4713390, truck_from: "ZTR-001-A", truck_to: "ZUY-999-Z", truck_allocated: 712287, bus_from: "ZUZ-001-A", bus_to: "ZVJ-999-Z", trailer_from: "ZVK-001-A", trailer_to: "ZVV-999-Z" }
136
+ - { code: MX-SON, name: "Sonora", car_from: "A01-SWA-1", car_to: "Z99-TAZ-9", car_allocated: 2356695, truck_from: "ZVW-001-A", truck_to: "ZXB-999-Z", truck_allocated: 666333, bus_from: "ZXC-001-A", bus_to: "ZXM-999-Z", trailer_from: "ZXN-001-A", trailer_to: "ZXY-999-Z" }
137
+ - { code: MX-TAM, name: "Tamaulipas", car_from: "A01-THA-1", car_to: "Z99-TTZ-9", car_allocated: 4713390, truck_from: "ZXZ-001-A", truck_to: "ZZC-999-Z", truck_allocated: 620379, bus_from: "ZZD-001-A", bus_to: "ZZN-999-Z", trailer_from: "ZZP-001-A", trailer_to: "ZZZ-999-Z" }
138
+
139
+ # ---------------------------------------------------------------------------
140
+ # 4. PÚBLICO LOCAL FRONTERIZO — the border public-transport series
141
+ # (A-000-AAA). Kept separate: same shape as the ordinary public-local
142
+ # car format, different range block (all in the Z-tail).
143
+ # ---------------------------------------------------------------------------
144
+ public_border:
145
+ - { code: MX-BCN, car_from: "A-001-ZLA", car_to: "Z-999-ZMN", car_allocated: 827172, truck_from: "A-001-ZMP", truck_to: "Z-999-ZNB", truck_allocated: 275724 }
146
+ - { code: MX-BCS, car_from: "A-001-ZNR", car_to: "Z-999-ZPJ", car_allocated: 413586, truck_from: "A-001-ZPK", truck_to: "Z-999-ZPR", truck_allocated: 137862 }
147
+ - { code: MX-COA, car_from: "A-001-ZPY", car_to: "Z-999-ZRS", car_allocated: 413586, truck_from: "A-001-ZRT", truck_to: "Z-999-ZRY", truck_allocated: 137862 }
148
+ - { code: MX-CHP, car_from: "A-001-ZSF", car_to: "Z-999-ZSZ", car_allocated: 413586, truck_from: "A-001-ZTA", truck_to: "Z-999-ZTF", truck_allocated: 137862 }
149
+ - { code: MX-CHH, car_from: "A-001-ZTN", car_to: "Z-999-ZVA", car_allocated: 804195, truck_from: "A-001-ZVB", truck_to: "Z-999-ZVN", truck_allocated: 275724 }
150
+ - { code: MX-SON, car_from: "A-001-ZWC", car_to: "Z-999-ZWW", car_allocated: 413586, truck_from: "A-001-ZWX", truck_to: "Z-999-ZXC", truck_allocated: 137862 }
151
+ - { code: MX-TAM, car_from: "A-001-ZXK", car_to: "Z-999-ZYY", car_allocated: 827172, truck_from: "A-001-ZYZ", truck_to: "Z-999-ZZL", truck_allocated: 275724 }
152
+
153
+ # ---------------------------------------------------------------------------
154
+ # 5. PÚBLICO LOCAL, ENTIDADES FEDERATIVAS (non-border) — added by the
155
+ # verification pass, 2026-08-02. Referenced by mx-public-car-2016
156
+ # (A-000-AAA).
157
+ #
158
+ # THE DECODE KEY INVERTS, AND THIS IS THE MOST IMPORTANT SINGLE FACT IN
159
+ # THIS FILE. The private-car series carries the entity in its LEADING
160
+ # letter triple; the public-local car series carries it in the TRAILING
161
+ # triple. Two seven-character shapes, opposite decode keys. A parse API
162
+ # that reuses the private decoder on a public plate will confidently name
163
+ # the wrong state, every time.
164
+ # ---------------------------------------------------------------------------
165
+ public_entity:
166
+ - { code: MX-AGU, name: "Aguascalientes", car_from: "A-001-AAA", car_to: "Z-999-ACZ", car_allocated: 1585413 }
167
+ - { code: MX-BCN, name: "Baja California", car_from: "A-001-ADA", car_to: "Z-999-AUZ", car_allocated: 7927065 }
168
+ - { code: MX-BCS, name: "Baja California Sur", car_from: "A-001-AVA", car_to: "Z-999-BDZ", car_allocated: 4756239 }
169
+ - { code: MX-CAM, name: "Campeche", car_from: "A-001-BEA", car_to: "Z-999-BGZ", car_allocated: 1585413 }
170
+ - { code: MX-CHP, name: "Chiapas", car_from: "A-001-BHA", car_to: "Z-999-BVZ", car_allocated: 6341652 }
171
+ - { code: MX-CHH, name: "Chihuahua", car_from: "A-001-BWA", car_to: "Z-999-CSZ", car_allocated: 10569420 }
172
+ - { code: MX-COA, name: "Coahuila de Zaragoza", car_from: "A-001-CTA", car_to: "Z-999-DUZ", car_allocated: 13211775 }
173
+ - { code: MX-COL, name: "Colima", car_from: "A-001-DVA", car_to: "Z-999-DXZ", car_allocated: 1585413 }
174
+ - { code: MX-DUR, name: "Durango", car_from: "A-001-DYA", car_to: "Z-999-EFZ", car_allocated: 4227768 }
175
+ - { code: MX-GUA, name: "Guanajuato", car_from: "A-001-EGA", car_to: "Z-999-FEZ", car_allocated: 11626362 }
176
+ - { code: MX-GRO, name: "Guerrero", car_from: "A-001-FFA", car_to: "Z-999-FTZ", car_allocated: 6341652 }
177
+ - { code: MX-HID, name: "Hidalgo", car_from: "A-001-FUA", car_to: "Z-999-GLZ", car_allocated: 8984007 }
178
+ - { code: MX-JAL, name: "Jalisco", car_from: "A-001-GMA", car_to: "Z-999-JDZ", car_allocated: 20610369 }
179
+ - { code: MX-MEX, name: "México (Estado de)", car_from: "A-001-JEA", car_to: "Z-999-LAZ", car_allocated: 22724253 }
180
+ - { code: MX-MIC, name: "Michoacán de Ocampo", car_from: "A-001-LBA", car_to: "Z-999-LSZ", car_allocated: 7927065 }
181
+ - { code: MX-MOR, name: "Morelos", car_from: "A-001-LTA", car_to: "Z-999-MCZ", car_allocated: 5284710 }
182
+ - { code: MX-NAY, name: "Nayarit", car_from: "A-001-MDA", car_to: "Z-999-MJZ", car_allocated: 3170826 }
183
+ - { code: MX-NLE, name: "Nuevo León", car_from: "A-001-MKA", car_to: "Z-999-SHZ", car_allocated: 48090861 }
184
+ - { code: MX-OAX, name: "Oaxaca", car_from: "A-001-SJA", car_to: "Z-999-SRZ", car_allocated: 3699297 }
185
+ - { code: MX-PUE, name: "Puebla", car_from: "A-001-SSA", car_to: "Z-999-TFZ", car_allocated: 7398594 }
186
+ - { code: MX-QUE, name: "Querétaro", car_from: "A-001-TGA", car_to: "Z-999-TLZ", car_allocated: 2642355 }
187
+ - { code: MX-ROO, name: "Quintana Roo", car_from: "A-001-TMA", car_to: "Z-999-TRZ", car_allocated: 2113884 }
188
+ - { code: MX-SLP, name: "San Luis Potosí", car_from: "A-001-TSA", car_to: "Z-999-TUZ", car_allocated: 1585413 }
189
+ - { code: MX-SIN, name: "Sinaloa", car_from: "A-001-TVA", car_to: "Z-999-UNZ", car_allocated: 9512478 }
190
+ - { code: MX-SON, name: "Sonora", car_from: "A-001-UPA", car_to: "Z-999-VLZ", car_allocated: 11097891 }
191
+ - { code: MX-TAB, name: "Tabasco", car_from: "A-001-VMA", car_to: "Z-999-VRZ", car_allocated: 2113884 }
192
+ - { code: MX-TAM, name: "Tamaulipas", car_from: "A-001-VSA", car_to: "Z-999-WVZ", car_allocated: 14268717 }
193
+ - { code: MX-TLA, name: "Tlaxcala", car_from: "A-001-WWA", car_to: "Z-999-XBZ", car_allocated: 3170826 }
194
+ - { code: MX-VER, name: "Veracruz de Ignacio de la Llave", car_from: "A-001-XCA", car_to: "Z-999-YRZ", car_allocated: 19024956 }
195
+ - { code: MX-YUC, name: "Yucatán", car_from: "A-001-YSA", car_to: "Z-999-ZEZ", car_allocated: 6870123 }
196
+ - { code: MX-ZAC, name: "Zacatecas", car_from: "A-001-ZFA", car_to: "Z-999-ZKZ", car_allocated: 2642355 }
197
+ public_entity_note: >-
198
+ The trailing triples skip I, O and Q exactly as the Apéndice C NOTA requires
199
+ — Oaxaca runs SJA..SRZ and not SIA.., Sonora runs UPA..VLZ and not UOA.. That
200
+ the allocation is internally consistent with its own charset rule is the best
201
+ available corroboration that this transcription is faithful, and it is the
202
+ check a verifier should re-run before trusting any row.
203
+ public_entity_source: "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # Apéndice C, 'NUMERACIÓN DE LAS PLACAS ASIGNADAS A CADA ENTIDAD FEDERATIVA PÚBLICO LOCAL', AUTOMÓVILES column; accessed 2026-08-02"
204
+
205
+ # ---------------------------------------------------------------------------
206
+ # 6. POLICE ENTITY CODES — added by the verification pass, 2026-08-02.
207
+ #
208
+ # THE ONE MEXICAN SERIES THAT PRINTS A LITERAL ENTITY CODE. Everywhere else
209
+ # in this file the state is recoverable only by range comparison; on a
210
+ # police plate it is the first two characters, and a human can read it off.
211
+ # Grammar AA-000A-0 for vehicles, AA00A for motorcycles (NOM Apéndice B
212
+ # Tabla C row 4). Each entity gets the whole space under its own pair —
213
+ # 206,793 vehicle and 2,277 motorcycle combinations — so the code IS the
214
+ # decode and per-entity ranges add nothing.
215
+ #
216
+ # THESE ARE NOT THE §5.1.4.2 LEGEND ABBREVIATIONS AND MUST NOT BE MERGED
217
+ # WITH THEM: Oaxaca is AX here and OAX/OC there; Querétaro is ER here and
218
+ # QRO/QT there; Quintana Roo is TR here and QR there. Mexico City's code is
219
+ # DF — a name abolished in 2016, surviving inside a 2016 instrument.
220
+ # ---------------------------------------------------------------------------
221
+ police_entity_codes:
222
+ - { code: MX-AGU, name: "Aguascalientes", plate_code: "AG" }
223
+ - { code: MX-BCN, name: "Baja California", plate_code: "BC" }
224
+ - { code: MX-BCS, name: "Baja California Sur", plate_code: "BS" }
225
+ - { code: MX-CAM, name: "Campeche", plate_code: "CM" }
226
+ - { code: MX-COA, name: "Coahuila de Zaragoza", plate_code: "CA" }
227
+ - { code: MX-COL, name: "Colima", plate_code: "CL" }
228
+ - { code: MX-CHP, name: "Chiapas", plate_code: "CS" }
229
+ - { code: MX-CHH, name: "Chihuahua", plate_code: "CH" }
230
+ - { code: MX-CMX, name: "Ciudad de México", plate_code: "DF" }
231
+ - { code: MX-DUR, name: "Durango", plate_code: "DG" }
232
+ - { code: MX-MEX, name: "México (Estado de)", plate_code: "ME" }
233
+ - { code: MX-GUA, name: "Guanajuato", plate_code: "GT" }
234
+ - { code: MX-GRO, name: "Guerrero", plate_code: "GR" }
235
+ - { code: MX-HID, name: "Hidalgo", plate_code: "HG" }
236
+ - { code: MX-JAL, name: "Jalisco", plate_code: "JA" }
237
+ - { code: MX-MIC, name: "Michoacán de Ocampo", plate_code: "MC" }
238
+ - { code: MX-MOR, name: "Morelos", plate_code: "MR" }
239
+ - { code: MX-NAY, name: "Nayarit", plate_code: "NA" }
240
+ - { code: MX-NLE, name: "Nuevo León", plate_code: "NL" }
241
+ - { code: MX-OAX, name: "Oaxaca", plate_code: "AX" }
242
+ - { code: MX-PUE, name: "Puebla", plate_code: "PB" }
243
+ - { code: MX-QUE, name: "Querétaro", plate_code: "ER" }
244
+ - { code: MX-ROO, name: "Quintana Roo", plate_code: "TR" }
245
+ - { code: MX-SLP, name: "San Luis Potosí", plate_code: "SL" }
246
+ - { code: MX-SIN, name: "Sinaloa", plate_code: "SA" }
247
+ - { code: MX-SON, name: "Sonora", plate_code: "SN" }
248
+ - { code: MX-TAB, name: "Tabasco", plate_code: "TB" }
249
+ - { code: MX-TAM, name: "Tamaulipas", plate_code: "TM" }
250
+ - { code: MX-TLA, name: "Tlaxcala", plate_code: "TL" }
251
+ - { code: MX-VER, name: "Veracruz de Ignacio de la Llave", plate_code: "VE" }
252
+ - { code: MX-YUC, name: "Yucatán", plate_code: "YU" }
253
+ - { code: MX-ZAC, name: "Zacatecas", plate_code: "ZA" }
254
+ police_entity_codes_collision_warning: >-
255
+ VE is Veracruz's police code AND the fixed pair on manufacturer diagnostic
256
+ plates ("En la numeración de placas para vehículos de diagnóstico no se
257
+ modifican las letras 'VE'"). The two are separated by GRAMMAR, not by the
258
+ pair: police is AA-000A-0, diagnostic is AA-A000. A consumer that strips
259
+ separators before decoding must keep the shapes apart first.
260
+ police_entity_codes_source: "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # Apéndice C, 'SERIES ASIGNADAS PARA LA POLICÍA DE LAS DIFERENTES ENTIDADES FEDERATIVAS Y LA CIUDAD DE MÉXICO', AUTOMÓVILES and MOTOCICLETAS columns (AG-001A-1..AG-999Z-9 and AG01A..AG99Z per entity); accessed 2026-08-02"
261
+
262
+ # ---------------------------------------------------------------------------
263
+ # 7. LEGEND ABBREVIATIONS — NOM §5.1.4.2, columns (A), (B) and (C). Added by
264
+ # the verification pass, 2026-08-02.
265
+ #
266
+ # These are WORDS PRINTED ON THE PLATE, not part of any serial, and they are
267
+ # in this file only so nobody mistakes them for the police codes above.
268
+ # Column B is the traditional abbreviation; column C is the RENAPO-aligned
269
+ # catalogue code. The NOM permits either ("las posibles abreviaturas"), so a
270
+ # renderer must be able to set both.
271
+ #
272
+ # COLLISION IN THE PRIMARY, recorded not repaired: COLIMA and CIUDAD DE
273
+ # MÉXICO both carry the column-C code CM.
274
+ # ---------------------------------------------------------------------------
275
+ legend_abbreviations:
276
+ - { code: MX-AGU, option1: "AGS", renapo: "AS" }
277
+ - { code: MX-BCN, option1: "BC", renapo: "BC" }
278
+ - { code: MX-BCS, option1: "BCS", renapo: "BS" }
279
+ - { code: MX-CAM, option1: "CAMP", renapo: "CC" }
280
+ - { code: MX-COA, option1: "COAH", renapo: "CL" }
281
+ - { code: MX-COL, option1: "COL", renapo: "CM" }
282
+ - { code: MX-CHP, option1: "CHIS", renapo: "CS" }
283
+ - { code: MX-CHH, option1: "CHIH", renapo: "CH" }
284
+ - { code: MX-CMX, option1: "CDMX", renapo: "CM" }
285
+ - { code: MX-DUR, option1: "DGO", renapo: "DG" }
286
+ - { code: MX-GUA, option1: "GTO", renapo: "GT" }
287
+ - { code: MX-GRO, option1: "GRO", renapo: "GR" }
288
+ - { code: MX-HID, option1: "HGO", renapo: "HG" }
289
+ - { code: MX-JAL, option1: "JAL", renapo: "JC" }
290
+ - { code: MX-MEX, option1: "MEX", renapo: "MC" }
291
+ - { code: MX-MIC, option1: "MICH", renapo: "MN" }
292
+ - { code: MX-MOR, option1: "MOR", renapo: "MS" }
293
+ - { code: MX-NAY, option1: "NAY", renapo: "NT" }
294
+ - { code: MX-NLE, option1: "NL", renapo: "NL" }
295
+ - { code: MX-OAX, option1: "OAX", renapo: "OC" }
296
+ - { code: MX-PUE, option1: "PUE", renapo: "PL" }
297
+ - { code: MX-QUE, option1: "QRO", renapo: "QT" }
298
+ - { code: MX-ROO, option1: "QR", renapo: "QR" }
299
+ - { code: MX-SLP, option1: "SLP", renapo: "SP" }
300
+ - { code: MX-SIN, option1: "SIN", renapo: "SL" }
301
+ - { code: MX-SON, option1: "SON", renapo: "SR" }
302
+ - { code: MX-TAB, option1: "TAB", renapo: "TC" }
303
+ - { code: MX-TAM, option1: "TAMP", renapo: "TS" }
304
+ - { code: MX-TLA, option1: "TLAX", renapo: "TL" }
305
+ - { code: MX-VER, option1: "VER", renapo: "VZ" }
306
+ - { code: MX-YUC, option1: "YUC", renapo: "YN" }
307
+ - { code: MX-ZAC, option1: "ZAC", renapo: "ZS" }
308
+ legend_abbreviations_source: "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # §5.1.4.2: 'El nombre y las posibles abreviaturas que deben emplear las Entidades Federativas se indica en las columnas A, B y C de la siguiente Tabla.'; accessed 2026-08-02"
309
+
310
+ # ---------------------------------------------------------------------------
311
+ # 8. RESERVED LETTER TOKENS — added by the verification pass, 2026-08-02.
312
+ # Small, closed, and each one is a ONE-SHOT identification for a parse API,
313
+ # which is why they belong beside the ranges rather than buried in a series
314
+ # note. Every one is fixed by an express NOTA in Apéndice C or spelled
315
+ # literally in Tabla C.
316
+ # ---------------------------------------------------------------------------
317
+ reserved_letter_tokens:
318
+ - token: "D"
319
+ applies_to: "Convertidor (Dolly), federal, grammar A-00-000"
320
+ quote: "NOTA: En la numeración de placas para convertidor (Dolly) no se modifica la letra “D”."
321
+ - token: "VE"
322
+ applies_to: "Vehículos de diagnóstico (manufacturer road-test), grammar AA-A000"
323
+ quote: "NOTA: En la numeración de placas para vehículos de diagnóstico no se modifican las letras “VE”."
324
+ - token: "MT"
325
+ applies_to: "Traslado Nacional motocicletas, grammar AA000A, whole national range MT001A-MT999Z (22,977)"
326
+ quote: "NOTA: En la numeración de placas para traslado de motocicleta no se modifican las letras “MT”."
327
+ - token: "DM"
328
+ applies_to: "Demostración, Ciudad de México, grammar DM-AA-0 — spelled literally in Tabla C itself"
329
+ quote: "Tabla C, Apéndice B: 6.- Transporte Privado — Demostración, Ciudad de México (Todo tipo de vehículos) — DM-AA-0"
330
+ - token: "AM"
331
+ applies_to: "Ambulancias, grammar AA-000-AA; the pair is fixed by the ALLOCATION, not by Tabla C, which writes it generically"
332
+ quote: "Apéndice C, AMBULANCIA: AGUASCALIENTES AM-001-AA - AM-879-AS ... ZACATECAS AM-600-ZP - AM-999-ZZ"
333
+ - token: "BM"
334
+ applies_to: "Bomberos, grammar AA-000-AA; same basis as AM"
335
+ quote: "Apéndice C, BOMBEROS: AGUASCALIENTES BM-001-AA - BM-879-AS ... ZACATECAS BM-600-ZP - BM-999-ZZ"
336
+ - token: "PC"
337
+ applies_to: "Protección Civil, grammar 00-AA-000; and the LEADING DIGIT PAIR is the entity's fiscal number 01-32, which makes this the only Mexican series with a NUMERIC geographic decode"
338
+ quote: "Apéndice C, PROTECCIÓN CIVIL: AGUASCALIENTES 01-PC-001 - 01-PC-999 ... ZACATECAS 32-PC-001 - 32-PC-999"
339
+ reserved_letter_tokens_source: "https://www.dof.gob.mx/nota_detalle.php?codigo=5442476&fecha=24/06/2016 # the NOTA lines and the AM/BM/PC allocation tables in Apéndice C; Tabla C in Apéndice B for the DM token; accessed 2026-08-02"
340
+
341
+ # ---------------------------------------------------------------------------
342
+ # 9. VERIFICATION RECORD — independent second transcription, 2026-08-02.
343
+ # ---------------------------------------------------------------------------
344
+ verification:
345
+ method: >-
346
+ The whole of Apéndice C was re-extracted independently from a SECOND
347
+ federal copy of the instrument — the Secretaría de Economía NOM repository
348
+ PDF at http://www.economia-noms.gob.mx/normas/noms/2010/001sct22016.pdf,
349
+ 86 pages, text-extracted with `pdftotext -layout` and parsed by script —
350
+ and the resulting rows were compared against sections 1 to 4 of this file
351
+ row by row.
352
+ result: >-
353
+ AGREEMENT on every private-car range, every Ciudad de México range, and
354
+ every border range checked. Two independent transcriptions of a scanned
355
+ federal instrument agreeing is the strongest evidence available short of
356
+ the DOF facsimile itself.
357
+ anomalies_found:
358
+ - >-
359
+ MORELOS private-TRUCK row (section 1): the instrument prints
360
+ "UN-0001-A - NZ-9999-Z", whose end sorts BEFORE its start in the NOM's
361
+ own 23-letter alphabet. Both transcriptions read it identically, so the
362
+ defect is in the instrument or in its DOF type-setting, not in the
363
+ extraction. It is recorded, not repaired. A verifier with the DOF
364
+ facsimile should settle it; until then no consumer should range-decode a
365
+ Mexican private truck through that row.
366
+ - >-
367
+ PRINTED ORDER IS NOT MONOTONIC IN `from`. Apéndice C prints entities in
368
+ SPANISH alphabetical order, in which CH sorts as its own letter, so
369
+ Chiapas and Chihuahua precede Coahuila; and the Estado de México and
370
+ Michoacán blocks (LGA.. and PFA..) sit between Jalisco and Morelos in
371
+ letter space while being printed at their alphabetical positions. A
372
+ consumer MUST sort by `from` and must not assume row order. Sorted, the
373
+ blocks are contiguous and non-overlapping — which is the first check a
374
+ verifier should run.
375
+ not_transcribed: >-
376
+ Apéndice C also carries per-entity allocations for autobuses, remolques,
377
+ convertidores, motocicletas (three grammars), demostración, ecológicos,
378
+ ambulancias, bomberos, protección civil and escoltas. They are sourced at
379
+ exactly the same quality and are omitted for scope (PRD-PLATES §2.5).
380
+ Extending this file needs no new sourcing, only transcription.