# kvPlat **Repository Path**: chenjian835/kv-plat ## Basic Information - **Project Name**: kvPlat - **Description**: 管理动态配置,数据量比较小,表结构比较简单的业务数据,或者业务配置数据,类似于数据字典 - **Primary Language**: Java - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2026-09-22 - **Last Updated**: 2026-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # kvPlat — AI-Native Dynamic Configuration Management Platform kvPlat manages dynamic business data or configuration data with simple, relatively stable table structures — think of it as an enhanced, multi-tenant, cache-backed data dictionary with built-in APIs. It fits scenarios such as regions, departments, positions, roles, permissions, menus, and buttons. Core idea: define business models online without writing code (config dictionary → config instance → field mapping → table deployment), and expose a unified Web / Open API plus a Spring Boot Starter client. Starting from v1.1.0, an embedded AI Agent lets you model data, edit records, and run business-rule scripts through natural language — with every write operation passing through multiple safety guards and an approval workflow. - Repository: `git@gitee.com:sky-painting/kv-plat.git` - Language / Framework: Java 17 + Spring Boot 3.2.5, multi-module Maven project - Chinese docs: [README.md](README.md) ## Version History | Version | Date | Highlights | |---------|------|-----------| | v1.0.0 | 2026-08 | Multi-tenant configuration management, visual modeling & table deployment, L1/L2 multi-level cache with cross-node consistency, Web/Open API, Spring Boot Starter client, example project | | v1.1.0 | 2026-08 | Embedded AgentScope AI Agent (platform-level + application-level), natural-language Chat (SSE streaming/sync), intent routing, business-rule scripts (GraalJS sandbox), tiered tool approval with page-based tickets, field-change approval, dynamic-instance-based RBAC, LLM proxy with context compaction, Agent audit log | ## Core Capabilities - **Visual dynamic modeling**: compose atomic field definitions (`config_dict`) into business models (`config_instance`), then generate/execute DDL in one click — the model becomes a physical table. - **Multi-tenant isolation**: a MyBatis interceptor automatically injects `tenant_id` / `app_id` conditions based on the login context, keeping tenant and application data naturally isolated. - **Multi-level cache**: L1 Caffeine + L2 Redis, with weight-based eviction, secondary business indexes, cross-node invalidation via Redis Stream, and cache-monitoring endpoints. - **Field/data encryption**: built-in AES, SM4, and RSA providers that transparently encrypt/decrypt sensitive fields per encryption scene (e.g. at-rest storage). - **Configuration change approval**: structural field changes follow preview → submit → review → execute → rollback, with forward and rollback DDL generated automatically. - **AI Agent (v1.1.0)**: a platform-level admin Agent and application-level Agents, with 60+ tools covering tenant/app/instance/field/data/dictionary/change/knowledge/rule/script/verification, and tiered approval on write operations. - **RBAC (v1.1.0)**: roles, menus, buttons, and tenant/app grants all live in dynamic config instances — a self-bootstrapping permission model. - **Multiple access channels**: Web admin, Open API (signature auth), Client Starter (local/Redis cache + auto registration & heartbeat), and an OpenAI-compatible LLM proxy. ## Tech Stack | Category | Choice | |----------|--------| | Language / Runtime | Java 17 | | Framework | Spring Boot 3.2.5 | | Persistence | MyBatis (mybatis-spring-boot 3.0.3) + TK generic Mapper, PageHelper 2.1.0 | | Database | MySQL 8.0+ | | Cache | Caffeine (L1), Redis / Spring Data Redis (L2, Redis Stream cross-node sync) | | AI Agent | AgentScope Java 2.0.1 (ReAct Agent) | | Script sandbox | GraalVM Polyglot / JS 25.0.3 | | Cryptography | Bouncy Castle 1.78.1 (bcprov-jdk18on), supporting AES / SM4 / RSA | | HTTP client | Forest (common), custom HTTP in the client module | | Serialization | Fastjson2 2.0.47, Hutool 5.8.32 | | API docs | SpringDoc OpenAPI 2.6.0 (Swagger UI) | | Operation log | bizlog-sdk 3.0.6 (api module) | | Build | Maven 3.8+ | ## Project Structure Seven Maven modules; parent POM `groupId=com.tianhua`: ``` kv-plat/ ├── pom.xml # Parent POM: unified versions & module declarations ├── sql/ # DB scripts (init.sql / config_dict.sql / agent_audit_log_menu.sql) ├── docs/ # Architecture, roadmap, and V1.1.0/V1.2.0 design docs ├── common/ # Shared base module (jar) │ ├── model/ # Result, PageResult, UserContext │ ├── exception/ # BusinessException + global exception handling │ ├── constant/ enums/ # Constants & enums │ ├── interceptor/ # Multi-tenant SQL interceptor + TenantContext/UserContext │ ├── crypto/(impl) # AES/SM4 crypto providers & registry │ ├── cache/ # Shared caches such as LoginWebCache │ ├── invoker/ anno/ utils/ config/ ├── tenant/ # Tenant / User / Application / Permission module (jar) │ ├── entity/ mapper/ param/ resp/ │ └── service/(impl) # TenantService, UserService, ApplicationService, PermissionService (RBAC) ├── config/ # Core config-modeling & data-management module (jar) │ ├── entity/ mapper/ dao/(impl) dialect/ │ ├── service/(impl) # Dictionary/instance/field/data/DDL services │ ├── change/ # Field-change approval (entity/dto/mapper/service) │ ├── cache/ # Multi-level cache mgmt, warm-up, Redis Stream publish, stats │ ├── crypto/ # Field-level encryption strategy (DataEncryptor/Decryptor) │ ├── rule/(impl) validate/ listener/ # Business-rule validation, data checks, cache events ├── client/ # Spring Boot Starter client SDK (jar) │ ├── config/ # KvPlatClientProperties auto-configuration │ ├── KvPlatTemplate # Unified save/update/query/... template │ ├── cache/ http/ lifecycle/ handler/ annotation/ ├── ai/ # AI Agent module (jar, v1.1.0 core) │ ├── config/ # AgentModelConfig, AgentToolApprovalPolicy, AgentScopeProperties │ ├── agent/ # AgentRuntimeFactory, AppAgentRegistry (app-level profiles) │ ├── tool/ # 10 tool classes, 60+ @Tool methods │ ├── policy/(impl) # Tool execution / approval policies │ ├── intent/ # Intent routing (AgentIntentRouter + agent-intents.yml) │ ├── script/ # GraalJS restricted runtime, masking, result validation │ ├── knowledge/ rule/ # Application knowledge base, business-rule assets │ ├── sandbox/ # DataSandbox / SchemaSandbox dry-run previews │ ├── verification/ # Verification-code example Skill │ ├── protocol/ # AgentSseEvent SSE protocol │ ├── audit/ context/ dao/(impl) service/ ├── api/ # Main app (executable Spring Boot jar, port 8060) │ ├── controller/web/ # Web admin endpoints │ ├── controller/open/ # Open API (signature auth) │ ├── controller/ai/ # AI chat / tool-approval endpoints │ ├── controller/server/ # Client registry endpoints │ ├── controller/llm/ # OpenAI-compatible LLM proxy │ ├── interceptor/ # ApiAuthInterceptor unified auth │ ├── llm/ limit/ filter/ log/ manager/(impl) config/ └── example/ # Client integration example (Department/Role invokers, port 8080) ``` ## Module Dependencies ``` common / | \ config client (depended upon downstream) / \ \ tenant \ example | \ \ | \ \ api ── ai ``` - `common` is the foundation for all modules. - `config` depends on `common`; `tenant` depends on `common` + `config` (`PermissionServiceImpl` needs config-instance data). - `ai` depends on `common` + `config` + `tenant` (note: `api` is an executable jar with a BOOT-INF layout, so `ai` depends directly on `config`/`tenant` rather than `api`). - `api` depends on `common` + `config` + `tenant` + `ai` and is the only executable module. - `client` depends only on `common` and is packaged as a standalone Starter; `example` depends on `common` + `client` to demonstrate integration. ## Data Model ### v1.0.0 base tables (`sql/init.sql`) | Table | Description | |-------|-------------| | `tenant` | Tenant table, auto-increment from 10000000, with `api_key` / `api_secret` for Open API signing | | `user` | Login user seed data | | `application` | Application table, auto-increment from 1000000, the app dimension under a tenant | | `config_dict` | Field-definition base table (name/description/type/length) — the atom of every business model | | `config_instance` | Config instance (business model): instance code, physical table name, model name, create-table DDL, ext settings | | `config_instance_field` | Mapping between instance and field definition; flags such as encrypt, encrypt type, returnable, validation rules | | `config_change_request` / `_item` | Structural field-change request and its items | | `agent_audit_log` | Agent tool-call audit log (enhanced in v1.1.0) | `config_instance.status` semantics: `0`-draft, `1`-uninitialized, `2`-initialized (DDL generated only), `3`-in use/deployed (physical table created; only then can data be read/written). ### v1.1.0 new tables (`docs/V1.1.0/ai-agent.sql` + `agent-business-rule.sql`) | Table | Description | |-------|-------------| | `agent_audit_log` | Enhanced audit: adds `app_id` / `agent_scope` / `profile_version` / `result_code` / `cost_ms`, with a time-desc composite index | | `agent_session` | JDBC fallback for AgentStateStore when Redis is unavailable | | `agent_app_knowledge` | App/instance-level knowledge base (field semantics, relationships, textual business rules), written after AI confirmation | | `agent_instance_script` | Instance business-rule scripts; `active_hook_key` generated column enforces a single active script per hook | | `agent_instance_script_run` | Script execution records with real/masked output; `script_run_id` consumes the real result once | | `agent_pending_tool_execution` | Post-approval tool execution audit linking `pendingId → scriptRunId → write result` | | `agent_verification_code` | Persistence for the verification-code example Skill; stores only `code_hash`, never plaintext | | `agent_business_rule` | Executable business-rule asset table, bound to `agent_app_knowledge` via `knowledge_id` so description and executable config share the same lifecycle | > Note: approval tickets have no dedicated physical table — `approvalTicketModel` / `approvalTicketItemModel` and related models are themselves self-bootstrapping dynamic config instances (see permissions below). `agentscope_skills` / `agentscope_skill_resources` are commented out in the SQL, kept for manual management reference. ## Multi-Tenancy & Permissions ### Multi-tenant isolation A **column-isolation** strategy: `TenantInterceptor` (a MyBatis interceptor) automatically injects `tenant_id` and `app_id` conditions on queries/updates: - Tenant and application context is written to `UserContext` / `TenantContext` by `ApiAuthInterceptor` during authentication (for the Web side, the login Token resolves the user's roles, tenants, and apps from `LoginWebCache`); the interceptor reads that context to inject SQL. - Tables without multi-tenant columns are skipped: `TenantMapper`, `UserMapper`, `ConfigDictMapper`, `ConfigInstanceFieldMapper`, `ApplicationMapper`. ### RBAC (v1.1.0) `PermissionService` / `PermissionServiceImpl` implement RBAC via **self-bootstrapping dynamic config instances** — roles, admins, menu buttons, and tenant/app grants all live in the built-in application's config instances (`appId=1000000`, default tenant `tenantId=10000000`): | Capability | Description | |-----------|-------------| | `currentUserMenus` | Returns the current user's visible menu tree and permission points | | `isCurrentUserSuperAdmin` / `requireSuperAdmin` | Super-admin (`superAccount`) check and hard enforcement | | `requireTenantAccess` / `requireApplicationAccess` / `requireConfigInstanceAccess` | Resource-access checks | | `filterAccessibleTenants/Applications/ConfigInstances` | Accessible-resource filtering | The built-in application ships 12 permission-related instances (e.g. `roleAdmin`, `roleModelKvPlat`, `moduleModel`, `roleModuleModel`, `approvalPermissionModel`, `approvalTicketModel`). The platform-level AI Chat entrypoint calls `requireSuperAdmin()`. ### Authentication model `ApiAuthInterceptor` intercepts `/kvplat/**`, `/open/**`, `/web/**`, `/llm/**`, `/ai/**`, with the auth type declared via `@ApiAuth`: | Type | Credential | Description | |------|-----------|-------------| | `isWeb` | `Token` + `LoginWebCache` | Web admin session | | `isAdmin` | JWT + `TokenService` | Admin Token | | `isOpen` | `X-Public-Key` + `X-Sign` + `X-TimeStamp` | Open API: MD5 signature, 5-minute anti-replay | | `isClient` | App Key/Secret | Client SDK registration & calls | ## AI Agent Architecture (v1.1.0 core) ### Assembly & runtime - **Model access**: `AgentModelConfig` builds an `OpenAIChatModel` whose `baseUrl` points to the platform's own LLM proxy `.../kvplat/llm/internal/v1` (looping back to reuse rate limiting, auditing, and context compaction). - **Platform-level Agent**: `kvplat-admin` (ReActAgent); the Toolkit registers 10 tool classes with built-in system-prompt rules. - **Application-level Agent**: `AgentRuntimeFactory` caches `kvplat-app-{appId}` per `AgentProfile` (`tenantId:appId:profileVersion`); profiles and prompts come from `AppAgentRegistry`. - **State persistence**: `JedisAgentStateStore`, key prefix `agentscope:kvplat:` (platform) / `agentscope:kvplat:app:{tenantId}:{appId}:` (application). - **Skill repository**: `FileSystemSkillRepository`, at `{workspaceDir}/skills` and `{workspaceDir}/skills/app/{appCode}`; `workspaceDir` defaults to `.agentscope/workspace`. ### Middleware chain (four guards on writes) ``` AppScopeGuardMiddleware (application-level only) → ToolExecutionPolicyMiddleware → ToolApprovalMiddleware → AuditMiddleware ``` - **AppScopeGuard**: application-level Agents may not call platform-only tools (`create_tenant` / `update_tenant` / `create_application`), and input parameters `tenant_id/app_id/instance_id/...` are validated to belong to the current application. - **ExecutionPolicy**: runs business-rule validation on `create_data` / `update_data` / `delete_data`; blocking violations are denied. - **Approval**: decides allow / chat confirmation / page approval by risk tier. - **Audit**: records every tool call's inputs, result, and latency to `agent_audit_log`. ### Tool catalog (10 classes, 60+ @Tool methods) | Tool class | Count | Representative tools | |-----------|-------|---------------------| | `TenantTools` | 3 | create_tenant / list_tenants / update_tenant | | `ApplicationTools` | 4 | create_application / list_applications / list_accessible_apps / switch_app_context | | `ConfigInstanceTools` | 13 | create_config_instance / add_field / get_instance_ddl / initialize_instance / publish_instance / deploy_config_instance | | `ConfigDictTools` | 3 | list_config_dicts / list_config_dicts_simple / create_config_dict | | `ConfigDataTools` | 8 | query_data / validate_data_input / create_data / update_data / delete_data | | `ConfigChangeTools` | 9 | preview_changes / sandbox_preview / submit_change / approve_change / execute_change / rollback_change | | `AppKnowledgeTools` | 4 | list_app_knowledge / upsert_app_knowledge / upsert_instance_knowledge | | `BusinessRuleTools` | 7 | list_business_rules / preview_business_rule_impact / upsert_business_rule_asset / disable_business_rule | | `InstanceScriptTools` | 7 | list_instance_scripts / run_instance_script / upsert_instance_script / enable/disable_instance_script | | `VerificationCodeTools` | 2 | send_verification_code / verify_verification_code | ### Tool approval & risk tiers (`AgentToolApprovalPolicy`) - About 32 mutating tools require approval. Risk tiers: - **HIGH**: `deploy_config_instance` (DDL deploy), `delete_data` (high-risk data). - **MEDIUM**: structural changes (`add_field`/`remove_field`/`update_field_settings`, 7 tools) and rule/knowledge/script tools (9 tools). - **LOW**: all other mutating tools. - Approval surface: `LOW → CHAT_OR_PAGE` (in-chat confirmation allowed); `MEDIUM/HIGH → PAGE_ONLY` (page approval required). - Decision enum: `ALLOW` / `DENY` / `REQUIRE_CHAT_APPROVAL` / `REQUIRE_PAGE_APPROVAL`. ### Intent routing (`AgentIntentRouter` + `agent-intents.yml`) Loads a static intent dictionary from `resources/agent-intents.yml` and scores it (verb hit +0.3, object hit +0.5, write-verb hit -0.6, clamped to `[0,1]`): `<0.45 → GENERAL`; `0.45–0.75` or ambiguous without a verb → ask for clarification (write tools forbidden); `≥0.75` → return an intent with allowed/forbidden tool sets. ### Business-rule script sandbox (`RestrictedJavaScriptRuntime`, GraalJS) Strongly isolated user-script execution: `HostAccess.NONE`, host class lookup / IO / thread creation / process creation / environment access all disabled; the blacklist rejects `java.type`, `import`, `require(`, `fetch(`, `jdbc`, `mapper.`, `process.`, `runtime.getruntime`, etc. Scripts may only use the platform-injected `tools` (`validate.*`, `hash.md5/sha256`, `crypto.sm4`, `random.salt`, `hasText`) and must return `{ ok, data, message, fieldErrors, warnings }`; hook mapping: `before_create→beforeCreate` / `before_update→beforeUpdate` / `before_send_code→beforeSendCode`. ### SSE protocol (`AgentSseEvent`) Event `type` values: `text.delta`, `tool.call`, `tool.result`, `approval.required`, `approval.result`, `error`, `done`. ## API Reference Server port `8060`, context-path `/kvplat`; Swagger UI is served by SpringDoc. All paths below are relative to the context-path. ### Web admin (`isWeb` auth) | Prefix | Main endpoints | |--------|---------------| | `/web/tenant` | Tenant CRUD, dropdown, pagination | | `/web/application` | Application CRUD, list by tenant, accessible apps for current user | | `/web/user-login` `/web/user-logout` | Login / logout | | `/web` | `/dashboard` base info, `/menus` current user's menu permissions | | `/web/config-dict` | Field-definition CRUD, all/paged lists | | `/web/config-instance` | Instance CRUD, `/init`, `/{id}/deploy`, `/list-all`, `/list-by-app` | | `/web/config-instance-field` | Field-mapping CRUD, `/detail`, `/batch-update`, `/preview-alter` | | `/web/config-instance/data` | Data `create/update/list/enable/disable/delete` | | `/web/config-change-request` | `preview`, submit, `list`, `{id}/approve\|reject\|execute\|rollback` | | `/web/monitor/cache` | `stats`, `l1`, `l1/biz-index`, `l2`, `counters/reset` | | `/web/log-record/list` | Operation-log pagination | | `/web/agent-audit-log/list` | Agent audit-log pagination | | `/web/approval/tickets` | Tool tickets: `pending`, `reviewed`, `{id}`, `{id}/approve\|reject\|cancel` | ### AI chat (`/ai/agent`) | Method | Path | Description | |--------|------|-------------| | POST | `/ai/agent/chat` | Platform-level streaming chat (SSE) | | POST | `/ai/agent/chat/sync` | Platform-level sync chat | | POST | `/ai/agent/app/{appId}/chat` | Application-level streaming chat (SSE) | | POST | `/ai/agent/app/{appId}/chat/sync` | Application-level sync chat | | POST | `/ai/agent/pending/{id}/approve[/stream]` | Approve a pending tool operation | | POST | `/ai/agent/pending/{id}/approval-result[/stream]` | Query a pending operation's result | | POST | `/ai/agent/pending/{id}/cancel` | Cancel a pending tool operation | ### LLM proxy (`/llm`, OpenAI-compatible) | Method | Path | Description | |--------|------|-------------| | POST | `/llm/v1/chat/completions` | External chat-completion proxy (rate limit + audit + context compaction) | | POST | `/llm/internal/v1/chat/completions` | Internal reuse entrypoint for the Agent | ### Open API (`/open/instance`, signature auth) Unified config-data read/write: `/data/{save,saveBatch,import,export,edit,editBatch,updateStatus,updateStatusBatch,getById,getByIds,delete,deleteBatch,queryListOptions,queryPage,query}` plus `/instance/detail`. ### Client registry (`/client`) `/register`, `/heartbeat/{clientId}`, `/callback`, `/unregister`, `/ping`. ## Client SDK Integration After adding the `kv-plat-client` Starter, configure `kv-plat.client.*` in `application.yml`: ```yaml kv-plat: client: enabled: true server-url: http://localhost:8060/kvplat app-api-key: app-secret: connect-timeout: 5000 read-timeout: 10000 cache: enabled: true type: caffeine # local | caffeine max-capacity: 10000 expire-after-write: 300000 instances: # business instance code -> that instance's apiKey dept_instance: roleModel: retry: max-attempts: 3 ``` Read/write data through `KvPlatTemplate` (bound to a fixed `instanceCode`), with generic POJO support: ```java @Component public class DepartmentInvoker { private final KvPlatTemplate deptTemplate; public DepartmentInvoker(@Qualifier("deptTemplate") KvPlatTemplate deptTemplate) { this.deptTemplate = deptTemplate; } public Department save(Department data) { return deptTemplate.save(data, Department.class).getData(); } public List listAll() { return deptTemplate.listAll(Department.class).getData(); } } ``` Template methods cover `save` / `update` / `query` / `queryById` / `listAll` / `delete` and their generic variants; see the `example` module (port 8080) for a full sample. ## Configuration Main app configuration lives in `api/src/main/resources/application.yml`: - **Datasource**: `spring.datasource.*` (MySQL). - **Multi-level cache** `kv-plat.server.instance-data-cache`: `l1` (Caffeine — `max-weight`, `expire-after-write/access`, `cross-node-sync`), `l2` (Redis — `key-prefix`, `default-ttl`). - **LLM proxy** `kv-plat.llm`: `enabled`, `api-key` (when blank, read in order from system property `KV_PLAT_LLM_API_KEY` / environment variable / file), `base-url` (default `https://api.deepseek.com/v1`), `default-model`, timeouts, `rate-limit-per-user`, `audit-enabled`, request-body cap, and context compaction (`context-compression-enabled`, target/max bytes, max messages, recent rounds to keep, etc.). - **AgentScope** `agentscope`: `llm.base-url` (default `http://localhost:8060`), `llm.model-name`, `workspace-dir` (default `.agentscope/workspace`), `redis.host/port`. ## Getting Started ### 1. Initialize the database ```bash # v1.0.0 base tables + built-in tenant/app/admin mysql -u root -p kv_plat < sql/init.sql # v1.1.0 AI Agent tables mysql -u root -p kv_plat < docs/V1.1.0/ai-agent.sql mysql -u root -p kv_plat < docs/V1.1.0/agent-business-rule.sql # Agent audit-log menu (writes into the dynamic menu physical table) mysql -u root -p kv_plat < sql/agent_audit_log_menu.sql ``` ### 2. Configure datasource & LLM Edit `api/src/main/resources/application.yml`: set `spring.datasource.*`. To enable AI Chat, set `kv-plat.llm.api-key` (or the `KV_PLAT_LLM_API_KEY` environment variable) and adjust `base-url` / `default-model` as needed. When using Redis cache or Agent state persistence, enable `l2.enabled` and configure `agentscope.redis`. ### 3. Build & run ```bash mvn clean install -DskipTests mvn -pl api spring-boot:run ``` Or run `KvPlatApplication.java` in the `api` module directly. After startup, open Swagger UI for the API docs. ## Roadmap - v1.2.0 (in research): multi-tenant dynamic business-process orchestration (see `docs/V1.2.0/`). ## License See the repository license notice.