# `api-types` — Foundation gap 5 cleanup: nullable tenant on RequestContext **Package**: `@suaveplan/api-types` **Status**: PROPOSED **Type**: type-soundness-fix ## Why The `foundation-fix-gap-5-default-tenant` change widened the runtime behaviour: when the resolver chain misses and no `defaultTenant` is configured, `RequestContext.tenant` / `RequestContext.tenantId` are `null` at runtime. The static types in `@suaveplan/api-types` were NOT updated — they still declared `tenant: TenantContext` and `tenantId: TenantId` as non-nullable. Consequences observed in `request-pipeline-helpers.ts`: ```ts tenantId: (args.tenant?.id ?? null) as never, tenant: (args.tenant ?? null) as never, ``` The `as never` is a documented escape hatch — but it is a type lie that defeats every handler-side guard the type system was supposed to enforce. Out-of-spec debt; resolved before moving on per the user's directive. ## What changes MODIFIED: `RequestContext` field types in `@suaveplan/api-types/plugin-context`: ```ts readonly tenantId: TenantId | null; readonly tenant: TenantContext | null; ``` Existing `tenant`/`tenantId` consumers in the monorepo already use the null-safe `?.` access pattern (verified across `e2e/foundation-stack`, `apps/demo`, `apps/testbed`, and every `api-plugin-*`). No handler needed a code change beyond stripping the now-redundant casts. The `JobContext` and `ConnectionContext` flavours are NOT widened. Per-tenant jobs and connection-scoped contexts only exist after a tenant has been resolved — their resolver chain runs separately and never returns `null` to the handler. Widening those would force a spurious null-check on every job/connection handler. The `as never` casts in `request-pipeline-helpers.ts` lines 143-150 are removed. The two remaining `as` casts at the same site are generic-erasure points (capabilities/instruments resolve to typed slices at the route handler call-site, not at the untyped pipeline seam); they now use the explicit `as RequestContext["capabilities"]` form with a multi-line code comment explaining the boundary instead of a blanket `as never`. ## Impact - `@suaveplan/api-types` — spec MODIFIED Requirement (this delta). - `@suaveplan/api-host` — `as never` casts stripped from `buildRequestContext`; generic-erasure casts retained with the documented boundary comment. - E2E foundation-stack: 11 Playwright tests still green; no handler changes needed since fixture plugin already used `ctx.tenant?.id`. ## Verification ``` bunx turbo lint typecheck test build --filter=@suaveplan/api-types --filter=@suaveplan/api-host bunx turbo test:coverage --filter=@suaveplan/api-host --filter=@suaveplan/api-types cd e2e/foundation-stack && bunx playwright test # 11/11 ``` All green. No `as never` remains for `tenant`/`tenantId` in `request-pipeline-helpers.ts`. No `biome-ignore` / `@ts-ignore` / `@ts-expect-error` added anywhere.