Why hotels care
Multi-property owners (one login, many hotels) are the confused-deputy footgun. A bug that lets property A’s token read property B’s reservation by id is a career-limiting incident for an indie group.
ops/harden/TENANT_ISOLATION.md already lists owner invariants — but they are checklist-only. The CLI covers two-user cross-tenant deny, not same-user multi-property mistakes.
Current state (code anchors)
ops/harden/cli/ — harden:local / harden:live
ops/harden/TENANT_ISOLATION.md — "Multi-property owner invariants (same account)"
- API: every property-scoped
:id route requires propertyId query param; services must and(eq(id), eq(propertyId))
What we need
Extend pnpm harden:live probes when env provides an owner token with property_ids=[A,B]:
GET entity of B with propertyId=A → 404 (not 200)
POST /reservations with propertyId=A and guestId only linked at B → 404
- Document required env vars in
ops/harden/.env.harden.example
- Keep existing two-user probes green
Acceptance criteria
How to contribute
Good first issue for someone comfortable with Node CLIs and HTTP assertions. Hotel IT / MSSP folks who pen-test tenant isolation: please add more probe ideas in comments.
Search keywords: multi-tenant, propertyId, tenant isolation, harden CLI, confused deputy, hotel group, Keycloak property_ids
Why hotels care
Multi-property owners (one login, many hotels) are the confused-deputy footgun. A bug that lets property A’s token read property B’s reservation by id is a career-limiting incident for an indie group.
ops/harden/TENANT_ISOLATION.mdalready lists owner invariants — but they are checklist-only. The CLI covers two-user cross-tenant deny, not same-user multi-property mistakes.Current state (code anchors)
ops/harden/cli/—harden:local/harden:liveops/harden/TENANT_ISOLATION.md— "Multi-property owner invariants (same account)":idroute requirespropertyIdquery param; services mustand(eq(id), eq(propertyId))What we need
Extend
pnpm harden:liveprobes when env provides an owner token withproperty_ids=[A,B]:GETentity of B withpropertyId=A→ 404 (not 200)POST /reservationswithpropertyId=AandguestIdonly linked at B → 404ops/harden/.env.harden.exampleAcceptance criteria
How to contribute
Good first issue for someone comfortable with Node CLIs and HTTP assertions. Hotel IT / MSSP folks who pen-test tenant isolation: please add more probe ideas in comments.
Search keywords: multi-tenant, propertyId, tenant isolation, harden CLI, confused deputy, hotel group, Keycloak property_ids