@jantstack/adonis-authz 2.5.0-alpha.1 → 2.5.0-alpha.3
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 +515 -22
- package/build/commands/authz_relations_reconcile.d.ts +13 -62
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -1
- package/build/commands/authz_relations_reconcile.js +202 -116
- package/build/commands/authz_relations_reconcile.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +62 -0
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +193 -1
- package/build/commands/openfga_provision.js.map +1 -1
- package/build/index.d.ts +6 -6
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -3
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +4 -1
- package/build/providers/authz_provider.js.map +1 -1
- package/build/src/define_config.d.ts +32 -0
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js +109 -0
- package/build/src/define_config.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +36 -1
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -1
- package/build/src/drivers/database_relations_driver.js +213 -46
- package/build/src/drivers/database_relations_driver.js.map +1 -1
- package/build/src/drivers/openfga_driver.d.ts +30 -4
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +151 -45
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +21 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -1
- package/build/src/drivers/openfga_facts.js +74 -8
- package/build/src/drivers/openfga_facts.js.map +1 -1
- package/build/src/drivers/openfga_relations_driver.d.ts +140 -10
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_relations_driver.js +743 -49
- package/build/src/drivers/openfga_relations_driver.js.map +1 -1
- package/build/src/errors.d.ts +148 -0
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +166 -0
- package/build/src/errors.js.map +1 -1
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +15 -5
- package/build/src/manager.js.map +1 -1
- package/build/src/openfga.d.ts +1 -1
- package/build/src/openfga.d.ts.map +1 -1
- package/build/src/openfga.js +1 -1
- package/build/src/openfga.js.map +1 -1
- package/build/src/relations/check_many.d.ts +1 -1
- package/build/src/relations/check_many.d.ts.map +1 -1
- package/build/src/relations/check_many.js +6 -4
- package/build/src/relations/check_many.js.map +1 -1
- package/build/src/relations/define_relations_config.d.ts +187 -1
- package/build/src/relations/define_relations_config.d.ts.map +1 -1
- package/build/src/relations/define_relations_config.js +395 -7
- package/build/src/relations/define_relations_config.js.map +1 -1
- package/build/src/relations/manager.d.ts +33 -2
- package/build/src/relations/manager.d.ts.map +1 -1
- package/build/src/relations/manager.js +123 -4
- package/build/src/relations/manager.js.map +1 -1
- package/build/src/relations/reconcile.d.ts +295 -13
- package/build/src/relations/reconcile.d.ts.map +1 -1
- package/build/src/relations/reconcile.js +886 -85
- package/build/src/relations/reconcile.js.map +1 -1
- package/build/src/relations/tuple_order.d.ts +126 -0
- package/build/src/relations/tuple_order.d.ts.map +1 -0
- package/build/src/relations/tuple_order.js +598 -0
- package/build/src/relations/tuple_order.js.map +1 -0
- package/build/src/relations_config_store.d.ts.map +1 -1
- package/build/src/relations_config_store.js +29 -7
- package/build/src/relations_config_store.js.map +1 -1
- package/build/src/relations_reconcile.d.ts +79 -0
- package/build/src/relations_reconcile.d.ts.map +1 -0
- package/build/src/relations_reconcile.js +85 -0
- package/build/src/relations_reconcile.js.map +1 -0
- package/build/src/scope_outbox.d.ts +9 -5
- package/build/src/scope_outbox.d.ts.map +1 -1
- package/build/src/scope_outbox.js +7 -4
- package/build/src/scope_outbox.js.map +1 -1
- package/build/src/shared/backend_guard.d.ts +8 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -1
- package/build/src/shared/backend_guard.js +15 -0
- package/build/src/shared/backend_guard.js.map +1 -1
- package/build/src/testing/main.d.ts +1 -1
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +1 -1
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/relations_contract.d.ts +18 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -1
- package/build/src/testing/relations_contract.js +895 -45
- package/build/src/testing/relations_contract.js.map +1 -1
- package/build/src/testing/relations_reconcile_contract.d.ts +9 -0
- package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -1
- package/build/src/testing/relations_reconcile_contract.js +207 -0
- package/build/src/testing/relations_reconcile_contract.js.map +1 -1
- package/build/src/testing/scope_outbox_contract.d.ts +14 -1
- package/build/src/testing/scope_outbox_contract.d.ts.map +1 -1
- package/build/src/testing/scope_outbox_contract.js +126 -48
- package/build/src/testing/scope_outbox_contract.js.map +1 -1
- package/build/src/types.d.ts +90 -6
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +2 -0
- package/build/src/types.js.map +1 -1
- package/package.json +2 -1
package/build/src/openfga.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type { HolderTypeMap, OpenFgaDriverOptions } from './drivers/openfga_driv
|
|
|
15
15
|
* sobre el MISMO store y `modelId` que el driver `facts` de roles. Vive detrás
|
|
16
16
|
* de esta puerta como el resto de lo que toca `@openfga/sdk`.
|
|
17
17
|
*/
|
|
18
|
-
export { OpenFgaRelationsDriver } from './drivers/openfga_relations_driver.js';
|
|
18
|
+
export { OpenFgaRelationsDriver, DEFAULT_LIST_OBJECTS_DEADLINE_MS, LIST_OBJECTS_DEADLINE_RATIO, RELATIONS_PURGE_WRITE_MAX } from './drivers/openfga_relations_driver.js';
|
|
19
19
|
export type { OpenFgaRelationsDriverOptions } from './drivers/openfga_relations_driver.js';
|
|
20
20
|
/**
|
|
21
21
|
* El modelo (c2r) y la proyección del catálogo (3b-2a; desde 3b-2k · K2 es
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openfga.d.ts","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAEtF;;;;GAIG;AACH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"openfga.d.ts","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAEtF;;;;GAIG;AACH,OAAO,EAAE,sBAAsB,EAAE,gCAAgC,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AACxK,YAAY,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAA;AAE1F;;;;;;GAMG;AACH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,gCAAgC,EAChC,oBAAoB,EACpB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,4BAA4B,CAAA;AACnC,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,4BAA4B,CAAA"}
|
package/build/src/openfga.js
CHANGED
|
@@ -14,7 +14,7 @@ export { OpenFgaAuthorizationDriver, provisionOpenFgaStore, assertHolderTypes, p
|
|
|
14
14
|
* sobre el MISMO store y `modelId` que el driver `facts` de roles. Vive detrás
|
|
15
15
|
* de esta puerta como el resto de lo que toca `@openfga/sdk`.
|
|
16
16
|
*/
|
|
17
|
-
export { OpenFgaRelationsDriver } from './drivers/openfga_relations_driver.js';
|
|
17
|
+
export { OpenFgaRelationsDriver, DEFAULT_LIST_OBJECTS_DEADLINE_MS, LIST_OBJECTS_DEADLINE_RATIO, RELATIONS_PURGE_WRITE_MAX } from './drivers/openfga_relations_driver.js';
|
|
18
18
|
/**
|
|
19
19
|
* El modelo (c2r) y la proyección del catálogo (3b-2a; desde 3b-2k · K2 es
|
|
20
20
|
* el ÚNICO modelo: `openFgaAuthorizationModel` —el del modo `resolver`— y
|
package/build/src/openfga.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openfga.js","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AAGpC;;;;GAIG;AACH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"openfga.js","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AAGpC;;;;GAIG;AACH,OAAO,EAAE,sBAAsB,EAAE,gCAAgC,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAGxK;;;;;;GAMG;AACH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,gCAAgC,EAChC,oBAAoB,EACpB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,4BAA4B,CAAA"}
|
|
@@ -2,7 +2,7 @@ import type { RelObject } from '../types.js';
|
|
|
2
2
|
/** Objetos por lote de `checkMany`. Es el tope de `batchCheck` del servidor FGA (50), para que un lote sea UNA request. */
|
|
3
3
|
export declare const RELATIONS_CHECK_MANY_MAX = 50;
|
|
4
4
|
/** `objects` es un array con 1..RELATIONS_CHECK_MANY_MAX elementos, o 422 (`E_AUTHZ_CHECK_MANY_BATCH`) sin tocar nada. */
|
|
5
|
-
export declare function assertCheckManyObjects(objects: unknown): asserts objects is RelObject[];
|
|
5
|
+
export declare function assertCheckManyObjects(objects: unknown, operation?: 'checkMany' | 'decideMany' | string): asserts objects is RelObject[];
|
|
6
6
|
/**
|
|
7
7
|
* Los objetos DISTINTOS del lote (por `type:id`, en orden de primera aparición)
|
|
8
8
|
* y, por posición del lote, el índice del distinto que la responde. Con
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check_many.d.ts","sourceRoot":"","sources":["../../../src/relations/check_many.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,2HAA2H;AAC3H,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAE1C,0HAA0H;AAC1H,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"check_many.d.ts","sourceRoot":"","sources":["../../../src/relations/check_many.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,2HAA2H;AAC3H,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAE1C,0HAA0H;AAC1H,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,GAAE,WAAW,GAAG,YAAY,GAAG,MAAoB,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,EAAE,CAiBrJ;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG;IAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAehG;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAE/E"}
|
|
@@ -17,15 +17,17 @@ import { CheckManyBatchError } from '../errors.js';
|
|
|
17
17
|
/** Objetos por lote de `checkMany`. Es el tope de `batchCheck` del servidor FGA (50), para que un lote sea UNA request. */
|
|
18
18
|
export const RELATIONS_CHECK_MANY_MAX = 50;
|
|
19
19
|
/** `objects` es un array con 1..RELATIONS_CHECK_MANY_MAX elementos, o 422 (`E_AUTHZ_CHECK_MANY_BATCH`) sin tocar nada. */
|
|
20
|
-
export function assertCheckManyObjects(objects) {
|
|
20
|
+
export function assertCheckManyObjects(objects, operation = 'checkMany') {
|
|
21
|
+
// Lote D · D9: `decideMany` tiene las MISMAS garantías que `checkMany` (tope, `[]`, forma), con la misma clase y el
|
|
22
|
+
// mismo `code`; el mensaje nombra la operación.
|
|
21
23
|
if (!Array.isArray(objects)) {
|
|
22
|
-
throw new CheckManyBatchError(
|
|
24
|
+
throw new CheckManyBatchError(`${operation}: 'objects' tiene que ser un array de objetos (llegó ${typeof objects}).`);
|
|
23
25
|
}
|
|
24
26
|
if (objects.length === 0) {
|
|
25
|
-
throw new CheckManyBatchError(
|
|
27
|
+
throw new CheckManyBatchError(`${operation}: el lote está VACÍO. Un lote sin objetos no es una pregunta (y \`[]\` ⇒ \`[]\` se leería como «todo denegado»): pasa al menos un objeto.`);
|
|
26
28
|
}
|
|
27
29
|
if (objects.length > RELATIONS_CHECK_MANY_MAX) {
|
|
28
|
-
throw new CheckManyBatchError(
|
|
30
|
+
throw new CheckManyBatchError(`${operation}: el lote tiene ${objects.length} objetos y el tope es ${RELATIONS_CHECK_MANY_MAX} (RELATIONS_CHECK_MANY_MAX, ` +
|
|
29
31
|
`= el tope de batchCheck del servidor): trocea en el llamante. No se ha preguntado nada.`);
|
|
30
32
|
}
|
|
31
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check_many.js","sourceRoot":"","sources":["../../../src/relations/check_many.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGlD,2HAA2H;AAC3H,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAE1C,0HAA0H;AAC1H,MAAM,UAAU,sBAAsB,CAAC,OAAgB;
|
|
1
|
+
{"version":3,"file":"check_many.js","sourceRoot":"","sources":["../../../src/relations/check_many.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGlD,2HAA2H;AAC3H,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAE1C,0HAA0H;AAC1H,MAAM,UAAU,sBAAsB,CAAC,OAAgB,EAAE,YAAiD,WAAW;IACnH,oHAAoH;IACpH,gDAAgD;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,mBAAmB,CAAC,GAAG,SAAS,wDAAwD,OAAO,OAAO,IAAI,CAAC,CAAA;IACvH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAC3B,GAAG,SAAS,2IAA2I,CACxJ,CAAA;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC9C,MAAM,IAAI,mBAAmB,CAC3B,GAAG,SAAS,mBAAmB,OAAO,CAAC,MAAM,yBAAyB,wBAAwB,8BAA8B;YAC1H,yFAAyF,CAC5F,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAoB;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;IACtC,MAAM,QAAQ,GAAgB,EAAE,CAAA;IAChC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,EAAE,CAAA;QACzC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACtB,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAA;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;YACjB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;AAC5B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,KAAe,EAAE,OAAkB;IAClE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;AACvC,CAAC"}
|
|
@@ -1,4 +1,58 @@
|
|
|
1
|
-
import type { RelObject } from '../types.js';
|
|
1
|
+
import type { RelObject, RelUserset, RelationDecision } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* **El ÚNICO userset que el modelo admite como sujeto** (plan 2.5 · lote B · B3):
|
|
4
|
+
* `group#member`. El generador del modelo fusionado emite, para CADA relación de
|
|
5
|
+
* dominio, `[<holders> with not_expired, group#member]` y nada más; `group` es el
|
|
6
|
+
* tipo BUILT-IN (`declared.set('group', …)` abajo) y el consumidor no lo declara.
|
|
7
|
+
*/
|
|
8
|
+
export declare const RELATION_USERSET_TYPE = "group";
|
|
9
|
+
export declare const RELATION_USERSET_RELATION = "member";
|
|
10
|
+
/**
|
|
11
|
+
* **El prefijo de la relación ALMACENADA de un deny** (plan 2.5 · lote D · D1): `deny(u, viewer, doc)` escribe la
|
|
12
|
+
* tupla `doc#denied_viewer@u` —en `authz_relations` (`database`) y en el store (`openfga`)—. Es el MISMO prefijo que
|
|
13
|
+
* la familia del deny de roles (`FACTS_DENIED_PREFIX`) y está en `RESERVED_SLUG_PREFIXES`: ninguna relación de dominio
|
|
14
|
+
* puede empezar por él (⚪4), así que el nombre público y el almacenado nunca colisionan.
|
|
15
|
+
*/
|
|
16
|
+
export declare const RELATION_DENY_PREFIX = "denied_";
|
|
17
|
+
/**
|
|
18
|
+
* **La cota de una relación DENEGABLE** (D1, juez ronda 2 · fila D: «≤ 43 caracteres»): `denied_<rel>` tiene que caber
|
|
19
|
+
* en los 50 de FGA (y en la columna `relation` de `authz_relations`), así que una relación de un tipo con `deny`
|
|
20
|
+
* mide como mucho `50 − 'denied_'.length` = 43. DERIVADA, como `MAX_SLUG_LENGTH`. En un tipo SIN `deny` la cota sigue
|
|
21
|
+
* siendo 50 (D-18: una cota global sería una ruptura para quien no usa el deny).
|
|
22
|
+
*/
|
|
23
|
+
export declare const DENIABLE_RELATION_NAME_MAX: number;
|
|
24
|
+
/**
|
|
25
|
+
* **El opt-in del deny, en DOS FASES** (D10, decisión del dueño 2026-10-14; auditor R2-2): un solo interruptor no
|
|
26
|
+
* tiene secuencia segura con pods de dos versiones (un pod nuevo escribe un deny y uno viejo —o uno con el `modelId`
|
|
27
|
+
* viejo— no lo mira). Por eso son dos valores y dos despliegues:
|
|
28
|
+
*
|
|
29
|
+
* - `'read'` (fase 1): el modelo publicado declara `denied_<rel>` (`<rel> … but not denied_<rel>`) y TODAS las
|
|
30
|
+
* lecturas lo honran; `deny()` sobre ese tipo es 422 `E_AUTHZ_RELATION_NOT_DENYABLE` (todavía no se escriben).
|
|
31
|
+
* `removeDeny`/`listDenies` sí funcionan (retirar el opt-in tiene que ser reversible).
|
|
32
|
+
* - `'write'` (fase 2): además se aceptan escrituras de deny.
|
|
33
|
+
*
|
|
34
|
+
* El runbook: (1) toda la flota en ≥ 2.5.0-alpha.3 con el tipo en `'read'`, el modelo publicado y todos los pods
|
|
35
|
+
* fijados al `modelId` nuevo; (2) verificar; (3) un SEGUNDO despliegue pasa a `'write'`. `deny: true` no existe a
|
|
36
|
+
* propósito (422 nombrando las dos fases): sería el interruptor único que R2-2 descartó.
|
|
37
|
+
*/
|
|
38
|
+
export type RelationDenyPhase = 'read' | 'write';
|
|
39
|
+
/**
|
|
40
|
+
* **Listas blancas por nivel de la spec** (plan 2.5 · lote B · B2; linaje L5,
|
|
41
|
+
* propiedad universal «ninguna clave de una spec de config se descarta»).
|
|
42
|
+
* Una clave que no está en la lista de SU nivel es 422
|
|
43
|
+
* `E_AUTHZ_RELATION_CONFIG_UNKNOWN_KEY` nombrando la ruta (`objectTypes[1].deny`)
|
|
44
|
+
* y la lista. Hasta `2.5.0-alpha.1` la config congelada copiaba solo lo que
|
|
45
|
+
* conocía y tiraba el resto en silencio (tester H3, medido: `deny: true` y
|
|
46
|
+
* `denny: 1` desaparecían): un typo era una entrada inerte, y el lote D (deny)
|
|
47
|
+
* habría nacido con la clave `deny` leída por un proceso viejo como «nada».
|
|
48
|
+
* Las claves del lote D entran AQUÍ, en el mismo commit que su efecto.
|
|
49
|
+
*/
|
|
50
|
+
export declare const RELATIONS_SPEC_KEYS: Readonly<{
|
|
51
|
+
root: readonly ["objectTypes", "holderTypes", "database"];
|
|
52
|
+
objectType: readonly ["type", "relations", "deny"];
|
|
53
|
+
relation: readonly ["name", "includes"];
|
|
54
|
+
database: readonly ["membersOf"];
|
|
55
|
+
}>;
|
|
2
56
|
/** Una relación de un tipo de objeto (`document#viewer`), con sus `includes` de un nivel. */
|
|
3
57
|
export interface RelationObjectRelationSpec {
|
|
4
58
|
/** El nombre de la relación (`owner`, `editor`, `viewer`). */
|
|
@@ -17,6 +71,12 @@ export interface RelationObjectTypeSpec {
|
|
|
17
71
|
type: string;
|
|
18
72
|
/** Sus relaciones, en orden de declaración. */
|
|
19
73
|
relations: readonly RelationObjectRelationSpec[];
|
|
74
|
+
/**
|
|
75
|
+
* **Opt-in del deny para este tipo** (plan 2.5 · lote D, D10: dos fases, ver `RelationDenyPhase`). Ausente = el tipo
|
|
76
|
+
* no se puede denegar (`deny()` ⇒ 422) y su modelo es byte a byte el de 2.4.0-alpha.10 (D-29). Con `'read'` o
|
|
77
|
+
* `'write'` cada relación del tipo mide ≤ `DENIABLE_RELATION_NAME_MAX` (43) y el modelo publica `denied_<rel>`.
|
|
78
|
+
*/
|
|
79
|
+
deny?: RelationDenyPhase;
|
|
20
80
|
}
|
|
21
81
|
/** Opciones específicas del driver `database`. */
|
|
22
82
|
export interface RelationsDatabaseOptions {
|
|
@@ -101,9 +161,135 @@ export declare function assertRelationDeclared(config: RelationsConfig, object:
|
|
|
101
161
|
export declare function assertObjectTypeDeclared(config: RelationsConfig, object: RelObject | {
|
|
102
162
|
type: string;
|
|
103
163
|
}): void;
|
|
164
|
+
/**
|
|
165
|
+
* **B3 · el userset del SUJETO: F-05 (par) y, además, `group#member` y solo
|
|
166
|
+
* `group#member`** (plan 2.5 · lote B; auditor [N 9] de la ronda 1, analista
|
|
167
|
+
* B(2); patrón F-05 `assertRelationDeclared`: UNA función, misma clase, mismo
|
|
168
|
+
* `code` y mismo mensaje por cualquier puerta). Hasta `2.5.0-alpha.1` un
|
|
169
|
+
* `{ object: document, relation: viewer }` como sujeto pasaba F-05 (tipo y
|
|
170
|
+
* relación declarados) y después: `database` guardaba la fila INERTE (ningún
|
|
171
|
+
* holder la alcanza: la expansión de principales solo baja por `group#member`)
|
|
172
|
+
* y `openfga` componía `document:<key>|<id>#viewer` como `user`, que el modelo
|
|
173
|
+
* fusionado no admite ⇒ 400 del servidor ⇒ 503 mal clasificado (invariante 5:
|
|
174
|
+
* una pregunta inválida es 422, no una caída). La aplican el `RelationsManager`
|
|
175
|
+
* (`#assertSubject`), los DOS drivers (`#subjectColumns` / `#subjectUser`) y el
|
|
176
|
+
* doble publicado, en TODA operación que recibe sujeto —`relate`/`unrelate`/
|
|
177
|
+
* `check`/`checkMany`/`listObjects`/`purgeSubject`—, ANTES de tocar el backend
|
|
178
|
+
* (cero `INSERT`, cero `Write`/`Read`/`Check`). La guardia de superficie lo
|
|
179
|
+
* sondea como variante de F-05 (`usersetUnsupported`) con un mutante por capa.
|
|
180
|
+
*/
|
|
181
|
+
export declare function assertUsersetSubject(config: RelationsConfig, subject: RelUserset): void;
|
|
182
|
+
/**
|
|
183
|
+
* **La mitad de B3 que no necesita config**: `group#member` y solo `group#member`
|
|
184
|
+
* (cierre 1 del lote B · 🟠 2). Es la regla que `reconcileRelations` aplica en el
|
|
185
|
+
* PLAN a cada tupla ENUMERADA —del origen y del destino— también cuando no hay
|
|
186
|
+
* `toConfig` (sin config no se puede juzgar F-05 del par, pero la forma del
|
|
187
|
+
* userset sí): así un residuo pre-2.5 se clasifica ANTES del driver, con los
|
|
188
|
+
* mismos números en `--dry-run` y en la pasada real. **En el plan la FORMA va
|
|
189
|
+
* ANTES que F-05** (cierre 2 · 🟡 N2): un residuo B3 es inadmisible con
|
|
190
|
+
* cualquier config, así que un userset de tipo/relación no declarados sigue
|
|
191
|
+
* siendo residuo (`usersetUnsupported`, con receta) y nunca `undeclared` (cuyo
|
|
192
|
+
* consejo «decláralo» no lo arreglaría). En la API (`assertUsersetSubject`,
|
|
193
|
+
* la pregunta del llamante) el orden sigue siendo F-05 → forma: los dos son
|
|
194
|
+
* 422 y ninguno escribe.
|
|
195
|
+
*/
|
|
196
|
+
export declare function assertSupportedUserset(subject: RelUserset): void;
|
|
197
|
+
/**
|
|
198
|
+
* **El residuo pre-2.5 de B3 y cómo se borra** (cierre 1 del lote B · 🟠 1/🟠 2,
|
|
199
|
+
* ⚪ 12): una fila de `authz_relations` escrita ANTES de 2.5.0 con un sujeto
|
|
200
|
+
* userset ≠ `group#member`. La API ya no la admite (ni `relate`, ni `unrelate`,
|
|
201
|
+
* ni `purgeSubject(userset)`), el reconcile la LISTA con este motivo y **nunca
|
|
202
|
+
* la borra por vía de plataforma** (decisión del coordinador, 2026-10-15: la
|
|
203
|
+
* misma regla que toda tupla del destino fuera de gramática — se lista, exit
|
|
204
|
+
* ≠ 0, se borra a mano). Las dos sentencias valen en los tres motores
|
|
205
|
+
* (`subject_relation <> ''` excluye los holders, también los `NULL` de antes
|
|
206
|
+
* de L-4b: `NULL <> ''` es NULL ⇒ falso); `upgrade_recipe.spec` las EJECUTA y
|
|
207
|
+
* el README §Upgrading las publica literalmente.
|
|
208
|
+
*/
|
|
209
|
+
export declare const RELATION_USERSET_RESIDUE_WHERE = "subject_relation <> '' AND NOT (subject_type = 'group' AND subject_relation = 'member')";
|
|
210
|
+
export declare const RELATION_USERSET_RESIDUE_SELECT = "SELECT uuid, partition_key, object_type, object_uuid, relation, subject_type, subject_uuid, subject_relation FROM authz_relations WHERE subject_relation <> '' AND NOT (subject_type = 'group' AND subject_relation = 'member');";
|
|
211
|
+
export declare const RELATION_USERSET_RESIDUE_DELETE = "DELETE FROM authz_relations WHERE subject_relation <> '' AND NOT (subject_type = 'group' AND subject_relation = 'member');";
|
|
104
212
|
/**
|
|
105
213
|
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
106
214
|
* `E_AUTHZ_RELATION_CONFIG` (misma clase que el gate del modelo del lote 4-1).
|
|
107
215
|
*/
|
|
108
216
|
export declare function defineRelationsConfig(spec: RelationsConfigSpec): RelationsConfig;
|
|
217
|
+
/** La fase del opt-in del deny de un tipo (`undefined` = sin opt-in; `group` nunca). */
|
|
218
|
+
export declare function denyPhaseOf(config: Pick<RelationsConfig, 'objectTypes'>, objectType: string): RelationDenyPhase | undefined;
|
|
219
|
+
/** ¿Algún tipo de la config declara el opt-in (en cualquier fase)? Decide D14 (`modelId` fijado obligatorio en `openfga`). */
|
|
220
|
+
export declare function hasDenyTypes(config: Pick<RelationsConfig, 'objectTypes'>): boolean;
|
|
221
|
+
/** La relación ALMACENADA del deny de `relation` (`viewer` ⇒ `denied_viewer`). */
|
|
222
|
+
export declare function deniedRelationOf(relation: string): string;
|
|
223
|
+
/**
|
|
224
|
+
* **La consulta del README §Upgrading que cuenta los denies VIVOS de relaciones** (plan 2.5 · lote D · D2; D12/S17: no
|
|
225
|
+
* hay rollback por debajo de 2.5 con denies vivos — antes de volver atrás tiene que dar 0). Portable a los tres motores
|
|
226
|
+
* (`substr` existe en SQLite, PostgreSQL y MySQL; `LIKE 'denied\_%'` no: SQLite no tiene escape por defecto). La ejecutan
|
|
227
|
+
* `tests/upgrade_recipe.spec.ts` (los cuatro modos, contra el README byte a byte) y el paso 21 del runbook.
|
|
228
|
+
*/
|
|
229
|
+
export declare const RELATION_DENIES_COUNT_SQL = "SELECT count(*) AS n FROM authz_relations WHERE substr(relation, 1, 7) = 'denied_';";
|
|
230
|
+
/**
|
|
231
|
+
* **La relación ALMACENADA, leída de vuelta: nombre público + `kind`** (plan 2.5 · lote D · D2; el reconcile con
|
|
232
|
+
* `kind`). Es el PUNTO DE PASO ÚNICO de `enumerateRelations(Many)` en los dos drivers y en el doble: `denied_viewer`
|
|
233
|
+
* ⇒ `{ relation: 'viewer', kind: 'deny' }`; cualquier otra ⇒ `{ relation, kind: 'allow' }`. Inequívoco porque el
|
|
234
|
+
* prefijo está en `RESERVED_SLUG_PREFIXES` (ninguna relación de dominio puede empezar por `denied_`). Hasta D2 los
|
|
235
|
+
* drivers emitían `relation: 'denied_viewer'` sin `kind`, y `reconcileRelations` lo contaba como relación NO
|
|
236
|
+
* declarada (`skipped.undeclared`): una migración `database → openfga` no llevaba los denies.
|
|
237
|
+
*/
|
|
238
|
+
export declare function storedRelationKind(stored: string): {
|
|
239
|
+
relation: string;
|
|
240
|
+
kind: 'allow' | 'deny';
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* **`down*(R)`: las relaciones cuyo hecho DIRECTO satisface `R`** (R y todo lo que incluye, transitivamente). Es el
|
|
244
|
+
* PUNTO DE PASO ÚNICO del grafo de `includes` hacia abajo (lote D: antes lo reimplementaban `#expandDown` del driver
|
|
245
|
+
* `database` y el doble; con el deny hacen falta las dos direcciones en tres sitios y, calculadas tres veces,
|
|
246
|
+
* divergen). En el retículo del contrato: `down*(viewer) = {viewer, editor, owner}`.
|
|
247
|
+
*/
|
|
248
|
+
export declare function relationsDown(config: Pick<RelationsConfig, 'objectTypes'>, objectType: string, relation: string): string[];
|
|
249
|
+
/**
|
|
250
|
+
* **`up*(R)`: las relaciones que INCLUYEN a `R`** (R y todo lo que la incluye, transitivamente). Un deny en cualquiera
|
|
251
|
+
* de ellas CORTA un grant de `R` (D5, corte de camino): `up*(owner) = {owner, editor, viewer}` ⇒ un deny en `editor`
|
|
252
|
+
* anula entero un grant de `owner`.
|
|
253
|
+
*/
|
|
254
|
+
export declare function relationsUp(config: Pick<RelationsConfig, 'objectTypes'>, objectType: string, relation: string): string[];
|
|
255
|
+
/**
|
|
256
|
+
* **D5 · CORTE DE CAMINO, la regla ÚNICA** (decisión del dueño 2026-10-14; tester §2.1, la tabla T1 de 64 estados):
|
|
257
|
+
* `check(s, Q, o) = T` sii existe un grant `T ∈ A ∩ down*(Q)` tal que `up*(T) ∩ D = ∅`, con `A` = las relaciones con
|
|
258
|
+
* allow vivo que alcanzan al sujeto (directo o por `group#member`, anidado) y `D` = las relaciones con deny que lo
|
|
259
|
+
* alcanzan igual. Es EXACTAMENTE lo que el modelo FGA evalúa en el servidor (`X = (this ∨ I…) but not denied_X`,
|
|
260
|
+
* `denied_X = this ∨ denied_P` por cada `P ⊇ X`), y es la función que usan el driver `database`, el doble y el
|
|
261
|
+
* oráculo de la suite: tres copias divergirían (L8).
|
|
262
|
+
*/
|
|
263
|
+
export declare function cutPathAllows(config: Pick<RelationsConfig, 'objectTypes'>, objectType: string, relation: string, allowed: ReadonlySet<string>, denied: ReadonlySet<string>): boolean;
|
|
264
|
+
/** Las relaciones del deny que `decideMany`/`check` tienen que leer para `R`: `up*(down*(R))` (D9, definición AMPLIA). */
|
|
265
|
+
export declare function deniableAbove(config: Pick<RelationsConfig, 'objectTypes'>, objectType: string, relation: string): string[];
|
|
266
|
+
/**
|
|
267
|
+
* **D9 · `decideMany` AMPLIO, la regla ÚNICA** (decisión del dueño 2026-10-14; juez ronda 2 §4): `allow` si `check`
|
|
268
|
+
* concede (el deny ya está aplicado dentro del objeto por corte de camino); si no, `deny` si el sujeto tiene un deny
|
|
269
|
+
* vivo sobre ALGUNA relación de `up*(down*(R))` en el objeto; si no, `none`. Más amplia que `check` a propósito
|
|
270
|
+
* (fail-closed en la cadena del llamante): un `viewer` heredado con un deny(`editor`) en el hijo da `deny`.
|
|
271
|
+
*/
|
|
272
|
+
export declare function decideFrom(config: Pick<RelationsConfig, 'objectTypes'>, objectType: string, relation: string, allowed: ReadonlySet<string>, denied: ReadonlySet<string>): RelationDecision;
|
|
273
|
+
/**
|
|
274
|
+
* **La puerta de ESCRITURA del deny** (D10/D-17): `deny()` solo entra sobre un tipo en fase `'write'`; sin opt-in, en
|
|
275
|
+
* `'read'` o sobre `group` ⇒ 422 `E_AUTHZ_RELATION_NOT_DENYABLE`. La aplican el manager, los dos drivers y el doble,
|
|
276
|
+
* DESPUÉS de F-05 (un tipo no declarado sigue siendo `E_AUTHZ_RELATION_TYPE_UNKNOWN`). `removeDeny`/`listDenies` NO
|
|
277
|
+
* pasan por aquí: aceptan cualquier tipo declarado (D8/R2-4 b: retirar el opt-in tiene que ser reversible).
|
|
278
|
+
*/
|
|
279
|
+
export declare function assertRelationDenyable(config: Pick<RelationsConfig, 'objectTypes'>, object: {
|
|
280
|
+
type: string;
|
|
281
|
+
}, relation: string): void;
|
|
282
|
+
/**
|
|
283
|
+
* **El comodín `*` no es un sujeto de deny** (D-17): un deny a «todos» sería un apagado del objeto que nadie
|
|
284
|
+
* auditaría como tal. Hoy la gramática de holder ya rechaza `*` (422 `E_AUTHZ_INVALID_IDENTITY`); esta guarda lo dice
|
|
285
|
+
* con el código del deny ANTES de la gramática, para que un cambio de la gramática no lo abra en silencio.
|
|
286
|
+
*/
|
|
287
|
+
export declare function assertDenySubject(subject: unknown): void;
|
|
288
|
+
/**
|
|
289
|
+
* **D3: el deny no caduca en v1.** `expiresAt` en las opciones de `deny`/`removeDeny` —incluso `null`, que en `relate`
|
|
290
|
+
* significa «quitar la caducidad»— es 422 `E_AUTHZ_DENY_EXPIRY_UNSUPPORTED` ANTES de tocar el backend, con la razón
|
|
291
|
+
* medida (M5). La clave PRESENTE es lo que se rechaza: un `null` aceptado sería una puerta para que la siguiente
|
|
292
|
+
* versión la lea como «permanente» sin que nadie lo decidiera.
|
|
293
|
+
*/
|
|
294
|
+
export declare function assertDenyNoExpiry(options: unknown): void;
|
|
109
295
|
//# sourceMappingURL=define_relations_config.d.ts.map
|
|
@@ -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":"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"}
|