mojulo 0.0.0 → 0.1.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 (121) hide show
  1. package/README.md +53 -4
  2. package/lib/audit-logger-new.js +11 -0
  3. package/lib/auth/gate.js +25 -0
  4. package/lib/auth/service.js +17 -0
  5. package/lib/auth/session.js +63 -0
  6. package/lib/builder/chat-processor.js +607 -0
  7. package/lib/builder/composer-bridge.js +82 -0
  8. package/lib/builder/evaluator.js +159 -0
  9. package/lib/builder/executor.js +252 -0
  10. package/lib/builder/index.js +48 -0
  11. package/lib/builder/session.js +248 -0
  12. package/lib/builder/system-prompt.js +422 -0
  13. package/lib/builder/tone-presets.js +75 -0
  14. package/lib/builder/tool-executors.js +1418 -0
  15. package/lib/builder/tools.js +338 -0
  16. package/lib/builder/validators.js +239 -0
  17. package/lib/composer/composer.js +225 -0
  18. package/lib/composer/index.js +40 -0
  19. package/lib/composer/protocols/00_base.txt +19 -0
  20. package/lib/composer/protocols/01_knowledge.txt +9 -0
  21. package/lib/composer/protocols/02_form-gathering.txt +32 -0
  22. package/lib/composer/protocols/03_appointments.txt +16 -0
  23. package/lib/composer/protocols/04_triage.txt +15 -0
  24. package/lib/composer/protocols/05_optical-read.txt +22 -0
  25. package/lib/composer/response-builder.js +98 -0
  26. package/lib/config-builder.js +650 -0
  27. package/lib/db/ids.js +10 -0
  28. package/lib/db/index.js +179 -0
  29. package/lib/db/repositories/apiKeys.js +72 -0
  30. package/lib/db/repositories/auditLogs.js +12 -0
  31. package/lib/db/repositories/botSpaces.js +12 -0
  32. package/lib/db/repositories/builderSessions.js +312 -0
  33. package/lib/db/repositories/deploymentEvents.js +12 -0
  34. package/lib/db/repositories/deployments.js +385 -0
  35. package/lib/db/repositories/documents.js +68 -0
  36. package/lib/db/repositories/mcpJobs.js +84 -0
  37. package/lib/deployers/bot-fleet.js +110 -0
  38. package/lib/deployers/bot-proxy.js +72 -0
  39. package/lib/deployers/build.js +89 -0
  40. package/lib/deployers/cloud-deploy.js +310 -0
  41. package/lib/deployers/docker.js +439 -0
  42. package/lib/deployers/fly.js +432 -0
  43. package/lib/deployers/index.js +38 -0
  44. package/lib/deployment-auth.js +36 -0
  45. package/lib/document-parser.js +171 -0
  46. package/lib/embedder/chunker.js +93 -0
  47. package/lib/embedder/local.js +101 -0
  48. package/lib/embedder/preview-rag.js +93 -0
  49. package/lib/envelope-schema.js +54 -0
  50. package/lib/fleet/scoped-sql.js +342 -0
  51. package/lib/form-schema-config/base.js +135 -0
  52. package/lib/form-schema-config/index.js +286 -0
  53. package/lib/form-schema-config/locales/af-ZA.js +153 -0
  54. package/lib/form-schema-config/locales/ar-AE.js +142 -0
  55. package/lib/form-schema-config/locales/ar-SA.js +164 -0
  56. package/lib/form-schema-config/locales/de-DE.js +152 -0
  57. package/lib/form-schema-config/locales/en-AU.js +161 -0
  58. package/lib/form-schema-config/locales/en-CA.js +115 -0
  59. package/lib/form-schema-config/locales/en-GB.js +132 -0
  60. package/lib/form-schema-config/locales/en-IN.js +219 -0
  61. package/lib/form-schema-config/locales/en-MY.js +171 -0
  62. package/lib/form-schema-config/locales/en-NG.js +198 -0
  63. package/lib/form-schema-config/locales/en-PH.js +186 -0
  64. package/lib/form-schema-config/locales/en-SG.js +153 -0
  65. package/lib/form-schema-config/locales/en-US.js +138 -0
  66. package/lib/form-schema-config/locales/es-ES.js +171 -0
  67. package/lib/form-schema-config/locales/es-MX.js +193 -0
  68. package/lib/form-schema-config/locales/fr-CA.js +138 -0
  69. package/lib/form-schema-config/locales/fr-FR.js +155 -0
  70. package/lib/form-schema-config/locales/hi-IN.js +219 -0
  71. package/lib/form-schema-config/locales/it-IT.js +157 -0
  72. package/lib/form-schema-config/locales/ja-JP.js +169 -0
  73. package/lib/form-schema-config/locales/ko-KR.js +140 -0
  74. package/lib/form-schema-config/locales/nl-NL.js +149 -0
  75. package/lib/form-schema-config/locales/pt-BR.js +168 -0
  76. package/lib/form-schema-config/locales/zh-CN.js +172 -0
  77. package/lib/form-schema-config/locales/zh-HK.js +142 -0
  78. package/lib/form-structure-schema.js +191 -0
  79. package/lib/llm-providers.js +828 -0
  80. package/lib/markdown.js +197 -0
  81. package/lib/mcp/catalysts/appointment-to-calendar.md +84 -0
  82. package/lib/mcp/catalysts/conversations-to-channel-digest.md +104 -0
  83. package/lib/mcp/catalysts/document-extract-to-store.md +92 -0
  84. package/lib/mcp/catalysts/knowledge-gap-miner.md +96 -0
  85. package/lib/mcp/catalysts/loader.js +144 -0
  86. package/lib/mcp/catalysts/qualify-lead-to-crm.md +83 -0
  87. package/lib/mcp/catalysts/scan-conversations-for-signal.md +92 -0
  88. package/lib/mcp/catalysts/submission-to-ticket.md +83 -0
  89. package/lib/mcp/catalysts/submissions-to-warehouse.md +103 -0
  90. package/lib/mcp/catalysts/weekly-submissions-digest.md +82 -0
  91. package/lib/mcp/jobs.js +64 -0
  92. package/lib/mcp/server.js +184 -0
  93. package/lib/mcp/session-binding.js +130 -0
  94. package/lib/mcp/tools/build.js +123 -0
  95. package/lib/mcp/tools/catalysts.js +477 -0
  96. package/lib/mcp/tools/context.js +325 -0
  97. package/lib/mcp/tools/fleet.js +391 -0
  98. package/lib/mcp/tools/jobs-tools.js +240 -0
  99. package/lib/mcp/tools/operate.js +314 -0
  100. package/lib/preview/build-preview-config.js +136 -0
  101. package/lib/rate-limiter.js +11 -0
  102. package/lib/resolve-api-key.js +142 -0
  103. package/lib/storage/index.js +40 -0
  104. package/messages/de.json +2136 -0
  105. package/messages/en.json +2136 -0
  106. package/messages/es.json +2136 -0
  107. package/messages/fr.json +2136 -0
  108. package/messages/it.json +2136 -0
  109. package/messages/ja.json +2136 -0
  110. package/messages/ko.json +2136 -0
  111. package/messages/nl.json +2136 -0
  112. package/messages/pl.json +2136 -0
  113. package/messages/pt.json +2136 -0
  114. package/messages/ru.json +2136 -0
  115. package/messages/uk.json +2136 -0
  116. package/messages/zh.json +2136 -0
  117. package/package.json +61 -5
  118. package/scripts/mcp-config.mjs +162 -0
  119. package/scripts/mcp-stdio-loader.mjs +42 -0
  120. package/scripts/mcp-stdio.mjs +108 -0
  121. package/scripts/mojulo-paths.mjs +48 -0
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Spanish (es-ES) Locale Configuration
3
+ */
4
+
5
+ export const LOCALE_INFO = {
6
+ code: 'es-ES',
7
+ name: 'Spain',
8
+ region: 'EU',
9
+ currency: 'EUR',
10
+ dateFormat: 'DD/MM/YYYY'
11
+ };
12
+
13
+ export const PATTERNS = {
14
+ phone: {
15
+ pattern: '^(\\+34|0034)?[6789]\\d{8}$',
16
+ error: 'Introduce un número de teléfono válido',
17
+ description: 'Spanish phone number'
18
+ },
19
+ postalCode: {
20
+ pattern: '^(0[1-9]|[1-4]\\d|5[0-2])\\d{3}$',
21
+ error: 'Introduce un código postal válido (ej. 28001)',
22
+ description: 'Spanish postal code'
23
+ },
24
+ dni: {
25
+ pattern: '^\\d{8}[A-Z]$',
26
+ error: 'Introduce un DNI válido (8 dígitos y una letra)',
27
+ description: 'Documento Nacional de Identidad (DNI)'
28
+ },
29
+ nie: {
30
+ pattern: '^[XYZ]\\d{7}[A-Z]$',
31
+ error: 'Introduce un NIE válido',
32
+ description: 'Número de Identidad de Extranjero (NIE)'
33
+ },
34
+ iban: {
35
+ pattern: '^ES\\d{22}$',
36
+ error: 'Introduce un IBAN español válido',
37
+ description: 'Spanish IBAN'
38
+ },
39
+ bic: {
40
+ pattern: '^[A-Z]{4}ES[A-Z0-9]{2}([A-Z0-9]{3})?$',
41
+ error: 'Introduce un BIC válido',
42
+ description: 'BIC/SWIFT code'
43
+ },
44
+ vatNumber: {
45
+ pattern: '^ES[A-Z0-9]\\d{7}[A-Z0-9]$',
46
+ error: 'Introduce un NIF/CIF válido',
47
+ description: 'Spanish VAT number (NIF/CIF)'
48
+ },
49
+ cif: {
50
+ pattern: '^[ABCDEFGHJNPQRSUVW]\\d{7}[A-J0-9]$',
51
+ error: 'Introduce un CIF válido',
52
+ description: 'Código de Identificación Fiscal (CIF)'
53
+ },
54
+ socialSecurity: {
55
+ pattern: '^\\d{12}$',
56
+ error: 'Introduce un número de Seguridad Social válido',
57
+ description: 'Spanish Social Security Number'
58
+ },
59
+ currency: {
60
+ pattern: '^€?\\s?\\d{1,3}(\\.\\d{3})*(,\\d{2})?$',
61
+ error: 'Introduce un importe válido',
62
+ description: 'Euro amount (Spanish format)'
63
+ }
64
+ };
65
+
66
+ export const ARCHETYPES = {
67
+ phone: {
68
+ type: 'tel',
69
+ autocomplete: 'tel',
70
+ inputMode: 'tel',
71
+ placeholder: '612 345 678',
72
+ pattern: PATTERNS.phone.pattern,
73
+ patternError: PATTERNS.phone.error,
74
+ pii: true
75
+ },
76
+ postalCode: {
77
+ type: 'text',
78
+ autocomplete: 'postal-code',
79
+ inputMode: 'numeric',
80
+ placeholder: '28001',
81
+ pattern: PATTERNS.postalCode.pattern,
82
+ patternError: PATTERNS.postalCode.error,
83
+ maxLength: 5
84
+ },
85
+ nationalId: {
86
+ type: 'text',
87
+ inputMode: 'text',
88
+ placeholder: '12345678A',
89
+ pattern: PATTERNS.dni.pattern,
90
+ patternError: PATTERNS.dni.error,
91
+ pii: true,
92
+ sensitive: true,
93
+ helpText: 'Tu DNI se almacenará de forma segura'
94
+ },
95
+ nie: {
96
+ type: 'text',
97
+ inputMode: 'text',
98
+ placeholder: 'X1234567A',
99
+ pattern: PATTERNS.nie.pattern,
100
+ patternError: PATTERNS.nie.error,
101
+ pii: true,
102
+ sensitive: true,
103
+ helpText: 'Tu NIE se almacenará de forma segura'
104
+ },
105
+ iban: {
106
+ type: 'text',
107
+ inputMode: 'text',
108
+ placeholder: 'ES9121000418450200051332',
109
+ pattern: PATTERNS.iban.pattern,
110
+ patternError: PATTERNS.iban.error,
111
+ pii: true
112
+ },
113
+ comunidadAutonoma: {
114
+ type: 'dropdown',
115
+ autocomplete: 'address-level1',
116
+ options: [
117
+ { value: 'AN', label: 'Andalucía' },
118
+ { value: 'AR', label: 'Aragón' },
119
+ { value: 'AS', label: 'Asturias' },
120
+ { value: 'IB', label: 'Baleares' },
121
+ { value: 'CN', label: 'Canarias' },
122
+ { value: 'CB', label: 'Cantabria' },
123
+ { value: 'CL', label: 'Castilla y León' },
124
+ { value: 'CM', label: 'Castilla-La Mancha' },
125
+ { value: 'CT', label: 'Cataluña' },
126
+ { value: 'CE', label: 'Ceuta' },
127
+ { value: 'VC', label: 'Comunidad Valenciana' },
128
+ { value: 'EX', label: 'Extremadura' },
129
+ { value: 'GA', label: 'Galicia' },
130
+ { value: 'MD', label: 'Madrid' },
131
+ { value: 'ML', label: 'Melilla' },
132
+ { value: 'MC', label: 'Murcia' },
133
+ { value: 'NC', label: 'Navarra' },
134
+ { value: 'PV', label: 'País Vasco' },
135
+ { value: 'RI', label: 'La Rioja' }
136
+ ]
137
+ },
138
+ currency: {
139
+ type: 'text',
140
+ inputMode: 'decimal',
141
+ placeholder: '€ 0,00',
142
+ pattern: PATTERNS.currency.pattern,
143
+ patternError: PATTERNS.currency.error
144
+ }
145
+ };
146
+
147
+ /**
148
+ * Spanish-specific field name mappings
149
+ */
150
+ export const FIELD_LABELS = {
151
+ postalCode: 'Código postal',
152
+ state: 'Comunidad Autónoma',
153
+ nationalId: 'DNI',
154
+ phone: 'Teléfono',
155
+ firstName: 'Nombre',
156
+ lastName: 'Apellidos',
157
+ streetAddress: 'Dirección',
158
+ city: 'Ciudad',
159
+ email: 'Correo electrónico',
160
+ dateOfBirth: 'Fecha de nacimiento'
161
+ };
162
+
163
+ /**
164
+ * GDPR compliance hints (strict for Spain/EU)
165
+ */
166
+ export const GDPR_HINTS = {
167
+ consentRequired: true,
168
+ dataRetentionNotice: true,
169
+ rightToErasure: true,
170
+ explicitConsentLanguage: 'Acepto el tratamiento de mis datos personales conforme a la política de privacidad.'
171
+ };
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Mexican Spanish (es-MX) Locale Configuration
3
+ */
4
+
5
+ export const LOCALE_INFO = {
6
+ code: 'es-MX',
7
+ name: 'Mexico',
8
+ region: 'North America',
9
+ currency: 'MXN',
10
+ dateFormat: 'DD/MM/YYYY'
11
+ };
12
+
13
+ export const PATTERNS = {
14
+ phone: {
15
+ pattern: '^(\\+52\\s?)?(\\(?\\d{2,3}\\)?\\s?)?\\d{3,4}[\\s-]?\\d{4}$',
16
+ error: 'Ingrese un número de teléfono válido',
17
+ description: 'Mexican phone number'
18
+ },
19
+ mobile: {
20
+ pattern: '^(\\+52\\s?)?1?\\s?\\d{10}$',
21
+ error: 'Ingrese un número de celular válido',
22
+ description: 'Mexican mobile number'
23
+ },
24
+ postalCode: {
25
+ pattern: '^\\d{5}$',
26
+ error: 'Ingrese un código postal válido (5 dígitos)',
27
+ description: 'Mexican postal code'
28
+ },
29
+ curp: {
30
+ pattern: '^[A-Z]{4}\\d{6}[HM][A-Z]{5}[A-Z\\d]\\d$',
31
+ error: 'Ingrese una CURP válida (18 caracteres)',
32
+ description: 'Clave Única de Registro de Población'
33
+ },
34
+ rfc: {
35
+ pattern: '^[A-ZÑ&]{3,4}\\d{6}[A-Z\\d]{3}$',
36
+ error: 'Ingrese un RFC válido',
37
+ description: 'Registro Federal de Contribuyentes'
38
+ },
39
+ rfcPersona: {
40
+ pattern: '^[A-ZÑ&]{4}\\d{6}[A-Z\\d]{3}$',
41
+ error: 'Ingrese un RFC válido (persona física)',
42
+ description: 'RFC for individuals (13 chars)'
43
+ },
44
+ rfcEmpresa: {
45
+ pattern: '^[A-ZÑ&]{3}\\d{6}[A-Z\\d]{3}$',
46
+ error: 'Ingrese un RFC válido (persona moral)',
47
+ description: 'RFC for companies (12 chars)'
48
+ },
49
+ nss: {
50
+ pattern: '^\\d{11}$',
51
+ error: 'Ingrese un NSS válido (11 dígitos)',
52
+ description: 'Número de Seguro Social'
53
+ },
54
+ clabe: {
55
+ pattern: '^\\d{18}$',
56
+ error: 'Ingrese una CLABE válida (18 dígitos)',
57
+ description: 'Interbank CLABE'
58
+ },
59
+ ine: {
60
+ pattern: '^\\d{13}$',
61
+ error: 'Ingrese un número de INE válido',
62
+ description: 'INE/IFE voter ID number'
63
+ },
64
+ currency: {
65
+ pattern: '^\\$?[\\d,]+(\\.\\d{2})?$',
66
+ error: 'Ingrese un monto válido',
67
+ description: 'Mexican Peso amount'
68
+ }
69
+ };
70
+
71
+ export const ARCHETYPES = {
72
+ phone: {
73
+ type: 'tel',
74
+ autocomplete: 'tel',
75
+ inputMode: 'tel',
76
+ placeholder: '55 1234 5678',
77
+ pattern: PATTERNS.mobile.pattern,
78
+ patternError: PATTERNS.mobile.error,
79
+ pii: true
80
+ },
81
+ postalCode: {
82
+ type: 'text',
83
+ autocomplete: 'postal-code',
84
+ inputMode: 'numeric',
85
+ placeholder: '06600',
86
+ pattern: PATTERNS.postalCode.pattern,
87
+ patternError: PATTERNS.postalCode.error,
88
+ maxLength: 5
89
+ },
90
+ nationalId: {
91
+ type: 'text',
92
+ inputMode: 'text',
93
+ placeholder: 'GARC850101HDFRRL09',
94
+ pattern: PATTERNS.curp.pattern,
95
+ patternError: PATTERNS.curp.error,
96
+ pii: true,
97
+ sensitive: true,
98
+ helpText: 'Tu CURP se almacenará de forma segura',
99
+ maxLength: 18
100
+ },
101
+ rfc: {
102
+ type: 'text',
103
+ inputMode: 'text',
104
+ placeholder: 'GARC850101ABC',
105
+ pattern: PATTERNS.rfc.pattern,
106
+ patternError: PATTERNS.rfc.error,
107
+ pii: true
108
+ },
109
+ clabe: {
110
+ type: 'text',
111
+ inputMode: 'numeric',
112
+ placeholder: '012345678901234567',
113
+ pattern: PATTERNS.clabe.pattern,
114
+ patternError: PATTERNS.clabe.error,
115
+ pii: true,
116
+ maxLength: 18
117
+ },
118
+ state: {
119
+ type: 'dropdown',
120
+ autocomplete: 'address-level1',
121
+ options: [
122
+ { value: 'AGU', label: 'Aguascalientes' },
123
+ { value: 'BCN', label: 'Baja California' },
124
+ { value: 'BCS', label: 'Baja California Sur' },
125
+ { value: 'CAM', label: 'Campeche' },
126
+ { value: 'CHP', label: 'Chiapas' },
127
+ { value: 'CHH', label: 'Chihuahua' },
128
+ { value: 'COA', label: 'Coahuila' },
129
+ { value: 'COL', label: 'Colima' },
130
+ { value: 'CMX', label: 'Ciudad de México' },
131
+ { value: 'DUR', label: 'Durango' },
132
+ { value: 'GUA', label: 'Guanajuato' },
133
+ { value: 'GRO', label: 'Guerrero' },
134
+ { value: 'HID', label: 'Hidalgo' },
135
+ { value: 'JAL', label: 'Jalisco' },
136
+ { value: 'MEX', label: 'Estado de México' },
137
+ { value: 'MIC', label: 'Michoacán' },
138
+ { value: 'MOR', label: 'Morelos' },
139
+ { value: 'NAY', label: 'Nayarit' },
140
+ { value: 'NLE', label: 'Nuevo León' },
141
+ { value: 'OAX', label: 'Oaxaca' },
142
+ { value: 'PUE', label: 'Puebla' },
143
+ { value: 'QUE', label: 'Querétaro' },
144
+ { value: 'ROO', label: 'Quintana Roo' },
145
+ { value: 'SLP', label: 'San Luis Potosí' },
146
+ { value: 'SIN', label: 'Sinaloa' },
147
+ { value: 'SON', label: 'Sonora' },
148
+ { value: 'TAB', label: 'Tabasco' },
149
+ { value: 'TAM', label: 'Tamaulipas' },
150
+ { value: 'TLA', label: 'Tlaxcala' },
151
+ { value: 'VER', label: 'Veracruz' },
152
+ { value: 'YUC', label: 'Yucatán' },
153
+ { value: 'ZAC', label: 'Zacatecas' }
154
+ ]
155
+ },
156
+ currency: {
157
+ type: 'text',
158
+ inputMode: 'decimal',
159
+ placeholder: '$1,000.00',
160
+ pattern: PATTERNS.currency.pattern,
161
+ patternError: PATTERNS.currency.error
162
+ }
163
+ };
164
+
165
+ /**
166
+ * Mexican Spanish field name mappings
167
+ */
168
+ export const FIELD_LABELS = {
169
+ postalCode: 'Código postal',
170
+ state: 'Estado',
171
+ nationalId: 'CURP',
172
+ phone: 'Teléfono',
173
+ mobile: 'Celular',
174
+ firstName: 'Nombre(s)',
175
+ lastName: 'Apellidos',
176
+ fullName: 'Nombre completo',
177
+ streetAddress: 'Dirección',
178
+ city: 'Ciudad',
179
+ neighborhood: 'Colonia',
180
+ email: 'Correo electrónico',
181
+ dateOfBirth: 'Fecha de nacimiento',
182
+ company: 'Empresa'
183
+ };
184
+
185
+ /**
186
+ * Mexican data protection (LFPDPPP) compliance hints
187
+ */
188
+ export const GDPR_HINTS = {
189
+ consentRequired: true,
190
+ dataRetentionNotice: true,
191
+ rightToErasure: true,
192
+ explicitConsentLanguage: 'Acepto el tratamiento de mis datos personales conforme al Aviso de Privacidad.'
193
+ };
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Canadian French (fr-CA) Locale Configuration
3
+ */
4
+
5
+ export const LOCALE_INFO = {
6
+ code: 'fr-CA',
7
+ name: 'Canada (Français)',
8
+ region: 'NA',
9
+ currency: 'CAD',
10
+ dateFormat: 'YYYY-MM-DD'
11
+ };
12
+
13
+ export const PATTERNS = {
14
+ phone: {
15
+ pattern: '^(\\+1)?[-.\\s]?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}$',
16
+ error: 'Entrez un numéro de téléphone valide',
17
+ description: 'Canadian phone number'
18
+ },
19
+ postalCode: {
20
+ pattern: '^[A-Za-z]\\d[A-Za-z][ -]?\\d[A-Za-z]\\d$',
21
+ error: 'Entrez un code postal valide (ex: A1A 1A1)',
22
+ description: 'Canadian postal code'
23
+ },
24
+ sin: {
25
+ pattern: '^\\d{3}[- ]?\\d{3}[- ]?\\d{3}$',
26
+ error: 'Entrez un NAS valide (XXX-XXX-XXX)',
27
+ description: 'Social Insurance Number (NAS)'
28
+ },
29
+ provinceCode: {
30
+ pattern: '^[A-Z]{2}$',
31
+ error: 'Entrez un code de province à 2 lettres',
32
+ description: 'Canadian province code'
33
+ },
34
+ currency: {
35
+ pattern: '^\\d{1,3}(\\s\\d{3})*(,\\d{2})?\\s?\\$?$',
36
+ error: 'Entrez un montant valide',
37
+ description: 'Canadian currency (French format)'
38
+ },
39
+ driversLicense: {
40
+ pattern: '^[A-Z0-9]{5,15}$',
41
+ error: 'Entrez un numéro de permis de conduire valide',
42
+ description: 'Canadian driver\'s license (varies by province)'
43
+ },
44
+ healthCard: {
45
+ pattern: '^[A-Z0-9]{10,14}$',
46
+ error: 'Entrez un numéro de carte santé valide',
47
+ description: 'Provincial health card number'
48
+ },
49
+ ramq: {
50
+ pattern: '^[A-Z]{4}\\d{8}$',
51
+ error: 'Entrez un numéro RAMQ valide',
52
+ description: 'Quebec health insurance number (RAMQ)'
53
+ }
54
+ };
55
+
56
+ export const ARCHETYPES = {
57
+ phone: {
58
+ type: 'tel',
59
+ autocomplete: 'tel',
60
+ inputMode: 'tel',
61
+ placeholder: '(514) 555-5555',
62
+ pattern: PATTERNS.phone.pattern,
63
+ patternError: PATTERNS.phone.error,
64
+ pii: true
65
+ },
66
+ postalCode: {
67
+ type: 'text',
68
+ autocomplete: 'postal-code',
69
+ inputMode: 'text',
70
+ placeholder: 'H2X 1Y4',
71
+ pattern: PATTERNS.postalCode.pattern,
72
+ patternError: PATTERNS.postalCode.error,
73
+ maxLength: 7
74
+ },
75
+ sin: {
76
+ type: 'text',
77
+ inputMode: 'numeric',
78
+ placeholder: 'XXX-XXX-XXX',
79
+ pattern: PATTERNS.sin.pattern,
80
+ patternError: PATTERNS.sin.error,
81
+ pii: true,
82
+ sensitive: true,
83
+ helpText: 'Votre numéro d\'assurance sociale sera conservé en toute sécurité'
84
+ },
85
+ province: {
86
+ type: 'dropdown',
87
+ autocomplete: 'address-level1',
88
+ options: [
89
+ { value: 'AB', label: 'Alberta' },
90
+ { value: 'BC', label: 'Colombie-Britannique' },
91
+ { value: 'MB', label: 'Manitoba' },
92
+ { value: 'NB', label: 'Nouveau-Brunswick' },
93
+ { value: 'NL', label: 'Terre-Neuve-et-Labrador' },
94
+ { value: 'NS', label: 'Nouvelle-Écosse' },
95
+ { value: 'NT', label: 'Territoires du Nord-Ouest' },
96
+ { value: 'NU', label: 'Nunavut' },
97
+ { value: 'ON', label: 'Ontario' },
98
+ { value: 'PE', label: 'Île-du-Prince-Édouard' },
99
+ { value: 'QC', label: 'Québec' },
100
+ { value: 'SK', label: 'Saskatchewan' },
101
+ { value: 'YT', label: 'Yukon' }
102
+ ]
103
+ },
104
+ currency: {
105
+ type: 'text',
106
+ inputMode: 'decimal',
107
+ placeholder: '0,00 $',
108
+ pattern: PATTERNS.currency.pattern,
109
+ patternError: PATTERNS.currency.error
110
+ }
111
+ };
112
+
113
+ /**
114
+ * French Canadian-specific field name mappings
115
+ */
116
+ export const FIELD_LABELS = {
117
+ postalCode: 'Code postal',
118
+ state: 'Province',
119
+ nationalId: 'Numéro d\'assurance sociale (NAS)',
120
+ phone: 'Téléphone',
121
+ firstName: 'Prénom',
122
+ lastName: 'Nom de famille',
123
+ streetAddress: 'Adresse',
124
+ city: 'Ville',
125
+ email: 'Adresse courriel',
126
+ dateOfBirth: 'Date de naissance',
127
+ fullName: 'Nom complet'
128
+ };
129
+
130
+ /**
131
+ * Canada has PIPEDA (similar to but less strict than GDPR)
132
+ */
133
+ export const GDPR_HINTS = {
134
+ consentRequired: true,
135
+ dataRetentionNotice: true,
136
+ rightToErasure: false,
137
+ explicitConsentLanguage: 'Je consens au traitement de mes renseignements personnels conformément à la politique de confidentialité.'
138
+ };
@@ -0,0 +1,155 @@
1
+ /**
2
+ * French (fr-FR) Locale Configuration
3
+ */
4
+
5
+ export const LOCALE_INFO = {
6
+ code: 'fr-FR',
7
+ name: 'France',
8
+ region: 'EU',
9
+ currency: 'EUR',
10
+ dateFormat: 'DD/MM/YYYY'
11
+ };
12
+
13
+ export const PATTERNS = {
14
+ phone: {
15
+ pattern: '^(\\+33|0)[1-9](\\d{2}){4}$',
16
+ error: 'Entrez un numéro de téléphone valide',
17
+ description: 'French phone number'
18
+ },
19
+ postalCode: {
20
+ pattern: '^\\d{5}$',
21
+ error: 'Entrez un code postal valide (5 chiffres)',
22
+ description: 'French postal code'
23
+ },
24
+ numeroSecuriteSociale: {
25
+ pattern: '^[12]\\d{2}(0[1-9]|1[0-2])\\d{8}(\\d{2})?$',
26
+ error: 'Entrez un numéro de sécurité sociale valide',
27
+ description: 'French social security number (NIR)'
28
+ },
29
+ iban: {
30
+ pattern: '^FR\\d{2}\\s?\\d{4}\\s?\\d{4}\\s?\\d{4}\\s?\\d{4}\\s?\\d{4}\\s?\\d{3}$',
31
+ error: 'Entrez un IBAN français valide',
32
+ description: 'French IBAN'
33
+ },
34
+ bic: {
35
+ pattern: '^[A-Z]{4}FR[A-Z0-9]{2}([A-Z0-9]{3})?$',
36
+ error: 'Entrez un code BIC valide',
37
+ description: 'BIC/SWIFT code'
38
+ },
39
+ vatNumber: {
40
+ pattern: '^FR[A-Z0-9]{2}\\d{9}$',
41
+ error: 'Entrez un numéro de TVA valide',
42
+ description: 'French VAT number (TVA)'
43
+ },
44
+ siret: {
45
+ pattern: '^\\d{14}$',
46
+ error: 'Entrez un numéro SIRET valide (14 chiffres)',
47
+ description: 'SIRET number'
48
+ },
49
+ siren: {
50
+ pattern: '^\\d{9}$',
51
+ error: 'Entrez un numéro SIREN valide (9 chiffres)',
52
+ description: 'SIREN number'
53
+ },
54
+ carteIdentite: {
55
+ pattern: '^\\d{12}$',
56
+ error: 'Entrez un numéro de carte d\'identité valide',
57
+ description: 'French ID card number'
58
+ },
59
+ currency: {
60
+ pattern: '^\\d{1,3}(\\s\\d{3})*(,\\d{2})?\\s?€?$',
61
+ error: 'Entrez un montant valide',
62
+ description: 'Euro amount (French format)'
63
+ }
64
+ };
65
+
66
+ export const ARCHETYPES = {
67
+ phone: {
68
+ type: 'tel',
69
+ autocomplete: 'tel',
70
+ inputMode: 'tel',
71
+ placeholder: '06 12 34 56 78',
72
+ pattern: PATTERNS.phone.pattern,
73
+ patternError: PATTERNS.phone.error,
74
+ pii: true
75
+ },
76
+ postalCode: {
77
+ type: 'text',
78
+ autocomplete: 'postal-code',
79
+ inputMode: 'numeric',
80
+ placeholder: '75001',
81
+ pattern: PATTERNS.postalCode.pattern,
82
+ patternError: PATTERNS.postalCode.error,
83
+ maxLength: 5
84
+ },
85
+ nationalId: {
86
+ type: 'text',
87
+ inputMode: 'numeric',
88
+ placeholder: '1 85 12 75 108 123 45',
89
+ pattern: PATTERNS.numeroSecuriteSociale.pattern,
90
+ patternError: PATTERNS.numeroSecuriteSociale.error,
91
+ pii: true,
92
+ sensitive: true,
93
+ helpText: 'Votre numéro de sécurité sociale sera gardé en sécurité'
94
+ },
95
+ iban: {
96
+ type: 'text',
97
+ inputMode: 'text',
98
+ placeholder: 'FR76 3000 6000 0112 3456 7890 189',
99
+ pattern: PATTERNS.iban.pattern,
100
+ patternError: PATTERNS.iban.error,
101
+ pii: true
102
+ },
103
+ region: {
104
+ type: 'dropdown',
105
+ autocomplete: 'address-level1',
106
+ options: [
107
+ { value: 'ARA', label: 'Auvergne-Rhône-Alpes' },
108
+ { value: 'BFC', label: 'Bourgogne-Franche-Comté' },
109
+ { value: 'BRE', label: 'Bretagne' },
110
+ { value: 'CVL', label: 'Centre-Val de Loire' },
111
+ { value: 'COR', label: 'Corse' },
112
+ { value: 'GES', label: 'Grand Est' },
113
+ { value: 'HDF', label: 'Hauts-de-France' },
114
+ { value: 'IDF', label: 'Île-de-France' },
115
+ { value: 'NOR', label: 'Normandie' },
116
+ { value: 'NAQ', label: 'Nouvelle-Aquitaine' },
117
+ { value: 'OCC', label: 'Occitanie' },
118
+ { value: 'PDL', label: 'Pays de la Loire' },
119
+ { value: 'PAC', label: 'Provence-Alpes-Côte d\'Azur' }
120
+ ]
121
+ },
122
+ currency: {
123
+ type: 'text',
124
+ inputMode: 'decimal',
125
+ placeholder: '0,00 €',
126
+ pattern: PATTERNS.currency.pattern,
127
+ patternError: PATTERNS.currency.error
128
+ }
129
+ };
130
+
131
+ /**
132
+ * French-specific field name mappings
133
+ */
134
+ export const FIELD_LABELS = {
135
+ postalCode: 'Code postal',
136
+ state: 'Région',
137
+ nationalId: 'Numéro de sécurité sociale',
138
+ phone: 'Téléphone',
139
+ firstName: 'Prénom',
140
+ lastName: 'Nom de famille',
141
+ streetAddress: 'Adresse',
142
+ city: 'Ville',
143
+ email: 'Adresse e-mail',
144
+ dateOfBirth: 'Date de naissance'
145
+ };
146
+
147
+ /**
148
+ * GDPR compliance hints (strict for France)
149
+ */
150
+ export const GDPR_HINTS = {
151
+ consentRequired: true,
152
+ dataRetentionNotice: true,
153
+ rightToErasure: true,
154
+ explicitConsentLanguage: 'J\'accepte le traitement de mes données personnelles conformément à la politique de confidentialité.'
155
+ };