Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
# `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<Caps>` 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.