@jantstack/adonis-authz 2.4.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 +248 -18
- package/build/commands/authz_relations_reconcile.d.ts +25 -1
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -1
- package/build/commands/authz_relations_reconcile.js +94 -6
- package/build/commands/authz_relations_reconcile.js.map +1 -1
- package/build/index.d.ts +12 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +10 -0
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +7 -0
- package/build/providers/authz_provider.js.map +1 -1
- package/build/src/define_config.d.ts +36 -0
- 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 +53 -14
- package/build/src/drivers/database_driver.d.ts.map +1 -1
- package/build/src/drivers/database_driver.js +104 -32
- package/build/src/drivers/database_driver.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +47 -9
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -1
- package/build/src/drivers/database_relations_driver.js +318 -89
- package/build/src/drivers/database_relations_driver.js.map +1 -1
- package/build/src/drivers/openfga_driver.d.ts +17 -4
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +38 -3
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +15 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -1
- package/build/src/drivers/openfga_facts.js +25 -2
- package/build/src/drivers/openfga_facts.js.map +1 -1
- package/build/src/drivers/openfga_relations_driver.d.ts +27 -6
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_relations_driver.js +140 -16
- package/build/src/drivers/openfga_relations_driver.js.map +1 -1
- package/build/src/errors.d.ts +35 -3
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +61 -3
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +37 -16
- package/build/src/freeze.d.ts.map +1 -1
- package/build/src/freeze.js +53 -8
- package/build/src/freeze.js.map +1 -1
- package/build/src/manager.d.ts +16 -1
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +116 -25
- package/build/src/manager.js.map +1 -1
- package/build/src/models/authz_assignment.d.ts +2 -2
- package/build/src/models/authz_assignment.d.ts.map +1 -1
- package/build/src/models/authz_deny.d.ts +2 -2
- package/build/src/models/authz_deny.d.ts.map +1 -1
- package/build/src/models/authz_permission.d.ts +2 -2
- package/build/src/models/authz_permission.d.ts.map +1 -1
- package/build/src/models/authz_role.d.ts +2 -2
- package/build/src/models/authz_role.d.ts.map +1 -1
- package/build/src/models/authz_role_permission.d.ts +2 -2
- package/build/src/models/authz_role_permission.d.ts.map +1 -1
- package/build/src/relation_partition_trigger.d.ts.map +1 -1
- package/build/src/relation_partition_trigger.js +11 -3
- package/build/src/relation_partition_trigger.js.map +1 -1
- package/build/src/relations/define_relations_config.d.ts +17 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -1
- package/build/src/relations/define_relations_config.js +30 -1
- package/build/src/relations/define_relations_config.js.map +1 -1
- package/build/src/relations/manager.d.ts +25 -3
- package/build/src/relations/manager.d.ts.map +1 -1
- package/build/src/relations/manager.js +76 -19
- package/build/src/relations/manager.js.map +1 -1
- package/build/src/relations/reconcile.d.ts +53 -4
- package/build/src/relations/reconcile.d.ts.map +1 -1
- package/build/src/relations/reconcile.js +92 -30
- package/build/src/relations/reconcile.js.map +1 -1
- package/build/src/scope_outbox.d.ts.map +1 -1
- package/build/src/scope_outbox.js +17 -10
- package/build/src/scope_outbox.js.map +1 -1
- package/build/src/shared/backend_guard.d.ts +28 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -1
- package/build/src/shared/backend_guard.js +52 -0
- package/build/src/shared/backend_guard.js.map +1 -1
- 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/testing/contract.d.ts +55 -4
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +240 -8
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +4 -4
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +2 -2
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/relations_contract.d.ts +23 -1
- package/build/src/testing/relations_contract.d.ts.map +1 -1
- package/build/src/testing/relations_contract.js +432 -17
- package/build/src/testing/relations_contract.js.map +1 -1
- package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -1
- package/build/src/testing/relations_reconcile_contract.js +49 -1
- package/build/src/testing/relations_reconcile_contract.js.map +1 -1
- package/build/src/traits/has_uuid.d.ts +2 -2
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +197 -10
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js.map +1 -1
- package/build/stubs/migration.stub +20 -10
- package/package.json +1 -1
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* ENTERA (su cuerpo `BEGIN…END` lleva `;` dentro): nunca por un runner que
|
|
11
11
|
* trocea por `;`.
|
|
12
12
|
*
|
|
13
|
+
* **L-4b**: «es userset» es `subject_relation <> ''`, no `IS NOT NULL`. Desde
|
|
14
|
+
* L-4b un holder lleva `''` (la columna es `NOT NULL DEFAULT ''` para que el
|
|
15
|
+
* UNIQUE lo defienda: NULL ≠ NULL en los tres motores); con `IS NOT NULL` el
|
|
16
|
+
* trigger dispararía en CADA holder (`subject_partition` NULL ≠ `partition_key`).
|
|
17
|
+
* Una fila vieja con NULL que nadie rellenó tampoco dispara: `NULL <> ''` es
|
|
18
|
+
* NULL —falso— en SQLite, PG y MySQL (tolerancia a NULL, coherente con el
|
|
19
|
+
* driver, que también lo lee como holder).
|
|
20
|
+
*
|
|
13
21
|
* La forma es RADICALMENTE distinta en cada motor (medido por el analista, y
|
|
14
22
|
* probado en INSERT **y** UPDATE):
|
|
15
23
|
* - **SQLite**: `CREATE TRIGGER … BEFORE INSERT/UPDATE … WHEN … BEGIN SELECT
|
|
@@ -44,7 +52,7 @@ export function relationPartitionTrigger(dialect) {
|
|
|
44
52
|
if (kind === 'sqlite') {
|
|
45
53
|
const body = (event) => `CREATE TRIGGER authz_relations_partition_b${event === 'INSERT' ? 'i' : 'u'} ` +
|
|
46
54
|
`BEFORE ${event} ON ${RELATIONS_TABLE} FOR EACH ROW ` +
|
|
47
|
-
`WHEN NEW.subject_relation
|
|
55
|
+
`WHEN NEW.subject_relation <> '' AND NEW.subject_partition IS NOT NEW.partition_key ` +
|
|
48
56
|
`BEGIN SELECT RAISE(ABORT, '${TRIGGER_MESSAGE}'); END`;
|
|
49
57
|
return [body('INSERT'), body('UPDATE')];
|
|
50
58
|
}
|
|
@@ -52,7 +60,7 @@ export function relationPartitionTrigger(dialect) {
|
|
|
52
60
|
return [
|
|
53
61
|
`CREATE OR REPLACE FUNCTION authz_relations_partition_guard() RETURNS trigger LANGUAGE plpgsql AS $authz$ ` +
|
|
54
62
|
`BEGIN ` +
|
|
55
|
-
`IF NEW.subject_relation
|
|
63
|
+
`IF NEW.subject_relation <> '' AND NEW.subject_partition IS DISTINCT FROM NEW.partition_key THEN ` +
|
|
56
64
|
`RAISE EXCEPTION '${TRIGGER_MESSAGE} (subject_partition=%, partition_key=%)', NEW.subject_partition, NEW.partition_key; ` +
|
|
57
65
|
`END IF; RETURN NEW; END; $authz$`,
|
|
58
66
|
`CREATE TRIGGER authz_relations_partition_biu BEFORE INSERT OR UPDATE ON ${RELATIONS_TABLE} ` +
|
|
@@ -63,7 +71,7 @@ export function relationPartitionTrigger(dialect) {
|
|
|
63
71
|
const body = (event) => `CREATE TRIGGER authz_relations_partition_b${event === 'INSERT' ? 'i' : 'u'} ` +
|
|
64
72
|
`BEFORE ${event} ON ${RELATIONS_TABLE} FOR EACH ROW ` +
|
|
65
73
|
`BEGIN ` +
|
|
66
|
-
`IF NEW.subject_relation
|
|
74
|
+
`IF NEW.subject_relation <> '' AND NOT (NEW.subject_partition <=> NEW.partition_key) THEN ` +
|
|
67
75
|
`SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '${TRIGGER_MESSAGE}'; ` +
|
|
68
76
|
`END IF; END`;
|
|
69
77
|
return [body('INSERT'), body('UPDATE')];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relation_partition_trigger.js","sourceRoot":"","sources":["../../src/relation_partition_trigger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"relation_partition_trigger.js","sourceRoot":"","sources":["../../src/relation_partition_trigger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAErD,MAAM,eAAe,GAAG,iBAAiB,CAAA;AACzC,MAAM,eAAe,GAAG,+EAA+E,CAAA;AAIvG,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,gBAAgB;QAAE,OAAO,QAAQ,CAAA;IAC1E,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,UAAU,CAAA;IAC7C,IAAI,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAA;IAC/D,MAAM,IAAI,uBAAuB,CAC/B,uCAAuC,OAAO,gCAAgC;QAC5E,4FAA4F;QAC5F,mGAAmG,CACtG,CAAA;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,wBAAwB,CAAC,OAAe;IACtD,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACtC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,CAAC,KAA0B,EAAE,EAAE,CAC1C,6CAA6C,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG;YAC9E,UAAU,KAAK,OAAO,eAAe,gBAAgB;YACrD,qFAAqF;YACrF,8BAA8B,eAAe,SAAS,CAAA;QACxD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IACzC,CAAC;IACD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO;YACL,2GAA2G;gBACzG,QAAQ;gBACR,kGAAkG;gBAClG,oBAAoB,eAAe,sFAAsF;gBACzH,kCAAkC;YACpC,2EAA2E,eAAe,GAAG;gBAC3F,iEAAiE;SACpE,CAAA;IACH,CAAC;IACD,QAAQ;IACR,MAAM,IAAI,GAAG,CAAC,KAA0B,EAAE,EAAE,CAC1C,6CAA6C,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG;QAC9E,UAAU,KAAK,OAAO,eAAe,gBAAgB;QACrD,QAAQ;QACR,2FAA2F;QAC3F,+CAA+C,eAAe,KAAK;QACnE,aAAa,CAAA;IACf,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;AACzC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,6BAA6B,CAAC,OAAe;IAC3D,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACtC,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO;YACL,2DAA2D,eAAe,EAAE;YAC5E,2DAA2D;SAC5D,CAAA;IACH,CAAC;IACD,OAAO;QACL,qDAAqD;QACrD,qDAAqD;KACtD,CAAA;AACH,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RelObject } from '../types.js';
|
|
1
2
|
/** Una relación de un tipo de objeto (`document#viewer`), con sus `includes` de un nivel. */
|
|
2
3
|
export interface RelationObjectRelationSpec {
|
|
3
4
|
/** El nombre de la relación (`owner`, `editor`, `viewer`). */
|
|
@@ -50,6 +51,22 @@ export interface RelationsConfig {
|
|
|
50
51
|
/** ¿La relación está declarada para ese tipo? (F-05, cara de la relación). */
|
|
51
52
|
isDeclared(objectType: string, relation: string): boolean;
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* **F-05, la función ÚNICA** (L-0): rechaza un `object.type` no declarado
|
|
56
|
+
* (422 `E_AUTHZ_RELATION_TYPE_UNKNOWN`) o una `relation` no declarada para ese
|
|
57
|
+
* tipo (422 `E_AUTHZ_RELATION_UNKNOWN`). La aplican el `RelationsManager`
|
|
58
|
+
* (corta primero) Y los dos drivers de relaciones en `relate`/`unrelate`,
|
|
59
|
+
* ANTES de tocar el backend — la misma función, así que la misma clase, el
|
|
60
|
+
* mismo `code` y el mismo mensaje por cualquier puerta. Hacía falta en el
|
|
61
|
+
* driver (panel `{trx}`, 🔴 2 del auditor): `manager.driver()` y
|
|
62
|
+
* `reconcileRelations` (que escribe con `to.relate`) entran por él, y sin la
|
|
63
|
+
* guarda `relate(evil, 'assignee', {type:'role_binding', id:<roleUuid>}, S)`
|
|
64
|
+
* componía en el store COMPARTIDO el id exacto de un binding de roles y
|
|
65
|
+
* `roles.authorize` pasaba de `false` a `true` (medido contra el `:8101`).
|
|
66
|
+
* La gramática de identidad no basta: `role_binding`/`assignee` son
|
|
67
|
+
* gramaticalmente válidos.
|
|
68
|
+
*/
|
|
69
|
+
export declare function assertRelationDeclared(config: RelationsConfig, object: RelObject, relation: string): void;
|
|
53
70
|
/**
|
|
54
71
|
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
55
72
|
* `E_AUTHZ_RELATION_CONFIG` (misma clase que el gate del modelo del lote 4-1).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define_relations_config.d.ts","sourceRoot":"","sources":["../../../src/relations/define_relations_config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"define_relations_config.d.ts","sourceRoot":"","sources":["../../../src/relations/define_relations_config.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAQ5C,6FAA6F;AAC7F,MAAM,WAAW,0BAA0B;IACzC,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B;AAED,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,SAAS,EAAE,SAAS,0BAA0B,EAAE,CAAA;CACjD;AAED,kDAAkD;AAClD,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC9C;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,wBAAwB,CAAA;CACpC;AAED,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAA;IACvD,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,wDAAwD;IACxD,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAA;IACpC,8EAA8E;IAC9E,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;CAC1D;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAmBzG;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe,CA0IhF"}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* (`../identity.js`); JAMÁS de `../manager` ni de `../drivers/*`. Es lo que
|
|
17
17
|
* mantiene `relations/` desacoplado de `roles/`.
|
|
18
18
|
*/
|
|
19
|
-
import { RelationConfigError } from '../errors.js';
|
|
19
|
+
import { RelationConfigError, RelationTypeUnknownError, RelationUnknownError } from '../errors.js';
|
|
20
20
|
import { RESERVED_FACTS_TYPES, RESERVED_SLUGS, RESERVED_SLUG_PREFIXES } from '../identity.js';
|
|
21
21
|
/** La cota de FGA para el nombre de una relación (50). Un tipo de objeto llega a 254. */
|
|
22
22
|
const RELATION_NAME_MAX = 50;
|
|
@@ -26,6 +26,35 @@ const FGA_NAME_FORMAT = /^[a-z0-9][a-z0-9._-]*$/;
|
|
|
26
26
|
function reject(message) {
|
|
27
27
|
throw new RelationConfigError(message);
|
|
28
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 en `relate`/`unrelate`,
|
|
34
|
+
* ANTES de tocar el backend — la misma función, así que la misma clase, el
|
|
35
|
+
* mismo `code` y el mismo mensaje por cualquier puerta. Hacía falta en el
|
|
36
|
+
* driver (panel `{trx}`, 🔴 2 del auditor): `manager.driver()` y
|
|
37
|
+
* `reconcileRelations` (que escribe con `to.relate`) entran por él, y sin la
|
|
38
|
+
* guarda `relate(evil, 'assignee', {type:'role_binding', id:<roleUuid>}, S)`
|
|
39
|
+
* componía 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
|
+
export function assertRelationDeclared(config, object, relation) {
|
|
45
|
+
if (!object || typeof object !== 'object' || typeof object.type !== 'string') {
|
|
46
|
+
throw new RelationTypeUnknownError(`Objeto de relación inválido: se esperaba { type, id } y llegó ${JSON.stringify(object)}.`);
|
|
47
|
+
}
|
|
48
|
+
if (!config.hasType(object.type)) {
|
|
49
|
+
throw new RelationTypeUnknownError(`El tipo de objeto '${object.type}' no está declarado en defineRelationsConfig (F-05): ` +
|
|
50
|
+
`relate/unrelate solo aceptan tipos declarados. En el store compartido un tipo no declarado ` +
|
|
51
|
+
`podría componer el id de un 'role_binding' real y escalar a roles.authorize.`);
|
|
52
|
+
}
|
|
53
|
+
if (!config.isDeclared(object.type, relation)) {
|
|
54
|
+
throw new RelationUnknownError(`La relación '${String(relation)}' no está declarada para el tipo '${object.type}' en ` +
|
|
55
|
+
`defineRelationsConfig (F-05).`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
29
58
|
/**
|
|
30
59
|
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
31
60
|
* `E_AUTHZ_RELATION_CONFIG` (misma clase que el gate del modelo del lote 4-1).
|
|
@@ -1 +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,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"define_relations_config.js","sourceRoot":"","sources":["../../../src/relations/define_relations_config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RelObject, RelSubject, RelationRef, RelationWriteEvent, RelationWriteOptions, RelationsDriver, RelationObjectsPage, RelationSubjectsPage, RelationPage, RelationTuplePage, ScopeRef } from '../types.js';
|
|
1
|
+
import type { RelObject, RelSubject, RelationRef, RelationWriteEvent, RelationWriteOptions, RelationsDriver, RelationObjectsPage, RelationSubjectsPage, RelationPage, RelationTuplePage, RelationTransactionOptions, ScopeRef } from '../types.js';
|
|
2
2
|
import type { RelationsConfig } from './define_relations_config.js';
|
|
3
3
|
export interface RelationsManagerOptions {
|
|
4
4
|
/**
|
|
@@ -11,6 +11,28 @@ export interface RelationsManagerOptions {
|
|
|
11
11
|
onRelationWrite?(event: RelationWriteEvent): void;
|
|
12
12
|
/** `true` exige `actor` en toda escritura (paridad con `requireActor` de roles). */
|
|
13
13
|
requireActor?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Reloj de pared (R-15, paridad con `config.clock` de roles, 2.5 · J1): se
|
|
16
|
+
* aplica al driver con `withClock` al construir; un driver sin `withClock`
|
|
17
|
+
* con `clock` declarado es 500 `E_AUTHZ_CONFIG` (el reloj mentiría).
|
|
18
|
+
*/
|
|
19
|
+
clock?: () => Date;
|
|
20
|
+
/**
|
|
21
|
+
* Deadline TOTAL (ms, default 5000) de la lectura de la barrera del freeze
|
|
22
|
+
* (paridad con `freezeTimeoutMs` del config de roles; el provider pasa el
|
|
23
|
+
* mismo valor).
|
|
24
|
+
*/
|
|
25
|
+
freezeTimeoutMs?: number;
|
|
26
|
+
/**
|
|
27
|
+
* **Puerta 2 de `{ transaction }`** (L-2, opt-in): con `true`, el driver
|
|
28
|
+
* tiene que declarar `capabilities.transactionalWrites: true` o el manager
|
|
29
|
+
* falla AL CONSTRUIRSE (500 `E_AUTHZ_CONFIG`) — que para este puerto es el
|
|
30
|
+
* momento de resolver el driver (`buildRelationsManager`). El provider pasa
|
|
31
|
+
* `relations.requireTransactionalWrites ?? config.requireTransactionalWrites`.
|
|
32
|
+
*/
|
|
33
|
+
requireTransactionalWrites?: boolean;
|
|
34
|
+
/** Nombre del driver (la clave en `relations.drivers`) para los mensajes de las dos puertas. Default `'relations'`. */
|
|
35
|
+
driverName?: string;
|
|
14
36
|
}
|
|
15
37
|
export declare class RelationsManager {
|
|
16
38
|
#private;
|
|
@@ -22,8 +44,8 @@ export declare class RelationsManager {
|
|
|
22
44
|
check(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef): Promise<boolean>;
|
|
23
45
|
listObjects(subject: RelSubject, relation: string, objectType: string, partition: ScopeRef, page?: RelationPage): Promise<RelationObjectsPage>;
|
|
24
46
|
listSubjects(relation: string, object: RelObject, partition: ScopeRef, page?: RelationPage): Promise<RelationSubjectsPage>;
|
|
25
|
-
purgeObject(object: RelObject, partition: ScopeRef): Promise<void>;
|
|
26
|
-
purgeSubject(subject: RelSubject, partition: ScopeRef): Promise<void>;
|
|
47
|
+
purgeObject(object: RelObject, partition: ScopeRef, options?: RelationTransactionOptions): Promise<void>;
|
|
48
|
+
purgeSubject(subject: RelSubject, partition: ScopeRef, options?: RelationTransactionOptions): Promise<void>;
|
|
27
49
|
/**
|
|
28
50
|
* Membresía TRANSITIVA de un grupo (a través de usersets anidados) —
|
|
29
51
|
* DISTINTA de `listSubjects`, que da los hechos DIRECTOS. Solo la trae el
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/relations/manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/relations/manager.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,0BAA0B,EAC1B,QAAQ,EACT,MAAM,aAAa,CAAA;AAGpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAEnE,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,WAAW,CAAC,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;IACpC,kFAAkF;IAClF,eAAe,CAAC,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjD,oFAAoF;IACpF,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,IAAI,CAAA;IAClB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;;OAMG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,uHAAuH;IACvH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,gBAAgB;;gBAKf,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,GAAE,uBAA4B;IA8CnG,iFAAiF;IACjF,MAAM,IAAI,eAAe;IAwDnB,MAAM,CACV,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,QAAQ,EACnB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAkBV,QAAQ,CACZ,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,QAAQ,EACnB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAcV,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAMtG,WAAW,CACf,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,QAAQ,EACnB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,mBAAmB,CAAC;IAKzB,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,QAAQ,EACnB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,oBAAoB,CAAC;IAM1B,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxG,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjH;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,QAAQ,EACnB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,oBAAoB,CAAC;IAchC,oGAAoG;IAC9F,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAuB/F"}
|
|
@@ -21,18 +21,52 @@
|
|
|
21
21
|
* Pureza (regla 2): solo depende del puerto, los errores, la gramática
|
|
22
22
|
* compartida y `defineRelationsConfig`. Nada de `manager`/`drivers/*`.
|
|
23
23
|
*/
|
|
24
|
-
import { ActorRequiredError,
|
|
25
|
-
import { assertScope, assertSubject, assertRelationId } from '../identity.js';
|
|
24
|
+
import { ActorRequiredError, AuthorizationConfigError, UnsupportedOperationError } from '../errors.js';
|
|
25
|
+
import { assertScope, assertSubject, assertRelationId, assertExpiresAt } from '../identity.js';
|
|
26
|
+
import { isClock, systemClock } from '../clock.js';
|
|
27
|
+
import { assertNotFrozenRow } from '../freeze.js';
|
|
26
28
|
import { isRelUserset } from '../types.js';
|
|
29
|
+
import { assertRelationDeclared } from './define_relations_config.js';
|
|
27
30
|
export class RelationsManager {
|
|
28
31
|
#driver;
|
|
29
32
|
#config;
|
|
30
33
|
#options;
|
|
31
34
|
constructor(driver, config, options = {}) {
|
|
35
|
+
if (options.clock !== undefined) {
|
|
36
|
+
if (!isClock(options.clock)) {
|
|
37
|
+
throw new AuthorizationConfigError(`RelationsManager: clock debe ser una función () => Date (llegó ${typeof options.clock})`);
|
|
38
|
+
}
|
|
39
|
+
if (typeof driver.withClock !== 'function') {
|
|
40
|
+
throw new AuthorizationConfigError(`RelationsManager: el driver de relaciones no implementa withClock(now) y la config declara clock: ` +
|
|
41
|
+
`sin él la caducidad de las relaciones se decidiría con otro reloj que el declarado.`);
|
|
42
|
+
}
|
|
43
|
+
driver = driver.withClock(options.clock);
|
|
44
|
+
}
|
|
45
|
+
if (options.requireTransactionalWrites === true && driver.capabilities?.transactionalWrites !== true) {
|
|
46
|
+
throw new AuthorizationConfigError(`requireTransactionalWrites está en true y el driver de relaciones '${options.driverName ?? 'relations'}' ` +
|
|
47
|
+
`declara transactionalWrites: ${driver.capabilities ? String(driver.capabilities.transactionalWrites) : 'nada (sin capabilities)'}: ` +
|
|
48
|
+
`no puede inscribir relate/unrelate/purge* en la transacción del consumidor («los dos o ninguno»), así que ` +
|
|
49
|
+
`el RelationsManager no se construye. Usa un driver que la declare (database) o quita el flag ` +
|
|
50
|
+
`(relations.requireTransactionalWrites, o el del raíz).`);
|
|
51
|
+
}
|
|
32
52
|
this.#driver = driver;
|
|
33
53
|
this.#config = config;
|
|
34
54
|
this.#options = options;
|
|
35
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* **Puerta 1 de `{ transaction }`** (L-2, siempre activa): una escritura con
|
|
58
|
+
* `{ transaction }` a un driver que no declara `transactionalWrites: true`
|
|
59
|
+
* es 500 `E_AUTHZ_UNSUPPORTED` nombrando driver y operación, ANTES de la
|
|
60
|
+
* barrera, de F-05 y del driver (cero llamadas). Encolar ≠ escribir: aquí
|
|
61
|
+
* la transacción ESCRIBE la tupla dentro de ella, no hay outbox.
|
|
62
|
+
*/
|
|
63
|
+
#assertTransactional(options, operation) {
|
|
64
|
+
if (options?.transaction === undefined || options.transaction === null)
|
|
65
|
+
return;
|
|
66
|
+
if (this.#driver.capabilities?.transactionalWrites === true)
|
|
67
|
+
return;
|
|
68
|
+
throw UnsupportedOperationError.transactional(`relations.${operation}`, this.#options.driverName ?? 'relations', 'relations');
|
|
69
|
+
}
|
|
36
70
|
/** El driver crudo — salida documentada de las barreras (plataforma y tests). */
|
|
37
71
|
driver() {
|
|
38
72
|
return this.#driver;
|
|
@@ -41,21 +75,12 @@ export class RelationsManager {
|
|
|
41
75
|
* **F-05**: rechaza un tipo/relación no declarado ANTES de tocar el driver.
|
|
42
76
|
* La gramática de identidad no basta: `role_binding`/`assignee` son
|
|
43
77
|
* gramaticalmente válidos y en el store compartido componen el id de un
|
|
44
|
-
* binding real.
|
|
78
|
+
* binding real. Es la MISMA función que aplican los dos drivers (L-0,
|
|
79
|
+
* `assertRelationDeclared`): el manager corta primero; el driver es la red
|
|
80
|
+
* para quien entra por `manager.driver()` o por `reconcileRelations`.
|
|
45
81
|
*/
|
|
46
82
|
#assertDeclared(object, relation) {
|
|
47
|
-
|
|
48
|
-
throw new RelationTypeUnknownError(`Objeto de relación inválido: se esperaba { type, id } y llegó ${JSON.stringify(object)}.`);
|
|
49
|
-
}
|
|
50
|
-
if (!this.#config.hasType(object.type)) {
|
|
51
|
-
throw new RelationTypeUnknownError(`El tipo de objeto '${object.type}' no está declarado en defineRelationsConfig (F-05): ` +
|
|
52
|
-
`relate/unrelate solo aceptan tipos declarados. En el store compartido un tipo no declarado ` +
|
|
53
|
-
`podría componer el id de un 'role_binding' real y escalar a roles.authorize.`);
|
|
54
|
-
}
|
|
55
|
-
if (!this.#config.isDeclared(object.type, relation)) {
|
|
56
|
-
throw new RelationUnknownError(`La relación '${relation}' no está declarada para el tipo '${object.type}' en ` +
|
|
57
|
-
`defineRelationsConfig (F-05).`);
|
|
58
|
-
}
|
|
83
|
+
assertRelationDeclared(this.#config, object, relation);
|
|
59
84
|
}
|
|
60
85
|
/**
|
|
61
86
|
* **R-16**: el `object.id` con la gramática estricta de relaciones ANTES del
|
|
@@ -73,18 +98,46 @@ export class RelationsManager {
|
|
|
73
98
|
throw new ActorRequiredError(`Escritura de relación sin 'actor' y la config exige uno (requireActor).`);
|
|
74
99
|
}
|
|
75
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* **La barrera del freeze, la MISMA que la de roles** (L-1 · J1, juez del
|
|
103
|
+
* panel `{trx}`): hasta L-1 no había una sola referencia al freeze en
|
|
104
|
+
* `relations/`, así que durante un cutover las escrituras de roles recibían
|
|
105
|
+
* 503 y las de relaciones ENTRABAN, y `authz:relations:reconcile`
|
|
106
|
+
* certificaba un estado que podía cambiar debajo. Es la fila `id = 2` de
|
|
107
|
+
* `authz_catalog_version` leída por la conexión del motor (`assertNotFrozenRow`,
|
|
108
|
+
* `src/freeze.ts` — raíz de `src/`, así que la regla 2 de pureza se cumple),
|
|
109
|
+
* delante de las CUATRO escrituras y antes de validar nada: 503
|
|
110
|
+
* `E_AUTHZ_FROZEN` reintentable. Las lecturas no pasan por aquí.
|
|
111
|
+
* `manager.driver()` sigue siendo la salida documentada.
|
|
112
|
+
*/
|
|
113
|
+
#assertNotFrozen(operation) {
|
|
114
|
+
return assertNotFrozenRow(`relations.${operation}`, {
|
|
115
|
+
driver: 'relations',
|
|
116
|
+
nowMs: (this.#options.clock ?? systemClock)().getTime(),
|
|
117
|
+
timeoutMs: this.#options.freezeTimeoutMs,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
76
120
|
async relate(subject, relation, object, partition, options) {
|
|
121
|
+
this.#assertTransactional(options, 'relate');
|
|
122
|
+
await this.#assertNotFrozen('relate');
|
|
77
123
|
this.#assertDeclared(object, relation);
|
|
78
124
|
this.#assertObjectId(object);
|
|
79
125
|
this.#assertActor(options);
|
|
80
126
|
assertScope(partition);
|
|
81
127
|
this.#assertSubject(subject, partition);
|
|
128
|
+
// R-15: `expiresAt` en sus tres estados legales (omitido / null / Date
|
|
129
|
+
// válida); cualquier otra cosa es 422 ANTES del driver (invariante 5).
|
|
130
|
+
assertExpiresAt(options?.expiresAt);
|
|
82
131
|
const ref = { operation: 'relate', subject, relation, object, partition };
|
|
132
|
+
if (options && 'expiresAt' in options)
|
|
133
|
+
ref.expiresAt = options.expiresAt;
|
|
83
134
|
this.#options.assertWrite?.(ref);
|
|
84
135
|
await this.#driver.relate(subject, relation, object, partition, options);
|
|
85
136
|
this.#options.onRelationWrite?.({ ...ref, actor: options?.actor });
|
|
86
137
|
}
|
|
87
138
|
async unrelate(subject, relation, object, partition, options) {
|
|
139
|
+
this.#assertTransactional(options, 'unrelate');
|
|
140
|
+
await this.#assertNotFrozen('unrelate');
|
|
88
141
|
this.#assertDeclared(object, relation);
|
|
89
142
|
this.#assertObjectId(object);
|
|
90
143
|
this.#assertActor(options);
|
|
@@ -109,14 +162,18 @@ export class RelationsManager {
|
|
|
109
162
|
this.#assertObjectId(object);
|
|
110
163
|
return this.#driver.listSubjects(relation, object, partition, page);
|
|
111
164
|
}
|
|
112
|
-
async purgeObject(object, partition) {
|
|
165
|
+
async purgeObject(object, partition, options) {
|
|
166
|
+
this.#assertTransactional(options, 'purgeObject');
|
|
167
|
+
await this.#assertNotFrozen('purgeObject');
|
|
113
168
|
assertScope(partition);
|
|
114
169
|
this.#assertObjectId(object);
|
|
115
|
-
return this.#driver.purgeObject(object, partition);
|
|
170
|
+
return this.#driver.purgeObject(object, partition, options);
|
|
116
171
|
}
|
|
117
|
-
async purgeSubject(subject, partition) {
|
|
172
|
+
async purgeSubject(subject, partition, options) {
|
|
173
|
+
this.#assertTransactional(options, 'purgeSubject');
|
|
174
|
+
await this.#assertNotFrozen('purgeSubject');
|
|
118
175
|
assertScope(partition);
|
|
119
|
-
return this.#driver.purgeSubject(subject, partition);
|
|
176
|
+
return this.#driver.purgeSubject(subject, partition, options);
|
|
120
177
|
}
|
|
121
178
|
/**
|
|
122
179
|
* Membresía TRANSITIVA de un grupo (a través de usersets anidados) —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/relations/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/relations/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Clock } from '../clock.js';
|
|
1
2
|
import type { RelationsDriver, ScopeRef } from '../types.js';
|
|
2
3
|
import type { RelationsConfig } from './define_relations_config.js';
|
|
3
4
|
export interface RelationsReconcileOptions {
|
|
@@ -21,11 +22,22 @@ export interface RelationsReconcileOptions {
|
|
|
21
22
|
*/
|
|
22
23
|
allowMassDelete?: boolean;
|
|
23
24
|
/**
|
|
24
|
-
* La config del DESTINO
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* La config del DESTINO. Dos usos: vigilar la deriva del modelo fusionado
|
|
26
|
+
* (un tipo del origen que el destino NO declara se reporta en `modelDrift`)
|
|
27
|
+
* y **embudar F-05 ANTES del driver** (L-0): la tupla cuyo tipo o relación
|
|
28
|
+
* el destino no declara se descarta aquí y se cuenta en
|
|
29
|
+
* `skipped.undeclared`, de modo que `--dry-run` y la pasada real dan los
|
|
30
|
+
* MISMOS números. Sin ella, la embuda el 422 del propio driver del destino
|
|
31
|
+
* (la misma función, `assertRelationDeclared`) y se cuenta igual — pero
|
|
32
|
+
* `--dry-run` no puede anticiparla (la reporta como `written`).
|
|
27
33
|
*/
|
|
28
34
|
toConfig?: RelationsConfig;
|
|
35
|
+
/**
|
|
36
|
+
* El reloj que decide qué tupla del ORIGEN está CADUCADA (R-15): una caducada
|
|
37
|
+
* no se migra —se cuenta en `skipped.expired`— y no respalda nada en el
|
|
38
|
+
* destino. Default `systemClock`; inyectable para el juez.
|
|
39
|
+
*/
|
|
40
|
+
now?: Clock;
|
|
29
41
|
}
|
|
30
42
|
export interface RelationsReconcileReport {
|
|
31
43
|
/** ¿Fue `--dry-run` (sin escrituras)? */
|
|
@@ -34,7 +46,13 @@ export interface RelationsReconcileReport {
|
|
|
34
46
|
written: number;
|
|
35
47
|
/** Tuplas que sobraban en el destino y se borraron (solo con `prune`; o que se borrarían). */
|
|
36
48
|
deleted: number;
|
|
37
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Tuplas que estaban en el destino con OTRA caducidad y se reescribieron con
|
|
51
|
+
* la del origen (R-15; delete+write en ambos drivers, nunca un `Ignore` a
|
|
52
|
+
* ciegas que se quedara la caducidad vieja — la lección S7 de la 3b).
|
|
53
|
+
*/
|
|
54
|
+
updated: number;
|
|
55
|
+
/** Tuplas que ya estaban exactamente igual (misma clave y misma caducidad). */
|
|
38
56
|
unchanged: number;
|
|
39
57
|
/**
|
|
40
58
|
* Tuplas del destino que el origen ya no respalda y que NO se borraron por
|
|
@@ -52,6 +70,37 @@ export interface RelationsReconcileReport {
|
|
|
52
70
|
* (salvo `allowMassDelete`); en `--dry-run` NO lanza y esto lo marca.
|
|
53
71
|
*/
|
|
54
72
|
massDelete: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Lo que el origen ENUMERÓ y no se migró, con su motivo:
|
|
75
|
+
* - `expired` (R-15) = tuplas caducadas al instante de la pasada. Es la
|
|
76
|
+
* pérdida DECLARADA de la migración (como `expired` en `authz:reconcile`
|
|
77
|
+
* de roles, 3b-8 · B2): se cuenta, no clava el exit 1. Un origen que las
|
|
78
|
+
* filtrara antes de enumerarlas las haría desaparecer sin rastro; por eso
|
|
79
|
+
* tienen que LLEGAR.
|
|
80
|
+
* - `undeclared` (L-0) = tuplas VIVAS cuyo `object.type` o `relation` el
|
|
81
|
+
* DESTINO no declara (F-05): no se escriben —hasta L-0 `modelDrift` las
|
|
82
|
+
* reportaba y `to.relate` las escribía igual, por el driver— y se cuentan
|
|
83
|
+
* aquí. Es una relación viva que no llegó, así que SÍ es deriva
|
|
84
|
+
* (exit ≠ 0 en el comando): declárala en el destino y repite la pasada.
|
|
85
|
+
*/
|
|
86
|
+
skipped: {
|
|
87
|
+
expired: number;
|
|
88
|
+
undeclared: number;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* **La ventana durable bajo la que corrió la pasada que ESCRIBE** (L-1 ·
|
|
92
|
+
* J1; paridad con `report.frozen` de `authz:reconcile` de roles). La pone
|
|
93
|
+
* `runRelationsReconcile` (el comando), no esta función —que no ve al
|
|
94
|
+
* manager de roles—; ausente en `--dry-run` (el verificador no congela) y
|
|
95
|
+
* cuando se llama a `reconcileRelations` a pelo. `lapsed: true` = el lease
|
|
96
|
+
* se perdió a mitad ⇒ la pasada NO se certifica (exit ≠ 0).
|
|
97
|
+
*/
|
|
98
|
+
frozen?: {
|
|
99
|
+
durable: true;
|
|
100
|
+
lapsed: boolean;
|
|
101
|
+
leaseMs: number | null;
|
|
102
|
+
fence: number;
|
|
103
|
+
};
|
|
55
104
|
}
|
|
56
105
|
/**
|
|
57
106
|
* Migra las tuplas de relación de `from` a `to` en `partition`. Idempotente
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/relations/reconcile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/relations/reconcile.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,EAA6B,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAkBnE,MAAM,WAAW,yBAAyB;IACxC,oFAAoF;IACpF,IAAI,EAAE,eAAe,CAAA;IACrB,mGAAmG;IACnG,EAAE,EAAE,eAAe,CAAA;IACnB,uFAAuF;IACvF,SAAS,EAAE,QAAQ,CAAA;IACnB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,qFAAqF;IACrF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B;;;;OAIG;IACH,GAAG,CAAC,EAAE,KAAK,CAAA;CACZ;AAED,MAAM,WAAW,wBAAwB;IACvC,yCAAyC;IACzC,MAAM,EAAE,OAAO,CAAA;IACf,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAA;IACf,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;;;OAYG;IACH,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACnF;AA8BD;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA8G9G"}
|