@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
@@ -1,12 +1,13 @@
1
- import type { AuthorizationConfig } from './define_config.js';
2
- import type { AuthorizationDriver, AuthorizedScopes, CatalogRole, DenyOptions, DenyRef, ExcludedSubtree, GrantOptions, GrantOutcome, RoleQuery, ScopeDetachOutcome, ScopedRoleChanges, ScopedRoleSpec, ScopedWriteOptions, ScopeRef, ScopeType, SubjectRef } from './types.js';
1
+ import { type AuthorizationConfig } from './define_config.js';
2
+ import type { FreezeKind, FreezeToken } from './freeze.js';
3
+ import type { AuthorizationDriver, AuthorizationDriverCapabilities, AuthorizedScopes, CatalogRole, CatalogRoleRef, DenyOptions, DenyRef, ExcludedSubtree, GrantOptions, GrantOutcome, RoleQuery, ScopedRoleChanges, ScopedRoleSpec, ReconcileOptions, ReconcileReport, ScopedWriteOptions, ScopeEnqueueReceipt, ScopeRequeueReport, ScopeRelayReport, ScopeRef, ScopeTreeWriteOptions, ScopeType, SubjectRef, RelationsDriverFactory } from './types.js';
3
4
  /**
4
5
  * Lo que devuelve `AuthorizationManager.forRequest()`: la misma API que el
5
6
  * manager (lecturas, escrituras, `scopes.*`), con los ancestros memoizados
6
7
  * SOLO en las lecturas. Es un tipo, no otra clase: la vista es un manager
7
8
  * hijo que comparte config, driver y hooks con su padre.
8
9
  */
9
- export type AuthorizationView = Pick<AuthorizationManager, 'authorize' | 'hasRole' | 'listSubjects' | 'listScopes' | 'listRoles' | 'listRoleScopes' | 'grant' | 'revoke' | 'deny' | 'removeDeny' | 'scopes' | 'driver' | 'forRequest' | 'isWithin' | 'listDenies' | 'effectivePermissions' | 'authorizeMany' | 'authorizedScopes' | 'expandExcludedSubtrees' | 'defineScopedRole' | 'updateScopedRole' | 'deleteScopedRole'>;
10
+ export type AuthorizationView = Pick<AuthorizationManager, 'authorize' | 'hasRole' | 'listSubjects' | 'listScopes' | 'listRoles' | 'listRoleScopes' | 'grant' | 'revoke' | 'deny' | 'removeDeny' | 'scopes' | 'driver' | 'capabilities' | 'forRequest' | 'isWithin' | 'listDenies' | 'effectivePermissions' | 'authorizeMany' | 'authorizedScopes' | 'expandExcludedSubtrees' | 'defineScopedRole' | 'updateScopedRole' | 'deleteScopedRole'>;
10
11
  /**
11
12
  * Expande los `excludedSubtrees` de un `all` (2D · F10) a la lista plana de
12
13
  * scopes que hay que restar: cada scope denegado y TODOS sus descendientes,
@@ -25,8 +26,51 @@ export declare const DEFAULT_MAX_DESCENDANTS = 10000;
25
26
  * Una cota mayor es config rota (500), nunca una pregunta.
26
27
  */
27
28
  export declare const MAX_SCOPE_BOUND = 10000000;
29
+ /**
30
+ * Cotas por defecto de `authz:scopes:relay` (3b-2d). El lote es el tamaño de
31
+ * cada `pending()`; el límite, cuántos cambios aplica una pasada antes de
32
+ * volver (lo que quede sigue pendiente: drenar es reanudable por diseño y
33
+ * una pasada eterna no es reanudable).
34
+ */
35
+ export declare const DEFAULT_RELAY_BATCH = 100;
36
+ export declare const DEFAULT_RELAY_LIMIT = 10000;
37
+ /**
38
+ * **Saltos que la sonda de `only` sigue hacia atrás para heredar el ORIGEN de
39
+ * un bloqueo** (2.4.0-alpha.6). Cada salto es una consulta `earlierPending`
40
+ * (0,69 ms) sobre una entrada NO pedida; la cadena es de ids estrictamente
41
+ * decrecientes, así que termina sola — la cota solo acota el coste dentro de
42
+ * una petición inline. Pasada la cota el origen se toma por FALLO (la purga se
43
+ * aplaza a la pasada completa): degrada hacia lo seguro, nunca aplica sin saber.
44
+ */
45
+ export declare const RELAY_ORIGIN_MAX_HOPS = 100;
46
+ /**
47
+ * **Cota PROPIA del censo de aparcadas** (alpha.5 · cierre, auditor 🟠 2). Las
48
+ * claves de `dead()` que taponan `attached`/`moved` se leen COMPLETAS en cada
49
+ * pasada, sean cuales sean `limit` y `batchSize` (con `--limit 50` o la receta
50
+ * inline `{ only, limit: 1 }` un censo acotado por `limit` dejaba a la aparcada
51
+ * 101 sin taponar y el `attached` colgaba del padre VIEJO — y la sonda de
52
+ * `only` no la ve porque `earlierPending` excluye lo aparcado). Si hay más
53
+ * aparcadas que esto, la pasada se NIEGA (500) en vez de aplicar con un tapón
54
+ * incompleto: una cola así es un incidente, no un lote.
55
+ */
56
+ export declare const PARKED_CENSUS_MAX = 50000;
28
57
  /** Vida por defecto de una vista de `forRequest()` para LEER (F9): un request, no un módulo. */
29
58
  export declare const DEFAULT_VIEW_MAX_AGE_MS = 30000;
59
+ /**
60
+ * Cada cuánto reintenta `acquire()` una pasada con `waitForLeaseMs` (2.4.0-alpha.8;
61
+ * panel relay 2, cuestión 7). Medido en PG: 0,29 ms por sondeo ocupado, y el
62
+ * sondeo no retiene conexión entre intentos (la transacción del intento fallido
63
+ * se revierte). El default de `waitForLeaseMs` es 0: el `busy` inmediato de
64
+ * siempre.
65
+ */
66
+ export declare const RELAY_LEASE_POLL_MS = 25;
67
+ /**
68
+ * Tope de `waitForLeaseMs` (cierre alpha.8, 🟡 1 del auditor): una espera sin tope
69
+ * cuelga la petición de un tenant; por encima es 500 `E_AUTHZ_CONFIG`. Y la espera
70
+ * se cuenta en SONDEOS (`waitForLeaseMs / RELAY_LEASE_POLL_MS`), no solo con el
71
+ * reloj de pared: con `config.clock` fijo el sondeo por reloj no terminaba nunca.
72
+ */
73
+ export declare const RELAY_WAIT_LEASE_MAX_MS = 60000;
30
74
  export interface ForRequestOptions {
31
75
  /**
32
76
  * Milisegundos durante los que la vista puede LEER (default 30 000).
@@ -45,6 +89,47 @@ export interface ForRequestOptions {
45
89
  */
46
90
  now?: () => number;
47
91
  }
92
+ /** Lo que `freezeStatus()` responde de un freeze VIVO (la fila, legible por cualquiera). */
93
+ export interface FreezeStatus {
94
+ reason: string;
95
+ holder: string;
96
+ kind: FreezeKind | 'unknown';
97
+ /** Instante (ms de pared) en el que el lease vence, o `null` si no caduca. */
98
+ untilMs: number | null;
99
+ fence: number;
100
+ }
101
+ /**
102
+ * Lo que `withFrozenWrites` le cuenta a la pasada que corre dentro (L-1 · J1):
103
+ * el fence de la ventana, su lease y si se PERDIÓ a mitad (`lapsed`), para
104
+ * que una pasada de plataforma ajena al manager publique la garantía en vez
105
+ * de suponerla (`report.frozen`).
106
+ */
107
+ export interface FrozenWindow {
108
+ fence: number;
109
+ /**
110
+ * El lease de la ventana. En la ventana del OPERADOR adoptada
111
+ * (2.4.0-alpha.10) es lo que le QUEDABA al adoptarla (`untilMs − ahora`);
112
+ * `null` solo si la ventana no caduca.
113
+ */
114
+ leaseMs: number | null;
115
+ /**
116
+ * Solo en la ventana del OPERADOR adoptada (2.4.0-alpha.10, 🟡 3 del sexto
117
+ * informe de COGNITIV): el instante (ms de pared) en el que caduca, de la
118
+ * fila, o `null` si no caduca. Quien adopta la ventana no la renueva: si
119
+ * caduca a mitad, `lapsed` lo dice; esto dice que PUEDE caducar.
120
+ */
121
+ untilMs?: number | null;
122
+ /**
123
+ * EN QUÉ ventana corrió (2.4.0-alpha.10, S2): la del OPERADOR adoptada, una
124
+ * PROPIA tomada para la pasada, o la que ya sostenía este manager
125
+ * (`enclosing`). La salida de los comandos lo dice siempre: «corrí dentro del
126
+ * cutover» y «tomé mi ventana porque no había ninguna» eran letra a letra
127
+ * iguales.
128
+ */
129
+ window?: 'operator' | 'own' | 'enclosing';
130
+ /** ¿Se perdió la ventana en algún momento? (renovación fallida, fila ajena o vencida). */
131
+ lapsed: () => Promise<boolean>;
132
+ }
48
133
  /**
49
134
  * Manager de autorización — la fachada que usan middleware, services y
50
135
  * seeders. Resuelve el driver activo del config y notifica cada escritura
@@ -91,6 +176,140 @@ export declare class AuthorizationManager {
91
176
  * sin `withClock` con `clock` declarado es 500 `E_AUTHZ_CONFIG`.
92
177
  */
93
178
  driver(): Promise<AuthorizationDriver>;
179
+ /**
180
+ * **Lo que el driver ACTIVO declara, de solo lectura** (2.4.0-alpha.4;
181
+ * pregunta 1 de COGNITIV, panel alpha.4). Para que el código de tenant
182
+ * pueda ramificar —`if ((await authorization.capabilities()).transactionalWrites)
183
+ * grant(…, { transaction }) else grant(…)`— sin llamar a `driver()`, que
184
+ * sigue siendo API de PLATAFORMA (el grep del README sigue significando lo
185
+ * que significa).
186
+ *
187
+ * Es `(await this.driver()).capabilities` y NADA más, a propósito:
188
+ * - las capacidades son de la INSTANCIA (`database` decide
189
+ * `transactionalWrites` desde sus opciones), así que hay que resolver;
190
+ * - y se resuelve POR `driver()`, con sus dos puertas
191
+ * (`requireTransactionalWrites` y el gate de deriva del árbol) y su
192
+ * caché. Resolverlo por otro camino «para que la lectura no lance» y
193
+ * guardarlo en `#driver` dejaría `driver()` sirviendo un driver que
194
+ * nunca pasó por las puertas: un bypass permanente del gate de deriva
195
+ * (🔴 1 del auditor). Por eso hereda los 500 de las puertas
196
+ * (`E_AUTHZ_CONFIG`, `E_AUTHZ_SCOPE_DRIFT_UNGUARDED`) y la factory del
197
+ * consumidor: llámalo al arrancar (un hook `booted`/`ready`), no por
198
+ * request en un endpoint de metadatos.
199
+ *
200
+ * Devuelve una copia CONGELADA y NORMALIZADA: todas las claves de
201
+ * `AuthorizationDriverCapabilities` presentes, solo `true` es `true`
202
+ * (la misma lectura que la puerta 1), nunca `undefined`; mutarla no toca
203
+ * el objeto que leen las puertas. La vista de `forRequest()` delega en el
204
+ * padre (por `driver()`).
205
+ */
206
+ capabilities(): Promise<Readonly<AuthorizationDriverCapabilities>>;
207
+ /**
208
+ * **Congela las ESCRITURAS del motor, DURABLE** (3b-7; decisión del dueño
209
+ * del 2026-08-31 (3b): B + E-analista). Operación de PLATAFORMA, como
210
+ * `driver()`: no se expone por HTTP.
211
+ *
212
+ * El estado ya NO vive en el proceso: vive en la fila `id = 2` de
213
+ * `authz_catalog_version`, así que alcanza a **todos los procesos que
214
+ * comparten las tablas `authz_*`** (invariante 14: el comando ace y los
215
+ * workers hablan con la misma base). Mientras el freeze está vivo, toda
216
+ * escritura del manager —las cuatro de hechos, las tres de árbol, la API
217
+ * de delegación, `pruneOrphanRoles({force})` y `relayScopeChanges`—
218
+ * responde 503 `E_AUTHZ_FROZEN` **reintentable** y no llega al driver; las
219
+ * LECTURAS siguen respondiendo con normalidad (la asimetría deliberada:
220
+ * `authorize` no se congela ni un milisegundo).
221
+ *
222
+ * Devuelve el **token del dueño** (`{ fence, holder }`): `unfreeze(token)`
223
+ * solo levanta el freeze cuyo token coincide — el `finally` de una ventana
224
+ * ajena o rezagada no puede levantar la tuya (auditor A1.3). Un freeze
225
+ * VIVO de otro dueño ⇒ 423 `E_AUTHZ_FREEZE_HELD`, nunca dos dueños.
226
+ *
227
+ * El **lease** (default 15 s) se renueva solo (`leaseMs / 3`, `unref()`)
228
+ * mientras este proceso vive; si el proceso muere (`SIGKILL`, OOM), el
229
+ * lease vence y la flota vuelve a escribir SOLA en ≤ `leaseMs` — nadie
230
+ * limpia nada a mano. `leaseMs: null` = sin caducidad: la ventana del
231
+ * OPERADOR (`authz:freeze`), que dura hasta su `authz:unfreeze`.
232
+ *
233
+ * Lo que el freeze **NO congela**, a propósito y documentado (auditor
234
+ * 🟠 5): `syncAuthzCatalog` (función libre que no ve al manager),
235
+ * `manager.driver()` (la salida documentada de TODAS las barreras) y el
236
+ * árbol SQL del consumidor (sus tablas, su SQL). Y lo que no puede
237
+ * prometer: una escritura que ya pasó su barrera cuando el freeze aterriza
238
+ * ENTRA (no hay atomicidad entre una fila SQL y un backend externo) — la
239
+ * promesa publicada es «otro proceso recibe 503», jamás «ninguna escritura
240
+ * entra en la ventana».
241
+ */
242
+ freeze(reason?: string, options?: {
243
+ leaseMs?: number | null;
244
+ kind?: FreezeKind;
245
+ }): Promise<FreezeToken>;
246
+ /**
247
+ * Levanta el freeze de ESTE token; uno ajeno o rezagado no toca nada (esa
248
+ * es toda la garantía del fence). Devuelve si de verdad lo levantó.
249
+ */
250
+ unfreeze(token: FreezeToken): Promise<boolean>;
251
+ /**
252
+ * ¿SOSTIENE este manager un freeze? (proceso-local: su token vive aquí.)
253
+ * Para saber si el MOTOR está congelado —por quien sea— pregunta
254
+ * `freezeStatus()`: eso es la fila, no la memoria.
255
+ */
256
+ get frozen(): boolean;
257
+ /**
258
+ * La clave (en `relations.drivers`) del driver de RELACIONES activo:
259
+ * `relations.default ?? default` (2.4.0-alpha.10). La lee el guard de la
260
+ * dirección rancia de `runRelationsReconcile`; desde el cierre del auditor
261
+ * (R4) el llamante ya no puede contradecirla con un `activeKey` propio.
262
+ */
263
+ relationsDriverKey(): string;
264
+ /** Las claves registradas en `relations.drivers` del config de ESTE manager (vacío si no hay relaciones). */
265
+ relationsDriverKeys(): string[];
266
+ /**
267
+ * La factory registrada bajo `key` en `relations.drivers` de ESTE manager, o
268
+ * `undefined` (cierre del auditor de alpha.10 · R4). `runRelationsReconcile`
269
+ * resuelve el origen y el destino por aquí —del MISMO config que decide el
270
+ * activo— y juzga la identidad por la factory resuelta, no por la etiqueta:
271
+ * dos claves con la misma factory son el mismo driver (y dos factories DISTINTAS
272
+ * sobre el mismo backend NO: límite declarado, cierre-2 · C1).
273
+ *
274
+ * **API de PLATAFORMA, junto a `driver()`** (cierre-2 · C6): con esta factory
275
+ * cualquier código que tenga el manager —vistas de `forRequest()` incluidas—
276
+ * construye un driver de relaciones NO activo y escribe en él sin `assertWrite`,
277
+ * `requireActor`, freeze ni `onRelationWrite`. No añade capacidad (el config ya
278
+ * da las factories), pero es otra cosa que buscar en una revisión.
279
+ */
280
+ relationsDriverFactory(key: string): RelationsDriverFactory | undefined;
281
+ /** El freeze VIVO de la fila compartida, o `null`. Lo lee cualquiera; solo el token lo levanta. */
282
+ freezeStatus(): Promise<FreezeStatus | null>;
283
+ /**
284
+ * **La ÚLTIMA ventana de la fila, también la CADUCADA** (2.4.0-alpha.10, 🟠 2
285
+ * del sexto informe de COGNITIV). `freezeStatus()` responde solo lo VIVO —y
286
+ * así lo siguen usando la barrera y los comandos—, de modo que una ventana
287
+ * cuyo lease venció era indistinguible de «nunca hubo»: `authz:unfreeze`
288
+ * decía éxito y el último paso del cutover no delataba que las escrituras
289
+ * habían vuelto a entrar a mitad. Se distingue por la fila: `releaseFreeze`
290
+ * pone el motivo a `null` al levantar, así que motivo puesto + `untilMs` en
291
+ * el pasado es una ventana que CADUCÓ sin que nadie la cerrase.
292
+ *
293
+ * `null` = nunca hubo o ya se levantó; `expired: false` = viva (lo mismo que
294
+ * `freezeStatus()`); `expired: true` = caducada. `checkedAtMs` es el instante
295
+ * del reloj del config con el que se decidió.
296
+ */
297
+ lastFreezeStatus(): Promise<(FreezeStatus & {
298
+ expired: boolean;
299
+ checkedAtMs: number;
300
+ }) | null>;
301
+ /**
302
+ * `freeze()` + `finally unfreeze(token)`. El `finally` es la parte que
303
+ * importa: una migración que revienta a la mitad no puede dejar la
304
+ * aplicación sin poder escribir (y si además el proceso muere sin
305
+ * `finally`, el lease vence solo). **El anidado corre DENTRO** (auditor
306
+ * A1.1/A1.3): si este manager ya sostiene el freeze, la ventana interior
307
+ * no toma otro ni lo levanta al salir — la exterior sigue en pie.
308
+ */
309
+ withFrozenWrites<T>(reason: string, fn: (window: FrozenWindow) => Promise<T>, options?: {
310
+ kind?: FreezeKind;
311
+ operatorAsContext?: boolean;
312
+ }): Promise<T>;
94
313
  /** Solo tests: fuerza re-resolución del driver. */
95
314
  clearCachedDriver(): void;
96
315
  /**
@@ -102,8 +321,21 @@ export declare class AuthorizationManager {
102
321
  * Espía: si la validación falla, cero llamadas al driver.
103
322
  */
104
323
  readonly scopes: {
105
- attached: (child: ScopeRef, parent: ScopeRef, options?: ScopedWriteOptions) => Promise<void>;
106
- moved: (child: ScopeRef, newParent: ScopeRef, options?: ScopedWriteOptions) => Promise<void>;
324
+ attached: (child: ScopeRef, parent: ScopeRef, options?: ScopeTreeWriteOptions) => Promise<ScopeEnqueueReceipt>;
325
+ /**
326
+ * `moved` NO vuelve a juzgar el catálogo, y no tiene por qué (3b-1 · D3,
327
+ * auditor 3G): mover un scope es un hecho del árbol, no una escritura de
328
+ * catálogo. Lo que hay que tener escrito es la consecuencia: la relación
329
+ * «A ensombrece a B» es función del árbol de HOY, así que un `moved` que
330
+ * mete un subárbol bajo un scope que ya tiene el homónimo **crea la
331
+ * sombra sin que se juzgue ningún rango en ninguna parte** — y el dueño
332
+ * del subárbol movido puede no poder repararla (su rango se mide en la
333
+ * cadena del owner de la sombra). Por eso «sobre un rol solo actúa quien
334
+ * lo supera en rango» (3G · W3) es una comprobación de ESCRITURA y no un
335
+ * invariante del sistema. Es ruidosa: `authz:catalog:diff` la lista como
336
+ * `shadowedByAncestor` (y `--fail-on-shadows` la cuenta como deriva).
337
+ */
338
+ moved: (child: ScopeRef, newParent: ScopeRef, options?: ScopeTreeWriteOptions) => Promise<ScopeEnqueueReceipt>;
107
339
  /**
108
340
  * Hechos primero (el driver demuestra cero o lanza), arista después
109
341
  * (S6): si la purga muere a medias, el subárbol sigue colgado y los
@@ -111,9 +343,208 @@ export declare class AuthorizationManager {
111
343
  * scope exista (el consumidor puede haber borrado ya su fila); con
112
344
  * `within` (2D · F2) el hijo tiene que seguir en el árbol para
113
345
  * contrastar su cadena: purga ANTES de borrar la fila.
346
+ *
347
+ * **Purga HECHOS y solo hechos** (invariante 11; 3b-0 · Z1). Entre 3D y
348
+ * 3G esta operación arrastraba además los roles LOCALES cuyo owner era
349
+ * ese scope (y, con `descendantsOf`, los de todo el subárbol), con su
350
+ * propia policy de rango, su degradación y un valor de retorno que
351
+ * contaba lo purgado. Cinco lotes la tocaron y TRES de las cuatro
352
+ * regresiones de la Fase 3 nacieron ahí, siempre por COMPOSICIÓN de
353
+ * piezas correctas por separado (3E · P3 + 3F · S1/S2 ⇒ 3G · W1). El
354
+ * requisito que lo pedía —un rol cuyo owner desaparece queda
355
+ * indeleteable y ocupa su `(slug, nivel)`— se resuelve más simple y
356
+ * fuera del camino de un tenant: el rol queda DORMIDO (no concede, no es
357
+ * membresía, no se asigna) y la PLATAFORMA lo retira con
358
+ * `authz:catalog:prune-orphans` (Z2). Así `scopes.detached` vuelve a ser
359
+ * O(1), sin rango que medir, sin árbol que enumerar y sin nada que
360
+ * declarar a medias.
114
361
  */
115
- detached: (child: ScopeRef, options?: ScopedWriteOptions) => Promise<ScopeDetachOutcome>;
362
+ detached: (child: ScopeRef, options?: ScopeTreeWriteOptions) => Promise<ScopeEnqueueReceipt>;
116
363
  };
364
+ /**
365
+ * **Drena la outbox del árbol y aplica los cambios al driver** (3b-2d).
366
+ * Es lo que hay detrás de `node ace authz:scopes:relay`.
367
+ *
368
+ * Operación de PLATAFORMA, como `pruneOrphanRoles`: se salta `requireActor`
369
+ * y `requireWithin` a propósito —la policy ya se juzgó al ENCOLAR, con el
370
+ * árbol y la sesión de aquel momento— así que **no se expone por HTTP**.
371
+ * Aquí solo se propaga lo que ya se validó.
372
+ *
373
+ * Reanudable y nunca silenciosa: el reporte dice QUÉ se aplicó (no un
374
+ * contador: la pasada no es atómica), qué falló, qué se aplazó y si queda
375
+ * trabajo.
376
+ *
377
+ * **El orden del árbol importa, pero solo entre cambios que se tocan**
378
+ * (3b-2h · 🔴 2, auditor R2). Hasta el 2h la pasada PARABA en el primer
379
+ * fallo, y eso convertía una entrada que ya no se puede aplicar —el padre
380
+ * del `attached` encolado se borró antes del relevo, la arista cerraría
381
+ * ahora un ciclo, el nodo acabó con dos padres— en un **tapón permanente
382
+ * para todos los tenants**: `pending()` devuelve lo no aplicado ordenado
383
+ * por id, así que la envenenada era la cabecera de la cola en TODAS las
384
+ * pasadas siguientes y ningún cambio del árbol volvía a llegar al store
385
+ * (medido: una unit nueva nunca recibía su arista `parent`, el deny de su
386
+ * organization nunca la alcanzaba y un `detached` posterior nunca purgaba).
387
+ * Ahora un fallo **contamina los scopes que nombra**: los cambios
388
+ * posteriores que tocan alguno de ellos se APLAZAN sin intentarse (y
389
+ * contaminan a su vez, así que la dependencia es transitiva), y los demás
390
+ * se aplican. El par ordenado que importaba —`attached(P, org)` antes que
391
+ * `attached(C, P)`, `moved` antes que `detached`— sigue respetado porque
392
+ * comparten scope; lo que ya no pasa es que el tenant A congele el árbol
393
+ * del tenant B.
394
+ *
395
+ * **Escritor ÚNICO** (3b-2h · 🟠 4): si la outbox sabe dar un lease
396
+ * (`acquire`), la pasada lo toma y una segunda pasada simultánea no hace
397
+ * nada y lo dice (`busy`). Sin lease, dos pasadas trabajan sobre el mismo
398
+ * lote —`pending()` no reserva y el lote no se relee— y la rezagada
399
+ * re-aplica cambios viejos sobre el árbol nuevo.
400
+ *
401
+ * Lo que esta pieza NO arregla, y va escrito en el README con estas
402
+ * palabras: entre el commit del consumidor y esta pasada hay un lag
403
+ * (segundos) durante el cual el backend decide con el árbol VIEJO. Es un
404
+ * **fail-open temporal** —el tenant antiguo conserva acceso tras un
405
+ * `moved`, los denies heredados no aplican tras un `attached`—. No hay
406
+ * 2PC; es el precio de tener el árbol en dos sitios.
407
+ *
408
+ * **`only` (2.4.0-alpha.5 · R1)**: relevar SOLO estas entradas —los ids del
409
+ * recibo de `scopes.*` que ESTE proceso acaba de recibir, jamás del cuerpo
410
+ * de una petición— sin leer la cola de los demás (medido: 4 507 ms → 19 ms
411
+ * con 500 entradas ajenas por delante). El orden por clave NO se relaja:
412
+ * antes de aplicar cada entrada pedida se sondea la cola ENTERA
413
+ * (`earlierPending`, o paginando `pending()` si la outbox no lo tiene) y,
414
+ * si hay una pendiente ANTERIOR que comparte clave de scope con ella, sale
415
+ * `deferred` con `depends-on:<id>` — nunca aplicada fuera de orden (el 🔴 1
416
+ * del panel relay, medido: un `attached(child, unit)` aplicado antes que su
417
+ * `moved(unit → orgB)` dejaba al editor de la org VIEJA autorizando sobre el
418
+ * hijo). `remaining` y `dead` siguen siendo GLOBALES. `only: []` es 500
419
+ * (un `filter` vacío del consumidor no puede acabar en drenaje ni en un
420
+ * reporte vacío en verde), y una outbox que no honre el filtro también.
421
+ *
422
+ * **Lo aparcado tapona por clave (alpha.5 · R2a)**: las claves de `dead()`
423
+ * siembran el bloqueo al inicio de la pasada para lo que CONCEDE o recuelga
424
+ * (`attached`/`moved`, `deferred` con `parked:<id>`) y dejan pasar lo que
425
+ * RETIRA (`detached`: una purga nunca queda bloqueada, invariante 11). Y un
426
+ * 503 del backend NO consume intento (`markFailed(..., { transient })`).
427
+ */
428
+ relayScopeChanges(options?: {
429
+ limit?: number;
430
+ batchSize?: number;
431
+ dryRun?: boolean;
432
+ only?: Array<string | number>;
433
+ waitForLeaseMs?: number;
434
+ /**
435
+ * Bajo `only`, `dead[]` va SIN `error` por DEFECTO (2.4.0-alpha.8): la
436
+ * causa la escribe el backend sobre el árbol de OTRO tenant; `'full'`
437
+ * la devuelve (lo de hasta alpha.7). Sin `only` no cambia nada.
438
+ */
439
+ deadDetail?: 'full';
440
+ }): Promise<ScopeRelayReport>;
441
+ /**
442
+ * **Devuelve entradas APARCADAS a la cola** (2.4.0-alpha.5 · R2b; panel
443
+ * relay, cuestión 2). Es lo que hay detrás de `node ace authz:scopes:requeue
444
+ * --id`. Operación de PLATAFORMA como `relayScopeChanges` y `driver()`: sin
445
+ * actor, sin `within`, **no se expone por HTTP**.
446
+ *
447
+ * **La sonda anti-reversión vive AQUÍ, no en la outbox**: reaplicar una
448
+ * entrada ANTERIOR a otra ya APLICADA sobre la misma clave de scope
449
+ * reescribe el árbol del store en un orden que nunca existió — el `moved`
450
+ * viejo tras el nuevo deja el padre VIEJO con UN solo padre, así que
451
+ * `assertOneParent` no lo delata y el tenant antiguo recupera el acceso
452
+ * (auditor 🔴 2, `relay-auditor-5.ts`, medido). Por eso, antes de tocar la
453
+ * cola, cada aparcada pedida se compara contra las aplicadas posteriores
454
+ * que compartan clave (`outbox.laterApplied`, espejo de `earlierPending`)
455
+ * y si hay alguna se NIEGA con 500 `E_AUTHZ_REQUEUE_REFUSED` nombrándola —
456
+ * todo o nada, cero filas tocadas—. El remedio correcto es
457
+ * `authz:reconcile --to=<driver>`, que recalcula con el árbol de HOY. La
458
+ * sonda es del manager porque necesita las claves del cambio
459
+ * (`#changeKeys`); `outbox.requeue` queda mecánico y una outbox de
460
+ * terceros la hereda gratis.
461
+ *
462
+ * **`force`** salta la sonda y devuelve el diff en `overrides`. Existe para
463
+ * el comando ace —que lo imprime y exige el flag explícito (decisión del
464
+ * dueño del 2026-09-09 (2))— y para nada más: llamarlo con `force: true`
465
+ * desde un endpoint es policy en una API sin policy.
466
+ *
467
+ * `attempts` queda en `maxAttempts − 1` (lo hace la outbox): si la causa
468
+ * sigue rota la entrada vuelve a aparcarse en UNA pasada y contamina su
469
+ * clave solo en esa pasada —un requeue automatizado de lo irreparable no
470
+ * es un grifo de aplazamiento permanente (auditor 🔴 2, segunda mitad)—; si
471
+ * el operador la arregló, entra a la primera. No hay bucle: lo aparcado no
472
+ * vuelve solo a `pending()`.
473
+ *
474
+ * Exige `dead`, `requeue` y `laterApplied` en el puerto (500
475
+ * `E_AUTHZ_UNSUPPORTED` nombrando el que falte): sin censo no se sabe qué
476
+ * se reencola y sin sonda no hay requeue. Sin `apply` no pasa por la
477
+ * barrera del freeze: no escribe en el backend; la pasada que aplique la
478
+ * entrada sí la pasa.
479
+ *
480
+ * **`apply: true` — reencolar Y relevar en la misma llamada** (2.4.0-alpha.8;
481
+ * panel relay 2, cuestión 4; decisión del dueño 2026-09-10 (4)). Medido
482
+ * (tester P14): la reencolada vuelve con su id ORIGINAL (menor) y la
483
+ * siguiente pasada `only` del tenant salía `deferred · depends-on:` — el
484
+ * incidente no se cerraba con un comando. Con `apply`, tras reencolar se
485
+ * releva SOLO eso (`only` = exactamente los ids reencolados: los
486
+ * dependientes NO se arrastran, quedan `deferred`/pendientes y el reporte lo
487
+ * dice —«`only` es mi recibo»—) y el reporte del relay viaja en
488
+ * `report.relay`. Cuatro condiciones, todas fijadas con caso: (1) **un solo
489
+ * lease** para toda la llamada (tomarlo dos veces era `busy` en verde,
490
+ * auditor 🟠 5) — se toma PRIMERO, y si está ocupado es `relay.busy` con
491
+ * CERO filas reencoladas (reencolar y decir `busy` dejaba `attempts = max −
492
+ * 1` y la entrada se volvía a aparcar contaminando su clave); (2) **pasa la
493
+ * barrera del freeze** ANTES de tocar nada (con `apply` escribe el árbol);
494
+ * (3) **excluyente con `force`** (500 juntos: con las dos, revertir el árbol
495
+ * pasaba de dos llamadas de plataforma a una, auditor 🟠 6); (4) la sonda
496
+ * anti-reversión corre ANTES de reencolar, como siempre. `waitForLeaseMs`
497
+ * (solo con `apply`) es la misma espera acotada que en el relay, para que
498
+ * el comando que cierra el incidente no pierda siempre contra el cron.
499
+ */
500
+ requeueScopeChanges(ids: Array<string | number>, options?: {
501
+ force?: boolean;
502
+ apply?: boolean;
503
+ waitForLeaseMs?: number;
504
+ }): Promise<ScopeRequeueReport>;
505
+ /**
506
+ * **`authz:reconcile --to=<driver>`** (3b-3a): la ÚNICA primitiva de
507
+ * migración y verificación del paquete, y el motivo de la fase entera —
508
+ * «todo en un driver o todo en otro, con una migración idempotente y
509
+ * bidireccional». Sustituye a `openfga:import`, que el 2k borró.
510
+ *
511
+ * Operación de PLATAFORMA, como `driver()` y `relayScopeChanges`: no lleva
512
+ * actor, no mide rangos y **no se expone por HTTP**.
513
+ *
514
+ * El driver de destino se resuelve **por nombre del registro**
515
+ * (`config.drivers[to]`), no por `config.default`: la migración de verdad
516
+ * es «el motor sigue corriendo con `database` mientras se llena el store de
517
+ * `openfga`», y con el default no habría forma de nombrar al destino. Un
518
+ * driver que no sabe reconstruirse lo dice (500 `E_AUTHZ_UNSUPPORTED`
519
+ * nombrando `reconcile`); el driver `database` es ese caso: sus tablas SON
520
+ * el origen y llenarlas desde un store es la otra dirección (3b-3b).
521
+ *
522
+ * Durante la pasada que ESCRIBE, las escrituras del motor están CONGELADAS
523
+ * (`withFrozenWrites`): un `grant` que aterrizara entre la lectura del
524
+ * origen y la escritura del destino no llegaría al destino y no aparecería
525
+ * en ningún contador. Las lecturas siguen. El `finally` descongela pase lo
526
+ * que pase.
527
+ *
528
+ * **`--dry-run` NO congela** (3b-6, panel 3 · juez §3). El verificador es
529
+ * read-only por contrato: no escribe nada, así que no tiene NADA que
530
+ * proteger, y congelar ahí sería apagar las escrituras a cambio de cero.
531
+ * Está publicado para correrlo en CI y en un cron, o sea justo el sitio
532
+ * desde el que un mecanismo de indisponibilidad se dispara solo — hoy
533
+ * contra el proceso del job, y contra la flota entera el día que el freeze
534
+ * sea durable. El único contraargumento posible —que congelar estabiliza
535
+ * sus números— no vale: los números de un verificador read-only no son una
536
+ * garantía de nada.
537
+ *
538
+ * Lo que añade el manager al reporte del driver es lo único que el driver
539
+ * no puede ver: **la ventana del relay** —los cambios del árbol encolados y
540
+ * sin aplicar, que son la deriva que el store todavía no conoce (decisión
541
+ * del dueño del 2026-08-30, consecuencia 4)— y las entradas APARCADAS, que
542
+ * no son una ventana sino una divergencia permanente.
543
+ */
544
+ reconcile(options: {
545
+ to: string;
546
+ from?: string;
547
+ } & ReconcileOptions): Promise<ReconcileReport>;
117
548
  /**
118
549
  * ¿`outer` contiene a `inner`? = `outer ∈ chain(inner)`, inclusive: un scope
119
550
  * se contiene a sí mismo y `APP_SCOPE` contiene todo. Un `inner` que el
@@ -184,6 +615,118 @@ export declare class AuthorizationManager {
184
615
  * su owner. Notifica `role_purged`. No necesita `listDenies`.
185
616
  */
186
617
  deleteScopedRole(actor: SubjectRef, roleUuid: string, options?: ScopedWriteOptions): Promise<void>;
618
+ /**
619
+ * Los roles LOCALES cuyo owner el árbol YA NO conoce, y —con `force`— su
620
+ * purga. Es el motor de `authz:catalog:prune-orphans` (3b-0 · Z2).
621
+ *
622
+ * Un rol así está DORMIDO, y «dormido» significa **exactamente** esto
623
+ * (3b-0b · AA1, auditor 3b-0): no es visible desde ningún scope vivo cuya
624
+ * cadena NO pase por su owner. No significa que no conceda. La regla única
625
+ * de visibilidad (invariante 18) pide que el owner esté en la cadena del
626
+ * scope preguntado, y **un descendiente vivo cuya ruta materializada sigue
627
+ * pasando por el owner la cumple**: ahí el rol concede, es membresía por
628
+ * los seis caminos de lectura y se puede ASIGNAR, por slug y por uuid.
629
+ * Ocurre en cuanto el consumidor borra la fila del owner sin borrar (o sin
630
+ * notificar) la de sus descendientes — el borrado en dos pasos y las rutas
631
+ * materializadas son lo normal. Por eso este barrido es destructivo de
632
+ * verdad y por eso `--dry-run` es el default: puede estar revocando
633
+ * permisos VIVOS, no recogiendo basura inerte. Lo que sí es seguro decir:
634
+ * un rol huérfano SIN asignaciones vigentes no concede nada, y ninguno
635
+ * concede en un scope cuya cadena no pase por el owner.
636
+ *
637
+ * Cada huérfano viene con `assignments` (hechos vigentes) y
638
+ * `stillGranting` (`assignments > 0`), que es la marca CONSERVADORA de
639
+ * «esto no es basura inerte»: cuenta hechos, no comprueba si el scope de
640
+ * cada uno sigue resolviendo. Falso ⇒ no concede seguro; verdadero ⇒
641
+ * míralo antes de `--force`.
642
+ *
643
+ * **Y esos hechos se los cuenta el DRIVER** (3b-2j, decisión del dueño del
644
+ * 2026-08-31 (3)), con `countRoleAssignments` del puerto. Hasta aquí los
645
+ * contaba el propio barrido en `authz_assignments` —la tabla del driver
646
+ * `database`—, así que con `openfga` en modo `facts`, donde los hechos
647
+ * viven en el store, `stillGranting` era SIEMPRE `false`: el barrido
648
+ * declaraba basura inerte, justo antes de un borrado destructivo, un rol
649
+ * que estaba concediendo (medido en el lote 2i). Un driver que no traiga
650
+ * el método deja los DOS campos en **`undefined`**, nunca en `false`: «no
651
+ * lo sé» no puede degradar a «no concede», que es exactamente el bug. Con
652
+ * `undefined` el rol no es demostrablemente inerte y el comando lo lista
653
+ * APARTE, igual que a los que sí conceden.
654
+ *
655
+ * Lo que el rol dormido sí hace en todo caso es ocupar su `(slug, nivel)`
656
+ * dentro del subárbol donde todavía se le vea, y `deleteScopedRole` no lo
657
+ * alcanza (resuelve el owner en fresco y responde 422
658
+ * `E_AUTHZ_UNKNOWN_SCOPE`). Hasta 3G esa limpieza la arrastraba
659
+ * `scopes.detached`, y ahí es donde nacieron tres de las cuatro
660
+ * regresiones de la Fase 3: la operación la dispara un TENANT, sobre un
661
+ * scope que ya no resuelve, así que hubo que inventarle una policy de
662
+ * rango sin cadena donde medirla, una enumeración del subárbol y una
663
+ * degradación — tres piezas que compuestas destruían roles de
664
+ * descendientes VIVOS. Aquí no hay nada de eso: es una operación de
665
+ * PLATAFORMA (una tarea de mantenimiento con acceso al catálogo, como
666
+ * `authz:catalog:sync`), no lleva actor y no mide rangos, exactamente como
667
+ * el `purgeRole` de último recurso que el README ya prometía. Es, junto a
668
+ * `driver()`, **API de plataforma**: se salta `requireActor` y
669
+ * `requireWithin` a propósito, así que no se expone a un controlador.
670
+ *
671
+ * `force: false` (el default, y el del comando: `--dry-run`) NO escribe:
672
+ * devuelve la lista para que un humano la mire. Con `force: true` cada rol
673
+ * se purga con `purgeRole` —atómico: asignaciones + vínculos + fila +
674
+ * versión del catálogo— y se notifica `role_purged` (sin `actor`). El
675
+ * conjunto no es atómico, y por eso el reporte dice QUÉ se purgó
676
+ * (`purged: CatalogRoleRef[]`, 3b-0b · AB3) y no cuántos: si un
677
+ * `purgeRole` falla a mitad, lo anterior ya está borrado —con el hallazgo
678
+ * de AA1 eso puede ser revocación parcial de permisos vivos— y quien
679
+ * recoge el 503 necesita la lista, no un contador. Una pasada
680
+ * interrumpida la recoge la siguiente (el orden es estable por uuid).
681
+ *
682
+ * **Dos seguros contra el barrido a ciegas**, que es el riesgo real
683
+ * (auditor 3b-0):
684
+ *
685
+ * - **Cota de purga masiva** (AA2): si TODOS los owners distintos
686
+ * resultan huérfanos, o si los huérfanos superan el 50 % de los roles
687
+ * locales, `force` es 500 `E_AUTHZ_MASS_PURGE_REFUSED` **antes de
688
+ * borrar nada**. Esa es la firma de un `resolveChain` filtrado por el
689
+ * tenant de la petición o corriendo sin contexto (comando, réplica
690
+ * atrasada): devuelve `null` para todo y la pasada se lleva el catálogo
691
+ * local de TODOS los tenants (medido: 2 de 2 roles vivos). Una poda
692
+ * grande de verdad pasa con `allowMassPurge: true`
693
+ * (`--allow-mass-purge`), que es una decisión humana. El `--dry-run` no
694
+ * lanza —es justo el diagnóstico que hay que poder mirar— pero lo
695
+ * marca en `massPurge`.
696
+ * - **Re-resolución justo antes de cada purga** (AA3): entre la lectura y
697
+ * el borrado cabe un `scopes.attached`/restore concurrente, y la
698
+ * ventana es TODA la pasada (N roles + N `resolveChain`), no un
699
+ * instante. Cada owner se vuelve a resolver en FRESCO inmediatamente
700
+ * antes de su `purgeRole`; si ha vuelto, el rol se salta y se cuenta en
701
+ * `skipped` con `reason: 'owner-came-back'`.
702
+ *
703
+ * Coste: una lectura del catálogo local + un `resolveChain` por OWNER
704
+ * DISTINTO (memoizado) + UNA llamada a `countRoleAssignments` con los
705
+ * uuids de los huérfanos (ninguna si no hay) + un `resolveChain` más por
706
+ * rol purgado (el de AA3). Es O(owners con roles locales) para mirar y
707
+ * O(roles purgados) para borrar, y corre en un comando, no en el camino de
708
+ * una petición.
709
+ */
710
+ pruneOrphanRoles(options?: {
711
+ force?: boolean;
712
+ allowMassPurge?: boolean;
713
+ }): Promise<{
714
+ orphans: Array<{
715
+ role: CatalogRole;
716
+ owner: ScopeRef;
717
+ permissions: string[];
718
+ assignments: number | undefined;
719
+ stillGranting: boolean | undefined;
720
+ }>;
721
+ purged: CatalogRoleRef[];
722
+ skipped: Array<{
723
+ role: CatalogRoleRef;
724
+ reason: 'owner-came-back';
725
+ }>;
726
+ /** ¿La pasada tiene la firma de un resolutor ciego? Con `force` exige `allowMassPurge`. */
727
+ massPurge: boolean;
728
+ dryRun: boolean;
729
+ }>;
187
730
  /**
188
731
  * Asigna un rol al holder en un scope. `role` es un `RoleQuery` (3D · M1):
189
732
  * un slug, `{ slug, scopeType }` o `{ uuid }` — esta última es la forma
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manager.ts"],"names":[],"mappings":"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"}