Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,17 @@ public List<ConversionJobLifecycleEvent> findLifecycleEventsByJobId(UUID jobId)
/**
* Returns lifecycle events for a tenant.
*
* <p>Missing or blank scoped tenant identifiers fail closed and never infer
* the explicit legacy demo tenant.</p>
*
* @param tenantId tenant identifier
* @return append-only lifecycle events for the tenant
* @return append-only lifecycle events for the tenant, or an empty list when
* scoped tenant context is absent
*/
public List<ConversionJobLifecycleEvent> findLifecycleEventsByTenantId(String tenantId) {
if (tenantId == null || tenantId.isBlank()) {
return List.of();
}
String normalizedTenantId = normalizeTenantId(tenantId);
return lifecycleEvents.stream()
.filter(event -> event.tenantId().equals(normalizedTenantId))
Expand Down Expand Up @@ -379,7 +386,7 @@ private String contentKey(String tenantId, String contentHash) {
}

private String normalizeTenantId(String tenantId) {
return tenantId == null || tenantId.isBlank() ? "buyer-demo" : tenantId.strip();
return Objects.requireNonNull(tenantId, "tenantId").strip();
}

private boolean matchesContentIndex(ConversionJob job, String expectedContentKey) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.clearfolio.viewer.repository;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.UUID;

import org.junit.jupiter.api.Test;

import com.clearfolio.viewer.model.ConversionJob;

/**
* Verifies that lifecycle-event queries never infer the demo tenant from a
* missing scoped tenant identifier.
*/
class InMemoryConversionJobRepositoryTenantLifecycleIsolationTest {

@Test
void nullAndBlankTenantQueriesCannotReadDemoLifecycleEvents() {
InMemoryConversionJobRepository repository = new InMemoryConversionJobRepository();
ConversionJob demoJob = new ConversionJob(
UUID.fromString("11111111-2222-3333-4444-555555555555"),
"buyer-demo",
"subject-demo",
"report.pdf",
"application/pdf",
"tenant-lifecycle-isolation-hash",
42L,
3
);
repository.findOrStoreByContentHash(demoJob);

assertEquals(1, repository.findLifecycleEventsByTenantId("buyer-demo").size());
assertTrue(repository.findLifecycleEventsByTenantId(null).isEmpty());
assertTrue(repository.findLifecycleEventsByTenantId(" ").isEmpty());
}
}