feat: add opencode skill for tx-admin-endpoint collection and API generation

This commit is contained in:
2026-07-22 19:44:47 -03:00
parent 4029566063
commit e6662aac18
@@ -0,0 +1,86 @@
---
name: tx-admin-endpoint
description: "Trigger: crear colección, nueva colección, crear endpoint, nuevo endpoint, Models, api, turnosxpress admin. Reglas para crear colecciones y endpoints del backend admin de turnosxpress."
license: Apache-2.0
metadata:
author: gentleman-programming
version: "1.0"
---
## Activation Contract
Load this skill when creating a new collection or a new endpoint in the `server` backend of the turnosxpress admin (the API consumed by admins/employees, not the public client app). Applies to both the data layer (`server/src/Models`) and the HTTP layer (`server/src/api`). Example to imitate: `Clients`, `Posts`, `SchedulesDisabled`.
## Hard Rules
- Use the ACTUAL paths: collections live in `server/src/Models/<Name>/`, endpoints in `server/src/api/<Name>/`. The folder name is the collection name (e.g. `Clients`, `Posts`).
- A collection is ALWAYS exactly 3 files with separated responsibilities (never collapse them):
| File | Owns | Forbidden here |
|------|------|-----------------|
| `<Name>.Interface.ts` | All TS types: `*Params` (Create/Update/Delete/Find), `IX`, `IXDocument` re-export, `IXAdapter`, `IXManager`, view/result types. | No Mongoose, no business logic. |
| `<Name>.Adapter.Mongoose.ts` | Mongoose ONLY: `Schema`, `IXDocument extends IX & Document`, `model()`, and pure DB ops (`create`, `delete`, `find`, `findOne`, `paginate`). Implements `IXAdapter`. | No business rules, NO security checks. |
| `<Name>.ts` | Business rules AND security. A `<Name>Manager implements IXManager` class that instantiates the adapter in the constructor; exported as a singleton (`const XList = new ...Manager(); export default XList;`). | No Schema, no `model()`. |
- SECURITY STANDARD (mandatory, even though `Clients.ts` inlines it — that is legacy): use the shared helpers from `server/src/helpers/check.ts`:
- `validateSessionUser({ sessionUser })` — confirm the session user exists. Call FIRST in any method that receives `sessionUser`.
- `validatePermissionsByCompany({ companyId, sessionUser })` — confirm the company exists AND the session user has ADMIN role. Call whenever a `companyId` is involved.
- Modern reference: `server/src/Models/Posts/Posts.ts`, `server/src/Models/SchedulesDisabled/SchedulesDisabled.ts`.
- Role checks beyond ADMIN (EMPLOYEE, etc.) go through `EmployeesList.checkPermission` / `checkRoleById`.
- An endpoint is ALWAYS 2 files:
- `<Name>.Controller.ts` — tsoa decorators. One controller class per `@Route("resource/action")`. Each handler `@Post()`, takes `@Body()`, sets status, wraps in try/catch and returns `new ApiValidationError(500, message)` on error. Import `ApiValidationError` from `../../Models/Server.Error.model`.
- `<Name>.Service.ts` — thin: each method `await connect(process.env.DATABASE_CONNECTION)` then delegates to the manager singleton. No business logic here.
- `authenticationMiddleware` (from `server/src/middleware/authentication.ts`) MUST be applied with `@Middlewares(authenticateMiddleware)` on EVERY controller, UNLESS the endpoint is intentionally public. Never omit it without explicit confirmation (see Ask Before Building).
- 99% of endpoints use `@Post()`. Default to POST; use GET/other only with a concrete, justified reason.
- After adding/changing controllers, regenerate the tsoa routes/spec: `npm run routes` (binds `tsoa spec-and-routes`); compile with `npm run build`.
## Decision Gates
| Situation | Decision |
|-----------|----------|
| Does the method take `sessionUser`? | Call `validateSessionUser` first. |
| Does the method act on a `companyId`? | Then `validatePermissionsByCompany`. |
| Endpoint exposed in the admin backend? | Default: `@Middlewares(authenticateMiddleware)`. |
| Endpoint hits WhatsApp notification / public recovery / ratings or another abuse-prone path? | Consider `rateLimiter` (or `ratingRateLimiter`) from `server/src/middleware/ratelimiter.ts`. When both apply: `@Middlewares([rateLimiter, authenticateMiddleware])`. |
| Internal/system-only endpoint? | Use `systemTokenMiddleware` instead of/with the above. |
| Doubt about middleware, role, or method? | STOP and ask. See Ask Before Building. |
## Ask Before Building (HARD — security first)
STOP and ask the user BEFORE writing security or middleware code whenever there is ANY doubt. Never guess on these:
1. Which validations/roles/plan features the new method requires (ADMIN vs EMPLOYEE vs extra feature gates).
2. Whether the endpoint should be public (no `authenticateMiddleware`) or authenticated. A missing auth middleware is a security hole — when unsure, default to KEEPING `authenticateMiddleware` and confirm.
3. Whether `rateLimiter` should be applied to a given endpoint. Do NOT add it by default; ask when the endpoint could be abuse-prone.
4. Whether a non-POST method is genuinely needed.
Ask at most a couple of focused questions, then wait. Do not proceed by assumption on security.
## Execution Steps
Creating a collection:
1. Create `server/src/Models/<Name>/<Name>.Interface.ts` — define all params, `IX`, `IXAdapter`, `IXManager`, view/result types.
2. Create `server/src/Models/<Name>/<Name>.Adapter.Mongoose.ts` — schema, `IXDocument`, `model()`, pure DB ops implementing `IXAdapter`.
3. Create `server/src/Models/<Name>/<Name>.ts``<Name>Manager implements IXManager`; instantiate the adapter in the constructor; put business rules; call `validateSessionUser` / `validatePermissionsByCompany` at the top of each secured method; export a singleton default.
4. Re-check Ask Before Building for any unconfirmed security requirement.
Creating an endpoint:
1. Create `server/src/api/<Name>/<Name>.Service.ts` — one method per action, `connect(process.env.DATABASE_CONNECTION)` then delegate to the manager singleton.
2. Create `server/src/api/<Name>/<Name>.Controller.ts` — one controller class per `@Route`; `@Middlewares(authenticateMiddleware)` unless confirmed public; `@Post()` + `@Body()`; try/catch returning `ApiValidationError`.
3. Apply Decision Gates (rateLimiter? system token? method?).
4. Regenerate routes: `npm run routes` then `npm run build`.
## Output Contract
Return: files created, the singletons/middlewares wired, any security decision that was confirmed with the user, and whether `npm run routes` / `npm run build` were run.
## References
- `server/src/Models/Clients/Clients.ts`, `Clients.Interface.ts`, `Clients.Adapter.Mongoose.ts` — canonical 3-file collection example (note: Clients inlines security; do NOT copy that part).
- `server/src/Models/Posts/Posts.ts` — modern security pattern using the shared helpers.
- `server/src/helpers/check.ts``validateSessionUser`, `validatePermissionsByCompany`, `validatePermissionsByClient`.
- `server/src/api/Clients/Clients.Controller.ts`, `Clients.Service.ts` — endpoint pattern (Controller + Service).
- `server/src/middleware/authentication.ts`, `server/src/middleware/ratelimiter.ts` — middleware sources.
- `server/tsoa.json`, `server/package.json` (`npm run routes`) — route generation.