Skip to content

feat: tenant isolation for single-instance multi-tenant deployment#671

Draft
Copilot wants to merge 3 commits into
mainfrom
copilot/user-story-single-backend-deployment
Draft

feat: tenant isolation for single-instance multi-tenant deployment#671
Copilot wants to merge 3 commits into
mainfrom
copilot/user-story-single-backend-deployment

Conversation

Copy link
Copy Markdown

Copilot AI commented Jun 3, 2026

A single deployed backend instance needs to serve users within a company under an isolated tenant scope, with tenant derived automatically — no manual configuration required.

Approach

Tenant resolution (TenantService):

  • No auth → hardcoded tenant "global"
  • OIDC enabled → last path segment of JWT issuer URL (Keycloak: http://host/realms/compas"compas")
  • Handles trailing slashes, bare hostnames, null/blank issuer, and missing tokens — all fall back to "global"
// OIDC: http://keycloak/realms/my-company  →  "my-company"
// No auth / fallback                        →  "global"
String tenant = tenantService.resolveTenant();

Database (V1_8 Flyway migration):

  • Adds tenant varchar(255) NOT NULL DEFAULT 'global' + index to scl_file
  • Existing rows migrate safely to "global" tenant

Layer changestenant threaded as first parameter through every read/write path:

  • CompasSclDataRepository interface + PostgreSQL implementation (all SQL queries filter/insert by tenant)
  • SoftDeleteCompasSclDataPostgreSQLRepository (DELETE SQL updated)
  • CompasSclDataService — all public methods
  • CompasSclDataResource + CompasPluginsResource — inject TenantService, resolve per request
  • WebSocket event models (CreateEventRequest, GetEventRequest, GetVersionEventRequest, UpdateEventRequest) + all 4 endpoints + CompasSclDataEventHandler
  • CompasPluginsResourceService (list, count, upload)

scl_label is unaffected — tenant isolation is enforced via the scl_file FK, no column needed there.

Copilot AI added 2 commits June 3, 2026 11:27
- Add Flyway migration V1_8 to add tenant column to scl_file table
- Add GLOBAL_TENANT constant ("global") for no-auth mode
- Add TenantService to resolve tenant from JWT issuer or fall back to "global"
- Update CompasSclDataRepository interface: all methods take tenant as first param
- Update PostgreSQL repository SQL to filter/insert by tenant
- Update SoftDeleteCompasSclDataPostgreSQLRepository with tenant in DELETE SQL
- Update CompasSclDataService: all public methods take tenant as first param
- Update REST resource (CompasSclDataResource) to inject TenantService
- Update WebSocket event models and endpoints with tenant field
- Update CompasPluginsResourceService and CompasPluginsResource with tenant
- Add TenantServiceTest with 6 unit tests covering all scenarios
- Update all existing tests to use tenant parameter
- Strip trailing slash before extracting last path segment so that
  "http://host/realms/compas/" correctly returns "compas"
- Guard against bare hostname URLs (e.g. "http://host") returning the
  hostname as tenant by checking that the char before lastSlash is not
  also a slash (i.e. not the "://" separator)
- Fix test method name typo: AssTenant → AsTenant
- Update no-path test to assert GLOBAL_TENANT (was incorrectly asserting "host")
- Add new trailing-slash test case
Copilot AI changed the title [WIP] Implement single backend instance deployment for multiple tenants feat: tenant isolation for single-instance multi-tenant deployment Jun 3, 2026
Copilot AI requested a review from david-monichi June 3, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User Story: Single Backend Instance Deployment for multiple tenants

2 participants