union-ark-web 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/PROJECT_OVERVIEW.md +405 -0
  2. package/README.md +177 -0
  3. package/ark-control/pom.xml +142 -0
  4. package/ark-control/src/local-mock/java/com/epcc/commons/securityproxy/api/SecurityResult.java +14 -0
  5. package/ark-control/src/local-mock/java/com/epcc/commons/securityproxy/api/SymmetricalSecurityService.java +11 -0
  6. package/ark-control/src/local-mock/java/com/epcc/dubbo/result/Result.java +29 -0
  7. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/annotation/EnDecryptField.java +16 -0
  8. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/annotation/EnDecryptFieldLong.java +17 -0
  9. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/annotation/EnDecryptFieldWithTag.java +16 -0
  10. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/exception/BaseDataErrorCode.java +26 -0
  11. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/exception/CheckException.java +33 -0
  12. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/exception/ErrorCode.java +9 -0
  13. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/redis/RedisCacheService.java +131 -0
  14. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/util/Constant.java +24 -0
  15. package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/util/ResultUtil.java +9 -0
  16. package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalMockSensitiveProxy.java +40 -0
  17. package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalRedisCacheService.java +45 -0
  18. package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalSensitiveHostConfiguration.java +27 -0
  19. package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalSensitiveProxyConfiguration.java +16 -0
  20. package/ark-control/src/main/java/com/union/control/ArkControlApplication.java +17 -0
  21. package/ark-control/src/main/java/com/union/control/dubbo/ProviderAccessLogFilter.java +45 -0
  22. package/ark-control/src/main/java/com/union/control/mapper/AgentExecutionMapper.java +35 -0
  23. package/ark-control/src/main/java/com/union/control/mapper/ConversationMapper.java +44 -0
  24. package/ark-control/src/main/java/com/union/control/mapper/MemoryStoreMapper.java +41 -0
  25. package/ark-control/src/main/java/com/union/control/mapper/ScheduledTaskMapper.java +96 -0
  26. package/ark-control/src/main/java/com/union/control/mapper/SensitiveAddressBookDemo.java +31 -0
  27. package/ark-control/src/main/java/com/union/control/mapper/SensitiveDataDemoMapper.java +24 -0
  28. package/ark-control/src/main/java/com/union/control/mapper/interceptor/AESInterceptor.java +265 -0
  29. package/ark-control/src/main/java/com/union/control/mapper/interceptor/AddressBookHandler.java +105 -0
  30. package/ark-control/src/main/java/com/union/control/schedule/ScheduledExecutionToken.java +55 -0
  31. package/ark-control/src/main/java/com/union/control/schedule/ScheduledTaskScheduler.java +206 -0
  32. package/ark-control/src/main/java/com/union/control/service/impl/AgentExecutionServiceImpl.java +212 -0
  33. package/ark-control/src/main/java/com/union/control/service/impl/AgentProxyServiceImpl.java +143 -0
  34. package/ark-control/src/main/java/com/union/control/service/impl/ConversationServiceImpl.java +245 -0
  35. package/ark-control/src/main/java/com/union/control/service/impl/MemoryStoreServiceImpl.java +252 -0
  36. package/ark-control/src/main/java/com/union/control/service/impl/RunningAnalysisMockServiceImpl.java +301 -0
  37. package/ark-control/src/main/java/com/union/control/service/impl/ScheduledTaskServiceImpl.java +576 -0
  38. package/ark-control/src/main/java/com/union/control/service/impl/SensitiveDataDemoServiceImpl.java +144 -0
  39. package/ark-control/src/main/java/com/union/control/service/sensitive/RedisRevealTokenStore.java +90 -0
  40. package/ark-control/src/main/java/com/union/control/service/sensitive/SensitiveRevealProcessor.java +319 -0
  41. package/ark-control/src/main/java/com/union/control/service/sensitive/SensitiveRevealServiceImpl.java +72 -0
  42. package/ark-control/src/main/java/com/union/control/utils/AgentSupport.java +103 -0
  43. package/ark-control/src/main/java/com/union/control/utils/security/SymmetricalSecurityUtils.java +160 -0
  44. package/ark-control/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter +1 -0
  45. package/ark-control/src/main/resources/application.properties +4 -0
  46. package/ark-control/src/main/resources/application.yml +32 -0
  47. package/ark-control/src/main/resources/dubbo-provider.xml +20 -0
  48. package/ark-control/src/main/resources/mapper/AgentExecutionMapper.xml +75 -0
  49. package/ark-control/src/main/resources/mapper/ConversationMapper.xml +110 -0
  50. package/ark-control/src/main/resources/mapper/MemoryStoreMapper.xml +74 -0
  51. package/ark-control/src/main/resources/mapper/ScheduledTaskMapper.xml +286 -0
  52. package/ark-control/src/main/resources/mapper/SensitiveDataDemoMapper.xml +55 -0
  53. package/ark-control/src/main/resources/schema.sql +146 -0
  54. package/ark-control/src/test/java/com/union/control/AgentExecutionServiceTest.java +170 -0
  55. package/ark-control/src/test/java/com/union/control/ArkControlStructureContractTest.java +107 -0
  56. package/ark-control/src/test/java/com/union/control/ConversationServiceTest.java +89 -0
  57. package/ark-control/src/test/java/com/union/control/MemoryStoreServiceTest.java +26 -0
  58. package/ark-control/src/test/java/com/union/control/PydanticAiControlContractTest.java +52 -0
  59. package/ark-control/src/test/java/com/union/control/TestJson.java +45 -0
  60. package/ark-control/src/test/java/com/union/control/dubbo/ProviderAccessLogFilterTest.java +53 -0
  61. package/ark-control/src/test/java/com/union/control/local/sensitive/LocalSensitiveProxyConfigurationTest.java +23 -0
  62. package/ark-control/src/test/java/com/union/control/mapper/interceptor/AESInterceptorCompatibilityTest.java +505 -0
  63. package/ark-control/src/test/java/com/union/control/schedule/ScheduledExecutionTokenTest.java +27 -0
  64. package/ark-control/src/test/java/com/union/control/schedule/ScheduledTaskSchedulerTest.java +51 -0
  65. package/ark-control/src/test/java/com/union/control/service/AgentProxyServiceTest.java +111 -0
  66. package/ark-control/src/test/java/com/union/control/service/ScheduledTaskServiceTest.java +483 -0
  67. package/ark-control/src/test/java/com/union/control/service/impl/SensitiveDataDemoServiceImplTest.java +104 -0
  68. package/ark-control/src/test/java/com/union/control/service/sensitive/RedisRevealTokenStoreTest.java +65 -0
  69. package/ark-control/src/test/java/com/union/control/service/sensitive/SensitiveRevealBoundaryTest.java +99 -0
  70. package/ark-control/src/test/java/com/union/control/service/sensitive/SensitiveRevealProcessorCodecTest.java +111 -0
  71. package/ark-control/src/test/java/com/union/control/service/sensitive/SensitiveRevealProcessorTest.java +111 -0
  72. package/ark-control/src/test/java/com/union/control/utils/security/SymmetricalSecurityUtilsCompatibilityTest.java +87 -0
  73. package/ark-control-facade/pom.xml +16 -0
  74. package/ark-control-facade/src/main/java/com/union/control/service/AgentExecutionService.java +8 -0
  75. package/ark-control-facade/src/main/java/com/union/control/service/AgentProxyService.java +7 -0
  76. package/ark-control-facade/src/main/java/com/union/control/service/AgentResponse.java +22 -0
  77. package/ark-control-facade/src/main/java/com/union/control/service/ConversationService.java +12 -0
  78. package/ark-control-facade/src/main/java/com/union/control/service/MemoryStoreService.java +12 -0
  79. package/ark-control-facade/src/main/java/com/union/control/service/RunningAnalysisMockService.java +10 -0
  80. package/ark-control-facade/src/main/java/com/union/control/service/ScheduledTaskService.java +40 -0
  81. package/ark-control-facade/src/main/java/com/union/control/service/SensitiveDataDemoService.java +13 -0
  82. package/ark-control-facade/src/main/java/com/union/control/service/sensitive/SensitiveRevealService.java +18 -0
  83. package/ark-web/README.md +80 -0
  84. package/ark-web/pom.xml +105 -0
  85. package/ark-web/src/local-mock/java/com/epcc/arkweb/mock/ArkAuthServiceMock.java +105 -0
  86. package/ark-web/src/local-mock/java/com/epcc/arkweb/mock/LocalKaptchaConfiguration.java +26 -0
  87. package/ark-web/src/main/java/com/epcc/arkweb/Application.java +13 -0
  88. package/ark-web/src/main/java/com/epcc/arkweb/config/InterceptorConfig.java +20 -0
  89. package/ark-web/src/main/java/com/epcc/arkweb/config/Realm.java +64 -0
  90. package/ark-web/src/main/java/com/epcc/arkweb/config/ShiroConfig.java +129 -0
  91. package/ark-web/src/main/java/com/epcc/arkweb/filter/LoginFormFilter.java +43 -0
  92. package/ark-web/src/main/java/com/epcc/arkweb/helper/AuthContextHolder.java +39 -0
  93. package/ark-web/src/main/java/com/epcc/arkweb/helper/AuthenticatedRequest.java +91 -0
  94. package/ark-web/src/main/java/com/epcc/arkweb/model/ShiroUser.java +21 -0
  95. package/ark-web/src/main/java/com/epcc/arkweb/utils/ResultMsg.java +19 -0
  96. package/ark-web/src/main/java/com/epcc/arkweb/vo/llm/ScheduledTaskCommandVO.java +30 -0
  97. package/ark-web/src/main/java/com/epcc/arkweb/vo/llm/ScheduledTaskQueryVO.java +20 -0
  98. package/ark-web/src/main/java/com/epcc/arkweb/web/CommonController.java +25 -0
  99. package/ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentAuthorizationInterceptor.java +229 -0
  100. package/ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentController.java +165 -0
  101. package/ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentPermission.java +13 -0
  102. package/ark-web/src/main/java/com/epcc/arkweb/web/llm/LlmController.java +209 -0
  103. package/ark-web/src/main/java/com/epcc/arkweb/web/llm/ScheduledTaskController.java +160 -0
  104. package/ark-web/src/main/java/com/epcc/arkweb/web/sensitive/reveal/SensitiveCaptchaService.java +146 -0
  105. package/ark-web/src/main/java/com/epcc/arkweb/web/sensitive/reveal/SensitiveRevealController.java +163 -0
  106. package/ark-web/src/main/resources/application.properties +1 -0
  107. package/ark-web/src/main/resources/application.yml +23 -0
  108. package/ark-web/src/main/resources/dubbo-consumer.xml +19 -0
  109. package/ark-web/src/production-overlay/java/com/epcc/arkweb/config/CasShiroConfig.java +229 -0
  110. package/ark-web/src/production-overlay/java/com/epcc/arkweb/config/InterceptorConfig.java +35 -0
  111. package/ark-web/src/production-overlay/java/com/epcc/arkweb/config/ShiroConfig.java +161 -0
  112. package/ark-web/src/test/java/com/epcc/arkweb/ArkWebStructureContractTest.java +290 -0
  113. package/ark-web/src/test/java/com/epcc/arkweb/ShiroTestSupport.java +32 -0
  114. package/ark-web/src/test/java/com/epcc/arkweb/config/LocalShiroIntegrationTest.java +121 -0
  115. package/ark-web/src/test/java/com/epcc/arkweb/helper/AuthenticatedRequestTest.java +131 -0
  116. package/ark-web/src/test/java/com/epcc/arkweb/local/LocalArkAuthServiceMockTest.java +17 -0
  117. package/ark-web/src/test/java/com/epcc/arkweb/web/llm/AgentAuthorizationInterceptorTest.java +134 -0
  118. package/ark-web/src/test/java/com/epcc/arkweb/web/llm/AgentControllerAuthorizationTest.java +97 -0
  119. package/ark-web/src/test/java/com/epcc/arkweb/web/llm/LlmControllerTest.java +113 -0
  120. package/ark-web/src/test/java/com/epcc/arkweb/web/sensitive/reveal/SensitiveRevealControllerTest.java +273 -0
  121. package/package.json +18 -0
  122. package/pom.xml +16 -0
@@ -0,0 +1,107 @@
1
+ package com.union.control;
2
+
3
+ import org.junit.Test;
4
+
5
+ import java.nio.charset.StandardCharsets;
6
+ import java.nio.file.Files;
7
+ import java.nio.file.Path;
8
+ import java.nio.file.Paths;
9
+ import java.util.Arrays;
10
+ import java.util.List;
11
+ import java.util.stream.Collectors;
12
+
13
+ import static org.assertj.core.api.Assertions.assertThat;
14
+
15
+ public class ArkControlStructureContractTest {
16
+
17
+ private static final Path JAVA_ROOT = Paths.get("src/main/java");
18
+
19
+ @Test
20
+ public void applicationStartsAHeadlessDubboProvider() throws Exception {
21
+ String application = source("com/union/control/ArkControlApplication.java");
22
+ String config = resource("application.yml");
23
+
24
+ assertThat(application)
25
+ .contains("class ArkControlApplication")
26
+ .contains("@MapperScan(\"com.union.control.mapper\")")
27
+ .contains("@EnableScheduling")
28
+ .contains("@ImportResource(\"classpath:dubbo-provider.xml\")");
29
+ assertThat(config).contains("web-environment: false");
30
+ }
31
+
32
+ @Test
33
+ public void providerPublishesEveryFacadeService() throws Exception {
34
+ String dubbo = resource("dubbo-provider.xml");
35
+ assertThat(dubbo).contains("<dubbo:provider filter=\"providerAccessLog\"");
36
+ for (String service : Arrays.asList(
37
+ "AgentExecutionService",
38
+ "AgentProxyService",
39
+ "ConversationService",
40
+ "MemoryStoreService",
41
+ "RunningAnalysisMockService",
42
+ "ScheduledTaskService",
43
+ "SensitiveDataDemoService")) {
44
+ assertThat(dubbo).contains(
45
+ "interface=\"com.union.control.service." + service + "\"");
46
+ }
47
+ assertThat(dubbo).contains(
48
+ "interface=\"com.union.control.service.sensitive.SensitiveRevealService\"");
49
+
50
+ assertThat(resource("META-INF/dubbo/com.alibaba.dubbo.rpc.Filter"))
51
+ .contains("providerAccessLog=com.union.control.dubbo.ProviderAccessLogFilter");
52
+ assertThat(source("com/union/control/dubbo/ProviderAccessLogFilter.java"))
53
+ .contains("Dubbo provider request started")
54
+ .contains("Dubbo provider request completed")
55
+ .doesNotContain("getArguments()");
56
+ }
57
+
58
+ @Test
59
+ public void providerDoesNotExposeTheWebOnlyStream() throws Exception {
60
+ String dubbo = resource("dubbo-provider.xml");
61
+ String facade = new String(Files.readAllBytes(Paths.get(
62
+ "../ark-control-facade/src/main/java/com/union/control/service/AgentProxyService.java")),
63
+ StandardCharsets.UTF_8);
64
+
65
+ assertThat(dubbo)
66
+ .doesNotContain("name=\"stream\"")
67
+ .doesNotContain("callback=\"true\"");
68
+ assertThat(facade).doesNotContain("stream(").doesNotContain("AgentStreamCallback");
69
+ }
70
+
71
+ @Test
72
+ public void providerContainsNoWebControllerOrShiroBoundary() throws Exception {
73
+ List<Path> javaFiles = Files.walk(JAVA_ROOT)
74
+ .filter(Files::isRegularFile)
75
+ .collect(Collectors.toList());
76
+ String source = javaFiles.stream()
77
+ .map(path -> {
78
+ try {
79
+ return new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
80
+ } catch (Exception error) {
81
+ throw new IllegalStateException(error);
82
+ }
83
+ })
84
+ .collect(Collectors.joining("\n"));
85
+
86
+ assertThat(javaFiles.stream()
87
+ .map(path -> path.getFileName().toString())
88
+ .filter(name -> name.endsWith("Controller.java"))
89
+ .collect(Collectors.toList())).isEmpty();
90
+ assertThat(source)
91
+ .doesNotContain("org.apache.shiro")
92
+ .doesNotContain("HttpServletRequest")
93
+ .doesNotContain("HttpServletResponse");
94
+ assertThat(JAVA_ROOT.resolve("com/union/control/schedule/ScheduledTaskScheduler.java")).exists();
95
+ assertThat(JAVA_ROOT.resolve("com/union/control/schedule/ScheduledExecutionToken.java")).exists();
96
+ }
97
+
98
+ private static String source(String relative) throws Exception {
99
+ return new String(Files.readAllBytes(JAVA_ROOT.resolve(relative)), StandardCharsets.UTF_8);
100
+ }
101
+
102
+ private static String resource(String relative) throws Exception {
103
+ return new String(Files.readAllBytes(Paths.get("src/main/resources").resolve(relative)),
104
+ StandardCharsets.UTF_8);
105
+ }
106
+
107
+ }
@@ -0,0 +1,89 @@
1
+ package com.union.control;
2
+
3
+ import com.fasterxml.jackson.databind.ObjectMapper;
4
+ import com.union.control.mapper.AgentExecutionMapper;
5
+ import com.union.control.mapper.ConversationMapper;
6
+ import com.union.control.mapper.ScheduledTaskMapper;
7
+ import com.union.control.service.impl.ConversationServiceImpl;
8
+ import org.junit.Test;
9
+
10
+ import java.nio.charset.StandardCharsets;
11
+ import java.nio.file.Files;
12
+ import java.nio.file.Paths;
13
+ import java.util.Collections;
14
+
15
+ import static org.junit.Assert.assertFalse;
16
+ import static org.junit.Assert.assertTrue;
17
+ import static org.assertj.core.api.Assertions.assertThatThrownBy;
18
+ import static org.mockito.Mockito.mock;
19
+ import static org.mockito.Mockito.verify;
20
+ import static org.mockito.Mockito.when;
21
+
22
+ public class ConversationServiceTest {
23
+ @Test
24
+ public void parsesAuthenticatedUserFromJsonBeforeCallingMapper() {
25
+ ConversationMapper conversations = mock(ConversationMapper.class);
26
+ AgentExecutionMapper executions = mock(AgentExecutionMapper.class);
27
+ ScheduledTaskMapper scheduledTasks = mock(ScheduledTaskMapper.class);
28
+ ConversationServiceImpl service = new ConversationServiceImpl(
29
+ conversations, executions, scheduledTasks, new ObjectMapper());
30
+ when(conversations.findConversations(TestJson.USER_ID, 20))
31
+ .thenReturn(Collections.emptyList());
32
+
33
+ service.conversations(TestJson.request("limit", 20));
34
+
35
+ verify(conversations).findConversations(TestJson.USER_ID, 20);
36
+ }
37
+
38
+ @Test
39
+ public void conversationDetailsLoadsExecutionsOnce() {
40
+ ConversationMapper conversations = mock(ConversationMapper.class);
41
+ AgentExecutionMapper executions = mock(AgentExecutionMapper.class);
42
+ when(conversations.findConversation(TestJson.USER_ID, "thread-1"))
43
+ .thenReturn(new java.util.LinkedHashMap<>());
44
+ when(executions.findExecutions(TestJson.USER_ID, "thread-1"))
45
+ .thenReturn(Collections.emptyList());
46
+ new ConversationServiceImpl(conversations, executions,
47
+ mock(ScheduledTaskMapper.class), new ObjectMapper())
48
+ .conversation(TestJson.request("conversationId", "thread-1"));
49
+ verify(executions).findExecutions(TestJson.USER_ID, "thread-1");
50
+ }
51
+
52
+ @Test
53
+ public void deletingConversationAlsoDeletesItsClaimedScheduledRun() {
54
+ ConversationMapper conversations = mock(ConversationMapper.class);
55
+ AgentExecutionMapper executions = mock(AgentExecutionMapper.class);
56
+ ScheduledTaskMapper scheduledTasks = mock(ScheduledTaskMapper.class);
57
+ ConversationServiceImpl service = new ConversationServiceImpl(
58
+ conversations, executions, scheduledTasks, new ObjectMapper());
59
+ when(conversations.softDeleteConversation("scheduled-7", TestJson.USER_ID))
60
+ .thenReturn(1);
61
+
62
+ service.deleteConversation(TestJson.request("conversationId", "scheduled-7"));
63
+
64
+ verify(scheduledTasks).softDeleteByConversation("scheduled-7", TestJson.USER_ID);
65
+ }
66
+
67
+ @Test
68
+ public void conversationMessagesRejectMissingOwnership() {
69
+ ConversationMapper conversations = mock(ConversationMapper.class);
70
+ ConversationServiceImpl service = new ConversationServiceImpl(
71
+ conversations, mock(AgentExecutionMapper.class),
72
+ mock(ScheduledTaskMapper.class), new ObjectMapper());
73
+ when(conversations.requireOwned("foreign-thread", TestJson.USER_ID, false))
74
+ .thenReturn(null);
75
+
76
+ assertThatThrownBy(() -> service.conversationMessages(
77
+ TestJson.request("conversationId", "foreign-thread")))
78
+ .isInstanceOf(java.util.NoSuchElementException.class);
79
+ }
80
+
81
+ @Test
82
+ public void claimedScheduledRunCleanupIsALogicalDelete() throws Exception {
83
+ String mapper = new String(Files.readAllBytes(Paths.get(
84
+ "src/main/resources/mapper/ScheduledTaskMapper.xml")), StandardCharsets.UTF_8);
85
+
86
+ assertTrue(mapper.contains("SET r.delete_flag=0"));
87
+ assertFalse(mapper.contains("DELETE FROM agent_scheduled_task_run"));
88
+ }
89
+ }
@@ -0,0 +1,26 @@
1
+ package com.union.control;
2
+
3
+ import com.fasterxml.jackson.databind.ObjectMapper;
4
+ import com.union.control.mapper.MemoryStoreMapper;
5
+ import com.union.control.service.impl.MemoryStoreServiceImpl;
6
+ import org.junit.Test;
7
+
8
+ import java.util.Collections;
9
+
10
+ import static org.mockito.Mockito.mock;
11
+ import static org.mockito.Mockito.verify;
12
+ import static org.mockito.Mockito.when;
13
+
14
+ public class MemoryStoreServiceTest {
15
+ @Test
16
+ public void parsesAuthenticatedUserFromJsonBeforeCallingMapper() {
17
+ MemoryStoreMapper mapper = mock(MemoryStoreMapper.class);
18
+ MemoryStoreServiceImpl service = new MemoryStoreServiceImpl(mapper, new ObjectMapper());
19
+ String path = TestJson.USER_ID + "/personal/notes.md";
20
+ when(mapper.readMemory(TestJson.USER_ID, path)).thenReturn(Collections.emptyList());
21
+
22
+ service.memoryRead(TestJson.request("path", path, "maxChars", 100));
23
+
24
+ verify(mapper).readMemory(TestJson.USER_ID, path);
25
+ }
26
+ }
@@ -0,0 +1,52 @@
1
+ package com.union.control;
2
+
3
+ import com.fasterxml.jackson.databind.ObjectMapper;
4
+ import com.union.control.service.impl.RunningAnalysisMockServiceImpl;
5
+ import org.junit.Test;
6
+ import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
7
+
8
+ import java.nio.charset.StandardCharsets;
9
+ import java.nio.file.Files;
10
+ import java.nio.file.Path;
11
+ import java.nio.file.Paths;
12
+
13
+ import static org.assertj.core.api.Assertions.assertThat;
14
+
15
+ public class PydanticAiControlContractTest {
16
+ @Test
17
+ public void springSelectsTheRunningAnalysisProductionConstructor() {
18
+ java.lang.reflect.Constructor<?>[] constructors = new AutowiredAnnotationBeanPostProcessor()
19
+ .determineCandidateConstructors(RunningAnalysisMockServiceImpl.class,
20
+ "runningAnalysisMockService");
21
+
22
+ assertThat(constructors).hasSize(1);
23
+ assertThat(constructors[0].getParameterTypes()).containsExactly(ObjectMapper.class);
24
+ }
25
+
26
+ @Test
27
+ public void sharedRequestUtilitiesStayOutsideTheServicePackage() {
28
+ Path root = Paths.get("src/main/java/com/union/control");
29
+
30
+ assertThat(root.resolve("utils/AgentSupport.java")).exists();
31
+ assertThat(root.resolve("service/AgentSupport.java")).doesNotExist();
32
+ assertThat(root.resolve("service/ServiceExceptions.java")).doesNotExist();
33
+ }
34
+
35
+ @Test
36
+ public void serviceModuleHasNoAuthenticationRuntime() throws Exception {
37
+ Path root = Paths.get("src/main/java");
38
+ StringBuilder sources = new StringBuilder();
39
+ Files.walk(root).filter(path -> path.toString().endsWith(".java")).forEach(path -> {
40
+ try {
41
+ sources.append(new String(Files.readAllBytes(path), StandardCharsets.UTF_8));
42
+ } catch (Exception error) {
43
+ throw new RuntimeException(error);
44
+ }
45
+ });
46
+ assertThat(sources.toString())
47
+ .doesNotContain("org.apache.shiro")
48
+ .doesNotContain("AuthContextHolder")
49
+ .doesNotContain("currentUserId()")
50
+ .doesNotContain("@RequiresPermissions");
51
+ }
52
+ }
@@ -0,0 +1,45 @@
1
+ package com.union.control;
2
+
3
+ import com.fasterxml.jackson.core.type.TypeReference;
4
+ import com.fasterxml.jackson.databind.ObjectMapper;
5
+
6
+ import java.util.LinkedHashMap;
7
+ import java.util.Map;
8
+
9
+ public final class TestJson {
10
+ public static final String USER_ID = "local-user";
11
+ public static final String ORG_CODE = "local-org";
12
+ public static final String ROLE_ID = "local-role";
13
+ private static final ObjectMapper JSON = new ObjectMapper();
14
+
15
+ private TestJson() {}
16
+
17
+ public static String request(String raw) {
18
+ try {
19
+ Map<String, Object> parsed = JSON.readValue(
20
+ raw, new TypeReference<Map<String, Object>>() {});
21
+ return request(parsed);
22
+ } catch (Exception error) {
23
+ throw new AssertionError(error);
24
+ }
25
+ }
26
+
27
+ public static String request(Map<String, Object> values) {
28
+ Map<String, Object> input = new LinkedHashMap<>(values);
29
+ input.put("userId", USER_ID);
30
+ input.put("orgCode", ORG_CODE);
31
+ input.put("roleId", ROLE_ID);
32
+ try {
33
+ return JSON.writeValueAsString(input);
34
+ } catch (Exception error) {
35
+ throw new AssertionError(error);
36
+ }
37
+ }
38
+
39
+ public static String request(Object... entries) {
40
+ Map<String, Object> input = new LinkedHashMap<>();
41
+ for (int index = 0; index < entries.length; index += 2)
42
+ input.put(String.valueOf(entries[index]), entries[index + 1]);
43
+ return request(input);
44
+ }
45
+ }
@@ -0,0 +1,53 @@
1
+ package com.union.control.dubbo;
2
+
3
+ import ch.qos.logback.classic.Logger;
4
+ import ch.qos.logback.classic.spi.ILoggingEvent;
5
+ import ch.qos.logback.core.read.ListAppender;
6
+ import com.alibaba.dubbo.rpc.Invocation;
7
+ import com.alibaba.dubbo.rpc.Invoker;
8
+ import com.alibaba.dubbo.rpc.Result;
9
+ import com.union.control.service.ConversationService;
10
+ import org.junit.Test;
11
+ import org.slf4j.LoggerFactory;
12
+
13
+ import java.util.List;
14
+ import java.util.stream.Collectors;
15
+
16
+ import static org.assertj.core.api.Assertions.assertThat;
17
+ import static org.mockito.Mockito.mock;
18
+ import static org.mockito.Mockito.never;
19
+ import static org.mockito.Mockito.verify;
20
+ import static org.mockito.Mockito.when;
21
+
22
+ public class ProviderAccessLogFilterTest {
23
+
24
+ @SuppressWarnings("unchecked")
25
+ @Test
26
+ public void logsOnlyTheRpcBoundaryAndDelegatesTheCall() {
27
+ Invoker<ConversationService> invoker = mock(Invoker.class);
28
+ Invocation invocation = mock(Invocation.class);
29
+ Result result = mock(Result.class);
30
+ when(invoker.getInterface()).thenReturn(ConversationService.class);
31
+ when(invocation.getMethodName()).thenReturn("conversations");
32
+ when(invoker.invoke(invocation)).thenReturn(result);
33
+
34
+ Logger logger = (Logger) LoggerFactory.getLogger(ProviderAccessLogFilter.class);
35
+ ListAppender<ILoggingEvent> appender = new ListAppender<>();
36
+ appender.start();
37
+ logger.addAppender(appender);
38
+ try {
39
+ assertThat(new ProviderAccessLogFilter().invoke(invoker, invocation)).isSameAs(result);
40
+ } finally {
41
+ logger.detachAppender(appender);
42
+ }
43
+
44
+ List<String> messages = appender.list.stream()
45
+ .map(ILoggingEvent::getFormattedMessage)
46
+ .collect(Collectors.toList());
47
+ assertThat(messages.toString())
48
+ .contains("request started: service=ConversationService, method=conversations")
49
+ .contains("request completed: service=ConversationService, method=conversations");
50
+ verify(invoker).invoke(invocation);
51
+ verify(invocation, never()).getArguments();
52
+ }
53
+ }
@@ -0,0 +1,23 @@
1
+ package com.union.control.local.sensitive;
2
+
3
+ import com.epcc.commons.securityproxy.api.SymmetricalSecurityService;
4
+ import org.junit.Test;
5
+ import org.springframework.context.annotation.AnnotationConfigApplicationContext;
6
+
7
+ import static org.assertj.core.api.Assertions.assertThat;
8
+
9
+ public class LocalSensitiveProxyConfigurationTest {
10
+
11
+ @Test
12
+ public void defaultProfileProvidesTheLocalSensitiveProxy() {
13
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
14
+ context.register(LocalSensitiveProxyConfiguration.class);
15
+ context.refresh();
16
+ try {
17
+ assertThat(context.getBean("sensitiveProxy"))
18
+ .isInstanceOf(SymmetricalSecurityService.class);
19
+ } finally {
20
+ context.close();
21
+ }
22
+ }
23
+ }