@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.
- package/README.md +693 -36
- 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 +97 -0
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
- package/build/commands/authz_relations_reconcile.js +313 -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 +50 -10
- package/build/index.d.ts.map +1 -1
- package/build/index.js +45 -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 +55 -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 +137 -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 +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 +113 -0
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/database_relations_driver.js +679 -0
- package/build/src/drivers/database_relations_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +729 -122
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +2083 -476
- 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 +141 -0
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_relations_driver.js +590 -0
- package/build/src/drivers/openfga_relations_driver.js.map +1 -0
- package/build/src/errors.d.ts +290 -5
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +296 -7
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +141 -0
- package/build/src/freeze.d.ts.map +1 -0
- package/build/src/freeze.js +217 -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 +330 -4
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +1285 -188
- 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 +75 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -0
- package/build/src/relations/define_relations_config.js +173 -0
- package/build/src/relations/define_relations_config.js.map +1 -0
- package/build/src/relations/manager.d.ts +60 -0
- package/build/src/relations/manager.d.ts.map +1 -0
- package/build/src/relations/manager.js +213 -0
- package/build/src/relations/manager.js.map +1 -0
- package/build/src/relations/reconcile.d.ts +111 -0
- package/build/src/relations/reconcile.d.ts.map +1 -0
- package/build/src/relations/reconcile.js +200 -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 +298 -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/shared/sql_expiry.d.ts.map +1 -0
- package/build/src/shared/sql_expiry.js.map +1 -0
- package/build/src/shared/transaction_guard.d.ts +50 -0
- package/build/src/shared/transaction_guard.d.ts.map +1 -0
- package/build/src/shared/transaction_guard.js +60 -0
- package/build/src/shared/transaction_guard.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 +129 -4
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +912 -177
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +8 -2
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +4 -1
- 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 +73 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -0
- package/build/src/testing/relations_contract.js +1069 -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/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 +1053 -83
- 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 +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
- /package/build/src/{drivers → shared}/sql_expiry.d.ts +0 -0
- /package/build/src/{drivers → shared}/sql_expiry.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql_expiry.js","sourceRoot":"","sources":["../../../src/shared/sql_expiry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **¿De quién es esta transacción?** (L-1 · 🟠 9, auditor del panel `{trx}`;
|
|
3
|
+
* ascendido por el juez a REGLA del puerto `{trx}` de L-3/L-4.)
|
|
4
|
+
*
|
|
5
|
+
* Una escritura que se inscribe en la transacción del llamante solo cumple
|
|
6
|
+
* «los dos o ninguno» si esa transacción es de la MISMA conexión que usa
|
|
7
|
+
* quien escribe. `sqlScopeOutbox` lo daba por hecho: con un `trx` devolvía el
|
|
8
|
+
* `trx` tal cual e ignoraba `connection` en silencio, así que el encolado
|
|
9
|
+
* caía en la base del llamante — donde, si existe la tabla, ningún relay
|
|
10
|
+
* lee y la fila ni siquiera sale en `dead()`. Y `db` entero pasaba el
|
|
11
|
+
* duck-check (`.from`/`.table`) y escribía FUERA de toda transacción, sin un
|
|
12
|
+
* solo aviso: la mitigación entera apagada.
|
|
13
|
+
*
|
|
14
|
+
* Esta es la ÚNICA comprobación, para que la outbox de hoy y el
|
|
15
|
+
* `{ transaction }` de `grant`/`relate` de mañana no puedan desincronizarse:
|
|
16
|
+
*
|
|
17
|
+
* 1. tiene que ser un cliente de Lucid (`.from()`/`.table()`);
|
|
18
|
+
* 2. tiene que ser una TRANSACCIÓN ABIERTA (`isTransaction === true`): el
|
|
19
|
+
* `db` de Lucid y un `QueryClient` (`db.connection()`) no lo son;
|
|
20
|
+
* 3. tiene que pertenecer a la conexión de quien escribe (`connectionName`),
|
|
21
|
+
* cuando se conoce cuál es.
|
|
22
|
+
*
|
|
23
|
+
* Cualquiera de las tres ⇒ 500 `E_AUTHZ_CONFIG` nombrando la operación y las
|
|
24
|
+
* dos conexiones. Es un error de cableado del consumidor, no del backend ni de
|
|
25
|
+
* la petición; y va ANTES de tocar la base (cero sentencias por la
|
|
26
|
+
* transacción ajena).
|
|
27
|
+
*/
|
|
28
|
+
/** Lo mínimo que se exige de la transacción del llamante (un `TransactionClientContract` de Lucid). */
|
|
29
|
+
export interface CallerTransaction {
|
|
30
|
+
from(table: string): any;
|
|
31
|
+
table(table: string): any;
|
|
32
|
+
readonly isTransaction: true;
|
|
33
|
+
readonly connectionName: string;
|
|
34
|
+
}
|
|
35
|
+
export interface CallerTransactionOwner {
|
|
36
|
+
/**
|
|
37
|
+
* La conexión de quien ESCRIBE: la declarada (`connection` de la outbox o
|
|
38
|
+
* del driver) o la primaria del `db` de Lucid. `undefined` solo cuando no
|
|
39
|
+
* se puede saber (un `db` doble sin `primaryConnectionName`): entonces se
|
|
40
|
+
* exige que sea una transacción, pero no se juzga su conexión.
|
|
41
|
+
*/
|
|
42
|
+
connection: string | undefined;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Valida que `transaction` sea la transacción ABIERTA del llamante sobre la
|
|
46
|
+
* conexión de `owner`, y la devuelve tipada. `undefined`/`null` ⇒ `undefined`
|
|
47
|
+
* (no llegó ninguna; el llamante decide qué hacer).
|
|
48
|
+
*/
|
|
49
|
+
export declare function assertCallerTransaction(operation: string, transaction: unknown, owner: CallerTransactionOwner): CallerTransaction | undefined;
|
|
50
|
+
//# sourceMappingURL=transaction_guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction_guard.d.ts","sourceRoot":"","sources":["../../../src/shared/transaction_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,uGAAuG;AACvG,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;IACxB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,KAAK,EAAE,sBAAsB,GAC5B,iBAAiB,GAAG,SAAS,CAgC/B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **¿De quién es esta transacción?** (L-1 · 🟠 9, auditor del panel `{trx}`;
|
|
3
|
+
* ascendido por el juez a REGLA del puerto `{trx}` de L-3/L-4.)
|
|
4
|
+
*
|
|
5
|
+
* Una escritura que se inscribe en la transacción del llamante solo cumple
|
|
6
|
+
* «los dos o ninguno» si esa transacción es de la MISMA conexión que usa
|
|
7
|
+
* quien escribe. `sqlScopeOutbox` lo daba por hecho: con un `trx` devolvía el
|
|
8
|
+
* `trx` tal cual e ignoraba `connection` en silencio, así que el encolado
|
|
9
|
+
* caía en la base del llamante — donde, si existe la tabla, ningún relay
|
|
10
|
+
* lee y la fila ni siquiera sale en `dead()`. Y `db` entero pasaba el
|
|
11
|
+
* duck-check (`.from`/`.table`) y escribía FUERA de toda transacción, sin un
|
|
12
|
+
* solo aviso: la mitigación entera apagada.
|
|
13
|
+
*
|
|
14
|
+
* Esta es la ÚNICA comprobación, para que la outbox de hoy y el
|
|
15
|
+
* `{ transaction }` de `grant`/`relate` de mañana no puedan desincronizarse:
|
|
16
|
+
*
|
|
17
|
+
* 1. tiene que ser un cliente de Lucid (`.from()`/`.table()`);
|
|
18
|
+
* 2. tiene que ser una TRANSACCIÓN ABIERTA (`isTransaction === true`): el
|
|
19
|
+
* `db` de Lucid y un `QueryClient` (`db.connection()`) no lo son;
|
|
20
|
+
* 3. tiene que pertenecer a la conexión de quien escribe (`connectionName`),
|
|
21
|
+
* cuando se conoce cuál es.
|
|
22
|
+
*
|
|
23
|
+
* Cualquiera de las tres ⇒ 500 `E_AUTHZ_CONFIG` nombrando la operación y las
|
|
24
|
+
* dos conexiones. Es un error de cableado del consumidor, no del backend ni de
|
|
25
|
+
* la petición; y va ANTES de tocar la base (cero sentencias por la
|
|
26
|
+
* transacción ajena).
|
|
27
|
+
*/
|
|
28
|
+
import { AuthorizationConfigError } from '../errors.js';
|
|
29
|
+
/**
|
|
30
|
+
* Valida que `transaction` sea la transacción ABIERTA del llamante sobre la
|
|
31
|
+
* conexión de `owner`, y la devuelve tipada. `undefined`/`null` ⇒ `undefined`
|
|
32
|
+
* (no llegó ninguna; el llamante decide qué hacer).
|
|
33
|
+
*/
|
|
34
|
+
export function assertCallerTransaction(operation, transaction, owner) {
|
|
35
|
+
if (transaction === undefined || transaction === null)
|
|
36
|
+
return undefined;
|
|
37
|
+
const trx = transaction;
|
|
38
|
+
if (typeof trx.from !== 'function' || typeof trx.table !== 'function') {
|
|
39
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' no parece un cliente de Lucid (le faltan .from()/.table()). ` +
|
|
40
|
+
'Pasa el `trx` de db.transaction(); si usas otra cosa, implementa el puerto a mano.');
|
|
41
|
+
}
|
|
42
|
+
// El `db` de Lucid entero (`connection()`/`manager`/`primaryConnectionName`)
|
|
43
|
+
// tiene `.from()`/`.table()` y pasaba: escribía fuera de toda transacción.
|
|
44
|
+
if (typeof trx.connection === 'function' || typeof trx.primaryConnectionName === 'string') {
|
|
45
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' es el servicio \`db\` entero, no una transacción abierta: la escritura se ` +
|
|
46
|
+
'confirmaría sola, FUERA de tu transacción, y la mitigación no existiría. Pasa el `trx` de db.transaction().');
|
|
47
|
+
}
|
|
48
|
+
if (trx.isTransaction !== true) {
|
|
49
|
+
throw new AuthorizationConfigError(`${operation}: 'transaction' no es una transacción ABIERTA de Lucid (isTransaction !== true` +
|
|
50
|
+
`${typeof trx.connectionName === 'string' ? `, conexión '${trx.connectionName}'` : ''}): ` +
|
|
51
|
+
'un cliente de consulta confirma cada sentencia por su cuenta. Pasa el `trx` de db.transaction().');
|
|
52
|
+
}
|
|
53
|
+
if (owner.connection !== undefined && trx.connectionName !== owner.connection) {
|
|
54
|
+
throw new AuthorizationConfigError(`${operation}: la transacción es de la conexión '${String(trx.connectionName)}' y la escritura va por la ` +
|
|
55
|
+
`conexión '${owner.connection}': no puede inscribirse en ella («los dos o ninguno» sería falso). ` +
|
|
56
|
+
`Abre la transacción con db.connection('${owner.connection}').transaction(), o declara esa conexión aquí.`);
|
|
57
|
+
}
|
|
58
|
+
return trx;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=transaction_guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction_guard.js","sourceRoot":"","sources":["../../../src/shared/transaction_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAoBvD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,SAAiB,EACjB,WAAoB,EACpB,KAA6B;IAE7B,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACvE,MAAM,GAAG,GAAQ,WAAW,CAAA;IAC5B,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QACtE,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,8EAA8E;YACxF,oFAAoF,CACvF,CAAA;IACH,CAAC;IACD,6EAA6E;IAC7E,2EAA2E;IAC3E,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,qBAAqB,KAAK,QAAQ,EAAE,CAAC;QAC1F,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,4FAA4F;YACtG,6GAA6G,CAChH,CAAA;IACH,CAAC;IACD,IAAI,GAAG,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,gFAAgF;YAC1F,GAAG,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK;YAC1F,kGAAkG,CACrG,CAAA;IACH,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,cAAc,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;QAC9E,MAAM,IAAI,wBAAwB,CAChC,GAAG,SAAS,uCAAuC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,6BAA6B;YACxG,aAAa,KAAK,CAAC,UAAU,qEAAqE;YAClG,0CAA0C,KAAK,CAAC,UAAU,gDAAgD,CAC7G,CAAA;IACH,CAAC;IACD,OAAO,GAAwB,CAAA;AACjC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScopeDescendantsResolver } from './types.js';
|
|
1
|
+
import type { ScopeDescendantsResolver, ScopeEdgesEnumerator } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* `descendantsOf` opt-in sobre una tabla del consumidor con columna padre
|
|
4
4
|
* (2.1, B2). Genera UNA CTE recursiva (`WITH RECURSIVE`), la misma para
|
|
@@ -47,5 +47,51 @@ interface DatabaseLike {
|
|
|
47
47
|
connection(name?: string): any;
|
|
48
48
|
}
|
|
49
49
|
export declare function sqlDescendantsOf(options: SqlDescendantsOptions, database?: DatabaseLike): ScopeDescendantsResolver;
|
|
50
|
+
/**
|
|
51
|
+
* `scopes.enumerateEdges` sobre la MISMA tabla que `sqlDescendantsOf`
|
|
52
|
+
* (3b-3a): una página de aristas `hijo → padre` por llamada, ordenadas por la
|
|
53
|
+
* clave primaria y continuadas con un cursor.
|
|
54
|
+
*
|
|
55
|
+
* scopes: {
|
|
56
|
+
* resolveChain,
|
|
57
|
+
* enumerateEdges: sqlScopeEdges({
|
|
58
|
+
* table: 'organization_nodes', uuidColumn: 'uuid',
|
|
59
|
+
* parentColumn: 'parent_uuid', typeColumn: 'kind',
|
|
60
|
+
* }),
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* Lo usa `authz:reconcile --to=openfga` para reconstruir el árbol del store
|
|
64
|
+
* (y para borrar las aristas que la tabla ya no respalda).
|
|
65
|
+
*
|
|
66
|
+
* Decisiones que hay que conocer:
|
|
67
|
+
* - **el cursor es el uuid de la última fila**, y el orden es `ORDER BY
|
|
68
|
+
* uuid` (clave primaria: orden total y estable). Una pasada reanudada no
|
|
69
|
+
* se salta nodos aunque el árbol cambie entre páginas; lo que cambie por
|
|
70
|
+
* debajo del cursor entra en la siguiente pasada, que es idempotente.
|
|
71
|
+
* - **una fila cuyo padre NO existe no produce arista** (LEFT JOIN sin
|
|
72
|
+
* pareja). Es coherente con `resolveChain`, que devuelve `null` para ese
|
|
73
|
+
* nodo: no está en el árbol. No es silencioso: el destino conserva la
|
|
74
|
+
* arista vieja, `authz:reconcile` la cuenta como sobrante y sus hechos
|
|
75
|
+
* salen en `skipped` con el motivo.
|
|
76
|
+
* - `parentColumn IS NULL` es la raíz (`APP_SCOPE`).
|
|
77
|
+
*
|
|
78
|
+
* Mismos dialectos que `sqlDescendantsOf` (PG, MySQL 8, SQLite) y el mismo
|
|
79
|
+
* 500 `E_AUTHZ_UNSUPPORTED_DIALECT` para cualquier otro.
|
|
80
|
+
*/
|
|
81
|
+
export interface SqlScopeEdgesOptions {
|
|
82
|
+
table: string;
|
|
83
|
+
uuidColumn: string;
|
|
84
|
+
/** Columna con el uuid del padre; `NULL` = el nodo cuelga de `app`. */
|
|
85
|
+
parentColumn: string;
|
|
86
|
+
/** Columna con el `ScopeRef.type` de cada fila. Excluyente con `scopeType`. */
|
|
87
|
+
typeColumn?: string;
|
|
88
|
+
/** Tipo fijo de todos los nodos de la tabla (sin columna de tipo). Excluyente con `typeColumn`. */
|
|
89
|
+
scopeType?: string;
|
|
90
|
+
/** Nombre de la conexión Lucid (default: la primaria). */
|
|
91
|
+
connection?: string;
|
|
92
|
+
/** Deadline de cada consulta en ms (default 5000): vencido ⇒ 503. */
|
|
93
|
+
timeoutMs?: number;
|
|
94
|
+
}
|
|
95
|
+
export declare function sqlScopeEdges(options: SqlScopeEdgesOptions, database?: DatabaseLike): ScopeEdgesEnumerator;
|
|
50
96
|
export {};
|
|
51
97
|
//# sourceMappingURL=sql_descendants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql_descendants.d.ts","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sql_descendants.d.ts","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAa,oBAAoB,EAAY,MAAM,YAAY,CAAA;AAErG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAuBD,0FAA0F;AAC1F,UAAU,YAAY;IACpB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;CAC/B;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,GAAE,YAAiB,GAC1B,wBAAwB,CAiH1B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,GAAE,YAAiB,GAC1B,oBAAoB,CA+EtB"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import db from '@adonisjs/lucid/services/db';
|
|
2
2
|
import { AuthorizationConfigError, TooManyScopesError, UnsupportedDialectError } from './errors.js';
|
|
3
3
|
import { assertScope, assertScopeType } from './identity.js';
|
|
4
|
-
import { guardSql } from './
|
|
4
|
+
import { guardSql } from './shared/backend_guard.js';
|
|
5
5
|
import { APP_SCOPE_TYPE } from './types.js';
|
|
6
|
+
import { APP_SCOPE } from './types.js';
|
|
6
7
|
const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
7
8
|
/** Dialecto → carácter con el que cita identificadores (MySQL: backtick; el resto: comilla doble ANSI). */
|
|
8
9
|
const QUOTE_BY_DIALECT = {
|
|
@@ -126,4 +127,77 @@ export function sqlDescendantsOf(options, database = db) {
|
|
|
126
127
|
return rows.map((row) => ({ type: typeCol ? row.type : fixedType, uuid: row.uuid }));
|
|
127
128
|
};
|
|
128
129
|
}
|
|
130
|
+
export function sqlScopeEdges(options, database = db) {
|
|
131
|
+
const table = identifier('table', options.table);
|
|
132
|
+
const uuidCol = identifier('uuidColumn', options.uuidColumn);
|
|
133
|
+
const parentCol = identifier('parentColumn', options.parentColumn);
|
|
134
|
+
if ((options.typeColumn === undefined) === (options.scopeType === undefined)) {
|
|
135
|
+
throw new AuthorizationConfigError('sqlScopeEdges: declara exactamente uno de typeColumn (el tipo viene de la fila) o scopeType (tipo fijo).');
|
|
136
|
+
}
|
|
137
|
+
const typeCol = options.typeColumn === undefined ? null : identifier('typeColumn', options.typeColumn);
|
|
138
|
+
const fixedType = options.scopeType ?? null;
|
|
139
|
+
if (fixedType !== null) {
|
|
140
|
+
try {
|
|
141
|
+
assertScopeType(fixedType);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
throw new AuthorizationConfigError(`sqlScopeEdges: scopeType inválido: ${error.message}`);
|
|
145
|
+
}
|
|
146
|
+
if (fixedType === APP_SCOPE_TYPE) {
|
|
147
|
+
throw new AuthorizationConfigError("sqlScopeEdges: scopeType no puede ser 'app' (la raíz no tiene fila)");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
151
|
+
const connectionName = options.connection;
|
|
152
|
+
return async ({ limit, after }) => {
|
|
153
|
+
if (!Number.isInteger(limit) || limit < 1) {
|
|
154
|
+
throw new AuthorizationConfigError(`sqlScopeEdges: limit debe ser un entero >= 1 (llegó ${String(limit)})`);
|
|
155
|
+
}
|
|
156
|
+
const connection = database.connection(connectionName);
|
|
157
|
+
const dialect = connection?.dialect?.name ?? connection?.client?.driverName ?? 'desconocido';
|
|
158
|
+
const quote = QUOTE_BY_DIALECT[dialect];
|
|
159
|
+
if (!quote) {
|
|
160
|
+
throw new UnsupportedDialectError(`sqlScopeEdges: dialecto '${dialect}' sin observación en la suite (hoy: PostgreSQL, MySQL 8 y SQLite). ` +
|
|
161
|
+
`Implementa scopes.enumerateEdges a mano para este motor.`);
|
|
162
|
+
}
|
|
163
|
+
const q = (name) => `${quote}${name}${quote}`;
|
|
164
|
+
const childType = typeCol ? `t.${q(typeCol)}` : 'NULL';
|
|
165
|
+
const parentType = typeCol ? `p.${q(typeCol)}` : 'NULL';
|
|
166
|
+
const text = `SELECT t.${q(uuidCol)} AS ${q('child_uuid')}, ${childType} AS ${q('child_type')},` +
|
|
167
|
+
` t.${q(parentCol)} AS ${q('parent_uuid')}, ${parentType} AS ${q('parent_type')},` +
|
|
168
|
+
` p.${q(uuidCol)} AS ${q('parent_row')}` +
|
|
169
|
+
` FROM ${q(table)} t LEFT JOIN ${q(table)} p ON t.${q(parentCol)} = p.${q(uuidCol)}` +
|
|
170
|
+
(after === undefined ? '' : ` WHERE t.${q(uuidCol)} > ?`) +
|
|
171
|
+
` ORDER BY t.${q(uuidCol)} LIMIT ?`;
|
|
172
|
+
const bindings = after === undefined ? [limit] : [after, limit];
|
|
173
|
+
const result = await guardSql('sqlScopeEdges', 'enumerateEdges', timeoutMs, () => connection.rawQuery(text, bindings));
|
|
174
|
+
const rows = Array.isArray(result)
|
|
175
|
+
? result.length === 2 && Array.isArray(result[0]) && Array.isArray(result[1])
|
|
176
|
+
? result[0]
|
|
177
|
+
: result
|
|
178
|
+
: (result?.rows ?? []);
|
|
179
|
+
const edges = [];
|
|
180
|
+
for (const row of rows) {
|
|
181
|
+
const child = { type: typeCol ? row.child_type : fixedType, uuid: String(row.child_uuid) };
|
|
182
|
+
if (row.parent_uuid === null || row.parent_uuid === undefined) {
|
|
183
|
+
edges.push({ child, parent: APP_SCOPE });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
// Padre declarado que no tiene fila: el nodo NO está en el árbol
|
|
187
|
+
// (`resolveChain` devuelve `null` ahí). No se inventa la arista.
|
|
188
|
+
if (row.parent_row === null || row.parent_row === undefined)
|
|
189
|
+
continue;
|
|
190
|
+
edges.push({
|
|
191
|
+
child,
|
|
192
|
+
parent: { type: typeCol ? row.parent_type : fixedType, uuid: String(row.parent_uuid) },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// El cursor es la ÚLTIMA FILA LEÍDA, no la última arista emitida: si no,
|
|
196
|
+
// una fila con el padre colgando pararía la paginación en seco.
|
|
197
|
+
const last = rows[rows.length - 1];
|
|
198
|
+
return rows.length < limit
|
|
199
|
+
? { edges }
|
|
200
|
+
: { edges, cursor: String(last.child_uuid) };
|
|
201
|
+
};
|
|
202
|
+
}
|
|
129
203
|
//# sourceMappingURL=sql_descendants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql_descendants.js","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC5C,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sql_descendants.js","sourceRoot":"","sources":["../../src/sql_descendants.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '@japa/assert';
|
|
2
2
|
import type { Assert } from '@japa/assert';
|
|
3
|
-
import type { AuthorizationDriver, CatalogSpec } from '../types.js';
|
|
3
|
+
import type { AuthorizationDriver, CatalogSpec, SubjectRef } from '../types.js';
|
|
4
4
|
import type { ContractScopeTree } from './scope_tree.js';
|
|
5
5
|
/**
|
|
6
6
|
* Suite de contrato del sistema de autorización — EL JUEZ.
|
|
@@ -12,7 +12,7 @@ import type { ContractScopeTree } from './scope_tree.js';
|
|
|
12
12
|
* runAuthorizationDriverContract({
|
|
13
13
|
* name: 'mi-driver',
|
|
14
14
|
* level: '2.0', // omitido = 'core': solo los casos de 1.x
|
|
15
|
-
* capabilities: { hierarchyFacts: false,
|
|
15
|
+
* capabilities: { hierarchyFacts: false, transactionalWrites: false, truncationSignal: false,
|
|
16
16
|
* singleCheckAuthorize: false, injectableClock: false },
|
|
17
17
|
* seedCatalog: (catalog) => ..., // materializa roles/permisos
|
|
18
18
|
* makeDriver: (tree) => new MiDriver({ resolveChain: ... }), // recibe el árbol
|
|
@@ -41,8 +41,29 @@ import type { ContractScopeTree } from './scope_tree.js';
|
|
|
41
41
|
export interface DriverCapabilities {
|
|
42
42
|
/** El driver materializa el árbol como hechos propios (Fase 3b). */
|
|
43
43
|
hierarchyFacts: boolean;
|
|
44
|
-
/**
|
|
45
|
-
|
|
44
|
+
/**
|
|
45
|
+
* **`{ transaction }` en `grant`/`revoke`/`deny`/`removeDeny` ESCRIBE en
|
|
46
|
+
* la transacción del consumidor** — «los dos o ninguno con TU transacción»,
|
|
47
|
+
* nunca «no se pierde» (L-2, panel `{trx}` (C); mismo nombre que
|
|
48
|
+
* `AuthorizationDriverCapabilities.transactionalWrites` y que su par de
|
|
49
|
+
* relaciones). Es el ÚNICO par del juez con las DOS caras obligatorias:
|
|
50
|
+
* `true` sin caso `whenTrue` Y `false` sin caso `whenFalse` hacen que la
|
|
51
|
+
* suite lance al registrarse (los demás pares solo exigen la cara `true`;
|
|
52
|
+
* la lección de 4-2 es que una `whenFalse` ausente se salta en silencio).
|
|
53
|
+
* Con `false` el juez fija que `{ transaction }` es 500 `E_AUTHZ_UNSUPPORTED`
|
|
54
|
+
* nombrando driver y operación con CERO llamadas al driver (espía), y que
|
|
55
|
+
* `requireTransactionalWrites: true` lo convierte en 500 `E_AUTHZ_CONFIG`
|
|
56
|
+
* al RESOLVER. Con `true` (L-3) el juez abre una transacción de la conexión
|
|
57
|
+
* del driver (`DriverContractHarness.transactions`, default Lucid +
|
|
58
|
+
* `authz_*`) y fija, para las cuatro escrituras, que **rollback ⇒ CERO
|
|
59
|
+
* filas por CENSO** (no solo `authorize`), commit ⇒ aplicado, la escritura
|
|
60
|
+
* sin confirmar invisible para la autoridad, y que una transacción ajena es
|
|
61
|
+
* 500 `E_AUTHZ_CONFIG` sin una sentencia. `database` declara `true` (con
|
|
62
|
+
* pool ≥ 2; en `:memory:` el harness del paquete declara `false` porque la
|
|
63
|
+
* autoridad no tendría por dónde leer); `openfga` no puede ser otra cosa que
|
|
64
|
+
* `false`: una tupla no entra en una transacción SQL.
|
|
65
|
+
*/
|
|
66
|
+
transactionalWrites: boolean;
|
|
46
67
|
/**
|
|
47
68
|
* Los `list*` lanzan si el backend trunca. Ningún driver del paquete trunca
|
|
48
69
|
* (L0.7 se cerró enumerando con `Read` paginado), así que no hay caso para
|
|
@@ -89,6 +110,19 @@ export interface DriverCapabilities {
|
|
|
89
110
|
* store entero. En un harness por debajo de `'2.2'` declara `false`.
|
|
90
111
|
*/
|
|
91
112
|
purgeRole: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* `countRoleAssignments(uuids)` está implementado de verdad (3b-2j): el
|
|
115
|
+
* driver sabe decir cuántos hechos VIGENTES tiene cada rol, que es lo que
|
|
116
|
+
* hace verdadero el `stillGranting` de `pruneOrphanRoles` —el campo que se
|
|
117
|
+
* lee justo antes de un borrado destructivo—. Con `true` se juzga el
|
|
118
|
+
* conteo (caducidad estricta, por posición, 422 por uuid mal formado); con
|
|
119
|
+
* `false`, que el barrido diga `undefined` y **nunca** `false`: «no lo sé»
|
|
120
|
+
* no puede degradar a «no concede». Solo tiene casos en `level: '2.2'`.
|
|
121
|
+
*
|
|
122
|
+
* **Es la capacidad que este lote estrena y es breaking**: un driver de
|
|
123
|
+
* terceros de 2.2 la declara `false` hasta que traiga el método.
|
|
124
|
+
*/
|
|
125
|
+
countRoleAssignments: boolean;
|
|
92
126
|
/**
|
|
93
127
|
* Las escrituras del CATÁLOGO se serializan de verdad en el motor (3E ·
|
|
94
128
|
* R2, tester): dos `defineScopedRole` del mismo `(slug, nivel)` en
|
|
@@ -105,6 +139,67 @@ export interface DriverCapabilities {
|
|
|
105
139
|
* convierte la colisión en 503. Solo tiene casos en `level: '2.2'`.
|
|
106
140
|
*/
|
|
107
141
|
serializedCatalogWrites: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* El backend resuelve la MEMBRESÍA por sí mismo (3b-2e · E2). **`false` en
|
|
144
|
+
* los dos drivers del paquete, también en el modo `facts`** (panel 2, cruce
|
|
145
|
+
* 6): `hasRole`, `listRoles`, `listRoleScopes`, `listSubjects` y
|
|
146
|
+
* `listScopes` siguen usando el `resolveChain` del consumidor. Con `false`
|
|
147
|
+
* el juez lo DEMUESTRA con un espía sobre el árbol, que es lo que impide
|
|
148
|
+
* vender «sin SQL en el camino caliente» a secas: lo cierto es «sin SQL por
|
|
149
|
+
* request en `authorize`». La cara `true` no tiene caso todavía: no hay
|
|
150
|
+
* driver que lo cumpla.
|
|
151
|
+
*/
|
|
152
|
+
roleInheritanceNative: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Los `list*` enumeran también lo HEREDADO (3b-2e · E2). **`false` siempre
|
|
155
|
+
* en este paquete** (invariante 7): enumerar descendientes sería abierto, y
|
|
156
|
+
* en `openfga` obligaría a `ListObjects`, que trunca al tope del servidor
|
|
157
|
+
* SIN señal (S16, y `Check` y `ListObjects` ni siquiera coinciden en
|
|
158
|
+
* profundidad). Con `false` el juez fija que un grant en el ANCESTRO no
|
|
159
|
+
* aparece en las listas del descendiente aunque `authorize` diga `true`.
|
|
160
|
+
*/
|
|
161
|
+
listObjectsInherited: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* **Las LECTURAS canonizan la ortografía del scope contra el árbol del
|
|
164
|
+
* consumidor antes de buscar los hechos** (3b-2k · K1 · R2 (c)). El árbol
|
|
165
|
+
* del consumidor puede fundir dos formas del mismo id —el tipo `uuid` de
|
|
166
|
+
* PostgreSQL y la collation `*_ci` de MySQL leen `bbbb…` con y sin guiones
|
|
167
|
+
* como la MISMA fila—, y `authz_*` compara por bytes.
|
|
168
|
+
*
|
|
169
|
+
* Con `true` (driver `database`) `authorize` resuelve la cadena y usa
|
|
170
|
+
* `chain[0]`, la identidad CANÓNICA (invariante 17): un alias que el árbol
|
|
171
|
+
* funde con la fila real encuentra exactamente los mismos hechos que la
|
|
172
|
+
* forma canónica.
|
|
173
|
+
*
|
|
174
|
+
* Con `false` (`openfga` en modo `facts`) la DECISIÓN no pasa por el árbol
|
|
175
|
+
* —es la contrapartida de `singleCheckAuthorize`— así que el objeto del
|
|
176
|
+
* store se compone con la ortografía del LLAMANTE y un alias no encuentra
|
|
177
|
+
* nada: `authorize` responde `false` donde la forma canónica concede. Es
|
|
178
|
+
* fail-**CLOSED** y no evade ningún deny, pero **no es la misma respuesta
|
|
179
|
+
* que `database`** y por eso se declara. Lo que NO cambia es la ESCRITURA:
|
|
180
|
+
* `grant`/`revoke`/`removeDeny`/`purgeScope` sí canonizan en los dos
|
|
181
|
+
* drivers (3b-2h · 🟠 3 cerró la cara fail-open), y el juez lo fija en las
|
|
182
|
+
* DOS caras del par para que nadie lea esta capacidad como «en `facts` la
|
|
183
|
+
* ortografía da igual».
|
|
184
|
+
*/
|
|
185
|
+
canonicalScopeReads: boolean;
|
|
186
|
+
/**
|
|
187
|
+
* El driver sabe ser el **ORIGEN** de `authz:reconcile` (3b-3b):
|
|
188
|
+
* `enumerateFacts` entrega sus hechos por páginas, con su caducidad y **sin
|
|
189
|
+
* filtrar** (una asignación caducada tiene que LLEGAR para que el destino
|
|
190
|
+
* la cuente en `skipped`; filtrarla la haría desaparecer sin rastro).
|
|
191
|
+
*
|
|
192
|
+
* Con `true` el juez pasea las páginas, comprueba que el cursor avanza,
|
|
193
|
+
* que no se devuelven más de `limit` hechos y que la caducada sale con su
|
|
194
|
+
* instante. Con `false` juzga que el driver no puede ser origen y que
|
|
195
|
+
* `authz:reconcile` lo DICE —500 `E_AUTHZ_UNSUPPORTED` nombrando el
|
|
196
|
+
* método— en vez de leer cero hechos y vaciar el destino con `--prune`.
|
|
197
|
+
*
|
|
198
|
+
* `false` en el driver `database` a propósito: sus hechos son
|
|
199
|
+
* `authz_assignments`/`authz_denies`, el esquema publicado del paquete, y
|
|
200
|
+
* el destino los lee de ahí. Solo tiene casos en `level: '2.2'`.
|
|
201
|
+
*/
|
|
202
|
+
enumerateFacts: boolean;
|
|
108
203
|
}
|
|
109
204
|
export type ContractLevel = 'core' | '2.0' | '2.1' | '2.2';
|
|
110
205
|
export interface DriverContractHarness {
|
|
@@ -133,7 +228,31 @@ export interface DriverContractHarness {
|
|
|
133
228
|
*/
|
|
134
229
|
makeTwin?(driver: AuthorizationDriver, tree: ContractScopeTree): AuthorizationDriver | Promise<AuthorizationDriver>;
|
|
135
230
|
cleanup(): Promise<void>;
|
|
231
|
+
/**
|
|
232
|
+
* Solo con `transactionalWrites: true` (L-3): cómo abre el juez una
|
|
233
|
+
* transacción de LA CONEXIÓN DEL DRIVER y cómo cuenta los hechos de un
|
|
234
|
+
* holder en el backend — el CENSO: el rollback se juzga por filas, no solo
|
|
235
|
+
* por la respuesta de `authorize` (la lección del contrato de migración).
|
|
236
|
+
* Default: `db.transaction()` de Lucid (conexión primaria) y
|
|
237
|
+
* `authz_assignments`/`authz_denies`, lo que vale para el driver `database`.
|
|
238
|
+
* Un driver de terceros con otra conexión u otras tablas trae el suyo.
|
|
239
|
+
*/
|
|
240
|
+
transactions?: ContractTransactions;
|
|
241
|
+
}
|
|
242
|
+
/** Ver `DriverContractHarness.transactions`. */
|
|
243
|
+
export interface ContractTransactions {
|
|
244
|
+
begin(): Promise<{
|
|
245
|
+
client: unknown;
|
|
246
|
+
commit(): Promise<unknown>;
|
|
247
|
+
rollback(): Promise<unknown>;
|
|
248
|
+
}>;
|
|
249
|
+
census(subject: SubjectRef): Promise<{
|
|
250
|
+
assignments: number;
|
|
251
|
+
denies: number;
|
|
252
|
+
}>;
|
|
136
253
|
}
|
|
254
|
+
/** El default de `DriverContractHarness.transactions`: Lucid + `authz_*`. */
|
|
255
|
+
export declare function lucidContractTransactions(): ContractTransactions;
|
|
137
256
|
/**
|
|
138
257
|
* Lo mínimo que el juez necesita del runner. En producción es el `test` de
|
|
139
258
|
* Japa; en `tests/contract_harness.spec.ts` es una API falsa que solo anota
|
|
@@ -155,4 +274,10 @@ export interface ContractTestApi {
|
|
|
155
274
|
}
|
|
156
275
|
export declare function runAuthorizationDriverContract(harness: DriverContractHarness): void;
|
|
157
276
|
export declare function registerAuthorizationDriverContract(harness: DriverContractHarness, api: ContractTestApi): void;
|
|
277
|
+
/**
|
|
278
|
+
* La regla del guard, PURA (para que `contract_harness.spec.ts` la juzgue sin
|
|
279
|
+
* borrar caras): una capacidad `true` sin caso registrado queda sin cubrir;
|
|
280
|
+
* y una de `BOTH_FACES_REQUIRED` queda sin cubrir con CUALQUIER valor.
|
|
281
|
+
*/
|
|
282
|
+
export declare function uncoveredCapabilities(capabilities: DriverCapabilities, covered: ReadonlySet<keyof DriverCapabilities>): (keyof DriverCapabilities)[];
|
|
158
283
|
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/testing/contract.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAG1C,OAAO,KAAK,EACV,mBAAmB,EAEnB,WAAW,
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/testing/contract.ts"],"names":[],"mappings":"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"}
|