@hablala/api-contract 0.4.0 → 0.5.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.
- package/dist/index.d.ts +81 -42
- package/llms.txt +53 -0
- package/openapi.json +124 -57
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1195,7 +1195,7 @@ interface paths {
|
|
|
1195
1195
|
put?: never;
|
|
1196
1196
|
/**
|
|
1197
1197
|
* Crear un access token
|
|
1198
|
-
* @description Emite una credencial de máquina (`hpat_…`) con la que un agente (Claude Code) o un script CI escribe
|
|
1198
|
+
* @description Emite una credencial de máquina (`hpat_…`) con la que un agente (Claude Code) o un script CI escribe el modelo de datos por HTTP. La respuesta incluye el secreto en claro UNA sola vez (`token`); guárdalo, no se puede recuperar. Los permisos se intersectan con los del creador (un token nunca puede más que quien lo emite).
|
|
1199
1199
|
*/
|
|
1200
1200
|
post: operations["HablalaApiWeb.AccessTokens.TokenController.create"];
|
|
1201
1201
|
delete?: never;
|
|
@@ -1305,10 +1305,10 @@ interface paths {
|
|
|
1305
1305
|
cookie?: never;
|
|
1306
1306
|
};
|
|
1307
1307
|
/** Listar citas */
|
|
1308
|
-
get: operations["HablalaApiWeb.
|
|
1308
|
+
get: operations["HablalaApiWeb.Scheduling.AppointmentController.index"];
|
|
1309
1309
|
put?: never;
|
|
1310
1310
|
/** Crear una cita */
|
|
1311
|
-
post: operations["HablalaApiWeb.
|
|
1311
|
+
post: operations["HablalaApiWeb.Scheduling.AppointmentController.create"];
|
|
1312
1312
|
delete?: never;
|
|
1313
1313
|
options?: never;
|
|
1314
1314
|
head?: never;
|
|
@@ -1323,7 +1323,7 @@ interface paths {
|
|
|
1323
1323
|
cookie?: never;
|
|
1324
1324
|
};
|
|
1325
1325
|
/** Ver una cita */
|
|
1326
|
-
get: operations["HablalaApiWeb.
|
|
1326
|
+
get: operations["HablalaApiWeb.Scheduling.AppointmentController.show"];
|
|
1327
1327
|
put?: never;
|
|
1328
1328
|
post?: never;
|
|
1329
1329
|
delete?: never;
|
|
@@ -1342,7 +1342,7 @@ interface paths {
|
|
|
1342
1342
|
get?: never;
|
|
1343
1343
|
put?: never;
|
|
1344
1344
|
/** Cancelar una cita (libera el hueco) */
|
|
1345
|
-
post: operations["HablalaApiWeb.
|
|
1345
|
+
post: operations["HablalaApiWeb.Scheduling.AppointmentController.cancel"];
|
|
1346
1346
|
delete?: never;
|
|
1347
1347
|
options?: never;
|
|
1348
1348
|
head?: never;
|
|
@@ -1359,7 +1359,7 @@ interface paths {
|
|
|
1359
1359
|
get?: never;
|
|
1360
1360
|
put?: never;
|
|
1361
1361
|
/** Confirmar una cita pending */
|
|
1362
|
-
post: operations["HablalaApiWeb.
|
|
1362
|
+
post: operations["HablalaApiWeb.Scheduling.AppointmentController.confirm"];
|
|
1363
1363
|
delete?: never;
|
|
1364
1364
|
options?: never;
|
|
1365
1365
|
head?: never;
|
|
@@ -1379,7 +1379,7 @@ interface paths {
|
|
|
1379
1379
|
* Marcar/desmarcar el no-show
|
|
1380
1380
|
* @description Flag ortogonal al estado; la cita no libera su hueco.
|
|
1381
1381
|
*/
|
|
1382
|
-
post: operations["HablalaApiWeb.
|
|
1382
|
+
post: operations["HablalaApiWeb.Scheduling.AppointmentController.no_show"];
|
|
1383
1383
|
delete?: never;
|
|
1384
1384
|
options?: never;
|
|
1385
1385
|
head?: never;
|
|
@@ -1399,7 +1399,7 @@ interface paths {
|
|
|
1399
1399
|
* Reagendar una cita
|
|
1400
1400
|
* @description Cancela la cita y crea una nueva enlazada, en una transacción: si el hueco nuevo está tomado, la original queda intacta.
|
|
1401
1401
|
*/
|
|
1402
|
-
post: operations["HablalaApiWeb.
|
|
1402
|
+
post: operations["HablalaApiWeb.Scheduling.AppointmentController.reschedule"];
|
|
1403
1403
|
delete?: never;
|
|
1404
1404
|
options?: never;
|
|
1405
1405
|
head?: never;
|
|
@@ -1538,7 +1538,7 @@ interface paths {
|
|
|
1538
1538
|
};
|
|
1539
1539
|
/**
|
|
1540
1540
|
* Exportar la configuración del workspace como manifiesto
|
|
1541
|
-
* @description El estado real de lo declarable (
|
|
1541
|
+
* @description El estado real de lo declarable (objetos, workflows, agentes) como manifiesto. Es lo que `hablala pull`/`init` baja a archivos.
|
|
1542
1542
|
*/
|
|
1543
1543
|
get: operations["HablalaApiWeb.Data.WorkspaceConfigController.show"];
|
|
1544
1544
|
/**
|
|
@@ -2191,10 +2191,10 @@ interface paths {
|
|
|
2191
2191
|
cookie?: never;
|
|
2192
2192
|
};
|
|
2193
2193
|
/** Listar horarios del equipo */
|
|
2194
|
-
get: operations["HablalaApiWeb.
|
|
2194
|
+
get: operations["HablalaApiWeb.Scheduling.ScheduleController.index"];
|
|
2195
2195
|
put?: never;
|
|
2196
2196
|
/** Crear un horario */
|
|
2197
|
-
post: operations["HablalaApiWeb.
|
|
2197
|
+
post: operations["HablalaApiWeb.Scheduling.ScheduleController.create"];
|
|
2198
2198
|
delete?: never;
|
|
2199
2199
|
options?: never;
|
|
2200
2200
|
head?: never;
|
|
@@ -2209,16 +2209,16 @@ interface paths {
|
|
|
2209
2209
|
cookie?: never;
|
|
2210
2210
|
};
|
|
2211
2211
|
/** Ver un horario */
|
|
2212
|
-
get: operations["HablalaApiWeb.
|
|
2212
|
+
get: operations["HablalaApiWeb.Scheduling.ScheduleController.show"];
|
|
2213
2213
|
/** Actualizar un horario (nombre, zona) */
|
|
2214
|
-
put: operations["HablalaApiWeb.
|
|
2214
|
+
put: operations["HablalaApiWeb.Scheduling.ScheduleController.update"];
|
|
2215
2215
|
post?: never;
|
|
2216
2216
|
/** Borrar un horario (y sus franjas) */
|
|
2217
|
-
delete: operations["HablalaApiWeb.
|
|
2217
|
+
delete: operations["HablalaApiWeb.Scheduling.ScheduleController.delete"];
|
|
2218
2218
|
options?: never;
|
|
2219
2219
|
head?: never;
|
|
2220
2220
|
/** Actualizar un horario (nombre, zona) */
|
|
2221
|
-
patch: operations["HablalaApiWeb.
|
|
2221
|
+
patch: operations["HablalaApiWeb.Scheduling.ScheduleController.update (2)"];
|
|
2222
2222
|
trace?: never;
|
|
2223
2223
|
};
|
|
2224
2224
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/schedules/{schedule_id}/availabilities": {
|
|
@@ -2231,7 +2231,7 @@ interface paths {
|
|
|
2231
2231
|
get?: never;
|
|
2232
2232
|
put?: never;
|
|
2233
2233
|
/** Agregar una franja de disponibilidad al horario */
|
|
2234
|
-
post: operations["HablalaApiWeb.
|
|
2234
|
+
post: operations["HablalaApiWeb.Scheduling.ScheduleController.add_availability"];
|
|
2235
2235
|
delete?: never;
|
|
2236
2236
|
options?: never;
|
|
2237
2237
|
head?: never;
|
|
@@ -2249,7 +2249,7 @@ interface paths {
|
|
|
2249
2249
|
put?: never;
|
|
2250
2250
|
post?: never;
|
|
2251
2251
|
/** Quitar una franja de disponibilidad */
|
|
2252
|
-
delete: operations["HablalaApiWeb.
|
|
2252
|
+
delete: operations["HablalaApiWeb.Scheduling.ScheduleController.remove_availability"];
|
|
2253
2253
|
options?: never;
|
|
2254
2254
|
head?: never;
|
|
2255
2255
|
patch?: never;
|
|
@@ -2885,7 +2885,7 @@ interface components {
|
|
|
2885
2885
|
schemas: {
|
|
2886
2886
|
/**
|
|
2887
2887
|
* AccessToken
|
|
2888
|
-
* @description Metadatos de un access token de máquina (`hpat_…`): la credencial con la que un agente (Claude Code) o un script CI escribe
|
|
2888
|
+
* @description Metadatos de un access token de máquina (`hpat_…`): la credencial con la que un agente (Claude Code) o un script CI escribe el modelo de datos por HTTP. El secreto en claro NO se incluye aquí — solo se devuelve una vez, al crearlo.
|
|
2889
2889
|
*/
|
|
2890
2890
|
AccessToken: {
|
|
2891
2891
|
/** @description ¿Ni revocado ni expirado? */
|
|
@@ -2965,7 +2965,7 @@ interface components {
|
|
|
2965
2965
|
name: string;
|
|
2966
2966
|
/** @description Permisos RBAC (`recurso:accion`) crudos, p. ej. `["objects:create", "objects:read"]`. Vía avanzada (CI/scripts); la UI usa `preset` en su lugar. */
|
|
2967
2967
|
permissions?: string[];
|
|
2968
|
-
/** @description Clave de un preset de permisos (ver `GET .../access-tokens/presets`), p. ej. `"
|
|
2968
|
+
/** @description Clave de un preset de permisos (ver `GET .../access-tokens/presets`), p. ej. `"objects_builder"`. La vía que usa la UI. Si viene, gana sobre `permissions`. */
|
|
2969
2969
|
preset?: string;
|
|
2970
2970
|
};
|
|
2971
2971
|
/** AccessTokensResponse */
|
|
@@ -3494,10 +3494,51 @@ interface components {
|
|
|
3494
3494
|
EdgeResponse: {
|
|
3495
3495
|
data: components["schemas"]["Edge"];
|
|
3496
3496
|
};
|
|
3497
|
-
/**
|
|
3497
|
+
/**
|
|
3498
|
+
* Error
|
|
3499
|
+
* @description Error en formato RFC 9457 (application/problem+json).
|
|
3500
|
+
*/
|
|
3498
3501
|
Error: {
|
|
3499
|
-
/**
|
|
3500
|
-
|
|
3502
|
+
/**
|
|
3503
|
+
* @description Code estable legible por máquina; el ancla del contrato de errores.
|
|
3504
|
+
* @example validation_failed
|
|
3505
|
+
*/
|
|
3506
|
+
code: string;
|
|
3507
|
+
/**
|
|
3508
|
+
* @description Mensaje humano específico de esta ocurrencia.
|
|
3509
|
+
* @example uno o más campos no son válidos
|
|
3510
|
+
*/
|
|
3511
|
+
detail: string;
|
|
3512
|
+
/**
|
|
3513
|
+
* @description Sugerencias por sinónimo/similitud (unknown_attribute/object).
|
|
3514
|
+
* @example [
|
|
3515
|
+
* "titulo"
|
|
3516
|
+
* ]
|
|
3517
|
+
*/
|
|
3518
|
+
did_you_mean?: string[];
|
|
3519
|
+
/** @description Errores por campo (validación). */
|
|
3520
|
+
errors?: {
|
|
3521
|
+
/** @example talla */
|
|
3522
|
+
field?: string;
|
|
3523
|
+
/** @example is required */
|
|
3524
|
+
message?: string;
|
|
3525
|
+
}[];
|
|
3526
|
+
/**
|
|
3527
|
+
* @description Código HTTP.
|
|
3528
|
+
* @example 422
|
|
3529
|
+
*/
|
|
3530
|
+
status: number;
|
|
3531
|
+
/**
|
|
3532
|
+
* @description Etiqueta canónica en inglés del tipo de problema (estable).
|
|
3533
|
+
* @example Validation failed
|
|
3534
|
+
*/
|
|
3535
|
+
title: string;
|
|
3536
|
+
/**
|
|
3537
|
+
* Format: uri
|
|
3538
|
+
* @description URI que identifica el tipo de problema (deriva de `code`).
|
|
3539
|
+
* @example https://hablala.com/errors/validation_failed
|
|
3540
|
+
*/
|
|
3541
|
+
type: string;
|
|
3501
3542
|
};
|
|
3502
3543
|
/**
|
|
3503
3544
|
* Event
|
|
@@ -5082,14 +5123,12 @@ interface components {
|
|
|
5082
5123
|
};
|
|
5083
5124
|
/**
|
|
5084
5125
|
* WorkspaceConfigManifest
|
|
5085
|
-
* @description El manifiesto declarativo del workspace (WORKSPACE_AS_CODE): el estado deseado de lo declarable —
|
|
5126
|
+
* @description El manifiesto declarativo del workspace (WORKSPACE_AS_CODE): el estado deseado de lo declarable — objects, relationships, workflows y agentes. Cada sección es opcional (ausente = no gestionada) y autoritativa cuando está presente (lo existente no declarado se archiva; nunca se borra). Los datos (records) no son configuración.
|
|
5086
5127
|
*/
|
|
5087
5128
|
WorkspaceConfigManifest: {
|
|
5088
5129
|
agents?: components["schemas"]["ManifestAgent"][];
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
relationships?: components["schemas"]["ManifestRelationship"][];
|
|
5092
|
-
};
|
|
5130
|
+
objects?: components["schemas"]["ManifestObject"][];
|
|
5131
|
+
relationships?: components["schemas"]["ManifestRelationship"][];
|
|
5093
5132
|
workflows?: components["schemas"]["ManifestWorkflow"][];
|
|
5094
5133
|
};
|
|
5095
5134
|
/**
|
|
@@ -8682,7 +8721,7 @@ interface operations {
|
|
|
8682
8721
|
};
|
|
8683
8722
|
};
|
|
8684
8723
|
};
|
|
8685
|
-
"HablalaApiWeb.
|
|
8724
|
+
"HablalaApiWeb.Scheduling.AppointmentController.index": {
|
|
8686
8725
|
parameters: {
|
|
8687
8726
|
query?: {
|
|
8688
8727
|
organizerId?: string;
|
|
@@ -8710,7 +8749,7 @@ interface operations {
|
|
|
8710
8749
|
};
|
|
8711
8750
|
};
|
|
8712
8751
|
};
|
|
8713
|
-
"HablalaApiWeb.
|
|
8752
|
+
"HablalaApiWeb.Scheduling.AppointmentController.create": {
|
|
8714
8753
|
parameters: {
|
|
8715
8754
|
query?: never;
|
|
8716
8755
|
header?: never;
|
|
@@ -8747,7 +8786,7 @@ interface operations {
|
|
|
8747
8786
|
};
|
|
8748
8787
|
};
|
|
8749
8788
|
};
|
|
8750
|
-
"HablalaApiWeb.
|
|
8789
|
+
"HablalaApiWeb.Scheduling.AppointmentController.show": {
|
|
8751
8790
|
parameters: {
|
|
8752
8791
|
query?: never;
|
|
8753
8792
|
header?: never;
|
|
@@ -8780,7 +8819,7 @@ interface operations {
|
|
|
8780
8819
|
};
|
|
8781
8820
|
};
|
|
8782
8821
|
};
|
|
8783
|
-
"HablalaApiWeb.
|
|
8822
|
+
"HablalaApiWeb.Scheduling.AppointmentController.cancel": {
|
|
8784
8823
|
parameters: {
|
|
8785
8824
|
query?: never;
|
|
8786
8825
|
header?: never;
|
|
@@ -8818,7 +8857,7 @@ interface operations {
|
|
|
8818
8857
|
};
|
|
8819
8858
|
};
|
|
8820
8859
|
};
|
|
8821
|
-
"HablalaApiWeb.
|
|
8860
|
+
"HablalaApiWeb.Scheduling.AppointmentController.confirm": {
|
|
8822
8861
|
parameters: {
|
|
8823
8862
|
query?: never;
|
|
8824
8863
|
header?: never;
|
|
@@ -8851,7 +8890,7 @@ interface operations {
|
|
|
8851
8890
|
};
|
|
8852
8891
|
};
|
|
8853
8892
|
};
|
|
8854
|
-
"HablalaApiWeb.
|
|
8893
|
+
"HablalaApiWeb.Scheduling.AppointmentController.no_show": {
|
|
8855
8894
|
parameters: {
|
|
8856
8895
|
query?: {
|
|
8857
8896
|
/** @description Default true. */
|
|
@@ -8878,7 +8917,7 @@ interface operations {
|
|
|
8878
8917
|
};
|
|
8879
8918
|
};
|
|
8880
8919
|
};
|
|
8881
|
-
"HablalaApiWeb.
|
|
8920
|
+
"HablalaApiWeb.Scheduling.AppointmentController.reschedule": {
|
|
8882
8921
|
parameters: {
|
|
8883
8922
|
query?: never;
|
|
8884
8923
|
header?: never;
|
|
@@ -11322,7 +11361,7 @@ interface operations {
|
|
|
11322
11361
|
};
|
|
11323
11362
|
};
|
|
11324
11363
|
};
|
|
11325
|
-
"HablalaApiWeb.
|
|
11364
|
+
"HablalaApiWeb.Scheduling.ScheduleController.index": {
|
|
11326
11365
|
parameters: {
|
|
11327
11366
|
query?: never;
|
|
11328
11367
|
header?: never;
|
|
@@ -11354,7 +11393,7 @@ interface operations {
|
|
|
11354
11393
|
};
|
|
11355
11394
|
};
|
|
11356
11395
|
};
|
|
11357
|
-
"HablalaApiWeb.
|
|
11396
|
+
"HablalaApiWeb.Scheduling.ScheduleController.create": {
|
|
11358
11397
|
parameters: {
|
|
11359
11398
|
query?: never;
|
|
11360
11399
|
header?: never;
|
|
@@ -11391,7 +11430,7 @@ interface operations {
|
|
|
11391
11430
|
};
|
|
11392
11431
|
};
|
|
11393
11432
|
};
|
|
11394
|
-
"HablalaApiWeb.
|
|
11433
|
+
"HablalaApiWeb.Scheduling.ScheduleController.show": {
|
|
11395
11434
|
parameters: {
|
|
11396
11435
|
query?: never;
|
|
11397
11436
|
header?: never;
|
|
@@ -11424,7 +11463,7 @@ interface operations {
|
|
|
11424
11463
|
};
|
|
11425
11464
|
};
|
|
11426
11465
|
};
|
|
11427
|
-
"HablalaApiWeb.
|
|
11466
|
+
"HablalaApiWeb.Scheduling.ScheduleController.update": {
|
|
11428
11467
|
parameters: {
|
|
11429
11468
|
query?: never;
|
|
11430
11469
|
header?: never;
|
|
@@ -11462,7 +11501,7 @@ interface operations {
|
|
|
11462
11501
|
};
|
|
11463
11502
|
};
|
|
11464
11503
|
};
|
|
11465
|
-
"HablalaApiWeb.
|
|
11504
|
+
"HablalaApiWeb.Scheduling.ScheduleController.delete": {
|
|
11466
11505
|
parameters: {
|
|
11467
11506
|
query?: never;
|
|
11468
11507
|
header?: never;
|
|
@@ -11484,7 +11523,7 @@ interface operations {
|
|
|
11484
11523
|
};
|
|
11485
11524
|
};
|
|
11486
11525
|
};
|
|
11487
|
-
"HablalaApiWeb.
|
|
11526
|
+
"HablalaApiWeb.Scheduling.ScheduleController.update (2)": {
|
|
11488
11527
|
parameters: {
|
|
11489
11528
|
query?: never;
|
|
11490
11529
|
header?: never;
|
|
@@ -11522,7 +11561,7 @@ interface operations {
|
|
|
11522
11561
|
};
|
|
11523
11562
|
};
|
|
11524
11563
|
};
|
|
11525
|
-
"HablalaApiWeb.
|
|
11564
|
+
"HablalaApiWeb.Scheduling.ScheduleController.add_availability": {
|
|
11526
11565
|
parameters: {
|
|
11527
11566
|
query?: never;
|
|
11528
11567
|
header?: never;
|
|
@@ -11560,7 +11599,7 @@ interface operations {
|
|
|
11560
11599
|
};
|
|
11561
11600
|
};
|
|
11562
11601
|
};
|
|
11563
|
-
"HablalaApiWeb.
|
|
11602
|
+
"HablalaApiWeb.Scheduling.ScheduleController.remove_availability": {
|
|
11564
11603
|
parameters: {
|
|
11565
11604
|
query?: never;
|
|
11566
11605
|
header?: never;
|
package/llms.txt
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @hablala/api-contract
|
|
2
|
+
|
|
3
|
+
> El contrato **single source of truth** de la API de Hablalá: un `openapi.json` (OpenAPI 3.1)
|
|
4
|
+
> generado desde el backend Elixir con OpenApiSpex, del que derivan los tipos TypeScript. Nadie
|
|
5
|
+
> escribe tipos de la API a mano. Hablalá es API-first y headless: la API es el producto, solo
|
|
6
|
+
> habla JSON, sin UI.
|
|
7
|
+
|
|
8
|
+
## El contrato
|
|
9
|
+
|
|
10
|
+
- [openapi.json](./openapi.json): el spec OpenAPI 3.1 completo, generado desde Elixir
|
|
11
|
+
(`mix openapi.spec.json`). Es la fuente de verdad; los tipos y los clientes derivan de aquí.
|
|
12
|
+
- [generated/types.ts](./generated/types.ts): tipos TypeScript generados con `openapi-typescript`
|
|
13
|
+
(no editar a mano). Se reexportan desde `src/index.ts` como `paths`, `components`, `operations`.
|
|
14
|
+
|
|
15
|
+
## Formato de error (RFC 9457)
|
|
16
|
+
|
|
17
|
+
Todo error de la API responde con `application/problem+json` (RFC 9457), un formato único:
|
|
18
|
+
|
|
19
|
+
{
|
|
20
|
+
"type": "https://hablala.com/errors/<code>",
|
|
21
|
+
"title": "<etiqueta canónica en inglés>",
|
|
22
|
+
"status": <int>,
|
|
23
|
+
"detail": "<mensaje humano>",
|
|
24
|
+
"code": "<code estable, legible por máquina>",
|
|
25
|
+
"did_you_mean": ["<sugerencia>"], // opcional (unknown_attribute/object)
|
|
26
|
+
"errors": [{ "field": "...", "message": "..." }] // opcional (validación por campo)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
El `code` es el ancla del contrato: ramifica por él, no por el status. El schema está en
|
|
30
|
+
`components.schemas.Error` del `openapi.json`.
|
|
31
|
+
|
|
32
|
+
## Rate limiting
|
|
33
|
+
|
|
34
|
+
Las respuestas llevan `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset`. Al
|
|
35
|
+
exceder la cuota: `429` con `Retry-After` (segundos) y un cuerpo RFC 9457 con `code: "rate_limited"`.
|
|
36
|
+
|
|
37
|
+
## Autenticación
|
|
38
|
+
|
|
39
|
+
Una credencial es una identidad completa (el token porta su tenant): no se pasa `organizationId`
|
|
40
|
+
ni `workspaceId`. Access token de máquina `hpat_…` (Bearer) para el motor; storefront token
|
|
41
|
+
`sfpk_…`/`sfpr_…` (header `X-Hablala-Storefront-Token`) para la Data API pública read-only.
|
|
42
|
+
|
|
43
|
+
## Cómo consumirlo
|
|
44
|
+
|
|
45
|
+
- TypeScript (web/móvil): importa los tipos de `@hablala/api-contract` y usa `openapi-fetch`.
|
|
46
|
+
El SDK de alto nivel es [`@hablala/client`](../client).
|
|
47
|
+
- Regeneración: `npm run generate` (openapi.json → types.ts). CI falla si hay drift.
|
|
48
|
+
|
|
49
|
+
## Docs de arquitectura (en el monorepo)
|
|
50
|
+
|
|
51
|
+
- [apps/api/ARCHITECTURE.md](../../apps/api/ARCHITECTURE.md): el mapa completo de la plataforma.
|
|
52
|
+
- [apps/api/API_FIRST.md](../../apps/api/API_FIRST.md): por qué API-first, cómo se genera el contrato.
|
|
53
|
+
- [apps/api/UBIQUITOUS_LANGUAGE.md](../../apps/api/UBIQUITOUS_LANGUAGE.md): el vocabulario normativo.
|
package/openapi.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"responses": {},
|
|
4
4
|
"schemas": {
|
|
5
5
|
"AccessToken": {
|
|
6
|
-
"description": "Metadatos de un access token de máquina (`hpat_…`): la credencial con la que un agente (Claude Code) o un script CI escribe
|
|
6
|
+
"description": "Metadatos de un access token de máquina (`hpat_…`): la credencial con la que un agente (Claude Code) o un script CI escribe el modelo de datos por HTTP. El secreto en claro NO se incluye aquí — solo se devuelve una vez, al crearlo.",
|
|
7
7
|
"properties": {
|
|
8
8
|
"active": {
|
|
9
9
|
"description": "¿Ni revocado ni expirado?",
|
|
@@ -263,7 +263,7 @@
|
|
|
263
263
|
"x-validate": null
|
|
264
264
|
},
|
|
265
265
|
"preset": {
|
|
266
|
-
"description": "Clave de un preset de permisos (ver `GET .../access-tokens/presets`), p. ej. `\"
|
|
266
|
+
"description": "Clave de un preset de permisos (ver `GET .../access-tokens/presets`), p. ej. `\"objects_builder\"`. La vía que usa la UI. Si viene, gana sobre `permissions`.",
|
|
267
267
|
"type": "string",
|
|
268
268
|
"x-struct": null,
|
|
269
269
|
"x-validate": null
|
|
@@ -2205,16 +2205,90 @@
|
|
|
2205
2205
|
"x-validate": null
|
|
2206
2206
|
},
|
|
2207
2207
|
"Error": {
|
|
2208
|
+
"description": "Error en formato RFC 9457 (application/problem+json).",
|
|
2208
2209
|
"properties": {
|
|
2210
|
+
"code": {
|
|
2211
|
+
"description": "Code estable legible por máquina; el ancla del contrato de errores.",
|
|
2212
|
+
"example": "validation_failed",
|
|
2213
|
+
"type": "string",
|
|
2214
|
+
"x-struct": null,
|
|
2215
|
+
"x-validate": null
|
|
2216
|
+
},
|
|
2217
|
+
"detail": {
|
|
2218
|
+
"description": "Mensaje humano específico de esta ocurrencia.",
|
|
2219
|
+
"example": "uno o más campos no son válidos",
|
|
2220
|
+
"type": "string",
|
|
2221
|
+
"x-struct": null,
|
|
2222
|
+
"x-validate": null
|
|
2223
|
+
},
|
|
2224
|
+
"did_you_mean": {
|
|
2225
|
+
"description": "Sugerencias por sinónimo/similitud (unknown_attribute/object).",
|
|
2226
|
+
"example": [
|
|
2227
|
+
"titulo"
|
|
2228
|
+
],
|
|
2229
|
+
"items": {
|
|
2230
|
+
"type": "string",
|
|
2231
|
+
"x-struct": null,
|
|
2232
|
+
"x-validate": null
|
|
2233
|
+
},
|
|
2234
|
+
"type": "array",
|
|
2235
|
+
"x-struct": null,
|
|
2236
|
+
"x-validate": null
|
|
2237
|
+
},
|
|
2209
2238
|
"errors": {
|
|
2210
|
-
"description": "
|
|
2211
|
-
"
|
|
2239
|
+
"description": "Errores por campo (validación).",
|
|
2240
|
+
"items": {
|
|
2241
|
+
"properties": {
|
|
2242
|
+
"field": {
|
|
2243
|
+
"example": "talla",
|
|
2244
|
+
"type": "string",
|
|
2245
|
+
"x-struct": null,
|
|
2246
|
+
"x-validate": null
|
|
2247
|
+
},
|
|
2248
|
+
"message": {
|
|
2249
|
+
"example": "is required",
|
|
2250
|
+
"type": "string",
|
|
2251
|
+
"x-struct": null,
|
|
2252
|
+
"x-validate": null
|
|
2253
|
+
}
|
|
2254
|
+
},
|
|
2255
|
+
"type": "object",
|
|
2256
|
+
"x-struct": null,
|
|
2257
|
+
"x-validate": null
|
|
2258
|
+
},
|
|
2259
|
+
"type": "array",
|
|
2260
|
+
"x-struct": null,
|
|
2261
|
+
"x-validate": null
|
|
2262
|
+
},
|
|
2263
|
+
"status": {
|
|
2264
|
+
"description": "Código HTTP.",
|
|
2265
|
+
"example": 422,
|
|
2266
|
+
"type": "integer",
|
|
2267
|
+
"x-struct": null,
|
|
2268
|
+
"x-validate": null
|
|
2269
|
+
},
|
|
2270
|
+
"title": {
|
|
2271
|
+
"description": "Etiqueta canónica en inglés del tipo de problema (estable).",
|
|
2272
|
+
"example": "Validation failed",
|
|
2273
|
+
"type": "string",
|
|
2274
|
+
"x-struct": null,
|
|
2275
|
+
"x-validate": null
|
|
2276
|
+
},
|
|
2277
|
+
"type": {
|
|
2278
|
+
"description": "URI que identifica el tipo de problema (deriva de `code`).",
|
|
2279
|
+
"example": "https://hablala.com/errors/validation_failed",
|
|
2280
|
+
"format": "uri",
|
|
2281
|
+
"type": "string",
|
|
2212
2282
|
"x-struct": null,
|
|
2213
2283
|
"x-validate": null
|
|
2214
2284
|
}
|
|
2215
2285
|
},
|
|
2216
2286
|
"required": [
|
|
2217
|
-
"
|
|
2287
|
+
"type",
|
|
2288
|
+
"title",
|
|
2289
|
+
"status",
|
|
2290
|
+
"detail",
|
|
2291
|
+
"code"
|
|
2218
2292
|
],
|
|
2219
2293
|
"title": "Error",
|
|
2220
2294
|
"type": "object",
|
|
@@ -7948,7 +8022,7 @@
|
|
|
7948
8022
|
"x-validate": null
|
|
7949
8023
|
},
|
|
7950
8024
|
"WorkspaceConfigManifest": {
|
|
7951
|
-
"description": "El manifiesto declarativo del workspace (WORKSPACE_AS_CODE): el estado deseado de lo declarable —
|
|
8025
|
+
"description": "El manifiesto declarativo del workspace (WORKSPACE_AS_CODE): el estado deseado de lo declarable — objects, relationships, workflows y agentes. Cada sección es opcional (ausente = no gestionada) y autoritativa cuando está presente (lo existente no declarado se archiva; nunca se borra). Los datos (records) no son configuración.",
|
|
7952
8026
|
"properties": {
|
|
7953
8027
|
"agents": {
|
|
7954
8028
|
"items": {
|
|
@@ -7958,26 +8032,19 @@
|
|
|
7958
8032
|
"x-struct": null,
|
|
7959
8033
|
"x-validate": null
|
|
7960
8034
|
},
|
|
7961
|
-
"
|
|
7962
|
-
"
|
|
7963
|
-
"
|
|
7964
|
-
"items": {
|
|
7965
|
-
"$ref": "#/components/schemas/ManifestObject"
|
|
7966
|
-
},
|
|
7967
|
-
"type": "array",
|
|
7968
|
-
"x-struct": null,
|
|
7969
|
-
"x-validate": null
|
|
7970
|
-
},
|
|
7971
|
-
"relationships": {
|
|
7972
|
-
"items": {
|
|
7973
|
-
"$ref": "#/components/schemas/ManifestRelationship"
|
|
7974
|
-
},
|
|
7975
|
-
"type": "array",
|
|
7976
|
-
"x-struct": null,
|
|
7977
|
-
"x-validate": null
|
|
7978
|
-
}
|
|
8035
|
+
"objects": {
|
|
8036
|
+
"items": {
|
|
8037
|
+
"$ref": "#/components/schemas/ManifestObject"
|
|
7979
8038
|
},
|
|
7980
|
-
"type": "
|
|
8039
|
+
"type": "array",
|
|
8040
|
+
"x-struct": null,
|
|
8041
|
+
"x-validate": null
|
|
8042
|
+
},
|
|
8043
|
+
"relationships": {
|
|
8044
|
+
"items": {
|
|
8045
|
+
"$ref": "#/components/schemas/ManifestRelationship"
|
|
8046
|
+
},
|
|
8047
|
+
"type": "array",
|
|
7981
8048
|
"x-struct": null,
|
|
7982
8049
|
"x-validate": null
|
|
7983
8050
|
},
|
|
@@ -13261,7 +13328,7 @@
|
|
|
13261
13328
|
},
|
|
13262
13329
|
"post": {
|
|
13263
13330
|
"callbacks": {},
|
|
13264
|
-
"description": "Emite una credencial de máquina (`hpat_…`) con la que un agente (Claude Code) o un script CI escribe
|
|
13331
|
+
"description": "Emite una credencial de máquina (`hpat_…`) con la que un agente (Claude Code) o un script CI escribe el modelo de datos por HTTP. La respuesta incluye el secreto en claro UNA sola vez (`token`); guárdalo, no se puede recuperar. Los permisos se intersectan con los del creador (un token nunca puede más que quien lo emite).",
|
|
13265
13332
|
"operationId": "HablalaApiWeb.AccessTokens.TokenController.create",
|
|
13266
13333
|
"parameters": [
|
|
13267
13334
|
{
|
|
@@ -13860,7 +13927,7 @@
|
|
|
13860
13927
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/appointments": {
|
|
13861
13928
|
"get": {
|
|
13862
13929
|
"callbacks": {},
|
|
13863
|
-
"operationId": "HablalaApiWeb.
|
|
13930
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.index",
|
|
13864
13931
|
"parameters": [
|
|
13865
13932
|
{
|
|
13866
13933
|
"description": "",
|
|
@@ -13932,12 +13999,12 @@
|
|
|
13932
13999
|
},
|
|
13933
14000
|
"summary": "Listar citas",
|
|
13934
14001
|
"tags": [
|
|
13935
|
-
"
|
|
14002
|
+
"scheduling"
|
|
13936
14003
|
]
|
|
13937
14004
|
},
|
|
13938
14005
|
"post": {
|
|
13939
14006
|
"callbacks": {},
|
|
13940
|
-
"operationId": "HablalaApiWeb.
|
|
14007
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.create",
|
|
13941
14008
|
"parameters": [
|
|
13942
14009
|
{
|
|
13943
14010
|
"description": "",
|
|
@@ -13997,14 +14064,14 @@
|
|
|
13997
14064
|
},
|
|
13998
14065
|
"summary": "Crear una cita",
|
|
13999
14066
|
"tags": [
|
|
14000
|
-
"
|
|
14067
|
+
"scheduling"
|
|
14001
14068
|
]
|
|
14002
14069
|
}
|
|
14003
14070
|
},
|
|
14004
14071
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/appointments/{id}": {
|
|
14005
14072
|
"get": {
|
|
14006
14073
|
"callbacks": {},
|
|
14007
|
-
"operationId": "HablalaApiWeb.
|
|
14074
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.show",
|
|
14008
14075
|
"parameters": [
|
|
14009
14076
|
{
|
|
14010
14077
|
"description": "",
|
|
@@ -14064,14 +14131,14 @@
|
|
|
14064
14131
|
},
|
|
14065
14132
|
"summary": "Ver una cita",
|
|
14066
14133
|
"tags": [
|
|
14067
|
-
"
|
|
14134
|
+
"scheduling"
|
|
14068
14135
|
]
|
|
14069
14136
|
}
|
|
14070
14137
|
},
|
|
14071
14138
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/appointments/{id}/cancel": {
|
|
14072
14139
|
"post": {
|
|
14073
14140
|
"callbacks": {},
|
|
14074
|
-
"operationId": "HablalaApiWeb.
|
|
14141
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.cancel",
|
|
14075
14142
|
"parameters": [
|
|
14076
14143
|
{
|
|
14077
14144
|
"description": "",
|
|
@@ -14142,14 +14209,14 @@
|
|
|
14142
14209
|
},
|
|
14143
14210
|
"summary": "Cancelar una cita (libera el hueco)",
|
|
14144
14211
|
"tags": [
|
|
14145
|
-
"
|
|
14212
|
+
"scheduling"
|
|
14146
14213
|
]
|
|
14147
14214
|
}
|
|
14148
14215
|
},
|
|
14149
14216
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/appointments/{id}/confirm": {
|
|
14150
14217
|
"post": {
|
|
14151
14218
|
"callbacks": {},
|
|
14152
|
-
"operationId": "HablalaApiWeb.
|
|
14219
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.confirm",
|
|
14153
14220
|
"parameters": [
|
|
14154
14221
|
{
|
|
14155
14222
|
"description": "",
|
|
@@ -14209,7 +14276,7 @@
|
|
|
14209
14276
|
},
|
|
14210
14277
|
"summary": "Confirmar una cita pending",
|
|
14211
14278
|
"tags": [
|
|
14212
|
-
"
|
|
14279
|
+
"scheduling"
|
|
14213
14280
|
]
|
|
14214
14281
|
}
|
|
14215
14282
|
},
|
|
@@ -14217,7 +14284,7 @@
|
|
|
14217
14284
|
"post": {
|
|
14218
14285
|
"callbacks": {},
|
|
14219
14286
|
"description": "Flag ortogonal al estado; la cita no libera su hueco.",
|
|
14220
|
-
"operationId": "HablalaApiWeb.
|
|
14287
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.no_show",
|
|
14221
14288
|
"parameters": [
|
|
14222
14289
|
{
|
|
14223
14290
|
"description": "",
|
|
@@ -14278,7 +14345,7 @@
|
|
|
14278
14345
|
},
|
|
14279
14346
|
"summary": "Marcar/desmarcar el no-show",
|
|
14280
14347
|
"tags": [
|
|
14281
|
-
"
|
|
14348
|
+
"scheduling"
|
|
14282
14349
|
]
|
|
14283
14350
|
}
|
|
14284
14351
|
},
|
|
@@ -14286,7 +14353,7 @@
|
|
|
14286
14353
|
"post": {
|
|
14287
14354
|
"callbacks": {},
|
|
14288
14355
|
"description": "Cancela la cita y crea una nueva enlazada, en una transacción: si el hueco nuevo está tomado, la original queda intacta.",
|
|
14289
|
-
"operationId": "HablalaApiWeb.
|
|
14356
|
+
"operationId": "HablalaApiWeb.Scheduling.AppointmentController.reschedule",
|
|
14290
14357
|
"parameters": [
|
|
14291
14358
|
{
|
|
14292
14359
|
"description": "",
|
|
@@ -14357,7 +14424,7 @@
|
|
|
14357
14424
|
},
|
|
14358
14425
|
"summary": "Reagendar una cita",
|
|
14359
14426
|
"tags": [
|
|
14360
|
-
"
|
|
14427
|
+
"scheduling"
|
|
14361
14428
|
]
|
|
14362
14429
|
}
|
|
14363
14430
|
},
|
|
@@ -14955,7 +15022,7 @@
|
|
|
14955
15022
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/config": {
|
|
14956
15023
|
"get": {
|
|
14957
15024
|
"callbacks": {},
|
|
14958
|
-
"description": "El estado real de lo declarable (
|
|
15025
|
+
"description": "El estado real de lo declarable (objetos, workflows, agentes) como manifiesto. Es lo que `hablala pull`/`init` baja a archivos.",
|
|
14959
15026
|
"operationId": "HablalaApiWeb.Data.WorkspaceConfigController.show",
|
|
14960
15027
|
"parameters": [
|
|
14961
15028
|
{
|
|
@@ -19206,7 +19273,7 @@
|
|
|
19206
19273
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/schedules": {
|
|
19207
19274
|
"get": {
|
|
19208
19275
|
"callbacks": {},
|
|
19209
|
-
"operationId": "HablalaApiWeb.
|
|
19276
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.index",
|
|
19210
19277
|
"parameters": [
|
|
19211
19278
|
{
|
|
19212
19279
|
"description": "",
|
|
@@ -19255,12 +19322,12 @@
|
|
|
19255
19322
|
},
|
|
19256
19323
|
"summary": "Listar horarios del equipo",
|
|
19257
19324
|
"tags": [
|
|
19258
|
-
"
|
|
19325
|
+
"scheduling"
|
|
19259
19326
|
]
|
|
19260
19327
|
},
|
|
19261
19328
|
"post": {
|
|
19262
19329
|
"callbacks": {},
|
|
19263
|
-
"operationId": "HablalaApiWeb.
|
|
19330
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.create",
|
|
19264
19331
|
"parameters": [
|
|
19265
19332
|
{
|
|
19266
19333
|
"description": "",
|
|
@@ -19320,14 +19387,14 @@
|
|
|
19320
19387
|
},
|
|
19321
19388
|
"summary": "Crear un horario",
|
|
19322
19389
|
"tags": [
|
|
19323
|
-
"
|
|
19390
|
+
"scheduling"
|
|
19324
19391
|
]
|
|
19325
19392
|
}
|
|
19326
19393
|
},
|
|
19327
19394
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/schedules/{id}": {
|
|
19328
19395
|
"delete": {
|
|
19329
19396
|
"callbacks": {},
|
|
19330
|
-
"operationId": "HablalaApiWeb.
|
|
19397
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.delete",
|
|
19331
19398
|
"parameters": [
|
|
19332
19399
|
{
|
|
19333
19400
|
"description": "",
|
|
@@ -19370,12 +19437,12 @@
|
|
|
19370
19437
|
},
|
|
19371
19438
|
"summary": "Borrar un horario (y sus franjas)",
|
|
19372
19439
|
"tags": [
|
|
19373
|
-
"
|
|
19440
|
+
"scheduling"
|
|
19374
19441
|
]
|
|
19375
19442
|
},
|
|
19376
19443
|
"get": {
|
|
19377
19444
|
"callbacks": {},
|
|
19378
|
-
"operationId": "HablalaApiWeb.
|
|
19445
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.show",
|
|
19379
19446
|
"parameters": [
|
|
19380
19447
|
{
|
|
19381
19448
|
"description": "",
|
|
@@ -19435,12 +19502,12 @@
|
|
|
19435
19502
|
},
|
|
19436
19503
|
"summary": "Ver un horario",
|
|
19437
19504
|
"tags": [
|
|
19438
|
-
"
|
|
19505
|
+
"scheduling"
|
|
19439
19506
|
]
|
|
19440
19507
|
},
|
|
19441
19508
|
"patch": {
|
|
19442
19509
|
"callbacks": {},
|
|
19443
|
-
"operationId": "HablalaApiWeb.
|
|
19510
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.update (2)",
|
|
19444
19511
|
"parameters": [
|
|
19445
19512
|
{
|
|
19446
19513
|
"description": "",
|
|
@@ -19511,12 +19578,12 @@
|
|
|
19511
19578
|
},
|
|
19512
19579
|
"summary": "Actualizar un horario (nombre, zona)",
|
|
19513
19580
|
"tags": [
|
|
19514
|
-
"
|
|
19581
|
+
"scheduling"
|
|
19515
19582
|
]
|
|
19516
19583
|
},
|
|
19517
19584
|
"put": {
|
|
19518
19585
|
"callbacks": {},
|
|
19519
|
-
"operationId": "HablalaApiWeb.
|
|
19586
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.update",
|
|
19520
19587
|
"parameters": [
|
|
19521
19588
|
{
|
|
19522
19589
|
"description": "",
|
|
@@ -19587,14 +19654,14 @@
|
|
|
19587
19654
|
},
|
|
19588
19655
|
"summary": "Actualizar un horario (nombre, zona)",
|
|
19589
19656
|
"tags": [
|
|
19590
|
-
"
|
|
19657
|
+
"scheduling"
|
|
19591
19658
|
]
|
|
19592
19659
|
}
|
|
19593
19660
|
},
|
|
19594
19661
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/schedules/{schedule_id}/availabilities": {
|
|
19595
19662
|
"post": {
|
|
19596
19663
|
"callbacks": {},
|
|
19597
|
-
"operationId": "HablalaApiWeb.
|
|
19664
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.add_availability",
|
|
19598
19665
|
"parameters": [
|
|
19599
19666
|
{
|
|
19600
19667
|
"description": "",
|
|
@@ -19665,14 +19732,14 @@
|
|
|
19665
19732
|
},
|
|
19666
19733
|
"summary": "Agregar una franja de disponibilidad al horario",
|
|
19667
19734
|
"tags": [
|
|
19668
|
-
"
|
|
19735
|
+
"scheduling"
|
|
19669
19736
|
]
|
|
19670
19737
|
}
|
|
19671
19738
|
},
|
|
19672
19739
|
"/v1/organizations/{organization_id}/workspaces/{workspace_id}/schedules/{schedule_id}/availabilities/{id}": {
|
|
19673
19740
|
"delete": {
|
|
19674
19741
|
"callbacks": {},
|
|
19675
|
-
"operationId": "HablalaApiWeb.
|
|
19742
|
+
"operationId": "HablalaApiWeb.Scheduling.ScheduleController.remove_availability",
|
|
19676
19743
|
"parameters": [
|
|
19677
19744
|
{
|
|
19678
19745
|
"description": "",
|
|
@@ -19726,7 +19793,7 @@
|
|
|
19726
19793
|
},
|
|
19727
19794
|
"summary": "Quitar una franja de disponibilidad",
|
|
19728
19795
|
"tags": [
|
|
19729
|
-
"
|
|
19796
|
+
"scheduling"
|
|
19730
19797
|
]
|
|
19731
19798
|
}
|
|
19732
19799
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hablala/api-contract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Contrato tipado (OpenAPI → TypeScript) de la API de Hablalá — single source of truth generada desde el backend Elixir.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"files": [
|
|
31
31
|
"dist",
|
|
32
32
|
"openapi.json",
|
|
33
|
+
"llms.txt",
|
|
33
34
|
"README.md",
|
|
34
35
|
"LICENSE"
|
|
35
36
|
],
|