How to add an API
Follow this order so consumers (SDK, UI, integrations) never drift from the gateway.
1. OpenAPI (prego-zuplo or prego_ai zuplo)
- ERP / auth / business routes: add or edit a fragment under
prego-zuplo/config/*.oas.json. Merge order, Zuplo portal titles, and Dev Portal copy lists come fromprego-zuplo/config/oas-manifest.json(viascripts/oas-config.mjs). New fragments must be registered there and stay aligned withzuplo.jsonc—pnpm run check-oas-listsvalidates alignment. Older planning docs may cite legacy names (00-security, hand-editedmerge-openapi.jslists); see OAS layout history. prego_aiZuplo project (separate from the ERP/auth gateway): edit public route fragments under prego_aizuplo/config/. Runpnpm run zuplo:verify(orpnpm run zuplo:verify:portal) from the prego_ai repo root — see prego_ai zuplo/README.md.- Assign a stable
operationId(becomes SDK / generated client method names). - Document path/query/body and headers (
X-Tenant-Id, auth, etc.). - Run the repo’s merge / sync scripts if present (e.g. merge into
merged.oas.json).- prego-zuplo: from repo root,
pnpm run sync-oascopies intodocs/openapi/and regeneratesdocs/openapi/merged.oas.json. - prego_ai zuplo: from repo root,
pnpm run zuplo:verify(runssync-oas-equivalent and merge checks insidezuplo/). - Example (www trial → control plane): trial-access fragments
config/15-trial-access-*…19-trial-access-*(seeoas-manifest.json), handlersmodules/trial-access-handlers.ts, upstreamCONTROL_PLANE_URL+ paths like/v1/trial/email/checkand/v1/trial/manual-approval/*. D1 migrations for trial data ship in prego-control-plane, not the gateway.
- prego-zuplo: from repo root,
- Add CI checks (
check-oas-*.mjs) to the PR if available.- prego-zuplo:
pnpm run verify(OAS, merged drift,$ref, MDX tables, unit tests).pnpm run verify:portalmatches GitHub CI (verify+ Zudoku productiondocsbuild). - prego_ai zuplo:
pnpm run zuplo:verify/pnpm run zuplo:verify:portal.
- prego-zuplo:
2. Zuplo route
- Wire the route to the correct upstream (prego_ai, control-plane, Frappe forwarder).
- Attach policies: auth, CORS, rate limit, quota as required. For browser
fetchcallers that correlate checkout or onboarding, ensure CORSAccess-Control-Allow-Headers(or equivalent) allows optionalx-trace-id; values must matchtrace_*/ length rules in Tenant trust boundaries. ForALLOWED_ORIGINS, Pages previews, and preflight triage, see the prego-zuplo runbook — allowed origins /x-trace-idand CORS error causes. - Ensure no new business rules — only transformation and forwarding consistent with the OAS.
x-zuplo-routehandler modules: In OAS,handler.moduleuses Zuplo’s$import(./modules/...). That path must be the file where the named export (ordefault) is defined for the bundler — not a file that only re-exports withexport { … } from "./other"(Zuplo won’t see those names). Examples of broken barrels:billing-handler.ts,auth-handler.ts(importbilling-handlers,auth-*-handlersinstead). If you want one OAS module path, add thinexport async functionwrappers that delegate to implementation modules (seemcp-oauth-handler.ts). prego-zuplo CI includescheck-oas-zuplo-handler-barrelsfor known re-export-only barrels; extend that list when you add another.
3. Handler
- Worker (prego_ai / control-plane): implement route; read tenant from trusted headers; enforce internal signature when required. When persisting or echoing funnel ids, use
sanitizeTraceIdValue/sanitizeTraceIdFromRequestfrom@platform/platform-trust(same rules as Zuplo). - Frappe (prego_saas): implement whitelisted API; keep DocType rules server-side.
4. Clients
- Regenerate or update the SDK from the merged OAS (when generation is in use).
- Update Next.js callers to use the new operation or path version.
5. Docs
- Link the operation from Contracts or this site’s runbook if operators need it.
Breaking changes
- Bump API version (e.g.
/v2/...) or use deprecation headers; update all gateways and clients in a coordinated release.
한국어
OpenAPI → Zuplo 라우트 → 핸들러(워커 또는 Frappe) → 클라이언트 순으로 작업합니다. 게이트웨이에만 비즈니스 규칙을 두지 않습니다. prego-zuplo OpenAPI 조각은 config/*.oas.json 이고, 병합·포털 순서는 config/oas-manifest.json (구 파일명·merge-openapi FILES 설명은 OAS layout history 참고). 예: www 트라이얼 공개 경로는 15-trial-access-* … 19-trial-access-* 조각 → CP /v1/trial/*; D1은 prego-control-plane 쪽 마이그레이션입니다. breaking change 시 버전 경로 또는 deprecation 정책을 함께 적용합니다. prego-zuplo에서는 저장소 루트에서 pnpm run sync-oas 후 pnpm run verify; CI와 동일하게 보려면 pnpm run verify:portal을 실행합니다. OAS의 $import(./modules/...)는 핸들러가 정의된 TS 파일을 가리켜야 하며, export { … } from 만 있는 재수출 전용 배럴(billing-handler, auth-handler 등)을 쓰면 Zuplo 빌드가 실패할 수 있습니다. 구현 파일을 직접 import하거나 mcp-oauth-handler.ts처럼 래퍼 export async function을 두면 됩니다. 브라우저가 온보딩 상관관계를 위해 x-trace-id를 사용하면 CORS 허용 헤더에 포함하고, 워커에서는 @platform/platform-trust 검증 규칙에 맞춥니다(테넌트 신뢰 경계 참고). ALLOWED_ORIGINS·프리플라이트·x-trace-id 운영은 prego-zuplo allowed-origins runbook·CORS 진단을 참고하세요.