源码有据简报 · 5 个视角 · 生成于 2026-06-14 · 只读
同一套代码库的五个视角。每张图独立溯源;合起来追踪一次请求从令牌到 Postgres 的完整路径、决定执行内容的路由/编排大脑、进程部署位置、权限边界如何维持,以及持久化状态转换如何受治理。
一次 /api/chat 请求生命周期:Aida JWT → 网关 → 会话绑定 → ReAct 循环 → SSE 事件 → Postgres + 审计。
能力优先路由管道、共享 ReAct 循环、工具门控/风险、子运行 agent-as-tool,以及本地工作台调度。
开发/本地进程拓扑与外部依赖。生产拓扑不在仓库中。
双令牌边界、通过 Action Proposal 的写入治理、阻塞式审计安全门、路由决策加密 + 管理员访问。
ActionProposal、PendingInteraction 与 CapabilityRoute 状态生命周期及其交叉耦合。
sequenceDiagram
autonumber
actor Client as "客户端 (Aida JWT)"
participant GW as "网关 (Hono Auth)"
participant Bind as "会话绑定"
participant RT as "OrchestratorRuntime"
participant Orch as "编排器 (ReAct)"
participant Gate as "ToolCallGate"
participant LLM as "LLM 流 (AI SDK)"
participant Tool as "工具后端 (Spring Boot)"
participant Router as "能力路由"
participant PG as "Postgres 存储"
participant Audit as "审计管道 (WAL + Sink)"
Note over Client,GW: auth.ts:76-194 + shared/types.ts:243-257
Client->>GW: "Authorization: Bearer Aida-JWT"
GW->>GW: "authMiddleware verify JWT"
GW->>GW: "tokenProvider.resolve(tenantId,userId)"
GW->>GW: "create TenantContext via AsyncLocalStorage"
Note over GW,Bind: chat-routes.ts:125-280 + session-binding.ts:82-280
GW->>GW: "validate body (message/agentId/agentKey)"
GW->>Bind: "resolveSessionBinding (configDbReady)"
Bind->>PG: "sessionStore.lookup or create"
Bind->>Bind: "ConfigFacade.resolveAgent (agentId or '')"
Bind-->>GW: "SessionBindingResult: sessionId + agentId"
Note over GW,Client: chat-routes.ts:283-330 streamSSE
GW->>Client: "SSE open: session_bound event"
alt agentId === '' (统一入口)
Note over GW,Router: chat-routes.ts:333-407 + routing/router.ts (ADR-0016)
GW->>Router: "CapabilityRouter.route(message)"
Router->>Client: "capability_route_decision event"
Router->>RT: "routed: child agent run or local workbench"
else agentId specified (代理绑定)
Note over GW,RT: chat-routes.ts:410-459
GW->>RT: "runtime.resolveAndRun(input, localExecutor?)"
end
Note over RT,Orch: orchestrator-runtime.ts:126-196 + resolve-and-orchestrate.ts:92-195
RT->>RT: "resolveAgentPipeline: llm/tools/systemPrompt"
RT->>RT: "assemble TurnConfig per agent (ADR-0018)"
RT->>Orch: "orchestrate(input, deps, signal)"
Note over Orch,PG: persistence-helpers.ts:43-100
Orch->>PG: "check concurrent runs then runStore.create"
Orch->>PG: "load message history"
Orch->>Client: "run_bound event (runId/conversationId)"
opt memoryEnabled (CONTEXT.md)
Orch->>Orch: "memoryRecall prepended to LLM context"
end
Note over Orch,Tool: drive-react-loop.ts:30-100 ReAct loop
loop ReAct Rounds (0..maxIterations)
Orch->>LLM: "llm.stream({messages,tools,systemPrompt})"
LLM-->>Client: "response/thinking events (streamed chunks)"
Orch->>Orch: "ResponseGuard validate critical fields (ADR-0018)"
Orch->>Client: "usage event (prompt/completion tokens)"
alt model emitted tool_use
Orch->>Client: "tool_call event"
Orch->>Gate: "ToolCallGate: pass / confirm / reject"
alt passed
Gate->>Tool: "ToolBackendClient.call (backendToken injected)"
Tool-->>Orch: "tool result"
opt result-verifier.ts
Orch->>Tool: "optional 2nd-call verification"
end
Orch->>Client: "tool_result event"
else confirm needed
Gate->>PG: "create PendingInteraction"
Orch->>Client: "interaction_pending event (pause run)"
Note over Client,Orch: chat-routes.ts:801-891 confirm / 648-799 tool-result callback
Client->>GW: "POST /:sessionId/confirm or /tool-result"
GW->>PG: "resume PendingInteraction"
end
else no tool call (exit)
Note over Orch,PG: persistence-helpers.ts persistRoundMessages
Orch->>PG: "messageStore.insert + runStore.finalize"
Orch->>Bind: "sessionStore.update(lastActiveAt)"
end
end
Note over Orch,Audit: audit/pipeline.ts emit/emitAndWait
Orch->>Audit: "emit events"
Audit->>PG: "write JSONL + Postgres sink (ADR-0003)"
opt context overflow / off-path (CONTEXT.md)
Orch->>Orch: "compaction + summarization"
Orch->>PG: "memoryExtractor mines candidates after run"
end
alt failure
Orch->>Client: "error event (code/message/category)"
else abort signal
Orch->>Client: "cancelled event (stream close)"
end
Note over Orch,Client: transport/events.ts:57-68 serializeAgentEvent
Orch->>Client: "all events serialized to SSE JSON lines"
packages/agent/src/gateway/{auth.ts:76-194, chat-routes.ts:125-891, session-binding.ts:82-280, orchestrator-runtime.ts:126-196}、src/orchestrator/{agent.ts:232, drive-react-loop.ts:30-100, round.ts:82-100, tool-executor.ts:17-100, run.ts:27-90, persistence-helpers.ts:43-100}、src/shared/types.ts:13-257、src/audit/pipeline.ts;ADR-0003/0016/0018/0020 与 CONTEXT.md。
flowchart TB entry["统一入口
(Unified Entry)"] subgraph ROUTER["CapabilityRouter 管道 (ADR-0016 K2)"] direction TB rf["ruleFilter
租户启用 + 角色门控预过滤"] lc["llmClassify
单步 LLM,畸形回退"] dr["resolveCapabilityDispatchability
执行器绑定可用性"] ds["decideStatus
纯决策矩阵 (PRD R17)"] dec["CapabilityRouteDecision
routed / refused / clarifying / route_only"] store["PgRouteDecisionStore
持久化 + SSE (R-Y 加密)"] rf -->|"filtered candidates (non-empty)"| lc lc -->|"classification + candidates"| dr dr -->|"dispatchability map"| ds ds -->|"status, primaryCapabilityId, riskAssessment"| dec dec --> store end rc["Router Context
recent msgs, child-run output filtered"] subgraph LOOP["编排器循环"] direction TB react["driveReActLoop
共享轻量 ReAct(无持久化)"] gate["ToolCallGate
同轮 / 重复 / 跨轮守卫"] risk["evaluateToolRisk
metadata + riskLevel: allow / confirm / reject"] disc["discoverTools
每轮加载写入工具"] reqc["requestConfirmation
第 1 轮写入门控 (sideEffectLevel=read)"] react -->|"executeRound calls gate.decide"| gate gate -->|"def.riskDecision"| risk gate -->|"markConfirmationRequested()"| reqc end td["Tool Disclosure
读工具始终挂载,写工具经 discoverTools"] pend["PendingInteraction
confirm / ask_user / local_tool_result, once-only, expiry"] prop["Action Proposal
confirm|reject, approverTarget, executionPayload, hash"] subgraph CHILD["子运行 (agent_as_tool, ADR-0016 K1/K7)"] direction TB allow["assertChildAgentAllowed
seed_key 白名单"] resolve["Child Agent resolver
seed_key to ChildAgentRuntime"] minc["minimizeContext
recent N msgs + extracted inputs"] runc["runChildAgent
child agent as tool, parent_run_id lineage"] fwd["transparentForward
ChildRunOutput to user-visible text (no rewrite)"] allow --> resolve resolve --> runc minc -->|"MinimizedContext"| runc runc --> fwd end subgraph WORKBENCH["本地工作台 (local_workbench, K5)"] direction TB lwb["dispatchLocalWorkbench
直接桌面原语(无子运行)"] lexec["buildLocalExecutorRuntime
read/write tool defs + prompt suffix"] lexec -->|"filtered tools"| lwb end subgraph RUNTIME["启动组装 (ADR-0018)"] direction TB ort["OrchestratorRuntime
启动时组装的基础设施"] tc["TurnConfig
per-turn LLM, tools, prompt, skills"] ort -->|"resolveAgentPipeline"| tc end entry --> rf store -->|"decision status drives dispatch"| entry rc -->|"recent messages to classifier"| lc entry -->|"routed + agent_as_tool"| runc entry -->|"routed + local_workbench"| lwb runc --> react lwb --> react disc -->|"per-run discovery"| td reqc -->|"high-risk park"| pend risk -->|"confirm: high-risk write"| prop prop --> pend ort -.->|"infra container"| LOOP tc -.->|"per-turn config"| react %% ADR-0017: server-side desktop write policy risk -.->|"ADR-0017 write gating"| gate
packages/agent/src/routing/{router,rule-filter,llm-classifier,dispatchability,decide-status}.ts、src/orchestrator/{tool-call-gate,risk-policy,drive-react-loop,internal-tools,local-workbench-dispatch}.ts、src/orchestrator/agent-as-tool/{child-run-orchestrator,allowed-child-agents,context-minimization,transparent-forward}.ts、src/gateway/{unified-entry,local-executor,orchestrator-runtime}.ts,以及 docs/adr/0010/0016/0017/0018。
flowchart LR
subgraph clients["客户端"]
chat["Shared Chat Packages
(../../ai-chat)"]
desktop["AIDA Desktop Host
(../aida-desktop, Hybrid Local Executor)"]
web["React Admin Web
(Vite dev, port 8887)"]
end
subgraph agentproc["Hono Agent 进程 (port 3000)"]
agent["Hono Agent
(packages/agent)"]
orch["OrchestratorRuntime"]
sched["Scheduler Engine
(BullMQ Worker)"]
audit["Audit Pipeline
(JSONL + optional Postgres)"]
toolclient["@aida/tool-client
(HTTP Tool Client)"]
end
subgraph datastores["数据存储"]
configdb[("Config DB
(Postgres)")]
redisSess[("Redis
(Session Dedup + Backend Token cache)")]
redisSched[("Redis
(BullMQ Scheduler)")]
end
subgraph external["外部服务"]
nacos["Nacos
(Service Discovery + Config)"]
authsvc["caidao-auth-service
(OAuth2)"]
springboot["Spring Boot Tool Backend
(caidaocloud-ai-service)"]
llm["LLM Provider
(OpenAI-compatible / Anthropic)"]
embed["Embedding Provider
(OpenAI-compatible)"]
feishu["Feishu IM Platform"]
end
eval["Agent Eval Framework
(YAML scenarios)"]
chat -->|"HTTP/SSE (Aida JWT auth)"| agent
desktop -->|"HTTP/SSE (Aida JWT, Hybrid Local Executor)"| agent
web -->|"Vite dev proxy: /api /admin /healthz /aida-work/* to :3000"| agent
agent --> orch
agent --> sched
agent --> audit
orch -->|"Tool schema + execution"| toolclient
agent -->|"agent/provider/skill/entitlement config"| configdb
agent -->|"Backend Token cache + channel dedup store"| redisSess
agent -->|"BullMQ queue + job storage"| redisSched
sched -->|"BullMQ Worker process"| redisSched
sched -->|"Scheduled task via resolveAndRun"| orch
agent <-->|"Service discovery + config bootstrap (optional)"| nacos
agent -->|"Backend Token exchange + verification"| authsvc
agent -->|"Tool schema discovery + execution (Backend Token)"| springboot
toolclient -->|"HTTP REST with Backend Token"| springboot
agent -->|"OpenAI-compatible API calls"| llm
agent -->|"Embedding calls for memory recall"| embed
agent <-->|"Webhook + WebSocket; IM message webhooks + user binding"| feishu
audit -.->|"Optional Postgres audit sink"| configdb
prodUNKNOWN{{"未知:生产部署拓扑
不在仓库中 — 无 Dockerfile / k8s / wrangler;项目尚未发布"}}
agentproc -.->|"生产环境运行方式未经验证"| prodUNKNOWN
classDef unknown fill:#3a2a00,stroke:#d99000,stroke-width:2px,color:#ffd97a,stroke-dasharray:5 4;
class prodUNKNOWN unknown;
packages/agent/src/config.ts(PORT 3000、toolBackendUrl、authServiceUrl、scheduler/backendToken Redis URLs、configDbUrl、llmBaseUrl)、packages/web/vite.config.ts(port 8887 + /api /admin /healthz /aida-work 代理到 localhost:3000)、packages/agent/src/index.ts、nacos.ts、scheduler/engine.ts、gateway/channels/feishu + dedup/redis、CONTEXT.md / AGENTS.md;已确认仓库中不存在 Dockerfile/docker-compose/k8s/wrangler。
flowchart TB
subgraph TOKENS["双令牌边界 (ADR-0001)"]
direction TB
EXCHANGE["Token Exchange
/api/auth/exchange
(only bootstrap path)"]
AIDA["Aida JWT (HS256)
Client to Agent auth
30d expiry"]
BACKEND["Backend Token (OAuth2)
Agent to Spring Boot auth"]
AUTHZCACHE["Authorized Identity Cache
10 min TTL
(after /api/auth/authorize)"]
EXCHANGE -->|"returns Aida JWT"| AIDA
EXCHANGE -->|"caches Backend Token
for tool calls"| BACKEND
AUTHZCACHE -->|"pre-caches identity"| EXCHANGE
end
subgraph GATE["请求级认证与传播"]
direction TB
AUTHMW["authMiddleware
verify Aida JWT signature"]
CLAIMS["JWT Claims Validation
tenantId + userId required
empId, roles optional"]
ALS["TenantContext via AsyncLocalStorage
request-scoped propagation"]
PROFILE["User Profile Fetch (async, 3s)
GET /api/users/me
department enrichment"]
TOKENPROV["TokenProvider
resolve/fetch Backend Token"]
TOKENCACHE["Backend Token Cache
Redis (CONFIG_REDIS_URL) or In-Memory
25 min default TTL"]
AUTHMW --> CLAIMS
CLAIMS -->|"creates TenantContext"| ALS
PROFILE -.->|"enriches department
(non-blocking)"| ALS
ALS --> TOKENPROV
TOKENPROV --> TOKENCACHE
TOKENCACHE -->|"store/retrieve OAuth2
tokens with TTL"| BACKEND
end
AIDA -->|"Authorization: Bearer"| AUTHMW
subgraph WRITEGOV["写入治理 — Action Proposals"]
direction TB
GATE_TC["ToolCallGate
write enters execution or creates Proposal"]
RISKEVAL["Risk Policy Evaluator
evaluateToolRisk()"]
RISKACTION["ToolRiskDecisionAction
allow | confirm | reject"]
PROPOSAL["ActionProposal
persistent write record
(Postgres or In-Memory store)"]
HASH["payloadHash (SHA256)
stable stringify before exec"]
REDACT["Safe Args Redaction
token / password / secret"]
SAVEFLAG["savePrivatePayload flag
true=confirm, false=reject"]
STATEM["Status Machine
pending to (approved | rejected | expired)
to executing to (executed | failed)"]
REQID["requesterUserId
who initiated the write"]
DECSRC["decisionSource
policy auto-allow vs human"]
GATE_TC -->|"calls"| RISKEVAL
RISKEVAL --> RISKACTION
RISKACTION -->|"confirm=create, reject=create rejected,
allow=skip"| PROPOSAL
PROPOSAL --> HASH
PROPOSAL --> REDACT
SAVEFLAG -->|"controls privatePayload stored vs null"| PROPOSAL
PROPOSAL --> STATEM
REQID --> PROPOSAL
DECSRC -->|"records transition origin"| STATEM
HASH -->|"re-hash and compare
before executing"| STATEM
end
ALS -->|"TenantContext supplies tenantId/userId"| GATE_TC
subgraph APPROVAL["审批授权"]
direction TB
TARGETVAL["ApproverTarget Validation
requester | user:ID
(deferred: role: dynamic: notify:)"]
CONFIRMRULE["Confirm Rules
high-risk cannot use requester
requires explicit user:ID"]
AUTHZ["Approver Authorization
requester=userId match
OR explicit user:ID match"]
RESPOND["POST /api/interactions/:id/respond
approval decision endpoint"]
PISHELL["PendingInteraction(kind=confirm)
delivery/response shell"]
EXPIRY["Approval Expiry Lifecycle
created to pending(expiresAt)
to expired before/after decision"]
TARGETVAL --> CONFIRMRULE
TARGETVAL --> AUTHZ
RESPOND -->|"calls authorizeApproverDecision()"| AUTHZ
RESPOND -->|"updates status approved | rejected"| STATEM
REQID -.->|"requester must match requesterUserId"| TARGETVAL
EXPIRY -->|"wraps Proposal lifetime"| PISHELL
end
PROPOSAL --> PISHELL
subgraph BLOCKING["阻塞式审计安全门"]
direction TB
EMIT["AuditPipeline.emit()
fire-and-forget
(sync for high-risk)"]
EMITWAIT["AuditPipeline.emitAndWait()
strong sync, must succeed first"]
HIGHRISK["High-Risk Auto-Sync
auth + error categories
critical/high severity"]
JWTFAIL["JWT Signature Failure
blocking audit then 401"]
CROSSTENANT["Session Cross-Tenant Denial
blocking audit before exception"]
DENIEDERR["SessionAccessDeniedError
critical severity audit then 403"]
EMITPARAMS["EmitParams
category/action/severity/detail
(tenantId auto-resolved from ALS)"]
EMIT --> HIGHRISK
EMITWAIT -->|"awaits WAL + primary sink"| HIGHRISK
JWTFAIL -->|"emitBlockingAuthFailure()"| EMITWAIT
CROSSTENANT -->|"before throwing"| EMITWAIT
DENIEDERR -->|"thrown only after critical audit"| CROSSTENANT
EMITPARAMS --> EMIT
end
subgraph AUDITSTRUCT["审计事件模型"]
direction TB
EVTSTRUCT["AuditEvent Structure
id, timestamp, requestId, traceId,
spanId, tenantId, userId, action,
detail, category, severity"]
CATS["Categories
auth, session, tool_call,
interaction, guardrail, error"]
ORPHAN["ORPHAN_TENANT_ID = __orphan__
sentinel for lost-in-async events"]
TENANTREQ["TENANT_REQUIRED_CATEGORIES
tool_call, tool_result, llm_call, session,
quota, interaction, guardrail, quality"]
EVTSTRUCT -->|"no tenantId logged under __orphan__"| ORPHAN
CATS -->|"warn if tenantId missing"| TENANTREQ
end
CLAIMS -.-> JWTFAIL
ALS -.-> CROSSTENANT
subgraph ENCRYPT["路由决策加密与管理员访问"]
direction TB
AESGCM["AES-256-GCM (CONFIG_ENC_KEY)
IV=12 TAG=16, 32-byte key
route decision originals"]
LAYERS["R-Y 3 Encryption Layers
(a) original in payload_* columns
(b) redacted view in DB
(c) /admin/audit/read-original decrypt"]
FIELDREDACT["Field-Level Redaction (layer b)
name to hash, idcard to last4,
salary to bracket, phone to masked"]
READORIG["POST /admin/audit/read-original
audit:read-original scope required
logs decryption_access before plaintext"]
ADMINMW["adminAuthMiddleware
scope check: audit:read vs audit:read-original"]
STATICTOK["Static Admin Access Token
(ADMIN_ACCESS_TOKEN env)
bypass JWT verification"]
ADMINSUBJ["adminSubject
tracks who made admin action
(JWT sub or static token)"]
AESGCM --> LAYERS
LAYERS -->|"redacted copy to extracted_inputs jsonb"| FIELDREDACT
FIELDREDACT --> READORIG
READORIG --> ADMINMW
ADMINMW -->|"allow static token or scoped JWT"| STATICTOK
ADMINSUBJ -->|"recorded in audit_decryption_access row"| READORIG
end
packages/agent/src:orchestrator/risk-policy.ts(allow|confirm|reject)、session/approver-target.ts(requester|user:ID + high-risk deferral)、session/action-proposal-store.ts(SHA256 hash、状态机、脱敏)、audit/pipeline.ts(emit/emitAndWait、ORPHAN_TENANT_ID、TENANT_REQUIRED_CATEGORIES)、config/crypto.ts(AES-256-GCM IV=12/TAG=16)、gateway/admin-audit-original.ts(audit:read-original scope、自审计),以及 CONTEXT.md/AGENTS.md/ADR-0001。
---
title: ActionProposal & PendingInteraction 状态机
---
stateDiagram-v2
state "ActionProposal 状态机" as APTitle
note right of APTitle
action-proposal-store.ts:7-14
privatePayload: cleared on reject, kept on
approve until exec, cleared on failed
end note
[*] --> ap_pending
state "pending
初始,等待决策" as ap_pending
state "approved
decision=approved, ready" as ap_approved
state "rejected
decisionSource policy|human
privatePayload cleared" as ap_rejected
state "expired
expiresAt deadline passed" as ap_expired
state "executing
payload integrity verified" as ap_executing
state "executed
executionResult stored" as ap_executed
state "failed
payload hash mismatch" as ap_failed
ap_pending --> ap_approved : decide(status=approved) via approver
ap_pending --> ap_rejected : decide(status=rejected, decisionSource=policy|human)
ap_pending --> ap_expired : expire() on expiresAt deadline
ap_approved --> ap_executing : markExecuting() about to execute
ap_executing --> ap_executed : markExecuted(result) succeeded
ap_executing --> ap_failed : markFailed(error) mid-execution
ap_approved --> ap_failed : markFailed(error) post-decision integrity failure
ap_executed --> [*]
ap_rejected --> [*]
ap_expired --> [*]
ap_failed --> [*]
state "PendingInteraction 状态机" as PITitle
note right of PITitle
shared/types.ts:122-126
kinds: confirm, ask_user, secret_ref,
scheduled_task_approval, local_tool_result
confirm kind syncs to ActionProposal above
end note
[*] --> pi_pending
state "pending
初始,尚未响应" as pi_pending
state "approved
user/approver approved" as pi_approved
state "rejected
user/approver rejected" as pi_rejected
state "expired
expiresAt passed (once-only)" as pi_expired
pi_pending --> pi_approved : respond(decision=approve)
pi_pending --> pi_rejected : respond(decision=reject)
pi_pending --> pi_expired : expire() or respond() detects expiresAt past now
pi_approved --> [*]
pi_rejected --> [*]
pi_expired --> [*]
note left of pi_approved : confirm kind syncActionProposalDecision drives ap_approved
note left of pi_rejected : confirm kind syncActionProposalDecision drives ap_rejected
note left of pi_expired : confirm kind interaction expiry expires ActionProposal (once-only)
packages/agent/src/session/action-proposal-store.ts:7-14,278-340;packages/tool-client/src/types/capability.ts:90-101;packages/agent/src/shared/types.ts:115-126;packages/agent/src/session/pending-interaction-store.ts:141-206;packages/agent/src/routing/{decide-status.ts,route-decision-store.ts:178-189};docs/adr/0014。
每条 ADR 映射到其最主要管辖的视角,以及决策被强制执行的代码路径。ADR 编号与图中依据引用一致;映射关系是审阅者对说明文字的解读,并非对代码的新主张。
| ADR | 视角 | 代码路径(引用处) |
|---|---|---|
ADR-0001 双令牌模型 |
权限 | gateway/auth.ts、/api/auth/exchange、TokenProvider + Backend Token cache |
ADR-0003 审计管道 / 接收端 |
数据流;权限 | audit/pipeline.ts(emit / emitAndWait)、JSONL + optional Postgres sink |
ADR-0010 工具 / 风险策略 |
代理编排 | orchestrator/risk-policy.ts、tool-call-gate.ts |
ADR-0014 Action Proposal 生命周期 |
状态机;权限 | session/action-proposal-store.ts:7-14,278-340;pending-interaction-store.ts:141-206 |
ADR-0016 能力优先路由 |
代理编排;数据流 | routing/{router,rule-filter,llm-classifier,dispatchability,decide-status}.ts;agent-as-tool (K1/K7)、local workbench (K5) |
ADR-0017 服务端桌面写入策略 |
代理编排 | risk-policy.ts 中的写入门控 → tool-call-gate.ts;local-executor |
ADR-0018 启动组装 + TurnConfig |
数据流;代理编排 | orchestrator-runtime.ts:126-196、resolve-and-orchestrate.ts:92-195、ResponseGuard |
ADR-0020(数据流依据中引用) |
数据流 | 与 chat-routes.ts / orchestrator persistence 一并引用;说明中未详述具体范围 |
| R-Y 路由决策加密 | 权限;代理编排 | config/crypto.ts(AES-256-GCM)、PgRouteDecisionStore、gateway/admin-audit-original.ts |
下方完整复现源图中 unknowns 列表的全部条目,实质内容未作改动。每条标记为 未知(证据缺口 — 代码中尚未观察到)或 风险(若向不利方向落地,将威胁正确性、安全性或可运维性的未知项)。以上均非对系统实际行为的断言。