conceptadev / conceptadev/nestjs-modules

nestjs-repository: ship a fail-closed tenant scope hook

Open
#473 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
95
Forks
12
Avg merge
35m
Merged PRs (30d)
1

Description

### Use case

Multi-tenant apps (in our case, rows isolated per sales territory) need a read-side tenant filter that **fails closed**. Today every consumer writes their own `@BeforeFind` hook, and the README example in `nestjs-repository` (Repository Hooks, `TenantScopeHook`) returns the options unscoped when no tenant is on the context:

```ts
const tenant = ctx?.supports(TenantCtx) ? ctx.with(TenantCtx) : undefined;
if (!tenant) return options;
```

That means a missing overlay, a wrong entity key or a call site that forgets to pass `ctx` silently returns every tenant's rows. In a spike on `8.0.0-alpha.12` (hooks only, no database RLS), a repository call without `ctx` returned all rows across two tenants.

### Proposal

Ship a tenant scope hook in `nestjs-repository` that is safe by default:

- A resolver `(ctx) => tenantIds[]` configured per entity key and tenant field.
- No actor, or an empty set, produces an always-false clause (match nothing; `findOne` becomes not-found), never "no restriction".
- Applies to `find`, `findOne`, `findAndCount`, `count`, and to the lookups behind `update` and `delete`.
- Fails at boot when the entity key or tenant field does not exist, instead of never firing.
- An explicit, opt-in "all tenants" mode for roles such as a corporate administrator, so nobody has to pass the full tenant list.
- Update the README example to fail closed.

Prior art: Rockets ships this as `TenantScopeHook` in `packages/rockets-core/src/infrastructure/hooks/tenant-scope.hook.ts` (always-false clause on an empty set, boot-time key validation). Happy to help port it when contributions open.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the README's nestjs-repository Repository Hooks example, especially TenantScopeHook, and compare it with packages/rockets-core/src/infrastructure/hooks/tenant-scope.hook.ts. Define how the hook is configured and validated, then cover the listed read and write lookups, fail-closed empty-tenant behavior, and explicit all-tenants mode. Update the README example and add coverage for each required operation and boot-time validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
authorization, backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.