@jantstack/adonis-authz 2.0.0-alpha.1 → 2.4.0-alpha.2

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 (214) hide show
  1. package/README.md +693 -36
  2. package/build/commands/authz_catalog_diff.js +1 -1
  3. package/build/commands/authz_catalog_diff.js.map +1 -1
  4. package/build/commands/authz_catalog_prune_orphans.d.ts +78 -0
  5. package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -0
  6. package/build/commands/authz_catalog_prune_orphans.js +136 -0
  7. package/build/commands/authz_catalog_prune_orphans.js.map +1 -0
  8. package/build/commands/authz_catalog_sync.d.ts +17 -0
  9. package/build/commands/authz_catalog_sync.d.ts.map +1 -1
  10. package/build/commands/authz_catalog_sync.js +27 -4
  11. package/build/commands/authz_catalog_sync.js.map +1 -1
  12. package/build/commands/authz_freeze.d.ts +44 -0
  13. package/build/commands/authz_freeze.d.ts.map +1 -0
  14. package/build/commands/authz_freeze.js +95 -0
  15. package/build/commands/authz_freeze.js.map +1 -0
  16. package/build/commands/authz_reconcile.d.ts +102 -0
  17. package/build/commands/authz_reconcile.d.ts.map +1 -0
  18. package/build/commands/authz_reconcile.js +294 -0
  19. package/build/commands/authz_reconcile.js.map +1 -0
  20. package/build/commands/authz_relations_reconcile.d.ts +97 -0
  21. package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
  22. package/build/commands/authz_relations_reconcile.js +313 -0
  23. package/build/commands/authz_relations_reconcile.js.map +1 -0
  24. package/build/commands/authz_scopes_relay.d.ts +47 -0
  25. package/build/commands/authz_scopes_relay.d.ts.map +1 -0
  26. package/build/commands/authz_scopes_relay.js +141 -0
  27. package/build/commands/authz_scopes_relay.js.map +1 -0
  28. package/build/commands/authz_unfreeze.d.ts +37 -0
  29. package/build/commands/authz_unfreeze.d.ts.map +1 -0
  30. package/build/commands/authz_unfreeze.js +92 -0
  31. package/build/commands/authz_unfreeze.js.map +1 -0
  32. package/build/commands/main.d.ts +6 -1
  33. package/build/commands/main.d.ts.map +1 -1
  34. package/build/commands/main.js +6 -1
  35. package/build/commands/main.js.map +1 -1
  36. package/build/commands/openfga_provision.d.ts +46 -4
  37. package/build/commands/openfga_provision.d.ts.map +1 -1
  38. package/build/commands/openfga_provision.js +90 -7
  39. package/build/commands/openfga_provision.js.map +1 -1
  40. package/build/configure.d.ts +11 -0
  41. package/build/configure.d.ts.map +1 -1
  42. package/build/configure.js +37 -1
  43. package/build/configure.js.map +1 -1
  44. package/build/index.d.ts +50 -10
  45. package/build/index.d.ts.map +1 -1
  46. package/build/index.js +45 -6
  47. package/build/index.js.map +1 -1
  48. package/build/providers/authz_provider.d.ts +26 -2
  49. package/build/providers/authz_provider.d.ts.map +1 -1
  50. package/build/providers/authz_provider.js +55 -2
  51. package/build/providers/authz_provider.js.map +1 -1
  52. package/build/services/relations.d.ts +14 -0
  53. package/build/services/relations.d.ts.map +1 -0
  54. package/build/services/relations.js +17 -0
  55. package/build/services/relations.js.map +1 -0
  56. package/build/src/{catalog.d.ts → catalog/catalog.d.ts} +41 -2
  57. package/build/src/catalog/catalog.d.ts.map +1 -0
  58. package/build/src/{catalog.js → catalog/catalog.js} +120 -14
  59. package/build/src/catalog/catalog.js.map +1 -0
  60. package/build/src/{catalog_cache.d.ts → catalog/catalog_cache.d.ts} +46 -22
  61. package/build/src/catalog/catalog_cache.d.ts.map +1 -0
  62. package/build/src/{catalog_cache.js → catalog/catalog_cache.js} +53 -43
  63. package/build/src/catalog/catalog_cache.js.map +1 -0
  64. package/build/src/define_config.d.ts +137 -3
  65. package/build/src/define_config.d.ts.map +1 -1
  66. package/build/src/define_config.js.map +1 -1
  67. package/build/src/drivers/database_driver.d.ts +128 -7
  68. package/build/src/drivers/database_driver.d.ts.map +1 -1
  69. package/build/src/drivers/database_driver.js +510 -24
  70. package/build/src/drivers/database_driver.js.map +1 -1
  71. package/build/src/drivers/database_relations_driver.d.ts +113 -0
  72. package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
  73. package/build/src/drivers/database_relations_driver.js +679 -0
  74. package/build/src/drivers/database_relations_driver.js.map +1 -0
  75. package/build/src/drivers/openfga_driver.d.ts +729 -122
  76. package/build/src/drivers/openfga_driver.d.ts.map +1 -1
  77. package/build/src/drivers/openfga_driver.js +2083 -476
  78. package/build/src/drivers/openfga_driver.js.map +1 -1
  79. package/build/src/drivers/openfga_facts.d.ts +384 -0
  80. package/build/src/drivers/openfga_facts.d.ts.map +1 -0
  81. package/build/src/drivers/openfga_facts.js +836 -0
  82. package/build/src/drivers/openfga_facts.js.map +1 -0
  83. package/build/src/drivers/openfga_relations_driver.d.ts +141 -0
  84. package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
  85. package/build/src/drivers/openfga_relations_driver.js +590 -0
  86. package/build/src/drivers/openfga_relations_driver.js.map +1 -0
  87. package/build/src/errors.d.ts +290 -5
  88. package/build/src/errors.d.ts.map +1 -1
  89. package/build/src/errors.js +296 -7
  90. package/build/src/errors.js.map +1 -1
  91. package/build/src/freeze.d.ts +141 -0
  92. package/build/src/freeze.d.ts.map +1 -0
  93. package/build/src/freeze.js +217 -0
  94. package/build/src/freeze.js.map +1 -0
  95. package/build/src/http/app_access_middleware.d.ts.map +1 -0
  96. package/build/src/http/app_access_middleware.js.map +1 -0
  97. package/build/src/http/resource_access_middleware.d.ts +105 -0
  98. package/build/src/http/resource_access_middleware.d.ts.map +1 -0
  99. package/build/src/http/resource_access_middleware.js +81 -0
  100. package/build/src/http/resource_access_middleware.js.map +1 -0
  101. package/build/src/identity.d.ts +74 -1
  102. package/build/src/identity.d.ts.map +1 -1
  103. package/build/src/identity.js +100 -2
  104. package/build/src/identity.js.map +1 -1
  105. package/build/src/manager.d.ts +330 -4
  106. package/build/src/manager.d.ts.map +1 -1
  107. package/build/src/manager.js +1285 -188
  108. package/build/src/manager.js.map +1 -1
  109. package/build/src/models/authz_assignment.d.ts +7 -7
  110. package/build/src/models/authz_assignment.d.ts.map +1 -1
  111. package/build/src/models/authz_deny.d.ts +7 -7
  112. package/build/src/models/authz_deny.d.ts.map +1 -1
  113. package/build/src/models/authz_permission.d.ts +7 -7
  114. package/build/src/models/authz_permission.d.ts.map +1 -1
  115. package/build/src/models/authz_role.d.ts +7 -7
  116. package/build/src/models/authz_role.d.ts.map +1 -1
  117. package/build/src/models/authz_role_permission.d.ts +7 -7
  118. package/build/src/models/authz_role_permission.d.ts.map +1 -1
  119. package/build/src/openfga.d.ts +18 -2
  120. package/build/src/openfga.d.ts.map +1 -1
  121. package/build/src/openfga.js +15 -1
  122. package/build/src/openfga.js.map +1 -1
  123. package/build/src/reconcile.d.ts +37 -0
  124. package/build/src/reconcile.d.ts.map +1 -0
  125. package/build/src/reconcile.js +69 -0
  126. package/build/src/reconcile.js.map +1 -0
  127. package/build/src/relation_partition_trigger.d.ts +8 -0
  128. package/build/src/relation_partition_trigger.d.ts.map +1 -0
  129. package/build/src/relation_partition_trigger.js +93 -0
  130. package/build/src/relation_partition_trigger.js.map +1 -0
  131. package/build/src/relations/define_relations_config.d.ts +75 -0
  132. package/build/src/relations/define_relations_config.d.ts.map +1 -0
  133. package/build/src/relations/define_relations_config.js +173 -0
  134. package/build/src/relations/define_relations_config.js.map +1 -0
  135. package/build/src/relations/manager.d.ts +60 -0
  136. package/build/src/relations/manager.d.ts.map +1 -0
  137. package/build/src/relations/manager.js +213 -0
  138. package/build/src/relations/manager.js.map +1 -0
  139. package/build/src/relations/reconcile.d.ts +111 -0
  140. package/build/src/relations/reconcile.d.ts.map +1 -0
  141. package/build/src/relations/reconcile.js +200 -0
  142. package/build/src/relations/reconcile.js.map +1 -0
  143. package/build/src/relations_config_store.d.ts +22 -0
  144. package/build/src/relations_config_store.d.ts.map +1 -0
  145. package/build/src/relations_config_store.js +74 -0
  146. package/build/src/relations_config_store.js.map +1 -0
  147. package/build/src/scope_outbox.d.ts +69 -0
  148. package/build/src/scope_outbox.d.ts.map +1 -0
  149. package/build/src/scope_outbox.js +298 -0
  150. package/build/src/scope_outbox.js.map +1 -0
  151. package/build/src/{drivers → shared}/backend_guard.d.ts +42 -0
  152. package/build/src/shared/backend_guard.d.ts.map +1 -0
  153. package/build/src/{drivers → shared}/backend_guard.js +78 -1
  154. package/build/src/shared/backend_guard.js.map +1 -0
  155. package/build/src/shared/sql_expiry.d.ts.map +1 -0
  156. package/build/src/shared/sql_expiry.js.map +1 -0
  157. package/build/src/shared/transaction_guard.d.ts +50 -0
  158. package/build/src/shared/transaction_guard.d.ts.map +1 -0
  159. package/build/src/shared/transaction_guard.js +60 -0
  160. package/build/src/shared/transaction_guard.js.map +1 -0
  161. package/build/src/sql_descendants.d.ts +47 -1
  162. package/build/src/sql_descendants.d.ts.map +1 -1
  163. package/build/src/sql_descendants.js +75 -1
  164. package/build/src/sql_descendants.js.map +1 -1
  165. package/build/src/testing/contract.d.ts +129 -4
  166. package/build/src/testing/contract.d.ts.map +1 -1
  167. package/build/src/testing/contract.js +912 -177
  168. package/build/src/testing/contract.js.map +1 -1
  169. package/build/src/testing/main.d.ts +8 -2
  170. package/build/src/testing/main.d.ts.map +1 -1
  171. package/build/src/testing/main.js +4 -1
  172. package/build/src/testing/main.js.map +1 -1
  173. package/build/src/testing/migration_contract.d.ts +284 -0
  174. package/build/src/testing/migration_contract.d.ts.map +1 -0
  175. package/build/src/testing/migration_contract.js +586 -0
  176. package/build/src/testing/migration_contract.js.map +1 -0
  177. package/build/src/testing/relations_contract.d.ts +73 -0
  178. package/build/src/testing/relations_contract.d.ts.map +1 -0
  179. package/build/src/testing/relations_contract.js +1069 -0
  180. package/build/src/testing/relations_contract.js.map +1 -0
  181. package/build/src/testing/relations_reconcile_contract.d.ts +24 -0
  182. package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -0
  183. package/build/src/testing/relations_reconcile_contract.js +220 -0
  184. package/build/src/testing/relations_reconcile_contract.js.map +1 -0
  185. package/build/src/traits/authz_scopes.js +1 -1
  186. package/build/src/traits/authz_scopes.js.map +1 -1
  187. package/build/src/traits/has_uuid.d.ts +8 -8
  188. package/build/src/traits/has_uuid.d.ts.map +1 -1
  189. package/build/src/types.d.ts +1053 -83
  190. package/build/src/types.d.ts.map +1 -1
  191. package/build/src/types.js +10 -0
  192. package/build/src/types.js.map +1 -1
  193. package/build/stubs/config/authorization.stub +104 -4
  194. package/build/stubs/migration.stub +136 -0
  195. package/build/stubs/scopes_outbox_migration.stub +57 -0
  196. package/package.json +4 -2
  197. package/build/commands/openfga_import.d.ts +0 -34
  198. package/build/commands/openfga_import.d.ts.map +0 -1
  199. package/build/commands/openfga_import.js +0 -97
  200. package/build/commands/openfga_import.js.map +0 -1
  201. package/build/src/catalog.d.ts.map +0 -1
  202. package/build/src/catalog.js.map +0 -1
  203. package/build/src/catalog_cache.d.ts.map +0 -1
  204. package/build/src/catalog_cache.js.map +0 -1
  205. package/build/src/drivers/backend_guard.d.ts.map +0 -1
  206. package/build/src/drivers/backend_guard.js.map +0 -1
  207. package/build/src/drivers/sql_expiry.d.ts.map +0 -1
  208. package/build/src/drivers/sql_expiry.js.map +0 -1
  209. package/build/src/middleware/app_access_middleware.d.ts.map +0 -1
  210. package/build/src/middleware/app_access_middleware.js.map +0 -1
  211. /package/build/src/{middleware → http}/app_access_middleware.d.ts +0 -0
  212. /package/build/src/{middleware → http}/app_access_middleware.js +0 -0
  213. /package/build/src/{drivers → shared}/sql_expiry.d.ts +0 -0
  214. /package/build/src/{drivers → shared}/sql_expiry.js +0 -0
@@ -0,0 +1,586 @@
1
+ /**
2
+ * **El contrato de MIGRACIÓN** (3b-3b · B3) — la pieza que convierte «migra»
3
+ * en «migra sin perder nada que no esté declarado».
4
+ *
5
+ * import { runMigrationContract } from '@jantstack/adonis-authz/testing'
6
+ *
7
+ * Se publica junto al resto de la suite de contrato porque un driver de
8
+ * TERCEROS tiene que poder correrlo: el paquete promete migración idempotente
9
+ * y bidireccional entre drivers, y esa promesa no la puede sostener un test
10
+ * privado del paquete.
11
+ *
12
+ * Cómo funciona, y por qué así:
13
+ *
14
+ * 1. **Siembra FIJA** — 7 nodos, 6 holders, 4 roles, 14 grants, 5
15
+ * caducidades y 6 denies, escritos siempre con la API del driver. Fija a
16
+ * propósito: un fixture que cambia con cada corrida no permite comparar
17
+ * dos versiones del paquete, y el juez del panel 2 pedía «un set fijo de
18
+ * preguntas».
19
+ * 2. **448 preguntas idénticas** en origen y destino: 168 `authorize`
20
+ * (6 holders × 7 scopes × 4 permisos), 168 `hasRole` (× 4 roles), 42
21
+ * `listRoles`, 24 `listScopes`, 28 `listSubjects` y 18 `listRoleScopes`.
22
+ * Se preguntan ANTES de migrar sobre el origen y DESPUÉS sobre el
23
+ * destino, y las respuestas tienen que coincidir.
24
+ * 3. **`expectedLosses`** — la migración **no es sin pérdida** (panel 2,
25
+ * requisito 3 del dueño: *«posible con pérdidas declaradas y con
26
+ * ventana»*), así que las pérdidas se declaran DE ANTEMANO y el contrato
27
+ * las cruza en las dos direcciones:
28
+ * - una pérdida declarada tiene que aparecer **contada en
29
+ * `report.skipped`**; si no aparece, el contrato FALLA (una pérdida
30
+ * que nunca ocurre es una línea falsa en el README);
31
+ * - una respuesta que cambia y que NINGUNA pérdida declarada explica
32
+ * hace FALLAR el contrato. Ese es todo el punto: **nunca se ignora
33
+ * ninguna**.
34
+ * 4. **El CENSO de la siembra** (lote 3b-4 · C1) — y esto es lo que hace
35
+ * que el punto 3 sea una garantía y no un formulario. Las dos caras de
36
+ * `expectedLosses` cruzan `Object.keys(report.skipped)`, o sea **lo que
37
+ * el driver se auto-declara**: cierran las omisiones DESCUIDADAS, no las
38
+ * silenciosas. Un driver que tira un hecho sin contarlo no puebla
39
+ * `skipped` y, si esa pérdida no mueve ninguna de las 448, pasaba.
40
+ * Medido, y no es teórico: los denies solo se observan por `authorize`,
41
+ * que no distingue un deny en su sitio de uno reubicado a otro scope de
42
+ * la misma cadena.
43
+ * El censo no le pregunta al driver qué se dejó: mira el destino **hecho
44
+ * a hecho** (los 20 de la siembra: 14 asignaciones + 6 denies) por el
45
+ * camino DIRECTO del puerto —`listRoles`/`listDenies`, invariante 7— y
46
+ * una ausencia sin motivo declarado **y contado** hace FALLAR el
47
+ * contrato. `listDenies` es opcional en el puerto: un driver que no lo
48
+ * traiga deja sus denies observados solo por `authorize`, y el veredicto
49
+ * lo dice en `censusLimits` en vez de callárselo.
50
+ * 5. **El CRUCE DE CADUCIDADES** — ninguna de las 448 devuelve un
51
+ * `expiresAt` y el contrato no adelanta ningún reloj, así que perder la
52
+ * caducidad de un grant VIVO (convertirlo en permanente: fail-OPEN) era
53
+ * invisible. Se cruza por el único camino de solo-lectura-efectiva que
54
+ * hay en el puerto: `grant` con `expiresAt` OMITIDO devuelve
55
+ * `previousExpiresAt` (invariante 10).
56
+ * 6. **Tres combinaciones**: ida, vuelta e ida-y-vuelta (con `--prune`, que
57
+ * es la que demuestra que el viaje redondo no inventa ni pierde).
58
+ *
59
+ * **El límite de `a→b→a`, dicho en voz alta** (tester Fase 3b · M3): las 448
60
+ * de la vuelta se le preguntan al ORIGEN, y **nadie lo vacía** entre los dos
61
+ * tramos. Así que esa combinación observa lo que el tramo de vuelta DESTRUYE
62
+ * (un `--prune` que se lleva de más) y **no** lo que deja de escribir: con el
63
+ * origen ya lleno, «todo `unchanged`» es la respuesta correcta y un tramo
64
+ * omisivo es indistinguible de uno bueno. Quien migra de verdad (vacía el
65
+ * origen y lo reconstruye) está cubierto por las combinaciones `a→b` y `b→a`,
66
+ * que sí preguntan al destino recién llenado. Cerrar el hueco pide un gancho
67
+ * nuevo en el harness («vacía los hechos de este extremo»), que es una
68
+ * decisión del dueño y no se toma aquí.
69
+ *
70
+ * El motor está separado del registro de casos (`runMigrationDirection` /
71
+ * `runMigrationContract`) para que el propio paquete pueda comprobar que el
72
+ * contrato **sabe fallar**: un contrato que no falla no es una garantía.
73
+ */
74
+ import { test } from '@japa/runner';
75
+ import { v7 as uuidv7 } from 'uuid';
76
+ import { APP_SCOPE } from '../types.js';
77
+ import { scopeKey } from '../identity.js';
78
+ import { memoryScopeTree } from './scope_tree.js';
79
+ /* ── La siembra FIJA ─────────────────────────────────────────────────────── */
80
+ /** Los 4 permisos del contrato de migración. `admin:all` no lo lleva ningún rol: hay preguntas que son `false` en todas partes. */
81
+ export const MIGRATION_PERMISSIONS = ['docs:read', 'docs:write', 'billing:read', 'admin:all'];
82
+ /** Los 4 roles, uno por nivel útil (dos a `app`, para que el nivel no sea la única variable). */
83
+ export const MIGRATION_ROLES = ['mig-editor', 'mig-viewer', 'mig-lead', 'mig-auditor'];
84
+ export const MIGRATION_CATALOG = {
85
+ permissions: MIGRATION_PERMISSIONS.map((slug) => ({ slug })),
86
+ roles: [
87
+ { slug: 'mig-editor', scopeType: 'app', permissions: ['docs:read', 'docs:write'] },
88
+ { slug: 'mig-viewer', scopeType: 'organization', permissions: ['docs:read'] },
89
+ { slug: 'mig-lead', scopeType: 'unit', permissions: ['docs:read', 'docs:write', 'billing:read'] },
90
+ { slug: 'mig-auditor', scopeType: 'app', permissions: ['billing:read'] },
91
+ ],
92
+ };
93
+ export function makeMigrationSeed(now = new Date()) {
94
+ const shared = uuidv7();
95
+ return {
96
+ scopes: {
97
+ app: APP_SCOPE,
98
+ org1: { type: 'organization', uuid: uuidv7() },
99
+ org2: { type: 'organization', uuid: uuidv7() },
100
+ unit1: { type: 'unit', uuid: uuidv7() },
101
+ unit2: { type: 'unit', uuid: uuidv7() },
102
+ unit3: { type: 'unit', uuid: uuidv7() },
103
+ unit4: { type: 'unit', uuid: uuidv7() },
104
+ },
105
+ holders: [
106
+ { type: 'users', uuid: uuidv7() },
107
+ { type: 'users', uuid: uuidv7() },
108
+ { type: 'users', uuid: uuidv7() },
109
+ { type: 'users', uuid: shared },
110
+ // Invariante 4: el MISMO uuid con otro morph name jamás se cruza.
111
+ { type: 'admins', uuid: shared },
112
+ { type: 'admins', uuid: uuidv7() },
113
+ ],
114
+ now,
115
+ };
116
+ }
117
+ /** El árbol: 7 nodos con profundidad 4 (`app → org1 → unit1 → unit4`). */
118
+ export async function plantMigrationTree(tree, seed) {
119
+ const s = seed.scopes;
120
+ await tree.attach(s.org1, s.app);
121
+ await tree.attach(s.org2, s.app);
122
+ await tree.attach(s.unit1, s.org1);
123
+ await tree.attach(s.unit2, s.org1);
124
+ await tree.attach(s.unit3, s.org2);
125
+ await tree.attach(s.unit4, s.unit1);
126
+ }
127
+ /**
128
+ * **Los 14 grants, en una tabla** — para que la siembra y el CRUCE DE
129
+ * CADUCIDADES salgan del mismo sitio: dos listas paralelas se separan al
130
+ * primer cambio y el cruce dejaría de comprobar lo que se sembró.
131
+ */
132
+ export function migrationGrants(seed) {
133
+ const s = seed.scopes;
134
+ const [u1, u2, u3, u4, a1, a2] = seed.holders;
135
+ const soon = new Date(seed.now.getTime() + 3_600_000);
136
+ const later = new Date(seed.now.getTime() + 7_200_000);
137
+ const past = new Date(seed.now.getTime() - 3_600_000);
138
+ return [
139
+ { holder: u1, role: 'mig-editor', scope: s.app },
140
+ { holder: u1, role: 'mig-viewer', scope: s.org2 },
141
+ { holder: u2, role: 'mig-viewer', scope: s.org1 },
142
+ { holder: u2, role: 'mig-lead', scope: s.unit3, expiresAt: soon },
143
+ { holder: u3, role: 'mig-lead', scope: s.unit1 },
144
+ { holder: u3, role: 'mig-lead', scope: s.unit2, expiresAt: later },
145
+ // La caducada: existe en el origen y NO concede. Es la pérdida `expired`.
146
+ { holder: u3, role: 'mig-auditor', scope: s.app, expiresAt: past, expired: true },
147
+ { holder: u4, role: 'mig-lead', scope: s.unit4 },
148
+ { holder: u4, role: 'mig-viewer', scope: s.org1, expiresAt: later },
149
+ { holder: a1, role: 'mig-editor', scope: s.app },
150
+ { holder: a1, role: 'mig-lead', scope: s.unit1 },
151
+ { holder: a2, role: 'mig-viewer', scope: s.org2 },
152
+ { holder: a2, role: 'mig-auditor', scope: s.app },
153
+ { holder: u2, role: 'mig-lead', scope: s.unit4, expiresAt: soon },
154
+ ];
155
+ }
156
+ /**
157
+ * **Los 6 denies, en una tabla** — misma razón que los grants: el CENSO
158
+ * (abajo) tiene que preguntar por lo que se sembró, y dos listas paralelas se
159
+ * separan al primer cambio.
160
+ */
161
+ export function migrationDenies(seed) {
162
+ const s = seed.scopes;
163
+ const [u1, u2, u3, u4, a1, a2] = seed.holders;
164
+ return [
165
+ { holder: u1, permission: 'docs:write', scope: s.org2 },
166
+ { holder: u2, permission: 'docs:read', scope: s.unit3 },
167
+ { holder: u3, permission: 'docs:write', scope: s.unit1 },
168
+ { holder: u4, permission: 'billing:read', scope: s.app },
169
+ { holder: a1, permission: 'docs:read', scope: s.unit1 },
170
+ { holder: a2, permission: 'billing:read', scope: s.org2 },
171
+ ];
172
+ }
173
+ export async function plantMigrationFacts(driver, seed) {
174
+ for (const g of migrationGrants(seed)) {
175
+ await driver.grant(g.holder, g.role, g.scope, g.expiresAt ? { expiresAt: g.expiresAt } : {});
176
+ }
177
+ for (const d of migrationDenies(seed)) {
178
+ await driver.deny(d.holder, d.permission, d.scope);
179
+ }
180
+ }
181
+ /** Los 20 hechos de la siembra (14 asignaciones + 6 denies), en un solo sitio. */
182
+ export function migrationFacts(seed) {
183
+ const facts = migrationGrants(seed).map((g) => ({
184
+ kind: 'assignment',
185
+ holder: g.holder,
186
+ scope: g.scope,
187
+ name: g.role,
188
+ // La caducada NO llega al destino, y eso está declarado: es la pérdida
189
+ // `expired`. Cualquier otra ausencia es un fallo.
190
+ ...(g.expired ? { expectedLoss: 'expired' } : {}),
191
+ }));
192
+ for (const d of migrationDenies(seed)) {
193
+ facts.push({ kind: 'deny', holder: d.holder, scope: d.scope, name: d.permission });
194
+ }
195
+ return facts;
196
+ }
197
+ /** Cómo se nombra un hecho en el informe del contrato. */
198
+ export function describeMigrationFact(fact) {
199
+ return `${fact.kind === 'deny' ? 'deny' : 'grant'} ${tag(fact.holder)} ${fact.name} @ ${scopeTag(fact.scope)}`;
200
+ }
201
+ /**
202
+ * **El censo** (lote 3b-4 · C1): pregunta al destino, hecho a hecho, si lo
203
+ * que se sembró está. Se lee por el camino DIRECTO del puerto —invariante 7,
204
+ * hechos directos del scope exacto—: `listRoles` para las asignaciones y
205
+ * `listDenies` para los denies. No mira `report.skipped`, no compara
206
+ * respuestas y no depende de que la pérdida cambie ninguna de las 448.
207
+ *
208
+ * `listDenies` es OPCIONAL en el puerto: un driver que no lo trae deja sus
209
+ * denies censados solo por `authorize` (lo dice `limits`, y está escrito en
210
+ * el README). Los dos drivers del paquete lo implementan.
211
+ */
212
+ export async function censusMigrationFacts(driver, seed) {
213
+ const present = [];
214
+ const missing = [];
215
+ const limits = [];
216
+ let denyReadable = typeof driver.listDenies === 'function';
217
+ if (!denyReadable) {
218
+ limits.push('este driver no implementa `listDenies`, así que los 6 denies de la siembra no se pueden ' +
219
+ 'censar uno a uno: solo los observa `authorize`, que no los ve donde no bloquean nada.');
220
+ }
221
+ for (const fact of migrationFacts(seed)) {
222
+ if (fact.kind === 'assignment') {
223
+ const roles = await driver.listRoles(fact.holder, fact.scope);
224
+ (roles.includes(fact.name) ? present : missing).push(fact);
225
+ continue;
226
+ }
227
+ if (!denyReadable)
228
+ continue;
229
+ try {
230
+ const denies = await driver.listDenies(fact.holder, fact.scope);
231
+ (denies.some((deny) => deny.permission === fact.name) ? present : missing).push(fact);
232
+ }
233
+ catch (error) {
234
+ // `listDenies: false` declarado con 500 `E_AUTHZ_UNSUPPORTED`: es la
235
+ // misma respuesta que no traerlo, y se dice igual.
236
+ if (error?.code !== 'E_AUTHZ_UNSUPPORTED')
237
+ throw error;
238
+ denyReadable = false;
239
+ limits.push('este driver responde 500 `E_AUTHZ_UNSUPPORTED` a `listDenies`, así que los denies de la ' +
240
+ 'siembra no se censan uno a uno: solo los observa `authorize`.');
241
+ }
242
+ }
243
+ return { present, missing, limits };
244
+ }
245
+ /* ── Las 448 preguntas ───────────────────────────────────────────────────── */
246
+ function tag(subject) {
247
+ return `${subject.type}:${subject.uuid}`;
248
+ }
249
+ function scopeTag(scope) {
250
+ return scopeKey(scope);
251
+ }
252
+ function scopeList(scopes) {
253
+ return scopes.map(scopeTag).sort().join(',');
254
+ }
255
+ function subjectList(subjects) {
256
+ return subjects.map(tag).sort().join(',');
257
+ }
258
+ /**
259
+ * Las 448: **168 + 168 + 42 + 24 + 28 + 18**. No es un número redondo por
260
+ * casualidad — es el producto de la siembra fija, y por eso el contrato
261
+ * puede afirmar «448 preguntas idénticas» y no «unas cuantas».
262
+ */
263
+ export function migrationQuestions(seed) {
264
+ const s = seed.scopes;
265
+ const scopes = [s.app, s.org1, s.org2, s.unit1, s.unit2, s.unit3, s.unit4];
266
+ const holders = seed.holders;
267
+ const questions = [];
268
+ for (const holder of holders) {
269
+ for (const scope of scopes) {
270
+ for (const permission of MIGRATION_PERMISSIONS) {
271
+ questions.push({
272
+ id: `authorize(${tag(holder)}, ${permission}, ${scopeTag(scope)})`,
273
+ kind: 'authorize',
274
+ ask: async (driver) => String(await driver.authorize(holder, permission, scope)),
275
+ });
276
+ }
277
+ }
278
+ }
279
+ for (const holder of holders) {
280
+ for (const scope of scopes) {
281
+ for (const role of MIGRATION_ROLES) {
282
+ questions.push({
283
+ id: `hasRole(${tag(holder)}, ${role}, ${scopeTag(scope)})`,
284
+ kind: 'hasRole',
285
+ ask: async (driver) => String(await driver.hasRole(holder, role, scope)),
286
+ });
287
+ }
288
+ }
289
+ }
290
+ for (const holder of holders) {
291
+ for (const scope of scopes) {
292
+ questions.push({
293
+ id: `listRoles(${tag(holder)}, ${scopeTag(scope)})`,
294
+ kind: 'listRoles',
295
+ ask: async (driver) => [...(await driver.listRoles(holder, scope))].sort().join(','),
296
+ });
297
+ }
298
+ }
299
+ for (const holder of holders) {
300
+ for (const permission of MIGRATION_PERMISSIONS) {
301
+ questions.push({
302
+ id: `listScopes(${tag(holder)}, ${permission})`,
303
+ kind: 'listScopes',
304
+ ask: async (driver) => scopeList(await driver.listScopes(holder, permission)),
305
+ });
306
+ }
307
+ }
308
+ for (const role of MIGRATION_ROLES) {
309
+ for (const scope of scopes) {
310
+ questions.push({
311
+ id: `listSubjects(${role}, ${scopeTag(scope)})`,
312
+ kind: 'listSubjects',
313
+ ask: async (driver) => subjectList(await driver.listSubjects(role, scope)),
314
+ });
315
+ }
316
+ }
317
+ for (const holder of holders) {
318
+ for (const scopeType of ['app', 'organization', 'unit']) {
319
+ questions.push({
320
+ id: `listRoleScopes(${tag(holder)}, ${scopeType})`,
321
+ kind: 'listRoleScopes',
322
+ ask: async (driver) => scopeList(await driver.listRoleScopes(holder, scopeType)),
323
+ });
324
+ }
325
+ }
326
+ return questions;
327
+ }
328
+ /** Cuántas preguntas tiene el set fijo. Es una CIFRA del contrato, no un detalle. */
329
+ export const MIGRATION_QUESTION_COUNT = 448;
330
+ function reasonsOf(reports) {
331
+ const out = new Set();
332
+ for (const report of reports)
333
+ for (const reason of Object.keys(report.skipped))
334
+ out.add(reason);
335
+ return out;
336
+ }
337
+ /**
338
+ * Corre UNA combinación de punta a punta y devuelve el veredicto. Es el
339
+ * motor: `runMigrationContract` solo lo envuelve en tres casos de Japa, y el
340
+ * paquete lo usa directamente para demostrar que el contrato **sabe fallar**.
341
+ */
342
+ export async function runMigrationDirection(harness, direction) {
343
+ await harness.cleanup();
344
+ await harness.seedCatalog(MIGRATION_CATALOG);
345
+ const tree = harness.makeTree ? await harness.makeTree() : memoryScopeTree();
346
+ const { reconcile, drivers } = await harness.setup(tree);
347
+ const seed = makeMigrationSeed();
348
+ await plantMigrationTree(tree, seed);
349
+ const origin = direction === 'b→a' ? harness.b : harness.a;
350
+ const other = origin === harness.a ? harness.b : harness.a;
351
+ await plantMigrationFacts(drivers[origin], seed);
352
+ const questions = migrationQuestions(seed);
353
+ const before = new Map();
354
+ for (const question of questions)
355
+ before.set(question.id, await question.ask(drivers[origin]));
356
+ const reports = [];
357
+ const failures = [];
358
+ const mismatches = [];
359
+ const explains = (question) => harness.expectedLosses.find((candidate) => (candidate.directions ?? ['a→b', 'b→a', 'a→b→a']).includes(direction) &&
360
+ candidate.changesAnswer?.(question) === true) ?? null;
361
+ /** Compara las 448 contra UN extremo y apunta lo que cambió sin explicación. */
362
+ const compareAgainst = async (driverKey, label) => {
363
+ for (const question of questions) {
364
+ const after = await question.ask(drivers[driverKey]);
365
+ const was = before.get(question.id);
366
+ if (after === was)
367
+ continue;
368
+ const loss = explains(question);
369
+ const id = label ? `${label} ${question.id}` : question.id;
370
+ mismatches.push({ question: id, before: was, after, explainedBy: loss?.reason ?? null });
371
+ if (!loss) {
372
+ failures.push(`[${direction}] la respuesta CAMBIÓ y no hay pérdida declarada que lo explique: ` +
373
+ `${id} — antes '${was}', después '${after}'`);
374
+ }
375
+ }
376
+ };
377
+ /**
378
+ * **Un tramo tiene que HACER algo** (tester Fase 3b · M3). Sin esto, en
379
+ * `a→b→a` el tramo de vuelta podía no ejecutarse siquiera: como las
380
+ * preguntas se le hacen al ORIGEN —que nadie vacía—, un tramo de vuelta que
381
+ * no escribe, no borra y no lee NADA es indistinguible de uno correcto y
382
+ * las 448 salen idénticas. Medido: quitando el `reconcile` de vuelta la
383
+ * suite entera seguía en verde.
384
+ */
385
+ const legDidSomething = (report, leg) => {
386
+ const seen = report.written + report.updated + report.unchanged + report.extra + report.deleted;
387
+ if (seen > 0)
388
+ return;
389
+ failures.push(`[${direction}] el tramo ${leg} no tocó NI UNA tupla (written/updated/unchanged/extra/deleted todo a cero). ` +
390
+ `Una migración que no mira nada no es una migración: comprueba el origen, el destino y el --from.`);
391
+ };
392
+ /* ── El CENSO de la siembra (lote 3b-4 · C1) ─────────────────────────
393
+ *
394
+ * `expectedLosses` cruzaba `Object.keys(report.skipped)`, o sea **lo que el
395
+ * propio driver se auto-declara**: cerraba las omisiones DESCUIDADAS y no
396
+ * las silenciosas. Un driver que tira un hecho sin contarlo no puebla
397
+ * `skipped`, y si esa pérdida no mueve ninguna de las 448 —los denies solo
398
+ * se observan por `authorize`, y `authorize` no ve un deny reubicado dentro
399
+ * de la misma cadena— el contrato pasaba.
400
+ *
401
+ * El censo no pregunta al driver qué se dejó: **mira el destino hecho a
402
+ * hecho** por el camino DIRECTO del puerto y compara con lo que el propio
403
+ * contrato sembró. Una ausencia sin motivo DECLARADO **y CONTADO** es un
404
+ * fallo, cuente el driver lo que cuente.
405
+ */
406
+ const silentLosses = [];
407
+ const censusLimits = [];
408
+ const censusAt = async (driverKey, label) => {
409
+ const census = await censusMigrationFacts(drivers[driverKey], seed);
410
+ for (const limit of census.limits)
411
+ if (!censusLimits.includes(limit))
412
+ censusLimits.push(limit);
413
+ const seen = reasonsOf(reports);
414
+ const known = new Set(harness.expectedLosses
415
+ .filter((loss) => (loss.directions ?? ['a→b', 'b→a', 'a→b→a']).includes(direction))
416
+ .map((loss) => loss.reason));
417
+ for (const fact of census.missing) {
418
+ const id = describeMigrationFact(fact);
419
+ if (!fact.expectedLoss) {
420
+ silentLosses.push({ fact: id, at: driverKey });
421
+ failures.push(`[${direction}] PÉRDIDA SILENCIOSA: '${id}' se sembró y '${driverKey}'${label} no lo tiene. ` +
422
+ `No hay ninguna pérdida declarada que lo cubra y el driver TAMPOCO lo contó en report.skipped ` +
423
+ `(motivos vistos: ${[...seen].sort().join(', ') || 'ninguno'}). Que las 448 respuestas no se ` +
424
+ `muevan no lo salva: un hecho que desaparece sin contarse es exactamente lo que la migración ` +
425
+ `no puede hacer.`);
426
+ continue;
427
+ }
428
+ if (!known.has(fact.expectedLoss)) {
429
+ failures.push(`[${direction}] '${id}' no está en '${driverKey}'${label} y el contrato lo atribuye a la pérdida ` +
430
+ `'${fact.expectedLoss}', que este harness NO declara en expectedLosses.`);
431
+ continue;
432
+ }
433
+ if (!seen.has(fact.expectedLoss)) {
434
+ failures.push(`[${direction}] '${id}' no está en '${driverKey}'${label}: la pérdida '${fact.expectedLoss}' ` +
435
+ `OCURRIÓ y el driver no la contó en report.skipped. Perderla está declarado; perderla en ` +
436
+ `silencio, no.`);
437
+ }
438
+ }
439
+ };
440
+ reports.push(await reconcile({ to: other, from: origin }));
441
+ legDidSomething(reports[0], `${origin} → ${other}`);
442
+ // La ida y vuelta lleva `--prune`: es la única forma de comprobar que el
443
+ // viaje redondo no deja de MÁS en el origen (y de ver que lo que se lleva
444
+ // por delante es exactamente una pérdida DECLARADA).
445
+ if (direction === 'a→b→a') {
446
+ // Y el INTERMEDIO también se pregunta: si no, el tramo de ida podría
447
+ // haberse dejado media siembra y la vuelta —que ni siquiera necesita
448
+ // escribir, porque el origen sigue lleno— lo taparía.
449
+ await compareAgainst(other, `[intermedio ${other}]`);
450
+ await censusAt(other, ' (intermedio)');
451
+ reports.push(await reconcile({ to: origin, from: other, prune: true }));
452
+ legDidSomething(reports[1], `${other} → ${origin} (--prune)`);
453
+ }
454
+ const asked = direction === 'a→b→a' ? origin : other;
455
+ await compareAgainst(asked, '');
456
+ await censusAt(asked, '');
457
+ // **Las dos caras, y las dos son obligatorias.**
458
+ //
459
+ // (i) Todo lo que la pasada dejó fuera —cada motivo de `report.skipped`—
460
+ // tiene que estar DECLARADO. Es la mitad que hace del contrato una
461
+ // garantía y no un adorno: sin ella, un driver puede saltarse lo que
462
+ // quiera mientras no cambie ninguna de las 448 respuestas de ESTA
463
+ // siembra, que es justo la clase de bug que una siembra fija no ve.
464
+ // «Nunca se ignora ninguna» significa esto.
465
+ const counted = reasonsOf(reports);
466
+ const declared = new Set(harness.expectedLosses
467
+ .filter((loss) => (loss.directions ?? ['a→b', 'b→a', 'a→b→a']).includes(direction))
468
+ .map((loss) => loss.reason));
469
+ for (const reason of [...counted].sort()) {
470
+ if (declared.has(reason))
471
+ continue;
472
+ failures.push(`[${direction}] la pasada NO migró algo por '${reason}' y esa pérdida no está declarada en ` +
473
+ `expectedLosses. Declárala (con su motivo medido) o arregla la migración: una pérdida que no ` +
474
+ `está escrita es una pérdida silenciosa.`);
475
+ }
476
+ // (ii) Y al revés: una pérdida declarada tiene que OCURRIR y salir contada.
477
+ // Si no, es una línea falsa en el README, y el README es el contrato
478
+ // con el consumidor.
479
+ const declaredButAbsent = [];
480
+ for (const loss of harness.expectedLosses) {
481
+ if (!(loss.directions ?? ['a→b', 'b→a', 'a→b→a']).includes(direction))
482
+ continue;
483
+ if (counted.has(loss.reason))
484
+ continue;
485
+ declaredButAbsent.push(loss.reason);
486
+ failures.push(`[${direction}] la pérdida declarada '${loss.reason}' NO aparece contada en report.skipped ` +
487
+ `(motivos vistos: ${[...counted].sort().join(', ') || 'ninguno'}). Una pérdida que nunca ocurre ` +
488
+ `no se declara: se borra.`);
489
+ }
490
+ /* ── El CRUCE DE CADUCIDADES (tester Fase 3b · M1) ────────────────────
491
+ *
492
+ * Ninguna de las 448 preguntas devuelve un `expiresAt`, y no hay reloj que
493
+ * adelantar: una migración que se deja por el camino la caducidad de un
494
+ * grant VIVO —lo convierte en permanente— responde exactamente lo mismo a
495
+ * las 448 y no cuenta nada en `skipped`. Medido: con
496
+ * `reconcile --to=database` escribiendo `expires_at: null`, las TRES
497
+ * combinaciones seguían en VERDE. Es la pérdida de datos que el contrato
498
+ * decía cortar y no cortaba, y además es fail-OPEN (un permiso temporal que
499
+ * ya no caduca).
500
+ *
501
+ * Se cruza por el ÚNICO camino del puerto que devuelve una caducidad sin
502
+ * inventar un método nuevo: `grant` con `expiresAt` OMITIDO devuelve
503
+ * `previousExpiresAt` (invariante 10, «omitido preserva»). Va DESPUÉS de
504
+ * las 448 —es una escritura, aunque idempotente y sin cambio de estado— y
505
+ * por eso no puede alterar ninguna respuesta ya medida.
506
+ */
507
+ const expiryMismatches = [];
508
+ const stamp = (value) => value === undefined ? 'ausente' : value === null ? 'sin caducidad' : value.toISOString();
509
+ const crossExpiries = async (driverKey, label) => {
510
+ for (const g of migrationGrants(seed)) {
511
+ // La caducada es la pérdida declarada: en el destino no está, y `grant`
512
+ // con `{}` la REVIVIRÍA (invariante 10). No se cruza.
513
+ if (g.expired)
514
+ continue;
515
+ const outcome = await drivers[driverKey].grant(g.holder, g.role, g.scope, {});
516
+ const after = stamp(outcome.existed ? (outcome.previousExpiresAt ?? null) : undefined);
517
+ const was = stamp(g.expiresAt ?? null);
518
+ if (after === was)
519
+ continue;
520
+ const id = `${tag(g.holder)} ${g.role} @ ${scopeTag(g.scope)}`;
521
+ expiryMismatches.push({ grant: `${driverKey}${label} ${id}`, before: was, after });
522
+ failures.push(`[${direction}] la CADUCIDAD no sobrevivió a la migración: ${id} en '${driverKey}'${label} ` +
523
+ `— antes '${was}', después '${after}'. Ninguna de las ${MIGRATION_QUESTION_COUNT} ` +
524
+ `preguntas lo ve (no devuelven caducidades) y perderla es fail-OPEN: un permiso temporal que ya no caduca.`);
525
+ }
526
+ };
527
+ // El INTERMEDIO también se cruza (lote 3b-4 · C1): en `a→b→a` las 448 y el
528
+ // cruce se le hacen al ORIGEN, que nadie vacía, así que una caducidad que
529
+ // el tramo de IDA se dejó quedaba tapada. Se hace DESPUÉS del segundo
530
+ // tramo a propósito: `grant` con `{}` es una escritura y crearía en el
531
+ // intermedio el hecho que falta, falseando la pasada de vuelta.
532
+ if (direction === 'a→b→a')
533
+ await crossExpiries(other, ' (intermedio)');
534
+ await crossExpiries(asked, '');
535
+ // Los TRAMOS que la combinación promete: `a→b→a` son DOS pasadas, no una.
536
+ // Es la comprobación barata que delata un motor —o un harness— al que se le
537
+ // ha caído un tramo por el camino (tester Fase 3b · M3).
538
+ const expectedLegs = direction === 'a→b→a' ? 2 : 1;
539
+ if (reports.length !== expectedLegs) {
540
+ failures.push(`[${direction}] la combinación son ${expectedLegs} pasada(s) de reconcile y se ejecutaron ${reports.length}`);
541
+ }
542
+ if (questions.length !== MIGRATION_QUESTION_COUNT) {
543
+ failures.push(`[${direction}] el set fijo tiene ${questions.length} preguntas y no ${MIGRATION_QUESTION_COUNT}`);
544
+ }
545
+ return {
546
+ direction,
547
+ reports,
548
+ questions: questions.length,
549
+ mismatches,
550
+ declaredButAbsent,
551
+ expiryMismatches,
552
+ silentLosses,
553
+ censusLimits,
554
+ failures,
555
+ };
556
+ }
557
+ /**
558
+ * Registra las tres combinaciones como casos de Japa. Llámala en el TOP LEVEL
559
+ * del spec (Japa descarta los grupos registrados tarde).
560
+ */
561
+ export function runMigrationContract(harness) {
562
+ return registerMigrationContract(harness, {
563
+ group: (title, define) => test.group(title, define),
564
+ test: (title, fn) => test(title, fn),
565
+ });
566
+ }
567
+ export function registerMigrationContract(harness, api) {
568
+ api.group(`migration contract [${harness.name}]`, (group) => {
569
+ group.teardown(async () => {
570
+ await harness.cleanup();
571
+ });
572
+ for (const direction of ['a→b', 'b→a', 'a→b→a']) {
573
+ const label = direction === 'a→b'
574
+ ? `${harness.a} → ${harness.b}`
575
+ : direction === 'b→a'
576
+ ? `${harness.b} → ${harness.a}`
577
+ : `${harness.a} → ${harness.b} → ${harness.a} (--prune)`;
578
+ api.test(`${MIGRATION_QUESTION_COUNT} preguntas idénticas, ${label}: las respuestas coinciden y toda pérdida está declarada`, async ({ assert }) => {
579
+ const verdict = await runMigrationDirection(harness, direction);
580
+ assert.equal(verdict.questions, MIGRATION_QUESTION_COUNT);
581
+ assert.deepEqual(verdict.failures, []);
582
+ })?.timeout(600_000);
583
+ }
584
+ });
585
+ }
586
+ //# sourceMappingURL=migration_contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration_contract.js","sourceRoot":"","sources":["../../../src/testing/migration_contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAA;AAEnC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AA4DjD,gFAAgF;AAEhF,mIAAmI;AACnI,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,CAAU,CAAA;AAEtG,iGAAiG;AACjG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,CAAU,CAAA;AAE/F,MAAM,CAAC,MAAM,iBAAiB,GAAgB;IAC5C,WAAW,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,EAAE;QACL,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE;QAClF,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,WAAW,CAAC,EAAE;QAC7E,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE;QACjG,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,cAAc,CAAC,EAAE;KACzE;CACF,CAAA;AAUD,MAAM,UAAU,iBAAiB,CAAC,MAAY,IAAI,IAAI,EAAE;IACtD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAA;IACvB,OAAO;QACL,MAAM,EAAE;YACN,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YAC9C,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YAC9C,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;SACxC;QACD,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACjC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACjC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;YACjC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE;YAC/B,kEAAkE;YAClE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE;YAChC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;SACnC;QACD,GAAG;KACJ,CAAA;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAuB,EAAE,IAAmB;IACnF,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;IACrB,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;IAChC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;IAChC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;IAClC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;IAClC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;IAClC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;AACrC,CAAC;AAyBD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAA;IAC7C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,CAAA;IACrD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,CAAA;IACtD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,CAAA;IACrD,OAAO;QACL,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE;QAChD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;QACjD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;QACjD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE;QACjE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;QAChD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE;QAClE,0EAA0E;QAC1E,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;QACjF,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;QAChD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE;QACnE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE;QAChD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;QAChD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;QACjD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE;QACjD,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE;KAClE,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAA;IAC7C,OAAO;QACL,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;QACvD,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;QACvD,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;QACxD,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE;QACxD,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;QACvD,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;KAC1D,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAA2B,EAAE,IAAmB;IACxF,KAAK,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC9F,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;IACpD,CAAC;AACH,CAAC;AAwBD,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,MAAM,KAAK,GAAoB,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,EAAE,YAAqB;QAC3B,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,uEAAuE;QACvE,kDAAkD;QAClD,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC,CAAC,CAAA;IACH,KAAK,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAA;IACpF,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,qBAAqB,CAAC,IAAmB;IACvD,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,MAAM,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAA;AAChH,CAAC;AASD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAA2B,EAC3B,IAAmB;IAEnB,MAAM,OAAO,GAAoB,EAAE,CAAA;IACnC,MAAM,OAAO,GAAoB,EAAE,CAAA;IACnC,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,YAAY,GAAG,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,CAAA;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CACT,0FAA0F;YACxF,uFAAuF,CAC1F,CAAA;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAC5D;YAAA,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC3D,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,YAAY;YAAE,SAAQ;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAC/D;YAAA,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxF,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,qEAAqE;YACrE,mDAAmD;YACnD,IAAI,KAAK,EAAE,IAAI,KAAK,qBAAqB;gBAAE,MAAM,KAAK,CAAA;YACtD,YAAY,GAAG,KAAK,CAAA;YACpB,MAAM,CAAC,IAAI,CACT,0FAA0F;gBACxF,+DAA+D,CAClE,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;AACrC,CAAC;AAED,gFAAgF;AAEhF,SAAS,GAAG,CAAC,OAAmB;IAC9B,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,CAAA;AAC1C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAe;IAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC;AAED,SAAS,SAAS,CAAC,MAAkB;IACnC,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9C,CAAC;AAED,SAAS,WAAW,CAAC,QAAsB;IACzC,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAmB;IACpD,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;IACrB,MAAM,MAAM,GAAe,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;IACtF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;IAC5B,MAAM,SAAS,GAAwB,EAAE,CAAA;IAEzC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,UAAU,IAAI,qBAAqB,EAAE,CAAC;gBAC/C,SAAS,CAAC,IAAI,CAAC;oBACb,EAAE,EAAE,aAAa,GAAG,CAAC,MAAM,CAAC,KAAK,UAAU,KAAK,QAAQ,CAAC,KAAK,CAAC,GAAG;oBAClE,IAAI,EAAE,WAAW;oBACjB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;iBACjF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;gBACnC,SAAS,CAAC,IAAI,CAAC;oBACb,EAAE,EAAE,WAAW,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,QAAQ,CAAC,KAAK,CAAC,GAAG;oBAC1D,IAAI,EAAE,SAAS;oBACf,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;iBACzE,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC;gBACb,EAAE,EAAE,aAAa,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,KAAK,CAAC,GAAG;gBACnD,IAAI,EAAE,WAAW;gBACjB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;aACrF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,UAAU,IAAI,qBAAqB,EAAE,CAAC;YAC/C,SAAS,CAAC,IAAI,CAAC;gBACb,EAAE,EAAE,cAAc,GAAG,CAAC,MAAM,CAAC,KAAK,UAAU,GAAG;gBAC/C,IAAI,EAAE,YAAY;gBAClB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;aAC9E,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC;gBACb,EAAE,EAAE,gBAAgB,IAAI,KAAK,QAAQ,CAAC,KAAK,CAAC,GAAG;gBAC/C,IAAI,EAAE,cAAc;gBACpB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;aAC3E,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,SAAS,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC;YACxD,SAAS,CAAC,IAAI,CAAC;gBACb,EAAE,EAAE,kBAAkB,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS,GAAG;gBAClD,IAAI,EAAE,gBAAgB;gBACtB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;aACjF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AA2B3C,SAAS,SAAS,CAAC,OAA0B;IAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7B,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/F,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAiC,EACjC,SAA6B;IAE7B,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;IACvB,MAAM,OAAO,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAA;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,CAAA;IAC5E,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACxD,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAA;IAChC,MAAM,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAEpC,MAAM,MAAM,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D,MAAM,KAAK,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D,MAAM,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAA;IAEhD,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IACxC,KAAK,MAAM,QAAQ,IAAI,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAE9F,MAAM,OAAO,GAAsB,EAAE,CAAA;IACrC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,UAAU,GAAmC,EAAE,CAAA;IAErD,MAAM,QAAQ,GAAG,CAAC,QAA2B,EAAE,EAAE,CAC/C,OAAO,CAAC,cAAc,CAAC,IAAI,CACzB,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;QACrE,SAAS,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,KAAK,IAAI,CAC/C,IAAI,IAAI,CAAA;IAEX,gFAAgF;IAChF,MAAM,cAAc,GAAG,KAAK,EAAE,SAAiB,EAAE,KAAa,EAAE,EAAE;QAChE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;YACpD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAE,CAAA;YACpC,IAAI,KAAK,KAAK,GAAG;gBAAE,SAAQ;YAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;YAC/B,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAA;YAC1D,UAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC,CAAA;YACxF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,oEAAoE;oBAC/E,GAAG,EAAE,aAAa,GAAG,eAAe,KAAK,GAAG,CAC/C,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED;;;;;;;OAOG;IACH,MAAM,eAAe,GAAG,CAAC,MAAuB,EAAE,GAAW,EAAE,EAAE;QAC/D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAA;QAC/F,IAAI,IAAI,GAAG,CAAC;YAAE,OAAM;QACpB,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,cAAc,GAAG,+EAA+E;YAC3G,kGAAkG,CACrG,CAAA;IACH,CAAC,CAAA;IAED;;;;;;;;;;;;;OAaG;IACH,MAAM,YAAY,GAAqC,EAAE,CAAA;IACzD,MAAM,YAAY,GAAa,EAAE,CAAA;IACjC,MAAM,QAAQ,GAAG,KAAK,EAAE,SAAiB,EAAE,KAAa,EAAE,EAAE;QAC1D,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAA;QACnE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM;YAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9F,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;QAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB,OAAO,CAAC,cAAc;aACnB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;aAClF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAC9B,CAAA;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAA;YACtC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvB,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;gBAC9C,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,0BAA0B,EAAE,kBAAkB,SAAS,IAAI,KAAK,gBAAgB;oBAC3F,+FAA+F;oBAC/F,oBAAoB,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,kCAAkC;oBAC9F,8FAA8F;oBAC9F,iBAAiB,CACpB,CAAA;gBACD,SAAQ;YACV,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBAClC,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,MAAM,EAAE,iBAAiB,SAAS,IAAI,KAAK,0CAA0C;oBAChG,IAAI,IAAI,CAAC,YAAY,mDAAmD,CAC3E,CAAA;gBACD,SAAQ;YACV,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,MAAM,EAAE,iBAAiB,SAAS,IAAI,KAAK,iBAAiB,IAAI,CAAC,YAAY,IAAI;oBAC5F,0FAA0F;oBAC1F,eAAe,CAClB,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,OAAO,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1D,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,MAAM,KAAK,EAAE,CAAC,CAAA;IAEnD,yEAAyE;IACzE,0EAA0E;IAC1E,qDAAqD;IACrD,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,qEAAqE;QACrE,qEAAqE;QACrE,sDAAsD;QACtD,MAAM,cAAc,CAAC,KAAK,EAAE,eAAe,KAAK,GAAG,CAAC,CAAA;QACpD,MAAM,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAA;QACtC,OAAO,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACvE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,MAAM,MAAM,YAAY,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;IACpD,MAAM,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC/B,MAAM,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAEzB,iDAAiD;IACjD,EAAE;IACF,yEAAyE;IACzE,uEAAuE;IACvE,yEAAyE;IACzE,sEAAsE;IACtE,wEAAwE;IACxE,gDAAgD;IAChD,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,OAAO,CAAC,cAAc;SACnB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;SAClF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAC9B,CAAA;IACD,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAQ;QAClC,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,kCAAkC,MAAM,uCAAuC;YAC1F,8FAA8F;YAC9F,yCAAyC,CAC5C,CAAA;IACH,CAAC;IAED,4EAA4E;IAC5E,0EAA0E;IAC1E,0BAA0B;IAC1B,MAAM,iBAAiB,GAAa,EAAE,CAAA;IACtC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC1C,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,SAAQ;QAC/E,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,SAAQ;QACtC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACnC,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,2BAA2B,IAAI,CAAC,MAAM,yCAAyC;YAC1F,oBAAoB,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,kCAAkC;YACjG,0BAA0B,CAC7B,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,gBAAgB,GAAyC,EAAE,CAAA;IACjE,MAAM,KAAK,GAAG,CAAC,KAA8B,EAAE,EAAE,CAC/C,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAA;IAC1F,MAAM,aAAa,GAAG,KAAK,EAAE,SAAiB,EAAE,KAAa,EAAE,EAAE;QAC/D,KAAK,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,wEAAwE;YACxE,sDAAsD;YACtD,IAAI,CAAC,CAAC,OAAO;gBAAE,SAAQ;YACvB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAC7E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACtF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAA;YACtC,IAAI,KAAK,KAAK,GAAG;gBAAE,SAAQ;YAC3B,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAA;YAC9D,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,GAAG,KAAK,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;YAClF,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,gDAAgD,EAAE,QAAQ,SAAS,IAAI,KAAK,GAAG;gBAC1F,YAAY,GAAG,eAAe,KAAK,qBAAqB,wBAAwB,GAAG;gBACnF,2GAA2G,CAC9G,CAAA;QACH,CAAC;IACH,CAAC,CAAA;IACD,2EAA2E;IAC3E,0EAA0E;IAC1E,sEAAsE;IACtE,uEAAuE;IACvE,gEAAgE;IAChE,IAAI,SAAS,KAAK,OAAO;QAAE,MAAM,aAAa,CAAC,KAAK,EAAE,eAAe,CAAC,CAAA;IACtE,MAAM,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAE9B,0EAA0E;IAC1E,4EAA4E;IAC5E,yDAAyD;IACzD,MAAM,YAAY,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAClD,IAAI,OAAO,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CACX,IAAI,SAAS,wBAAwB,YAAY,2CAA2C,OAAO,CAAC,MAAM,EAAE,CAC7G,CAAA;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,wBAAwB,EAAE,CAAC;QAClD,QAAQ,CAAC,IAAI,CAAC,IAAI,SAAS,uBAAuB,SAAS,CAAC,MAAM,mBAAmB,wBAAwB,EAAE,CAAC,CAAA;IAClH,CAAC;IAED,OAAO;QACL,SAAS;QACT,OAAO;QACP,SAAS,EAAE,SAAS,CAAC,MAAM;QAC3B,UAAU;QACV,iBAAiB;QACjB,gBAAgB;QAChB,YAAY;QACZ,YAAY;QACZ,QAAQ;KACT,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAiC;IACpE,OAAO,yBAAyB,CAAC,OAAO,EAAE;QACxC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAa,CAAC;QAC1D,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAS,CAAC;KAC5C,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAiC,EAAE,GAAoB;IAC/F,GAAG,CAAC,KAAK,CAAC,uBAAuB,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1D,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YACxB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;QACzB,CAAC,CAAC,CAAA;QAEF,KAAK,MAAM,SAAS,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAU,EAAE,CAAC;YACzD,MAAM,KAAK,GACT,SAAS,KAAK,KAAK;gBACjB,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,EAAE;gBAC/B,CAAC,CAAC,SAAS,KAAK,KAAK;oBACnB,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,EAAE;oBAC/B,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,YAAY,CAAA;YAC9D,GAAG,CAAC,IAAI,CACN,GAAG,wBAAwB,yBAAyB,KAAK,0DAA0D,EACnH,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBACnB,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;gBAC/D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAA;gBACzD,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;YACxC,CAAC,CACF,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;QACrB,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}