@jantstack/adonis-authz 2.5.0-alpha.2 → 2.5.0-alpha.4

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 (275) hide show
  1. package/README.md +743 -28
  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 +0 -1
  5. package/build/commands/authz_catalog_prune_orphans.js +0 -1
  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 +6 -1
  13. package/build/commands/authz_relations_reconcile.js +163 -5
  14. package/build/commands/authz_scopes_relay.d.ts +0 -1
  15. package/build/commands/authz_scopes_relay.js +49 -5
  16. package/build/commands/authz_scopes_requeue.d.ts +0 -1
  17. package/build/commands/authz_scopes_requeue.js +14 -2
  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 +72 -1
  23. package/build/commands/openfga_provision.js +236 -4
  24. package/build/configure.d.ts +0 -1
  25. package/build/configure.js +0 -1
  26. package/build/index.d.ts +11 -9
  27. package/build/index.js +12 -5
  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 +25 -1
  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 +6 -1
  43. package/build/src/drivers/database_driver.js +22 -2
  44. package/build/src/drivers/database_relations_driver.d.ts +46 -5
  45. package/build/src/drivers/database_relations_driver.js +297 -59
  46. package/build/src/drivers/openfga_driver.d.ts +159 -26
  47. package/build/src/drivers/openfga_driver.js +980 -231
  48. package/build/src/drivers/openfga_facts.d.ts +112 -1
  49. package/build/src/drivers/openfga_facts.js +351 -11
  50. package/build/src/drivers/openfga_relations_driver.d.ts +109 -8
  51. package/build/src/drivers/openfga_relations_driver.js +817 -53
  52. package/build/src/errors.d.ts +233 -1
  53. package/build/src/errors.js +283 -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 +2 -1
  65. package/build/src/identity.js +4 -1
  66. package/build/src/manager.d.ts +0 -1
  67. package/build/src/manager.js +164 -31
  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 +3 -4
  81. package/build/src/openfga.js +5 -3
  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 +1 -2
  87. package/build/src/relations/check_many.js +6 -5
  88. package/build/src/relations/define_relations_config.d.ts +140 -5
  89. package/build/src/relations/define_relations_config.js +205 -6
  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 +46 -8
  95. package/build/src/relations/manager.js +178 -16
  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 +274 -2
  99. package/build/src/relations/reconcile.js +1006 -162
  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 +127 -0
  103. package/build/src/relations/tuple_order.js +599 -0
  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 +0 -1
  109. package/build/src/scope_outbox.js +0 -1
  110. package/build/src/shared/backend_guard.d.ts +60 -1
  111. package/build/src/shared/backend_guard.js +179 -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 +7 -1
  119. package/build/src/testing/contract.js +77 -1
  120. package/build/src/testing/main.d.ts +1 -2
  121. package/build/src/testing/main.js +1 -2
  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 +25 -1
  125. package/build/src/testing/relations_contract.js +996 -49
  126. package/build/src/testing/relations_reconcile_contract.d.ts +9 -1
  127. package/build/src/testing/relations_reconcile_contract.js +207 -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 +170 -15
  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_config_store.d.ts.map +0 -1
  239. package/build/src/relations_config_store.js.map +0 -1
  240. package/build/src/relations_reconcile.d.ts.map +0 -1
  241. package/build/src/relations_reconcile.js.map +0 -1
  242. package/build/src/scope_outbox.d.ts.map +0 -1
  243. package/build/src/scope_outbox.js.map +0 -1
  244. package/build/src/shared/backend_guard.d.ts.map +0 -1
  245. package/build/src/shared/backend_guard.js.map +0 -1
  246. package/build/src/shared/sql_expiry.d.ts.map +0 -1
  247. package/build/src/shared/sql_expiry.js.map +0 -1
  248. package/build/src/shared/transaction_guard.d.ts.map +0 -1
  249. package/build/src/shared/transaction_guard.js.map +0 -1
  250. package/build/src/sql_descendants.d.ts.map +0 -1
  251. package/build/src/sql_descendants.js.map +0 -1
  252. package/build/src/testing/contract.d.ts.map +0 -1
  253. package/build/src/testing/contract.js.map +0 -1
  254. package/build/src/testing/main.d.ts.map +0 -1
  255. package/build/src/testing/main.js.map +0 -1
  256. package/build/src/testing/migration_contract.d.ts.map +0 -1
  257. package/build/src/testing/migration_contract.js.map +0 -1
  258. package/build/src/testing/relations_contract.d.ts.map +0 -1
  259. package/build/src/testing/relations_contract.js.map +0 -1
  260. package/build/src/testing/relations_reconcile_contract.d.ts.map +0 -1
  261. package/build/src/testing/relations_reconcile_contract.js.map +0 -1
  262. package/build/src/testing/scope_outbox_contract.d.ts.map +0 -1
  263. package/build/src/testing/scope_outbox_contract.js.map +0 -1
  264. package/build/src/testing/scope_tree.d.ts.map +0 -1
  265. package/build/src/testing/scope_tree.js.map +0 -1
  266. package/build/src/testing/test_clock.d.ts.map +0 -1
  267. package/build/src/testing/test_clock.js.map +0 -1
  268. package/build/src/traits/authz_scopes.d.ts.map +0 -1
  269. package/build/src/traits/authz_scopes.js.map +0 -1
  270. package/build/src/traits/has_uuid.d.ts.map +0 -1
  271. package/build/src/traits/has_uuid.js.map +0 -1
  272. package/build/src/types.d.ts.map +0 -1
  273. package/build/src/types.js.map +0 -1
  274. package/build/stubs/main.d.ts.map +0 -1
  275. package/build/stubs/main.js.map +0 -1
@@ -1,8 +1,26 @@
1
1
  import type { Clock } from '../clock.js';
2
- import type { RelObject, RelSubject, RelationObjectsPage, RelationSubjectsPage, RelationPage, RelationTuplePage, RelationsDriver, RelationsDriverCapabilities, RelationTransactionOptions, RelationWriteOptions, ScopeRef } from '../types.js';
2
+ import type { RelObject, RelSubject, RelationObjectsPage, RelationSubjectsPage, RelationPage, RelationTuplePage, RelationsDriver, RelationsDriverCapabilities, RelationTransactionOptions, RelationWriteOptions, RelationDenyOptions, RelationDecision, ScopeRef } from '../types.js';
3
3
  import type { HolderTypeMap } from './openfga_driver.js';
4
4
  import type { RelationsConfig } from '../relations/define_relations_config.js';
5
5
  export declare const DEFAULT_TIMEOUT_MS = 5000;
6
+ /**
7
+ * **Tope de operaciones por `Write` en FGA** — `--max-tuples-per-write` del servidor, default 100. MEDIDO en v1.19.0
8
+ * (`openfga-dev`, lote D · cierre 1 de D1): 100 deletes en un `Write` entran; 101 —o 50 writes + 51 deletes— es 400
9
+ * «The number of write operations exceeds the allowed limit of 100» y NO se aplica nada (el `Write` es transaccional).
10
+ * Es también la frontera de la purga atómica PARA EL ESCRITOR (`#purgeByFilters`): una purga que cabe aquí es UN
11
+ * `Write`, sin PREFIJO que cortar —un `Check` concurrente SÍ puede observar ese `Write` a medias: lector rasgado, fila
12
+ * «torn read» de Limits, decisión (6a) del dueño—; con más membresías de grupo que esto, el residuo es una fila DECLARADA
13
+ * (README, «Deny on relations»).
14
+ * **Requisito del despliegue: `--max-tuples-per-write` ≥ 100** (README, «Limits»). Un servidor con el tope MÁS BAJO
15
+ * responde 400 `exceeded_entity_limit` al primer `Write` que lo pase, y ése puede no ser el primero de la purga (con
16
+ * tope 50 y `[3 allows][60 membresías][40 denies]` el `Write` de 3 ya se aplicó): el driver lo dice como **500
17
+ * `E_AUTHZ_CONFIG`** nombrando el requisito —no como un 503 que parece transitorio: repetida, la purga vuelve a pedir
18
+ * un `Write` de más de lo que el servidor admite y no termina nunca— y, si ya borró algo, **marcado como escritura
19
+ * parcial** (`indeterminate: true`, invariante 13). Cierre 2 de D1 · ⚪ N3 del auditor (la letra anterior, «503 sin
20
+ * haber borrado nada», era falsa con varios `Write`). Uno con el tope más alto no cambia nada (el driver sigue partiendo
21
+ * en 100). Sin opción para bajarlo: la cota es del servidor y el remedio es su arranque.
22
+ */
23
+ export declare const RELATIONS_PURGE_WRITE_MAX = 100;
6
24
  /**
7
25
  * **B4 (plan 2.5 · lote B): el corte EFECTIVO de `ListObjects` del servidor**.
8
26
  * Pasado, el servidor devuelve lo que llevaba resuelto con 200 y SIN señal
@@ -40,8 +58,12 @@ export declare const MONOTONIC_CLOCK: unique symbol;
40
58
  export interface OpenFgaRelationsDriverOptions {
41
59
  apiUrl: string;
42
60
  storeId: string;
43
- /** Pin del model FUSIONADO; si se omite, FGA usa el último del store. */
44
- modelId?: string;
61
+ /**
62
+ * **Pin del model FUSIONADO — OBLIGATORIO** (L11, decisión del dueño 2026-10-17 (2): D14 ampliado a los dos drivers
63
+ * `openfga`, siempre). Sin él cada `Check` evalúa contra el ÚLTIMO modelo del store mientras la puerta L11 compara
64
+ * el del arranque. `openfga:provision` lo imprime (`OPENFGA_MODEL_ID`).
65
+ */
66
+ modelId: string;
45
67
  /** Holders del consumidor: morph name → tipo FGA. El MISMO mapa del driver de roles. */
46
68
  holderTypes: HolderTypeMap;
47
69
  /** Deadline de cada llamada en ms (default 5000): vencido ⇒ 503. */
@@ -90,6 +112,12 @@ export interface OpenFgaRelationsDriverOptions {
90
112
  * `RelationsManager` con `clock` (`withClock`).
91
113
  */
92
114
  now?: Clock;
115
+ /**
116
+ * **`openfga` es EXPERIMENTAL en 2.5.x** (estrategia 2.5.0, firma 4): el MISMO literal versionado que el driver de roles.
117
+ * Sin él, 500 `E_AUTHZ_CONFIG` al construir (primera línea, sin crear el cliente). Opcional en el tipo para que el stub
118
+ * que solo registra la factory compile; obligatorio al construir.
119
+ */
120
+ experimental?: 'openfga@2.5';
93
121
  }
94
122
  export declare class OpenFgaRelationsDriver implements RelationsDriver {
95
123
  #private;
@@ -133,7 +161,36 @@ export declare class OpenFgaRelationsDriver implements RelationsDriver {
133
161
  */
134
162
  withClock(now: Clock): RelationsDriver;
135
163
  relate(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationWriteOptions): Promise<void>;
164
+ /**
165
+ * **El techo de anidación de grupos de ESTE driver** (lote «antes de RC» · R1, decisiones del dueño 2026-10-17 (5) y
166
+ * (5-bis), opción (a)): ACTIVO por defecto. Se CALIBRA contra el servidor (`#calibratedGroupDepth`) y es el mínimo de
167
+ * la sonda positiva y la negativa (22 en OpenFGA v1.19 con `--resolve-node-limit` por defecto, medido en F0 · M-c); el
168
+ * `maxGroupDepth` de la config solo puede BAJARLO — uno mayor que el calibrado es 500 `E_AUTHZ_CONFIG` con las dos
169
+ * cifras (el despliegue promete un techo que el servidor no resuelve) —, y `false` lo apaga de forma explícita (sin
170
+ * calibrar). Solo lectura: lo usa `relate` antes de escribir una arista `group#member` y el plan de
171
+ * `reconcileRelations` sobre el destino.
172
+ */
173
+ groupDepthLimit(): Promise<number | null>;
136
174
  unrelate(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationWriteOptions): Promise<void>;
175
+ /**
176
+ * **`deny` = UN `Write` de la tupla `denied_<rel>`** (lote D · D1): sin caducidad (D3), así que no hay renovación
177
+ * ni ventana —un re-deny idéntico lo ignora el servidor (`on_duplicate: ignore`)—; una tupla de deny escrita a mano
178
+ * CON condición devuelve 409 y, desde el cierre 1 de D2 (🟡 4), sale como 500 `E_AUTHZ_CONFIG` con la receta
179
+ * (`AuthorizationConfigError.conditionalDeny`; hasta entonces era un 503 que se repetía para siempre). Antes del `Write`: la
180
+ * puerta de `{ transaction }` (L-5), F-05 sobre el nombre PÚBLICO, la puerta del opt-in (fase `'write'`), sin
181
+ * caducidad, la partición, `*`, el sujeto y la puerta del modelo (L11). CERO llamadas si algo de eso falla.
182
+ */
183
+ deny(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationDenyOptions): Promise<void>;
184
+ /**
185
+ * **`removeDeny` = UN delete de `denied_<rel>`** (no-op si no está). Sobre CUALQUIER tipo declarado (D8/R2-4 b):
186
+ * `Write` con delete no valida la relación contra el modelo (medido en v1.19.0), así que un deny vivo de un tipo
187
+ * que retiró el opt-in se puede borrar. Ojo: quitar un deny CONCEDE (filas declaradas S8–S10).
188
+ * **La puerta del modelo (L11, antes D-31) SÍ corre aquí** (letra corregida en el cierre 1 de D1, ⚪ 5 del auditor:
189
+ * la decisión 4 del informe decía que no): con el opt-in vivo y un modelo fijado sin `denied_*` ⇒ 500 antes del
190
+ * delete. Con el opt-in RETIRADO no hay guarda (el tipo no está en la config con `deny`) y el delete borra de verdad
191
+ * (medido por el auditor: `listDenies` de 1 a 0 y `check` vuelve a `true` con el modelo viejo) — retirar es reversible.
192
+ */
193
+ removeDeny(subject: RelSubject, relation: string, object: RelObject, partition: ScopeRef, options?: RelationDenyOptions): Promise<void>;
137
194
  /**
138
195
  * **F-05 en las LECTURAS y las PURGAS del driver** (2.4.0-alpha.3, cierre
139
196
  * del 🔴 1 / 🟠 2 del auditor; la MISMA función y la misma posición que
@@ -161,6 +218,29 @@ export declare class OpenFgaRelationsDriver implements RelationsDriver {
161
218
  * del id POR ÍTEM antes de componer nada (defensa en profundidad).
162
219
  */
163
220
  checkMany(subject: RelSubject, relation: string, objects: RelObject[], partition: ScopeRef): Promise<boolean[]>;
221
+ /**
222
+ * **`decideMany` = un `batchCheck` con `R` y los `denied_<m>` de las relaciones FUENTE de `down*(R)`** (lote D ·
223
+ * D9, juez ronda 2 §4): por el cierre ascendente del modelo (`denied_X = this ∨ denied_P`), `denied_<fuente>`
224
+ * cubre todo `up*(down*(R))` — en el retículo del contrato, 2 ítems por objeto (`R` y `denied_owner`). Mismo
225
+ * `current_time` en TODOS los ítems (un `now` por lote), alineado por `correlationId` (`alignBatchResults`, la
226
+ * misma función que `checkMany` y roles), troceado por `FGA_MAX_BATCH_CHECK`, y un `error` en UN ítem ⇒ 503 para
227
+ * todo el lote (nunca `none`: S15). La decisión sale de `decideFrom`, la regla ÚNICA (la misma que `database` y el
228
+ * doble). En un tipo sin opt-in se pregunta el deny solo si el modelo que sirve el driver lo declara (opt-in
229
+ * retirado con el modelo aún publicado, D8); si no, cada posición es `allow` o `none` (no hay deny posible).
230
+ */
231
+ decideMany(subject: RelSubject, relation: string, objects: RelObject[], partition: ScopeRef): Promise<RelationDecision[]>;
232
+ /**
233
+ * **`denyPhase` — ¿admite este driver escrituras de deny en el tipo?** (lote D · D2, R2-5). La fase del opt-in EN
234
+ * LA CONFIG DE ESTE DRIVER y, con opt-in, el modelo FIJADO comprobado con la MISMA puerta L11 que `deny` (500 si
235
+ * no declara `denied_<rel>`). F-05 estricto del par, antes de nada (422, cero llamadas). La llama
236
+ * `reconcileRelations` en la fase de plan cuando el origen trae denies: un destino `openfga` sin `'write'` en el
237
+ * tipo, o con un pin a un modelo sin el deny, NIEGA la pasada antes de la primera escritura (jamás `skipped`).
238
+ */
239
+ denyPhase(object: {
240
+ type: string;
241
+ }, relation: string): Promise<'read' | 'write' | null>;
242
+ /** `listDenies` = `Read` por `(object, denied_<rel>)`: los denies DIRECTOS (hechos). Cualquier tipo declarado (D8). */
243
+ listDenies(relation: string, object: RelObject, partition: ScopeRef): Promise<RelationSubjectsPage>;
164
244
  /**
165
245
  * `listObjects` = `ListObjects` (resuelve includes + usersets del lado del
166
246
  * servidor) + FILTRO por partición + señal de TRUNCADO (`#listObjectsPage`:
@@ -169,14 +249,14 @@ export declare class OpenFgaRelationsDriver implements RelationsDriver {
169
249
  * se consume entre todas — otra razón para señalar el truncado y no callar
170
250
  * (documentado en el README).
171
251
  */
172
- listObjects(subject: RelSubject, relation: string, objectType: string, partition: ScopeRef, _page?: RelationPage): Promise<RelationObjectsPage>;
252
+ listObjects(subject: RelSubject, relation: string, objectType: string, partition: ScopeRef): Promise<RelationObjectsPage>;
173
253
  /**
174
254
  * `listSubjects` = `Read` por `(object, relation)` — hechos DIRECTOS del
175
255
  * relation EXACTO (invariante 7): ni transitivo (eso es `membersOf`) ni
176
256
  * derivado por includes. `usersetSubjects: true` ⇒ los usersets
177
257
  * (`group#member`) salen junto con los holders.
178
258
  */
179
- listSubjects(relation: string, object: RelObject, partition: ScopeRef, _page?: RelationPage): Promise<RelationSubjectsPage>;
259
+ listSubjects(relation: string, object: RelObject, partition: ScopeRef): Promise<RelationSubjectsPage>;
180
260
  /**
181
261
  * **`membersOf` ⇒ 500 `E_AUTHZ_UNSUPPORTED`** (cara `whenFalse`): la
182
262
  * membresía TRANSITIVA de un grupo sería `ListUsers`, que trunca al tope del
@@ -202,12 +282,19 @@ export declare class OpenFgaRelationsDriver implements RelationsDriver {
202
282
  * la CADUCADA también llega, con su `expiresAt` (R-15), para que el destino
203
283
  * la cuente en `skipped`.
204
284
  *
285
+ * **Una tupla con condición AJENA llega marcada** (`invalidCondition`, L11) y
286
+ * con `expiresAt` = la ÉPOCA. Eso es conservador SOLO para los allows: un
287
+ * lector que ignore la marca lee el deny (o la membresía de `group` que lo
288
+ * transporta) como VENCIDO y deja de negar —fail-OPEN— (cierre-2 · ⚪ C3).
289
+ * Ninguna fecha sirve para los dos tipos de tupla: el lector tiene que mirar
290
+ * `invalidCondition` ANTES que `expiresAt` (el plan del paquete lo hace).
291
+ *
205
292
  * **Coste: O(tuplas del store) por PASADA** (2.4.0-alpha.6): es un barrido
206
293
  * entero por llamada, sea cual sea el tamaño de la partición (medido: 5 000
207
294
  * tuplas ⇒ 50 páginas ≈ 170 ms; 15 000 ⇒ 151 páginas ≈ 0,5 s). Para K
208
295
  * particiones usa `enumerateRelationsMany`: UN barrido en vez de K.
209
296
  */
210
- enumerateRelations(partition: ScopeRef, _page?: RelationPage): Promise<RelationTuplePage>;
297
+ enumerateRelations(partition: ScopeRef, page?: RelationPage): Promise<RelationTuplePage>;
211
298
  /**
212
299
  * **`enumerateRelationsMany` — K particiones en UN barrido** (2.4.0-alpha.6;
213
300
  * panel relay, analista §3: con 3 particiones 1,4 s → 0,46 s). MISMA
@@ -234,7 +321,7 @@ export declare class OpenFgaRelationsDriver implements RelationsDriver {
234
321
  * se cuenta en `diagnostics.unparseableTuples` y se avisa. Sin particiones
235
322
  * es 500 `E_AUTHZ_CONFIG` con cero lecturas: no hay «éxito vacío».
236
323
  */
237
- enumerateRelationsMany(partitions: ScopeRef[], _page?: RelationPage): Promise<RelationTuplePage>;
324
+ enumerateRelationsMany(partitions: ScopeRef[], page?: RelationPage): Promise<RelationTuplePage>;
238
325
  /**
239
326
  * Borra TODAS las tuplas del objeto (cualquier relación) y demuestra cero.
240
327
  * Hasta 2.5.0 barría las DOS ortografías del uuid de partición (🟡2);
@@ -252,4 +339,18 @@ export declare class OpenFgaRelationsDriver implements RelationsDriver {
252
339
  */
253
340
  purgeSubject(subject: RelSubject, partition: ScopeRef, options?: RelationTransactionOptions): Promise<void>;
254
341
  }
255
- //# sourceMappingURL=openfga_relations_driver.d.ts.map
342
+ /**
343
+ * **Los `Write` de una purga, en orden** (lote D · cierre 1 de D1, 🟠 1; ver `#purgeByFilters`): uno solo si todo cabe
344
+ * en `RELATIONS_PURGE_WRITE_MAX`; si no, en el orden de BORRADO del punto de paso ÚNICO `relationDeleteOrder`
345
+ * (`src/relations/tuple_order.ts`, cierre 1 de D2 · 🟠 1: el MISMO que usa el reconcile) — allows sobre objetos que no
346
+ * son `group`, luego las membresías `group:*#member` (las portadoras de deny al final, ordenadas por objeto y sujeto) y
347
+ * al final los `denied_*` —, con CADA CLASE en sus PROPIOS `Write` (con ≤ 100 membresías, uno). Pura: la tabla de verdad
348
+ * del caso la juzga contra el servidor, y la PROPIEDAD la juzga sin servidor la guardia de superficie
349
+ * (`GS · P · openfga.purge.order`, cierre 2 de D1 · ⚪ N2), con los mutantes de orden en el corredor publicado
350
+ * (`npm run check:guard-mutants`). Exportada solo para eso: no sale por `/openfga`.
351
+ */
352
+ export declare function purgeWrites<K extends {
353
+ user: string;
354
+ relation: string;
355
+ object: string;
356
+ }>(keys: readonly K[]): K[][];