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.
- package/PROJECT_OVERVIEW.md +405 -0
- package/README.md +177 -0
- package/ark-control/pom.xml +142 -0
- package/ark-control/src/local-mock/java/com/epcc/commons/securityproxy/api/SecurityResult.java +14 -0
- package/ark-control/src/local-mock/java/com/epcc/commons/securityproxy/api/SymmetricalSecurityService.java +11 -0
- package/ark-control/src/local-mock/java/com/epcc/dubbo/result/Result.java +29 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/annotation/EnDecryptField.java +16 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/annotation/EnDecryptFieldLong.java +17 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/annotation/EnDecryptFieldWithTag.java +16 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/exception/BaseDataErrorCode.java +26 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/exception/CheckException.java +33 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/exception/ErrorCode.java +9 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/redis/RedisCacheService.java +131 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/util/Constant.java +24 -0
- package/ark-control/src/local-mock/java/com/nucc/channel/ark/common/util/ResultUtil.java +9 -0
- package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalMockSensitiveProxy.java +40 -0
- package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalRedisCacheService.java +45 -0
- package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalSensitiveHostConfiguration.java +27 -0
- package/ark-control/src/local-mock/java/com/union/control/local/sensitive/LocalSensitiveProxyConfiguration.java +16 -0
- package/ark-control/src/main/java/com/union/control/ArkControlApplication.java +17 -0
- package/ark-control/src/main/java/com/union/control/dubbo/ProviderAccessLogFilter.java +45 -0
- package/ark-control/src/main/java/com/union/control/mapper/AgentExecutionMapper.java +35 -0
- package/ark-control/src/main/java/com/union/control/mapper/ConversationMapper.java +44 -0
- package/ark-control/src/main/java/com/union/control/mapper/MemoryStoreMapper.java +41 -0
- package/ark-control/src/main/java/com/union/control/mapper/ScheduledTaskMapper.java +96 -0
- package/ark-control/src/main/java/com/union/control/mapper/SensitiveAddressBookDemo.java +31 -0
- package/ark-control/src/main/java/com/union/control/mapper/SensitiveDataDemoMapper.java +24 -0
- package/ark-control/src/main/java/com/union/control/mapper/interceptor/AESInterceptor.java +265 -0
- package/ark-control/src/main/java/com/union/control/mapper/interceptor/AddressBookHandler.java +105 -0
- package/ark-control/src/main/java/com/union/control/schedule/ScheduledExecutionToken.java +55 -0
- package/ark-control/src/main/java/com/union/control/schedule/ScheduledTaskScheduler.java +206 -0
- package/ark-control/src/main/java/com/union/control/service/impl/AgentExecutionServiceImpl.java +212 -0
- package/ark-control/src/main/java/com/union/control/service/impl/AgentProxyServiceImpl.java +143 -0
- package/ark-control/src/main/java/com/union/control/service/impl/ConversationServiceImpl.java +245 -0
- package/ark-control/src/main/java/com/union/control/service/impl/MemoryStoreServiceImpl.java +252 -0
- package/ark-control/src/main/java/com/union/control/service/impl/RunningAnalysisMockServiceImpl.java +301 -0
- package/ark-control/src/main/java/com/union/control/service/impl/ScheduledTaskServiceImpl.java +576 -0
- package/ark-control/src/main/java/com/union/control/service/impl/SensitiveDataDemoServiceImpl.java +144 -0
- package/ark-control/src/main/java/com/union/control/service/sensitive/RedisRevealTokenStore.java +90 -0
- package/ark-control/src/main/java/com/union/control/service/sensitive/SensitiveRevealProcessor.java +319 -0
- package/ark-control/src/main/java/com/union/control/service/sensitive/SensitiveRevealServiceImpl.java +72 -0
- package/ark-control/src/main/java/com/union/control/utils/AgentSupport.java +103 -0
- package/ark-control/src/main/java/com/union/control/utils/security/SymmetricalSecurityUtils.java +160 -0
- package/ark-control/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter +1 -0
- package/ark-control/src/main/resources/application.properties +4 -0
- package/ark-control/src/main/resources/application.yml +32 -0
- package/ark-control/src/main/resources/dubbo-provider.xml +20 -0
- package/ark-control/src/main/resources/mapper/AgentExecutionMapper.xml +75 -0
- package/ark-control/src/main/resources/mapper/ConversationMapper.xml +110 -0
- package/ark-control/src/main/resources/mapper/MemoryStoreMapper.xml +74 -0
- package/ark-control/src/main/resources/mapper/ScheduledTaskMapper.xml +286 -0
- package/ark-control/src/main/resources/mapper/SensitiveDataDemoMapper.xml +55 -0
- package/ark-control/src/main/resources/schema.sql +146 -0
- package/ark-control/src/test/java/com/union/control/AgentExecutionServiceTest.java +170 -0
- package/ark-control/src/test/java/com/union/control/ArkControlStructureContractTest.java +107 -0
- package/ark-control/src/test/java/com/union/control/ConversationServiceTest.java +89 -0
- package/ark-control/src/test/java/com/union/control/MemoryStoreServiceTest.java +26 -0
- package/ark-control/src/test/java/com/union/control/PydanticAiControlContractTest.java +52 -0
- package/ark-control/src/test/java/com/union/control/TestJson.java +45 -0
- package/ark-control/src/test/java/com/union/control/dubbo/ProviderAccessLogFilterTest.java +53 -0
- package/ark-control/src/test/java/com/union/control/local/sensitive/LocalSensitiveProxyConfigurationTest.java +23 -0
- package/ark-control/src/test/java/com/union/control/mapper/interceptor/AESInterceptorCompatibilityTest.java +505 -0
- package/ark-control/src/test/java/com/union/control/schedule/ScheduledExecutionTokenTest.java +27 -0
- package/ark-control/src/test/java/com/union/control/schedule/ScheduledTaskSchedulerTest.java +51 -0
- package/ark-control/src/test/java/com/union/control/service/AgentProxyServiceTest.java +111 -0
- package/ark-control/src/test/java/com/union/control/service/ScheduledTaskServiceTest.java +483 -0
- package/ark-control/src/test/java/com/union/control/service/impl/SensitiveDataDemoServiceImplTest.java +104 -0
- package/ark-control/src/test/java/com/union/control/service/sensitive/RedisRevealTokenStoreTest.java +65 -0
- package/ark-control/src/test/java/com/union/control/service/sensitive/SensitiveRevealBoundaryTest.java +99 -0
- package/ark-control/src/test/java/com/union/control/service/sensitive/SensitiveRevealProcessorCodecTest.java +111 -0
- package/ark-control/src/test/java/com/union/control/service/sensitive/SensitiveRevealProcessorTest.java +111 -0
- package/ark-control/src/test/java/com/union/control/utils/security/SymmetricalSecurityUtilsCompatibilityTest.java +87 -0
- package/ark-control-facade/pom.xml +16 -0
- package/ark-control-facade/src/main/java/com/union/control/service/AgentExecutionService.java +8 -0
- package/ark-control-facade/src/main/java/com/union/control/service/AgentProxyService.java +7 -0
- package/ark-control-facade/src/main/java/com/union/control/service/AgentResponse.java +22 -0
- package/ark-control-facade/src/main/java/com/union/control/service/ConversationService.java +12 -0
- package/ark-control-facade/src/main/java/com/union/control/service/MemoryStoreService.java +12 -0
- package/ark-control-facade/src/main/java/com/union/control/service/RunningAnalysisMockService.java +10 -0
- package/ark-control-facade/src/main/java/com/union/control/service/ScheduledTaskService.java +40 -0
- package/ark-control-facade/src/main/java/com/union/control/service/SensitiveDataDemoService.java +13 -0
- package/ark-control-facade/src/main/java/com/union/control/service/sensitive/SensitiveRevealService.java +18 -0
- package/ark-web/README.md +80 -0
- package/ark-web/pom.xml +105 -0
- package/ark-web/src/local-mock/java/com/epcc/arkweb/mock/ArkAuthServiceMock.java +105 -0
- package/ark-web/src/local-mock/java/com/epcc/arkweb/mock/LocalKaptchaConfiguration.java +26 -0
- package/ark-web/src/main/java/com/epcc/arkweb/Application.java +13 -0
- package/ark-web/src/main/java/com/epcc/arkweb/config/InterceptorConfig.java +20 -0
- package/ark-web/src/main/java/com/epcc/arkweb/config/Realm.java +64 -0
- package/ark-web/src/main/java/com/epcc/arkweb/config/ShiroConfig.java +129 -0
- package/ark-web/src/main/java/com/epcc/arkweb/filter/LoginFormFilter.java +43 -0
- package/ark-web/src/main/java/com/epcc/arkweb/helper/AuthContextHolder.java +39 -0
- package/ark-web/src/main/java/com/epcc/arkweb/helper/AuthenticatedRequest.java +91 -0
- package/ark-web/src/main/java/com/epcc/arkweb/model/ShiroUser.java +21 -0
- package/ark-web/src/main/java/com/epcc/arkweb/utils/ResultMsg.java +19 -0
- package/ark-web/src/main/java/com/epcc/arkweb/vo/llm/ScheduledTaskCommandVO.java +30 -0
- package/ark-web/src/main/java/com/epcc/arkweb/vo/llm/ScheduledTaskQueryVO.java +20 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/CommonController.java +25 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentAuthorizationInterceptor.java +229 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentController.java +165 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentPermission.java +13 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/llm/LlmController.java +209 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/llm/ScheduledTaskController.java +160 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/sensitive/reveal/SensitiveCaptchaService.java +146 -0
- package/ark-web/src/main/java/com/epcc/arkweb/web/sensitive/reveal/SensitiveRevealController.java +163 -0
- package/ark-web/src/main/resources/application.properties +1 -0
- package/ark-web/src/main/resources/application.yml +23 -0
- package/ark-web/src/main/resources/dubbo-consumer.xml +19 -0
- package/ark-web/src/production-overlay/java/com/epcc/arkweb/config/CasShiroConfig.java +229 -0
- package/ark-web/src/production-overlay/java/com/epcc/arkweb/config/InterceptorConfig.java +35 -0
- package/ark-web/src/production-overlay/java/com/epcc/arkweb/config/ShiroConfig.java +161 -0
- package/ark-web/src/test/java/com/epcc/arkweb/ArkWebStructureContractTest.java +290 -0
- package/ark-web/src/test/java/com/epcc/arkweb/ShiroTestSupport.java +32 -0
- package/ark-web/src/test/java/com/epcc/arkweb/config/LocalShiroIntegrationTest.java +121 -0
- package/ark-web/src/test/java/com/epcc/arkweb/helper/AuthenticatedRequestTest.java +131 -0
- package/ark-web/src/test/java/com/epcc/arkweb/local/LocalArkAuthServiceMockTest.java +17 -0
- package/ark-web/src/test/java/com/epcc/arkweb/web/llm/AgentAuthorizationInterceptorTest.java +134 -0
- package/ark-web/src/test/java/com/epcc/arkweb/web/llm/AgentControllerAuthorizationTest.java +97 -0
- package/ark-web/src/test/java/com/epcc/arkweb/web/llm/LlmControllerTest.java +113 -0
- package/ark-web/src/test/java/com/epcc/arkweb/web/sensitive/reveal/SensitiveRevealControllerTest.java +273 -0
- package/package.json +18 -0
- package/pom.xml +16 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Project Overview
|
|
2
|
+
|
|
3
|
+
## Mandatory Architecture Contract
|
|
4
|
+
|
|
5
|
+
This section is the highest-level implementation constraint for every future
|
|
6
|
+
feature iteration. New requirements must comply with it before lower sections,
|
|
7
|
+
existing scenario code, or tests are considered. Existing code that conflicts
|
|
8
|
+
with this contract is technical debt to remove, not a precedent to copy.
|
|
9
|
+
|
|
10
|
+
### Web authentication and JSON-only service boundary
|
|
11
|
+
|
|
12
|
+
- `ark-web` is merged into the existing production Web application. Browser
|
|
13
|
+
routes reuse its existing Shiro/CAS implementation and authorization annotations.
|
|
14
|
+
The standalone build mirrors the production `ShiroConfig`, `Realm`,
|
|
15
|
+
`LoginFormFilter`, and `InterceptorConfig` names and lifecycle; only the
|
|
16
|
+
external `arkAuthService` bean is replaced under `src/local-mock/java`.
|
|
17
|
+
The production-overlay copies of both filter-chain configurations delegate
|
|
18
|
+
only `/agent/**` to the Agent guard with `anon` before their catch-all `authc`.
|
|
19
|
+
They replace the matching production files during integration; runtime source
|
|
20
|
+
must not define another Realm, Shiro configuration, CAS token, or authentication filter.
|
|
21
|
+
- `ark-control` is a trusted, independently deployed Dubbo provider. Business services must not
|
|
22
|
+
read Shiro subjects, cookies, thread-local authentication, or call helpers such
|
|
23
|
+
as `currentUserId()`. The module has no Shiro dependency.
|
|
24
|
+
- After Web authentication succeeds, `AuthenticatedRequest` overwrites any
|
|
25
|
+
client-supplied `userId`, `orgCode`, and `roleId` with the authenticated values
|
|
26
|
+
and serializes the complete backend input as one JSON string.
|
|
27
|
+
- User-facing business service methods accept that JSON string, parse and validate
|
|
28
|
+
it, then pass the parsed values to their mapper. Mapper ownership predicates
|
|
29
|
+
continue to use `userId`; the service trusts the Web boundary that supplied it.
|
|
30
|
+
- Background scheduler mechanics that create or consume execution credentials
|
|
31
|
+
live in `ark-control`. Backend-only scheduling state transitions may keep
|
|
32
|
+
typed internal method parameters because they are not public request inputs.
|
|
33
|
+
|
|
34
|
+
### One browser-to-Agent gateway
|
|
35
|
+
|
|
36
|
+
- Domain controllers own browser and MySQL interactions for their domain. They
|
|
37
|
+
must not proxy requests to a model service or expose callbacks, context APIs,
|
|
38
|
+
or tool replicas for py-app. All browser-to-Agent traffic belongs to
|
|
39
|
+
`LlmController` and the shared `AgentProxyService` execution methods.
|
|
40
|
+
- A new business scenario may add its domain specialist Agent and domain tools
|
|
41
|
+
in py-app, plus its own CRUD/persistence services in control when required. It
|
|
42
|
+
must not add a scenario-specific LLM controller route, proxy method, bearer
|
|
43
|
+
credential, long-timeout HTTP client, tool forwarding endpoint, completion
|
|
44
|
+
callback, or alternate conversation persistence path.
|
|
45
|
+
- Scheduling, batching, and other orchestration are invocation mechanisms, not
|
|
46
|
+
Agent domains. They may decide when to invoke work and persist their own job
|
|
47
|
+
state, but they must call the same normal Agent execution plane as an
|
|
48
|
+
interactive caller.
|
|
49
|
+
|
|
50
|
+
### Reuse stream or non-stream runs
|
|
51
|
+
|
|
52
|
+
- Use `/llm/chatMessage` when the caller needs AG-UI streaming and
|
|
53
|
+
`/llm/chatMessageSync` when it needs a final synchronous result. Both paths
|
|
54
|
+
must preserve the same CAS-authenticated identity and call the corresponding
|
|
55
|
+
shared py-app run endpoint.
|
|
56
|
+
- Background work such as a due scheduled occurrence must invoke the shared
|
|
57
|
+
non-stream application service behind `chatMessageSync`; it must not create a
|
|
58
|
+
second browser route just to forward to the model, nor call a scenario-specific
|
|
59
|
+
py-app route.
|
|
60
|
+
- Domain job state and final result payload may remain in domain tables. Normal
|
|
61
|
+
conversation, execution, and message records must be created through the
|
|
62
|
+
shared `ConversationService` and `AgentExecutionService` paths rather than
|
|
63
|
+
direct inserts from a domain mapper.
|
|
64
|
+
|
|
65
|
+
### Preserve one identity and tool path
|
|
66
|
+
|
|
67
|
+
- The Web application authenticates interactive execution and forwards the
|
|
68
|
+
validated CAS cookie unchanged. Scheduled execution uses a separate
|
|
69
|
+
single-occurrence, short-lived, sessionless token; Control stores only its
|
|
70
|
+
SHA-256 hash and never constructs a Shiro identity for it.
|
|
71
|
+
- Scheduled traffic carries only `Authorization: Scheduled <token>`. It enters
|
|
72
|
+
py through `/agent/v1/runs/scheduled`, then calls
|
|
73
|
+
`/agent/scheduledTaskAuthorize`. Web resolves the active run through Control,
|
|
74
|
+
calls the production `arkAuthService.queryResource` bean with the
|
|
75
|
+
stored role ID, and requires `/assistantManager/page`. The response includes
|
|
76
|
+
a database-backed trusted context for subsequent Agent tools. Those tools must
|
|
77
|
+
use `X-Agent-Trusted-Context`; the raw scheduled bearer is not accepted on a
|
|
78
|
+
tool route. The non-Shiro guard re-resolves the run and live resources for
|
|
79
|
+
every tool call and never constructs a Subject.
|
|
80
|
+
- Each business tool has one control endpoint and one authorization
|
|
81
|
+
implementation. Scenario-prefixed clones are forbidden.
|
|
82
|
+
|
|
83
|
+
### Layer and review gate
|
|
84
|
+
|
|
85
|
+
Transaction/control-plane packages contain reusable orchestration and runtime
|
|
86
|
+
mechanisms only; scenario business code belongs in its domain package. Before
|
|
87
|
+
implementation, every feature proposal must identify: domain persistence
|
|
88
|
+
ownership, the specialist and tools added or reused, stream versus non-stream
|
|
89
|
+
mode, the shared LLM entrypoint, and the full cookie identity path. Introducing
|
|
90
|
+
a second path in any category requires an explicit architecture decision
|
|
91
|
+
recorded in this section before code is written. Tests must enforce reuse of the
|
|
92
|
+
shared route and shared identity/tool path, and reviewers must reject violations
|
|
93
|
+
even when isolated feature tests pass.
|
|
94
|
+
|
|
95
|
+
Java sources follow the production project's responsibility-based packages:
|
|
96
|
+
MyBatis interfaces, application services, and timer entrypoints live in
|
|
97
|
+
`ark-control`; the Agent-only guard stays beside `AgentController`. Production
|
|
98
|
+
Shiro configuration, filters, Realm, and identity model are reused as-is.
|
|
99
|
+
Scheduled-task code must not introduce a parallel domain package containing its
|
|
100
|
+
own mapper, service, Web facade, production-authentication wrapper, or local mock.
|
|
101
|
+
|
|
102
|
+
### Production integration boundary and review baseline
|
|
103
|
+
|
|
104
|
+
Confirmed by the project owner on 2026-09-08: this repository is a local
|
|
105
|
+
simulation and a source integration workspace. Its standalone JARs, POMs,
|
|
106
|
+
configuration files, and Dubbo XML are not deployed wholesale to production.
|
|
107
|
+
Selected business changes are integrated into the existing production projects.
|
|
108
|
+
|
|
109
|
+
- Production already has the correct, independently maintained database schema
|
|
110
|
+
and configuration. Local ignored `schema.sql` and `application.yml` files,
|
|
111
|
+
local schema initialization, and local scheduler defaults are not production
|
|
112
|
+
deployment inputs. Missing local files may affect clean-checkout testing,
|
|
113
|
+
but must not be reported as missing production schema/configuration or as
|
|
114
|
+
production scheduling being enabled without evidence from the integration.
|
|
115
|
+
- Production excludes all demo/mock implementations and their wiring. This
|
|
116
|
+
includes local sensitive crypto/auth substitutes, compatibility copies,
|
|
117
|
+
`SensitiveDataDemo*`, and `RunningAnalysisMockService*`. Production retains
|
|
118
|
+
its real crypto, authentication, and business services. Exclusion also covers
|
|
119
|
+
demo controller methods, constructor dependencies, mapper registrations, and
|
|
120
|
+
Dubbo references/exports; removing only the implementation files is insufficient.
|
|
121
|
+
- Production already has its own complete Dubbo logging. It does not import
|
|
122
|
+
`ProviderAccessLogFilter`, its SPI registration, or the local XML filter
|
|
123
|
+
setting. Findings in this local logger do not establish a production log leak.
|
|
124
|
+
Preserve the existing production logging implementation.
|
|
125
|
+
- Under this confirmed integration boundary, review findings F01, F03, F04,
|
|
126
|
+
F06, and F07 from the 2026-09-08 audit are not production release blockers.
|
|
127
|
+
Reopen them only if the actual integration starts importing the excluded
|
|
128
|
+
sources/configuration or contradicts these assumptions. Review the selected
|
|
129
|
+
production changeset, not a hypothetical deployment of this mock application.
|
|
130
|
+
- Implement new functionality against the production dependency versions;
|
|
131
|
+
do not downgrade the host to match the local build or upgrade the host just
|
|
132
|
+
to accommodate new code. Production reference sources are
|
|
133
|
+
`/Users/simon/code/restored/ark-web` and
|
|
134
|
+
`/Users/simon/code/restored/ark-control`; these are read-only reference inputs.
|
|
135
|
+
The Web parent POM specifies Boot 2.1.18.RELEASE, whose BOM manages Spring
|
|
136
|
+
5.1.19.RELEASE. Its Jackson BOM override is 2.17.2; Shiro is 1.12.0 and Dubbo
|
|
137
|
+
is 2.6.9. The production `InterceptorConfig` already implements
|
|
138
|
+
`WebMvcConfigurer`; the overlay compiles against Spring 5.1.19. F02's
|
|
139
|
+
Spring-4-only compilation failure is not a production incompatibility.
|
|
140
|
+
- The restored Control snapshot currently contains only dao/common child
|
|
141
|
+
POMs, with versions inherited from an absent root `ark-control/pom.xml`.
|
|
142
|
+
Do not infer Control's Spring/MyBatis versions from the local simulation or
|
|
143
|
+
the Web parent. Obtain its root/effective POM before claiming full production
|
|
144
|
+
dependency compatibility. Host-specific dependency overrides take precedence
|
|
145
|
+
over a Boot version alone.
|
|
146
|
+
|
|
147
|
+
### Cross-service timeout review
|
|
148
|
+
|
|
149
|
+
Inspect `/Users/simon/code/union-py-app` before assessing Agent timeout coverage.
|
|
150
|
+
Py owns Agent execution deadlines; Java transport timeouts are a separate
|
|
151
|
+
connection/resource safeguard, not another Agent lifecycle implementation.
|
|
152
|
+
|
|
153
|
+
`AGENT_MAX_RUN_SECONDS` is the shared execution duration, defaulting to 900
|
|
154
|
+
seconds. Set the same value in web, control, and py-app. Py's
|
|
155
|
+
`ExecutionCoordinator` applies it across streaming preparation and execution;
|
|
156
|
+
`sync_runs._sync_response` applies one `anyio.fail_after` scope across the shared
|
|
157
|
+
router and root Agent for both `/sync` and `/scheduled`, returning HTTP 504 with
|
|
158
|
+
`execution_timeout` on expiry. SSE comment keepalives remain every 15 seconds;
|
|
159
|
+
existing authentication, state, and tool HTTP timeouts remain unchanged.
|
|
160
|
+
|
|
161
|
+
Java Agent HTTP connect/read timeouts and the Agent proxy Dubbo reference use
|
|
162
|
+
this same duration (converted to milliseconds), instead of unbounded socket
|
|
163
|
+
waits or the historical 120-second RPC timeout. HTTP timeouts bound individual
|
|
164
|
+
socket waits; py remains responsible for the total execution deadline. No
|
|
165
|
+
second execution lifecycle is introduced. Preserve the scheduled stale-run
|
|
166
|
+
and token-expiry margins above that duration (defaults 930 and 960 seconds).
|
|
167
|
+
The F05 deadline gap is covered by sync/scheduled router, root, and combined
|
|
168
|
+
budget cancellation tests and Java silent-upstream tests.
|
|
169
|
+
|
|
170
|
+
## Purpose
|
|
171
|
+
|
|
172
|
+
`ark-web` is the browser-facing control plane for the PydanticAI service;
|
|
173
|
+
`ark-control` is its trusted Dubbo provider, and `ark-control-facade` is their
|
|
174
|
+
shared serializable contract. Together they own authenticated
|
|
175
|
+
conversation/run state, standard AG-UI message
|
|
176
|
+
persistence, the official Memory store protocol adapter, and transparent AG-UI
|
|
177
|
+
SSE proxying.
|
|
178
|
+
|
|
179
|
+
## Runtime
|
|
180
|
+
|
|
181
|
+
- Java 8
|
|
182
|
+
- Standalone simulation: Spring Boot 1.5.22.RELEASE / Spring 4.3.25.RELEASE
|
|
183
|
+
- Production Web: Spring Boot 2.1.18.RELEASE / Spring 5.1.19.RELEASE; use the
|
|
184
|
+
production POM overrides described above. Production Control version is
|
|
185
|
+
pending verification of its missing parent POM.
|
|
186
|
+
- MySQL 8
|
|
187
|
+
- Browser APIs remain under `/llm/**`
|
|
188
|
+
- Internal py-app APIs remain under `/agent/**`; they must not move under the
|
|
189
|
+
production-anonymous `/api/**` namespace. Interactive calls validate the CAS
|
|
190
|
+
session and scheduled calls use the dedicated token/context guard.
|
|
191
|
+
|
|
192
|
+
Only GET and POST endpoints are used in production.
|
|
193
|
+
|
|
194
|
+
Natural-language scheduled-task browser APIs also live under `/llm/**`.
|
|
195
|
+
They create `ONCE`, six-field Spring `CRON`, or fixed `INTERVAL` tasks and
|
|
196
|
+
expose task/run lists, unread results, and an explicit open-result action.
|
|
197
|
+
Draft generation is an ordinary browser call to `/llm/chatMessageSync`; there
|
|
198
|
+
is no scheduled-task-specific model endpoint.
|
|
199
|
+
|
|
200
|
+
## Protocol
|
|
201
|
+
|
|
202
|
+
- `POST /llm/chatMessage` accepts the standard AG-UI `RunAgentInput`, creates
|
|
203
|
+
its persistence row, and transparently proxies AG-UI SSE.
|
|
204
|
+
- `GET /llm/conversationDetails` returns conversation metadata and a
|
|
205
|
+
`messages` array of standard AG-UI messages.
|
|
206
|
+
- `POST /llm/executionCancel` requires `conversationId` and `runId` and forwards
|
|
207
|
+
the owner-scoped cancellation request to py-app. Control does not maintain a
|
|
208
|
+
second cancellation state.
|
|
209
|
+
- `POST /llm/chatMessageSync` keeps the product `{content}` response.
|
|
210
|
+
|
|
211
|
+
There is no execution-current/recovery endpoint, legacy event translation,
|
|
212
|
+
SDK item API, heartbeat event, or dual-write path.
|
|
213
|
+
|
|
214
|
+
## Persistence
|
|
215
|
+
|
|
216
|
+
`ai_conversation` owns only conversation metadata and status.
|
|
217
|
+
|
|
218
|
+
`ai_agent_execution` stores the root and child execution snapshots submitted by
|
|
219
|
+
py-app. Control does not enforce Agent concurrency or execution topology.
|
|
220
|
+
|
|
221
|
+
`ai_conversation_message` stores:
|
|
222
|
+
|
|
223
|
+
- message ID
|
|
224
|
+
- role and role-specific JSON payload
|
|
225
|
+
- an `agent_execution_id` foreign key
|
|
226
|
+
- a stable per-conversation sequence
|
|
227
|
+
- `delete_flag`
|
|
228
|
+
|
|
229
|
+
Browser history reconstructs each child execution as a standard AG-UI
|
|
230
|
+
`ActivityMessage`; model history contains root execution messages only.
|
|
231
|
+
|
|
232
|
+
Browser SSE disconnects forward cancellation to py-app. Py-app owns execution
|
|
233
|
+
timeouts, cancellation precedence, root/child lifecycle, and the final status;
|
|
234
|
+
control persists the final snapshot without maintaining a second execution
|
|
235
|
+
state machine.
|
|
236
|
+
|
|
237
|
+
`ai_memory_file` and `ai_memory_operation` implement PydanticAI Harness
|
|
238
|
+
`SearchableMemoryStore` semantics: bounded read/list/search, CAS versioning,
|
|
239
|
+
operation-ID idempotency, and operation fingerprint conflicts.
|
|
240
|
+
|
|
241
|
+
The local sensitive-data implementation mirrors the restored production
|
|
242
|
+
`AESInterceptor` and `SymmetricalSecurityUtils` contracts. Sensitive statements
|
|
243
|
+
route through general encryption, general decryption, or the AddressBook table
|
|
244
|
+
migration branch. The global reveal mode replaces sensitive plaintext fragments
|
|
245
|
+
with masks and short-lived Redis tokens. AddressBook result rows whose returned
|
|
246
|
+
`role` value is explicitly configured may remain plaintext; missing, unknown, or
|
|
247
|
+
invalid roles stay masked. The authenticated reveal API decrypts only the token's
|
|
248
|
+
fragment. The local simulation supplies a non-cryptographic `sensitiveProxy`
|
|
249
|
+
under the default or explicit `local-sensitive-mock` profile. This substitute
|
|
250
|
+
is excluded from production, which retains its existing real proxy.
|
|
251
|
+
|
|
252
|
+
`sensitive.reveal.strict_mode` defaults to false and must have the same value
|
|
253
|
+
on every Web and Control instance. When true, Control forces the existing
|
|
254
|
+
masking flow even if `sensitive.reveal.enabled` is false, and AddressBook ignores
|
|
255
|
+
its plaintext-role whitelist. Web requires a two-minute, user- and token-bound
|
|
256
|
+
image captcha before calling the unchanged reveal service. Captchas are generated
|
|
257
|
+
with the production Kaptcha `Producer` and stored only as an attribute of the
|
|
258
|
+
existing Shiro login session; no captcha Redis adapter, database table, or Dubbo
|
|
259
|
+
contract is added. A new image replaces the session's previous challenge and
|
|
260
|
+
each submission consumes it, including failed attempts. The local JVM lock does
|
|
261
|
+
not provide distributed atomic consumption: use session affinity for concurrent
|
|
262
|
+
requests, and do not claim cross-node exactly-once verification. The existing
|
|
263
|
+
production session DAO may itself use Redis; this feature does not replace it.
|
|
264
|
+
See `docs/sensitive-reveal-strict-mode.md` for the browser contract and rollout.
|
|
265
|
+
|
|
266
|
+
`agent_scheduled_task` and `agent_scheduled_task_run` persist task definitions
|
|
267
|
+
and individual outcomes. The task table owns the natural-language prompt,
|
|
268
|
+
schedule definition, state, timezone, and next due time. The run table owns one
|
|
269
|
+
scheduled occurrence, its execution state, stored result or safe error, unread
|
|
270
|
+
state, and optional materialized conversation ID. No additional token or
|
|
271
|
+
run-item table is involved.
|
|
272
|
+
|
|
273
|
+
The scheduled-task flow is:
|
|
274
|
+
|
|
275
|
+
1. A MySQL-backed `@Scheduled` scanner locks due active tasks with
|
|
276
|
+
`FOR UPDATE SKIP LOCKED`, inserts a `PENDING` run, and advances the task's
|
|
277
|
+
next due time. The `(task_id, scheduled_at)` unique key prevents duplicate
|
|
278
|
+
occurrences across control instances. Claiming an `ONCE` task atomically
|
|
279
|
+
marks its definition `COMPLETED` while the run itself remains the source of
|
|
280
|
+
truth for `PENDING` / `RUNNING` / terminal progress, so pause/start cannot
|
|
281
|
+
enqueue the consumed occurrence again.
|
|
282
|
+
2. Pending runs are moved to `RUNNING` and submitted to a bounded worker pool.
|
|
283
|
+
Control loads the prompt, owner, role, timezone, and effective occurrence
|
|
284
|
+
time, atomically issues a token, and calls py's scheduled execution endpoint
|
|
285
|
+
with `{}`. Control stores only the token hash and makes no permission
|
|
286
|
+
decision. Web's `/agent/scheduledTaskAuthorize` resolves the run, calls the
|
|
287
|
+
production `arkAuthService.queryResource` bean, and requires the
|
|
288
|
+
exact `/assistantManager/page` resource. Agent tools then use a non-Shiro
|
|
289
|
+
`@AgentPermission` guard with the returned trusted context; browser/CAS
|
|
290
|
+
requests continue to use the production Shiro Subject.
|
|
291
|
+
3. Every terminal run is unread until opened. Successful py-app content is
|
|
292
|
+
stored as bounded JSON; failed runs retain a bounded, structured, user-safe
|
|
293
|
+
error code and message supplied by py-app. Neither
|
|
294
|
+
creates a conversation in the background.
|
|
295
|
+
4. `scheduledTaskRunOpen` verifies the browser owner and locks the run. It
|
|
296
|
+
idempotently creates one normal AG-UI conversation with exactly two trusted
|
|
297
|
+
messages: the task prompt as the user message and the stored final content
|
|
298
|
+
as the assistant message. It marks the result read and returns the existing
|
|
299
|
+
conversation on repeated opens. Deleting that materialized conversation also
|
|
300
|
+
logically deletes its claimed run record, so run history never links to a
|
|
301
|
+
deleted conversation.
|
|
302
|
+
|
|
303
|
+
Only the successful result's `content` and `agentName` fields are persisted.
|
|
304
|
+
Provider messages and unknown response fields are discarded at the control
|
|
305
|
+
boundary. Failed callbacks accept only bounded error codes and single-line
|
|
306
|
+
user-safe messages produced by py-app; raw upstream bodies, stack traces, and
|
|
307
|
+
credentials are never persisted. Opening either terminal state creates the same standard
|
|
308
|
+
two-message conversation, so users can follow up on a result or a failure.
|
|
309
|
+
|
|
310
|
+
Every logical delete sets `delete_flag=0`; active rows use
|
|
311
|
+
`delete_flag=1`. The former message and personal-memory schemas are not
|
|
312
|
+
migrated or retained because the feature was not released.
|
|
313
|
+
|
|
314
|
+
## Security
|
|
315
|
+
|
|
316
|
+
- `ark-web` authenticates browser callers before creating the JSON string passed
|
|
317
|
+
to `ark-control`; `ark-control` performs no authentication or permission
|
|
318
|
+
decision of its own, including while scheduling.
|
|
319
|
+
- Scheduled-task browser routes authenticate the caller's same-origin
|
|
320
|
+
`CASSESSIONID`; the controller never substitutes a synthetic browser identity.
|
|
321
|
+
Apache Shiro enforces `@RequiresPermissions("/assistantManager/page")` on every
|
|
322
|
+
CAS-protected API. The explicit `local-auth-mock` profile exercises the same
|
|
323
|
+
Filter/Realm/Subject path and mocks only the Realm's auth-service dependency;
|
|
324
|
+
production continues to use its unchanged Realm and Shiro configuration.
|
|
325
|
+
- Normal Agent, tool, history, completion, cancellation, sync, and Memory calls
|
|
326
|
+
forward and validate that `CASSESSIONID`.
|
|
327
|
+
- Scheduled execution has no browser session and must not derive or fabricate a
|
|
328
|
+
CAS Cookie from the task owner. Its token is checked against the active
|
|
329
|
+
RUNNING occurrence in Control; Agent tools use only the trusted context
|
|
330
|
+
returned by the dedicated authorization endpoint, recheck live resources, and
|
|
331
|
+
do not construct a Shiro Subject.
|
|
332
|
+
- The production Shiro Filter and Realm implementations remain unchanged. Both
|
|
333
|
+
SSO and non-SSO filter-chain maps place `/agent/** -> anon` before `/** -> authc`,
|
|
334
|
+
delegating this exact namespace to the fail-closed Agent guard. Missing
|
|
335
|
+
`@AgentPermission`, invalid credentials, mixed authentication, unavailable
|
|
336
|
+
Control, or unavailable role-resource lookup all deny the request. `/api/**`
|
|
337
|
+
anonymity is not used for Agent traffic.
|
|
338
|
+
- Conversation completion and cancellation validate user/conversation/run
|
|
339
|
+
ownership.
|
|
340
|
+
- Memory paths must begin with `<authenticated-user>/personal/`.
|
|
341
|
+
- Agent, Skill, memory namespace, model, provider, and frontend tools are not
|
|
342
|
+
accepted from browser configuration.
|
|
343
|
+
|
|
344
|
+
## Scheduled-task configuration
|
|
345
|
+
|
|
346
|
+
- `SCHEDULED_TASK_ENABLED` controls claiming and execution in `ark-control` and
|
|
347
|
+
remains disabled until the database schema, dedicated Agent
|
|
348
|
+
authorization endpoint, production role-resource adapter, and py scheduled
|
|
349
|
+
adapter are deployed and cross-service security checks are complete.
|
|
350
|
+
- Worker tuning: `SCHEDULED_TASK_WORKER_THREADS` and
|
|
351
|
+
`SCHEDULED_TASK_MAX_RUN_SECONDS`.
|
|
352
|
+
|
|
353
|
+
The scanner runs every five seconds, claims at most 20 tasks per pass, queues
|
|
354
|
+
at most 32 worker submissions, and rejects schedules more frequent than once
|
|
355
|
+
per minute. These implementation limits are fixed in code. Configurable defaults
|
|
356
|
+
are defined locally in `ark-control/src/main/resources/application.yml`;
|
|
357
|
+
production uses its separately maintained configuration. Keep the
|
|
358
|
+
scheduler disabled while deploying or rolling back incompatible control and
|
|
359
|
+
py-app versions.
|
|
360
|
+
|
|
361
|
+
## Scheduled-task deployment and rollback
|
|
362
|
+
|
|
363
|
+
Roll out in this order:
|
|
364
|
+
|
|
365
|
+
1. Leave scheduling disabled and verify the existing production schema with
|
|
366
|
+
the DBA. Production already maintains the correct schema separately; the
|
|
367
|
+
local `ark-control/src/main/resources/schema.sql` is a simulation reference,
|
|
368
|
+
not a required production deployment input.
|
|
369
|
+
2. Copy the three files from `ark-web/src/production-overlay/java/.../config`
|
|
370
|
+
over their matching production configurations. The two Shiro files differ
|
|
371
|
+
from the restored originals only by `/agent/** -> anon` before `/** -> authc`;
|
|
372
|
+
`InterceptorConfig` registers the Agent guard and excludes `/agent/**` from
|
|
373
|
+
the browser-only Referer, session-IP, and CSRF interceptors. Deploy the guard
|
|
374
|
+
using the existing `arkAuthService.queryResource` bean, then deploy the py
|
|
375
|
+
scheduled adapter while scheduling remains disabled.
|
|
376
|
+
3. Deploy the web UI and verify draft, create, update, list, pause/start, and result
|
|
377
|
+
APIs while no background run can be claimed.
|
|
378
|
+
4. Enable scheduling on control only after the cross-service contract and
|
|
379
|
+
database schema are verified.
|
|
380
|
+
|
|
381
|
+
Roll back in this order:
|
|
382
|
+
|
|
383
|
+
1. Disable scheduling on every control instance and restart or drain them so
|
|
384
|
+
no new run is claimed; allow or explicitly terminate in-flight work.
|
|
385
|
+
2. Roll back the web UI, then control, then py-app. The scheduled-task tables
|
|
386
|
+
may remain in place.
|
|
387
|
+
3. If the tables must be removed, drop `agent_scheduled_task_run` first and
|
|
388
|
+
`agent_scheduled_task` second because of the foreign key.
|
|
389
|
+
|
|
390
|
+
## Deployment boundary
|
|
391
|
+
|
|
392
|
+
Publish `ark-control-facade` first. `ark-control` registers provider services in
|
|
393
|
+
ZooKeeper, and `ark-web` consumes them. The SSE `chatMessage` path goes directly
|
|
394
|
+
from `ark-web` to py-app and immediately writes and flushes each upstream byte
|
|
395
|
+
chunk to the browser. Non-stream Agent operations remain synchronous Dubbo RPCs.
|
|
396
|
+
|
|
397
|
+
HTTP and Dubbo filters must not log Agent arguments or stream data. They include
|
|
398
|
+
the CAS cookie and model payload. During rollback, stop or
|
|
399
|
+
roll back `ark-web` consumers before rolling back `ark-control` or its facade.
|
|
400
|
+
|
|
401
|
+
## Validation
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
JAVA_HOME=/path/to/java8 mvn clean test
|
|
405
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Ark Agent applications
|
|
2
|
+
|
|
3
|
+
This repository builds one headless application, one production Web integration
|
|
4
|
+
module, and one shared Dubbo contract artifact:
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
ark-control-facade/ serializable Dubbo interfaces shared by both applications
|
|
8
|
+
ark-control/ headless Dubbo provider, business services and database mappers
|
|
9
|
+
ark-web/ HTTP/SSE integration, Agent guard and Dubbo consumer
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`ark-web` authenticates HTTP callers and owns `HttpServletResponse`. Streaming
|
|
13
|
+
requests go directly from `ark-web` to py-app so SSE has no Dubbo hop.
|
|
14
|
+
`ark-control` owns persistence and provides the remaining synchronous RPCs.
|
|
15
|
+
|
|
16
|
+
The main scheduled-task paths are:
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
ark-control/src/main/java/com/union/control/mapper/ScheduledTaskMapper.java
|
|
20
|
+
ark-control/src/main/java/com/union/control/service/impl/ScheduledTaskServiceImpl.java
|
|
21
|
+
ark-control/src/main/java/com/union/control/schedule/ScheduledTaskScheduler.java
|
|
22
|
+
ark-control/src/main/java/com/union/control/schedule/ScheduledExecutionToken.java
|
|
23
|
+
ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentAuthorizationInterceptor.java
|
|
24
|
+
ark-web/src/main/java/com/epcc/arkweb/web/llm/AgentController.java
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Mapper, business service, token and scheduler code remain in `ark-control`;
|
|
28
|
+
browser authentication and the Agent-only permission guard remain in
|
|
29
|
+
`ark-web`.
|
|
30
|
+
|
|
31
|
+
The standalone module keeps the production class and bean names
|
|
32
|
+
`ShiroConfig`, `Realm`, `LoginFormFilter`, and `InterceptorConfig`, and follows
|
|
33
|
+
the same filter -> Realm -> Subject -> permission path. Its only local
|
|
34
|
+
replacement is the external `arkAuthService` bean under
|
|
35
|
+
`ark-web/src/local-mock/java`, inactive unless `local-auth-mock` is set.
|
|
36
|
+
Production keeps its existing Realm and filters.
|
|
37
|
+
The `ark-control` provider must not contain any Spring MVC controller.
|
|
38
|
+
|
|
39
|
+
Production Realm and Filter implementations are unchanged. The SSO and non-SSO
|
|
40
|
+
configuration copies under `ark-web/src/production-overlay/java` add
|
|
41
|
+
`/agent/** -> anon` before `/** -> authc`, delegating only that namespace to the
|
|
42
|
+
fail-closed Agent guard. Copy them over the matching production files; they are
|
|
43
|
+
not compiled as an additional local Shiro configuration. Browser/CAS requests still check
|
|
44
|
+
the existing Subject and permission; scheduled calls enter only
|
|
45
|
+
`/agent/scheduledTaskAuthorize`, and subsequent tools use `@AgentPermission`
|
|
46
|
+
with a Control-backed execution context. `/api/**` is not used as a workaround.
|
|
47
|
+
|
|
48
|
+
`ark-web` resolves the Shiro subject through `AuthContextHolder`, replaces
|
|
49
|
+
any client identity fields, and serializes the backend request through
|
|
50
|
+
`AuthenticatedRequest`. Every user-facing business service accepts that one JSON
|
|
51
|
+
string and never reads Shiro or a cookie. All browser/internal HTTP controllers, including
|
|
52
|
+
`LlmController`, `AgentController` and `ScheduledTaskController`, live in
|
|
53
|
+
`ark-web/src/main/java/com/epcc/arkweb/web/llm`. The scheduled controller
|
|
54
|
+
uses the shared Dubbo facade directly; no scheduled-package facade or local
|
|
55
|
+
adapter is introduced.
|
|
56
|
+
|
|
57
|
+
The applications share the following deployment configuration where relevant.
|
|
58
|
+
|
|
59
|
+
Configuration:
|
|
60
|
+
|
|
61
|
+
- `PY_APP_BASE_URL`
|
|
62
|
+
- `DUBBO_REGISTRY_ADDRESS`
|
|
63
|
+
- `DUBBO_PROTOCOL_PORT` (provider, default `20880`)
|
|
64
|
+
- `DUBBO_CONSUMER_CHECK` (consumer, default `false`)
|
|
65
|
+
- `DUBBO_DIRECT_URL` (consumer, optional; local direct-connect example:
|
|
66
|
+
`dubbo://ark-control.localhost:20880`)
|
|
67
|
+
- `DUBBO_CONSUMER_TIMEOUT_MS` (ordinary RPCs, default `10000`)
|
|
68
|
+
- `AGENT_MAX_RUN_SECONDS` (default `900`; set the same value on web, control,
|
|
69
|
+
and py-app; Agent HTTP connect/read and proxy RPC timeouts use this duration)
|
|
70
|
+
- `LOCAL_AUTHORIZED_ROLE_ID` (local `arkAuthService` mock only, default `role-1`)
|
|
71
|
+
- `SCHEDULED_TASK_ENABLED` (production keeps scheduling disabled until rollout
|
|
72
|
+
checks pass; the independently maintained local YAML may enable it)
|
|
73
|
+
- `SCHEDULED_TASK_WORKER_THREADS` (default `2`)
|
|
74
|
+
- `SCHEDULED_TASK_MAX_RUN_SECONDS` (default `930`)
|
|
75
|
+
- `SCHEDULED_TASK_TOKEN_TTL_SECONDS` (default `960`; must exceed the max run time)
|
|
76
|
+
- `MYSQL_URL`, `MYSQL_USER`, `MYSQL_PASSWORD` (`MYSQL_URL` must use a UTC connection timezone)
|
|
77
|
+
- `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`, `REDIS_TIMEOUT_MS`
|
|
78
|
+
- `SENSITIVE_REVEAL_ENABLED` (local application.properties defaults to `true`;
|
|
79
|
+
production supplies its own setting)
|
|
80
|
+
- `SENSITIVE_REVEAL_TTL_SECONDS` (default `300`)
|
|
81
|
+
|
|
82
|
+
For local Dubbo without ZooKeeper, set `DUBBO_REGISTRY_ADDRESS=N/A` on both
|
|
83
|
+
applications and set `DUBBO_DIRECT_URL=dubbo://ark-control.localhost:20880` on
|
|
84
|
+
`ark-web`. Do not use `127.0.0.1` in Dubbo 2.6.9 direct URLs: that version
|
|
85
|
+
rewrites loopback to the machine's preferred network address, which may be a
|
|
86
|
+
VPN interface. Remove any per-interface `-Dcom.union.control.service.*` direct
|
|
87
|
+
URL VM options because they override `DUBBO_DIRECT_URL`.
|
|
88
|
+
|
|
89
|
+
The unavailable production `sensitiveProxy` has an intentionally non-cryptographic
|
|
90
|
+
local stand-in. It is enabled for the default local profile and for the explicit
|
|
91
|
+
`local-sensitive-mock` profile. Production must activate its production profile
|
|
92
|
+
and keep the existing AES256 proxy binding.
|
|
93
|
+
The Maven `local-sensitive-compat` profile is active by default; when combining
|
|
94
|
+
it with another Maven profile, enable both explicitly with `-Pother,local-sensitive-compat`.
|
|
95
|
+
|
|
96
|
+
The unavailable production authentication service has one local substitute at
|
|
97
|
+
`ark-web/src/local-mock/java/com/epcc/arkweb/mock/ArkAuthServiceMock.java`,
|
|
98
|
+
enabled only by `--spring.profiles.active=local-auth-mock`. Local browser
|
|
99
|
+
requests still pass through Shiro's filter, Realm, Subject and permission
|
|
100
|
+
advisor. It automatically establishes a normal local Shiro Subject using
|
|
101
|
+
`user-1` / `local-only` (override with `LOCAL_USER_ID` and `LOCAL_PASSWORD`),
|
|
102
|
+
so no local login page is required. Scheduled headers skip this auto-login and
|
|
103
|
+
remain on the non-Shiro Agent guard. The mock grants `/assistantManager/page`
|
|
104
|
+
only to `LOCAL_AUTHORIZED_ROLE_ID`.
|
|
105
|
+
|
|
106
|
+
CAS browser routes reuse production Apache Shiro permission
|
|
107
|
+
`@RequiresPermissions("/assistantManager/page")`. Normal
|
|
108
|
+
control-to-py calls forward only the authenticated CAS session. If
|
|
109
|
+
`PY_APP_BASE_URL` is not loopback, use HTTPS with mTLS or an equivalent
|
|
110
|
+
authenticated service mesh.
|
|
111
|
+
|
|
112
|
+
Production already maintains its own correct schema and configuration.
|
|
113
|
+
`ark-control/src/main/resources/schema.sql` is the local AG-UI, Memory, and
|
|
114
|
+
scheduled-task simulation reference. These local files and standalone JARs are
|
|
115
|
+
not production deployment inputs; see PROJECT_OVERVIEW.md for the integration boundary.
|
|
116
|
+
|
|
117
|
+
Natural-language scheduled tasks use the two `agent_scheduled_task*` tables and
|
|
118
|
+
snapshot the authenticated CAS principal's `userId`, `orgCode`, and selected
|
|
119
|
+
Ark `roleId` on create and update.
|
|
120
|
+
The scheduler stores only the successful py-app result's `content` and
|
|
121
|
+
`agentName` on the run; opening an unread run atomically creates the normal
|
|
122
|
+
AG-UI conversation and messages.
|
|
123
|
+
Production uses its DBA-maintained schema and separately managed configuration.
|
|
124
|
+
Each occurrence receives a 256-bit, short-lived token while the database stores
|
|
125
|
+
only its SHA-256 hash. Control calls py `/agent/v1/runs/scheduled` with only that
|
|
126
|
+
token and `{}`; py calls `/agent/scheduledTaskAuthorize`, which resolves the
|
|
127
|
+
active run through Control and checks the role's real-time resources for the
|
|
128
|
+
exact `/assistantManager/page` URL. The response contains a database-backed
|
|
129
|
+
trusted context. Subsequent `/agent/*` tools must send that value in
|
|
130
|
+
`X-Agent-Trusted-Context`; the raw `Authorization: Scheduled ...` credential is
|
|
131
|
+
accepted only by the authorization endpoint. No scheduled Realm, synthetic
|
|
132
|
+
Subject, or tool endpoint copy is introduced.
|
|
133
|
+
Each user may keep at most 100 `ACTIVE` or `PAUSED` tasks.
|
|
134
|
+
|
|
135
|
+
The isolated sensitive-data demo mirrors the production database boundary.
|
|
136
|
+
`POST /api/sensitive/reveal/demo/insert` and
|
|
137
|
+
`GET /api/sensitive/reveal/demo/query` exercise field encryption on write and
|
|
138
|
+
masking on read. AddressBook demos use the `/demo/address-book/insert` and
|
|
139
|
+
`/demo/address-book/query` suffixes under `/api/sensitive/reveal`.
|
|
140
|
+
The reveal hook replaces plaintext fragments with masks and short-lived bearer
|
|
141
|
+
tokens. `POST /api/sensitive/reveal` requires the existing authenticated
|
|
142
|
+
permission and resolves the fragment token; this version does not bind tokens
|
|
143
|
+
to their owner's identity. Local authentication uses `local-auth-mock` and its
|
|
144
|
+
normal Shiro session, not a hard-coded CAS cookie. The crypto mock prefixes and
|
|
145
|
+
Base64-encodes data; it is not encryption. Production excludes the demo and mock
|
|
146
|
+
code and retains its own authentication, crypto, configuration, and Dubbo logs.
|
|
147
|
+
|
|
148
|
+
Set `sensitive.reveal.strict_mode=true` on both Web and Control to require a
|
|
149
|
+
Web-session image captcha before reveal and mask all AddressBook roles. Omission
|
|
150
|
+
or false preserves the original mode. The local environment variable is
|
|
151
|
+
`SENSITIVE_REVEAL_STRICT_MODE` in both applications. Browser clients read
|
|
152
|
+
`GET /api/sensitive/reveal/options`, fetch a PNG from
|
|
153
|
+
`POST /api/sensitive/reveal/captcha` with `{token}`, then submit
|
|
154
|
+
`{token, captchaCode}` to the existing reveal endpoint. See
|
|
155
|
+
[the strict-mode integration guide](docs/sensitive-reveal-strict-mode.md) for
|
|
156
|
+
error handling, session requirements, and production integration boundaries.
|
|
157
|
+
|
|
158
|
+
Streaming, sync, and scheduled py execution use `AGENT_MAX_RUN_SECONDS` (900
|
|
159
|
+
seconds by default). Sync and scheduled return HTTP 504 with `execution_timeout`
|
|
160
|
+
when the shared router-plus-Agent budget expires. Java uses the same setting
|
|
161
|
+
for finite HTTP connect/read waits and the Agent proxy Dubbo reference, replacing
|
|
162
|
+
the old fixed 120-second RPC wait. These are socket wait limits, not another
|
|
163
|
+
Agent lifecycle. Deploy the same value to all three processes; retain a larger
|
|
164
|
+
scheduled stale-run threshold and an even larger token TTL (defaults 930/960).
|
|
165
|
+
|
|
166
|
+
Run the Java 8 test suite with:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
mvn clean test
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Both applications are packaged independently with `mvn clean package`. Publish
|
|
173
|
+
`ark-control-facade` before deploying the provider and consumer. The facade
|
|
174
|
+
version used by `ark-control` and `ark-web` must match.
|
|
175
|
+
|
|
176
|
+
Do not install an HTTP or Dubbo filter that logs Agent arguments: they contain
|
|
177
|
+
the CAS cookie and model payload. Logs must also never contain SSE chunks.
|