@jantstack/adonis-authz 2.4.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 +496 -29
- package/build/commands/authz_catalog_diff.d.ts.map +1 -1
- package/build/commands/authz_catalog_diff.js +0 -1
- package/build/commands/authz_catalog_diff.js.map +1 -1
- package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -1
- package/build/commands/authz_catalog_prune_orphans.js +0 -1
- package/build/commands/authz_catalog_prune_orphans.js.map +1 -1
- package/build/commands/authz_freeze.d.ts.map +1 -1
- package/build/commands/authz_freeze.js +1 -2
- package/build/commands/authz_freeze.js.map +1 -1
- package/build/commands/authz_reconcile.d.ts +15 -6
- package/build/commands/authz_reconcile.d.ts.map +1 -1
- package/build/commands/authz_reconcile.js +143 -20
- package/build/commands/authz_reconcile.js.map +1 -1
- package/build/commands/authz_relations_reconcile.d.ts +72 -1
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -1
- package/build/commands/authz_relations_reconcile.js +234 -21
- package/build/commands/authz_relations_reconcile.js.map +1 -1
- package/build/commands/authz_scopes_relay.d.ts +50 -0
- package/build/commands/authz_scopes_relay.d.ts.map +1 -1
- package/build/commands/authz_scopes_relay.js +213 -10
- package/build/commands/authz_scopes_relay.js.map +1 -1
- 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 +12 -4
- package/build/commands/authz_unfreeze.d.ts.map +1 -1
- package/build/commands/authz_unfreeze.js +74 -9
- package/build/commands/authz_unfreeze.js.map +1 -1
- package/build/commands/main.d.ts +16 -13
- package/build/commands/main.d.ts.map +1 -1
- package/build/commands/main.js +59 -11
- package/build/commands/main.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +49 -3
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +72 -7
- package/build/commands/openfga_provision.js.map +1 -1
- package/build/index.d.ts +15 -5
- package/build/index.d.ts.map +1 -1
- package/build/index.js +16 -3
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts +7 -2
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +20 -3
- package/build/providers/authz_provider.js.map +1 -1
- package/build/src/define_config.d.ts +106 -1
- 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 +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 +74 -9
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -1
- package/build/src/drivers/database_relations_driver.js +391 -93
- package/build/src/drivers/database_relations_driver.js.map +1 -1
- package/build/src/drivers/openfga_driver.d.ts +71 -10
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +195 -16
- 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 +72 -6
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_relations_driver.js +308 -50
- package/build/src/drivers/openfga_relations_driver.js.map +1 -1
- package/build/src/errors.d.ts +175 -4
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +219 -3
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +100 -20
- package/build/src/freeze.d.ts.map +1 -1
- package/build/src/freeze.js +159 -25
- package/build/src/freeze.js.map +1 -1
- package/build/src/manager.d.ts +239 -7
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +1192 -148
- 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 +51 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -1
- package/build/src/relations/define_relations_config.js +68 -1
- package/build/src/relations/define_relations_config.js.map +1 -1
- package/build/src/relations/manager.d.ts +106 -6
- package/build/src/relations/manager.d.ts.map +1 -1
- package/build/src/relations/manager.js +368 -30
- package/build/src/relations/manager.js.map +1 -1
- package/build/src/relations/reconcile.d.ts +81 -6
- package/build/src/relations/reconcile.d.ts.map +1 -1
- package/build/src/relations/reconcile.js +233 -77
- package/build/src/relations/reconcile.js.map +1 -1
- package/build/src/scope_outbox.d.ts +54 -0
- package/build/src/scope_outbox.d.ts.map +1 -1
- package/build/src/scope_outbox.js +274 -33
- 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/sql_expiry.d.ts +2 -0
- package/build/src/shared/sql_expiry.d.ts.map +1 -1
- package/build/src/shared/sql_expiry.js +4 -0
- package/build/src/shared/sql_expiry.js.map +1 -1
- 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 +8 -0
- package/build/src/sql_descendants.d.ts.map +1 -1
- package/build/src/sql_descendants.js.map +1 -1
- 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 +244 -9
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +6 -4
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +3 -2
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/migration_contract.d.ts +9 -0
- package/build/src/testing/migration_contract.d.ts.map +1 -1
- package/build/src/testing/migration_contract.js +5 -2
- package/build/src/testing/migration_contract.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 +603 -19
- 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/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/has_uuid.d.ts +2 -2
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +708 -38
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +55 -0
- package/build/src/types.js.map +1 -1
- package/build/stubs/config/authorization.stub +45 -1
- package/build/stubs/migration.stub +20 -10
- package/package.json +1 -1
|
@@ -62,13 +62,14 @@ declare const AuthzRolePermission_base: {
|
|
|
62
62
|
selfAssignPrimaryKey: boolean;
|
|
63
63
|
generateUuid(model: any): void;
|
|
64
64
|
nextUuid(): string;
|
|
65
|
-
transaction: import("@adonisjs/lucid/types/database").TransactionFn;
|
|
66
65
|
all: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
|
|
67
66
|
find: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
|
|
68
67
|
table: string;
|
|
69
68
|
connection?: string | undefined;
|
|
70
69
|
first: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
|
|
71
70
|
truncate: (cascade?: boolean) => Promise<void>;
|
|
71
|
+
transaction: import("@adonisjs/lucid/types/database").TransactionFn;
|
|
72
|
+
query: <Model extends import("@adonisjs/lucid/types/model").LucidModel, Result = InstanceType<Model>>(this: Model, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model, Result>;
|
|
72
73
|
after: {
|
|
73
74
|
<Model extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model>[], "fetch">): void;
|
|
74
75
|
<Model extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelPaginatorContract<InstanceType<Model>>, "paginate">): void;
|
|
@@ -140,7 +141,6 @@ declare const AuthzRolePermission_base: {
|
|
|
140
141
|
fetchOrNewUpMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
|
|
141
142
|
fetchOrCreateMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
|
|
142
143
|
updateOrCreateMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
|
|
143
|
-
query: <Model extends import("@adonisjs/lucid/types/model").LucidModel, Result = InstanceType<Model>>(this: Model, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model, Result>;
|
|
144
144
|
} & import("@adonisjs/lucid/types/model").LucidModel;
|
|
145
145
|
/** Pivot rol ↔ permiso del motor de autorización propio. */
|
|
146
146
|
export default class AuthzRolePermission extends AuthzRolePermission_base {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz_role_permission.d.ts","sourceRoot":"","sources":["../../../src/models/authz_role_permission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA
|
|
1
|
+
{"version":3,"file":"authz_role_permission.d.ts","sourceRoot":"","sources":["../../../src/models/authz_role_permission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oZAsBoxtB,gDAAiD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAjBr2tB,4DAA4D;AAC5D,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,wBAA2B;IAC1E,OAAc,KAAK,SAA2B;IAC9C,OAAc,UAAU,SAAS;IAGzB,IAAI,EAAE,MAAM,CAAA;IAGZ,QAAQ,EAAE,MAAM,CAAA;IAGhB,cAAc,EAAE,MAAM,CAAA;IAGtB,SAAS,EAAE,QAAQ,CAAA;CAC5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relation_partition_trigger.d.ts","sourceRoot":"","sources":["../../src/relation_partition_trigger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"relation_partition_trigger.d.ts","sourceRoot":"","sources":["../../src/relation_partition_trigger.ts"],"names":[],"mappings":"AAuCA,KAAK,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAA;AAErD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAShE;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BlE;AAED,mFAAmF;AACnF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAYvE"}
|
|
@@ -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,56 @@ 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, ANTES de tocar el backend
|
|
59
|
+
* — la misma función, así que la misma clase, el mismo `code` y el mismo
|
|
60
|
+
* mensaje por cualquier puerta. Hacía falta en el driver (panel `{trx}`, 🔴 2
|
|
61
|
+
* del auditor): `manager.driver()` y `reconcileRelations` (que escribe con
|
|
62
|
+
* `to.relate`) entran por él, y sin la guarda
|
|
63
|
+
* `relate(evil, 'assignee', {type:'role_binding', id:<roleUuid>}, S)` componía
|
|
64
|
+
* 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
|
+
* **Cubre las OCHO operaciones del puerto** (`2.4.0-alpha.3`, cierre del
|
|
70
|
+
* 🔴 1 / 🟠 2 del auditor y cierre-2): hasta alpha.3 solo `relate`/`unrelate`
|
|
71
|
+
* la llamaban, y por `purgeObject({ type: 'role_binding', id: R }, S)` el
|
|
72
|
+
* puerto de relaciones BORRABA el binding real del store compartido
|
|
73
|
+
* (`authorize` pasaba de `true` a `false`, 0 tuplas, evento de auditoría
|
|
74
|
+
* limpio), y `listSubjects('assignee', role_binding)` enumeraba sus asignados
|
|
75
|
+
* sin catálogo ni `within`. **Son DOS funciones, no un opcional** (cierre-2,
|
|
76
|
+
* 🟠 1 del re-ataque): el primer cierre hizo `relation` opcional con un
|
|
77
|
+
* `if (relation === undefined) return` compartido por todas las llamadas, y
|
|
78
|
+
* eso APAGÓ F-05 en `relate`/`unrelate` sin relación (`request.input('relation')`
|
|
79
|
+
* ausente): antes `isDeclared('document', undefined)` era `false` ⇒ 422 con
|
|
80
|
+
* cero llamadas; con el opcional los dobles escribían la tupla, `openfga`
|
|
81
|
+
* devolvía 503 del servidor y `database` lo salvaba su driver (paridad rota),
|
|
82
|
+
* y `listSubjects(undefined)` devolvía la UNIÓN de relaciones del objeto.
|
|
83
|
+
* Esta función es ESTRICTA: la relación es obligatoria (ausente, `undefined`,
|
|
84
|
+
* vacía o no-string ⇒ 422 `E_AUTHZ_RELATION_UNKNOWN`) y la usan `relate`/
|
|
85
|
+
* `unrelate`/`check`/`listSubjects`/`membersOf` (+ `listObjects`, que también
|
|
86
|
+
* nombra una relación) y el userset de un sujeto (`{ object, relation }`).
|
|
87
|
+
* Quien NO nombra relación —`purgeObject`— usa `assertObjectTypeDeclared`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function assertRelationDeclared(config: RelationsConfig, object: RelObject | {
|
|
90
|
+
type: string;
|
|
91
|
+
}, relation: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* **F-05 sobre el TIPO solo** (cierre-2 de alpha.3): la mitad de F-05 que
|
|
94
|
+
* aplican las operaciones que NO nombran relación —`purgeObject`— y la primera
|
|
95
|
+
* comprobación de `assertRelationDeclared`. Un tipo no declarado (o un objeto
|
|
96
|
+
* que no es `{ type }`) ⇒ 422 `E_AUTHZ_RELATION_TYPE_UNKNOWN`. Separada de la
|
|
97
|
+
* estricta a propósito: deducir «solo el tipo» de un `relation === undefined`
|
|
98
|
+
* era lo que apagaba F-05 en `relate`/`unrelate` sin relación (🟠 1 del
|
|
99
|
+
* re-ataque del auditor).
|
|
100
|
+
*/
|
|
101
|
+
export declare function assertObjectTypeDeclared(config: RelationsConfig, object: RelObject | {
|
|
102
|
+
type: string;
|
|
103
|
+
}): void;
|
|
53
104
|
/**
|
|
54
105
|
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
55
106
|
* `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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ,EAAE,MAAM,GACf,IAAI,CAeN;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAc5G;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,73 @@ 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, 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
|
+
}
|
|
29
96
|
/**
|
|
30
97
|
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
31
98
|
* `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":"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"}
|
|
@@ -1,29 +1,106 @@
|
|
|
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, RelationsDriverCapabilities, RelationObjectsPage, RelationSubjectsPage, RelationPage, RelationTuplePage, RelationPurgeOptions, ScopeRef } from '../types.js';
|
|
2
2
|
import type { RelationsConfig } from './define_relations_config.js';
|
|
3
3
|
export interface RelationsManagerOptions {
|
|
4
4
|
/**
|
|
5
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
|
|
7
|
-
* rechazarla. Corre DESPUÉS de F-05 y ANTES de tocar el driver.
|
|
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).
|
|
8
12
|
*/
|
|
9
13
|
assertWrite?(ref: RelationRef): void;
|
|
10
|
-
/**
|
|
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
|
+
*/
|
|
11
24
|
onRelationWrite?(event: RelationWriteEvent): void;
|
|
12
25
|
/** `true` exige `actor` en toda escritura (paridad con `requireActor` de roles). */
|
|
13
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;
|
|
14
49
|
}
|
|
15
50
|
export declare class RelationsManager {
|
|
16
51
|
#private;
|
|
17
52
|
constructor(driver: RelationsDriver, config: RelationsConfig, options?: RelationsManagerOptions);
|
|
18
53
|
/** El driver crudo — salida documentada de las barreras (plataforma y tests). */
|
|
19
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>;
|
|
20
67
|
relate(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationWriteOptions): Promise<void>;
|
|
21
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
|
+
*/
|
|
22
79
|
check(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef): Promise<boolean>;
|
|
23
80
|
listObjects(subject: RelSubject, relation: string, objectType: string, partition: ScopeRef, page?: RelationPage): Promise<RelationObjectsPage>;
|
|
24
81
|
listSubjects(relation: string, object: RelObject, partition: ScopeRef, page?: RelationPage): Promise<RelationSubjectsPage>;
|
|
25
|
-
|
|
26
|
-
|
|
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>;
|
|
27
104
|
/**
|
|
28
105
|
* Membresía TRANSITIVA de un grupo (a través de usersets anidados) —
|
|
29
106
|
* DISTINTA de `listSubjects`, que da los hechos DIRECTOS. Solo la trae el
|
|
@@ -34,5 +111,28 @@ export declare class RelationsManager {
|
|
|
34
111
|
membersOf(object: RelObject, relation: string, partition: ScopeRef, page?: RelationPage): Promise<RelationSubjectsPage>;
|
|
35
112
|
/** ORIGEN de `authz:reconcile` de relaciones. 500 `E_AUTHZ_UNSUPPORTED` si el driver no lo trae. */
|
|
36
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>;
|
|
37
137
|
}
|
|
38
138
|
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -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":"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"}
|