@jantstack/adonis-authz 2.0.0-alpha.1 → 2.4.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +934 -40
- package/build/commands/authz_catalog_diff.d.ts.map +1 -1
- package/build/commands/authz_catalog_diff.js +1 -2
- package/build/commands/authz_catalog_diff.js.map +1 -1
- package/build/commands/authz_catalog_prune_orphans.d.ts +78 -0
- package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -0
- package/build/commands/authz_catalog_prune_orphans.js +135 -0
- package/build/commands/authz_catalog_prune_orphans.js.map +1 -0
- package/build/commands/authz_catalog_sync.d.ts +17 -0
- package/build/commands/authz_catalog_sync.d.ts.map +1 -1
- package/build/commands/authz_catalog_sync.js +27 -4
- package/build/commands/authz_catalog_sync.js.map +1 -1
- package/build/commands/authz_freeze.d.ts +44 -0
- package/build/commands/authz_freeze.d.ts.map +1 -0
- package/build/commands/authz_freeze.js +94 -0
- package/build/commands/authz_freeze.js.map +1 -0
- package/build/commands/authz_reconcile.d.ts +111 -0
- package/build/commands/authz_reconcile.d.ts.map +1 -0
- package/build/commands/authz_reconcile.js +417 -0
- package/build/commands/authz_reconcile.js.map +1 -0
- package/build/commands/authz_relations_reconcile.d.ts +144 -0
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
- package/build/commands/authz_relations_reconcile.js +438 -0
- package/build/commands/authz_relations_reconcile.js.map +1 -0
- package/build/commands/authz_scopes_relay.d.ts +97 -0
- package/build/commands/authz_scopes_relay.d.ts.map +1 -0
- package/build/commands/authz_scopes_relay.js +344 -0
- package/build/commands/authz_scopes_relay.js.map +1 -0
- package/build/commands/authz_scopes_requeue.d.ts +80 -0
- package/build/commands/authz_scopes_requeue.d.ts.map +1 -0
- package/build/commands/authz_scopes_requeue.js +230 -0
- package/build/commands/authz_scopes_requeue.js.map +1 -0
- package/build/commands/authz_unfreeze.d.ts +45 -0
- package/build/commands/authz_unfreeze.d.ts.map +1 -0
- package/build/commands/authz_unfreeze.js +157 -0
- package/build/commands/authz_unfreeze.js.map +1 -0
- package/build/commands/main.d.ts +16 -8
- package/build/commands/main.d.ts.map +1 -1
- package/build/commands/main.js +59 -6
- package/build/commands/main.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +92 -4
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +155 -7
- package/build/commands/openfga_provision.js.map +1 -1
- package/build/configure.d.ts +11 -0
- package/build/configure.d.ts.map +1 -1
- package/build/configure.js +37 -1
- package/build/configure.js.map +1 -1
- package/build/index.d.ts +50 -11
- package/build/index.d.ts.map +1 -1
- package/build/index.js +49 -7
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts +31 -2
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +65 -2
- package/build/providers/authz_provider.js.map +1 -1
- package/build/services/relations.d.ts +14 -0
- package/build/services/relations.d.ts.map +1 -0
- package/build/services/relations.js +17 -0
- package/build/services/relations.js.map +1 -0
- package/build/src/{catalog.d.ts → catalog/catalog.d.ts} +41 -2
- package/build/src/catalog/catalog.d.ts.map +1 -0
- package/build/src/{catalog.js → catalog/catalog.js} +120 -14
- package/build/src/catalog/catalog.js.map +1 -0
- package/build/src/{catalog_cache.d.ts → catalog/catalog_cache.d.ts} +46 -22
- package/build/src/catalog/catalog_cache.d.ts.map +1 -0
- package/build/src/{catalog_cache.js → catalog/catalog_cache.js} +53 -43
- package/build/src/catalog/catalog_cache.js.map +1 -0
- package/build/src/define_config.d.ts +206 -3
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js +11 -0
- package/build/src/define_config.js.map +1 -1
- package/build/src/drivers/database_driver.d.ts +128 -7
- package/build/src/drivers/database_driver.d.ts.map +1 -1
- package/build/src/drivers/database_driver.js +510 -24
- package/build/src/drivers/database_driver.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +140 -0
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/database_relations_driver.js +748 -0
- package/build/src/drivers/database_relations_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +777 -122
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +2228 -477
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +384 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -0
- package/build/src/drivers/openfga_facts.js +836 -0
- package/build/src/drivers/openfga_facts.js.map +1 -0
- package/build/src/drivers/openfga_relations_driver.d.ts +186 -0
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_relations_driver.js +724 -0
- package/build/src/drivers/openfga_relations_driver.js.map +1 -0
- package/build/src/errors.d.ts +430 -6
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +453 -6
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +200 -0
- package/build/src/freeze.d.ts.map +1 -0
- package/build/src/freeze.js +306 -0
- package/build/src/freeze.js.map +1 -0
- package/build/src/http/app_access_middleware.d.ts.map +1 -0
- package/build/src/http/app_access_middleware.js.map +1 -0
- package/build/src/http/resource_access_middleware.d.ts +105 -0
- package/build/src/http/resource_access_middleware.d.ts.map +1 -0
- package/build/src/http/resource_access_middleware.js +81 -0
- package/build/src/http/resource_access_middleware.js.map +1 -0
- package/build/src/identity.d.ts +74 -1
- package/build/src/identity.d.ts.map +1 -1
- package/build/src/identity.js +100 -2
- package/build/src/identity.js.map +1 -1
- package/build/src/manager.d.ts +549 -6
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +2243 -193
- package/build/src/manager.js.map +1 -1
- package/build/src/models/authz_assignment.d.ts +7 -7
- package/build/src/models/authz_assignment.d.ts.map +1 -1
- package/build/src/models/authz_deny.d.ts +7 -7
- package/build/src/models/authz_deny.d.ts.map +1 -1
- package/build/src/models/authz_permission.d.ts +7 -7
- package/build/src/models/authz_permission.d.ts.map +1 -1
- package/build/src/models/authz_role.d.ts +7 -7
- package/build/src/models/authz_role.d.ts.map +1 -1
- package/build/src/models/authz_role_permission.d.ts +7 -7
- package/build/src/models/authz_role_permission.d.ts.map +1 -1
- package/build/src/openfga.d.ts +18 -2
- package/build/src/openfga.d.ts.map +1 -1
- package/build/src/openfga.js +15 -1
- package/build/src/openfga.js.map +1 -1
- package/build/src/reconcile.d.ts +37 -0
- package/build/src/reconcile.d.ts.map +1 -0
- package/build/src/reconcile.js +69 -0
- package/build/src/reconcile.js.map +1 -0
- package/build/src/relation_partition_trigger.d.ts +8 -0
- package/build/src/relation_partition_trigger.d.ts.map +1 -0
- package/build/src/relation_partition_trigger.js +93 -0
- package/build/src/relation_partition_trigger.js.map +1 -0
- package/build/src/relations/define_relations_config.d.ts +109 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -0
- package/build/src/relations/define_relations_config.js +211 -0
- package/build/src/relations/define_relations_config.js.map +1 -0
- package/build/src/relations/manager.d.ts +138 -0
- package/build/src/relations/manager.d.ts.map +1 -0
- package/build/src/relations/manager.js +494 -0
- package/build/src/relations/manager.js.map +1 -0
- package/build/src/relations/reconcile.d.ts +137 -0
- package/build/src/relations/reconcile.d.ts.map +1 -0
- package/build/src/relations/reconcile.js +294 -0
- package/build/src/relations/reconcile.js.map +1 -0
- package/build/src/relations_config_store.d.ts +22 -0
- package/build/src/relations_config_store.d.ts.map +1 -0
- package/build/src/relations_config_store.js +74 -0
- package/build/src/relations_config_store.js.map +1 -0
- package/build/src/scope_outbox.d.ts +123 -0
- package/build/src/scope_outbox.d.ts.map +1 -0
- package/build/src/scope_outbox.js +532 -0
- package/build/src/scope_outbox.js.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.d.ts +42 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.js +78 -1
- package/build/src/shared/backend_guard.js.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.d.ts +2 -0
- package/build/src/shared/sql_expiry.d.ts.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.js +4 -0
- package/build/src/shared/sql_expiry.js.map +1 -0
- package/build/src/shared/transaction_guard.d.ts +53 -0
- package/build/src/shared/transaction_guard.d.ts.map +1 -0
- package/build/src/shared/transaction_guard.js +74 -0
- package/build/src/shared/transaction_guard.js.map +1 -0
- package/build/src/sql_descendants.d.ts +55 -1
- package/build/src/sql_descendants.d.ts.map +1 -1
- package/build/src/sql_descendants.js +75 -1
- package/build/src/sql_descendants.js.map +1 -1
- package/build/src/testing/contract.d.ts +129 -4
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +915 -177
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +10 -2
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +5 -1
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/migration_contract.d.ts +293 -0
- package/build/src/testing/migration_contract.d.ts.map +1 -0
- package/build/src/testing/migration_contract.js +589 -0
- package/build/src/testing/migration_contract.js.map +1 -0
- package/build/src/testing/relations_contract.d.ts +73 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -0
- package/build/src/testing/relations_contract.js +1238 -0
- package/build/src/testing/relations_contract.js.map +1 -0
- package/build/src/testing/relations_reconcile_contract.d.ts +24 -0
- package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -0
- package/build/src/testing/relations_reconcile_contract.js +220 -0
- package/build/src/testing/relations_reconcile_contract.js.map +1 -0
- package/build/src/testing/scope_outbox_contract.d.ts +98 -0
- package/build/src/testing/scope_outbox_contract.d.ts.map +1 -0
- package/build/src/testing/scope_outbox_contract.js +677 -0
- package/build/src/testing/scope_outbox_contract.js.map +1 -0
- package/build/src/traits/authz_scopes.js +1 -1
- package/build/src/traits/authz_scopes.js.map +1 -1
- package/build/src/traits/has_uuid.d.ts +8 -8
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +1537 -84
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +65 -0
- package/build/src/types.js.map +1 -1
- package/build/stubs/config/authorization.stub +149 -5
- package/build/stubs/migration.stub +136 -0
- package/build/stubs/scopes_outbox_migration.stub +57 -0
- package/package.json +4 -2
- package/build/commands/openfga_import.d.ts +0 -34
- package/build/commands/openfga_import.d.ts.map +0 -1
- package/build/commands/openfga_import.js +0 -97
- package/build/commands/openfga_import.js.map +0 -1
- package/build/src/catalog.d.ts.map +0 -1
- package/build/src/catalog.js.map +0 -1
- package/build/src/catalog_cache.d.ts.map +0 -1
- package/build/src/catalog_cache.js.map +0 -1
- package/build/src/drivers/backend_guard.d.ts.map +0 -1
- package/build/src/drivers/backend_guard.js.map +0 -1
- package/build/src/drivers/sql_expiry.d.ts.map +0 -1
- package/build/src/drivers/sql_expiry.js.map +0 -1
- package/build/src/middleware/app_access_middleware.d.ts.map +0 -1
- package/build/src/middleware/app_access_middleware.js.map +0 -1
- /package/build/src/{middleware → http}/app_access_middleware.d.ts +0 -0
- /package/build/src/{middleware → http}/app_access_middleware.js +0 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineRelationsConfig` — la API declarativa de ReBAC (Fase 4, lote 4-2).
|
|
3
|
+
*
|
|
4
|
+
* Valida la config de relaciones del consumidor y devuelve un objeto
|
|
5
|
+
* CONGELADO que el manager de relaciones consulta para F-05 (`isDeclared`).
|
|
6
|
+
* Es la puerta de entrada, AGNÓSTICA de driver: rige igual en `database` y en
|
|
7
|
+
* `openfga` (paridad ⚪4). El generador del modelo fusionado
|
|
8
|
+
* (`src/drivers/openfga_facts.ts`, lote 4-1) hace la MISMA comprobación de
|
|
9
|
+
* reservados por defensa en profundidad al emitir el modelo —y además la de
|
|
10
|
+
* F-04 (colisión con un permiso del catálogo), que necesita las tuplas del
|
|
11
|
+
* catálogo y por eso vive en la capa del modelo—; las dos comparten la fuente
|
|
12
|
+
* única de tipos reservados (`RESERVED_FACTS_TYPES` en `src/identity.ts`).
|
|
13
|
+
*
|
|
14
|
+
* Pureza (regla 2 de `check_purity.mjs`): este módulo solo depende del puerto
|
|
15
|
+
* (`../types.js`), de los errores y de la gramática compartida
|
|
16
|
+
* (`../identity.js`); JAMÁS de `../manager` ni de `../drivers/*`. Es lo que
|
|
17
|
+
* mantiene `relations/` desacoplado de `roles/`.
|
|
18
|
+
*/
|
|
19
|
+
import { RelationConfigError, RelationTypeUnknownError, RelationUnknownError } from '../errors.js';
|
|
20
|
+
import { RESERVED_FACTS_TYPES, RESERVED_SLUGS, RESERVED_SLUG_PREFIXES } from '../identity.js';
|
|
21
|
+
/** La cota de FGA para el nombre de una relación (50). Un tipo de objeto llega a 254. */
|
|
22
|
+
const RELATION_NAME_MAX = 50;
|
|
23
|
+
const OBJECT_TYPE_MAX = 254;
|
|
24
|
+
/** Nombres FGA: minúsculas, dígitos y `._-`; sin `:`/`#`/`@`/espacios ni `|`. */
|
|
25
|
+
const FGA_NAME_FORMAT = /^[a-z0-9][a-z0-9._-]*$/;
|
|
26
|
+
function reject(message) {
|
|
27
|
+
throw new RelationConfigError(message);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* **F-05, la función ÚNICA** (L-0): rechaza un `object.type` no declarado
|
|
31
|
+
* (422 `E_AUTHZ_RELATION_TYPE_UNKNOWN`) o una `relation` no declarada para ese
|
|
32
|
+
* tipo (422 `E_AUTHZ_RELATION_UNKNOWN`). La aplican el `RelationsManager`
|
|
33
|
+
* (corta primero) Y los dos drivers de relaciones, ANTES de tocar el backend
|
|
34
|
+
* — la misma función, así que la misma clase, el mismo `code` y el mismo
|
|
35
|
+
* mensaje por cualquier puerta. Hacía falta en el driver (panel `{trx}`, 🔴 2
|
|
36
|
+
* del auditor): `manager.driver()` y `reconcileRelations` (que escribe con
|
|
37
|
+
* `to.relate`) entran por él, y sin la guarda
|
|
38
|
+
* `relate(evil, 'assignee', {type:'role_binding', id:<roleUuid>}, S)` componía
|
|
39
|
+
* en el store COMPARTIDO el id exacto de un binding de roles y
|
|
40
|
+
* `roles.authorize` pasaba de `false` a `true` (medido contra el `:8101`).
|
|
41
|
+
* La gramática de identidad no basta: `role_binding`/`assignee` son
|
|
42
|
+
* gramaticalmente válidos.
|
|
43
|
+
*
|
|
44
|
+
* **Cubre las OCHO operaciones del puerto** (`2.4.0-alpha.3`, cierre del
|
|
45
|
+
* 🔴 1 / 🟠 2 del auditor y cierre-2): hasta alpha.3 solo `relate`/`unrelate`
|
|
46
|
+
* la llamaban, y por `purgeObject({ type: 'role_binding', id: R }, S)` el
|
|
47
|
+
* puerto de relaciones BORRABA el binding real del store compartido
|
|
48
|
+
* (`authorize` pasaba de `true` a `false`, 0 tuplas, evento de auditoría
|
|
49
|
+
* limpio), y `listSubjects('assignee', role_binding)` enumeraba sus asignados
|
|
50
|
+
* sin catálogo ni `within`. **Son DOS funciones, no un opcional** (cierre-2,
|
|
51
|
+
* 🟠 1 del re-ataque): el primer cierre hizo `relation` opcional con un
|
|
52
|
+
* `if (relation === undefined) return` compartido por todas las llamadas, y
|
|
53
|
+
* eso APAGÓ F-05 en `relate`/`unrelate` sin relación (`request.input('relation')`
|
|
54
|
+
* ausente): antes `isDeclared('document', undefined)` era `false` ⇒ 422 con
|
|
55
|
+
* cero llamadas; con el opcional los dobles escribían la tupla, `openfga`
|
|
56
|
+
* devolvía 503 del servidor y `database` lo salvaba su driver (paridad rota),
|
|
57
|
+
* y `listSubjects(undefined)` devolvía la UNIÓN de relaciones del objeto.
|
|
58
|
+
* Esta función es ESTRICTA: la relación es obligatoria (ausente, `undefined`,
|
|
59
|
+
* vacía o no-string ⇒ 422 `E_AUTHZ_RELATION_UNKNOWN`) y la usan `relate`/
|
|
60
|
+
* `unrelate`/`check`/`listSubjects`/`membersOf` (+ `listObjects`, que también
|
|
61
|
+
* nombra una relación) y el userset de un sujeto (`{ object, relation }`).
|
|
62
|
+
* Quien NO nombra relación —`purgeObject`— usa `assertObjectTypeDeclared`.
|
|
63
|
+
*/
|
|
64
|
+
export function assertRelationDeclared(config, object, relation) {
|
|
65
|
+
assertObjectTypeDeclared(config, object);
|
|
66
|
+
if (typeof relation !== 'string' || relation.length === 0) {
|
|
67
|
+
throw new RelationUnknownError(`La relación de '${object.type}' es obligatoria y llegó ${relation === undefined ? 'undefined' : JSON.stringify(relation)} ` +
|
|
68
|
+
`(F-05): relate/unrelate/check/listObjects/listSubjects/membersOf exigen una relación declarada; ` +
|
|
69
|
+
`sin ella no hay tupla que escribir ni pregunta que responder.`);
|
|
70
|
+
}
|
|
71
|
+
if (!config.isDeclared(object.type, relation)) {
|
|
72
|
+
throw new RelationUnknownError(`La relación '${String(relation)}' no está declarada para el tipo '${object.type}' en ` +
|
|
73
|
+
`defineRelationsConfig (F-05).`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* **F-05 sobre el TIPO solo** (cierre-2 de alpha.3): la mitad de F-05 que
|
|
78
|
+
* aplican las operaciones que NO nombran relación —`purgeObject`— y la primera
|
|
79
|
+
* comprobación de `assertRelationDeclared`. Un tipo no declarado (o un objeto
|
|
80
|
+
* que no es `{ type }`) ⇒ 422 `E_AUTHZ_RELATION_TYPE_UNKNOWN`. Separada de la
|
|
81
|
+
* estricta a propósito: deducir «solo el tipo» de un `relation === undefined`
|
|
82
|
+
* era lo que apagaba F-05 en `relate`/`unrelate` sin relación (🟠 1 del
|
|
83
|
+
* re-ataque del auditor).
|
|
84
|
+
*/
|
|
85
|
+
export function assertObjectTypeDeclared(config, object) {
|
|
86
|
+
if (!object || typeof object !== 'object' || typeof object.type !== 'string') {
|
|
87
|
+
throw new RelationTypeUnknownError(`Objeto de relación inválido: se esperaba { type, id } y llegó ${JSON.stringify(object)}.`);
|
|
88
|
+
}
|
|
89
|
+
if (!config.hasType(object.type)) {
|
|
90
|
+
throw new RelationTypeUnknownError(`El tipo de objeto '${object.type}' no está declarado en defineRelationsConfig (F-05): ` +
|
|
91
|
+
`relate/unrelate/purgeObject/purgeSubject/check/listObjects/listSubjects/membersOf solo aceptan ` +
|
|
92
|
+
`tipos declarados. En el store compartido un tipo no declarado podría componer el id de un ` +
|
|
93
|
+
`'role_binding' real y escalar a roles.authorize, purgarlo o enumerar sus asignados.`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
98
|
+
* `E_AUTHZ_RELATION_CONFIG` (misma clase que el gate del modelo del lote 4-1).
|
|
99
|
+
*/
|
|
100
|
+
export function defineRelationsConfig(spec) {
|
|
101
|
+
if (!spec || typeof spec !== 'object') {
|
|
102
|
+
reject(`Config de relaciones inválida: se esperaba un objeto y llegó ${JSON.stringify(spec)}.`);
|
|
103
|
+
}
|
|
104
|
+
// `membersOf` SOLO puede vivir en las opciones de `database` (⚪ del tester):
|
|
105
|
+
// ponerlo en la raíz o en un futuro bloque `openfga` es un error de
|
|
106
|
+
// configuración —`openfga` no puede resolver la transitiva sin truncar—.
|
|
107
|
+
if ('membersOf' in spec) {
|
|
108
|
+
reject(`Config de relaciones inválida: 'membersOf' es una opción del driver 'database' ` +
|
|
109
|
+
`(membresía transitiva por CTE recursiva) y va en 'database.membersOf', no en la raíz. ` +
|
|
110
|
+
`En 'openfga' la transitiva sería 'ListUsers', que trunca al tope del servidor.`);
|
|
111
|
+
}
|
|
112
|
+
if (!Array.isArray(spec.objectTypes) || spec.objectTypes.length === 0) {
|
|
113
|
+
reject(`Config de relaciones inválida: 'objectTypes' tiene que ser un array no vacío.`);
|
|
114
|
+
}
|
|
115
|
+
const holderTypes = spec.holderTypes ?? [];
|
|
116
|
+
for (const holder of holderTypes) {
|
|
117
|
+
if (typeof holder !== 'string') {
|
|
118
|
+
reject(`Config de relaciones inválida: un holder type no es una cadena (${JSON.stringify(holder)}).`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const reservedTypes = new Set([...RESERVED_FACTS_TYPES, ...holderTypes]);
|
|
122
|
+
const seenTypes = new Set();
|
|
123
|
+
for (const objectType of spec.objectTypes) {
|
|
124
|
+
const type = objectType?.type;
|
|
125
|
+
if (typeof type !== 'string' || !FGA_NAME_FORMAT.test(type) || type.length > OBJECT_TYPE_MAX) {
|
|
126
|
+
reject(`Config de relaciones inválida: tipo de objeto ${JSON.stringify(type)} no es un tipo FGA válido ` +
|
|
127
|
+
`(minúsculas, dígitos y '._-'; sin ':'/'#'/'@'/'|'/espacios; 1-${OBJECT_TYPE_MAX} caracteres).`);
|
|
128
|
+
}
|
|
129
|
+
if (reservedTypes.has(type)) {
|
|
130
|
+
reject(`Config de relaciones inválida: el tipo de objeto '${type}' colisiona con un tipo reservado del ` +
|
|
131
|
+
`modelo compartido (${[...RESERVED_FACTS_TYPES].join(', ')}` +
|
|
132
|
+
`${holderTypes.length ? ', y los holder types ' + holderTypes.join(', ') : ''}). ` +
|
|
133
|
+
`En el store compartido un tipo de relaciones no puede duplicar uno de 'facts' (⚪4): ` +
|
|
134
|
+
`si pudiera declarar 'role_binding', 'relate' compondría el id de un binding real y escalaría a ` +
|
|
135
|
+
`roles.authorize. Renómbralo.`);
|
|
136
|
+
}
|
|
137
|
+
if (seenTypes.has(type)) {
|
|
138
|
+
reject(`Config de relaciones inválida: el tipo de objeto '${type}' está declarado dos veces.`);
|
|
139
|
+
}
|
|
140
|
+
seenTypes.add(type);
|
|
141
|
+
if (!Array.isArray(objectType.relations) || objectType.relations.length === 0) {
|
|
142
|
+
reject(`Config de relaciones inválida: el tipo '${type}' no declara ninguna relación.`);
|
|
143
|
+
}
|
|
144
|
+
const own = new Set();
|
|
145
|
+
for (const relation of objectType.relations) {
|
|
146
|
+
const name = relation?.name;
|
|
147
|
+
if (typeof name !== 'string' || !FGA_NAME_FORMAT.test(name)) {
|
|
148
|
+
reject(`Config de relaciones inválida: relación ${JSON.stringify(name)} del tipo '${type}' no es un ` +
|
|
149
|
+
`nombre de relación válido (minúsculas, dígitos y '._-').`);
|
|
150
|
+
}
|
|
151
|
+
if (name.length > RELATION_NAME_MAX) {
|
|
152
|
+
reject(`Config de relaciones inválida: la relación '${name}' del tipo '${type}' tiene ${name.length} ` +
|
|
153
|
+
`caracteres y FGA admite ${RELATION_NAME_MAX}.`);
|
|
154
|
+
}
|
|
155
|
+
if (RESERVED_SLUGS.has(name)) {
|
|
156
|
+
reject(`Config de relaciones inválida: la relación '${type}#${name}' usa un nombre reservado del modelo ` +
|
|
157
|
+
`facts (${[...RESERVED_SLUGS].join(', ')}): elegiría una relación propia de 'facts' (⚪4).`);
|
|
158
|
+
}
|
|
159
|
+
const family = RESERVED_SLUG_PREFIXES.find((prefix) => name.startsWith(prefix));
|
|
160
|
+
if (family) {
|
|
161
|
+
reject(`Config de relaciones inválida: la relación '${type}#${name}' empieza por '${family}', prefijo ` +
|
|
162
|
+
`reservado de las relaciones derivadas del modelo facts (${RESERVED_SLUG_PREFIXES.join(', ')}): ` +
|
|
163
|
+
`pisaría el nombre de un permiso proyectado (⚪4).`);
|
|
164
|
+
}
|
|
165
|
+
if (own.has(name)) {
|
|
166
|
+
reject(`Config de relaciones inválida: la relación '${type}#${name}' está declarada dos veces.`);
|
|
167
|
+
}
|
|
168
|
+
own.add(name);
|
|
169
|
+
}
|
|
170
|
+
// Los `includes` refieren relaciones del MISMO tipo (un nivel, SIN `from`).
|
|
171
|
+
for (const relation of objectType.relations) {
|
|
172
|
+
for (const included of relation.includes ?? []) {
|
|
173
|
+
if (typeof included !== 'string') {
|
|
174
|
+
reject(`Config de relaciones inválida: un 'includes' de '${type}#${relation.name}' no es una cadena.`);
|
|
175
|
+
}
|
|
176
|
+
// Un `from` (`viewer from parent`) se escribe con un separador; v1 no lo soporta.
|
|
177
|
+
if (/[:#@|. ]/.test(included) && !own.has(included)) {
|
|
178
|
+
reject(`Config de relaciones inválida: '${type}#${relation.name}' incluye '${included}', que parece una ` +
|
|
179
|
+
`herencia cross-objeto ('from'). v1 solo soporta includes de un nivel y del MISMO tipo.`);
|
|
180
|
+
}
|
|
181
|
+
if (!own.has(included)) {
|
|
182
|
+
reject(`Config de relaciones inválida: '${type}#${relation.name}' incluye '${included}', que no es una ` +
|
|
183
|
+
`relación de '${type}'. Los includes son de un nivel y del mismo tipo (v1 no soporta 'from').`);
|
|
184
|
+
}
|
|
185
|
+
if (included === relation.name) {
|
|
186
|
+
reject(`Config de relaciones inválida: '${type}#${relation.name}' se incluye a sí misma.`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const declared = new Map();
|
|
192
|
+
// `group` es el tipo BUILT-IN de las relaciones (el portador de los
|
|
193
|
+
// usersets, `group:g#member`): lo emite SIEMPRE el generador del modelo, no
|
|
194
|
+
// el consumidor —por eso NO se declara en `objectTypes` (arriba se rechaza)
|
|
195
|
+
// pero SÍ es un tipo válido para F-05: `relate(group:g#member, viewer, doc)`
|
|
196
|
+
// y `relate(u, member, group:g)` son legales. `role_binding`/`scope`/`role`
|
|
197
|
+
// siguen fuera: la frontera del 🔴 se mantiene.
|
|
198
|
+
declared.set('group', new Set(['member']));
|
|
199
|
+
const frozenTypes = spec.objectTypes.map((objectType) => {
|
|
200
|
+
const relations = objectType.relations.map((relation) => Object.freeze({ name: relation.name, includes: relation.includes ? Object.freeze([...relation.includes]) : undefined }));
|
|
201
|
+
declared.set(objectType.type, new Set(relations.map((r) => r.name)));
|
|
202
|
+
return Object.freeze({ type: objectType.type, relations: Object.freeze(relations) });
|
|
203
|
+
});
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
objectTypes: Object.freeze(frozenTypes),
|
|
206
|
+
membersOf: spec.database?.membersOf === true,
|
|
207
|
+
hasType: (objectType) => declared.has(objectType),
|
|
208
|
+
isDeclared: (objectType, relation) => declared.get(objectType)?.has(relation) ?? false,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=define_relations_config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define_relations_config.js","sourceRoot":"","sources":["../../../src/relations/define_relations_config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAClG,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAG7F,yFAAyF;AACzF,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAC5B,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,iFAAiF;AACjF,MAAM,eAAe,GAAG,wBAAwB,CAAA;AA2DhD,SAAS,MAAM,CAAC,OAAe;IAC7B,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAA;AACxC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAuB,EACvB,MAAoC,EACpC,QAAgB;IAEhB,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,oBAAoB,CAC5B,mBAAmB,MAAM,CAAC,IAAI,4BAA4B,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG;YAC1H,kGAAkG;YAClG,+DAA+D,CAClE,CAAA;IACH,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,oBAAoB,CAC5B,gBAAgB,MAAM,CAAC,QAAQ,CAAC,qCAAqC,MAAM,CAAC,IAAI,OAAO;YACrF,+BAA+B,CAClC,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAuB,EAAE,MAAoC;IACpG,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7E,MAAM,IAAI,wBAAwB,CAChC,iEAAiE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAC3F,CAAA;IACH,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,wBAAwB,CAChC,sBAAsB,MAAM,CAAC,IAAI,uDAAuD;YACtF,iGAAiG;YACjG,4FAA4F;YAC5F,qFAAqF,CACxF,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAyB;IAC7D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,MAAM,CAAC,gEAAgE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACjG,CAAC;IACD,6EAA6E;IAC7E,oEAAoE;IACpE,yEAAyE;IACzE,IAAI,WAAW,IAAK,IAA2C,EAAE,CAAC;QAChE,MAAM,CACJ,iFAAiF;YAC/E,wFAAwF;YACxF,gFAAgF,CACnF,CAAA;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtE,MAAM,CAAC,+EAA+E,CAAC,CAAA;IACzF,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAA;IAC1C,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,CAAC,mEAAmE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACvG,CAAC;IACH,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,oBAAoB,EAAE,GAAG,WAAW,CAAC,CAAC,CAAA;IAEhF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IACnC,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,UAAU,EAAE,IAAI,CAAA;QAC7B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;YAC7F,MAAM,CACJ,iDAAiD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,4BAA4B;gBAC/F,iEAAiE,eAAe,eAAe,CAClG,CAAA;QACH,CAAC;QACD,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,CACJ,qDAAqD,IAAI,wCAAwC;gBAC/F,sBAAsB,CAAC,GAAG,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC5D,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,uBAAuB,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK;gBAClF,sFAAsF;gBACtF,iGAAiG;gBACjG,8BAA8B,CACjC,CAAA;QACH,CAAC;QACD,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,qDAAqD,IAAI,6BAA6B,CAAC,CAAA;QAChG,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9E,MAAM,CAAC,2CAA2C,IAAI,gCAAgC,CAAC,CAAA;QACzF,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;QAC7B,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAA;YAC3B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5D,MAAM,CACJ,2CAA2C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,IAAI,aAAa;oBAC5F,0DAA0D,CAC7D,CAAA;YACH,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;gBACpC,MAAM,CACJ,+CAA+C,IAAI,eAAe,IAAI,WAAW,IAAI,CAAC,MAAM,GAAG;oBAC7F,2BAA2B,iBAAiB,GAAG,CAClD,CAAA;YACH,CAAC;YACD,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,CACJ,+CAA+C,IAAI,IAAI,IAAI,uCAAuC;oBAChG,UAAU,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,kDAAkD,CAC7F,CAAA;YACH,CAAC;YACD,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;YAC/E,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CACJ,+CAA+C,IAAI,IAAI,IAAI,kBAAkB,MAAM,aAAa;oBAC9F,2DAA2D,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;oBACjG,kDAAkD,CACrD,CAAA;YACH,CAAC;YACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,MAAM,CAAC,+CAA+C,IAAI,IAAI,IAAI,6BAA6B,CAAC,CAAA;YAClG,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACf,CAAC;QAED,4EAA4E;QAC5E,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YAC5C,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;gBAC/C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBACjC,MAAM,CAAC,oDAAoD,IAAI,IAAI,QAAQ,CAAC,IAAI,qBAAqB,CAAC,CAAA;gBACxG,CAAC;gBACD,kFAAkF;gBAClF,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACpD,MAAM,CACJ,mCAAmC,IAAI,IAAI,QAAQ,CAAC,IAAI,cAAc,QAAQ,oBAAoB;wBAChG,wFAAwF,CAC3F,CAAA;gBACH,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvB,MAAM,CACJ,mCAAmC,IAAI,IAAI,QAAQ,CAAC,IAAI,cAAc,QAAQ,mBAAmB;wBAC/F,gBAAgB,IAAI,0EAA0E,CACjG,CAAA;gBACH,CAAC;gBACD,IAAI,QAAQ,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAC/B,MAAM,CAAC,mCAAmC,IAAI,IAAI,QAAQ,CAAC,IAAI,0BAA0B,CAAC,CAAA;gBAC5F,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC/C,oEAAoE;IACpE,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,gDAAgD;IAChD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAoC,EAAE,EAAE,CAClF,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CACxH,CAAA;QACD,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAA6B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAChG,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IACtF,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;QACvC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,KAAK,IAAI;QAC5C,OAAO,EAAE,CAAC,UAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;QACzD,UAAU,EAAE,CAAC,UAAkB,EAAE,QAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK;KACvG,CAAoB,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { RelObject, RelSubject, RelationRef, RelationWriteEvent, RelationWriteOptions, RelationsDriver, RelationsDriverCapabilities, RelationObjectsPage, RelationSubjectsPage, RelationPage, RelationTuplePage, RelationPurgeOptions, ScopeRef } from '../types.js';
|
|
2
|
+
import type { RelationsConfig } from './define_relations_config.js';
|
|
3
|
+
export interface RelationsManagerOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Comprobación PURA de escritura (R-13): recibe la referencia completa de la
|
|
6
|
+
* tupla (sujeto, relación, objeto, partición, operación) y LANZA para
|
|
7
|
+
* rechazarla. Corre DESPUÉS de F-05 y ANTES de tocar el driver. **No
|
|
8
|
+
* devuelve veredictos**: todo retorno distinto de `undefined` —una promesa,
|
|
9
|
+
* un `false`, un `true`, una función con `.then`— es 500 `E_AUTHZ_CONFIG`
|
|
10
|
+
* antes del driver (2.4.0-alpha.3 y su cierre: un `false` devuelto no
|
|
11
|
+
* denegaba nada y la escritura entraba).
|
|
12
|
+
*/
|
|
13
|
+
assertWrite?(ref: RelationRef): void;
|
|
14
|
+
/**
|
|
15
|
+
* Auditoría: se notifica DESPUÉS de que el driver vuelva, con el `actor`
|
|
16
|
+
* (validado), `transactional: true` con `{ transaction }` e
|
|
17
|
+
* `indeterminate: true` al vencer el deadline (invariante 13). Puede ser
|
|
18
|
+
* `async` (la promesa devuelta SE ESPERA); si lanza o rechaza, se registra y
|
|
19
|
+
* NO tumba la escritura ya aplicada (2.4.0-alpha.3, paridad con
|
|
20
|
+
* `hooks.onWrite`). Se tipa `void` (y no `void | Promise<void>`) para no
|
|
21
|
+
* romper a quien ya lo construye a mano con `(e) => events.push(e)`: un
|
|
22
|
+
* retorno cualquiera solo es asignable a `void` a secas.
|
|
23
|
+
*/
|
|
24
|
+
onRelationWrite?(event: RelationWriteEvent): void;
|
|
25
|
+
/** `true` exige `actor` en toda escritura (paridad con `requireActor` de roles). */
|
|
26
|
+
requireActor?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Reloj de pared (R-15, paridad con `config.clock` de roles, 2.5 · J1): se
|
|
29
|
+
* aplica al driver con `withClock` al construir; un driver sin `withClock`
|
|
30
|
+
* con `clock` declarado es 500 `E_AUTHZ_CONFIG` (el reloj mentiría).
|
|
31
|
+
*/
|
|
32
|
+
clock?: () => Date;
|
|
33
|
+
/**
|
|
34
|
+
* Deadline TOTAL (ms, default 5000) de la lectura de la barrera del freeze
|
|
35
|
+
* (paridad con `freezeTimeoutMs` del config de roles; el provider pasa el
|
|
36
|
+
* mismo valor).
|
|
37
|
+
*/
|
|
38
|
+
freezeTimeoutMs?: number;
|
|
39
|
+
/**
|
|
40
|
+
* **Puerta 2 de `{ transaction }`** (L-2, opt-in): con `true`, el driver
|
|
41
|
+
* tiene que declarar `capabilities.transactionalWrites: true` o el manager
|
|
42
|
+
* falla AL CONSTRUIRSE (500 `E_AUTHZ_CONFIG`) — que para este puerto es el
|
|
43
|
+
* momento de resolver el driver (`buildRelationsManager`). El provider pasa
|
|
44
|
+
* `relations.requireTransactionalWrites ?? config.requireTransactionalWrites`.
|
|
45
|
+
*/
|
|
46
|
+
requireTransactionalWrites?: boolean;
|
|
47
|
+
/** Nombre del driver (la clave en `relations.drivers`) para los mensajes de las dos puertas. Default `'relations'`. */
|
|
48
|
+
driverName?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare class RelationsManager {
|
|
51
|
+
#private;
|
|
52
|
+
constructor(driver: RelationsDriver, config: RelationsConfig, options?: RelationsManagerOptions);
|
|
53
|
+
/** El driver crudo — salida documentada de las barreras (plataforma y tests). */
|
|
54
|
+
driver(): RelationsDriver;
|
|
55
|
+
/**
|
|
56
|
+
* **Lo que el driver de relaciones ACTIVO declara, de solo lectura**
|
|
57
|
+
* (2.4.0-alpha.4; pregunta 1 de COGNITIV). Para que el código de tenant
|
|
58
|
+
* ramifique —`if (relations.capabilities().transactionalWrites) relate(…,
|
|
59
|
+
* { transaction }) else relate(…)`— sin llamar a `driver()`, que sigue
|
|
60
|
+
* siendo API de PLATAFORMA. Síncrono, a diferencia del de roles: aquí el
|
|
61
|
+
* driver es eager (la puerta 2 ya corrió en el constructor) y no hay nada
|
|
62
|
+
* que resolver. Copia CONGELADA y NORMALIZADA (todas las claves de
|
|
63
|
+
* `RelationsDriverCapabilities`, `undefined` → `false`): mutarla no toca
|
|
64
|
+
* lo que lee la puerta 1.
|
|
65
|
+
*/
|
|
66
|
+
capabilities(): Readonly<RelationsDriverCapabilities>;
|
|
67
|
+
relate(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationWriteOptions): Promise<void>;
|
|
68
|
+
unrelate(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationWriteOptions): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* **Las lecturas también pasan por F-05** (2.4.0-alpha.3, 🟠 2 del auditor):
|
|
71
|
+
* el `objectId` lleva la partición, así que `listSubjects('assignee',
|
|
72
|
+
* { type: 'role_binding', id: R }, S)` era la lista de asignados de un rol
|
|
73
|
+
* en un scope, por el puerto de relaciones, sin catálogo, sin `within`, sin
|
|
74
|
+
* `requireActor` (las lecturas no lo tienen) y sin visibilidad de rol
|
|
75
|
+
* (invariante 18). `check`/`listSubjects` validan el par (tipo, relación);
|
|
76
|
+
* `listObjects` el tipo; el userset del sujeto, su par. PRIMERA línea,
|
|
77
|
+
* cero llamadas al driver; el driver re-valida (defensa en profundidad).
|
|
78
|
+
*/
|
|
79
|
+
check(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef): Promise<boolean>;
|
|
80
|
+
listObjects(subject: RelSubject, relation: string, objectType: string, partition: ScopeRef, page?: RelationPage): Promise<RelationObjectsPage>;
|
|
81
|
+
listSubjects(relation: string, object: RelObject, partition: ScopeRef, page?: RelationPage): Promise<RelationSubjectsPage>;
|
|
82
|
+
/**
|
|
83
|
+
* **Las purgas notifican** (2.4.0-alpha.3 · E, hallazgo #4; D-1/D-3): UN
|
|
84
|
+
* evento por llamada —aunque el driver barra las dos ortografías del uuid
|
|
85
|
+
* de partición por dentro: el manager no canoniza particiones, y diverge a
|
|
86
|
+
* propósito de `scopes.detached`, que emite uno por ortografía porque ahí
|
|
87
|
+
* canoniza el MANAGER—, con el objetivo y la partición TAL COMO la pasó el
|
|
88
|
+
* llamante, sin `relation` y SIN conteo (el puerto devuelve `void`; un
|
|
89
|
+
* conteo lo rompería para terceros y un rollback lo desmentiría). Se
|
|
90
|
+
* notifica también cuando no borra nada: el hecho auditable es «alguien
|
|
91
|
+
* pidió borrar las llaves de X». Sujeta a `requireActor` (D-3, breaking) y
|
|
92
|
+
* al actor validado; NO pasa por `assertWrite` (su `RelationRef.operation`
|
|
93
|
+
* es `'relate' | 'unrelate'`, tipo publicado de R-13). Mismo `#write`
|
|
94
|
+
* (invariante 13) y mismo `#notify` que `relate`/`unrelate`.
|
|
95
|
+
*
|
|
96
|
+
* **Y pasan por F-05** (cierre del 🔴 1 del auditor de alpha.3): el mismo
|
|
97
|
+
* orden que `relate` —puerta 1, freeze, F-05 (solo el TIPO: una purga no
|
|
98
|
+
* nombra relación), id, actor, scope—. `purgeSubject` valida su sujeto como
|
|
99
|
+
* `relate` (`#assertSubject`, ⚪ 7: un userset no declarado o un holder mal
|
|
100
|
+
* formado es 422 ANTES del driver y no llega al evento).
|
|
101
|
+
*/
|
|
102
|
+
purgeObject(object: RelObject, partition: ScopeRef, options?: RelationPurgeOptions): Promise<void>;
|
|
103
|
+
purgeSubject(subject: RelSubject, partition: ScopeRef, options?: RelationPurgeOptions): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Membresía TRANSITIVA de un grupo (a través de usersets anidados) —
|
|
106
|
+
* DISTINTA de `listSubjects`, que da los hechos DIRECTOS. Solo la trae el
|
|
107
|
+
* driver `database` (`membersOfNative: true`); en `openfga` es 500
|
|
108
|
+
* `E_AUTHZ_UNSUPPORTED` nombrándola (la transitiva sería `ListUsers`, que
|
|
109
|
+
* trunca), jamás un `skip`.
|
|
110
|
+
*/
|
|
111
|
+
membersOf(object: RelObject, relation: string, partition: ScopeRef, page?: RelationPage): Promise<RelationSubjectsPage>;
|
|
112
|
+
/** ORIGEN de `authz:reconcile` de relaciones. 500 `E_AUTHZ_UNSUPPORTED` si el driver no lo trae. */
|
|
113
|
+
enumerateRelations(partition: ScopeRef, page?: RelationPage): Promise<RelationTuplePage>;
|
|
114
|
+
/**
|
|
115
|
+
* **K particiones en UN barrido** (2.4.0-alpha.6) si el driver trae
|
|
116
|
+
* `enumerateRelationsMany` (los dos publicados lo traen desde alpha.8: el
|
|
117
|
+
* de `database` es una consulta con `partition_key IN (…)` y cursor
|
|
118
|
+
* estable); si no, K llamadas a `enumerateRelations` concatenadas
|
|
119
|
+
* (correcto, K barridos — el precio queda escrito en la tabla «Limits»).
|
|
120
|
+
* Sin particiones es 500: un barrido para nadie no es un éxito.
|
|
121
|
+
*
|
|
122
|
+
* **El respaldo es exhaustivo o RUIDOSO** (2.4.0-alpha.8 · C2; panel relay
|
|
123
|
+
* 2, analista §8, juez 7.1 🟠). Hasta alpha.7 acumulaba las K páginas y
|
|
124
|
+
* devolvía el cursor de la ÚLTIMA partición que tenía más; reanudar con él
|
|
125
|
+
* aplicaba `uuid > after` a TODAS y **perdía tuplas en silencio** (medido:
|
|
126
|
+
* 6 en el store, 5 vistas) — en el ORIGEN de una migración eso es «esa
|
|
127
|
+
* tupla no existía». Un cursor de una sola partición no sabe reanudar K,
|
|
128
|
+
* así que el respaldo no lo emite: si alguna partición devuelve cursor es
|
|
129
|
+
* 500 `E_AUTHZ_CONFIG` nombrando el método (misma doctrina que el barrido
|
|
130
|
+
* único: si no puede enumerar exhaustivamente, falla ruidoso), y un
|
|
131
|
+
* `after` que llegue aquí —un cursor que el respaldo nunca dio— es 500 con
|
|
132
|
+
* cero llamadas al driver. La salida: implementar `enumerateRelationsMany`
|
|
133
|
+
* en el driver, o paginar partición a partición con `enumerateRelations`
|
|
134
|
+
* (que es lo que hace `reconcileRelations`).
|
|
135
|
+
*/
|
|
136
|
+
enumerateRelationsMany(partitions: ScopeRef[], page?: RelationPage): Promise<RelationTuplePage>;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/relations/manager.ts"],"names":[],"mappings":"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"}
|