package com.baiyue.overseassecurity; import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import static org.assertj.core.api.Assertions.assertThat; class OverseasSecurityContractTest { @Test void sqlFreezesReliableInboxProjectionAndRedisRecoveryBoundary() throws Exception { String sql = read("overseas-security-service/src/main/resources/db/overseas-security.sql"); String service = read("overseas-security-service/src/main/java/com/baiyue/overseassecurity/service/SecurityProjectionService.java"); String validation = read("overseas-security-service/src/main/java/com/baiyue/overseassecurity/service/OverseasSecurityValidationService.java"); String mirror = read("overseas-security-service/src/main/java/com/baiyue/overseassecurity/service/SecurityProjectionRedisMirror.java"); assertThat(sql).contains("PRIMARY KEY (event_id)", "payload_hash CHAR(64)", "PRIMARY KEY (aggregate_type, aggregate_id)", "aggregate_version BIGINT", "permission_version BIGINT"); assertThat(service).contains("ProjectionMonotonicity.decide", "Decision.APPLY"); assertThat(mirror).contains("TransactionPhase.AFTER_COMMIT", "Redis 镜像写入失败"); assertThat(validation).contains("SELECT MAX(permission_version)", "USER_DISABLED", "TENANT_DISABLED", "PERMISSION_VERSION_STALE"); } @Test void eventBridgeRoutesIamTypesWithoutInspectingTheirPayload() throws Exception { String dispatcher = read("event-bridge-service/src/main/java/com/baiyue/eventbridge/service/OverseasEventDispatcher.java"); String client = read("event-bridge-service/src/main/java/com/baiyue/eventbridge/service/HttpSecurityProjectionEventClient.java"); String lastleg = read("lastleg-service/src/main/java/com/baiyue/lastleg/controller/LastlegOrderController.java"); assertThat(dispatcher).contains("IAM_USER_STATUS_CHANGED", "IAM_TENANT_STATUS_CHANGED", "IAM_PERMISSION_VERSION_CHANGED", "securityProjectionEventClient.deliver(event)"); assertThat(dispatcher).doesNotContain("IamSecurityEventsV1", "permissionVersion()", "status()"); assertThat(client).contains("path(\"data\").path(\"eventId\")", "row.getEventId().equals") .doesNotContain("IamSecurityEventsV1"); assertThat(lastleg).contains("Lastleg 不消费该事件类型") .doesNotContain("? shippingNodeConsumer.consume(event) : consumer.consume(event)"); } @Test void internalOpenApiNeverAcceptsRawTokensOrCredentials() throws Exception { String openapi = read("overseas-security-service/src/main/resources/openapi/internal-overseas-security-v1.yaml"); assertThat(openapi).contains("/internal/overseas-security/v1/events:", "/internal/overseas-security/v1/validate:", "X-Internal-Service-Token", "userId, tenantId, tokenVersion and permissionVersion"); assertThat(openapi).doesNotContain("accessToken", "refreshToken", "password:", "Authorization"); } private static String read(String relative) throws Exception { Path path = Path.of(relative); if (!Files.exists(path)) path = Path.of("..").resolve(relative); return Files.readString(path, StandardCharsets.UTF_8); } }