@hablala/api-contract 0.9.1 → 0.10.0

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 (3) hide show
  1. package/dist/index.d.ts +739 -50
  2. package/openapi.json +1014 -57
  3. package/package.json +1 -1
package/openapi.json CHANGED
@@ -730,6 +730,48 @@
730
730
  "AccountManifestSections": {
731
731
  "description": "Las secciones declarables de una cuenta (ADR-027). El `kind` fija la SUPERFICIE: una `organization` declara el diccionario (objects…), la mensajería (spaces/channels) y el acceso (roles, sso, domains, invitations); un `individual` declara su `profile` y su `privacy` (singletons). Cada sección es opcional (ausente = no gestionada). Gobernanza: la mayoría es AUTORITATIVA (lo no declarado se archiva — policies/roles/sso se BORRAN); son ADITIVAS (siembra, no expulsa) los `initialMembers` de un canal, los `domains` y las `invitations` — lifecycle, no estado deseado. Los datos (records/mensajes) no son configuración.",
732
732
  "properties": {
733
+ "actions": {
734
+ "oneOf": [
735
+ {
736
+ "items": {
737
+ "$ref": "#/components/schemas/ManifestAction"
738
+ },
739
+ "type": "array",
740
+ "x-struct": null,
741
+ "x-validate": null
742
+ },
743
+ {
744
+ "properties": {
745
+ "items": {
746
+ "items": {
747
+ "$ref": "#/components/schemas/ManifestAction"
748
+ },
749
+ "type": "array",
750
+ "x-struct": null,
751
+ "x-validate": null
752
+ },
753
+ "mode": {
754
+ "description": "`authoritative` (default): lo no declarado se archiva/borra. `additive`: solo crea/actualiza lo declarado, sin expulsar lo demás (least astonishment).",
755
+ "enum": [
756
+ "authoritative",
757
+ "additive"
758
+ ],
759
+ "type": "string",
760
+ "x-struct": null,
761
+ "x-validate": null
762
+ }
763
+ },
764
+ "required": [
765
+ "items"
766
+ ],
767
+ "type": "object",
768
+ "x-struct": null,
769
+ "x-validate": null
770
+ }
771
+ ],
772
+ "x-struct": null,
773
+ "x-validate": null
774
+ },
733
775
  "agents": {
734
776
  "oneOf": [
735
777
  {
@@ -1277,6 +1319,54 @@
1277
1319
  "x-struct": "Elixir.HablalaApiWeb.Schemas.AccountManifestSections",
1278
1320
  "x-validate": null
1279
1321
  },
1322
+ "ActionRunRequest": {
1323
+ "description": "Input de una action transaccional. `input` es el mapa que interpolan los steps (`{{input.…}}`, y `{{item.…}}` en los steps con for_each).",
1324
+ "properties": {
1325
+ "idempotency_key": {
1326
+ "description": "Clave natural para reintentos seguros (se propaga a cada step creado).",
1327
+ "type": "string",
1328
+ "x-struct": null,
1329
+ "x-validate": null
1330
+ },
1331
+ "input": {
1332
+ "description": "Los valores de entrada de la action (forma libre, definida por sus steps).",
1333
+ "type": "object",
1334
+ "x-struct": null,
1335
+ "x-validate": null
1336
+ }
1337
+ },
1338
+ "title": "ActionRunRequest",
1339
+ "type": "object",
1340
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.ActionRunRequest",
1341
+ "x-validate": null
1342
+ },
1343
+ "ActionRunResponse": {
1344
+ "properties": {
1345
+ "data": {
1346
+ "properties": {
1347
+ "results": {
1348
+ "description": "Por step_id, el/los records creados (`{id, properties}`). Un step con for_each devuelve una lista; uno simple, un objeto.",
1349
+ "type": "object",
1350
+ "x-struct": null,
1351
+ "x-validate": null
1352
+ }
1353
+ },
1354
+ "required": [
1355
+ "results"
1356
+ ],
1357
+ "type": "object",
1358
+ "x-struct": null,
1359
+ "x-validate": null
1360
+ }
1361
+ },
1362
+ "required": [
1363
+ "data"
1364
+ ],
1365
+ "title": "ActionRunResponse",
1366
+ "type": "object",
1367
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.ActionRunResponse",
1368
+ "x-validate": null
1369
+ },
1280
1370
  "AddMemberRequest": {
1281
1371
  "description": "Añade un usuario del tenant a una conversación (invitar a un canal).",
1282
1372
  "properties": {
@@ -1698,6 +1788,134 @@
1698
1788
  "x-struct": "Elixir.HablalaApiWeb.Schemas.AgentsResponse",
1699
1789
  "x-validate": null
1700
1790
  },
1791
+ "AggregateQueryRequest": {
1792
+ "description": "Aggregation query: agrupa records por `dimensions` y calcula `measures` (count/sum/avg/min/max), bajo la misma gobernanza (RBAC + ABAC default-deny) que la lectura puntual. El par canónico measures + dimensions del semantic layer (Cube.dev).",
1793
+ "properties": {
1794
+ "dimensions": {
1795
+ "description": "Los attributes por los que agrupar (GROUP BY).",
1796
+ "items": {
1797
+ "properties": {
1798
+ "attr": {
1799
+ "description": "Slug del attribute a agrupar.",
1800
+ "type": "string",
1801
+ "x-struct": null,
1802
+ "x-validate": null
1803
+ },
1804
+ "granularity": {
1805
+ "description": "Solo para date/timestamp (time dimension): trunca el valor a ese bucket.",
1806
+ "enum": [
1807
+ "day",
1808
+ "week",
1809
+ "month",
1810
+ "quarter",
1811
+ "year"
1812
+ ],
1813
+ "type": "string",
1814
+ "x-struct": null,
1815
+ "x-validate": null
1816
+ }
1817
+ },
1818
+ "required": [
1819
+ "attr"
1820
+ ],
1821
+ "type": "object",
1822
+ "x-struct": null,
1823
+ "x-validate": null
1824
+ },
1825
+ "type": "array",
1826
+ "x-struct": null,
1827
+ "x-validate": null
1828
+ },
1829
+ "measures": {
1830
+ "description": "Las agregaciones a calcular (al menos una).",
1831
+ "items": {
1832
+ "properties": {
1833
+ "as": {
1834
+ "description": "Alias de salida (default: `count` o `<fn>_<attr>`).",
1835
+ "type": "string",
1836
+ "x-struct": null,
1837
+ "x-validate": null
1838
+ },
1839
+ "attr": {
1840
+ "description": "Slug del attribute a agregar (number para sum/avg; number/date/timestamp para min/max). Omitido solo en `count`.",
1841
+ "type": "string",
1842
+ "x-struct": null,
1843
+ "x-validate": null
1844
+ },
1845
+ "fn": {
1846
+ "description": "La función de agregación. `count` no lleva `attr`.",
1847
+ "enum": [
1848
+ "count",
1849
+ "sum",
1850
+ "avg",
1851
+ "min",
1852
+ "max"
1853
+ ],
1854
+ "type": "string",
1855
+ "x-struct": null,
1856
+ "x-validate": null
1857
+ }
1858
+ },
1859
+ "required": [
1860
+ "fn"
1861
+ ],
1862
+ "type": "object",
1863
+ "x-struct": null,
1864
+ "x-validate": null
1865
+ },
1866
+ "type": "array",
1867
+ "x-struct": null,
1868
+ "x-validate": null
1869
+ },
1870
+ "object": {
1871
+ "description": "Slug del objeto raíz (requerido).",
1872
+ "type": "string",
1873
+ "x-struct": null,
1874
+ "x-validate": null
1875
+ },
1876
+ "where": {
1877
+ "description": "Mismo formato que en la consulta puntual: filtra ANTES de agregar.",
1878
+ "items": {
1879
+ "type": "object",
1880
+ "x-struct": null,
1881
+ "x-validate": null
1882
+ },
1883
+ "type": "array",
1884
+ "x-struct": null,
1885
+ "x-validate": null
1886
+ }
1887
+ },
1888
+ "required": [
1889
+ "object",
1890
+ "measures"
1891
+ ],
1892
+ "title": "AggregateQueryRequest",
1893
+ "type": "object",
1894
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.AggregateQueryRequest",
1895
+ "x-validate": null
1896
+ },
1897
+ "AggregateResultResponse": {
1898
+ "properties": {
1899
+ "data": {
1900
+ "description": "Un grupo por combinación de dimensions (o un solo grupo con los totales si no hay dimensions). Cada grupo es un mapa: cada dimension por su slug y cada measure por su alias de salida.",
1901
+ "items": {
1902
+ "type": "object",
1903
+ "x-struct": null,
1904
+ "x-validate": null
1905
+ },
1906
+ "type": "array",
1907
+ "x-struct": null,
1908
+ "x-validate": null
1909
+ }
1910
+ },
1911
+ "required": [
1912
+ "data"
1913
+ ],
1914
+ "title": "AggregateResultResponse",
1915
+ "type": "object",
1916
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.AggregateResultResponse",
1917
+ "x-validate": null
1918
+ },
1701
1919
  "ApiKey": {
1702
1920
  "description": "Metadatos de una API key de la Public API. El secreto en claro NO se incluye aquí — solo se devuelve una vez, al crearla.",
1703
1921
  "properties": {
@@ -2030,6 +2248,13 @@
2030
2248
  "x-struct": null,
2031
2249
  "x-validate": null
2032
2250
  },
2251
+ "seatsPerSlot": {
2252
+ "description": "Capacidad del slot: cuántas citas solapadas del mismo organizador caben a la vez (Cal.com seats per time slot). 1 = no-solape estricto; N = hasta N concurrentes.",
2253
+ "minimum": 1,
2254
+ "type": "integer",
2255
+ "x-struct": null,
2256
+ "x-validate": null
2257
+ },
2033
2258
  "startsAt": {
2034
2259
  "format": "date-time",
2035
2260
  "type": "string",
@@ -2100,6 +2325,13 @@
2100
2325
  "x-struct": null,
2101
2326
  "x-validate": null
2102
2327
  },
2328
+ "seatsPerSlot": {
2329
+ "description": "Capacidad del slot (default 1 = no-solape estricto). N permite hasta N citas solapadas del mismo organizador (aforo, clases, atención en paralelo).",
2330
+ "minimum": 1,
2331
+ "type": "integer",
2332
+ "x-struct": null,
2333
+ "x-validate": null
2334
+ },
2103
2335
  "startsAt": {
2104
2336
  "format": "date-time",
2105
2337
  "type": "string",
@@ -6734,6 +6966,60 @@
6734
6966
  "x-struct": "Elixir.HablalaApiWeb.Schemas.MachineOrganizationResponse",
6735
6967
  "x-validate": null
6736
6968
  },
6969
+ "ManifestAction": {
6970
+ "description": "Una action transaccional del tenant declarada (sección `actions/`), identificada por `slug`. Ejecuta sus `steps` en UNA transacción (todo-o-nada) al invocar `POST /v1/actions/:slug`: crear una cabecera + N líneas de forma atómica (el caso `create_rental` de una app interna). Cada step declara un `object` del diccionario y las `properties` a escribir, con interpolación `{{input.…}}`, `{{steps.<id>.id}}` (ref entre steps) y `{{item.…}}` en un step con `for_each`. Sección AUTORITATIVA: retirarla del manifiesto la archiva. `description`/`synonyms` son el contexto con el que los agentes LLM la descubren vía MCP (obligatoria la descripción, como el resto del diccionario).",
6971
+ "properties": {
6972
+ "description": {
6973
+ "description": "Qué hace la action (contexto para humanos y agentes LLM). Obligatoria al crear.",
6974
+ "type": "string",
6975
+ "x-struct": null,
6976
+ "x-validate": null
6977
+ },
6978
+ "slug": {
6979
+ "description": "Identidad estable snake_case, única por organización (match key).",
6980
+ "type": "string",
6981
+ "x-struct": null,
6982
+ "x-validate": null
6983
+ },
6984
+ "steps": {
6985
+ "description": "Lista NO vacía de pasos. Cada paso: `id` (opcional, para refs `{{steps.<id>.id}}`), `object` (slug del diccionario), `properties` (mapa slug→valor con interpolación) y opcionalmente `for_each` (una ruta del input que expande el step en N records).",
6986
+ "items": {
6987
+ "additionalProperties": true,
6988
+ "type": "object",
6989
+ "x-struct": null,
6990
+ "x-validate": null
6991
+ },
6992
+ "type": "array",
6993
+ "x-struct": null,
6994
+ "x-validate": null
6995
+ },
6996
+ "synonyms": {
6997
+ "description": "Sinónimos para el descubrimiento por búsqueda/LLM.",
6998
+ "items": {
6999
+ "type": "string",
7000
+ "x-struct": null,
7001
+ "x-validate": null
7002
+ },
7003
+ "type": "array",
7004
+ "x-struct": null,
7005
+ "x-validate": null
7006
+ },
7007
+ "title": {
7008
+ "description": "Nombre visible; si se omite, se deriva del slug.",
7009
+ "type": "string",
7010
+ "x-struct": null,
7011
+ "x-validate": null
7012
+ }
7013
+ },
7014
+ "required": [
7015
+ "slug",
7016
+ "steps"
7017
+ ],
7018
+ "title": "ManifestAction",
7019
+ "type": "object",
7020
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.ManifestAction",
7021
+ "x-validate": null
7022
+ },
6737
7023
  "ManifestAgent": {
6738
7024
  "description": "Un agente de IA declarado, identificado por `handle`. Archivar (no declararlo) lo revoca. `ownerUserId` (id público `user_…`) es obligatorio al crear con un access token de máquina; con un usuario, el creador es el dueño por defecto.",
6739
7025
  "properties": {
@@ -7845,49 +8131,178 @@
7845
8131
  "x-struct": "Elixir.HablalaApiWeb.Schemas.MediaResponse",
7846
8132
  "x-validate": null
7847
8133
  },
7848
- "Membership": {
8134
+ "Member": {
8135
+ "description": "Un miembro de la organización: identidad legible + sus roles (sin secretos).",
7849
8136
  "properties": {
7850
- "avatarUrl": {
7851
- "description": "Avatar override para esta org; `null` usa el global del usuario.",
7852
- "nullable": true,
7853
- "type": "string",
7854
- "x-struct": null,
7855
- "x-validate": null
7856
- },
7857
8137
  "displayName": {
7858
- "description": "Nombre visible en esta org (override del `name` global).",
7859
8138
  "nullable": true,
7860
8139
  "type": "string",
7861
8140
  "x-struct": null,
7862
8141
  "x-validate": null
7863
8142
  },
7864
8143
  "email": {
7865
- "description": "Email corporativo del miembro (dato de org entre colegas, acotado al tenant). `null` si la cuenta no tiene email. No confundir con el perfil público `user`, que no lleva PII.",
7866
- "format": "email",
7867
8144
  "nullable": true,
7868
8145
  "type": "string",
7869
8146
  "x-struct": null,
7870
8147
  "x-validate": null
7871
8148
  },
7872
8149
  "id": {
8150
+ "description": "Id de la membresía (`mbr_…`).",
7873
8151
  "type": "string",
7874
8152
  "x-struct": null,
7875
8153
  "x-validate": null
7876
8154
  },
7877
- "insertedAt": {
7878
- "format": "date-time",
8155
+ "roles": {
8156
+ "description": "Los roles del miembro por nombre (owner/admin/member o custom).",
8157
+ "items": {
8158
+ "type": "string",
8159
+ "x-struct": null,
8160
+ "x-validate": null
8161
+ },
8162
+ "type": "array",
8163
+ "x-struct": null,
8164
+ "x-validate": null
8165
+ }
8166
+ },
8167
+ "required": [
8168
+ "id",
8169
+ "roles"
8170
+ ],
8171
+ "title": "Member",
8172
+ "type": "object",
8173
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.Member",
8174
+ "x-validate": null
8175
+ },
8176
+ "MemberLoginRequest": {
8177
+ "description": "Credenciales de un miembro (empleado que opera la org). La organización sale de la API key.",
8178
+ "properties": {
8179
+ "email": {
8180
+ "format": "email",
7879
8181
  "type": "string",
7880
8182
  "x-struct": null,
7881
8183
  "x-validate": null
7882
8184
  },
7883
- "organizationId": {
8185
+ "password": {
8186
+ "format": "password",
7884
8187
  "type": "string",
7885
8188
  "x-struct": null,
7886
8189
  "x-validate": null
7887
- },
7888
- "roles": {
7889
- "items": {
7890
- "$ref": "#/components/schemas/RoleRef"
8190
+ }
8191
+ },
8192
+ "required": [
8193
+ "email",
8194
+ "password"
8195
+ ],
8196
+ "title": "MemberLoginRequest",
8197
+ "type": "object",
8198
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.MemberLoginRequest",
8199
+ "x-validate": null
8200
+ },
8201
+ "MemberResponse": {
8202
+ "properties": {
8203
+ "data": {
8204
+ "$ref": "#/components/schemas/Member"
8205
+ }
8206
+ },
8207
+ "required": [
8208
+ "data"
8209
+ ],
8210
+ "title": "MemberResponse",
8211
+ "type": "object",
8212
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.MemberResponse",
8213
+ "x-validate": null
8214
+ },
8215
+ "MemberSession": {
8216
+ "properties": {
8217
+ "expiresAt": {
8218
+ "format": "date-time",
8219
+ "nullable": true,
8220
+ "type": "string",
8221
+ "x-struct": null,
8222
+ "x-validate": null
8223
+ },
8224
+ "member": {
8225
+ "$ref": "#/components/schemas/Member"
8226
+ },
8227
+ "prefix": {
8228
+ "nullable": true,
8229
+ "type": "string",
8230
+ "x-struct": null,
8231
+ "x-validate": null
8232
+ },
8233
+ "token": {
8234
+ "description": "El member session token en claro (`mem_…`), legible SOLO en esta respuesta.",
8235
+ "type": "string",
8236
+ "x-struct": null,
8237
+ "x-validate": null
8238
+ }
8239
+ },
8240
+ "required": [
8241
+ "token",
8242
+ "member"
8243
+ ],
8244
+ "title": "MemberSession",
8245
+ "type": "object",
8246
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.MemberSession",
8247
+ "x-validate": null
8248
+ },
8249
+ "MemberSessionResponse": {
8250
+ "properties": {
8251
+ "data": {
8252
+ "$ref": "#/components/schemas/MemberSession"
8253
+ }
8254
+ },
8255
+ "required": [
8256
+ "data"
8257
+ ],
8258
+ "title": "MemberSessionResponse",
8259
+ "type": "object",
8260
+ "x-struct": "Elixir.HablalaApiWeb.Schemas.MemberSessionResponse",
8261
+ "x-validate": null
8262
+ },
8263
+ "Membership": {
8264
+ "properties": {
8265
+ "avatarUrl": {
8266
+ "description": "Avatar override para esta org; `null` usa el global del usuario.",
8267
+ "nullable": true,
8268
+ "type": "string",
8269
+ "x-struct": null,
8270
+ "x-validate": null
8271
+ },
8272
+ "displayName": {
8273
+ "description": "Nombre visible en esta org (override del `name` global).",
8274
+ "nullable": true,
8275
+ "type": "string",
8276
+ "x-struct": null,
8277
+ "x-validate": null
8278
+ },
8279
+ "email": {
8280
+ "description": "Email corporativo del miembro (dato de org entre colegas, acotado al tenant). `null` si la cuenta no tiene email. No confundir con el perfil público `user`, que no lleva PII.",
8281
+ "format": "email",
8282
+ "nullable": true,
8283
+ "type": "string",
8284
+ "x-struct": null,
8285
+ "x-validate": null
8286
+ },
8287
+ "id": {
8288
+ "type": "string",
8289
+ "x-struct": null,
8290
+ "x-validate": null
8291
+ },
8292
+ "insertedAt": {
8293
+ "format": "date-time",
8294
+ "type": "string",
8295
+ "x-struct": null,
8296
+ "x-validate": null
8297
+ },
8298
+ "organizationId": {
8299
+ "type": "string",
8300
+ "x-struct": null,
8301
+ "x-validate": null
8302
+ },
8303
+ "roles": {
8304
+ "items": {
8305
+ "$ref": "#/components/schemas/RoleRef"
7891
8306
  },
7892
8307
  "type": "array",
7893
8308
  "x-struct": null,
@@ -13361,6 +13776,11 @@
13361
13776
  "description": "End-user session token: `Authorization: Bearer <sess_…>`.",
13362
13777
  "scheme": "bearer",
13363
13778
  "type": "http"
13779
+ },
13780
+ "memberToken": {
13781
+ "description": "Member session token: `Authorization: Bearer <mem_…>` (empleado que opera la org).",
13782
+ "scheme": "bearer",
13783
+ "type": "http"
13364
13784
  }
13365
13785
  }
13366
13786
  },
@@ -13582,6 +14002,148 @@
13582
14002
  ]
13583
14003
  }
13584
14004
  },
14005
+ "/v1/actions/{slug}": {
14006
+ "post": {
14007
+ "callbacks": {},
14008
+ "description": "Corre los steps de la action `slug` en UNA transacción (todo-o-nada), interpolando el input, y devuelve los records creados por step. `create_rental`/`register_return` y similares. Gate: records:create.",
14009
+ "operationId": "post /v1/actions/{slug}",
14010
+ "parameters": [
14011
+ {
14012
+ "description": "Slug de la action a ejecutar.",
14013
+ "in": "path",
14014
+ "name": "slug",
14015
+ "required": true,
14016
+ "schema": {
14017
+ "type": "string",
14018
+ "x-struct": null,
14019
+ "x-validate": null
14020
+ }
14021
+ }
14022
+ ],
14023
+ "requestBody": {
14024
+ "content": {
14025
+ "application/json": {
14026
+ "schema": {
14027
+ "$ref": "#/components/schemas/ActionRunRequest"
14028
+ }
14029
+ }
14030
+ },
14031
+ "description": "Input de la action",
14032
+ "required": false
14033
+ },
14034
+ "responses": {
14035
+ "200": {
14036
+ "content": {
14037
+ "application/json": {
14038
+ "schema": {
14039
+ "$ref": "#/components/schemas/ActionRunResponse"
14040
+ }
14041
+ }
14042
+ },
14043
+ "description": "Resultado por step"
14044
+ },
14045
+ "403": {
14046
+ "content": {
14047
+ "application/json": {
14048
+ "schema": {
14049
+ "$ref": "#/components/schemas/Error"
14050
+ }
14051
+ }
14052
+ },
14053
+ "description": "Sin permiso"
14054
+ },
14055
+ "404": {
14056
+ "content": {
14057
+ "application/json": {
14058
+ "schema": {
14059
+ "$ref": "#/components/schemas/Error"
14060
+ }
14061
+ }
14062
+ },
14063
+ "description": "Action desconocida"
14064
+ },
14065
+ "422": {
14066
+ "content": {
14067
+ "application/json": {
14068
+ "schema": {
14069
+ "$ref": "#/components/schemas/Error"
14070
+ }
14071
+ }
14072
+ },
14073
+ "description": "Fallo de un step (rollback total)"
14074
+ }
14075
+ },
14076
+ "summary": "Ejecutar una action transaccional",
14077
+ "tags": [
14078
+ "actions"
14079
+ ]
14080
+ }
14081
+ },
14082
+ "/v1/aggregate": {
14083
+ "post": {
14084
+ "callbacks": {},
14085
+ "description": "Agrupa records por `dimensions` y calcula `measures` (count/sum/avg/min/max), bajo la misma gobernanza (RBAC + ABAC default-deny) que la lectura puntual. Reemplaza los reportes que serían RPCs de SQL por-tenant.",
14086
+ "operationId": "post /v1/aggregate",
14087
+ "parameters": [],
14088
+ "requestBody": {
14089
+ "content": {
14090
+ "application/json": {
14091
+ "schema": {
14092
+ "$ref": "#/components/schemas/AggregateQueryRequest"
14093
+ }
14094
+ }
14095
+ },
14096
+ "description": "Aggregation query",
14097
+ "required": false
14098
+ },
14099
+ "responses": {
14100
+ "200": {
14101
+ "content": {
14102
+ "application/json": {
14103
+ "schema": {
14104
+ "$ref": "#/components/schemas/AggregateResultResponse"
14105
+ }
14106
+ }
14107
+ },
14108
+ "description": "Grupos agregados"
14109
+ },
14110
+ "403": {
14111
+ "content": {
14112
+ "application/json": {
14113
+ "schema": {
14114
+ "$ref": "#/components/schemas/Error"
14115
+ }
14116
+ }
14117
+ },
14118
+ "description": "Sin permiso"
14119
+ },
14120
+ "404": {
14121
+ "content": {
14122
+ "application/json": {
14123
+ "schema": {
14124
+ "$ref": "#/components/schemas/Error"
14125
+ }
14126
+ }
14127
+ },
14128
+ "description": "Objeto desconocido"
14129
+ },
14130
+ "422": {
14131
+ "content": {
14132
+ "application/json": {
14133
+ "schema": {
14134
+ "$ref": "#/components/schemas/Error"
14135
+ }
14136
+ }
14137
+ },
14138
+ "description": "Consulta inválida"
14139
+ }
14140
+ },
14141
+ "summary": "Ejecutar una aggregation query",
14142
+ "tags": [
14143
+ "query"
14144
+ ]
14145
+ }
14146
+ },
13585
14147
  "/v1/device-links": {
13586
14148
  "post": {
13587
14149
  "callbacks": {},
@@ -16341,17 +16903,205 @@
16341
16903
  "required": false
16342
16904
  },
16343
16905
  "responses": {
16344
- "200": {
16906
+ "200": {
16907
+ "content": {
16908
+ "application/json": {
16909
+ "schema": {
16910
+ "$ref": "#/components/schemas/PresignResponse"
16911
+ }
16912
+ }
16913
+ },
16914
+ "description": "Sobre de subida prefirmado"
16915
+ },
16916
+ "415": {
16917
+ "content": {
16918
+ "application/json": {
16919
+ "schema": {
16920
+ "$ref": "#/components/schemas/Error"
16921
+ }
16922
+ }
16923
+ },
16924
+ "description": "Tipo de archivo no soportado"
16925
+ }
16926
+ },
16927
+ "summary": "Pedir un sobre de subida prefirmado (adjunto personal)",
16928
+ "tags": [
16929
+ "personal uploads"
16930
+ ]
16931
+ }
16932
+ },
16933
+ "/v1/me/usernames/available": {
16934
+ "get": {
16935
+ "callbacks": {},
16936
+ "operationId": "get /v1/me/usernames/available",
16937
+ "parameters": [
16938
+ {
16939
+ "description": "Handle a comprobar.",
16940
+ "in": "query",
16941
+ "name": "username",
16942
+ "required": true,
16943
+ "schema": {
16944
+ "type": "string",
16945
+ "x-struct": null,
16946
+ "x-validate": null
16947
+ }
16948
+ }
16949
+ ],
16950
+ "responses": {
16951
+ "200": {
16952
+ "content": {
16953
+ "application/json": {
16954
+ "schema": {
16955
+ "$ref": "#/components/schemas/UsernameAvailableResponse"
16956
+ }
16957
+ }
16958
+ },
16959
+ "description": "Disponibilidad"
16960
+ }
16961
+ },
16962
+ "summary": "¿Está disponible este username? (check en vivo del alta/cambio)",
16963
+ "tags": [
16964
+ "people"
16965
+ ]
16966
+ }
16967
+ },
16968
+ "/v1/members/me": {
16969
+ "get": {
16970
+ "callbacks": {},
16971
+ "description": "Devuelve el miembro de la member session actual: id, email, nombre visible y sus roles. El equivalente a `getCurrentUser` de una app interna.",
16972
+ "operationId": "get /v1/members/me",
16973
+ "parameters": [],
16974
+ "responses": {
16975
+ "200": {
16976
+ "content": {
16977
+ "application/json": {
16978
+ "schema": {
16979
+ "$ref": "#/components/schemas/MemberResponse"
16980
+ }
16981
+ }
16982
+ },
16983
+ "description": "El miembro actual"
16984
+ },
16985
+ "401": {
16986
+ "content": {
16987
+ "application/json": {
16988
+ "schema": {
16989
+ "$ref": "#/components/schemas/Error"
16990
+ }
16991
+ }
16992
+ },
16993
+ "description": "Sesión inválida"
16994
+ }
16995
+ },
16996
+ "security": [
16997
+ {
16998
+ "memberToken": []
16999
+ }
17000
+ ],
17001
+ "summary": "El miembro autenticado (quién soy)",
17002
+ "tags": [
17003
+ "members"
17004
+ ]
17005
+ }
17006
+ },
17007
+ "/v1/members/session": {
17008
+ "delete": {
17009
+ "callbacks": {},
17010
+ "description": "Revoca el member session token. Idempotente.",
17011
+ "operationId": "delete /v1/members/session",
17012
+ "parameters": [],
17013
+ "responses": {
17014
+ "204": {
17015
+ "description": "Sesión cerrada"
17016
+ }
17017
+ },
17018
+ "security": [
17019
+ {
17020
+ "memberToken": []
17021
+ }
17022
+ ],
17023
+ "summary": "Cerrar la sesión de miembro (logout)",
17024
+ "tags": [
17025
+ "members"
17026
+ ]
17027
+ },
17028
+ "post": {
17029
+ "callbacks": {},
17030
+ "description": "Autentica a un miembro humano (empleado que opera la org) por email+password y devuelve un member session token (`mem_…`) que porta su rol. La organización sale de la API key de la app. Es el login de operador de una app interna (patrón Organizations+Members).",
17031
+ "operationId": "post /v1/members/session",
17032
+ "parameters": [],
17033
+ "requestBody": {
17034
+ "content": {
17035
+ "application/json": {
17036
+ "schema": {
17037
+ "$ref": "#/components/schemas/MemberLoginRequest"
17038
+ }
17039
+ }
17040
+ },
17041
+ "description": "Credenciales del miembro",
17042
+ "required": false
17043
+ },
17044
+ "responses": {
17045
+ "201": {
17046
+ "content": {
17047
+ "application/json": {
17048
+ "schema": {
17049
+ "$ref": "#/components/schemas/MemberSessionResponse"
17050
+ }
17051
+ }
17052
+ },
17053
+ "description": "Sesión de miembro"
17054
+ },
17055
+ "401": {
17056
+ "content": {
17057
+ "application/json": {
17058
+ "schema": {
17059
+ "$ref": "#/components/schemas/Error"
17060
+ }
17061
+ }
17062
+ },
17063
+ "description": "API key o credenciales inválidas"
17064
+ },
17065
+ "422": {
17066
+ "content": {
17067
+ "application/json": {
17068
+ "schema": {
17069
+ "$ref": "#/components/schemas/Error"
17070
+ }
17071
+ }
17072
+ },
17073
+ "description": "Datos inválidos"
17074
+ }
17075
+ },
17076
+ "security": [
17077
+ {
17078
+ "apiKey": []
17079
+ }
17080
+ ],
17081
+ "summary": "Iniciar sesión de un miembro de la organización (login)",
17082
+ "tags": [
17083
+ "members"
17084
+ ]
17085
+ }
17086
+ },
17087
+ "/v1/members/session/refresh": {
17088
+ "post": {
17089
+ "callbacks": {},
17090
+ "description": "Rota el member session token: revoca el actual y emite uno nuevo para la misma membresía (patrón WorkOS refresh). Autenticado por el `mem_` actual.",
17091
+ "operationId": "post /v1/members/session/refresh",
17092
+ "parameters": [],
17093
+ "responses": {
17094
+ "201": {
16345
17095
  "content": {
16346
17096
  "application/json": {
16347
17097
  "schema": {
16348
- "$ref": "#/components/schemas/PresignResponse"
17098
+ "$ref": "#/components/schemas/MemberSessionResponse"
16349
17099
  }
16350
17100
  }
16351
17101
  },
16352
- "description": "Sobre de subida prefirmado"
17102
+ "description": "Nueva sesión"
16353
17103
  },
16354
- "415": {
17104
+ "401": {
16355
17105
  "content": {
16356
17106
  "application/json": {
16357
17107
  "schema": {
@@ -16359,47 +17109,17 @@
16359
17109
  }
16360
17110
  }
16361
17111
  },
16362
- "description": "Tipo de archivo no soportado"
17112
+ "description": "Sesión inválida"
16363
17113
  }
16364
17114
  },
16365
- "summary": "Pedir un sobre de subida prefirmado (adjunto personal)",
16366
- "tags": [
16367
- "personal uploads"
16368
- ]
16369
- }
16370
- },
16371
- "/v1/me/usernames/available": {
16372
- "get": {
16373
- "callbacks": {},
16374
- "operationId": "get /v1/me/usernames/available",
16375
- "parameters": [
17115
+ "security": [
16376
17116
  {
16377
- "description": "Handle a comprobar.",
16378
- "in": "query",
16379
- "name": "username",
16380
- "required": true,
16381
- "schema": {
16382
- "type": "string",
16383
- "x-struct": null,
16384
- "x-validate": null
16385
- }
17117
+ "memberToken": []
16386
17118
  }
16387
17119
  ],
16388
- "responses": {
16389
- "200": {
16390
- "content": {
16391
- "application/json": {
16392
- "schema": {
16393
- "$ref": "#/components/schemas/UsernameAvailableResponse"
16394
- }
16395
- }
16396
- },
16397
- "description": "Disponibilidad"
16398
- }
16399
- },
16400
- "summary": "¿Está disponible este username? (check en vivo del alta/cambio)",
17120
+ "summary": "Renovar la sesión de miembro",
16401
17121
  "tags": [
16402
- "people"
17122
+ "members"
16403
17123
  ]
16404
17124
  }
16405
17125
  },
@@ -18966,6 +19686,83 @@
18966
19686
  ]
18967
19687
  }
18968
19688
  },
19689
+ "/v1/organizations/{organization_id}/aggregate": {
19690
+ "post": {
19691
+ "callbacks": {},
19692
+ "description": "Agrupa records por `dimensions` y calcula `measures` (count/sum/avg/min/max), bajo la misma gobernanza (RBAC + ABAC default-deny) que la lectura puntual. Reemplaza los reportes que serían RPCs de SQL por-tenant.",
19693
+ "operationId": "post /v1/organizations/{organization_id}/aggregate",
19694
+ "parameters": [
19695
+ {
19696
+ "description": "",
19697
+ "in": "path",
19698
+ "name": "organization_id",
19699
+ "required": true,
19700
+ "schema": {
19701
+ "type": "string",
19702
+ "x-struct": null,
19703
+ "x-validate": null
19704
+ }
19705
+ }
19706
+ ],
19707
+ "requestBody": {
19708
+ "content": {
19709
+ "application/json": {
19710
+ "schema": {
19711
+ "$ref": "#/components/schemas/AggregateQueryRequest"
19712
+ }
19713
+ }
19714
+ },
19715
+ "description": "Aggregation query",
19716
+ "required": false
19717
+ },
19718
+ "responses": {
19719
+ "200": {
19720
+ "content": {
19721
+ "application/json": {
19722
+ "schema": {
19723
+ "$ref": "#/components/schemas/AggregateResultResponse"
19724
+ }
19725
+ }
19726
+ },
19727
+ "description": "Grupos agregados"
19728
+ },
19729
+ "403": {
19730
+ "content": {
19731
+ "application/json": {
19732
+ "schema": {
19733
+ "$ref": "#/components/schemas/Error"
19734
+ }
19735
+ }
19736
+ },
19737
+ "description": "Sin permiso"
19738
+ },
19739
+ "404": {
19740
+ "content": {
19741
+ "application/json": {
19742
+ "schema": {
19743
+ "$ref": "#/components/schemas/Error"
19744
+ }
19745
+ }
19746
+ },
19747
+ "description": "Objeto desconocido"
19748
+ },
19749
+ "422": {
19750
+ "content": {
19751
+ "application/json": {
19752
+ "schema": {
19753
+ "$ref": "#/components/schemas/Error"
19754
+ }
19755
+ }
19756
+ },
19757
+ "description": "Consulta inválida"
19758
+ }
19759
+ },
19760
+ "summary": "Ejecutar una aggregation query",
19761
+ "tags": [
19762
+ "query"
19763
+ ]
19764
+ }
19765
+ },
18969
19766
  "/v1/organizations/{organization_id}/api-keys": {
18970
19767
  "get": {
18971
19768
  "callbacks": {},
@@ -29338,6 +30135,86 @@
29338
30135
  ]
29339
30136
  }
29340
30137
  },
30138
+ "/v1/public/aggregate": {
30139
+ "post": {
30140
+ "callbacks": {},
30141
+ "description": "Agrupa records por `dimensions` y calcula `measures` (count/sum/avg/min/max), autenticado por una API key. Bajo el MISMO default-deny que la lectura: solo agrega lo que las policies exponen al principal `public`/`end_user`.",
30142
+ "operationId": "post /v1/public/aggregate",
30143
+ "parameters": [],
30144
+ "requestBody": {
30145
+ "content": {
30146
+ "application/json": {
30147
+ "schema": {
30148
+ "$ref": "#/components/schemas/AggregateQueryRequest"
30149
+ }
30150
+ }
30151
+ },
30152
+ "description": "Aggregation query",
30153
+ "required": false
30154
+ },
30155
+ "responses": {
30156
+ "200": {
30157
+ "content": {
30158
+ "application/json": {
30159
+ "schema": {
30160
+ "$ref": "#/components/schemas/AggregateResultResponse"
30161
+ }
30162
+ }
30163
+ },
30164
+ "description": "Grupos agregados"
30165
+ },
30166
+ "401": {
30167
+ "content": {
30168
+ "application/json": {
30169
+ "schema": {
30170
+ "$ref": "#/components/schemas/Error"
30171
+ }
30172
+ }
30173
+ },
30174
+ "description": "Token inválido"
30175
+ },
30176
+ "403": {
30177
+ "content": {
30178
+ "application/json": {
30179
+ "schema": {
30180
+ "$ref": "#/components/schemas/Error"
30181
+ }
30182
+ }
30183
+ },
30184
+ "description": "Sin permiso"
30185
+ },
30186
+ "404": {
30187
+ "content": {
30188
+ "application/json": {
30189
+ "schema": {
30190
+ "$ref": "#/components/schemas/Error"
30191
+ }
30192
+ }
30193
+ },
30194
+ "description": "Objeto o tenant desconocido"
30195
+ },
30196
+ "422": {
30197
+ "content": {
30198
+ "application/json": {
30199
+ "schema": {
30200
+ "$ref": "#/components/schemas/Error"
30201
+ }
30202
+ }
30203
+ },
30204
+ "description": "Consulta inválida"
30205
+ }
30206
+ },
30207
+ "security": [
30208
+ {
30209
+ "apiKey": []
30210
+ }
30211
+ ],
30212
+ "summary": "Agregar por la Data API pública (reportes)",
30213
+ "tags": [
30214
+ "public"
30215
+ ]
30216
+ }
30217
+ },
29341
30218
  "/v1/public/end-users": {
29342
30219
  "post": {
29343
30220
  "callbacks": {},
@@ -29478,6 +30355,86 @@
29478
30355
  ]
29479
30356
  }
29480
30357
  },
30358
+ "/v1/public/me/aggregate": {
30359
+ "post": {
30360
+ "callbacks": {},
30361
+ "description": "Agrupa records por `dimensions` y calcula `measures` (count/sum/avg/min/max), autenticado por una API key. Bajo el MISMO default-deny que la lectura: solo agrega lo que las policies exponen al principal `public`/`end_user`.",
30362
+ "operationId": "post /v1/public/me/aggregate",
30363
+ "parameters": [],
30364
+ "requestBody": {
30365
+ "content": {
30366
+ "application/json": {
30367
+ "schema": {
30368
+ "$ref": "#/components/schemas/AggregateQueryRequest"
30369
+ }
30370
+ }
30371
+ },
30372
+ "description": "Aggregation query",
30373
+ "required": false
30374
+ },
30375
+ "responses": {
30376
+ "200": {
30377
+ "content": {
30378
+ "application/json": {
30379
+ "schema": {
30380
+ "$ref": "#/components/schemas/AggregateResultResponse"
30381
+ }
30382
+ }
30383
+ },
30384
+ "description": "Grupos agregados"
30385
+ },
30386
+ "401": {
30387
+ "content": {
30388
+ "application/json": {
30389
+ "schema": {
30390
+ "$ref": "#/components/schemas/Error"
30391
+ }
30392
+ }
30393
+ },
30394
+ "description": "Token inválido"
30395
+ },
30396
+ "403": {
30397
+ "content": {
30398
+ "application/json": {
30399
+ "schema": {
30400
+ "$ref": "#/components/schemas/Error"
30401
+ }
30402
+ }
30403
+ },
30404
+ "description": "Sin permiso"
30405
+ },
30406
+ "404": {
30407
+ "content": {
30408
+ "application/json": {
30409
+ "schema": {
30410
+ "$ref": "#/components/schemas/Error"
30411
+ }
30412
+ }
30413
+ },
30414
+ "description": "Objeto o tenant desconocido"
30415
+ },
30416
+ "422": {
30417
+ "content": {
30418
+ "application/json": {
30419
+ "schema": {
30420
+ "$ref": "#/components/schemas/Error"
30421
+ }
30422
+ }
30423
+ },
30424
+ "description": "Consulta inválida"
30425
+ }
30426
+ },
30427
+ "security": [
30428
+ {
30429
+ "apiKey": []
30430
+ }
30431
+ ],
30432
+ "summary": "Agregar por la Data API pública (reportes)",
30433
+ "tags": [
30434
+ "public"
30435
+ ]
30436
+ }
30437
+ },
29481
30438
  "/v1/public/me/checkout": {
29482
30439
  "post": {
29483
30440
  "callbacks": {},