@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.
Files changed (224) hide show
  1. package/README.md +934 -40
  2. package/build/commands/authz_catalog_diff.d.ts.map +1 -1
  3. package/build/commands/authz_catalog_diff.js +1 -2
  4. package/build/commands/authz_catalog_diff.js.map +1 -1
  5. package/build/commands/authz_catalog_prune_orphans.d.ts +78 -0
  6. package/build/commands/authz_catalog_prune_orphans.d.ts.map +1 -0
  7. package/build/commands/authz_catalog_prune_orphans.js +135 -0
  8. package/build/commands/authz_catalog_prune_orphans.js.map +1 -0
  9. package/build/commands/authz_catalog_sync.d.ts +17 -0
  10. package/build/commands/authz_catalog_sync.d.ts.map +1 -1
  11. package/build/commands/authz_catalog_sync.js +27 -4
  12. package/build/commands/authz_catalog_sync.js.map +1 -1
  13. package/build/commands/authz_freeze.d.ts +44 -0
  14. package/build/commands/authz_freeze.d.ts.map +1 -0
  15. package/build/commands/authz_freeze.js +94 -0
  16. package/build/commands/authz_freeze.js.map +1 -0
  17. package/build/commands/authz_reconcile.d.ts +111 -0
  18. package/build/commands/authz_reconcile.d.ts.map +1 -0
  19. package/build/commands/authz_reconcile.js +417 -0
  20. package/build/commands/authz_reconcile.js.map +1 -0
  21. package/build/commands/authz_relations_reconcile.d.ts +144 -0
  22. package/build/commands/authz_relations_reconcile.d.ts.map +1 -0
  23. package/build/commands/authz_relations_reconcile.js +438 -0
  24. package/build/commands/authz_relations_reconcile.js.map +1 -0
  25. package/build/commands/authz_scopes_relay.d.ts +97 -0
  26. package/build/commands/authz_scopes_relay.d.ts.map +1 -0
  27. package/build/commands/authz_scopes_relay.js +344 -0
  28. package/build/commands/authz_scopes_relay.js.map +1 -0
  29. package/build/commands/authz_scopes_requeue.d.ts +80 -0
  30. package/build/commands/authz_scopes_requeue.d.ts.map +1 -0
  31. package/build/commands/authz_scopes_requeue.js +230 -0
  32. package/build/commands/authz_scopes_requeue.js.map +1 -0
  33. package/build/commands/authz_unfreeze.d.ts +45 -0
  34. package/build/commands/authz_unfreeze.d.ts.map +1 -0
  35. package/build/commands/authz_unfreeze.js +157 -0
  36. package/build/commands/authz_unfreeze.js.map +1 -0
  37. package/build/commands/main.d.ts +16 -8
  38. package/build/commands/main.d.ts.map +1 -1
  39. package/build/commands/main.js +59 -6
  40. package/build/commands/main.js.map +1 -1
  41. package/build/commands/openfga_provision.d.ts +92 -4
  42. package/build/commands/openfga_provision.d.ts.map +1 -1
  43. package/build/commands/openfga_provision.js +155 -7
  44. package/build/commands/openfga_provision.js.map +1 -1
  45. package/build/configure.d.ts +11 -0
  46. package/build/configure.d.ts.map +1 -1
  47. package/build/configure.js +37 -1
  48. package/build/configure.js.map +1 -1
  49. package/build/index.d.ts +50 -11
  50. package/build/index.d.ts.map +1 -1
  51. package/build/index.js +49 -7
  52. package/build/index.js.map +1 -1
  53. package/build/providers/authz_provider.d.ts +31 -2
  54. package/build/providers/authz_provider.d.ts.map +1 -1
  55. package/build/providers/authz_provider.js +65 -2
  56. package/build/providers/authz_provider.js.map +1 -1
  57. package/build/services/relations.d.ts +14 -0
  58. package/build/services/relations.d.ts.map +1 -0
  59. package/build/services/relations.js +17 -0
  60. package/build/services/relations.js.map +1 -0
  61. package/build/src/{catalog.d.ts → catalog/catalog.d.ts} +41 -2
  62. package/build/src/catalog/catalog.d.ts.map +1 -0
  63. package/build/src/{catalog.js → catalog/catalog.js} +120 -14
  64. package/build/src/catalog/catalog.js.map +1 -0
  65. package/build/src/{catalog_cache.d.ts → catalog/catalog_cache.d.ts} +46 -22
  66. package/build/src/catalog/catalog_cache.d.ts.map +1 -0
  67. package/build/src/{catalog_cache.js → catalog/catalog_cache.js} +53 -43
  68. package/build/src/catalog/catalog_cache.js.map +1 -0
  69. package/build/src/define_config.d.ts +206 -3
  70. package/build/src/define_config.d.ts.map +1 -1
  71. package/build/src/define_config.js +11 -0
  72. package/build/src/define_config.js.map +1 -1
  73. package/build/src/drivers/database_driver.d.ts +128 -7
  74. package/build/src/drivers/database_driver.d.ts.map +1 -1
  75. package/build/src/drivers/database_driver.js +510 -24
  76. package/build/src/drivers/database_driver.js.map +1 -1
  77. package/build/src/drivers/database_relations_driver.d.ts +140 -0
  78. package/build/src/drivers/database_relations_driver.d.ts.map +1 -0
  79. package/build/src/drivers/database_relations_driver.js +748 -0
  80. package/build/src/drivers/database_relations_driver.js.map +1 -0
  81. package/build/src/drivers/openfga_driver.d.ts +777 -122
  82. package/build/src/drivers/openfga_driver.d.ts.map +1 -1
  83. package/build/src/drivers/openfga_driver.js +2228 -477
  84. package/build/src/drivers/openfga_driver.js.map +1 -1
  85. package/build/src/drivers/openfga_facts.d.ts +384 -0
  86. package/build/src/drivers/openfga_facts.d.ts.map +1 -0
  87. package/build/src/drivers/openfga_facts.js +836 -0
  88. package/build/src/drivers/openfga_facts.js.map +1 -0
  89. package/build/src/drivers/openfga_relations_driver.d.ts +186 -0
  90. package/build/src/drivers/openfga_relations_driver.d.ts.map +1 -0
  91. package/build/src/drivers/openfga_relations_driver.js +724 -0
  92. package/build/src/drivers/openfga_relations_driver.js.map +1 -0
  93. package/build/src/errors.d.ts +430 -6
  94. package/build/src/errors.d.ts.map +1 -1
  95. package/build/src/errors.js +453 -6
  96. package/build/src/errors.js.map +1 -1
  97. package/build/src/freeze.d.ts +200 -0
  98. package/build/src/freeze.d.ts.map +1 -0
  99. package/build/src/freeze.js +306 -0
  100. package/build/src/freeze.js.map +1 -0
  101. package/build/src/http/app_access_middleware.d.ts.map +1 -0
  102. package/build/src/http/app_access_middleware.js.map +1 -0
  103. package/build/src/http/resource_access_middleware.d.ts +105 -0
  104. package/build/src/http/resource_access_middleware.d.ts.map +1 -0
  105. package/build/src/http/resource_access_middleware.js +81 -0
  106. package/build/src/http/resource_access_middleware.js.map +1 -0
  107. package/build/src/identity.d.ts +74 -1
  108. package/build/src/identity.d.ts.map +1 -1
  109. package/build/src/identity.js +100 -2
  110. package/build/src/identity.js.map +1 -1
  111. package/build/src/manager.d.ts +549 -6
  112. package/build/src/manager.d.ts.map +1 -1
  113. package/build/src/manager.js +2243 -193
  114. package/build/src/manager.js.map +1 -1
  115. package/build/src/models/authz_assignment.d.ts +7 -7
  116. package/build/src/models/authz_assignment.d.ts.map +1 -1
  117. package/build/src/models/authz_deny.d.ts +7 -7
  118. package/build/src/models/authz_deny.d.ts.map +1 -1
  119. package/build/src/models/authz_permission.d.ts +7 -7
  120. package/build/src/models/authz_permission.d.ts.map +1 -1
  121. package/build/src/models/authz_role.d.ts +7 -7
  122. package/build/src/models/authz_role.d.ts.map +1 -1
  123. package/build/src/models/authz_role_permission.d.ts +7 -7
  124. package/build/src/models/authz_role_permission.d.ts.map +1 -1
  125. package/build/src/openfga.d.ts +18 -2
  126. package/build/src/openfga.d.ts.map +1 -1
  127. package/build/src/openfga.js +15 -1
  128. package/build/src/openfga.js.map +1 -1
  129. package/build/src/reconcile.d.ts +37 -0
  130. package/build/src/reconcile.d.ts.map +1 -0
  131. package/build/src/reconcile.js +69 -0
  132. package/build/src/reconcile.js.map +1 -0
  133. package/build/src/relation_partition_trigger.d.ts +8 -0
  134. package/build/src/relation_partition_trigger.d.ts.map +1 -0
  135. package/build/src/relation_partition_trigger.js +93 -0
  136. package/build/src/relation_partition_trigger.js.map +1 -0
  137. package/build/src/relations/define_relations_config.d.ts +109 -0
  138. package/build/src/relations/define_relations_config.d.ts.map +1 -0
  139. package/build/src/relations/define_relations_config.js +211 -0
  140. package/build/src/relations/define_relations_config.js.map +1 -0
  141. package/build/src/relations/manager.d.ts +138 -0
  142. package/build/src/relations/manager.d.ts.map +1 -0
  143. package/build/src/relations/manager.js +494 -0
  144. package/build/src/relations/manager.js.map +1 -0
  145. package/build/src/relations/reconcile.d.ts +137 -0
  146. package/build/src/relations/reconcile.d.ts.map +1 -0
  147. package/build/src/relations/reconcile.js +294 -0
  148. package/build/src/relations/reconcile.js.map +1 -0
  149. package/build/src/relations_config_store.d.ts +22 -0
  150. package/build/src/relations_config_store.d.ts.map +1 -0
  151. package/build/src/relations_config_store.js +74 -0
  152. package/build/src/relations_config_store.js.map +1 -0
  153. package/build/src/scope_outbox.d.ts +123 -0
  154. package/build/src/scope_outbox.d.ts.map +1 -0
  155. package/build/src/scope_outbox.js +532 -0
  156. package/build/src/scope_outbox.js.map +1 -0
  157. package/build/src/{drivers → shared}/backend_guard.d.ts +42 -0
  158. package/build/src/shared/backend_guard.d.ts.map +1 -0
  159. package/build/src/{drivers → shared}/backend_guard.js +78 -1
  160. package/build/src/shared/backend_guard.js.map +1 -0
  161. package/build/src/{drivers → shared}/sql_expiry.d.ts +2 -0
  162. package/build/src/shared/sql_expiry.d.ts.map +1 -0
  163. package/build/src/{drivers → shared}/sql_expiry.js +4 -0
  164. package/build/src/shared/sql_expiry.js.map +1 -0
  165. package/build/src/shared/transaction_guard.d.ts +53 -0
  166. package/build/src/shared/transaction_guard.d.ts.map +1 -0
  167. package/build/src/shared/transaction_guard.js +74 -0
  168. package/build/src/shared/transaction_guard.js.map +1 -0
  169. package/build/src/sql_descendants.d.ts +55 -1
  170. package/build/src/sql_descendants.d.ts.map +1 -1
  171. package/build/src/sql_descendants.js +75 -1
  172. package/build/src/sql_descendants.js.map +1 -1
  173. package/build/src/testing/contract.d.ts +129 -4
  174. package/build/src/testing/contract.d.ts.map +1 -1
  175. package/build/src/testing/contract.js +915 -177
  176. package/build/src/testing/contract.js.map +1 -1
  177. package/build/src/testing/main.d.ts +10 -2
  178. package/build/src/testing/main.d.ts.map +1 -1
  179. package/build/src/testing/main.js +5 -1
  180. package/build/src/testing/main.js.map +1 -1
  181. package/build/src/testing/migration_contract.d.ts +293 -0
  182. package/build/src/testing/migration_contract.d.ts.map +1 -0
  183. package/build/src/testing/migration_contract.js +589 -0
  184. package/build/src/testing/migration_contract.js.map +1 -0
  185. package/build/src/testing/relations_contract.d.ts +73 -0
  186. package/build/src/testing/relations_contract.d.ts.map +1 -0
  187. package/build/src/testing/relations_contract.js +1238 -0
  188. package/build/src/testing/relations_contract.js.map +1 -0
  189. package/build/src/testing/relations_reconcile_contract.d.ts +24 -0
  190. package/build/src/testing/relations_reconcile_contract.d.ts.map +1 -0
  191. package/build/src/testing/relations_reconcile_contract.js +220 -0
  192. package/build/src/testing/relations_reconcile_contract.js.map +1 -0
  193. package/build/src/testing/scope_outbox_contract.d.ts +98 -0
  194. package/build/src/testing/scope_outbox_contract.d.ts.map +1 -0
  195. package/build/src/testing/scope_outbox_contract.js +677 -0
  196. package/build/src/testing/scope_outbox_contract.js.map +1 -0
  197. package/build/src/traits/authz_scopes.js +1 -1
  198. package/build/src/traits/authz_scopes.js.map +1 -1
  199. package/build/src/traits/has_uuid.d.ts +8 -8
  200. package/build/src/traits/has_uuid.d.ts.map +1 -1
  201. package/build/src/types.d.ts +1537 -84
  202. package/build/src/types.d.ts.map +1 -1
  203. package/build/src/types.js +65 -0
  204. package/build/src/types.js.map +1 -1
  205. package/build/stubs/config/authorization.stub +149 -5
  206. package/build/stubs/migration.stub +136 -0
  207. package/build/stubs/scopes_outbox_migration.stub +57 -0
  208. package/package.json +4 -2
  209. package/build/commands/openfga_import.d.ts +0 -34
  210. package/build/commands/openfga_import.d.ts.map +0 -1
  211. package/build/commands/openfga_import.js +0 -97
  212. package/build/commands/openfga_import.js.map +0 -1
  213. package/build/src/catalog.d.ts.map +0 -1
  214. package/build/src/catalog.js.map +0 -1
  215. package/build/src/catalog_cache.d.ts.map +0 -1
  216. package/build/src/catalog_cache.js.map +0 -1
  217. package/build/src/drivers/backend_guard.d.ts.map +0 -1
  218. package/build/src/drivers/backend_guard.js.map +0 -1
  219. package/build/src/drivers/sql_expiry.d.ts.map +0 -1
  220. package/build/src/drivers/sql_expiry.js.map +0 -1
  221. package/build/src/middleware/app_access_middleware.d.ts.map +0 -1
  222. package/build/src/middleware/app_access_middleware.js.map +0 -1
  223. /package/build/src/{middleware → http}/app_access_middleware.d.ts +0 -0
  224. /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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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
+ {"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"}
@@ -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, openFgaAuthorizationModel, provisionOpenFgaStore, importAuthzFactsToOpenFga, assertHolderTypes, parseBindingId, correlateBatchResults, isDuplicateWrite, DEFAULT_TIMEOUT_MS, } from './drivers/openfga_driver.js';
12
- export type { HolderTypeMap, OpenFgaDriverOptions, ImportFactsOptions, ImportFactsResult, } from './drivers/openfga_driver.js';
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,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"openfga.d.ts","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,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"}
@@ -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, openFgaAuthorizationModel, provisionOpenFgaStore, importAuthzFactsToOpenFga, assertHolderTypes, parseBindingId, correlateBatchResults, isDuplicateWrite, DEFAULT_TIMEOUT_MS, } from './drivers/openfga_driver.js';
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
@@ -1 +1 @@
1
- {"version":3,"file":"openfga.js","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"openfga.js","sourceRoot":"","sources":["../../src/openfga.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,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"}