@jantstack/adonis-authz 2.5.0-alpha.3 → 2.5.0-rc.1

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 (277) hide show
  1. package/README.md +437 -48
  2. package/build/commands/authz_catalog_diff.d.ts +0 -1
  3. package/build/commands/authz_catalog_diff.js +0 -1
  4. package/build/commands/authz_catalog_prune_orphans.d.ts +17 -3
  5. package/build/commands/authz_catalog_prune_orphans.js +28 -6
  6. package/build/commands/authz_catalog_sync.d.ts +0 -1
  7. package/build/commands/authz_catalog_sync.js +0 -1
  8. package/build/commands/authz_freeze.d.ts +0 -1
  9. package/build/commands/authz_freeze.js +0 -1
  10. package/build/commands/authz_reconcile.d.ts +0 -1
  11. package/build/commands/authz_reconcile.js +0 -1
  12. package/build/commands/authz_relations_reconcile.d.ts +0 -1
  13. package/build/commands/authz_relations_reconcile.js +56 -8
  14. package/build/commands/authz_scopes_relay.d.ts +0 -1
  15. package/build/commands/authz_scopes_relay.js +54 -6
  16. package/build/commands/authz_scopes_requeue.d.ts +0 -1
  17. package/build/commands/authz_scopes_requeue.js +16 -3
  18. package/build/commands/authz_unfreeze.d.ts +0 -1
  19. package/build/commands/authz_unfreeze.js +0 -1
  20. package/build/commands/main.d.ts +0 -1
  21. package/build/commands/main.js +0 -1
  22. package/build/commands/openfga_provision.d.ts +10 -1
  23. package/build/commands/openfga_provision.js +43 -3
  24. package/build/configure.d.ts +0 -1
  25. package/build/configure.js +0 -1
  26. package/build/index.d.ts +9 -7
  27. package/build/index.js +10 -3
  28. package/build/providers/authz_provider.d.ts +0 -1
  29. package/build/providers/authz_provider.js +0 -1
  30. package/build/services/main.d.ts +0 -1
  31. package/build/services/main.js +0 -1
  32. package/build/services/relations.d.ts +0 -1
  33. package/build/services/relations.js +0 -1
  34. package/build/src/catalog/catalog.d.ts +0 -1
  35. package/build/src/catalog/catalog.js +0 -1
  36. package/build/src/catalog/catalog_cache.d.ts +13 -1
  37. package/build/src/catalog/catalog_cache.js +27 -2
  38. package/build/src/clock.d.ts +0 -1
  39. package/build/src/clock.js +0 -1
  40. package/build/src/define_config.d.ts +0 -1
  41. package/build/src/define_config.js +24 -1
  42. package/build/src/drivers/database_driver.d.ts +60 -3
  43. package/build/src/drivers/database_driver.js +160 -25
  44. package/build/src/drivers/database_relations_driver.d.ts +11 -5
  45. package/build/src/drivers/database_relations_driver.js +115 -33
  46. package/build/src/drivers/openfga_driver.d.ts +159 -26
  47. package/build/src/drivers/openfga_driver.js +882 -199
  48. package/build/src/drivers/openfga_facts.d.ts +91 -1
  49. package/build/src/drivers/openfga_facts.js +277 -3
  50. package/build/src/drivers/openfga_relations_driver.d.ts +41 -13
  51. package/build/src/drivers/openfga_relations_driver.js +422 -228
  52. package/build/src/errors.d.ts +160 -1
  53. package/build/src/errors.js +161 -1
  54. package/build/src/expiry.d.ts +51 -2
  55. package/build/src/expiry.js +96 -2
  56. package/build/src/freeze.d.ts +0 -1
  57. package/build/src/freeze.js +0 -1
  58. package/build/src/hierarchical_resolver.d.ts +0 -1
  59. package/build/src/hierarchical_resolver.js +0 -1
  60. package/build/src/http/app_access_middleware.d.ts +0 -1
  61. package/build/src/http/app_access_middleware.js +0 -1
  62. package/build/src/http/resource_access_middleware.d.ts +0 -1
  63. package/build/src/http/resource_access_middleware.js +0 -1
  64. package/build/src/identity.d.ts +9 -2
  65. package/build/src/identity.js +33 -1
  66. package/build/src/manager.d.ts +24 -1
  67. package/build/src/manager.js +381 -85
  68. package/build/src/memoize_ancestors.d.ts +0 -1
  69. package/build/src/memoize_ancestors.js +0 -1
  70. package/build/src/models/authz_assignment.d.ts +5 -6
  71. package/build/src/models/authz_assignment.js +0 -1
  72. package/build/src/models/authz_deny.d.ts +5 -6
  73. package/build/src/models/authz_deny.js +0 -1
  74. package/build/src/models/authz_permission.d.ts +5 -6
  75. package/build/src/models/authz_permission.js +0 -1
  76. package/build/src/models/authz_role.d.ts +5 -6
  77. package/build/src/models/authz_role.js +0 -1
  78. package/build/src/models/authz_role_permission.d.ts +5 -6
  79. package/build/src/models/authz_role_permission.js +0 -1
  80. package/build/src/openfga.d.ts +2 -3
  81. package/build/src/openfga.js +4 -2
  82. package/build/src/reconcile.d.ts +0 -1
  83. package/build/src/reconcile.js +0 -1
  84. package/build/src/relation_partition_trigger.d.ts +0 -1
  85. package/build/src/relation_partition_trigger.js +0 -1
  86. package/build/src/relations/check_many.d.ts +0 -1
  87. package/build/src/relations/check_many.js +0 -1
  88. package/build/src/relations/define_relations_config.d.ts +25 -3
  89. package/build/src/relations/define_relations_config.js +8 -3
  90. package/build/src/relations/deny_reach.d.ts +102 -0
  91. package/build/src/relations/deny_reach.js +230 -0
  92. package/build/src/relations/group_depth.d.ts +215 -0
  93. package/build/src/relations/group_depth.js +453 -0
  94. package/build/src/relations/manager.d.ts +14 -7
  95. package/build/src/relations/manager.js +60 -15
  96. package/build/src/relations/page.d.ts +19 -0
  97. package/build/src/relations/page.js +74 -0
  98. package/build/src/relations/reconcile.d.ts +58 -4
  99. package/build/src/relations/reconcile.js +266 -12
  100. package/build/src/relations/tuple_key.d.ts +0 -1
  101. package/build/src/relations/tuple_key.js +0 -1
  102. package/build/src/relations/tuple_order.d.ts +5 -4
  103. package/build/src/relations/tuple_order.js +5 -4
  104. package/build/src/relations_config_store.d.ts +57 -2
  105. package/build/src/relations_config_store.js +155 -5
  106. package/build/src/relations_reconcile.d.ts +0 -1
  107. package/build/src/relations_reconcile.js +0 -1
  108. package/build/src/scope_outbox.d.ts +36 -3
  109. package/build/src/scope_outbox.js +78 -18
  110. package/build/src/shared/backend_guard.d.ts +52 -1
  111. package/build/src/shared/backend_guard.js +164 -2
  112. package/build/src/shared/sql_expiry.d.ts +0 -1
  113. package/build/src/shared/sql_expiry.js +0 -1
  114. package/build/src/shared/transaction_guard.d.ts +0 -1
  115. package/build/src/shared/transaction_guard.js +0 -1
  116. package/build/src/sql_descendants.d.ts +0 -1
  117. package/build/src/sql_descendants.js +0 -1
  118. package/build/src/testing/contract.d.ts +26 -3
  119. package/build/src/testing/contract.js +258 -20
  120. package/build/src/testing/main.d.ts +0 -1
  121. package/build/src/testing/main.js +0 -1
  122. package/build/src/testing/migration_contract.d.ts +0 -1
  123. package/build/src/testing/migration_contract.js +0 -1
  124. package/build/src/testing/relations_contract.d.ts +7 -1
  125. package/build/src/testing/relations_contract.js +174 -7
  126. package/build/src/testing/relations_reconcile_contract.d.ts +0 -1
  127. package/build/src/testing/relations_reconcile_contract.js +0 -1
  128. package/build/src/testing/scope_outbox_contract.d.ts +0 -1
  129. package/build/src/testing/scope_outbox_contract.js +0 -1
  130. package/build/src/testing/scope_tree.d.ts +0 -1
  131. package/build/src/testing/scope_tree.js +0 -1
  132. package/build/src/testing/test_clock.d.ts +0 -1
  133. package/build/src/testing/test_clock.js +0 -1
  134. package/build/src/traits/authz_scopes.d.ts +0 -1
  135. package/build/src/traits/authz_scopes.js +0 -1
  136. package/build/src/traits/has_uuid.d.ts +5 -6
  137. package/build/src/traits/has_uuid.js +0 -1
  138. package/build/src/types.d.ts +138 -14
  139. package/build/src/types.js +6 -1
  140. package/build/stubs/config/authorization.stub +22 -6
  141. package/build/stubs/main.d.ts +0 -1
  142. package/build/stubs/main.js +0 -1
  143. package/package.json +4 -3
  144. package/build/commands/authz_catalog_diff.d.ts.map +0 -1
  145. package/build/commands/authz_catalog_diff.js.map +0 -1
  146. package/build/commands/authz_catalog_prune_orphans.d.ts.map +0 -1
  147. package/build/commands/authz_catalog_prune_orphans.js.map +0 -1
  148. package/build/commands/authz_catalog_sync.d.ts.map +0 -1
  149. package/build/commands/authz_catalog_sync.js.map +0 -1
  150. package/build/commands/authz_freeze.d.ts.map +0 -1
  151. package/build/commands/authz_freeze.js.map +0 -1
  152. package/build/commands/authz_reconcile.d.ts.map +0 -1
  153. package/build/commands/authz_reconcile.js.map +0 -1
  154. package/build/commands/authz_relations_reconcile.d.ts.map +0 -1
  155. package/build/commands/authz_relations_reconcile.js.map +0 -1
  156. package/build/commands/authz_scopes_relay.d.ts.map +0 -1
  157. package/build/commands/authz_scopes_relay.js.map +0 -1
  158. package/build/commands/authz_scopes_requeue.d.ts.map +0 -1
  159. package/build/commands/authz_scopes_requeue.js.map +0 -1
  160. package/build/commands/authz_unfreeze.d.ts.map +0 -1
  161. package/build/commands/authz_unfreeze.js.map +0 -1
  162. package/build/commands/main.d.ts.map +0 -1
  163. package/build/commands/main.js.map +0 -1
  164. package/build/commands/openfga_provision.d.ts.map +0 -1
  165. package/build/commands/openfga_provision.js.map +0 -1
  166. package/build/configure.d.ts.map +0 -1
  167. package/build/configure.js.map +0 -1
  168. package/build/index.d.ts.map +0 -1
  169. package/build/index.js.map +0 -1
  170. package/build/providers/authz_provider.d.ts.map +0 -1
  171. package/build/providers/authz_provider.js.map +0 -1
  172. package/build/services/main.d.ts.map +0 -1
  173. package/build/services/main.js.map +0 -1
  174. package/build/services/relations.d.ts.map +0 -1
  175. package/build/services/relations.js.map +0 -1
  176. package/build/src/catalog/catalog.d.ts.map +0 -1
  177. package/build/src/catalog/catalog.js.map +0 -1
  178. package/build/src/catalog/catalog_cache.d.ts.map +0 -1
  179. package/build/src/catalog/catalog_cache.js.map +0 -1
  180. package/build/src/clock.d.ts.map +0 -1
  181. package/build/src/clock.js.map +0 -1
  182. package/build/src/define_config.d.ts.map +0 -1
  183. package/build/src/define_config.js.map +0 -1
  184. package/build/src/drivers/database_driver.d.ts.map +0 -1
  185. package/build/src/drivers/database_driver.js.map +0 -1
  186. package/build/src/drivers/database_relations_driver.d.ts.map +0 -1
  187. package/build/src/drivers/database_relations_driver.js.map +0 -1
  188. package/build/src/drivers/openfga_driver.d.ts.map +0 -1
  189. package/build/src/drivers/openfga_driver.js.map +0 -1
  190. package/build/src/drivers/openfga_facts.d.ts.map +0 -1
  191. package/build/src/drivers/openfga_facts.js.map +0 -1
  192. package/build/src/drivers/openfga_relations_driver.d.ts.map +0 -1
  193. package/build/src/drivers/openfga_relations_driver.js.map +0 -1
  194. package/build/src/errors.d.ts.map +0 -1
  195. package/build/src/errors.js.map +0 -1
  196. package/build/src/expiry.d.ts.map +0 -1
  197. package/build/src/expiry.js.map +0 -1
  198. package/build/src/freeze.d.ts.map +0 -1
  199. package/build/src/freeze.js.map +0 -1
  200. package/build/src/hierarchical_resolver.d.ts.map +0 -1
  201. package/build/src/hierarchical_resolver.js.map +0 -1
  202. package/build/src/http/app_access_middleware.d.ts.map +0 -1
  203. package/build/src/http/app_access_middleware.js.map +0 -1
  204. package/build/src/http/resource_access_middleware.d.ts.map +0 -1
  205. package/build/src/http/resource_access_middleware.js.map +0 -1
  206. package/build/src/identity.d.ts.map +0 -1
  207. package/build/src/identity.js.map +0 -1
  208. package/build/src/manager.d.ts.map +0 -1
  209. package/build/src/manager.js.map +0 -1
  210. package/build/src/memoize_ancestors.d.ts.map +0 -1
  211. package/build/src/memoize_ancestors.js.map +0 -1
  212. package/build/src/models/authz_assignment.d.ts.map +0 -1
  213. package/build/src/models/authz_assignment.js.map +0 -1
  214. package/build/src/models/authz_deny.d.ts.map +0 -1
  215. package/build/src/models/authz_deny.js.map +0 -1
  216. package/build/src/models/authz_permission.d.ts.map +0 -1
  217. package/build/src/models/authz_permission.js.map +0 -1
  218. package/build/src/models/authz_role.d.ts.map +0 -1
  219. package/build/src/models/authz_role.js.map +0 -1
  220. package/build/src/models/authz_role_permission.d.ts.map +0 -1
  221. package/build/src/models/authz_role_permission.js.map +0 -1
  222. package/build/src/openfga.d.ts.map +0 -1
  223. package/build/src/openfga.js.map +0 -1
  224. package/build/src/reconcile.d.ts.map +0 -1
  225. package/build/src/reconcile.js.map +0 -1
  226. package/build/src/relation_partition_trigger.d.ts.map +0 -1
  227. package/build/src/relation_partition_trigger.js.map +0 -1
  228. package/build/src/relations/check_many.d.ts.map +0 -1
  229. package/build/src/relations/check_many.js.map +0 -1
  230. package/build/src/relations/define_relations_config.d.ts.map +0 -1
  231. package/build/src/relations/define_relations_config.js.map +0 -1
  232. package/build/src/relations/manager.d.ts.map +0 -1
  233. package/build/src/relations/manager.js.map +0 -1
  234. package/build/src/relations/reconcile.d.ts.map +0 -1
  235. package/build/src/relations/reconcile.js.map +0 -1
  236. package/build/src/relations/tuple_key.d.ts.map +0 -1
  237. package/build/src/relations/tuple_key.js.map +0 -1
  238. package/build/src/relations/tuple_order.d.ts.map +0 -1
  239. package/build/src/relations/tuple_order.js.map +0 -1
  240. package/build/src/relations_config_store.d.ts.map +0 -1
  241. package/build/src/relations_config_store.js.map +0 -1
  242. package/build/src/relations_reconcile.d.ts.map +0 -1
  243. package/build/src/relations_reconcile.js.map +0 -1
  244. package/build/src/scope_outbox.d.ts.map +0 -1
  245. package/build/src/scope_outbox.js.map +0 -1
  246. package/build/src/shared/backend_guard.d.ts.map +0 -1
  247. package/build/src/shared/backend_guard.js.map +0 -1
  248. package/build/src/shared/sql_expiry.d.ts.map +0 -1
  249. package/build/src/shared/sql_expiry.js.map +0 -1
  250. package/build/src/shared/transaction_guard.d.ts.map +0 -1
  251. package/build/src/shared/transaction_guard.js.map +0 -1
  252. package/build/src/sql_descendants.d.ts.map +0 -1
  253. package/build/src/sql_descendants.js.map +0 -1
  254. package/build/src/testing/contract.d.ts.map +0 -1
  255. package/build/src/testing/contract.js.map +0 -1
  256. package/build/src/testing/main.d.ts.map +0 -1
  257. package/build/src/testing/main.js.map +0 -1
  258. package/build/src/testing/migration_contract.d.ts.map +0 -1
  259. package/build/src/testing/migration_contract.js.map +0 -1
  260. package/build/src/testing/relations_contract.d.ts.map +0 -1
  261. package/build/src/testing/relations_contract.js.map +0 -1
  262. package/build/src/testing/relations_reconcile_contract.d.ts.map +0 -1
  263. package/build/src/testing/relations_reconcile_contract.js.map +0 -1
  264. package/build/src/testing/scope_outbox_contract.d.ts.map +0 -1
  265. package/build/src/testing/scope_outbox_contract.js.map +0 -1
  266. package/build/src/testing/scope_tree.d.ts.map +0 -1
  267. package/build/src/testing/scope_tree.js.map +0 -1
  268. package/build/src/testing/test_clock.d.ts.map +0 -1
  269. package/build/src/testing/test_clock.js.map +0 -1
  270. package/build/src/traits/authz_scopes.d.ts.map +0 -1
  271. package/build/src/traits/authz_scopes.js.map +0 -1
  272. package/build/src/traits/has_uuid.d.ts.map +0 -1
  273. package/build/src/traits/has_uuid.js.map +0 -1
  274. package/build/src/types.d.ts.map +0 -1
  275. package/build/src/types.js.map +0 -1
  276. package/build/stubs/main.d.ts.map +0 -1
  277. package/build/stubs/main.js.map +0 -1
package/build/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * import { AuthorizationManager, APP_SCOPE } from '@jantstack/adonis-authz'
4
4
  */
5
5
  export { AuthorizationManager, DEFAULT_MAX_SCOPES, DEFAULT_MAX_DESCENDANTS, MAX_SCOPE_BOUND, DEFAULT_VIEW_MAX_AGE_MS, PARKED_CENSUS_MAX, RELAY_ORIGIN_MAX_HOPS, RELAY_LEASE_POLL_MS, expandExcludedSubtrees } from './src/manager.js';
6
- export type { AuthorizationView, ForRequestOptions } from './src/manager.js';
6
+ export type { AuthorizationView, ForRequestOptions, MassPurgeReason } from './src/manager.js';
7
7
  export { defineConfig } from './src/define_config.js';
8
8
  export type { AuthorizationConfig } from './src/define_config.js';
9
9
  export { syncAuthzCatalog, diffAuthzCatalog, catalogInSync, formatCatalogDiff, formatScopedRoles, formatShadowedRoles, runCatalogDiff, syncCatalogs, } from './src/catalog/catalog.js';
@@ -50,7 +50,7 @@ export type { SqlScopeOutboxOptions } from './src/scope_outbox.js';
50
50
  * obligaría a importar ese SDK — acoplando el call-site al backend que este
51
51
  * paquete existe para abstraer.
52
52
  */
53
- export { AuthorizationBackendError, AuthorizationBackendTimeoutError, ScopeResolverError, InvalidIdentityError, InvalidSlugError, AuthorizationConfigError, AuthorizationInternalError, UnknownScopeError, NoScopeResolverError, UnknownRoleError, UnknownPermissionError, CatalogConflictError, RoleIsNotAccessError, ScopeCycleError, PurgeIncompleteError, WriteConflictError, RenewalUnsafeError, RenewalRacedError, ActorRequiredError, CheckManyBatchError, NotWithinError, WithinRequiredError, WithinRootForbiddenError, TooManyScopesError, TooManyLocalRolesError, MassPurgeRefusedError, PruneInterruptedError, UnsupportedDialectError, ScopeTooDeepError, ScopeDepthLimitError, ScopeRequeueRefusedError, UnsupportedOperationError, NoDescendantsResolverError, ViewExpiredError, RoleNotVisibleError, AmbiguousRoleError, RoleImmutableError, RoleLevelAboveOwnerError, RoleNotAssignableAtError, PermissionNotDelegableError, RankExceededError, ModelTooLargeError, RelationConfigError, RelationConfigUnknownKeyError, RelationTypeUnknownError, RelationUnknownError, RelationUsersetUnsupportedError, RelationNotDenyableError, RelationDenyExpiryError, MembersOfDenyLimitError, ScopeTreeDriftError, ScopeDriftUnguardedError, AuthorizationFrozenError, FreezeHeldError, MassReconcileRefusedError, DenyMigrationRefusedError, StaleSourceRefusedError, OperatorWindowExpiredError, ReconcileTooLargeError, markPartialWrite, isPartialWrite, } from './src/errors.js';
53
+ export { AuthorizationBackendError, AuthorizationBackendTimeoutError, ResolutionLimitError, ScopeResolverError, InvalidIdentityError, InvalidSlugError, AuthorizationConfigError, AuthorizationInternalError, UnknownScopeError, NoScopeResolverError, UnknownRoleError, UnknownPermissionError, CatalogConflictError, RoleIsNotAccessError, ScopeCycleError, PurgeIncompleteError, WriteConflictError, RenewalUnsafeError, RenewalRacedError, ActorRequiredError, CheckManyBatchError, NotWithinError, WithinRequiredError, WithinRootForbiddenError, TooManyScopesError, TooManyLocalRolesError, MassPurgeRefusedError, PruneInterruptedError, UnsupportedDialectError, ScopeTooDeepError, ScopeDepthLimitError, GroupDepthLimitError, ScopeRequeueRefusedError, UnsupportedOperationError, NoDescendantsResolverError, ViewExpiredError, RoleNotVisibleError, AmbiguousRoleError, RoleImmutableError, RoleLevelAboveOwnerError, RoleNotAssignableAtError, PermissionNotDelegableError, RankExceededError, ModelTooLargeError, RelationConfigError, RelationConfigUnknownKeyError, RelationTypeUnknownError, RelationUnknownError, RelationUsersetUnsupportedError, RelationNotDenyableError, RelationDenyExpiryError, MembersOfDenyLimitError, InvalidRelationPageError, ScopeTreeDriftError, ScopeDriftUnguardedError, AuthorizationFrozenError, FreezeHeldError, MassReconcileRefusedError, DenyMigrationRefusedError, DenyReachRefusedError, StaleSourceRefusedError, OperatorWindowExpiredError, ReconcileTooLargeError, markPartialWrite, isPartialWrite, } from './src/errors.js';
54
54
  /**
55
55
  * Validación de identidad y de slugs (422). La aplica el manager en cada
56
56
  * llamada y los drivers por defensa en profundidad; se exporta para que un
@@ -72,9 +72,12 @@ export type { RelationsManagerOptions } from './src/relations/manager.js';
72
72
  export { relationTupleKey, relationSubjectKey } from './src/relations/tuple_key.js';
73
73
  export type { RelationTupleKind, RelationTupleIdentity } from './src/relations/tuple_key.js';
74
74
  export { RELATIONS_CHECK_MANY_MAX } from './src/relations/check_many.js';
75
- export type { RelationsReconcileReport, RelationsReconcileDetail, RelationsPartitionRefusal } from './src/relations/reconcile.js';
76
- export { saveRelationsConfig, readRelationsConfig, readRelationsConfigSpec, } from './src/relations_config_store.js';
77
- export type { RelationsConfigStoreOptions } from './src/relations_config_store.js';
75
+ export { RELATIONS_ENUMERATE_DEFAULT_LIMIT, RELATIONS_ENUMERATE_MAX_LIMIT } from './src/relations/page.js';
76
+ export { RELATIONS_GROUP_DEPTH_MEASURED, GROUP_DEPTH_CONFIG_MAX, GROUP_DEPTH_MAX_NODES, GROUP_DEPTH_MAX_READS, GROUP_DEPTH_MAX_TUPLES, GROUP_DEPTH_DEADLINE_MS, GROUP_DEPTH_CALIBRATION_BACKOFF_MS, GROUP_DEPTH_RECALIBRATION_MIN_INTERVAL_MS, } from './src/relations/group_depth.js';
77
+ export type { RelationsReconcileReport, RelationsReconcileDetail, RelationsPartitionRefusal, RelationsPartitionRefusalReason } from './src/relations/reconcile.js';
78
+ export { saveRelationsConfig, readRelationsConfig, readRelationsConfigSpec, checkRelationsConfigDenyReach, } from './src/relations_config_store.js';
79
+ export type { RelationsConfigStoreOptions, SaveRelationsConfigOptions, RelationsConfigDenyReachCheck } from './src/relations_config_store.js';
80
+ export type { DenyReachFinding, DenyReachReason } from './src/relations/deny_reach.js';
78
81
  export { DatabaseRelationsDriver, RELATIONS_MEMBERS_DENY_CHECK_MAX } from './src/drivers/database_relations_driver.js';
79
82
  export type { DatabaseRelationsDriverOptions } from './src/drivers/database_relations_driver.js';
80
83
  export { resolveGrantExpiry, isActiveExpiry, sameInstant } from './src/expiry.js';
@@ -86,7 +89,7 @@ export type { DatabaseDriverOptions } from './src/drivers/database_driver.js';
86
89
  * opcional `@openfga/sdk`. Un consumidor solo-database arranca sin él (D9).
87
90
  */
88
91
  export { APP_SCOPE, APP_SCOPE_TYPE, DEFAULT_RECONCILE_MAX_TUPLES } from './src/types.js';
89
- export type { AuthorizationDriver, AuthorizationDriverFactory, AuthorizedScopes, AuthzWriteEvent, AuthzCatalogWriteEvent, CatalogPermissionSpec, CatalogRole, CatalogRoleSpec, CatalogSpec, ScopedRoleChanges, ScopedRoleSpec, DenyOptions, DenyRef, ExcludedSubtree, GrantOptions, GrantOutcome, HolderTypeMap, ReconcileCounts, ReconcileFact, ReconcileFactPage, ReconcileFactsEnumerator, ReconcileOptions, ReconcileReport, ReconcileSkip, ReconcileSource, RoleQuery, ScopeChainResolver, ScopeDescendantsResolver, ScopeEdge, ScopeEdgePage, ScopeEdgesEnumerator, ScopedWriteOptions, ScopeRef, ScopeType, SubjectRef, WriteOptions, AuthorizationDriverCapabilities, RelationsDriver, RelationsDriverCapabilities, RelObject, RelSubject, RelUserset, RelationRef, RelationWriteEvent, RelationWriteOptions, RelationDenyOptions, RelationDecision, RelationTransactionOptions, RelationPurgeOptions, RelationPage, RelationObjectsPage, RelationSubjectsPage, RelationTuple, RelationTuplePage, ScopeOutbox, ScopeOutboxContext, ScopeOutboxLease, ScopeOutboxPendingFilter, ScopeOutboxFailure, ScopeRequeueConflict, ScopeRequeueReport, ScopeTreeChange, PendingScopeTreeChange, RelayedScopeChange, ScopeRelayReport, ScopeRelayFailure, ScopeRelayEntry, ScopeRelayEntryStatus, ScopeEnqueueReceipt, } from './src/types.js';
92
+ export type { AuthorizationDriver, AuthorizationDriverFactory, AuthorizedScopes, AuthzWriteEvent, AuthzCatalogWriteEvent, CatalogPermissionSpec, CatalogRole, CatalogRoleSpec, CatalogSpec, ScopedRoleChanges, ScopedRoleSpec, DenyOptions, DenyRef, ExcludedSubtree, GrantOptions, GrantOutcome, HolderTypeMap, ReconcileCounts, ReconcileFact, ReconcileFactPage, ReconcileFactsEnumerator, ReconcileOptions, ReconcileReport, ReconcileSkip, ReconcileSource, RoleQuery, ScopeChainResolver, ScopeDescendantsResolver, ScopeEdge, ScopeEdgePage, ScopeEdgesEnumerator, ScopedWriteOptions, ScopeRef, ScopeType, SnapshotAnswer, SnapshotReads, SubjectRef, WriteOptions, AuthorizationDriverCapabilities, RelationsDriver, RelationsDriverCapabilities, RelObject, RelSubject, RelUserset, RelationRef, RelationWriteEvent, RelationWriteOptions, RelationDenyOptions, RelationDecision, RelationTransactionOptions, RelationPurgeOptions, RelationPage, RelationObjectsPage, RelationSubjectsPage, RelationTuple, RelationTuplePage, ScopeOutbox, ScopeOutboxContext, ScopeOutboxLease, ScopeOutboxPendingFilter, ScopeOutboxFailure, ScopeRequeueConflict, ScopeRequeueReport, ScopeTreeChange, PendingScopeTreeChange, RelayedScopeChange, ScopeRelayReport, ScopeRelayFailure, ScopeRelayEntry, ScopeRelayEntryStatus, ScopeEnqueueReceipt, } from './src/types.js';
90
93
  export { isRelUserset } from './src/types.js';
91
94
  /**
92
95
  * **¿De quién es esta transacción?** (L-1 · 🟠 9, regla del puerto `{trx}`):
@@ -106,4 +109,3 @@ export { default as AuthzAssignment } from './src/models/authz_assignment.js';
106
109
  export { default as AuthzDeny } from './src/models/authz_deny.js';
107
110
  export { withAuthzScopes } from './src/traits/authz_scopes.js';
108
111
  export { hasUuid } from './src/traits/has_uuid.js';
109
- //# sourceMappingURL=index.d.ts.map
package/build/index.js CHANGED
@@ -43,7 +43,7 @@ export { sqlScopeOutbox } from './src/scope_outbox.js';
43
43
  * obligaría a importar ese SDK — acoplando el call-site al backend que este
44
44
  * paquete existe para abstraer.
45
45
  */
46
- export { AuthorizationBackendError, AuthorizationBackendTimeoutError, ScopeResolverError, InvalidIdentityError, InvalidSlugError, AuthorizationConfigError, AuthorizationInternalError, UnknownScopeError, NoScopeResolverError, UnknownRoleError, UnknownPermissionError, CatalogConflictError, RoleIsNotAccessError, ScopeCycleError, PurgeIncompleteError, WriteConflictError, RenewalUnsafeError, RenewalRacedError, ActorRequiredError, CheckManyBatchError, NotWithinError, WithinRequiredError, WithinRootForbiddenError, TooManyScopesError, TooManyLocalRolesError, MassPurgeRefusedError, PruneInterruptedError, UnsupportedDialectError, ScopeTooDeepError, ScopeDepthLimitError, ScopeRequeueRefusedError, UnsupportedOperationError, NoDescendantsResolverError, ViewExpiredError, RoleNotVisibleError, AmbiguousRoleError, RoleImmutableError, RoleLevelAboveOwnerError, RoleNotAssignableAtError, PermissionNotDelegableError, RankExceededError, ModelTooLargeError, RelationConfigError, RelationConfigUnknownKeyError, RelationTypeUnknownError, RelationUnknownError, RelationUsersetUnsupportedError, RelationNotDenyableError, RelationDenyExpiryError, MembersOfDenyLimitError, ScopeTreeDriftError, ScopeDriftUnguardedError, AuthorizationFrozenError, FreezeHeldError, MassReconcileRefusedError, DenyMigrationRefusedError, StaleSourceRefusedError, OperatorWindowExpiredError, ReconcileTooLargeError,
46
+ export { AuthorizationBackendError, AuthorizationBackendTimeoutError, ResolutionLimitError, ScopeResolverError, InvalidIdentityError, InvalidSlugError, AuthorizationConfigError, AuthorizationInternalError, UnknownScopeError, NoScopeResolverError, UnknownRoleError, UnknownPermissionError, CatalogConflictError, RoleIsNotAccessError, ScopeCycleError, PurgeIncompleteError, WriteConflictError, RenewalUnsafeError, RenewalRacedError, ActorRequiredError, CheckManyBatchError, NotWithinError, WithinRequiredError, WithinRootForbiddenError, TooManyScopesError, TooManyLocalRolesError, MassPurgeRefusedError, PruneInterruptedError, UnsupportedDialectError, ScopeTooDeepError, ScopeDepthLimitError, GroupDepthLimitError, ScopeRequeueRefusedError, UnsupportedOperationError, NoDescendantsResolverError, ViewExpiredError, RoleNotVisibleError, AmbiguousRoleError, RoleImmutableError, RoleLevelAboveOwnerError, RoleNotAssignableAtError, PermissionNotDelegableError, RankExceededError, ModelTooLargeError, RelationConfigError, RelationConfigUnknownKeyError, RelationTypeUnknownError, RelationUnknownError, RelationUsersetUnsupportedError, RelationNotDenyableError, RelationDenyExpiryError, MembersOfDenyLimitError, InvalidRelationPageError, ScopeTreeDriftError, ScopeDriftUnguardedError, AuthorizationFrozenError, FreezeHeldError, MassReconcileRefusedError, DenyMigrationRefusedError, DenyReachRefusedError, StaleSourceRefusedError, OperatorWindowExpiredError, ReconcileTooLargeError,
47
47
  // Cierre de alpha.3 (invariante 13 en purgas multi-request): un driver de
48
48
  // relaciones de terceros marca con `markPartialWrite` el fallo que llega
49
49
  // DESPUÉS de haber borrado parte; el manager notifica `indeterminate: true`.
@@ -66,10 +66,18 @@ export { RelationsManager } from './src/relations/manager.js';
66
66
  // Plan 2.5 · lote A: la clave PURA de una tupla (P3, con `kind` desde el primer día) y el tope de `checkMany` (P4).
67
67
  export { relationTupleKey, relationSubjectKey } from './src/relations/tuple_key.js';
68
68
  export { RELATIONS_CHECK_MANY_MAX } from './src/relations/check_many.js';
69
+ // Lote «antes de RC» · 7.4: la página de `enumerate*` (default y techo; por encima se recorta con cursor).
70
+ export { RELATIONS_ENUMERATE_DEFAULT_LIMIT, RELATIONS_ENUMERATE_MAX_LIMIT } from './src/relations/page.js';
71
+ // Lote «antes de RC» · R1: las cotas de la anidación de grupos (la fila de «Limits»); la regla vive en los drivers.
72
+ export { RELATIONS_GROUP_DEPTH_MEASURED, GROUP_DEPTH_CONFIG_MAX, GROUP_DEPTH_MAX_NODES,
73
+ // Cierre de R1 (🟠 1 del auditor): el presupuesto de la comprobación de una arista en openfga.
74
+ GROUP_DEPTH_MAX_READS, GROUP_DEPTH_MAX_TUPLES, GROUP_DEPTH_DEADLINE_MS,
75
+ // Cierre-2 de R1 (D5): la espera tras una calibración fallida y la cota de la re-calibración tras un 503 de profundidad.
76
+ GROUP_DEPTH_CALIBRATION_BACKOFF_MS, GROUP_DEPTH_RECALIBRATION_MIN_INTERVAL_MS, } from './src/relations/group_depth.js';
69
77
  // La config de relaciones PERSISTIDA (🟡3): API de PLATAFORMA (bajo el gate de
70
78
  // versión, invariante 14). La CONSUME `authz:relations:reconcile` (config del
71
79
  // destino, para la deriva del modelo fusionado en --dry-run).
72
- export { saveRelationsConfig, readRelationsConfig, readRelationsConfigSpec, } from './src/relations_config_store.js';
80
+ export { saveRelationsConfig, readRelationsConfig, readRelationsConfigSpec, checkRelationsConfigDenyReach, } from './src/relations_config_store.js';
73
81
  // El driver `database` de relaciones (el consumidor lo cablea en
74
82
  // `relations.drivers` de config/authorization.ts). El driver `openfga` de
75
83
  // relaciones NO sale de aquí: vive en el subpath `/openfga` (peer opcional).
@@ -100,4 +108,3 @@ export { default as AuthzAssignment } from './src/models/authz_assignment.js';
100
108
  export { default as AuthzDeny } from './src/models/authz_deny.js';
101
109
  export { withAuthzScopes } from './src/traits/authz_scopes.js';
102
110
  export { hasUuid } from './src/traits/has_uuid.js';
103
- //# sourceMappingURL=index.js.map
@@ -43,4 +43,3 @@ export default class AuthzProvider {
43
43
  constructor(app: ApplicationService);
44
44
  register(): void;
45
45
  }
46
- //# sourceMappingURL=authz_provider.d.ts.map
@@ -84,4 +84,3 @@ export default class AuthzProvider {
84
84
  });
85
85
  }
86
86
  }
87
- //# sourceMappingURL=authz_provider.js.map
@@ -7,4 +7,3 @@ import type { AuthorizationManager } from '../src/manager.js';
7
7
  */
8
8
  declare let authorization: AuthorizationManager;
9
9
  export { authorization as default };
10
- //# sourceMappingURL=main.d.ts.map
@@ -10,4 +10,3 @@ await app.booted(async () => {
10
10
  authorization = await app.container.make('authz.manager');
11
11
  });
12
12
  export { authorization as default };
13
- //# sourceMappingURL=main.js.map
@@ -11,4 +11,3 @@ import type { RelationsManager } from '../src/relations/manager.js';
11
11
  */
12
12
  declare let relations: RelationsManager;
13
13
  export { relations as default };
14
- //# sourceMappingURL=relations.d.ts.map
@@ -14,4 +14,3 @@ await app.booted(async () => {
14
14
  relations = await app.container.make('authz.relations');
15
15
  });
16
16
  export { relations as default };
17
- //# sourceMappingURL=relations.js.map
@@ -286,4 +286,3 @@ export declare function runCatalogDiff(catalogs: CatalogSource[], options?: {
286
286
  export declare function syncCatalogs(catalogs: CatalogSource[], options?: SyncCatalogOptions): Promise<{
287
287
  count: number;
288
288
  } & CatalogSyncReport>;
289
- //# sourceMappingURL=catalog.d.ts.map
@@ -856,4 +856,3 @@ export async function syncCatalogs(catalogs, options = {}) {
856
856
  }
857
857
  return { count, shadowedByGlobal, assignableAtViolations };
858
858
  }
859
- //# sourceMappingURL=catalog.js.map
@@ -304,6 +304,19 @@ export declare class CatalogCache {
304
304
  * vuelve a intentarlo.
305
305
  */
306
306
  view(): Promise<CatalogView>;
307
+ /**
308
+ * **La foto para una ESCRITURA** (lote C · carreras, resolución 2 del juez = K4): contrasta la versión con la fila
309
+ * SIEMPRE, ignore o no la ventana `{ everyMs }`. Con `'always'` es exactamente `view()`. La ventana es para DECIDIR
310
+ * (invariante 14: una pregunta puede responder con un catálogo de hasta `everyMs` de antigüedad); una escritura del driver
311
+ * deja ESTADO en el store que no caduca —el barrido de `moved`, el settle, la proyección—, y con un memo rancio un rol
312
+ * recién definido en otro proceso no se barre (fail-open persistente medido, K4). Coste: el SELECT por PK de `'always'`.
313
+ *
314
+ * **Nunca se suma a una comprobación ni a una carga EN VUELO** (asentar · cierre 2, ⚪ 6 / O-6 del auditor): la que ya
315
+ * estaba en marcha pudo leer la fila ANTES de la escritura que precede a esta llamada (la propia, o la de otro proceso
316
+ * que la escritura acaba de observar) y serviría esa foto. Se espera la carga en vuelo y se lee la versión otra vez;
317
+ * una carga que arranca DESPUÉS de esta llamada sí se comparte (ya es posterior).
318
+ */
319
+ freshView(): Promise<CatalogView>;
307
320
  /**
308
321
  * Olvida la foto de ESTE memo. La siguiente pregunta recarga. Es un bump
309
322
  * de generación, no un `#view = null`: una carga en vuelo capturó la
@@ -321,4 +334,3 @@ export declare class CatalogCache {
321
334
  * disfrazado de dato.
322
335
  */
323
336
  export declare function parseAssignableAt(slug: string, raw: unknown): readonly ScopeType[] | null;
324
- //# sourceMappingURL=catalog_cache.d.ts.map
@@ -240,7 +240,8 @@ export async function readLocalRoles(options = {}) {
240
240
  .select('uuid', 'slug', 'scope_type', 'rank', 'owner_scope_key'));
241
241
  if (rows.length > maxLocalRoles) {
242
242
  throw new TooManyLocalRolesError(`El catálogo tiene más de ${maxLocalRoles} roles locales (cota 'maxLocalRoles'). No se devuelve una lista ` +
243
- `parcial: quien lee esto decide qué se BORRA. Sube la cota a sabiendas si tu catálogo local es así de grande.`);
243
+ `parcial: quien lee esto decide qué se BORRA. Sube la cota a sabiendas si tu catálogo local es así de grande: ` +
244
+ `pruneOrphanRoles({ maxLocalRoles }) o --max-local-roles en authz:catalog:prune-orphans.`);
244
245
  }
245
246
  if (rows.length === 0)
246
247
  return [];
@@ -420,6 +421,31 @@ export class CatalogCache {
420
421
  }
421
422
  return this.#reload();
422
423
  }
424
+ /**
425
+ * **La foto para una ESCRITURA** (lote C · carreras, resolución 2 del juez = K4): contrasta la versión con la fila
426
+ * SIEMPRE, ignore o no la ventana `{ everyMs }`. Con `'always'` es exactamente `view()`. La ventana es para DECIDIR
427
+ * (invariante 14: una pregunta puede responder con un catálogo de hasta `everyMs` de antigüedad); una escritura del driver
428
+ * deja ESTADO en el store que no caduca —el barrido de `moved`, el settle, la proyección—, y con un memo rancio un rol
429
+ * recién definido en otro proceso no se barre (fail-open persistente medido, K4). Coste: el SELECT por PK de `'always'`.
430
+ *
431
+ * **Nunca se suma a una comprobación ni a una carga EN VUELO** (asentar · cierre 2, ⚪ 6 / O-6 del auditor): la que ya
432
+ * estaba en marcha pudo leer la fila ANTES de la escritura que precede a esta llamada (la propia, o la de otro proceso
433
+ * que la escritura acaba de observar) y serviría esa foto. Se espera la carga en vuelo y se lee la versión otra vez;
434
+ * una carga que arranca DESPUÉS de esta llamada sí se comparte (ya es posterior).
435
+ */
436
+ async freshView() {
437
+ if (this.#loading)
438
+ await this.#loading.catch(() => undefined);
439
+ const current = this.#view;
440
+ if (!current || !this.#isFresh())
441
+ return this.#reload();
442
+ const dbVersion = await this.#readVersion();
443
+ if (this.#view === current && this.#isFresh() && dbVersion === current.version) {
444
+ this.#checkedAt = this.#now();
445
+ return current;
446
+ }
447
+ return this.#reload(dbVersion);
448
+ }
423
449
  /** Una carga compartida; `knownVersion` es la fila recién leída por una revalidación (se ahorra releerla). */
424
450
  #reload(knownVersion) {
425
451
  if (!this.#loading) {
@@ -663,4 +689,3 @@ function buildCatalogView(permissions, roles, links, loadedAt, version) {
663
689
  version,
664
690
  };
665
691
  }
666
- //# sourceMappingURL=catalog_cache.js.map
@@ -21,4 +21,3 @@ export type Clock = () => Date;
21
21
  export declare const systemClock: Clock;
22
22
  /** `now` tiene que ser una función; se valida al construir (500 `E_AUTHZ_CONFIG` es del llamante). */
23
23
  export declare function isClock(value: unknown): value is Clock;
24
- //# sourceMappingURL=clock.d.ts.map
@@ -4,4 +4,3 @@ export const systemClock = () => new Date();
4
4
  export function isClock(value) {
5
5
  return typeof value === 'function';
6
6
  }
7
- //# sourceMappingURL=clock.js.map
@@ -381,4 +381,3 @@ export declare function defineConfig<T extends AuthorizationConfig>(config: T):
381
381
  * barata (claves, no valores).
382
382
  */
383
383
  export declare function assertAuthorizationConfigShape(config: unknown): void;
384
- //# sourceMappingURL=define_config.d.ts.map
@@ -77,12 +77,36 @@ function assertConfigBlock(value, path) {
77
77
  `una clave conocida no es «nada»: se ignoraría en silencio (plan 2.5 · B2).`);
78
78
  }
79
79
  }
80
+ /**
81
+ * **Lápidas: claves que NO existen aquí pero que la letra de una decisión firmada nombra así** (cierre-2 de R1 · D1 (a),
82
+ * decisión del dueño 2026-10-20: «`relations.maxGroupDepth` ⇒ 500 con mensaje que apunta a `defineRelationsConfig`»).
83
+ * La decisión (5) escribió `relations.maxGroupDepth`; el mando vive en `defineRelationsConfig` (la config que capturan
84
+ * las factories de los drivers, `manager.driver()` y `runRelationsReconcile`) y se lee como `relations.config.maxGroupDepth`.
85
+ * Sin alias (una clave hermana se validaría y no gobernaría tres de las cuatro rutas): la ruta literal es el MISMO 500
86
+ * de clave desconocida, con la receta del sitio bueno en vez de la lista de claves.
87
+ */
88
+ const MISPLACED_CONFIG_KEYS = Object.freeze({
89
+ 'relations.maxGroupDepth': "defineConfig: la clave 'relations.maxGroupDepth' no existe. El techo de anidación de grupos va en la config de " +
90
+ 'RELACIONES: defineRelationsConfig({ objectTypes, maxGroupDepth, database: { enforceGroupDepth } }), y ese objeto en ' +
91
+ 'relations.config. Es la config que capturan los drivers (las factories de relations.drivers), manager.driver() y ' +
92
+ 'runRelationsReconcile (authz:relations:reconcile): una clave hermana de relations no llegaría a ninguno y el límite ' +
93
+ 'no se aplicaría.',
94
+ 'relations.enforceGroupDepth': "defineConfig: la clave 'relations.enforceGroupDepth' no existe. El opt-in del techo de anidación de grupos en " +
95
+ 'database va en la config de RELACIONES: defineRelationsConfig({ objectTypes, maxGroupDepth, database: { ' +
96
+ 'enforceGroupDepth: true } }), y ese objeto en relations.config (la que capturan los drivers).',
97
+ });
80
98
  function assertKnownConfigKeys(value, known, path) {
81
99
  if (!value || typeof value !== 'object' || Array.isArray(value))
82
100
  return;
83
101
  for (const key of Object.keys(value)) {
84
102
  if (known.includes(key))
85
103
  continue;
104
+ // Cierre-3 · R-6: `Object.hasOwn` — una clave `constructor`/`toString` (o un `__proto__` propio de un JSON) leía el
105
+ // prototipo de la tabla y el 500 llevaba de mensaje `function Object() { [native code] }`.
106
+ const dotted = path === '' ? key : `${path}.${key}`;
107
+ const tombstone = Object.hasOwn(MISPLACED_CONFIG_KEYS, dotted) ? MISPLACED_CONFIG_KEYS[dotted] : undefined;
108
+ if (tombstone !== undefined)
109
+ throw new AuthorizationConfigError(tombstone);
86
110
  const where = path === '' ? `'${key}' en la raíz` : `'${path}.${key}'`;
87
111
  throw new AuthorizationConfigError(`defineConfig: la clave ${where} no existe (claves válidas en ${path === '' ? 'la raíz' : path}: ${known.join(', ')}). ` +
88
112
  `Ninguna clave del config se descarta en silencio (plan 2.5 · B2): un typo ('requireWithing') sería una ` +
@@ -121,4 +145,3 @@ export function assertAuthorizationConfigShape(config) {
121
145
  assertKnownConfigKeys(c[block], AUTHORIZATION_CONFIG_KEYS[block], block);
122
146
  }
123
147
  }
124
- //# sourceMappingURL=define_config.js.map
@@ -1,5 +1,5 @@
1
1
  import db from '@adonisjs/lucid/services/db';
2
- import type { AuthorizationDriver, AuthorizationDriverCapabilities, CatalogRoleRef, DenyRef, GrantOptions, GrantOutcome, NormalizedRoleQuery, ReconcileOptions, ReconcileReport, ReconcileSource, RoleQuery, ScopeRef, ScopeType, SubjectRef, WriteOptions } from '../types.js';
2
+ import type { AuthorizationDriver, AuthorizationDriverCapabilities, CatalogRoleRef, DenyRef, GrantOptions, GrantOutcome, NormalizedRoleQuery, ReconcileOptions, ReconcileReport, ReconcileSource, RoleQuery, ScopeRef, ScopeType, SnapshotAnswer, SnapshotReads, SubjectRef, WriteOptions } from '../types.js';
3
3
  import type { ScopeChainResolver } from '../types.js';
4
4
  import { CatalogCache } from '../catalog/catalog_cache.js';
5
5
  import type { CatalogRevalidate, CatalogRole, CatalogView } from '../catalog/catalog_cache.js';
@@ -168,7 +168,7 @@ export declare class DatabaseAuthorizationDriver implements AuthorizationDriver
168
168
  /**
169
169
  * Lo que este driver declara (3b-2e · E2). El árbol es del consumidor
170
170
  * (`resolveChain`), así que no hay hechos de jerarquía ni deriva que
171
- * mitigar; `authorize` son varias consultas SQL; la membresía la resuelve
171
+ * mitigar; `authorize` es UNA consulta SQL de hechos (la foto, rotación 2 · cierre 3) más el catálogo y el árbol, no un `Check`; la membresía la resuelve
172
172
  * el propio SQL contra la cadena que le pasan; los `list*` no enumeran
173
173
  * herencia (invariante 7); y `purgeRole` está implementado en una
174
174
  * transacción.
@@ -204,6 +204,12 @@ export declare class DatabaseAuthorizationDriver implements AuthorizationDriver
204
204
  */
205
205
  readonly catalog: CatalogCache;
206
206
  constructor(options?: DatabaseDriverOptions);
207
+ /**
208
+ * **El catálogo de una ESCRITURA** (K4; asentar · cierre 2, D-1): con la versión contrastada en fresco SIEMPRE
209
+ * (`CatalogCache.freshView`), ignore o no la ventana `{ everyMs }`. Un `catalog` inyectado que no lo traiga cae en
210
+ * `view()` (el contrato del memo es suyo). Gemelo de `OpenFgaAuthorizationDriver.writeCatalog`.
211
+ */
212
+ private writeCatalog;
207
213
  /**
208
214
  * Vista de este driver con OTRO resolutor de la cadena y el mismo estado
209
215
  * (conexión, memo del catálogo, deadline). Es lo que usa
@@ -242,6 +248,33 @@ export declare class DatabaseAuthorizationDriver implements AuthorizationDriver
242
248
  */
243
249
  private sql;
244
250
  private first;
251
+ /**
252
+ * **La FOTO de una decisión: el punto de paso ÚNICO** (rotación 2 · cierre 3; 4.ª aparición del linaje L12 «lector
253
+ * rasgado», la primera en `database`). Propiedad universal: *toda DECISIÓN de `database` que combina concesión y deny
254
+ * se lee en UNA foto*. Hasta aquí `authorize` leía los denies y las asignaciones en DOS sentencias, y una escritura
255
+ * que caía entre las dos daba una respuesta que NINGÚN estado real daba (un `deny` y después un `grant` ⇒ `true` una
256
+ * vez; repro `.claude/reproducciones/database-authorize-rasgado.spec.ts`).
257
+ *
258
+ * La foto es **UNA sentencia**: las partes van unidas con `UNION ALL` y cada fila dice de qué parte es
259
+ * (`foto_kind`). Una sentencia ve UN estado en los tres motores y en cualquier aislamiento —PostgreSQL toma la foto
260
+ * por SENTENCIA en READ COMMITTED, InnoDB una vista de lectura por sentencia, SQLite una transacción de lectura
261
+ * implícita—, así que no hace falta abrir una transacción REPEATABLE READ como `withSourceSnapshot` del reconcile:
262
+ * eso costaría BEGIN/COMMIT por pregunta en el camino caliente y, con un pool de 1 (`:memory:`), retendría la única
263
+ * conexión mientras el catálogo o un `resolveChain` SQL del consumidor esperan otra. Elegido por eso: una ida y
264
+ * vuelta (antes dos), sin conexión retenida y sin nivel por motor.
265
+ *
266
+ * Lo que va DENTRO de la foto: los HECHOS (asignaciones —con el vínculo rol→permiso por `JOIN` cuando la parte lo
267
+ * filtra— y denies). Lo que va FUERA, antes o después: el catálogo (memo contrastado con la versión compartida,
268
+ * invariante 14) y la cadena del consumidor (`resolveChain`). «Cadena frente a hechos» (un `scopes.moved` entre el
269
+ * `resolveChain` y la foto) depende del resolutor del consumidor y está DECLARADO en README «Limits» (fila «Torn
270
+ * read»), no se arregla aquí.
271
+ *
272
+ * Columnas comunes de cada parte: `foto_kind`, `foto_scope_type`, `foto_scope_uuid`, `foto_role` y
273
+ * `foto_permission` (`null` en la parte que no la tiene). Solo SQL estándar del query builder (M6). Una sola parte
274
+ * es una sola `SELECT`, sin `UNION`. La guardia `database.decision.snapshot` cuenta las sentencias que tocan
275
+ * `authz_assignments`/`authz_denies` por decisión: con dos, rojo.
276
+ */
277
+ private readFoto;
245
278
  /**
246
279
  * Por dónde escribe `operation` (L-3): la transacción ABIERTA del llamante
247
280
  * si llegó en `options.transaction` —validada contra la conexión de este
@@ -310,16 +343,41 @@ export declare class DatabaseAuthorizationDriver implements AuthorizationDriver
310
343
  scope: ScopeRef;
311
344
  role: CatalogRoleRef;
312
345
  }>>;
346
+ /** La parte de la foto de `rolesInChain`: asignaciones vigentes del holder en los scopes de la cadena (`null` sin cadena). */
347
+ private rolesInChainPart;
348
+ /** De las filas de la foto a la respuesta de `rolesInChain` (catálogo DESPUÉS de la foto: es memo, no hechos). */
349
+ private rolesInChainFrom;
313
350
  listRoleScopes(subject: SubjectRef, scopeType: ScopeType): Promise<ScopeRef[]>;
314
351
  /** ¿El rol (por uuid) existe en el scope cuya cadena tiene esas claves? (3B · B2, `declaredRoleAt`) */
315
352
  private visibleAt;
316
353
  listScopes(subject: SubjectRef, permission: string): Promise<ScopeRef[]>;
354
+ /** La parte «asignaciones vigentes del holder cuyo rol concede el permiso», en todo scope (la de `listScopes`). */
355
+ private grantsOfPart;
356
+ /** La parte «denies del holder» (de UN permiso si se da; si no, todos), en todo scope. */
357
+ private deniesPart;
358
+ /**
359
+ * De la foto a la respuesta de `listScopes` (árbol y catálogo DESPUÉS de la foto). `denies` son los del permiso: por
360
+ * scope, el conjunto de roles que conceden; el scope se lista si el árbol lo conoce, alguno de esos roles existe ahí
361
+ * (3B · B2) y ningún deny de la cadena lo bloquea — exactamente lo que `authorize` diría.
362
+ */
363
+ private listScopesFrom;
317
364
  /**
318
365
  * Denies directos del holder (2.1, B5): del scope exacto o todos. Solo los
319
366
  * de permisos que el catálogo declara (memo); los de scopes que el árbol
320
367
  * no conoce no se listan (D8), como en `listRoleScopes`.
321
368
  */
322
369
  listDenies(subject: SubjectRef, scope?: ScopeRef): Promise<DenyRef[]>;
370
+ /** De las filas de denies a `DenyRef[]` (catálogo y, sin `scope` pedido, árbol DESPUÉS de la foto). */
371
+ private deniesFrom;
372
+ /**
373
+ * **Varias lecturas del puerto en UNA foto** (rotación 2 · cierre 3, L12; método OPCIONAL del puerto,
374
+ * `AuthorizationDriver.readSnapshot`, capacidad `snapshotDecisions`). Es lo que el manager usa para las decisiones
375
+ * que COMPONE con dos métodos del puerto —`effectivePermissions` y la policy de delegación (`rolesInChain` +
376
+ * `listDenies`), `authorizedScopes` (`listScopes` + `listDenies`)—: cada respuesta pedida es EXACTAMENTE la del método
377
+ * homónimo, y todas salen de la MISMA foto de los hechos (`readFoto`: una sentencia). Lo no pedido no viene.
378
+ * Árbol y catálogo se leen después de la foto, como en cada método suelto.
379
+ */
380
+ readSnapshot(subject: SubjectRef, reads: SnapshotReads): Promise<SnapshotAnswer>;
323
381
  /**
324
382
  * Borra asignaciones y denies del scope exacto, en una transacción. Si el
325
383
  * árbol aún lo conoce se purga su identidad canónica (K1); si ya no (el
@@ -393,4 +451,3 @@ export declare class DatabaseAuthorizationDriver implements AuthorizationDriver
393
451
  */
394
452
  private eachReconcileRow;
395
453
  }
396
- //# sourceMappingURL=database_driver.d.ts.map