@jantstack/adonis-authz 2.0.0-alpha.1 → 2.4.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +934 -40
- package/build/commands/authz_catalog_diff.d.ts.map +1 -1
- package/build/commands/authz_catalog_diff.js +1 -2
- package/build/commands/authz_catalog_diff.js.map +1 -1
- package/build/commands/authz_catalog_prune_orphans.d.ts +78 -0
- package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -0
- package/build/commands/authz_catalog_prune_orphans.js +135 -0
- package/build/commands/authz_catalog_prune_orphans.js.map +1 -0
- package/build/commands/authz_catalog_sync.d.ts +17 -0
- package/build/commands/authz_catalog_sync.d.ts.map +1 -1
- package/build/commands/authz_catalog_sync.js +27 -4
- package/build/commands/authz_catalog_sync.js.map +1 -1
- package/build/commands/authz_freeze.d.ts +44 -0
- package/build/commands/authz_freeze.d.ts.map +1 -0
- package/build/commands/authz_freeze.js +94 -0
- package/build/commands/authz_freeze.js.map +1 -0
- package/build/commands/authz_reconcile.d.ts +111 -0
- package/build/commands/authz_reconcile.d.ts.map +1 -0
- package/build/commands/authz_reconcile.js +417 -0
- package/build/commands/authz_reconcile.js.map +1 -0
- package/build/commands/authz_relations_reconcile.d.ts +144 -0
- package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
- package/build/commands/authz_relations_reconcile.js +438 -0
- package/build/commands/authz_relations_reconcile.js.map +1 -0
- package/build/commands/authz_scopes_relay.d.ts +97 -0
- package/build/commands/authz_scopes_relay.d.ts.map +1 -0
- package/build/commands/authz_scopes_relay.js +344 -0
- package/build/commands/authz_scopes_relay.js.map +1 -0
- package/build/commands/authz_scopes_requeue.d.ts +80 -0
- package/build/commands/authz_scopes_requeue.d.ts.map +1 -0
- package/build/commands/authz_scopes_requeue.js +230 -0
- package/build/commands/authz_scopes_requeue.js.map +1 -0
- package/build/commands/authz_unfreeze.d.ts +45 -0
- package/build/commands/authz_unfreeze.d.ts.map +1 -0
- package/build/commands/authz_unfreeze.js +157 -0
- package/build/commands/authz_unfreeze.js.map +1 -0
- package/build/commands/main.d.ts +16 -8
- package/build/commands/main.d.ts.map +1 -1
- package/build/commands/main.js +59 -6
- package/build/commands/main.js.map +1 -1
- package/build/commands/openfga_provision.d.ts +92 -4
- package/build/commands/openfga_provision.d.ts.map +1 -1
- package/build/commands/openfga_provision.js +155 -7
- package/build/commands/openfga_provision.js.map +1 -1
- package/build/configure.d.ts +11 -0
- package/build/configure.d.ts.map +1 -1
- package/build/configure.js +37 -1
- package/build/configure.js.map +1 -1
- package/build/index.d.ts +50 -11
- package/build/index.d.ts.map +1 -1
- package/build/index.js +49 -7
- package/build/index.js.map +1 -1
- package/build/providers/authz_provider.d.ts +31 -2
- package/build/providers/authz_provider.d.ts.map +1 -1
- package/build/providers/authz_provider.js +65 -2
- package/build/providers/authz_provider.js.map +1 -1
- package/build/services/relations.d.ts +14 -0
- package/build/services/relations.d.ts.map +1 -0
- package/build/services/relations.js +17 -0
- package/build/services/relations.js.map +1 -0
- package/build/src/{catalog.d.ts → catalog/catalog.d.ts} +41 -2
- package/build/src/catalog/catalog.d.ts.map +1 -0
- package/build/src/{catalog.js → catalog/catalog.js} +120 -14
- package/build/src/catalog/catalog.js.map +1 -0
- package/build/src/{catalog_cache.d.ts → catalog/catalog_cache.d.ts} +46 -22
- package/build/src/catalog/catalog_cache.d.ts.map +1 -0
- package/build/src/{catalog_cache.js → catalog/catalog_cache.js} +53 -43
- package/build/src/catalog/catalog_cache.js.map +1 -0
- package/build/src/define_config.d.ts +206 -3
- package/build/src/define_config.d.ts.map +1 -1
- package/build/src/define_config.js +11 -0
- package/build/src/define_config.js.map +1 -1
- package/build/src/drivers/database_driver.d.ts +128 -7
- package/build/src/drivers/database_driver.d.ts.map +1 -1
- package/build/src/drivers/database_driver.js +510 -24
- package/build/src/drivers/database_driver.js.map +1 -1
- package/build/src/drivers/database_relations_driver.d.ts +140 -0
- package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/database_relations_driver.js +748 -0
- package/build/src/drivers/database_relations_driver.js.map +1 -0
- package/build/src/drivers/openfga_driver.d.ts +777 -122
- package/build/src/drivers/openfga_driver.d.ts.map +1 -1
- package/build/src/drivers/openfga_driver.js +2228 -477
- package/build/src/drivers/openfga_driver.js.map +1 -1
- package/build/src/drivers/openfga_facts.d.ts +384 -0
- package/build/src/drivers/openfga_facts.d.ts.map +1 -0
- package/build/src/drivers/openfga_facts.js +836 -0
- package/build/src/drivers/openfga_facts.js.map +1 -0
- package/build/src/drivers/openfga_relations_driver.d.ts +186 -0
- package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
- package/build/src/drivers/openfga_relations_driver.js +724 -0
- package/build/src/drivers/openfga_relations_driver.js.map +1 -0
- package/build/src/errors.d.ts +430 -6
- package/build/src/errors.d.ts.map +1 -1
- package/build/src/errors.js +453 -6
- package/build/src/errors.js.map +1 -1
- package/build/src/freeze.d.ts +200 -0
- package/build/src/freeze.d.ts.map +1 -0
- package/build/src/freeze.js +306 -0
- package/build/src/freeze.js.map +1 -0
- package/build/src/http/app_access_middleware.d.ts.map +1 -0
- package/build/src/http/app_access_middleware.js.map +1 -0
- package/build/src/http/resource_access_middleware.d.ts +105 -0
- package/build/src/http/resource_access_middleware.d.ts.map +1 -0
- package/build/src/http/resource_access_middleware.js +81 -0
- package/build/src/http/resource_access_middleware.js.map +1 -0
- package/build/src/identity.d.ts +74 -1
- package/build/src/identity.d.ts.map +1 -1
- package/build/src/identity.js +100 -2
- package/build/src/identity.js.map +1 -1
- package/build/src/manager.d.ts +549 -6
- package/build/src/manager.d.ts.map +1 -1
- package/build/src/manager.js +2243 -193
- package/build/src/manager.js.map +1 -1
- package/build/src/models/authz_assignment.d.ts +7 -7
- package/build/src/models/authz_assignment.d.ts.map +1 -1
- package/build/src/models/authz_deny.d.ts +7 -7
- package/build/src/models/authz_deny.d.ts.map +1 -1
- package/build/src/models/authz_permission.d.ts +7 -7
- package/build/src/models/authz_permission.d.ts.map +1 -1
- package/build/src/models/authz_role.d.ts +7 -7
- package/build/src/models/authz_role.d.ts.map +1 -1
- package/build/src/models/authz_role_permission.d.ts +7 -7
- package/build/src/models/authz_role_permission.d.ts.map +1 -1
- package/build/src/openfga.d.ts +18 -2
- package/build/src/openfga.d.ts.map +1 -1
- package/build/src/openfga.js +15 -1
- package/build/src/openfga.js.map +1 -1
- package/build/src/reconcile.d.ts +37 -0
- package/build/src/reconcile.d.ts.map +1 -0
- package/build/src/reconcile.js +69 -0
- package/build/src/reconcile.js.map +1 -0
- package/build/src/relation_partition_trigger.d.ts +8 -0
- package/build/src/relation_partition_trigger.d.ts.map +1 -0
- package/build/src/relation_partition_trigger.js +93 -0
- package/build/src/relation_partition_trigger.js.map +1 -0
- package/build/src/relations/define_relations_config.d.ts +109 -0
- package/build/src/relations/define_relations_config.d.ts.map +1 -0
- package/build/src/relations/define_relations_config.js +211 -0
- package/build/src/relations/define_relations_config.js.map +1 -0
- package/build/src/relations/manager.d.ts +138 -0
- package/build/src/relations/manager.d.ts.map +1 -0
- package/build/src/relations/manager.js +494 -0
- package/build/src/relations/manager.js.map +1 -0
- package/build/src/relations/reconcile.d.ts +137 -0
- package/build/src/relations/reconcile.d.ts.map +1 -0
- package/build/src/relations/reconcile.js +294 -0
- package/build/src/relations/reconcile.js.map +1 -0
- package/build/src/relations_config_store.d.ts +22 -0
- package/build/src/relations_config_store.d.ts.map +1 -0
- package/build/src/relations_config_store.js +74 -0
- package/build/src/relations_config_store.js.map +1 -0
- package/build/src/scope_outbox.d.ts +123 -0
- package/build/src/scope_outbox.d.ts.map +1 -0
- package/build/src/scope_outbox.js +532 -0
- package/build/src/scope_outbox.js.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.d.ts +42 -0
- package/build/src/shared/backend_guard.d.ts.map +1 -0
- package/build/src/{drivers → shared}/backend_guard.js +78 -1
- package/build/src/shared/backend_guard.js.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.d.ts +2 -0
- package/build/src/shared/sql_expiry.d.ts.map +1 -0
- package/build/src/{drivers → shared}/sql_expiry.js +4 -0
- package/build/src/shared/sql_expiry.js.map +1 -0
- package/build/src/shared/transaction_guard.d.ts +53 -0
- package/build/src/shared/transaction_guard.d.ts.map +1 -0
- package/build/src/shared/transaction_guard.js +74 -0
- package/build/src/shared/transaction_guard.js.map +1 -0
- package/build/src/sql_descendants.d.ts +55 -1
- package/build/src/sql_descendants.d.ts.map +1 -1
- package/build/src/sql_descendants.js +75 -1
- package/build/src/sql_descendants.js.map +1 -1
- package/build/src/testing/contract.d.ts +129 -4
- package/build/src/testing/contract.d.ts.map +1 -1
- package/build/src/testing/contract.js +915 -177
- package/build/src/testing/contract.js.map +1 -1
- package/build/src/testing/main.d.ts +10 -2
- package/build/src/testing/main.d.ts.map +1 -1
- package/build/src/testing/main.js +5 -1
- package/build/src/testing/main.js.map +1 -1
- package/build/src/testing/migration_contract.d.ts +293 -0
- package/build/src/testing/migration_contract.d.ts.map +1 -0
- package/build/src/testing/migration_contract.js +589 -0
- package/build/src/testing/migration_contract.js.map +1 -0
- package/build/src/testing/relations_contract.d.ts +73 -0
- package/build/src/testing/relations_contract.d.ts.map +1 -0
- package/build/src/testing/relations_contract.js +1238 -0
- package/build/src/testing/relations_contract.js.map +1 -0
- package/build/src/testing/relations_reconcile_contract.d.ts +24 -0
- package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -0
- package/build/src/testing/relations_reconcile_contract.js +220 -0
- package/build/src/testing/relations_reconcile_contract.js.map +1 -0
- package/build/src/testing/scope_outbox_contract.d.ts +98 -0
- package/build/src/testing/scope_outbox_contract.d.ts.map +1 -0
- package/build/src/testing/scope_outbox_contract.js +677 -0
- package/build/src/testing/scope_outbox_contract.js.map +1 -0
- package/build/src/traits/authz_scopes.js +1 -1
- package/build/src/traits/authz_scopes.js.map +1 -1
- package/build/src/traits/has_uuid.d.ts +8 -8
- package/build/src/traits/has_uuid.d.ts.map +1 -1
- package/build/src/types.d.ts +1537 -84
- package/build/src/types.d.ts.map +1 -1
- package/build/src/types.js +65 -0
- package/build/src/types.js.map +1 -1
- package/build/stubs/config/authorization.stub +149 -5
- package/build/stubs/migration.stub +136 -0
- package/build/stubs/scopes_outbox_migration.stub +57 -0
- package/package.json +4 -2
- package/build/commands/openfga_import.d.ts +0 -34
- package/build/commands/openfga_import.d.ts.map +0 -1
- package/build/commands/openfga_import.js +0 -97
- package/build/commands/openfga_import.js.map +0 -1
- package/build/src/catalog.d.ts.map +0 -1
- package/build/src/catalog.js.map +0 -1
- package/build/src/catalog_cache.d.ts.map +0 -1
- package/build/src/catalog_cache.js.map +0 -1
- package/build/src/drivers/backend_guard.d.ts.map +0 -1
- package/build/src/drivers/backend_guard.js.map +0 -1
- package/build/src/drivers/sql_expiry.d.ts.map +0 -1
- package/build/src/drivers/sql_expiry.js.map +0 -1
- package/build/src/middleware/app_access_middleware.d.ts.map +0 -1
- package/build/src/middleware/app_access_middleware.js.map +0 -1
- /package/build/src/{middleware → http}/app_access_middleware.d.ts +0 -0
- /package/build/src/{middleware → http}/app_access_middleware.js +0 -0
|
@@ -68,6 +68,13 @@ declare const AuthzRolePermission_base: {
|
|
|
68
68
|
connection?: string | undefined;
|
|
69
69
|
first: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
|
|
70
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>;
|
|
73
|
+
after: {
|
|
74
|
+
<Model extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model>[], "fetch">): void;
|
|
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;
|
|
76
|
+
<Model extends import("@adonisjs/lucid/types/model").LucidModel, Event extends import("@adonisjs/lucid/types/model").EventsList>(this: Model, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model>, Event>): void;
|
|
77
|
+
};
|
|
71
78
|
readonly booted: boolean;
|
|
72
79
|
$columnsDefinitions: Map<string, import("@adonisjs/lucid/types/model").ModelColumnOptions>;
|
|
73
80
|
$relationsDefinitions: Map<string, import("@adonisjs/lucid/types/relations").RelationshipsContract>;
|
|
@@ -109,11 +116,6 @@ declare const AuthzRolePermission_base: {
|
|
|
109
116
|
<Model extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<[import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model>, import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model>], "paginate">): void;
|
|
110
117
|
<Model extends import("@adonisjs/lucid/types/model").LucidModel, Event extends import("@adonisjs/lucid/types/model").EventsList>(this: Model, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model>, Event>): void;
|
|
111
118
|
};
|
|
112
|
-
after: {
|
|
113
|
-
<Model extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model>[], "fetch">): void;
|
|
114
|
-
<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;
|
|
115
|
-
<Model extends import("@adonisjs/lucid/types/model").LucidModel, Event extends import("@adonisjs/lucid/types/model").EventsList>(this: Model, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model>, Event>): void;
|
|
116
|
-
};
|
|
117
119
|
create: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
|
|
118
120
|
createQuietly: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
|
|
119
121
|
createMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
|
|
@@ -139,8 +141,6 @@ declare const AuthzRolePermission_base: {
|
|
|
139
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>[]>;
|
|
140
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>[]>;
|
|
141
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>[]>;
|
|
142
|
-
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>;
|
|
143
|
-
transaction: import("@adonisjs/lucid/types/database").TransactionFn;
|
|
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"}
|
package/build/src/openfga.d.ts
CHANGED
|
@@ -8,6 +8,22 @@
|
|
|
8
8
|
* el driver: un consumidor solo-database arranca sin el SDK instalado, y
|
|
9
9
|
* `scripts/check_purity.mjs` (regla 3) lo vigila en cada build.
|
|
10
10
|
*/
|
|
11
|
-
export { OpenFgaAuthorizationDriver,
|
|
12
|
-
export type { HolderTypeMap, OpenFgaDriverOptions
|
|
11
|
+
export { OpenFgaAuthorizationDriver, provisionOpenFgaStore, assertHolderTypes, parseBindingId, correlateBatchResults, isDuplicateWrite, DEFAULT_TIMEOUT_MS, } from './drivers/openfga_driver.js';
|
|
12
|
+
export type { HolderTypeMap, OpenFgaDriverOptions } from './drivers/openfga_driver.js';
|
|
13
|
+
/**
|
|
14
|
+
* El driver `openfga` del puerto `RelationsDriver` (Fase 4, lote 4-4): ReBAC
|
|
15
|
+
* sobre el MISMO store y `modelId` que el driver `facts` de roles. Vive detrás
|
|
16
|
+
* de esta puerta como el resto de lo que toca `@openfga/sdk`.
|
|
17
|
+
*/
|
|
18
|
+
export { OpenFgaRelationsDriver } from './drivers/openfga_relations_driver.js';
|
|
19
|
+
export type { OpenFgaRelationsDriverOptions } from './drivers/openfga_relations_driver.js';
|
|
20
|
+
/**
|
|
21
|
+
* El modelo (c2r) y la proyección del catálogo (3b-2a; desde 3b-2k · K2 es
|
|
22
|
+
* el ÚNICO modelo: `openFgaAuthorizationModel` —el del modo `resolver`— y
|
|
23
|
+
* `importAuthzFactsToOpenFga` se borraron con él). Sin `@openfga/sdk` —es
|
|
24
|
+
* JSON y cadenas—, pero se publica por esta misma puerta: es material de
|
|
25
|
+
* OpenFGA y solo lo usa quien lo elige.
|
|
26
|
+
*/
|
|
27
|
+
export { openFgaFactsModel, factsRelationsOf, factsRelationMap, factsCatalogTuples, factsTupleId, factsModelBytes, assertFactsModelPublishable, assertFgaObjectId, FACTS_MODEL_MAX_BYTES, FACTS_MODEL_WARN_RATIO, FGA_MAX_RELATION_NAME, FGA_MAX_OBJECT_ID, FACTS_MAX_RESOLVE_DEPTH, FGA_MAX_BATCH_CHECK, factsScopeObject, factsParentTuple, FACTS_SCOPE_TYPE, FACTS_PARENT_RELATION, factsRootTuples, FACTS_ROOTED_RELATION, factsRelationTypeDefinitions, assertRelationsConfigPublishable, RESERVED_FACTS_TYPES, FACTS_GROUP_TYPE, FACTS_GROUP_MEMBER_RELATION, } from './drivers/openfga_facts.js';
|
|
28
|
+
export type { FactsRelations, FactsCatalogTuple, FactsTuple, FactsRelationsConfig, RelationObjectType, RelationObjectRelation, } from './drivers/openfga_facts.js';
|
|
13
29
|
//# sourceMappingURL=openfga.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openfga.d.ts","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,
|
|
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,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;AAC9E,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
|
@@ -8,5 +8,19 @@
|
|
|
8
8
|
* el driver: un consumidor solo-database arranca sin el SDK instalado, y
|
|
9
9
|
* `scripts/check_purity.mjs` (regla 3) lo vigila en cada build.
|
|
10
10
|
*/
|
|
11
|
-
export { OpenFgaAuthorizationDriver,
|
|
11
|
+
export { OpenFgaAuthorizationDriver, provisionOpenFgaStore, assertHolderTypes, parseBindingId, correlateBatchResults, isDuplicateWrite, DEFAULT_TIMEOUT_MS, } from './drivers/openfga_driver.js';
|
|
12
|
+
/**
|
|
13
|
+
* El driver `openfga` del puerto `RelationsDriver` (Fase 4, lote 4-4): ReBAC
|
|
14
|
+
* sobre el MISMO store y `modelId` que el driver `facts` de roles. Vive detrás
|
|
15
|
+
* de esta puerta como el resto de lo que toca `@openfga/sdk`.
|
|
16
|
+
*/
|
|
17
|
+
export { OpenFgaRelationsDriver } from './drivers/openfga_relations_driver.js';
|
|
18
|
+
/**
|
|
19
|
+
* El modelo (c2r) y la proyección del catálogo (3b-2a; desde 3b-2k · K2 es
|
|
20
|
+
* el ÚNICO modelo: `openFgaAuthorizationModel` —el del modo `resolver`— y
|
|
21
|
+
* `importAuthzFactsToOpenFga` se borraron con él). Sin `@openfga/sdk` —es
|
|
22
|
+
* JSON y cadenas—, pero se publica por esta misma puerta: es material de
|
|
23
|
+
* OpenFGA y solo lo usa quien lo elige.
|
|
24
|
+
*/
|
|
25
|
+
export { openFgaFactsModel, factsRelationsOf, factsRelationMap, factsCatalogTuples, factsTupleId, factsModelBytes, assertFactsModelPublishable, assertFgaObjectId, FACTS_MODEL_MAX_BYTES, FACTS_MODEL_WARN_RATIO, FGA_MAX_RELATION_NAME, FGA_MAX_OBJECT_ID, FACTS_MAX_RESOLVE_DEPTH, FGA_MAX_BATCH_CHECK, factsScopeObject, factsParentTuple, FACTS_SCOPE_TYPE, FACTS_PARENT_RELATION, factsRootTuples, FACTS_ROOTED_RELATION, factsRelationTypeDefinitions, assertRelationsConfigPublishable, RESERVED_FACTS_TYPES, FACTS_GROUP_TYPE, FACTS_GROUP_MEMBER_RELATION, } from './drivers/openfga_facts.js';
|
|
12
26
|
//# sourceMappingURL=openfga.js.map
|
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,
|
|
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,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AAGpC;;;;GAIG;AACH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAG9E;;;;;;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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Piezas COMPARTIDAS de `authz:reconcile` (3b-3b): lo que las dos
|
|
3
|
+
* direcciones —`--to=openfga` (3b-3a) y `--to=database`— tienen que decidir
|
|
4
|
+
* igual o el reporte deja de significar lo mismo según hacia dónde se migre.
|
|
5
|
+
*
|
|
6
|
+
* Vive aquí y no en un driver porque el driver `database` no puede importar
|
|
7
|
+
* del `openfga` (arrastraría el SDK, que es una peer dependency opcional) y
|
|
8
|
+
* porque duplicar la normalización de `batchSize`, la cota del volcado o la
|
|
9
|
+
* suma de fases es la forma más barata de que las dos direcciones cuenten
|
|
10
|
+
* distinto. Módulo puro: sin base de datos, sin red y sin `#aliases` del
|
|
11
|
+
* consumidor (`check:purity`).
|
|
12
|
+
*/
|
|
13
|
+
import type { ReconcileCounts } from './types.js';
|
|
14
|
+
/** Filas por lote en el ORIGEN y operaciones por escritura en el destino. */
|
|
15
|
+
export declare const RECONCILE_BATCH = 100;
|
|
16
|
+
/**
|
|
17
|
+
* Cómo se NOMBRA el origen cuando los hechos son las tablas del paquete
|
|
18
|
+
* (3b-5). No es un driver: es el esquema PUBLICADO, y por eso tiene nombre
|
|
19
|
+
* propio en el reporte —«de dónde salieron los hechos» es la diferencia
|
|
20
|
+
* entre una migración y una pasada contra el driver activo—.
|
|
21
|
+
*/
|
|
22
|
+
export declare const AUTHZ_TABLES_ORIGIN = "authz_assignments/authz_denies";
|
|
23
|
+
/** Tope de filas del reporte que se nombran una a una (el resto solo se cuenta). */
|
|
24
|
+
export declare const RECONCILE_MAX_DETAILS = 200;
|
|
25
|
+
/** Las cuatro fases de una pasada; en `--to=database` las tres primeras son cero. */
|
|
26
|
+
export type ReconcileFamily = 'root' | 'catalog' | 'tree' | 'facts';
|
|
27
|
+
export declare function reconcileBatchSize(value: number | undefined): number;
|
|
28
|
+
/**
|
|
29
|
+
* La cota DECLARADA del volcado (3b-3b · B5). No es una promesa de memoria:
|
|
30
|
+
* es el número por encima del cual la pasada se niega con
|
|
31
|
+
* `E_AUTHZ_RECONCILE_TOO_LARGE` en vez de intentarlo y morir a medias.
|
|
32
|
+
*/
|
|
33
|
+
export declare function reconcileMaxTuples(value: number | undefined): number;
|
|
34
|
+
export declare function emptyReconcileCounts(): ReconcileCounts;
|
|
35
|
+
export declare function emptyReconcilePhases(): Record<ReconcileFamily, ReconcileCounts>;
|
|
36
|
+
export declare function sumReconcilePhases(phases: Record<ReconcileFamily, ReconcileCounts>): ReconcileCounts;
|
|
37
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,6EAA6E;AAC7E,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,mCAAmC,CAAA;AAEnE,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC,qFAAqF;AACrF,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAA;AAEnE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAMpE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAMpE;AAED,wBAAgB,oBAAoB,IAAI,eAAe,CAEtD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,CAO/E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,GAAG,eAAe,CAUpG"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Piezas COMPARTIDAS de `authz:reconcile` (3b-3b): lo que las dos
|
|
3
|
+
* direcciones —`--to=openfga` (3b-3a) y `--to=database`— tienen que decidir
|
|
4
|
+
* igual o el reporte deja de significar lo mismo según hacia dónde se migre.
|
|
5
|
+
*
|
|
6
|
+
* Vive aquí y no en un driver porque el driver `database` no puede importar
|
|
7
|
+
* del `openfga` (arrastraría el SDK, que es una peer dependency opcional) y
|
|
8
|
+
* porque duplicar la normalización de `batchSize`, la cota del volcado o la
|
|
9
|
+
* suma de fases es la forma más barata de que las dos direcciones cuenten
|
|
10
|
+
* distinto. Módulo puro: sin base de datos, sin red y sin `#aliases` del
|
|
11
|
+
* consumidor (`check:purity`).
|
|
12
|
+
*/
|
|
13
|
+
import { AuthorizationConfigError } from './errors.js';
|
|
14
|
+
import { DEFAULT_RECONCILE_MAX_TUPLES } from './types.js';
|
|
15
|
+
/** Filas por lote en el ORIGEN y operaciones por escritura en el destino. */
|
|
16
|
+
export const RECONCILE_BATCH = 100;
|
|
17
|
+
/**
|
|
18
|
+
* Cómo se NOMBRA el origen cuando los hechos son las tablas del paquete
|
|
19
|
+
* (3b-5). No es un driver: es el esquema PUBLICADO, y por eso tiene nombre
|
|
20
|
+
* propio en el reporte —«de dónde salieron los hechos» es la diferencia
|
|
21
|
+
* entre una migración y una pasada contra el driver activo—.
|
|
22
|
+
*/
|
|
23
|
+
export const AUTHZ_TABLES_ORIGIN = 'authz_assignments/authz_denies';
|
|
24
|
+
/** Tope de filas del reporte que se nombran una a una (el resto solo se cuenta). */
|
|
25
|
+
export const RECONCILE_MAX_DETAILS = 200;
|
|
26
|
+
export function reconcileBatchSize(value) {
|
|
27
|
+
if (value === undefined)
|
|
28
|
+
return RECONCILE_BATCH;
|
|
29
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
30
|
+
throw new AuthorizationConfigError(`authz:reconcile: batchSize debe ser un entero >= 1 (llegó ${String(value)})`);
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* La cota DECLARADA del volcado (3b-3b · B5). No es una promesa de memoria:
|
|
36
|
+
* es el número por encima del cual la pasada se niega con
|
|
37
|
+
* `E_AUTHZ_RECONCILE_TOO_LARGE` en vez de intentarlo y morir a medias.
|
|
38
|
+
*/
|
|
39
|
+
export function reconcileMaxTuples(value) {
|
|
40
|
+
if (value === undefined)
|
|
41
|
+
return DEFAULT_RECONCILE_MAX_TUPLES;
|
|
42
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
43
|
+
throw new AuthorizationConfigError(`authz:reconcile: maxTuples debe ser un entero >= 1 (llegó ${String(value)})`);
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
export function emptyReconcileCounts() {
|
|
48
|
+
return { written: 0, updated: 0, unchanged: 0, extra: 0, deleted: 0 };
|
|
49
|
+
}
|
|
50
|
+
export function emptyReconcilePhases() {
|
|
51
|
+
return {
|
|
52
|
+
root: emptyReconcileCounts(),
|
|
53
|
+
catalog: emptyReconcileCounts(),
|
|
54
|
+
tree: emptyReconcileCounts(),
|
|
55
|
+
facts: emptyReconcileCounts(),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function sumReconcilePhases(phases) {
|
|
59
|
+
const total = emptyReconcileCounts();
|
|
60
|
+
for (const counts of Object.values(phases)) {
|
|
61
|
+
total.written += counts.written;
|
|
62
|
+
total.updated += counts.updated;
|
|
63
|
+
total.unchanged += counts.unchanged;
|
|
64
|
+
total.extra += counts.extra;
|
|
65
|
+
total.deleted += counts.deleted;
|
|
66
|
+
}
|
|
67
|
+
return total;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=reconcile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAGzD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;AAElC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,gCAAgC,CAAA;AAEnE,oFAAoF;AACpF,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAA;AAKxC,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,eAAe,CAAA;IAC/C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,wBAAwB,CAAC,6DAA6D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,4BAA4B,CAAA;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,wBAAwB,CAAC,6DAA6D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;AACvE,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,IAAI,EAAE,oBAAoB,EAAE;QAC5B,OAAO,EAAE,oBAAoB,EAAE;QAC/B,IAAI,EAAE,oBAAoB,EAAE;QAC5B,KAAK,EAAE,oBAAoB,EAAE;KAC9B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAgD;IACjF,MAAM,KAAK,GAAG,oBAAoB,EAAE,CAAA;IACpC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAA;QAC/B,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAA;QAC/B,KAAK,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAA;QACnC,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAA;QAC3B,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAA;IACjC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type TriggerDialect = 'sqlite' | 'postgres' | 'mysql';
|
|
2
|
+
export declare function triggerDialectOf(dialect: string): TriggerDialect;
|
|
3
|
+
/** Las sentencias a EJECUTAR (enteras) para crear el trigger de partición. */
|
|
4
|
+
export declare function relationPartitionTrigger(dialect: string): string[];
|
|
5
|
+
/** Las sentencias para soltar el trigger (y, en PG, su función) en el `down()`. */
|
|
6
|
+
export declare function relationPartitionTriggerDrops(dialect: string): string[];
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=relation_partition_trigger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **La DDL del trigger de partición de `authz_relations` por dialecto** (Fase 4,
|
|
3
|
+
* lote 4-3) — módulo PURO, sin dependencia del servicio `db` de Lucid, para que
|
|
4
|
+
* lo pueda importar tanto el driver `database` de relaciones como el espejo del
|
|
5
|
+
* esquema de la suite (que se carga ANTES de bootear la app).
|
|
6
|
+
*
|
|
7
|
+
* El trigger es la defensa en profundidad contra un escritor «a mano» que meta
|
|
8
|
+
* en `authz_relations` una fila cuyo USERSET (sujeto con `subject_relation`)
|
|
9
|
+
* pertenece a OTRA partición que la de la fila. Cada sentencia se ejecuta
|
|
10
|
+
* ENTERA (su cuerpo `BEGIN…END` lleva `;` dentro): nunca por un runner que
|
|
11
|
+
* trocea por `;`.
|
|
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
|
+
*
|
|
21
|
+
* La forma es RADICALMENTE distinta en cada motor (medido por el analista, y
|
|
22
|
+
* probado en INSERT **y** UPDATE):
|
|
23
|
+
* - **SQLite**: `CREATE TRIGGER … BEFORE INSERT/UPDATE … WHEN … BEGIN SELECT
|
|
24
|
+
* RAISE(ABORT, …); END` — un trigger por evento; `IS NOT` es el distinto
|
|
25
|
+
* null-safe.
|
|
26
|
+
* - **PostgreSQL**: exige una FUNCIÓN plpgsql SEPARADA (`RAISE EXCEPTION`) y
|
|
27
|
+
* un `CREATE TRIGGER … EXECUTE FUNCTION` que la invoca; un solo trigger
|
|
28
|
+
* `BEFORE INSERT OR UPDATE`. `IS DISTINCT FROM` es el distinto null-safe.
|
|
29
|
+
* - **MySQL**: `SIGNAL SQLSTATE '45000'` dentro de `IF … THEN … END IF`; un
|
|
30
|
+
* trigger por evento; `<=>` es el igual null-safe (`NOT (a <=> b)` = distinto).
|
|
31
|
+
*
|
|
32
|
+
* Cualquier otro dialecto ⇒ 500 `E_AUTHZ_UNSUPPORTED_DIALECT` (nunca una tabla
|
|
33
|
+
* sin defensa), exactamente como `sqlDescendantsOf`.
|
|
34
|
+
*/
|
|
35
|
+
import { UnsupportedDialectError } from './errors.js';
|
|
36
|
+
const RELATIONS_TABLE = 'authz_relations';
|
|
37
|
+
const TRIGGER_MESSAGE = 'authz_relations: un userset no puede pertenecer a otra partición que su tupla';
|
|
38
|
+
export function triggerDialectOf(dialect) {
|
|
39
|
+
if (dialect === 'sqlite3' || dialect === 'better-sqlite3')
|
|
40
|
+
return 'sqlite';
|
|
41
|
+
if (dialect === 'postgres')
|
|
42
|
+
return 'postgres';
|
|
43
|
+
if (dialect === 'mysql' || dialect === 'mysql2')
|
|
44
|
+
return 'mysql';
|
|
45
|
+
throw new UnsupportedDialectError(`relationPartitionTrigger: dialecto '${dialect}' sin observación en la suite ` +
|
|
46
|
+
`(hoy: PostgreSQL, MySQL 8 y SQLite). El trigger de partición defiende al escritor a mano, ` +
|
|
47
|
+
`y su DDL no se declara igual en dos motores: mídelo antes de dar por buena una tabla sin defensa.`);
|
|
48
|
+
}
|
|
49
|
+
/** Las sentencias a EJECUTAR (enteras) para crear el trigger de partición. */
|
|
50
|
+
export function relationPartitionTrigger(dialect) {
|
|
51
|
+
const kind = triggerDialectOf(dialect);
|
|
52
|
+
if (kind === 'sqlite') {
|
|
53
|
+
const body = (event) => `CREATE TRIGGER authz_relations_partition_b${event === 'INSERT' ? 'i' : 'u'} ` +
|
|
54
|
+
`BEFORE ${event} ON ${RELATIONS_TABLE} FOR EACH ROW ` +
|
|
55
|
+
`WHEN NEW.subject_relation <> '' AND NEW.subject_partition IS NOT NEW.partition_key ` +
|
|
56
|
+
`BEGIN SELECT RAISE(ABORT, '${TRIGGER_MESSAGE}'); END`;
|
|
57
|
+
return [body('INSERT'), body('UPDATE')];
|
|
58
|
+
}
|
|
59
|
+
if (kind === 'postgres') {
|
|
60
|
+
return [
|
|
61
|
+
`CREATE OR REPLACE FUNCTION authz_relations_partition_guard() RETURNS trigger LANGUAGE plpgsql AS $authz$ ` +
|
|
62
|
+
`BEGIN ` +
|
|
63
|
+
`IF NEW.subject_relation <> '' AND NEW.subject_partition IS DISTINCT FROM NEW.partition_key THEN ` +
|
|
64
|
+
`RAISE EXCEPTION '${TRIGGER_MESSAGE} (subject_partition=%, partition_key=%)', NEW.subject_partition, NEW.partition_key; ` +
|
|
65
|
+
`END IF; RETURN NEW; END; $authz$`,
|
|
66
|
+
`CREATE TRIGGER authz_relations_partition_biu BEFORE INSERT OR UPDATE ON ${RELATIONS_TABLE} ` +
|
|
67
|
+
`FOR EACH ROW EXECUTE FUNCTION authz_relations_partition_guard()`,
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
// mysql
|
|
71
|
+
const body = (event) => `CREATE TRIGGER authz_relations_partition_b${event === 'INSERT' ? 'i' : 'u'} ` +
|
|
72
|
+
`BEFORE ${event} ON ${RELATIONS_TABLE} FOR EACH ROW ` +
|
|
73
|
+
`BEGIN ` +
|
|
74
|
+
`IF NEW.subject_relation <> '' AND NOT (NEW.subject_partition <=> NEW.partition_key) THEN ` +
|
|
75
|
+
`SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '${TRIGGER_MESSAGE}'; ` +
|
|
76
|
+
`END IF; END`;
|
|
77
|
+
return [body('INSERT'), body('UPDATE')];
|
|
78
|
+
}
|
|
79
|
+
/** Las sentencias para soltar el trigger (y, en PG, su función) en el `down()`. */
|
|
80
|
+
export function relationPartitionTriggerDrops(dialect) {
|
|
81
|
+
const kind = triggerDialectOf(dialect);
|
|
82
|
+
if (kind === 'postgres') {
|
|
83
|
+
return [
|
|
84
|
+
`DROP TRIGGER IF EXISTS authz_relations_partition_biu ON ${RELATIONS_TABLE}`,
|
|
85
|
+
'DROP FUNCTION IF EXISTS authz_relations_partition_guard()',
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
return [
|
|
89
|
+
'DROP TRIGGER IF EXISTS authz_relations_partition_bi',
|
|
90
|
+
'DROP TRIGGER IF EXISTS authz_relations_partition_bu',
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=relation_partition_trigger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { RelObject } from '../types.js';
|
|
2
|
+
/** Una relación de un tipo de objeto (`document#viewer`), con sus `includes` de un nivel. */
|
|
3
|
+
export interface RelationObjectRelationSpec {
|
|
4
|
+
/** El nombre de la relación (`owner`, `editor`, `viewer`). */
|
|
5
|
+
name: string;
|
|
6
|
+
/**
|
|
7
|
+
* Otras relaciones del MISMO tipo que ésta incluye (`viewer or editor`):
|
|
8
|
+
* un `relate(u, editor, doc)` concede también `viewer`. Un nivel, SIN
|
|
9
|
+
* `from` en v1 (la herencia cross-objeto metería un TTU entre tipos y
|
|
10
|
+
* habría que re-medir profundidad — diferido a 2.6+).
|
|
11
|
+
*/
|
|
12
|
+
includes?: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
/** Un tipo de objeto de relaciones (`document`, `folder`, `space`…). */
|
|
15
|
+
export interface RelationObjectTypeSpec {
|
|
16
|
+
/** El tipo FGA del objeto. */
|
|
17
|
+
type: string;
|
|
18
|
+
/** Sus relaciones, en orden de declaración. */
|
|
19
|
+
relations: readonly RelationObjectRelationSpec[];
|
|
20
|
+
}
|
|
21
|
+
/** Opciones específicas del driver `database`. */
|
|
22
|
+
export interface RelationsDatabaseOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Habilita `membersOf` (membresía TRANSITIVA a través de usersets), que solo
|
|
25
|
+
* el driver `database` resuelve (CTE recursiva). En `openfga` la transitiva
|
|
26
|
+
* sería `ListUsers`, que trunca, así que la opción NO es válida fuera de
|
|
27
|
+
* `database`.
|
|
28
|
+
*/
|
|
29
|
+
membersOf?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** La config que declara el consumidor. */
|
|
32
|
+
export interface RelationsConfigSpec {
|
|
33
|
+
/** Los tipos de objeto y sus relaciones. */
|
|
34
|
+
objectTypes: readonly RelationObjectTypeSpec[];
|
|
35
|
+
/**
|
|
36
|
+
* Los holder types del config del consumidor (`user`, `admin`…). Se suman a
|
|
37
|
+
* los tipos reservados: un tipo de objeto de relaciones no puede llamarse
|
|
38
|
+
* como un holder (⚪4).
|
|
39
|
+
*/
|
|
40
|
+
holderTypes?: readonly string[];
|
|
41
|
+
/** Opciones del driver `database` (donde vive `membersOf`). */
|
|
42
|
+
database?: RelationsDatabaseOptions;
|
|
43
|
+
}
|
|
44
|
+
/** La config ya validada y CONGELADA que consulta el manager de relaciones. */
|
|
45
|
+
export interface RelationsConfig {
|
|
46
|
+
readonly objectTypes: readonly RelationObjectTypeSpec[];
|
|
47
|
+
/** ¿`membersOf` está habilitado (opción de `database`)? */
|
|
48
|
+
readonly membersOf: boolean;
|
|
49
|
+
/** ¿Existe el tipo de objeto? (F-05, cara del tipo). */
|
|
50
|
+
hasType(objectType: string): boolean;
|
|
51
|
+
/** ¿La relación está declarada para ese tipo? (F-05, cara de la relación). */
|
|
52
|
+
isDeclared(objectType: string, relation: string): boolean;
|
|
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;
|
|
104
|
+
/**
|
|
105
|
+
* Valida y congela la config de relaciones. Config inválida ⇒ 422
|
|
106
|
+
* `E_AUTHZ_RELATION_CONFIG` (misma clase que el gate del modelo del lote 4-1).
|
|
107
|
+
*/
|
|
108
|
+
export declare function defineRelationsConfig(spec: RelationsConfigSpec): RelationsConfig;
|
|
109
|
+
//# sourceMappingURL=define_relations_config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|