@jantstack/adonis-authz 2.0.0-alpha.1 → 2.4.0-alpha.1
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 +462 -35
- package/build/commands/authz_catalog_diff.js +1 -1
- 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 +136 -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 +95 -0
- package/build/commands/authz_freeze.js.map +1 -0
- package/build/commands/authz_reconcile.d.ts +102 -0
- package/build/commands/authz_reconcile.d.ts.map +1 -0
- package/build/commands/authz_reconcile.js +294 -0
- package/build/commands/authz_reconcile.js.map +1 -0
- package/build/commands/authz_relations_reconcile.d.ts +73 -0
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
- package/build/commands/authz_relations_reconcile.js +225 -0
- package/build/commands/authz_relations_reconcile.js.map +1 -0
- package/build/commands/authz_scopes_relay.d.ts +47 -0
- package/build/commands/authz_scopes_relay.d.ts.map +1 -0
- package/build/commands/authz_scopes_relay.js +141 -0
- package/build/commands/authz_scopes_relay.js.map +1 -0
- package/build/commands/authz_unfreeze.d.ts +37 -0
- package/build/commands/authz_unfreeze.d.ts.map +1 -0
- package/build/commands/authz_unfreeze.js +92 -0
- package/build/commands/authz_unfreeze.js.map +1 -0
- package/build/commands/main.d.ts +6 -1
- package/build/commands/main.d.ts.map +1 -1
- package/build/commands/main.js +6 -1
- package/build/commands/main.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +46 -4
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +90 -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 +39 -10
- package/build/index.d.ts.map +1 -1
- package/build/index.js +35 -6
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts +26 -2
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +48 -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 +101 -3
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js.map +1 -1
- package/build/src/drivers/database_driver.d.ts +86 -4
- package/build/src/drivers/database_driver.d.ts.map +1 -1
- package/build/src/drivers/database_driver.js +425 -11
- package/build/src/drivers/database_driver.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +75 -0
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/database_relations_driver.js +450 -0
- package/build/src/drivers/database_relations_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +713 -119
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +2048 -476
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +369 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -0
- package/build/src/drivers/openfga_facts.js +813 -0
- package/build/src/drivers/openfga_facts.js.map +1 -0
- package/build/src/drivers/openfga_relations_driver.d.ts +120 -0
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_relations_driver.js +466 -0
- package/build/src/drivers/openfga_relations_driver.js.map +1 -0
- package/build/src/errors.d.ts +258 -5
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +238 -7
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +120 -0
- package/build/src/freeze.d.ts.map +1 -0
- package/build/src/freeze.js +172 -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 +315 -4
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +1187 -181
- package/build/src/manager.js.map +1 -1
- package/build/src/models/authz_assignment.d.ts +6 -6
- package/build/src/models/authz_assignment.d.ts.map +1 -1
- package/build/src/models/authz_deny.d.ts +6 -6
- package/build/src/models/authz_deny.d.ts.map +1 -1
- package/build/src/models/authz_permission.d.ts +6 -6
- package/build/src/models/authz_permission.d.ts.map +1 -1
- package/build/src/models/authz_role.d.ts +6 -6
- package/build/src/models/authz_role.d.ts.map +1 -1
- package/build/src/models/authz_role_permission.d.ts +6 -6
- 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 +85 -0
- package/build/src/relation_partition_trigger.js.map +1 -0
- package/build/src/relations/define_relations_config.d.ts +58 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -0
- package/build/src/relations/define_relations_config.js +144 -0
- package/build/src/relations/define_relations_config.js.map +1 -0
- package/build/src/relations/manager.d.ts +38 -0
- package/build/src/relations/manager.d.ts.map +1 -0
- package/build/src/relations/manager.js +156 -0
- package/build/src/relations/manager.js.map +1 -0
- package/build/src/relations/reconcile.d.ts +62 -0
- package/build/src/relations/reconcile.d.ts.map +1 -0
- package/build/src/relations/reconcile.js +138 -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 +69 -0
- package/build/src/scope_outbox.d.ts.map +1 -0
- package/build/src/scope_outbox.js +291 -0
- package/build/src/scope_outbox.js.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.d.ts +14 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.js +26 -1
- package/build/src/shared/backend_guard.js.map +1 -0
- package/build/src/shared/sql_expiry.d.ts.map +1 -0
- package/build/src/shared/sql_expiry.js.map +1 -0
- package/build/src/sql_descendants.d.ts +47 -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 +74 -0
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +672 -169
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +6 -0
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +3 -0
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/migration_contract.d.ts +284 -0
- package/build/src/testing/migration_contract.d.ts.map +1 -0
- package/build/src/testing/migration_contract.js +586 -0
- package/build/src/testing/migration_contract.js.map +1 -0
- package/build/src/testing/relations_contract.d.ts +51 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -0
- package/build/src/testing/relations_contract.js +654 -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 +172 -0
- package/build/src/testing/relations_reconcile_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 +7 -7
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +865 -82
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +10 -0
- package/build/src/types.js.map +1 -1
- package/build/stubs/config/authorization.stub +104 -4
- package/build/stubs/migration.stub +126 -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
- /package/build/src/{drivers → shared}/sql_expiry.d.ts +0 -0
- /package/build/src/{drivers → shared}/sql_expiry.js +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
|
+
import { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
|
+
/**
|
|
4
|
+
* Drena la OUTBOX del árbol de scopes y aplica los cambios al driver
|
|
5
|
+
* (3b-2d; panel 2, cruce 4 · S5).
|
|
6
|
+
*
|
|
7
|
+
* Con `scopes.outbox` declarada, `authorization.scopes.attached/moved/
|
|
8
|
+
* detached` no escriben en el backend: encolan el cambio DENTRO de la
|
|
9
|
+
* transacción del consumidor. Este comando es quien lo propaga.
|
|
10
|
+
*
|
|
11
|
+
* node ace authz:scopes:relay # drena
|
|
12
|
+
* node ace authz:scopes:relay --dry-run # solo dice qué haría
|
|
13
|
+
* node ace authz:scopes:relay --limit 500 # una pasada acotada
|
|
14
|
+
*
|
|
15
|
+
* Pensado para un supervisor (un bucle, un cron corto, un worker): la pasada
|
|
16
|
+
* es REANUDABLE —lo que no entra sigue pendiente—. Un cambio que falla
|
|
17
|
+
* **aplaza lo que depende de él** (todo cambio posterior que nombre alguno de
|
|
18
|
+
* sus scopes) y deja pasar el resto: hasta 3b-2h paraba la pasada entera, y
|
|
19
|
+
* eso convertía una entrada irreparable en un tapón permanente para todos los
|
|
20
|
+
* tenants (3b-2h · 🔴 2). Sale con código ≠ 0 si algo falló o hay entradas
|
|
21
|
+
* APARCADAS, para que el supervisor se entere.
|
|
22
|
+
*
|
|
23
|
+
* **Escritor ÚNICO**: si la outbox sabe dar lease (`sqlScopeOutbox` lo hace),
|
|
24
|
+
* una segunda pasada simultánea no hace nada y lo dice. Sin lease, no lances
|
|
25
|
+
* dos a la vez: la rezagada re-aplica cambios viejos sobre el árbol nuevo.
|
|
26
|
+
*
|
|
27
|
+
* **Lo que este comando no puede arreglar**: entre el commit del consumidor
|
|
28
|
+
* y la pasada hay un lag (segundos) en el que el backend decide con el árbol
|
|
29
|
+
* VIEJO. Es un fail-open temporal —el tenant antiguo conserva acceso tras un
|
|
30
|
+
* `moved`, los denies heredados no aplican tras un `attached`—. No hay 2PC.
|
|
31
|
+
* Un ciclo más corto acorta esa ventana **mientras la cola avance**: lo que
|
|
32
|
+
* falla o se aparca no está acotado por el ciclo y hay que mirarlo.
|
|
33
|
+
*
|
|
34
|
+
* Es una operación de PLATAFORMA (como `authz:catalog:prune-orphans`): se
|
|
35
|
+
* salta `requireActor`/`requireWithin` porque la policy ya se juzgó al
|
|
36
|
+
* ENCOLAR, con el árbol y la sesión de aquel momento. No se expone por HTTP.
|
|
37
|
+
*/
|
|
38
|
+
export default class AuthzScopesRelay extends BaseCommand {
|
|
39
|
+
static commandName: string;
|
|
40
|
+
static description: string;
|
|
41
|
+
static options: CommandOptions;
|
|
42
|
+
dryRun: boolean | undefined;
|
|
43
|
+
limit: number | undefined;
|
|
44
|
+
batchSize: number | undefined;
|
|
45
|
+
run(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=authz_scopes_relay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz_scopes_relay.d.ts","sourceRoot":"","sources":["../../commands/authz_scopes_relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACvD,MAAM,CAAC,WAAW,SAAuB;IACzC,MAAM,CAAC,WAAW,SAAiF;IAEnG,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAMO,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IAG3B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAGzB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAE/B,GAAG;CAkFV"}
|
|
@@ -0,0 +1,141 @@
|
|
|
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
|
+
* Drena la OUTBOX del árbol de scopes y aplica los cambios al driver
|
|
13
|
+
* (3b-2d; panel 2, cruce 4 · S5).
|
|
14
|
+
*
|
|
15
|
+
* Con `scopes.outbox` declarada, `authorization.scopes.attached/moved/
|
|
16
|
+
* detached` no escriben en el backend: encolan el cambio DENTRO de la
|
|
17
|
+
* transacción del consumidor. Este comando es quien lo propaga.
|
|
18
|
+
*
|
|
19
|
+
* node ace authz:scopes:relay # drena
|
|
20
|
+
* node ace authz:scopes:relay --dry-run # solo dice qué haría
|
|
21
|
+
* node ace authz:scopes:relay --limit 500 # una pasada acotada
|
|
22
|
+
*
|
|
23
|
+
* Pensado para un supervisor (un bucle, un cron corto, un worker): la pasada
|
|
24
|
+
* es REANUDABLE —lo que no entra sigue pendiente—. Un cambio que falla
|
|
25
|
+
* **aplaza lo que depende de él** (todo cambio posterior que nombre alguno de
|
|
26
|
+
* sus scopes) y deja pasar el resto: hasta 3b-2h paraba la pasada entera, y
|
|
27
|
+
* eso convertía una entrada irreparable en un tapón permanente para todos los
|
|
28
|
+
* tenants (3b-2h · 🔴 2). Sale con código ≠ 0 si algo falló o hay entradas
|
|
29
|
+
* APARCADAS, para que el supervisor se entere.
|
|
30
|
+
*
|
|
31
|
+
* **Escritor ÚNICO**: si la outbox sabe dar lease (`sqlScopeOutbox` lo hace),
|
|
32
|
+
* una segunda pasada simultánea no hace nada y lo dice. Sin lease, no lances
|
|
33
|
+
* dos a la vez: la rezagada re-aplica cambios viejos sobre el árbol nuevo.
|
|
34
|
+
*
|
|
35
|
+
* **Lo que este comando no puede arreglar**: entre el commit del consumidor
|
|
36
|
+
* y la pasada hay un lag (segundos) en el que el backend decide con el árbol
|
|
37
|
+
* VIEJO. Es un fail-open temporal —el tenant antiguo conserva acceso tras un
|
|
38
|
+
* `moved`, los denies heredados no aplican tras un `attached`—. No hay 2PC.
|
|
39
|
+
* Un ciclo más corto acorta esa ventana **mientras la cola avance**: lo que
|
|
40
|
+
* falla o se aparca no está acotado por el ciclo y hay que mirarlo.
|
|
41
|
+
*
|
|
42
|
+
* Es una operación de PLATAFORMA (como `authz:catalog:prune-orphans`): se
|
|
43
|
+
* salta `requireActor`/`requireWithin` porque la policy ya se juzgó al
|
|
44
|
+
* ENCOLAR, con el árbol y la sesión de aquel momento. No se expone por HTTP.
|
|
45
|
+
*/
|
|
46
|
+
export default class AuthzScopesRelay extends BaseCommand {
|
|
47
|
+
static commandName = 'authz:scopes:relay';
|
|
48
|
+
static description = 'Drain the scope-tree outbox and apply the pending tree changes to the driver';
|
|
49
|
+
static options = {
|
|
50
|
+
startApp: true,
|
|
51
|
+
};
|
|
52
|
+
async run() {
|
|
53
|
+
const { default: authorization } = await import('../services/main.js');
|
|
54
|
+
const report = await authorization.relayScopeChanges({
|
|
55
|
+
dryRun: this.dryRun === true,
|
|
56
|
+
limit: this.limit,
|
|
57
|
+
batchSize: this.batchSize,
|
|
58
|
+
});
|
|
59
|
+
const linea = (item) => {
|
|
60
|
+
const { change } = item;
|
|
61
|
+
const scope = (s) => `${s.type}:${s.uuid ?? ''}`;
|
|
62
|
+
const destino = change.op === 'detached' ? '' : ` → ${scope(change.parent)}`;
|
|
63
|
+
const intentos = item.attempts ? ` (intentos previos: ${item.attempts})` : '';
|
|
64
|
+
return `#${item.id} ${change.op} ${scope(change.child)}${destino}${intentos}`;
|
|
65
|
+
};
|
|
66
|
+
// Lo APARCADO se dice siempre, aplique o no esta pasada: es una
|
|
67
|
+
// divergencia permanente del árbol del backend, no un incidente pasado.
|
|
68
|
+
for (const item of report.dead) {
|
|
69
|
+
this.logger.error(`APARCADO tras agotar los intentos: ${linea(item)}${item.error ? ` — ${item.error}` : ''}`);
|
|
70
|
+
}
|
|
71
|
+
if (report.dead.length > 0) {
|
|
72
|
+
this.logger.warning('Una entrada aparcada NO se va a aplicar sola: el árbol del backend está divergente en ese nodo. ' +
|
|
73
|
+
'Revísala en la cola (el consumidor puede volver a notificar el cambio) o reconcilia.');
|
|
74
|
+
}
|
|
75
|
+
if (report.busy) {
|
|
76
|
+
this.logger.info('Otra pasada del relay tiene el lease de la cola: esta no ha aplicado nada (el relay es escritor único).');
|
|
77
|
+
if (report.dead.length > 0)
|
|
78
|
+
this.exitCode = 1;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (report.dryRun) {
|
|
82
|
+
for (const item of report.wouldApply)
|
|
83
|
+
this.logger.log(`pendiente: ${linea(item)}`);
|
|
84
|
+
if (report.wouldApply.length === 0) {
|
|
85
|
+
if (report.dead.length > 0)
|
|
86
|
+
this.exitCode = 1;
|
|
87
|
+
else
|
|
88
|
+
this.logger.success('La outbox del árbol está vacía: nada que propagar.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.logger.warning(`${report.wouldApply.length} cambio(s) del árbol sin propagar. No se ha aplicado nada: repite sin --dry-run. ` +
|
|
92
|
+
`Mientras tanto el backend decide con el árbol VIEJO.`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Qué se aplicó, uno a uno: la pasada no es atómica y un contador no
|
|
96
|
+
// permite retomar nada.
|
|
97
|
+
for (const item of report.applied)
|
|
98
|
+
this.logger.log(`aplicado: ${linea(item)}`);
|
|
99
|
+
for (const item of report.deferred) {
|
|
100
|
+
this.logger.warning(`aplazado: ${linea(item)}${item.error ? ` — ${item.error}` : ''}`);
|
|
101
|
+
}
|
|
102
|
+
if (report.failures.length > 0) {
|
|
103
|
+
for (const item of report.failures) {
|
|
104
|
+
this.logger.error(`falló #${item.id} (${item.change.op} ` +
|
|
105
|
+
`${item.change.child.type}:${item.change.child.uuid ?? ''}): ${item.error}`);
|
|
106
|
+
}
|
|
107
|
+
this.logger.warning('Lo que DEPENDE de un cambio fallido no se adelanta (el orden del árbol importa: aparece como «aplazado»), ' +
|
|
108
|
+
'pero el resto de la cola sí avanza. Arregla la causa y vuelve a ejecutar; retoma donde lo dejó. ' +
|
|
109
|
+
'Agotados los intentos que declare tu outbox, una entrada irreparable se APARCA y se reporta.');
|
|
110
|
+
this.exitCode = 1;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (report.dead.length > 0)
|
|
114
|
+
this.exitCode = 1;
|
|
115
|
+
if (report.applied.length === 0) {
|
|
116
|
+
if (report.dead.length === 0)
|
|
117
|
+
this.logger.success('La outbox del árbol está vacía: nada que propagar.');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
this.logger.success(`${report.applied.length} cambio(s) del árbol propagado(s) al driver.`);
|
|
121
|
+
if (report.remaining) {
|
|
122
|
+
this.logger.warning('Quedan cambios pendientes (se alcanzó el límite de la pasada o hay aplazados): vuelve a ejecutar.');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
__decorate([
|
|
127
|
+
flags.boolean({
|
|
128
|
+
name: 'dry-run',
|
|
129
|
+
description: 'List the pending tree changes without applying any of them',
|
|
130
|
+
}),
|
|
131
|
+
__metadata("design:type", Object)
|
|
132
|
+
], AuthzScopesRelay.prototype, "dryRun", void 0);
|
|
133
|
+
__decorate([
|
|
134
|
+
flags.number({ description: 'Stop after applying this many changes (the rest stays pending)' }),
|
|
135
|
+
__metadata("design:type", Object)
|
|
136
|
+
], AuthzScopesRelay.prototype, "limit", void 0);
|
|
137
|
+
__decorate([
|
|
138
|
+
flags.number({ name: 'batch-size', description: 'How many pending changes to read per round trip' }),
|
|
139
|
+
__metadata("design:type", Object)
|
|
140
|
+
], AuthzScopesRelay.prototype, "batchSize", void 0);
|
|
141
|
+
//# 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,37 @@
|
|
|
1
|
+
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
|
+
import { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
|
+
import type { FreezeStatus } from '../src/manager.js';
|
|
4
|
+
/**
|
|
5
|
+
* Qué hacer con el freeze vivo, en una función PURA (mismo patrón que
|
|
6
|
+
* `reconcileLines`): es la única decisión del comando y así tiene su caso
|
|
7
|
+
* sin montar un ace.
|
|
8
|
+
*
|
|
9
|
+
* Reglas:
|
|
10
|
+
* - Sin freeze vivo ⇒ no-op en verde (idempotente: descongelar lo
|
|
11
|
+
* descongelado no es un incidente).
|
|
12
|
+
* - Freeze de OPERADOR ⇒ se levanta (este comando es su otra mitad).
|
|
13
|
+
* - Freeze de OTRO dueño (`reconcile`, `platform`) ⇒ NO se levanta sin
|
|
14
|
+
* `--fence`: levantar la barrera de una pasada viva es exactamente el
|
|
15
|
+
* A1.3 que el token cierra. `--fence=<n>` es la decisión humana explícita
|
|
16
|
+
* («ese proceso murió sin lease»), y tiene que coincidir con el fence
|
|
17
|
+
* vivo — un fence viejo no levanta la ventana de otro.
|
|
18
|
+
*/
|
|
19
|
+
export declare function unfreezePlan(status: FreezeStatus | null, fence: number | undefined): {
|
|
20
|
+
action: 'noop' | 'lift' | 'refuse';
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* **Cierra la ventana de cutover** (3b-7): levanta el freeze de operador que
|
|
25
|
+
* abrió `authz:freeze`. La otra mitad de ese comando; ver su docblock.
|
|
26
|
+
*
|
|
27
|
+
* node ace authz:unfreeze # levanta la ventana del operador
|
|
28
|
+
* node ace authz:unfreeze --fence=7 # decisión humana: levanta ESE freeze aunque no sea de operador
|
|
29
|
+
*/
|
|
30
|
+
export default class AuthzUnfreeze extends BaseCommand {
|
|
31
|
+
static commandName: string;
|
|
32
|
+
static description: string;
|
|
33
|
+
static options: CommandOptions;
|
|
34
|
+
fence: number | undefined;
|
|
35
|
+
run(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=authz_unfreeze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz_unfreeze.d.ts","sourceRoot":"","sources":["../../commands/authz_unfreeze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,GAAG,IAAI,EAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB;IAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BzD;AAED;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,MAAM,CAAC,WAAW,SAAmB;IACrC,MAAM,CAAC,WAAW,SAAqF;IAEvG,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAKO,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAE3B,GAAG;CAqBV"}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
* Qué hacer con el freeze vivo, en una función PURA (mismo patrón que
|
|
13
|
+
* `reconcileLines`): es la única decisión del comando y así tiene su caso
|
|
14
|
+
* sin montar un ace.
|
|
15
|
+
*
|
|
16
|
+
* Reglas:
|
|
17
|
+
* - Sin freeze vivo ⇒ no-op en verde (idempotente: descongelar lo
|
|
18
|
+
* descongelado no es un incidente).
|
|
19
|
+
* - Freeze de OPERADOR ⇒ se levanta (este comando es su otra mitad).
|
|
20
|
+
* - Freeze de OTRO dueño (`reconcile`, `platform`) ⇒ NO se levanta sin
|
|
21
|
+
* `--fence`: levantar la barrera de una pasada viva es exactamente el
|
|
22
|
+
* A1.3 que el token cierra. `--fence=<n>` es la decisión humana explícita
|
|
23
|
+
* («ese proceso murió sin lease»), y tiene que coincidir con el fence
|
|
24
|
+
* vivo — un fence viejo no levanta la ventana de otro.
|
|
25
|
+
*/
|
|
26
|
+
export function unfreezePlan(status, fence) {
|
|
27
|
+
if (status === null) {
|
|
28
|
+
return { action: 'noop', message: 'No hay ningún freeze vivo: nada que levantar.' };
|
|
29
|
+
}
|
|
30
|
+
if (fence !== undefined && fence !== status.fence) {
|
|
31
|
+
return {
|
|
32
|
+
action: 'refuse',
|
|
33
|
+
message: `El fence vivo es ${status.fence} y pediste levantar el ${fence}: ese freeze ya no existe. ` +
|
|
34
|
+
`Mira el estado y repite con el fence actual si de verdad quieres levantarlo.`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (status.kind !== 'operator' && fence === undefined) {
|
|
38
|
+
return {
|
|
39
|
+
action: 'refuse',
|
|
40
|
+
message: `El freeze vivo NO es de operador: lo sostiene ${status.holder} (${status.reason}). ` +
|
|
41
|
+
`Levantárselo dejaría su pasada corriendo sin barrera (y su reporte lo delatará como lapsed). ` +
|
|
42
|
+
`Espera a que termine${status.untilMs === null ? '' : ' — o a que su lease venza solo'}; si su proceso ` +
|
|
43
|
+
`murió sin lease, la decisión humana es --fence=${status.fence}.`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
action: 'lift',
|
|
48
|
+
message: `Freeze de ${status.holder} (${status.reason}, fence ${status.fence}) levantado: la flota vuelve a escribir.`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* **Cierra la ventana de cutover** (3b-7): levanta el freeze de operador que
|
|
53
|
+
* abrió `authz:freeze`. La otra mitad de ese comando; ver su docblock.
|
|
54
|
+
*
|
|
55
|
+
* node ace authz:unfreeze # levanta la ventana del operador
|
|
56
|
+
* node ace authz:unfreeze --fence=7 # decisión humana: levanta ESE freeze aunque no sea de operador
|
|
57
|
+
*/
|
|
58
|
+
export default class AuthzUnfreeze extends BaseCommand {
|
|
59
|
+
static commandName = 'authz:unfreeze';
|
|
60
|
+
static description = 'Close the cutover window: lift the operator freeze and let the fleet write again';
|
|
61
|
+
static options = {
|
|
62
|
+
startApp: true,
|
|
63
|
+
};
|
|
64
|
+
async run() {
|
|
65
|
+
const { default: authorization } = await import('../services/main.js');
|
|
66
|
+
const status = await authorization.freezeStatus();
|
|
67
|
+
const plan = unfreezePlan(status, this.fence);
|
|
68
|
+
if (plan.action === 'noop') {
|
|
69
|
+
this.logger.success(plan.message);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (plan.action === 'refuse') {
|
|
73
|
+
this.logger.error(plan.message);
|
|
74
|
+
this.exitCode = 1;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const lifted = await authorization.unfreeze({ fence: status.fence, holder: status.holder });
|
|
78
|
+
if (!lifted) {
|
|
79
|
+
// Entre el SELECT y el UPDATE alguien lo levantó o venció: no es un error.
|
|
80
|
+
this.logger.success('El freeze ya no estaba (lo levantó su dueño o venció su lease).');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.logger.success(plan.message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
__decorate([
|
|
87
|
+
flags.number({
|
|
88
|
+
description: 'Lift exactly this freeze even if it is not an operator window (its owner died without a lease)',
|
|
89
|
+
}),
|
|
90
|
+
__metadata("design:type", Object)
|
|
91
|
+
], AuthzUnfreeze.prototype, "fence", void 0);
|
|
92
|
+
//# sourceMappingURL=authz_unfreeze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz_unfreeze.js","sourceRoot":"","sources":["../../commands/authz_unfreeze.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAIvD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAC1B,MAA2B,EAC3B,KAAyB;IAEzB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAAA;IACrF,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QAClD,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,OAAO,EACL,oBAAoB,MAAM,CAAC,KAAK,0BAA0B,KAAK,6BAA6B;gBAC5F,8EAA8E;SACjF,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtD,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,OAAO,EACL,iDAAiD,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,KAAK;gBACrF,+FAA+F;gBAC/F,uBAAuB,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gCAAgC,kBAAkB;gBACxG,kDAAkD,MAAM,CAAC,KAAK,GAAG;SACpE,CAAA;IACH,CAAC;IACD,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,aAAa,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,KAAK,0CAA0C;KACvH,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,MAAM,CAAC,WAAW,GAAG,gBAAgB,CAAA;IACrC,MAAM,CAAC,WAAW,GAAG,kFAAkF,CAAA;IAEvG,MAAM,CAAC,OAAO,GAAmB;QAC/B,QAAQ,EAAE,IAAI;KACf,CAAA;IAOD,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;QACtE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,CAAA;QACjD,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACjC,OAAM;QACR,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAC/B,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAO,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,2EAA2E;YAC3E,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,iEAAiE,CAAC,CAAA;YACtF,OAAM;QACR,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC;;AAtBO;IAHP,KAAK,CAAC,MAAM,CAAC;QACZ,WAAW,EAAE,gGAAgG;KAC9G,CAAC;;4CAC+B"}
|
package/build/commands/main.d.ts
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* node ace configure @jantstack/adonis-authz
|
|
4
4
|
*/
|
|
5
5
|
export { default as OpenFgaProvision } from './openfga_provision.js';
|
|
6
|
-
export { default as OpenFgaImport } from './openfga_import.js';
|
|
7
6
|
export { default as AuthzCatalogDiff } from './authz_catalog_diff.js';
|
|
8
7
|
export { default as AuthzCatalogSync } from './authz_catalog_sync.js';
|
|
8
|
+
export { default as AuthzCatalogPruneOrphans } from './authz_catalog_prune_orphans.js';
|
|
9
|
+
export { default as AuthzScopesRelay } from './authz_scopes_relay.js';
|
|
10
|
+
export { default as AuthzReconcile } from './authz_reconcile.js';
|
|
11
|
+
export { default as AuthzRelationsReconcile } from './authz_relations_reconcile.js';
|
|
12
|
+
export { default as AuthzFreeze } from './authz_freeze.js';
|
|
13
|
+
export { default as AuthzUnfreeze } from './authz_unfreeze.js';
|
|
9
14
|
//# sourceMappingURL=main.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;AACtF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AACnF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA"}
|
package/build/commands/main.js
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* node ace configure @jantstack/adonis-authz
|
|
4
4
|
*/
|
|
5
5
|
export { default as OpenFgaProvision } from './openfga_provision.js';
|
|
6
|
-
export { default as OpenFgaImport } from './openfga_import.js';
|
|
7
6
|
export { default as AuthzCatalogDiff } from './authz_catalog_diff.js';
|
|
8
7
|
export { default as AuthzCatalogSync } from './authz_catalog_sync.js';
|
|
8
|
+
export { default as AuthzCatalogPruneOrphans } from './authz_catalog_prune_orphans.js';
|
|
9
|
+
export { default as AuthzScopesRelay } from './authz_scopes_relay.js';
|
|
10
|
+
export { default as AuthzReconcile } from './authz_reconcile.js';
|
|
11
|
+
export { default as AuthzRelationsReconcile } from './authz_relations_reconcile.js';
|
|
12
|
+
export { default as AuthzFreeze } from './authz_freeze.js';
|
|
13
|
+
export { default as AuthzUnfreeze } from './authz_unfreeze.js';
|
|
9
14
|
//# sourceMappingURL=main.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;AACtF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AACnF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA"}
|
|
@@ -2,13 +2,22 @@ import { BaseCommand } from '@adonisjs/core/ace';
|
|
|
2
2
|
import { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
3
|
/**
|
|
4
4
|
* Provisiona OpenFGA para el driver `openfga` del motor de autorización:
|
|
5
|
-
* crea un store y escribe el authorization model
|
|
6
|
-
* ids para el .env (OPENFGA_STORE_ID / OPENFGA_MODEL_ID).
|
|
5
|
+
* crea un store y escribe el authorization model **`facts` (c2r)** del
|
|
6
|
+
* chasis. Imprime los ids para el .env (OPENFGA_STORE_ID / OPENFGA_MODEL_ID).
|
|
7
|
+
*
|
|
8
|
+
* **Publica el modelo `facts`** (3b-2k · K2): hasta 2.2 publicaba el del modo
|
|
9
|
+
* `resolver`, que ya no existe. Ese modelo declara CUATRO relaciones por
|
|
10
|
+
* permiso (`<P>`, `can_<P>`, `denied_<P>`, `permits_<P>`), así que necesita
|
|
11
|
+
* la lista de permisos: sale de los `catalogs` del config, resueltos aquí
|
|
12
|
+
* mismo (son funciones y no tocan la base). Sin `catalogs` no hay modelo que
|
|
13
|
+
* publicar y el comando sale ≠ 0 en vez de dejar un store que no responde a
|
|
14
|
+
* ninguna pregunta.
|
|
7
15
|
*
|
|
8
16
|
* Idempotencia: cada ejecución crea un store NUEVO (los stores son baratos y
|
|
9
17
|
* aislados); re-ejecutar sobre un store existente no es necesario salvo que
|
|
10
|
-
* cambie el modelo —
|
|
11
|
-
* versionado sobre el
|
|
18
|
+
* cambie el modelo —añadir o quitar un permiso del catálogo lo cambia— y en
|
|
19
|
+
* ese caso se usa --store-id para escribir un model nuevo versionado sobre el
|
|
20
|
+
* mismo store.
|
|
12
21
|
*
|
|
13
22
|
* @example
|
|
14
23
|
* node ace openfga:provision # usa OPENFGA_URL del .env
|
|
@@ -23,5 +32,38 @@ export default class OpenFgaProvision extends BaseCommand {
|
|
|
23
32
|
storeId: string | undefined;
|
|
24
33
|
name: string | undefined;
|
|
25
34
|
run(): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Los permisos del modelo, o `null` (y exit 1) si no hay ninguno: un modelo
|
|
37
|
+
* `facts` sin permisos no puede responder a nada, y descubrirlo aquí es
|
|
38
|
+
* mucho mejor que descubrirlo en el primer `authorize`.
|
|
39
|
+
*/
|
|
40
|
+
private resolvePermissions;
|
|
26
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Los slugs de permiso de TODOS los catálogos del config, sin duplicados y en
|
|
44
|
+
* orden estable (3b-2k · K2). Se exporta —y no es un método— para que se
|
|
45
|
+
* pueda juzgar sin montar un comando de ace: es la pieza que decide qué
|
|
46
|
+
* relaciones lleva el modelo `facts`, y una lista vacía es lo que hace que el
|
|
47
|
+
* comando se niegue a provisionar.
|
|
48
|
+
*
|
|
49
|
+
* Los catálogos del config son FUNCIONES del consumidor (pueden cargar otro
|
|
50
|
+
* módulo perezosamente) y no tocan la base: el modelo se publica antes de que
|
|
51
|
+
* haya una sola fila.
|
|
52
|
+
*/
|
|
53
|
+
export declare function permissionsOfCatalogs(config: any): Promise<string[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Los tipos de relación (ReBAC) que van FUSIONADOS en el modelo `facts`
|
|
56
|
+
* (Fase 4-8), leídos del CONFIG estático `relations.config` — o `undefined` si
|
|
57
|
+
* el consumidor no declaró relaciones (modelo facts-only, como hasta 4-8). Se
|
|
58
|
+
* exporta —y no es un método— para juzgar la decisión sin montar un ace: es la
|
|
59
|
+
* pieza que decide si un store recién aprovisionado acepta tuplas de relación.
|
|
60
|
+
*
|
|
61
|
+
* La fuente es el config (`relations.config`), NO `authz_relations_config` de
|
|
62
|
+
* la base: `openfga:provision` es `startApp: false` (bootstrap sin base) y el
|
|
63
|
+
* config es lo único que tiene cargado — igual que los permisos salen de
|
|
64
|
+
* `catalogs` y no de `authz_permissions`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function relationsConfigOf(config: any): {
|
|
67
|
+
objectTypes: readonly any[];
|
|
68
|
+
} | undefined;
|
|
27
69
|
//# sourceMappingURL=openfga_provision.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openfga_provision.d.ts","sourceRoot":"","sources":["../../commands/openfga_provision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD
|
|
1
|
+
{"version":3,"file":"openfga_provision.d.ts","sourceRoot":"","sources":["../../commands/openfga_provision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACvD,MAAM,CAAC,WAAW,SAAsB;IACxC,MAAM,CAAC,WAAW,SAAoE;IAEtF,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IAGvB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAG3B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IAE1B,GAAG;IA2DT;;;;OAIG;YACW,kBAAkB;CAajC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,GAAG;IAAE,WAAW,EAAE,SAAS,GAAG,EAAE,CAAA;CAAE,GAAG,SAAS,CAI1F"}
|
|
@@ -10,13 +10,22 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { BaseCommand, flags } from '@adonisjs/core/ace';
|
|
11
11
|
/**
|
|
12
12
|
* Provisiona OpenFGA para el driver `openfga` del motor de autorización:
|
|
13
|
-
* crea un store y escribe el authorization model
|
|
14
|
-
* ids para el .env (OPENFGA_STORE_ID / OPENFGA_MODEL_ID).
|
|
13
|
+
* crea un store y escribe el authorization model **`facts` (c2r)** del
|
|
14
|
+
* chasis. Imprime los ids para el .env (OPENFGA_STORE_ID / OPENFGA_MODEL_ID).
|
|
15
|
+
*
|
|
16
|
+
* **Publica el modelo `facts`** (3b-2k · K2): hasta 2.2 publicaba el del modo
|
|
17
|
+
* `resolver`, que ya no existe. Ese modelo declara CUATRO relaciones por
|
|
18
|
+
* permiso (`<P>`, `can_<P>`, `denied_<P>`, `permits_<P>`), así que necesita
|
|
19
|
+
* la lista de permisos: sale de los `catalogs` del config, resueltos aquí
|
|
20
|
+
* mismo (son funciones y no tocan la base). Sin `catalogs` no hay modelo que
|
|
21
|
+
* publicar y el comando sale ≠ 0 en vez de dejar un store que no responde a
|
|
22
|
+
* ninguna pregunta.
|
|
15
23
|
*
|
|
16
24
|
* Idempotencia: cada ejecución crea un store NUEVO (los stores son baratos y
|
|
17
25
|
* aislados); re-ejecutar sobre un store existente no es necesario salvo que
|
|
18
|
-
* cambie el modelo —
|
|
19
|
-
* versionado sobre el
|
|
26
|
+
* cambie el modelo —añadir o quitar un permiso del catálogo lo cambia— y en
|
|
27
|
+
* ese caso se usa --store-id para escribir un model nuevo versionado sobre el
|
|
28
|
+
* mismo store.
|
|
20
29
|
*
|
|
21
30
|
* @example
|
|
22
31
|
* node ace openfga:provision # usa OPENFGA_URL del .env
|
|
@@ -39,25 +48,60 @@ export default class OpenFgaProvision extends BaseCommand {
|
|
|
39
48
|
}
|
|
40
49
|
const { OpenFgaClient } = await import('@openfga/sdk');
|
|
41
50
|
// El subpath `/openfga` es la única puerta al SDK (D9).
|
|
42
|
-
const {
|
|
51
|
+
const { openFgaFactsModel, provisionOpenFgaStore } = await import('../src/openfga.js');
|
|
43
52
|
// Los holders del consumidor viven en SU config, no en el paquete.
|
|
44
53
|
const holderTypes = config?.holderTypes ?? {};
|
|
54
|
+
// Los PERMISOS del modelo (c2r) salen de los catálogos del config. Se
|
|
55
|
+
// resuelven aquí porque son funciones del consumidor (pueden cargar otro
|
|
56
|
+
// módulo) y no necesitan la base: el modelo se publica antes de que haya
|
|
57
|
+
// una sola fila.
|
|
58
|
+
const permissions = await this.resolvePermissions(config);
|
|
59
|
+
if (!permissions)
|
|
60
|
+
return;
|
|
61
|
+
// Los tipos de RELACIÓN (ReBAC) que el modelo lleva FUSIONADOS (Fase 4-8):
|
|
62
|
+
// salen del CONFIG estático (`relations.config`), igual que los permisos
|
|
63
|
+
// salen de `catalogs`. El comando es `startApp: false` (bootstrap del
|
|
64
|
+
// appliance, ANTES de que haya base) y no puede leer `authz_relations_config`
|
|
65
|
+
// de la BD; el config sí está cargado. Sin `relations.config` el modelo es
|
|
66
|
+
// facts-only, como hasta ahora. Con él, un store recién aprovisionado ya
|
|
67
|
+
// acepta tuplas de relación sin un `authz:catalog:sync` previo.
|
|
68
|
+
const relations = relationsConfigOf(config);
|
|
45
69
|
if (this.storeId) {
|
|
46
70
|
const client = new OpenFgaClient({ apiUrl, storeId: this.storeId });
|
|
47
|
-
const model = await client.writeAuthorizationModel(
|
|
71
|
+
const model = await client.writeAuthorizationModel(openFgaFactsModel(holderTypes, permissions, relations));
|
|
48
72
|
this.logger.success('Nuevo authorization model escrito en el store existente.');
|
|
73
|
+
if (relations)
|
|
74
|
+
this.logger.info(`Tipos de relación fusionados: ${relations.objectTypes.map((t) => t.type).join(', ')}`);
|
|
49
75
|
this.logger.log(`OPENFGA_STORE_ID=${this.storeId}`);
|
|
50
76
|
this.logger.log(`OPENFGA_MODEL_ID=${model.authorization_model_id}`);
|
|
51
77
|
return;
|
|
52
78
|
}
|
|
53
79
|
// El paquete no lee env: el default APP_NAME se resuelve aquí (chasis).
|
|
54
|
-
const { storeId, modelId } = await provisionOpenFgaStore(apiUrl, this.name ?? config?.openfga?.storeName ?? this.app.appName, holderTypes);
|
|
80
|
+
const { storeId, modelId } = await provisionOpenFgaStore(apiUrl, this.name ?? config?.openfga?.storeName ?? this.app.appName, holderTypes, permissions, relations);
|
|
81
|
+
if (relations)
|
|
82
|
+
this.logger.info(`Tipos de relación fusionados: ${relations.objectTypes.map((t) => t.type).join(', ')}`);
|
|
55
83
|
this.logger.success('Store + authorization model provisionados.');
|
|
56
84
|
this.logger.log('Añade al .env (junto a AUTHZ_DRIVER=openfga):');
|
|
57
85
|
this.logger.log(`OPENFGA_URL=${apiUrl}`);
|
|
58
86
|
this.logger.log(`OPENFGA_STORE_ID=${storeId}`);
|
|
59
87
|
this.logger.log(`OPENFGA_MODEL_ID=${modelId}`);
|
|
60
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Los permisos del modelo, o `null` (y exit 1) si no hay ninguno: un modelo
|
|
91
|
+
* `facts` sin permisos no puede responder a nada, y descubrirlo aquí es
|
|
92
|
+
* mucho mejor que descubrirlo en el primer `authorize`.
|
|
93
|
+
*/
|
|
94
|
+
async resolvePermissions(config) {
|
|
95
|
+
const slugs = await permissionsOfCatalogs(config);
|
|
96
|
+
if (slugs.length === 0) {
|
|
97
|
+
this.logger.error('El modelo `facts` declara cuatro relaciones por permiso: sin `catalogs` en ' +
|
|
98
|
+
'config/authorization.ts no hay modelo que publicar. Declara tus catálogos y repite ' +
|
|
99
|
+
'(el store que se creara sin ellos denegaría todo).');
|
|
100
|
+
this.exitCode = 1;
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return slugs;
|
|
104
|
+
}
|
|
61
105
|
}
|
|
62
106
|
__decorate([
|
|
63
107
|
flags.string({ description: 'OpenFGA API URL (defaults to OPENFGA_URL)' }),
|
|
@@ -71,4 +115,43 @@ __decorate([
|
|
|
71
115
|
flags.string({ description: 'Store name when creating one (default: APP_NAME del entorno)' }),
|
|
72
116
|
__metadata("design:type", Object)
|
|
73
117
|
], OpenFgaProvision.prototype, "name", void 0);
|
|
118
|
+
/**
|
|
119
|
+
* Los slugs de permiso de TODOS los catálogos del config, sin duplicados y en
|
|
120
|
+
* orden estable (3b-2k · K2). Se exporta —y no es un método— para que se
|
|
121
|
+
* pueda juzgar sin montar un comando de ace: es la pieza que decide qué
|
|
122
|
+
* relaciones lleva el modelo `facts`, y una lista vacía es lo que hace que el
|
|
123
|
+
* comando se niegue a provisionar.
|
|
124
|
+
*
|
|
125
|
+
* Los catálogos del config son FUNCIONES del consumidor (pueden cargar otro
|
|
126
|
+
* módulo perezosamente) y no tocan la base: el modelo se publica antes de que
|
|
127
|
+
* haya una sola fila.
|
|
128
|
+
*/
|
|
129
|
+
export async function permissionsOfCatalogs(config) {
|
|
130
|
+
const sources = config?.catalogs ?? [];
|
|
131
|
+
const slugs = new Set();
|
|
132
|
+
for (const source of sources) {
|
|
133
|
+
const catalog = await source();
|
|
134
|
+
for (const permission of catalog?.permissions ?? [])
|
|
135
|
+
slugs.add(permission.slug);
|
|
136
|
+
}
|
|
137
|
+
return [...slugs].sort();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Los tipos de relación (ReBAC) que van FUSIONADOS en el modelo `facts`
|
|
141
|
+
* (Fase 4-8), leídos del CONFIG estático `relations.config` — o `undefined` si
|
|
142
|
+
* el consumidor no declaró relaciones (modelo facts-only, como hasta 4-8). Se
|
|
143
|
+
* exporta —y no es un método— para juzgar la decisión sin montar un ace: es la
|
|
144
|
+
* pieza que decide si un store recién aprovisionado acepta tuplas de relación.
|
|
145
|
+
*
|
|
146
|
+
* La fuente es el config (`relations.config`), NO `authz_relations_config` de
|
|
147
|
+
* la base: `openfga:provision` es `startApp: false` (bootstrap sin base) y el
|
|
148
|
+
* config es lo único que tiene cargado — igual que los permisos salen de
|
|
149
|
+
* `catalogs` y no de `authz_permissions`.
|
|
150
|
+
*/
|
|
151
|
+
export function relationsConfigOf(config) {
|
|
152
|
+
const objectTypes = config?.relations?.config?.objectTypes;
|
|
153
|
+
if (!Array.isArray(objectTypes) || objectTypes.length === 0)
|
|
154
|
+
return undefined;
|
|
155
|
+
return { objectTypes };
|
|
156
|
+
}
|
|
74
157
|
//# sourceMappingURL=openfga_provision.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openfga_provision.js","sourceRoot":"","sources":["../../commands/openfga_provision.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAGvD
|
|
1
|
+
{"version":3,"file":"openfga_provision.js","sourceRoot":"","sources":["../../commands/openfga_provision.ts"],"names":[],"mappings":"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"}
|
package/build/configure.d.ts
CHANGED
|
@@ -5,6 +5,17 @@ import type Configure from '@adonisjs/core/commands/configure';
|
|
|
5
5
|
* Registra el provider, los comandos y el middleware, define las variables
|
|
6
6
|
* de entorno y PUBLICA en el proyecto lo que es suyo: la migración de las
|
|
7
7
|
* tablas `authz_*` y los dos configs (drivers + catálogo del nivel app).
|
|
8
|
+
*
|
|
9
|
+
* Es INTERACTIVO: pregunta lo MÍNIMO que cambia lo publicado —el driver por
|
|
10
|
+
* defecto y si publicar la migración de la outbox del árbol (opt-in, ver
|
|
11
|
+
* README)— con `command.prompt`. Lo que NO cambia según la respuesta no se
|
|
12
|
+
* pregunta: los dos configs siempre se publican con las dos costuras cableadas
|
|
13
|
+
* (el stub arranca en cualquier driver leyendo `AUTHZ_DRIVER`), así que la
|
|
14
|
+
* elección solo fija el DEFAULT de esa variable, no ramifica el stub —el que
|
|
15
|
+
* `configure.spec` compila sigue siendo el mismo—. Y las relaciones (Fase 4)
|
|
16
|
+
* NO se preguntan: sus tablas ya están en la migración del motor y su config
|
|
17
|
+
* es `defineRelationsConfig` en el propio proyecto; un prompt ahí no publicaría
|
|
18
|
+
* nada distinto.
|
|
8
19
|
*/
|
|
9
20
|
export declare function configure(command: Configure): Promise<void>;
|
|
10
21
|
//# sourceMappingURL=configure.d.ts.map
|
package/build/configure.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../configure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,mCAAmC,CAAA;AAG9D
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../configure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,mCAAmC,CAAA;AAG9D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,SAAS,iBA4EjD"}
|