@jantstack/adonis-authz 2.0.0-alpha.1 → 2.4.0-alpha.10
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.
- package/README.md +934 -40
- package/build/commands/authz_catalog_diff.d.ts.map +1 -1
- package/build/commands/authz_catalog_diff.js +1 -2
- package/build/commands/authz_catalog_diff.js.map +1 -1
- package/build/commands/authz_catalog_prune_orphans.d.ts +78 -0
- package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -0
- package/build/commands/authz_catalog_prune_orphans.js +135 -0
- package/build/commands/authz_catalog_prune_orphans.js.map +1 -0
- package/build/commands/authz_catalog_sync.d.ts +17 -0
- package/build/commands/authz_catalog_sync.d.ts.map +1 -1
- package/build/commands/authz_catalog_sync.js +27 -4
- package/build/commands/authz_catalog_sync.js.map +1 -1
- package/build/commands/authz_freeze.d.ts +44 -0
- package/build/commands/authz_freeze.d.ts.map +1 -0
- package/build/commands/authz_freeze.js +94 -0
- package/build/commands/authz_freeze.js.map +1 -0
- package/build/commands/authz_reconcile.d.ts +111 -0
- package/build/commands/authz_reconcile.d.ts.map +1 -0
- package/build/commands/authz_reconcile.js +417 -0
- package/build/commands/authz_reconcile.js.map +1 -0
- package/build/commands/authz_relations_reconcile.d.ts +144 -0
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
- package/build/commands/authz_relations_reconcile.js +438 -0
- package/build/commands/authz_relations_reconcile.js.map +1 -0
- package/build/commands/authz_scopes_relay.d.ts +97 -0
- package/build/commands/authz_scopes_relay.d.ts.map +1 -0
- package/build/commands/authz_scopes_relay.js +344 -0
- package/build/commands/authz_scopes_relay.js.map +1 -0
- package/build/commands/authz_scopes_requeue.d.ts +80 -0
- package/build/commands/authz_scopes_requeue.d.ts.map +1 -0
- package/build/commands/authz_scopes_requeue.js +230 -0
- package/build/commands/authz_scopes_requeue.js.map +1 -0
- package/build/commands/authz_unfreeze.d.ts +45 -0
- package/build/commands/authz_unfreeze.d.ts.map +1 -0
- package/build/commands/authz_unfreeze.js +157 -0
- package/build/commands/authz_unfreeze.js.map +1 -0
- package/build/commands/main.d.ts +16 -8
- package/build/commands/main.d.ts.map +1 -1
- package/build/commands/main.js +59 -6
- package/build/commands/main.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +92 -4
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +155 -7
- package/build/commands/openfga_provision.js.map +1 -1
- package/build/configure.d.ts +11 -0
- package/build/configure.d.ts.map +1 -1
- package/build/configure.js +37 -1
- package/build/configure.js.map +1 -1
- package/build/index.d.ts +50 -11
- package/build/index.d.ts.map +1 -1
- package/build/index.js +49 -7
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts +31 -2
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +65 -2
- package/build/providers/authz_provider.js.map +1 -1
- package/build/services/relations.d.ts +14 -0
- package/build/services/relations.d.ts.map +1 -0
- package/build/services/relations.js +17 -0
- package/build/services/relations.js.map +1 -0
- package/build/src/{catalog.d.ts → catalog/catalog.d.ts} +41 -2
- package/build/src/catalog/catalog.d.ts.map +1 -0
- package/build/src/{catalog.js → catalog/catalog.js} +120 -14
- package/build/src/catalog/catalog.js.map +1 -0
- package/build/src/{catalog_cache.d.ts → catalog/catalog_cache.d.ts} +46 -22
- package/build/src/catalog/catalog_cache.d.ts.map +1 -0
- package/build/src/{catalog_cache.js → catalog/catalog_cache.js} +53 -43
- package/build/src/catalog/catalog_cache.js.map +1 -0
- package/build/src/define_config.d.ts +206 -3
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js +11 -0
- package/build/src/define_config.js.map +1 -1
- package/build/src/drivers/database_driver.d.ts +128 -7
- package/build/src/drivers/database_driver.d.ts.map +1 -1
- package/build/src/drivers/database_driver.js +510 -24
- package/build/src/drivers/database_driver.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +140 -0
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/database_relations_driver.js +748 -0
- package/build/src/drivers/database_relations_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +777 -122
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +2228 -477
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +384 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -0
- package/build/src/drivers/openfga_facts.js +836 -0
- package/build/src/drivers/openfga_facts.js.map +1 -0
- package/build/src/drivers/openfga_relations_driver.d.ts +186 -0
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_relations_driver.js +724 -0
- package/build/src/drivers/openfga_relations_driver.js.map +1 -0
- package/build/src/errors.d.ts +430 -6
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +453 -6
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +200 -0
- package/build/src/freeze.d.ts.map +1 -0
- package/build/src/freeze.js +306 -0
- package/build/src/freeze.js.map +1 -0
- package/build/src/http/app_access_middleware.d.ts.map +1 -0
- package/build/src/http/app_access_middleware.js.map +1 -0
- package/build/src/http/resource_access_middleware.d.ts +105 -0
- package/build/src/http/resource_access_middleware.d.ts.map +1 -0
- package/build/src/http/resource_access_middleware.js +81 -0
- package/build/src/http/resource_access_middleware.js.map +1 -0
- package/build/src/identity.d.ts +74 -1
- package/build/src/identity.d.ts.map +1 -1
- package/build/src/identity.js +100 -2
- package/build/src/identity.js.map +1 -1
- package/build/src/manager.d.ts +549 -6
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +2243 -193
- package/build/src/manager.js.map +1 -1
- package/build/src/models/authz_assignment.d.ts +7 -7
- package/build/src/models/authz_assignment.d.ts.map +1 -1
- package/build/src/models/authz_deny.d.ts +7 -7
- package/build/src/models/authz_deny.d.ts.map +1 -1
- package/build/src/models/authz_permission.d.ts +7 -7
- package/build/src/models/authz_permission.d.ts.map +1 -1
- package/build/src/models/authz_role.d.ts +7 -7
- package/build/src/models/authz_role.d.ts.map +1 -1
- package/build/src/models/authz_role_permission.d.ts +7 -7
- package/build/src/models/authz_role_permission.d.ts.map +1 -1
- package/build/src/openfga.d.ts +18 -2
- package/build/src/openfga.d.ts.map +1 -1
- package/build/src/openfga.js +15 -1
- package/build/src/openfga.js.map +1 -1
- package/build/src/reconcile.d.ts +37 -0
- package/build/src/reconcile.d.ts.map +1 -0
- package/build/src/reconcile.js +69 -0
- package/build/src/reconcile.js.map +1 -0
- package/build/src/relation_partition_trigger.d.ts +8 -0
- package/build/src/relation_partition_trigger.d.ts.map +1 -0
- package/build/src/relation_partition_trigger.js +93 -0
- package/build/src/relation_partition_trigger.js.map +1 -0
- package/build/src/relations/define_relations_config.d.ts +109 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -0
- package/build/src/relations/define_relations_config.js +211 -0
- package/build/src/relations/define_relations_config.js.map +1 -0
- package/build/src/relations/manager.d.ts +138 -0
- package/build/src/relations/manager.d.ts.map +1 -0
- package/build/src/relations/manager.js +494 -0
- package/build/src/relations/manager.js.map +1 -0
- package/build/src/relations/reconcile.d.ts +137 -0
- package/build/src/relations/reconcile.d.ts.map +1 -0
- package/build/src/relations/reconcile.js +294 -0
- package/build/src/relations/reconcile.js.map +1 -0
- package/build/src/relations_config_store.d.ts +22 -0
- package/build/src/relations_config_store.d.ts.map +1 -0
- package/build/src/relations_config_store.js +74 -0
- package/build/src/relations_config_store.js.map +1 -0
- package/build/src/scope_outbox.d.ts +123 -0
- package/build/src/scope_outbox.d.ts.map +1 -0
- package/build/src/scope_outbox.js +532 -0
- package/build/src/scope_outbox.js.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.d.ts +42 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.js +78 -1
- package/build/src/shared/backend_guard.js.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.d.ts +2 -0
- package/build/src/shared/sql_expiry.d.ts.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.js +4 -0
- package/build/src/shared/sql_expiry.js.map +1 -0
- package/build/src/shared/transaction_guard.d.ts +53 -0
- package/build/src/shared/transaction_guard.d.ts.map +1 -0
- package/build/src/shared/transaction_guard.js +74 -0
- package/build/src/shared/transaction_guard.js.map +1 -0
- package/build/src/sql_descendants.d.ts +55 -1
- package/build/src/sql_descendants.d.ts.map +1 -1
- package/build/src/sql_descendants.js +75 -1
- package/build/src/sql_descendants.js.map +1 -1
- package/build/src/testing/contract.d.ts +129 -4
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +915 -177
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +10 -2
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +5 -1
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/migration_contract.d.ts +293 -0
- package/build/src/testing/migration_contract.d.ts.map +1 -0
- package/build/src/testing/migration_contract.js +589 -0
- package/build/src/testing/migration_contract.js.map +1 -0
- package/build/src/testing/relations_contract.d.ts +73 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -0
- package/build/src/testing/relations_contract.js +1238 -0
- package/build/src/testing/relations_contract.js.map +1 -0
- package/build/src/testing/relations_reconcile_contract.d.ts +24 -0
- package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -0
- package/build/src/testing/relations_reconcile_contract.js +220 -0
- package/build/src/testing/relations_reconcile_contract.js.map +1 -0
- package/build/src/testing/scope_outbox_contract.d.ts +98 -0
- package/build/src/testing/scope_outbox_contract.d.ts.map +1 -0
- package/build/src/testing/scope_outbox_contract.js +677 -0
- package/build/src/testing/scope_outbox_contract.js.map +1 -0
- package/build/src/traits/authz_scopes.js +1 -1
- package/build/src/traits/authz_scopes.js.map +1 -1
- package/build/src/traits/has_uuid.d.ts +8 -8
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +1537 -84
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +65 -0
- package/build/src/types.js.map +1 -1
- package/build/stubs/config/authorization.stub +149 -5
- package/build/stubs/migration.stub +136 -0
- package/build/stubs/scopes_outbox_migration.stub +57 -0
- package/package.json +4 -2
- package/build/commands/openfga_import.d.ts +0 -34
- package/build/commands/openfga_import.d.ts.map +0 -1
- package/build/commands/openfga_import.js +0 -97
- package/build/commands/openfga_import.js.map +0 -1
- package/build/src/catalog.d.ts.map +0 -1
- package/build/src/catalog.js.map +0 -1
- package/build/src/catalog_cache.d.ts.map +0 -1
- package/build/src/catalog_cache.js.map +0 -1
- package/build/src/drivers/backend_guard.d.ts.map +0 -1
- package/build/src/drivers/backend_guard.js.map +0 -1
- package/build/src/drivers/sql_expiry.d.ts.map +0 -1
- package/build/src/drivers/sql_expiry.js.map +0 -1
- package/build/src/middleware/app_access_middleware.d.ts.map +0 -1
- package/build/src/middleware/app_access_middleware.js.map +0 -1
- /package/build/src/{middleware → http}/app_access_middleware.d.ts +0 -0
- /package/build/src/{middleware → http}/app_access_middleware.js +0 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { BaseCommand, flags } from '@adonisjs/core/ace';
|
|
11
|
+
/**
|
|
12
|
+
* **La edad de la cola en el comando** (2.4.0-alpha.8; panel relay 2,
|
|
13
|
+
* cuestión 5), en una función PURA (patrón `requeueLines`): qué se imprime y
|
|
14
|
+
* si `--max-age` la convierte en salida ≠ 0.
|
|
15
|
+
*
|
|
16
|
+
* - Sin cabeza con fecha (`pendingAgeMs === null`: cola vacía, solo
|
|
17
|
+
* aparcadas, o una outbox de terceros sin `createdAt`) no se dice nada y
|
|
18
|
+
* nunca se alarma.
|
|
19
|
+
* - Con edad, se INFORMA siempre (es lo que faltaba en el B2 de COGNITIV:
|
|
20
|
+
* diez pasadas con el store caído y nadie sabía desde cuándo).
|
|
21
|
+
* - **Solo con umbral** (`--max-age=<ms>`) y edad POR ENCIMA es `exceeded`
|
|
22
|
+
* (exit ≠ 0): sin umbral un cron no puede quedarse en rojo para siempre
|
|
23
|
+
* por una cola que simplemente tiene backlog. Un umbral inválido lanza.
|
|
24
|
+
*/
|
|
25
|
+
export function queueAgeLines(queue, maxAgeMs, remaining = false) {
|
|
26
|
+
if (maxAgeMs !== undefined && !(Number.isInteger(maxAgeMs) && maxAgeMs >= 0)) {
|
|
27
|
+
throw new TypeError(`authz:scopes:relay: --max-age debe ser un entero >= 0 en milisegundos (llegó ${String(maxAgeMs)})`);
|
|
28
|
+
}
|
|
29
|
+
if (queue.pendingAgeMs === null || queue.oldestPendingAt === null) {
|
|
30
|
+
// «Cola vacía» y «no sé la edad» no son lo mismo (cierre alpha.8, 🟡 2 del
|
|
31
|
+
// auditor): con entradas pendientes y una outbox que no devuelve `createdAt`
|
|
32
|
+
// la alarma por edad no puede vigilar nada — y con `--max-age` eso es un
|
|
33
|
+
// fallo, no un silencio.
|
|
34
|
+
if (!remaining)
|
|
35
|
+
return { lines: [], exceeded: false };
|
|
36
|
+
const message = 'Hay entradas pendientes pero la outbox no devuelve `createdAt` (par de capacidad `createdAt` del contrato): ' +
|
|
37
|
+
'la edad de la cola es DESCONOCIDA y --max-age no puede vigilarla.';
|
|
38
|
+
return maxAgeMs === undefined
|
|
39
|
+
? { lines: [{ level: 'warning', message }], exceeded: false }
|
|
40
|
+
: { lines: [{ level: 'error', message }], exceeded: true };
|
|
41
|
+
}
|
|
42
|
+
const since = queue.oldestPendingAt.toISOString();
|
|
43
|
+
if (maxAgeMs !== undefined && queue.pendingAgeMs > maxAgeMs) {
|
|
44
|
+
return {
|
|
45
|
+
exceeded: true,
|
|
46
|
+
lines: [
|
|
47
|
+
{
|
|
48
|
+
level: 'error',
|
|
49
|
+
message: `La entrada pendiente más antigua de la cola lleva ${queue.pendingAgeMs} ms sin aplicarse (desde ${since}), ` +
|
|
50
|
+
`por encima de --max-age=${maxAgeMs}: la cola no avanza (¿el backend lleva caído desde entonces? un 503 no consume ` +
|
|
51
|
+
'intento y no aparca nada). Mira `failures` de esta pasada.',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
exceeded: false,
|
|
58
|
+
lines: [{ level: 'info', message: `Cabeza de la cola: pendiente desde ${since} (${queue.pendingAgeMs} ms; medida con el reloj de quien encoló).` }],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Drena la OUTBOX del árbol de scopes y aplica los cambios al driver
|
|
63
|
+
* (3b-2d; panel 2, cruce 4 · S5).
|
|
64
|
+
*
|
|
65
|
+
* Con `scopes.outbox` declarada, `authorization.scopes.attached/moved/
|
|
66
|
+
* detached` no escriben en el backend: encolan el cambio DENTRO de la
|
|
67
|
+
* transacción del consumidor. Este comando es quien lo propaga.
|
|
68
|
+
*
|
|
69
|
+
* node ace authz:scopes:relay # drena
|
|
70
|
+
* node ace authz:scopes:relay --dry-run # solo dice qué haría
|
|
71
|
+
* node ace authz:scopes:relay --limit 500 # una pasada acotada
|
|
72
|
+
* node ace authz:scopes:relay --only=12,13 # SOLO esas entradas (2.4.0-alpha.5)
|
|
73
|
+
* node ace authz:scopes:relay --wait-lease-ms=5000 # espera el lease hasta 5 s en vez de salir `busy` (2.4.0-alpha.8)
|
|
74
|
+
* node ace authz:scopes:relay --max-age=300000 # exit ≠ 0 si la pendiente más antigua lleva > 5 min (2.4.0-alpha.8)
|
|
75
|
+
*
|
|
76
|
+
* **`--max-age`** (alpha.8, cuestión 5 del panel relay 2): el reporte lleva
|
|
77
|
+
* SIEMPRE la edad de la cabeza global de la cola (`queue.pendingAgeMs`, con
|
|
78
|
+
* el reloj de quien encoló) y se imprime; con umbral, superarlo es salida ≠ 0
|
|
79
|
+
* — la alarma que faltaba cuando el store está caído (un 503 no consume
|
|
80
|
+
* intento: `attempts` y `dead` se quedan a cero). Sin umbral solo informa.
|
|
81
|
+
*
|
|
82
|
+
* **`--only`** (alpha.5 · R1): releva solo los ids del recibo que devolvió
|
|
83
|
+
* `scopes.attached/moved/detached` (`{ queued }`). El orden por clave no se
|
|
84
|
+
* relaja: una entrada pedida que dependa de una anterior sin aplicar y no
|
|
85
|
+
* pedida sale «aplazada» (`depends-on:<id>`), nunca fuera de orden; `--only`
|
|
86
|
+
* vacío es un error, no «todo». La salida es POR ENTRADA (`entries`), y los
|
|
87
|
+
* ids que no estaban ni pendientes ni aparcados se dicen (`missing`).
|
|
88
|
+
*
|
|
89
|
+
* **Lo aparcado tapona por clave** (alpha.5 · R2a): un `attached`/`moved`
|
|
90
|
+
* que nombre un scope de una entrada APARCADA sale «aplazado» con
|
|
91
|
+
* `parked:<id>` en todas las pasadas hasta que alguien mire la aparcada; un
|
|
92
|
+
* `detached` de esa clave se aplica igual (una purga nunca queda bloqueada).
|
|
93
|
+
* Y un 503 del backend NO consume intento: la caída del store es común a
|
|
94
|
+
* todas las entradas y no dice nada de ninguna.
|
|
95
|
+
*
|
|
96
|
+
* Pensado para un supervisor (un bucle, un cron corto, un worker): la pasada
|
|
97
|
+
* es REANUDABLE —lo que no entra sigue pendiente—. Un cambio que falla
|
|
98
|
+
* **aplaza lo que depende de él** (todo cambio posterior que nombre alguno de
|
|
99
|
+
* sus scopes) y deja pasar el resto: hasta 3b-2h paraba la pasada entera, y
|
|
100
|
+
* eso convertía una entrada irreparable en un tapón permanente para todos los
|
|
101
|
+
* tenants (3b-2h · 🔴 2). Sale con código ≠ 0 si algo falló o hay entradas
|
|
102
|
+
* APARCADAS, para que el supervisor se entere.
|
|
103
|
+
*
|
|
104
|
+
* **Escritor ÚNICO**: si la outbox sabe dar lease (`sqlScopeOutbox` lo hace),
|
|
105
|
+
* una segunda pasada simultánea no hace nada y lo dice. Sin lease, no lances
|
|
106
|
+
* dos a la vez: la rezagada re-aplica cambios viejos sobre el árbol nuevo.
|
|
107
|
+
*
|
|
108
|
+
* **Lo que este comando no puede arreglar**: entre el commit del consumidor
|
|
109
|
+
* y la pasada hay un lag (segundos) en el que el backend decide con el árbol
|
|
110
|
+
* VIEJO. Es un fail-open temporal —el tenant antiguo conserva acceso tras un
|
|
111
|
+
* `moved`, los denies heredados no aplican tras un `attached`—. No hay 2PC.
|
|
112
|
+
* Un ciclo más corto acorta esa ventana **mientras la cola avance**: lo que
|
|
113
|
+
* falla o se aparca no está acotado por el ciclo y hay que mirarlo.
|
|
114
|
+
*
|
|
115
|
+
* Es una operación de PLATAFORMA (como `authz:catalog:prune-orphans`): se
|
|
116
|
+
* salta `requireActor`/`requireWithin` porque la policy ya se juzgó al
|
|
117
|
+
* ENCOLAR, con el árbol y la sesión de aquel momento. No se expone por HTTP.
|
|
118
|
+
*/
|
|
119
|
+
export default class AuthzScopesRelay extends BaseCommand {
|
|
120
|
+
static commandName = 'authz:scopes:relay';
|
|
121
|
+
static description = 'Drain the scope-tree outbox and apply the pending tree changes to the driver';
|
|
122
|
+
static options = {
|
|
123
|
+
startApp: true,
|
|
124
|
+
};
|
|
125
|
+
/** `--only=12,13` o `--only=12 --only=13`: ids numéricos como número, el resto como cadena. */
|
|
126
|
+
static parseOnly(values) {
|
|
127
|
+
if (values === undefined)
|
|
128
|
+
return undefined;
|
|
129
|
+
return values
|
|
130
|
+
.flatMap((value) => String(value).split(','))
|
|
131
|
+
.map((value) => value.trim())
|
|
132
|
+
.filter((value) => value.length > 0)
|
|
133
|
+
.map((value) => (/^\d+$/.test(value) ? Number(value) : value));
|
|
134
|
+
}
|
|
135
|
+
async run() {
|
|
136
|
+
const { default: authorization } = await import('../services/main.js');
|
|
137
|
+
const only = AuthzScopesRelay.parseOnly(this.only);
|
|
138
|
+
if (only !== undefined && only.length === 0) {
|
|
139
|
+
this.logger.error('--only está vacío: relevar «nada» no es relevar «todo». Quita --only para drenar la cola entera.');
|
|
140
|
+
this.exitCode = 1;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// alpha.10 · S7 (auditoría de sistema): el umbral se valida ANTES de tocar
|
|
144
|
+
// la cola. Hasta alpha.9 `queueAgeLines` lanzaba DESPUÉS de relevar: la
|
|
145
|
+
// pasada aplicaba y marcaba entradas y el comando reventaba con un
|
|
146
|
+
// TypeError sin decir qué había aplicado.
|
|
147
|
+
if (this.maxAge !== undefined && !(Number.isInteger(this.maxAge) && this.maxAge >= 0)) {
|
|
148
|
+
this.logger.error(`--max-age debe ser un entero >= 0 en milisegundos (llegó ${String(this.maxAge)}). No se ha relevado nada.`);
|
|
149
|
+
this.exitCode = 1;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const report = await authorization.relayScopeChanges({
|
|
153
|
+
dryRun: this.dryRun === true,
|
|
154
|
+
limit: this.limit,
|
|
155
|
+
batchSize: this.batchSize,
|
|
156
|
+
only,
|
|
157
|
+
...(this.waitLeaseMs === undefined ? {} : { waitForLeaseMs: this.waitLeaseMs }),
|
|
158
|
+
});
|
|
159
|
+
// La EDAD de la cola, siempre; con `--max-age`, la alarma (2.4.0-alpha.8).
|
|
160
|
+
const age = queueAgeLines(report.queue, this.maxAge, report.remaining);
|
|
161
|
+
for (const line of age.lines)
|
|
162
|
+
this.logger[line.level](line.message);
|
|
163
|
+
if (age.exceeded)
|
|
164
|
+
this.exitCode = 1;
|
|
165
|
+
const linea = (item) => {
|
|
166
|
+
const { change } = item;
|
|
167
|
+
const scope = (s) => `${s.type}:${s.uuid ?? ''}`;
|
|
168
|
+
const destino = change.op === 'detached' ? '' : ` → ${scope(change.parent)}`;
|
|
169
|
+
const intentos = item.attempts ? ` (intentos previos: ${item.attempts})` : '';
|
|
170
|
+
return `#${item.id} ${change.op} ${scope(change.child)}${destino}${intentos}`;
|
|
171
|
+
};
|
|
172
|
+
// Lo APARCADO se dice siempre, aplique o no esta pasada: es una
|
|
173
|
+
// divergencia permanente del árbol del backend, no un incidente pasado.
|
|
174
|
+
for (const item of report.dead) {
|
|
175
|
+
this.logger.error(`APARCADO tras agotar los intentos: ${linea(item)}${item.error ? ` — ${item.error}` : ''}`);
|
|
176
|
+
}
|
|
177
|
+
// Cierre-2 · C2 (gemelo): un id PEDIDO aparcado más allá del primer lote de
|
|
178
|
+
// `dead` (acotado a `batchSize`) llega en `entries`; se nombra igual.
|
|
179
|
+
if (only !== undefined) {
|
|
180
|
+
const listed = new Set(report.dead.map((item) => String(item.id)));
|
|
181
|
+
for (const entry of report.entries) {
|
|
182
|
+
if (entry.status !== 'dead' || listed.has(String(entry.id)))
|
|
183
|
+
continue;
|
|
184
|
+
this.logger.error(`APARCADO tras agotar los intentos: ${linea(entry)}${entry.reason ? ` — ${entry.reason}` : ''}`);
|
|
185
|
+
this.exitCode = 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Cierre-2 · C2: `missing` (no está en la cola) ≠ `notEvaluated` (PENDIENTE y
|
|
189
|
+
// la pasada no llegó: alcanzó --limit). Hasta el cierre-2 los dos salían como
|
|
190
|
+
// «no estaba ni pendiente ni aparcado … o no existe», con exit 0.
|
|
191
|
+
const notEvaluated = only === undefined ? [] : (report.notEvaluated ?? []);
|
|
192
|
+
const limite = this.limit === undefined ? 'el --limit por defecto' : `--limit=${this.limit}`;
|
|
193
|
+
const rama = report.dryRun ? '--dry-run' : 'pasada que aplica';
|
|
194
|
+
const notEvaluatedLines = () => {
|
|
195
|
+
if (notEvaluated.length === 0)
|
|
196
|
+
return;
|
|
197
|
+
for (const id of notEvaluated) {
|
|
198
|
+
this.logger.error(`#${id} está PENDIENTE y esta pasada NO lo evaluó (${rama}): alcanzó ${limite} antes de llegar a él. ` +
|
|
199
|
+
(report.dryRun ? 'No se sabe si se aplicaría.' : 'No se ha aplicado: el cambio no ha aterrizado.'));
|
|
200
|
+
}
|
|
201
|
+
this.logger.error(`${notEvaluated.length} de los ids pedidos NO se evaluaron por el límite de la pasada ` +
|
|
202
|
+
`(${notEvaluated.map((id) => `#${id}`).join(', ')}): repite con un --limit mayor (o sin él).`);
|
|
203
|
+
this.exitCode = 1;
|
|
204
|
+
};
|
|
205
|
+
if (report.dead.length > 0) {
|
|
206
|
+
this.logger.warning('Una entrada aparcada NO se va a aplicar sola: el árbol del backend está divergente en ese nodo. ' +
|
|
207
|
+
'Revísala en la cola (el consumidor puede volver a notificar el cambio) o reconcilia.');
|
|
208
|
+
}
|
|
209
|
+
if (report.busy) {
|
|
210
|
+
this.logger.info('Otra pasada del relay tiene el lease de la cola: esta no ha aplicado nada (el relay es escritor único).');
|
|
211
|
+
if (report.dead.length > 0)
|
|
212
|
+
this.exitCode = 1;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (report.dryRun) {
|
|
216
|
+
for (const item of report.wouldApply)
|
|
217
|
+
this.logger.log(`pendiente: ${linea(item)}`);
|
|
218
|
+
// Cierre del auditor de alpha.10 · R3 (gemelo de S6 en --dry-run): con
|
|
219
|
+
// `--only` la pregunta es «¿qué fue de LO PEDIDO?» también aquí. Hasta el
|
|
220
|
+
// cierre esta rama retornaba antes del bloque S6 y `--dry-run --only=999`
|
|
221
|
+
// (errata) decía «La outbox del árbol está vacía» en verde sin nombrar el id.
|
|
222
|
+
// Misma letra por id que la pasada que aplica; el resumen dice su rama.
|
|
223
|
+
if (only !== undefined) {
|
|
224
|
+
for (const id of report.missing) {
|
|
225
|
+
this.logger.warning(`#${id} no estaba ni pendiente ni aparcado: ya lo aplicó otra pasada, o no existe.`);
|
|
226
|
+
}
|
|
227
|
+
notEvaluatedLines();
|
|
228
|
+
}
|
|
229
|
+
if (report.wouldApply.length === 0) {
|
|
230
|
+
if (report.dead.length > 0)
|
|
231
|
+
this.exitCode = 1;
|
|
232
|
+
if (only !== undefined) {
|
|
233
|
+
if (report.missing.length > 0 && notEvaluated.length === 0) {
|
|
234
|
+
this.logger.warning(`--dry-run: ninguno de los ids pedidos está pendiente (${report.missing.map((id) => `#${id}`).join(', ')}: ` +
|
|
235
|
+
'ni pendientes ni aparcados). No hay nada de LO PEDIDO que propagar; si no los aplicó otra pasada, revisa los ids.');
|
|
236
|
+
}
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (report.dead.length === 0)
|
|
240
|
+
this.logger.success('La outbox del árbol está vacía: nada que propagar.');
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
this.logger.warning(`${report.wouldApply.length} cambio(s) del árbol sin propagar. No se ha aplicado nada: repite sin --dry-run. ` +
|
|
244
|
+
`Mientras tanto el backend decide con el árbol VIEJO.`);
|
|
245
|
+
// alpha.10 · S5: lo APARCADO es exit ≠ 0 «mientras exista» (README), haya
|
|
246
|
+
// o no pendientes. Hasta alpha.9 un cron con --dry-run perdía la
|
|
247
|
+
// divergencia permanente justo cuando además había tráfico.
|
|
248
|
+
if (report.dead.length > 0)
|
|
249
|
+
this.exitCode = 1;
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
// Qué fue de cada entrada, una a una (`entries`): la pasada no es atómica
|
|
253
|
+
// y un contador no permite retomar nada. Lo aparcado ya se dijo arriba.
|
|
254
|
+
for (const entry of report.entries) {
|
|
255
|
+
if (entry.status === 'applied')
|
|
256
|
+
this.logger.log(`aplicado: ${linea(entry)}`);
|
|
257
|
+
if (entry.status === 'deferred') {
|
|
258
|
+
const motivo = entry.reason?.startsWith('parked:')
|
|
259
|
+
? `aplazado por APARCADO (${entry.reason}): no se aplica hasta que alguien mire esa entrada`
|
|
260
|
+
: `aplazado (${entry.reason ?? 'depende de una entrada anterior sin aplicar'}): corre el relay completo`;
|
|
261
|
+
this.logger.warning(`${motivo}: ${linea(entry)}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
for (const id of report.missing) {
|
|
265
|
+
this.logger.warning(`#${id} no estaba ni pendiente ni aparcado: ya lo aplicó otra pasada, o no existe.`);
|
|
266
|
+
}
|
|
267
|
+
notEvaluatedLines();
|
|
268
|
+
if (report.failures.length > 0) {
|
|
269
|
+
for (const item of report.failures) {
|
|
270
|
+
this.logger.error(`falló #${item.id} (${item.change.op} ` +
|
|
271
|
+
`${item.change.child.type}:${item.change.child.uuid ?? ''}): ${item.error}` +
|
|
272
|
+
(item.transient ? ' — el backend no respondió: este fallo NO consume intento' : ''));
|
|
273
|
+
}
|
|
274
|
+
this.logger.warning('Lo que DEPENDE de un cambio fallido no se adelanta (el orden del árbol importa: aparece como «aplazado»), ' +
|
|
275
|
+
'pero el resto de la cola sí avanza. Arregla la causa y vuelve a ejecutar; retoma donde lo dejó. ' +
|
|
276
|
+
'Agotados los intentos que declare tu outbox, una entrada irreparable se APARCA y se reporta.');
|
|
277
|
+
this.exitCode = 1;
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (report.dead.length > 0)
|
|
281
|
+
this.exitCode = 1;
|
|
282
|
+
// alpha.10 · S6: con `--only` la pregunta es «¿aterrizó LO QUE PEDÍ?», no
|
|
283
|
+
// «¿está vacía la cola?». Hasta alpha.9 un id aplazado (o una errata)
|
|
284
|
+
// imprimía «La outbox del árbol está vacía» en verde: el script de alta de
|
|
285
|
+
// tenant daba por relevado un cambio que no había aterrizado.
|
|
286
|
+
if (only !== undefined) {
|
|
287
|
+
const deferred = report.entries.filter((entry) => entry.status === 'deferred');
|
|
288
|
+
if (deferred.length > 0) {
|
|
289
|
+
this.logger.error(`${deferred.length} de los ids pedidos NO se ha aplicado (aplazado, arriba el motivo): ` +
|
|
290
|
+
`${deferred.map((entry) => `#${entry.id}`).join(', ')}. El cambio no ha aterrizado en el backend.`);
|
|
291
|
+
this.exitCode = 1;
|
|
292
|
+
}
|
|
293
|
+
if (report.applied.length === 0) {
|
|
294
|
+
if (deferred.length === 0 && notEvaluated.length === 0 && report.missing.length > 0) {
|
|
295
|
+
this.logger.warning(`Ninguno de los ids pedidos se ha aplicado en esta pasada (${report.missing.map((id) => `#${id}`).join(', ')}: ` +
|
|
296
|
+
'ni pendientes ni aparcados). Si no los aplicó otra pasada, revisa los ids.');
|
|
297
|
+
}
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (report.applied.length === 0) {
|
|
302
|
+
if (report.dead.length === 0)
|
|
303
|
+
this.logger.success('La outbox del árbol está vacía: nada que propagar.');
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
this.logger.success(`${report.applied.length} cambio(s) del árbol propagado(s) al driver.`);
|
|
307
|
+
if (report.remaining) {
|
|
308
|
+
this.logger.warning('Quedan cambios pendientes (se alcanzó el límite de la pasada o hay aplazados): vuelve a ejecutar.');
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
__decorate([
|
|
313
|
+
flags.boolean({
|
|
314
|
+
description: 'List the pending tree changes without applying any of them',
|
|
315
|
+
}),
|
|
316
|
+
__metadata("design:type", Object)
|
|
317
|
+
], AuthzScopesRelay.prototype, "dryRun", void 0);
|
|
318
|
+
__decorate([
|
|
319
|
+
flags.number({ description: 'Stop after applying this many changes (the rest stays pending)' }),
|
|
320
|
+
__metadata("design:type", Object)
|
|
321
|
+
], AuthzScopesRelay.prototype, "limit", void 0);
|
|
322
|
+
__decorate([
|
|
323
|
+
flags.number({ description: 'How many pending changes to read per round trip' }),
|
|
324
|
+
__metadata("design:type", Object)
|
|
325
|
+
], AuthzScopesRelay.prototype, "batchSize", void 0);
|
|
326
|
+
__decorate([
|
|
327
|
+
flags.array({
|
|
328
|
+
description: 'Apply ONLY these outbox ids (the receipt of scopes.*), comma-separated or repeated; dependencies are deferred, never skipped',
|
|
329
|
+
}),
|
|
330
|
+
__metadata("design:type", Object)
|
|
331
|
+
], AuthzScopesRelay.prototype, "only", void 0);
|
|
332
|
+
__decorate([
|
|
333
|
+
flags.number({
|
|
334
|
+
description: 'Wait up to this many ms for the relay lease instead of reporting busy at once (default 0; needs a pool >= 2)',
|
|
335
|
+
}),
|
|
336
|
+
__metadata("design:type", Object)
|
|
337
|
+
], AuthzScopesRelay.prototype, "waitLeaseMs", void 0);
|
|
338
|
+
__decorate([
|
|
339
|
+
flags.number({
|
|
340
|
+
description: 'Exit ≠ 0 if the oldest pending entry of the whole queue is older than this many ms (without it the age is only reported)',
|
|
341
|
+
}),
|
|
342
|
+
__metadata("design:type", Object)
|
|
343
|
+
], AuthzScopesRelay.prototype, "maxAge", void 0);
|
|
344
|
+
//# sourceMappingURL=authz_scopes_relay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz_scopes_relay.js","sourceRoot":"","sources":["../../commands/authz_scopes_relay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
|
+
import { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
|
+
import type { ScopeRequeueConflict, ScopeRequeueReport } from '../src/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Las líneas del comando y si la ejecución es «limpia», en una función PURA
|
|
6
|
+
* (mismo patrón que `reconcileLines`/`orphanLines`): es lo único del comando
|
|
7
|
+
* que decide algo, y así tiene su caso sin montar un ace.
|
|
8
|
+
*
|
|
9
|
+
* - `refused`: el manager se NEGÓ (500 `E_AUTHZ_REQUEUE_REFUSED`). Se imprime
|
|
10
|
+
* el DIFF entero —cada aparcada y cada entrada APLICADA posterior que
|
|
11
|
+
* reaplicarla revertiría— y se sale ≠ 0, con las dos salidas: `--force`
|
|
12
|
+
* (que entra igual, con este mismo diff delante) y `authz:reconcile`.
|
|
13
|
+
* - `report`: se reencoló. Con `forced` y `overrides`, el diff se imprime
|
|
14
|
+
* como AVISO: forzar no es un éxito mudo.
|
|
15
|
+
* - `report.relay` (con `--apply`, 2.4.0-alpha.8): la pasada que relevó SOLO
|
|
16
|
+
* lo reencolado, bajo el mismo lease. `busy` ⇒ NO se reencoló nada (todo o
|
|
17
|
+
* nada) y se sale ≠ 0 con la letra («otra pasada tiene el lease; reintenta,
|
|
18
|
+
* o `requeue` sin `--apply`»); cada entrada dice si se aplicó, falló o quedó
|
|
19
|
+
* aplazada, y solo es limpio si TODO lo reencolado se aplicó.
|
|
20
|
+
*/
|
|
21
|
+
export declare function requeueLines(input: {
|
|
22
|
+
refused?: ScopeRequeueConflict[];
|
|
23
|
+
report?: ScopeRequeueReport;
|
|
24
|
+
}): {
|
|
25
|
+
lines: Array<{
|
|
26
|
+
level: 'log' | 'warning' | 'error' | 'success';
|
|
27
|
+
message: string;
|
|
28
|
+
}>;
|
|
29
|
+
clean: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* **Devuelve entradas APARCADAS de la outbox a la cola** (2.4.0-alpha.5 · R2b;
|
|
33
|
+
* panel relay, cuestión 2).
|
|
34
|
+
*
|
|
35
|
+
* node ace authz:scopes:requeue --id=12 # una
|
|
36
|
+
* node ace authz:scopes:requeue --id=12,13 # varias (o --id repetido)
|
|
37
|
+
* node ace authz:scopes:requeue --id=12 --force # aunque revierta lo aplicado después (diff impreso)
|
|
38
|
+
* node ace authz:scopes:requeue --id=12 --apply # y la aplica en la MISMA llamada (2.4.0-alpha.8)
|
|
39
|
+
* node ace authz:scopes:requeue --id=12 --apply --wait-lease-ms=5000 # esperando el lease si el cron lo tiene
|
|
40
|
+
*
|
|
41
|
+
* Una entrada aparcada (`sqlScopeOutbox({ maxAttempts })`, 5 por defecto)
|
|
42
|
+
* no se reintenta sola: el relay la reporta en cada pasada y sale ≠ 0. Cuando
|
|
43
|
+
* el operador arregla la causa —el padre que faltaba vuelve, el store se
|
|
44
|
+
* reconcilia— este comando la devuelve a `pending()` con **`attempts =
|
|
45
|
+
* maxAttempts − 1`**: entra a la primera si está arreglada y vuelve a
|
|
46
|
+
* aparcarse en UNA sola pasada si no (así un requeue automatizado de lo
|
|
47
|
+
* irreparable no es un grifo de aplazamiento para el resto del scope).
|
|
48
|
+
*
|
|
49
|
+
* **La sonda anti-reversión es del manager y no tiene excepción**: si después
|
|
50
|
+
* de la aparcada se APLICÓ otra entrada sobre la misma clave de scope,
|
|
51
|
+
* reencolarla reaplicaría el cambio viejo por encima del nuevo —un `moved`
|
|
52
|
+
* viejo tras el nuevo deja el store con el padre VIEJO y un solo padre—. El
|
|
53
|
+
* comando imprime ese diff y sale ≠ 0. **`--force` existe SOLO aquí**
|
|
54
|
+
* (decisión del dueño del 2026-09-09 (2)): imprime el diff y entra igual. Nunca
|
|
55
|
+
* en una ruta alcanzable por HTTP.
|
|
56
|
+
*
|
|
57
|
+
* **`--apply` (2.4.0-alpha.8)**: reencola Y releva SOLO esas entradas en la
|
|
58
|
+
* misma llamada, bajo UN lease (medido: sin esto la reencolada volvía con su
|
|
59
|
+
* id original y la siguiente pasada `only` del tenant salía `depends-on`; el
|
|
60
|
+
* incidente no se cerraba con un comando). Explícito, jamás por defecto: el
|
|
61
|
+
* comando pasa a ESCRIBIR en el backend. No compone con `--force` (500). Pasa
|
|
62
|
+
* la barrera del freeze. Con el lease tomado por otra pasada NO reencola nada
|
|
63
|
+
* y sale ≠ 0 (`--wait-lease-ms` espera, acotado).
|
|
64
|
+
*
|
|
65
|
+
* Es una operación de PLATAFORMA (como `authz:scopes:relay`): sin actor, sin
|
|
66
|
+
* `within`, y no se expone por HTTP.
|
|
67
|
+
*/
|
|
68
|
+
export default class AuthzScopesRequeue extends BaseCommand {
|
|
69
|
+
static commandName: string;
|
|
70
|
+
static description: string;
|
|
71
|
+
static options: CommandOptions;
|
|
72
|
+
id: string[] | undefined;
|
|
73
|
+
force: boolean | undefined;
|
|
74
|
+
apply: boolean | undefined;
|
|
75
|
+
waitLeaseMs: number | undefined;
|
|
76
|
+
/** `--id=12,13` o `--id=12 --id=13`: ids numéricos como número, el resto como cadena. */
|
|
77
|
+
static parseIds(values: string[] | undefined): Array<string | number> | undefined;
|
|
78
|
+
run(): Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=authz_scopes_requeue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz_scopes_requeue.d.ts","sourceRoot":"","sources":["../../commands/authz_scopes_requeue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAA0B,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAYvG;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAE,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG;IACtG,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjF,KAAK,EAAE,OAAO,CAAA;CACf,CAqFA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,WAAW;IACzD,MAAM,CAAC,WAAW,SAAyB;IAC3C,MAAM,CAAC,WAAW,SAAkH;IAEpI,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAKO,EAAE,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAKxB,KAAK,EAAE,OAAO,GAAG,SAAS,CAAA;IAK1B,KAAK,EAAE,OAAO,GAAG,SAAS,CAAA;IAK1B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAEvC,yFAAyF;IACzF,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS;IAS3E,GAAG;CAuBV"}
|