two-tenant-verifylisted
Install: claude install-skill amineorion/claude-code-safety-skills
# Two-tenant verification
Green tests are not proof of isolation. A test fixture with one tenant will pass even
when a query has no tenant filter at all, because there is only one tenant's data to
return. The only honest check uses **two** tenants.
## The rule
> A data change is done when you have logged in as a second tenant and confirmed the
> first tenant's data is invisible — in the running app, not just green tests.
## Procedure
1. **Seed two tenants.** Adapt the template at
`${CLAUDE_SKILL_DIR}/scripts/seed-two-tenants.sql.template` to the project schema.
Each tenant gets one clearly-labeled secret row (`SECRET-A`, `SECRET-B`).
2. **Boot the stack against the seeded data.** Use the project's `scripts/dev.sh`
(or create a one-command launcher if none exists — the friction is why this step
gets skipped).
3. **Exercise the changed path as Tenant B.** Authenticate as `user-b@example.com` and
hit the exact endpoint/page/job the change touched.
4. **Assert the boundary, both directions:**
- As Tenant B, you can see `SECRET-B` and **never** `SECRET-A`.
- As Tenant A, you can see `SECRET-A` and **never** `SECRET-B`.
- Check the response body, not just the UI — leaked data sometimes renders blank
but is present in the payload, cache, or search results.
5. **Cover the non-DB vectors** the change touched: trigger the background job and
confirm it only processed Tenant B's rows; check that cached responses aren't shared;
confirm search re