From 8a222afb0e3e1ad7139c65806b2e0b3411d32394 Mon Sep 17 00:00:00 2001 From: daniel Date: Mon, 6 Jul 2026 09:54:25 +0200 Subject: [PATCH 1/3] chore: gitignore .worktrees/ for local parallel dev worktrees --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7868101a..f80656a9 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ apps/api/uploads/ # Entorno local personal (scripts, seeds, docker extra) — no subir al repo .local/ + +# Local git worktrees for parallel agent work — never commit +.worktrees/ From d4ac199a45f3d5a24e84939bd14c843a56df9ce6 Mon Sep 17 00:00:00 2001 From: daniel Date: Fri, 17 Jul 2026 10:25:13 +0200 Subject: [PATCH 2/3] chore: gitignore .claude/worktrees/ (native worktree tool output) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c7b5d6df..6f125eed 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ apps/api/uploads/ # Local git worktrees for parallel agent work — never commit .worktrees/ +.claude/worktrees/ From f2e7520a3efae7a418c997d187de3cf79465706c Mon Sep 17 00:00:00 2001 From: daniel Date: Fri, 17 Jul 2026 10:55:46 +0200 Subject: [PATCH 3/3] =?UTF-8?q?docs(supplies):=20actualiza=20AGENTS.md=20y?= =?UTF-8?q?=20Swagger=20del=20cat=C3=A1logo=20de=20insumos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documenta el modelo real del catálogo maestro tras la epica #228 (#395, #396, #397, #398, #399, #400, #405, #408): Supply como master-data (código XXX-NNNN, variantes por variantOfId, alias, i18n base+traducciones con fallback, naturaleza logística, external_codes de interop), el metamodelo de atributos data-driven con herencia por categoría, la tenencia global+tenant, la gobernanza admins-only con slugs núcleo protegidos, y los containers (palet/caja/lote) ya implementados. Añade las respuestas de error (404/400/409) que faltaban en los controladores admin y público de supplies para que /docs las refleje, y regenera openapi.json y el cliente tipado. --- AGENTS.md | 11 +- apps/api/openapi.json | 69 ++++++++ .../http/supplies-admin.controller.ts | 29 ++++ .../http/supplies.controller.ts | 2 + packages/api-client/src/schema.ts | 161 ++++++++++++++++++ 5 files changed, 270 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6ee6e4a1..a3e1add2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ Multi-emergency **material aid coordination + logistics** platform (org: **Globa - **`apps/api`** — NestJS 11, **hexagonal / DDD** (ports & adapters, CQRS-light, domain events via Redis/BullMQ), Drizzle ORM, Postgres 16, Redis 7. Swagger at `/docs`. - **`apps/web`** — Next 16 (App Router, React 19), **Atomic Design**, Tailwind 4, Leaflet + `leaflet.markercluster`. Consumes the typed client. (See `apps/web/AGENTS.md` for Next-16 specifics.) - **`packages/api-client`** — `@reliefhub/api-client`, openapi-fetch typed client. Regenerate with `pnpm gen:api`. -- **`packages/warehouse-*`** — `@globalemergency/warehouse-core` (reusable, framework-free WMS domain: `kernel`/`catalog`/`inventory`/`containers`/`logistics` over an opaque `ScopeId`) + `@globalemergency/warehouse-postgres` (Drizzle persistence). Consumed by `apps/api` via `workspace:*`; **pure domain** — ESLint forbids `@nestjs/*`/`drizzle-orm`/`pg`/`apps/*` imports. Own tests run via `node --test` on compiled JS (`pnpm --filter '@globalemergency/warehouse-core' test`). **The extraction-to-OSS-product roadmap is [EPIC #355](https://github.com/GlobalEmergency/ResponseGrid/issues/355)** — read it before touching these packages. +- **`packages/warehouse-*`** — `@globalemergency/warehouse-core` (reusable, framework-free WMS domain: `kernel`/`catalog`/`inventory`/`containers`/`logistics` over an opaque `ScopeId`) + `@globalemergency/warehouse-postgres` (Drizzle persistence). Consumed by `apps/api` via `workspace:*`; **pure domain** — ESLint forbids `@nestjs/*`/`drizzle-orm`/`pg`/`apps/*` imports. Own tests run via `node --test` on compiled JS (`pnpm --filter '@globalemergency/warehouse-core' test`). **The extraction-to-OSS-product roadmap is [EPIC #355](https://github.com/GlobalEmergency/ResponseGrid/issues/355)** — read it before touching these packages. `kernel`/`catalog`/`containers` are the actual domain model behind the `supplies` bounded context (below) — but `apps/api/src/contexts/supplies/infrastructure/drizzle` writes its **own** Drizzle adapters implementing those ports against ResponseGrid's production schema; it does **not** use `@globalemergency/warehouse-postgres`, which today only persists the separate `inventory`/`wms` module (vehicle-fleet work). - TDD throughout. Dev infra via docker-compose. ## Architecture @@ -25,7 +25,14 @@ Hexagonal bounded contexts in `apps/api/src/contexts/` (18): `emergencies · resources · needs · offers · supplies · logistics · volunteers · reports · identity` (authz: grants/service-accounts/API keys) `· groups` (cuadrillas) `· organizations · accreditation · templates · notifications · audit · metrics · geocoding · files`. - `domain/` and `application/` must **NOT** import `@nestjs/*`, drizzle, or infrastructure — enforced by ESLint `no-restricted-imports`. Output ports are mocked in tests; the real domain runs. -- **`supplies` (insumos) — upstream supporting domain (the material line is the core of the platform).** Owns the single material-line model reused everywhere instead of a copy per context: `Category` (the **canonical** enum of aid-material categories — food/water/hygiene/clothing/medical/shelter/tools/other + health vertical medicines/medical_equipment/medical_supplies/medical_personnel), `CategoryDefinition` (the `categories` table: localized labels, hierarchy, import aliases, facet counts — enrichment, not a parallel enum), and the **`SupplyLine`** value object (`name/quantity/unit/category/presentation`). `needs`, `offers`, `resources` (inventory) and `logistics` (`ShipmentItem`) depend on it. Public **`GET /categories`** surfaces the taxonomy. (Replaced the old `taxonomy` context; designed to later reference a `Supply` master-data catalogue and a grouping aggregate —palet/caja/lote— without touching consumers (OCP/DIP).) +- **`supplies` (insumos) — upstream supporting domain (the material line is the core of the platform).** `apps/api/src/contexts/supplies` is a hexagonal **host** (application use cases + Drizzle persistence + HTTP controllers) around domain types that actually live in `@globalemergency/warehouse-core`'s `kernel`/`catalog`/`containers` modules (see `packages/warehouse-*` above). It replaced the old `taxonomy` context and now owns considerably more than a shared taxonomy: + - **Category**: the taxonomy moved from a closed enum to a **data-driven, validated slug** (`CategorySlug`, format `^[a-z][a-z0-9_]*$`) — the `Category` TS enum survives only as the seed of **core** slugs (food/water/hygiene/clothing/medical/shelter/tools/other + health vertical + UCAB subcategories), exported as `CORE_CATEGORY_SLUGS`. `CategoryDefinition` (the `categories` table) enriches any slug — core or tenant-defined — with localized labels, hierarchy (`parentSlug`), `kind` (material/personnel), facet counts and `externalCodes`. Core slugs are **protected**: archiving one throws `CategoryProtectedError` → 409. Public `GET /categories`; admin CRUD at `admin/categories` (`catalogue:manage`). + - **`Supply` master-data catalogue** (epic #228, #222): the previously-planned catalogue is now real. Each `Supply` has a server-assigned code `XXX-NNNN` (prefix from its category's root, sequential), a canonical `name` (**base = `es`**) plus **i18n translations** (`supply_translations`, one row per locale) resolved with **fallback to the base name** when the requested locale has none, a `categorySlug`, freeform `attributes` (jsonb, governed by the attribute metamodel below), an optional **`variantOfId`** (a variant just points at its parent — no separate variants table; `attributes` is what actually differentiates it), **aliases** (`supply_aliases`, synonyms resolved by `SupplyResolver` against canonical name + every translation + code + alias; a label matching more than one supply resolves to `null` — ambiguous, must be `merge`d rather than aliased), `status` (`active`/`archived`; `merge` folds a duplicate into a canonical target, moving its aliases and re-pointing its variants), **`nature`** (`fungible`/`reusable`/`human` — logistics classification, lives on the *supply*, not the category, since one category can mix natures; `null` = unclassified), and **`externalCodes`** (open `namespace → code` map for interop, e.g. `unspsc`/`hxl`, indexed with a GIN index for reverse lookup). `unitWeightKg`/`unitVolumeM3` exist in the domain (for vehicle load calculations) but **ResponseGrid's HTTP and persistence don't wire them yet** — always `null` here. + - **Attribute metamodel** (epic #228): `AttributeDefinition` — an admin-defined, typed field (`text`/`number`/`integer`/`boolean`/`enum`/`date`/`quantity`, with optional `required`/`options`/`unit`) anchored to a `categorySlug` **family** and inherited down the category tree: `resolveEffectiveSchema` unions a category's own definitions with all its ancestors' (root → leaf); the same `key` appearing at two levels of that chain is a collision error, not an override. `Supply.attributes` is validated/coerced against this effective schema on create/edit (`validateAttributes`); a family with no definitions stays a free, ungoverned jsonb (backwards-compatible). CRUD at `admin/attribute-definitions`. + - **Tenancy** (base global + per-tenant extension): every governed row (`Supply`, `supply_aliases`, `attribute_definitions`) carries a nullable `scopeId` — `null` = global (shared by every tenant), a tenant id = an **additive** extension (effective schema/catalogue = global ∪ that tenant's rows, never overriding; a tenant `key`/alias/code colliding with a global one is rejected, not shadowed). **ResponseGrid's admin HTTP endpoints only operate in the global scope today** — `scopeId` isn't yet an exposed request parameter, so tenancy is a domain/persistence capability ahead of the wired API. + - **Governance**: `admin/supplies`, `admin/categories` and `admin/attribute-definitions` all require the `catalogue:manage` permission, granted today only via the `platform_admin` role (`ALL_PERMISSIONS`) — i.e. admins-only, no per-emergency coordinator access. The public `GET /supplies`, `GET /supplies/:id` and `GET /categories` serve **only active rows** and never expose `status`/`registrationNotes`/`nature`/`externalCodes`/`scopeId` (those stay in the admin-only projections/DTOs). + - **Containers** (palet/caja/lote) are **implemented**, not just designed-for (`#140`): a `Container` groups `SupplyLine[]` with declared weight/volume, nests under a parent (self-FK, cycle-checked), seals (lines become immutable once sealed) and moves between a polymorphic holder (`resource`|`shipment`, no FK). Routes under `supplies/containers/*`, gated on being a coordinator of the container's emergency (not `catalogue:manage` — containers are per-emergency, the catalogue is global). + - `needs`, `offers`, `resources` (inventory) and `logistics` (`ShipmentItem`) still depend on the shared **`SupplyLine`** value object (`name/quantity/unit/category/presentation/expiresAt`), which now carries an optional **`supplyId`** soft link to the master-data `Supply` (nullable — legacy free-text lines aren't forced to link); unlinked legacy text is reconciled via `admin/supplies/backfill` (report + best-effort execute, idempotent). - **Resource inventory.** A resource/place declares the material it holds for delivery as `SupplyLine[]` (`resource_items`, FK-cascade; migration `0028`). Captured at `/registrar`. The public detail endpoint exposes it **aggregated to distinct categories** (`inventoryCategories`) for privacy; the full lines are persisted for coordination. - Shared kernel in `apps/api/src/shared/` (EmergencyId, Location, Priority, DomainEvent, cross-context errors, the single `pg.Pool` via `DatabaseModule`). The material-line/category model lives in `supplies` (an upstream context), not in the shared kernel. - Authorization model: `Principal → Grant(role@scope) → Permission → can()`; `@RequirePermission` decorator (replaced the legacy per-context coordinator guards). API keys: `X-API-Key: rh_live_…`. diff --git a/apps/api/openapi.json b/apps/api/openapi.json index 960589b7..1942eddf 100644 --- a/apps/api/openapi.json +++ b/apps/api/openapi.json @@ -6569,6 +6569,9 @@ } } } + }, + "404": { + "description": "Supply not found (or archived)" } }, "summary": "Get a supply by id", @@ -6602,8 +6605,17 @@ } } }, + "400": { + "description": "Payload inválido (código de insumo, atributos sin casar el esquema efectivo de la categoría, etc.)" + }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "categorySlug o variantOfId no existen" } }, "security": [ @@ -6664,6 +6676,9 @@ } } }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" } @@ -6694,6 +6709,9 @@ } } }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" } @@ -6722,6 +6740,9 @@ } } }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" } @@ -6761,8 +6782,14 @@ } } }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "Insumo no encontrado" } }, "security": [ @@ -6801,8 +6828,17 @@ "204": { "description": "" }, + "400": { + "description": "Payload inválido o atributos que no casan el esquema" + }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "Insumo, categorySlug o variantOfId no encontrados" } }, "security": [ @@ -6833,8 +6869,14 @@ "204": { "description": "" }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "Insumo no encontrado" } }, "security": [ @@ -6865,8 +6907,14 @@ "204": { "description": "" }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "Insumo no encontrado" } }, "security": [ @@ -6907,8 +6955,17 @@ "204": { "description": "" }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "Insumo no encontrado" + }, + "409": { + "description": "El alias ya apunta a otro insumo del mismo scope" } }, "security": [ @@ -6947,6 +7004,9 @@ "204": { "description": "" }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" } @@ -6980,8 +7040,17 @@ "204": { "description": "" }, + "400": { + "description": "sourceId y targetId son el mismo insumo" + }, + "401": { + "description": "Token ausente o inválido" + }, "403": { "description": "Falta el permiso catalogue:manage" + }, + "404": { + "description": "sourceId o targetId no encontrados" } }, "security": [ diff --git a/apps/api/src/contexts/supplies/infrastructure/http/supplies-admin.controller.ts b/apps/api/src/contexts/supplies/infrastructure/http/supplies-admin.controller.ts index f8a00846..8c5561a3 100644 --- a/apps/api/src/contexts/supplies/infrastructure/http/supplies-admin.controller.ts +++ b/apps/api/src/contexts/supplies/infrastructure/http/supplies-admin.controller.ts @@ -13,13 +13,17 @@ import { UseGuards, } from '@nestjs/common'; import { + ApiBadRequestResponse, ApiBearerAuth, + ApiConflictResponse, ApiCreatedResponse, ApiForbiddenResponse, ApiNoContentResponse, + ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, + ApiUnauthorizedResponse, } from '@nestjs/swagger'; import { CreateSupply } from '../../application/create-supply'; import { EditSupply } from '../../application/edit-supply'; @@ -66,6 +70,7 @@ import { */ @ApiTags('supplies-admin') @ApiBearerAuth() +@ApiUnauthorizedResponse({ description: 'Token ausente o inválido' }) @ApiForbiddenResponse({ description: 'Falta el permiso catalogue:manage' }) @UseGuards(JwtAuthGuard, PermissionGuard) @UseFilters(SuppliesDomainExceptionFilter) @@ -90,6 +95,13 @@ export class SuppliesAdminController { @HttpCode(201) @ApiOperation({ summary: 'Crear un insumo (asigna código INS-NNNN)' }) @ApiCreatedResponse({ type: CreateSupplyResponseDto }) + @ApiBadRequestResponse({ + description: + 'Payload inválido (código de insumo, atributos sin casar el esquema efectivo de la categoría, etc.)', + }) + @ApiNotFoundResponse({ + description: 'categorySlug o variantOfId no existen', + }) async create(@Body() dto: CreateSupplyDto): Promise { const result = await this.createSupply.execute({ name: dto.name, @@ -145,6 +157,7 @@ export class SuppliesAdminController { @Get(':id') @ApiOperation({ summary: 'Detalle de gestión de un insumo' }) @ApiOkResponse({ type: AdminSupplyDto }) + @ApiNotFoundResponse({ description: 'Insumo no encontrado' }) async get(@Param('id', ParseUUIDPipe) id: string): Promise { return this.getSupplyAdmin.execute(id); } @@ -153,6 +166,12 @@ export class SuppliesAdminController { @HttpCode(204) @ApiOperation({ summary: 'Editar un insumo (code no editable)' }) @ApiNoContentResponse() + @ApiBadRequestResponse({ + description: 'Payload inválido o atributos que no casan el esquema', + }) + @ApiNotFoundResponse({ + description: 'Insumo, categorySlug o variantOfId no encontrados', + }) async edit( @Param('id', ParseUUIDPipe) id: string, @Body() dto: EditSupplyDto, @@ -165,6 +184,7 @@ export class SuppliesAdminController { @HttpCode(204) @ApiOperation({ summary: 'Archivar un insumo' }) @ApiNoContentResponse() + @ApiNotFoundResponse({ description: 'Insumo no encontrado' }) async archive(@Param('id', ParseUUIDPipe) id: string): Promise { await this.archiveSupply.execute(id); this.cache.invalidate(); @@ -174,6 +194,7 @@ export class SuppliesAdminController { @HttpCode(204) @ApiOperation({ summary: 'Reactivar un insumo archivado' }) @ApiNoContentResponse() + @ApiNotFoundResponse({ description: 'Insumo no encontrado' }) async restore(@Param('id', ParseUUIDPipe) id: string): Promise { await this.restoreSupply.execute(id); this.cache.invalidate(); @@ -183,6 +204,10 @@ export class SuppliesAdminController { @HttpCode(204) @ApiOperation({ summary: 'Añadir un alias/sinónimo a un insumo' }) @ApiNoContentResponse() + @ApiNotFoundResponse({ description: 'Insumo no encontrado' }) + @ApiConflictResponse({ + description: 'El alias ya apunta a otro insumo del mismo scope', + }) async addAlias( @Param('id', ParseUUIDPipe) id: string, @Body() dto: AddSupplyAliasDto, @@ -207,6 +232,10 @@ export class SuppliesAdminController { @HttpCode(204) @ApiOperation({ summary: 'Fusionar un insumo duplicado en el canónico' }) @ApiNoContentResponse() + @ApiBadRequestResponse({ + description: 'sourceId y targetId son el mismo insumo', + }) + @ApiNotFoundResponse({ description: 'sourceId o targetId no encontrados' }) async merge(@Body() dto: MergeSuppliesDto): Promise { await this.mergeSupplies.execute({ sourceId: dto.sourceId, diff --git a/apps/api/src/contexts/supplies/infrastructure/http/supplies.controller.ts b/apps/api/src/contexts/supplies/infrastructure/http/supplies.controller.ts index ffbf9879..c76bd3ff 100644 --- a/apps/api/src/contexts/supplies/infrastructure/http/supplies.controller.ts +++ b/apps/api/src/contexts/supplies/infrastructure/http/supplies.controller.ts @@ -8,6 +8,7 @@ import { } from '@nestjs/common'; import { ApiHeader, + ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiQuery, @@ -91,6 +92,7 @@ export class SuppliesController { description: 'Preferred locale', }) @ApiOkResponse({ description: 'Supply detail', type: SupplyDto }) + @ApiNotFoundResponse({ description: 'Supply not found (or archived)' }) async get( @Param('id') id: string, @Query('locale') localeParam: string | undefined, diff --git a/packages/api-client/src/schema.ts b/packages/api-client/src/schema.ts index 3743dec4..678f6d05 100644 --- a/packages/api-client/src/schema.ts +++ b/packages/api-client/src/schema.ts @@ -11684,6 +11684,13 @@ export interface operations { "application/json": components["schemas"]["SupplyDto"]; }; }; + /** @description Supply not found (or archived) */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_list: { @@ -11709,6 +11716,13 @@ export interface operations { "application/json": components["schemas"]["AdminSupplyDto"][]; }; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11739,6 +11753,20 @@ export interface operations { "application/json": components["schemas"]["CreateSupplyResponseDto"]; }; }; + /** @description Payload inválido (código de insumo, atributos sin casar el esquema efectivo de la categoría, etc.) */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11746,6 +11774,13 @@ export interface operations { }; content?: never; }; + /** @description categorySlug o variantOfId no existen */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_backfillReport: { @@ -11765,6 +11800,13 @@ export interface operations { "application/json": components["schemas"]["SupplyLinkReportDto"]; }; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11791,6 +11833,13 @@ export interface operations { "application/json": components["schemas"]["SupplyLinkBackfillResultDto"]; }; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11819,6 +11868,13 @@ export interface operations { "application/json": components["schemas"]["AdminSupplyDto"]; }; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11826,6 +11882,13 @@ export interface operations { }; content?: never; }; + /** @description Insumo no encontrado */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_edit: { @@ -11849,6 +11912,20 @@ export interface operations { }; content?: never; }; + /** @description Payload inválido o atributos que no casan el esquema */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11856,6 +11933,13 @@ export interface operations { }; content?: never; }; + /** @description Insumo, categorySlug o variantOfId no encontrados */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_archive: { @@ -11875,6 +11959,13 @@ export interface operations { }; content?: never; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11882,6 +11973,13 @@ export interface operations { }; content?: never; }; + /** @description Insumo no encontrado */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_restore: { @@ -11901,6 +11999,13 @@ export interface operations { }; content?: never; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11908,6 +12013,13 @@ export interface operations { }; content?: never; }; + /** @description Insumo no encontrado */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_addAlias: { @@ -11931,6 +12043,13 @@ export interface operations { }; content?: never; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11938,6 +12057,20 @@ export interface operations { }; content?: never; }; + /** @description Insumo no encontrado */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description El alias ya apunta a otro insumo del mismo scope */ + 409: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; SuppliesAdminController_removeAlias: { @@ -11958,6 +12091,13 @@ export interface operations { }; content?: never; }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11986,6 +12126,20 @@ export interface operations { }; content?: never; }; + /** @description sourceId y targetId son el mismo insumo */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Token ausente o inválido */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; /** @description Falta el permiso catalogue:manage */ 403: { headers: { @@ -11993,6 +12147,13 @@ export interface operations { }; content?: never; }; + /** @description sourceId o targetId no encontrados */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; ContainerController_create: {