Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .github/workflows/backend-prisma-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ on:
- "apps/backend/**"
- "packages/shared-types/**"
- "pnpm-lock.yaml"
- "package.json"
- "scripts/check-backend-capability-boundaries.ts"
- ".github/workflows/backend-prisma-quality.yml"
push:
branches:
Expand All @@ -14,6 +16,8 @@ on:
- "apps/backend/**"
- "packages/shared-types/**"
- "pnpm-lock.yaml"
- "package.json"
- "scripts/check-backend-capability-boundaries.ts"
- ".github/workflows/backend-prisma-quality.yml"

jobs:
Expand Down Expand Up @@ -65,6 +69,9 @@ jobs:
- name: Backend lint
run: pnpm --filter @text2sql/backend run lint

- name: Backend capability boundary check
run: pnpm run backend:capability-boundary:check

- name: Backend build
run: pnpm --filter @text2sql/backend run build

Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/governance-terminology-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: governance-terminology-quality

on:
pull_request:
paths:
- "README.md"
- "docs/standards/**"
- "apps/backend/src/modules/governance/**"
- "apps/frontend/src/app/settings/**"
- "apps/frontend/src/components/settings/**"
- "scripts/check-governance-terminology.ts"
- "package.json"
- "pnpm-lock.yaml"
- ".github/workflows/governance-terminology-quality.yml"
push:
branches:
- main
paths:
- "README.md"
- "docs/standards/**"
- "apps/backend/src/modules/governance/**"
- "apps/frontend/src/app/settings/**"
- "apps/frontend/src/components/settings/**"
- "scripts/check-governance-terminology.ts"
- "package.json"
- "pnpm-lock.yaml"
- ".github/workflows/governance-terminology-quality.yml"

jobs:
quality:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Setup PNPM
uses: pnpm/action-setup@v5

- name: Setup Node
uses: actions/setup-node@v5
with:
node-version: 20
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Governance terminology check
run: pnpm run governance:terminology:check
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ __pycache__/
.env.local
.env.*.local
.omx/
.enter/*
.enter/*
*/graphify-out/*
36 changes: 36 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,42 @@ CI 参考:
必跑检查:
- `GET http://localhost:3002/health` 中 stream/tool-calling 相关字段应符合预期。

### D. Governance 术语硬切规范
来源:`docs/standards/governance-terminology-spec.md`

适用范围:
- `apps/backend/src/modules/governance/**`
- `apps/frontend/src/lib/admin-api-client.ts`
- `docs/standards/**`
- `README.md`

关键 MUST:
- 治理主链路仅使用 `workspace datasource binding`、`table-permissions`、`policyVersion`。
- 不得在治理主链路继续接受 legacy 路由/字段(`table-acl`、`acl`、`rule-group`)。
- 历史术语只允许出现在明确迁移上下文(带迁移注记),不得作为 active narrative。

必跑检查:
- `pnpm run governance:terminology:check`

### E. 后端业务能力拓扑规范
来源:`docs/standards/backend-business-capability-topology-spec.md`

适用范围:
- `apps/backend/src/modules/**`
- `apps/backend/src/app.module.ts`
- `scripts/check-backend-capability-boundaries.ts`

关键 MUST:
- 后端一级能力域固定为 `conversation/governance/knowledge/platform`。
- 依赖方向固定:`conversation -> governance|knowledge|platform`,`governance|knowledge -> platform`。
- `platform` 禁止反向依赖业务域;跨域调用仅允许稳定入口(facade/public entry)。
- 禁止新增“宽导出中枢”形态依赖。
- 业务域及其兼容根模块(`chat/agent/memory/glossary/rag`)禁止直接 import `modules/data/**` 实现路径。
- 业务域及其兼容根模块禁止依赖 `platform/data/data.module.ts`(`PlatformDataModule` 聚合入口)。

必跑检查:
- `pnpm run backend:capability-boundary:check`(落地后)

说明:
- 以上仅为执行摘要,细节规则以 standards 原文为准。

Expand Down
39 changes: 39 additions & 0 deletions GOVERNANCE_HARD_CUT_PROGRESS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Governance Hard Cut Progress (2026-04-19 Revalidation)

Branch: `codex/governance-terminology-hard-cut-exec`

## Current Status

- Unit 1 (boundary scaffold): partial
- Unit 2 (auth policy boundary cutover): partial
- Unit 3 (canonical contract + workflow secret baseline): done
- Unit 4 (single-window consumer contract cutover): partial
- Unit 5 (docs/gate closeout): partial

## Multi-Agent Audit Summary

1. Three parallel lanes executed for status revalidation:
- Lane A: Unit 1 + Unit 2
- Lane B: Unit 3 + Unit 4
- Lane C: Unit 5 + Gate traceability
2. Unit 3 is technically complete and test-covered.
3. Unit 1/2/4/5 are behavior-mostly-green but not fully plan-file-parity-complete.
4. A gate-trace mismatch remains between plan naming (`G0/G1/G2/G3`) and execution log naming (`Gate A/B/C`).

## Fresh Verification Snapshot

- `pnpm run backend:capability-boundary:check` pass
- `pnpm --filter @text2sql/backend exec jest --runInBand test/unit/capability-boundary-check.spec.ts test/integration/policy-evaluator.spec.ts test/e2e/workspace-datasource-authz.spec.ts test/e2e/user-workspace-authz.spec.ts` pass
- `pnpm --filter @text2sql/backend exec jest --runInBand test/e2e/datasource-workflow-api.spec.ts test/e2e/workspace-datasource-api.spec.ts test/e2e/chat-table-permissions-policy.spec.ts test/integration/datasource-service.spec.ts` pass
- `pnpm run governance:terminology:check` pass (legacy module list line marked with `governance-terminology:allow-legacy`)

## Open Items

1. Complete Unit 2 governance access guard ownership landing.
2. Reconcile Unit 4 plan-listed declaration file expectation (`api.d.ts`) with actual shared-types generation/runtime path.
3. Align and close gate records (G0/G1/G2/G3) with owner sign-off evidence.

## Detailed Log

- Full execution notes: `docs/plans/2026-04-18-004-refactor-governance-domain-terminology-hard-cut-execution-log.md`
- Working tracker: `docs/plans/2026-04-18-004-refactor-governance-domain-terminology-hard-cut-progress-tracker.md`
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@ Text2SQL 学习演示版(阶段0-3路线)的单仓项目。
- 后端迁移规范:`docs/standards/backend-prisma-migration-spec.md`
- R1 门禁与灰度规范:`docs/standards/r1-gate-and-rollout-spec.md`
- LLM 流式与 Tool Calling 迁移规范:`docs/standards/llm-stream-tool-migration-spec.md`
- 治理术语硬切规范:`docs/standards/governance-terminology-spec.md`
- 后端能力域拓扑规范:`docs/standards/backend-business-capability-topology-spec.md`
- 前端重写需求:`docs/brainstorms/2026-04-10-frontend-react-shadcn-rewrite-requirements.md`

## 后端能力域拓扑(迁移中)
- 顶层能力域采用:`conversation`、`governance`、`knowledge`、`platform`。
- 依赖方向固定:`conversation -> governance|knowledge|platform`,`governance|knowledge -> platform`。
- 迁移阶段允许兼容入口(re-export/wrapper)短期存在,但禁止引入新的跨域实现细节直连。
- 详细规则见:`docs/standards/backend-business-capability-topology-spec.md`。

### 数据库结构改动铁律(必须遵守)
- 禁止手写或手改 `apps/backend/prisma/migrations/*/migration.sql`。
- 先改 `apps/backend/prisma/schema.prisma`,再执行 `pnpm --filter @text2sql/backend run prisma:migrate -- --name <migration_name>` 生成迁移。
Expand Down Expand Up @@ -209,11 +217,13 @@ ts-node apps/backend/scripts/langsmith-coverage-check.ts \
- `kind`:固定为 `agent-run`
- `outcome`:`clarification | executionResult | rejected | failed`
- `run`:完整运行结果(含 `trace` 与可选 `llmRaw`)
- 请求体支持可选 `contextEnvelope`(`metricDefinition/timeRange/entityMappings/mustIncludeTables/mustExcludeTables/businessConstraints`)
- `agent`:聚合元信息(provider/model、是否有 SQL、是否有工具调用、是否有错误)
- SSE 事件类型:`start`、`text-delta`、`tool-call`、`tool-result`、`tool-error`、`state`、`finish`、`error`。
- SSE 事件必填字段:`type`、`runId`、`sessionId`、`at`、`data`;其中 `data` 为结构化对象,不再混用字符串载荷。
- 当前 Tool Calling 基础能力默认启用,首个工具为 `runReadOnlySql`(只读 SQL 执行,含输入校验与安全守卫)。
- SQL 运行时提示词模板命中证据通过 `run.trace.promptTemplate` 与 `run.delivery.evidence.promptTemplate` 暴露(字段:`templateId/scene/scope/version/fallbackReason`)。
- 上下文生效证据通过 `run.trace.effectiveContextSummary/conflictHint` 与 `run.delivery.evidence.effectiveContextSummary/conflictHint` 双层暴露,前端可区分用户显式上下文与系统上下文来源。

## 测试
```bash
Expand Down
37 changes: 5 additions & 32 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,10 @@
import { Module } from "@nestjs/common";
import { AppConfigModule } from "./modules/config/config.module";
import { SystemModule } from "./modules/system/system.module";
import { DataModule } from "./modules/data/data.module";
import { AgentModule } from "./modules/agent/agent.module";
import { ChatModule } from "./modules/chat/chat.module";
import { EvalModule } from "./modules/eval/eval.module";
import { LlmModule } from "./modules/llm/llm.module";
import { ObservabilityModule } from "./modules/observability/observability.module";
import { RagModule } from "./modules/rag/rag.module";
import { DatasourceModule } from "./modules/datasource/datasource.module";
import { SettingsModule } from "./modules/settings/settings.module";
import { SemanticRegistryModule } from "./modules/semantic-registry/semantic-registry.module";
import { UserModule } from "./modules/user/user.module";
import { WorkspaceModule } from "./modules/workspace/workspace.module";
import { GlossaryModule } from "./modules/glossary/glossary.module";
import { ConversationModule } from "./modules/conversation/conversation.module";
import { GovernanceModule } from "./modules/governance/governance.module";
import { KnowledgeModule } from "./modules/knowledge/knowledge.module";
import { PlatformModule } from "./modules/platform/platform.module";

@Module({
imports: [
AppConfigModule,
DatasourceModule,
ObservabilityModule,
RagModule,
DataModule,
LlmModule,
SettingsModule,
SemanticRegistryModule,
UserModule,
WorkspaceModule,
GlossaryModule,
AgentModule,
ChatModule,
EvalModule,
SystemModule
]
imports: [PlatformModule, GovernanceModule, KnowledgeModule, ConversationModule]
})
export class AppModule {}
12 changes: 8 additions & 4 deletions apps/backend/src/modules/agent/agent.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Module } from "@nestjs/common";
import { AppConfigModule } from "../config/config.module";
import { DataModule } from "../data/data.module";
import { DatasourceModule } from "../datasource/datasource.module";
import { PlatformDataPersistenceModule } from "../platform/data/persistence.module";
import { PlatformDataQueryModule } from "../platform/data/query.module";
import { DatasourceModule } from "../governance/datasource/datasource.module";
import { GovernanceAccessModule } from "../governance/access/access.module";
import { LlmModule } from "../llm/llm.module";
import { ObservabilityModule } from "../observability/observability.module";
import { RagModule } from "../rag/rag.module";
import { SemanticRegistryModule } from "../semantic-registry/semantic-registry.module";
import { SettingsModule } from "../settings/settings.module";
import { SettingsModule } from "../governance/settings/settings.module";
import { BuildIntentPlanNode } from "./nodes/build-intent-plan.node";
import { BuildPhysicalPlanNode } from "./nodes/build-physical-plan.node";
import { BuildSemanticQueryNode } from "./nodes/build-semantic-query.node";
Expand All @@ -30,7 +32,9 @@ import { PlannerCacheService } from "./planner/planner-cache.service";
@Module({
imports: [
AppConfigModule,
DataModule,
PlatformDataPersistenceModule,
PlatformDataQueryModule,
GovernanceAccessModule,
DatasourceModule,
LlmModule,
SettingsModule,
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/modules/agent/graph/agent.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ClarificationPrompt, ExecutionTrace } from "@text2sql/shared-types";
import type { DatasourceType } from "@text2sql/shared-types";
import type { SqlTableAccessContext } from "../../data/query/sql-table-access-guard.service";
import type { SqlTableAccessContext } from "../../platform/data/query/index";

export interface GraphTraceContext {
source: "chat" | "evaluation";
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/modules/agent/graph/langgraph.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
SqlRun
} from "@text2sql/shared-types";
import type { GraphInput, GraphTraceContext } from "./agent.types";
import type { SqlTableAccessContext } from "../../data/query/sql-table-access-guard.service";
import type { SqlTableAccessContext } from "../../platform/data/query/index";
import type { RetrievedKnowledge } from "../nodes/retrieve-knowledge.node";
import type { IntentPlan } from "../nodes/build-intent-plan.node";
import type { SemanticQueryPlan } from "../nodes/build-semantic-query.node";
Expand Down
32 changes: 17 additions & 15 deletions apps/backend/src/modules/agent/nodes/execute-sql.node.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Injectable } from "@nestjs/common";
import { DomainError } from "../../../common/domain-error";
import { ChatRepository } from "../../data/persistence/chat.repository";
import { AuditLogRepository } from "../../data/persistence/audit-log.repository";
import { QueryExecutorRouterService } from "../../data/query/query-executor-router.service";
import type { SqlTableAccessContext } from "../../data/query/sql-table-access-guard.service";
import { DatasourceService } from "../../datasource/datasource.service";
import type { AccessContext } from "../../auth/datasource-access-policy.service";
import { PolicyEvaluatorService } from "../../auth/policy-evaluator.service";
import { AuditLogRepository, ChatRepository } from "../../platform/data/persistence/index";
import {
QueryExecutorRouterService,
type SqlTableAccessContext
} from "../../platform/data/query/index";
import { DatasourceService } from "../../governance/datasource/datasource.service";
import type { AccessContext } from "../../governance/access/datasource-access-policy.service";
import { PolicyEvaluatorService } from "../../governance/access/policy-evaluator.service";

@Injectable()
export class ExecuteSqlNode {
Expand Down Expand Up @@ -67,16 +68,16 @@ export class ExecuteSqlNode {
return await this.queryExecutorRouter.execute({
datasource,
sql: input.sql,
acl: effectiveAccessContext
tablePermissions: effectiveAccessContext
? {
accessContext: effectiveAccessContext,
allowedTables: policyResult?.readableTables
}
: undefined
});
} catch (error) {
if (this.isAclGuardError(error) && effectiveAccessContext) {
await this.writeAclDeniedAudit({
if (this.isTablePermissionsGuardError(error) && effectiveAccessContext) {
await this.writeTablePermissionsDeniedAudit({
error,
sql: input.sql,
datasourceId: input.datasourceId,
Expand Down Expand Up @@ -148,14 +149,15 @@ export class ExecuteSqlNode {
};
}

private isAclGuardError(error: unknown): error is DomainError {
private isTablePermissionsGuardError(error: unknown): error is DomainError {
return (
error instanceof DomainError &&
(error.code === "ACL_FORBIDDEN" || error.code === "ACL_PARSE_REJECTED")
(error.code === "TABLE_PERMISSIONS_FORBIDDEN" ||
error.code === "TABLE_PERMISSIONS_PARSE_REJECTED")
);
}

private async writeAclDeniedAudit(input: {
private async writeTablePermissionsDeniedAudit(input: {
error: DomainError;
sql: string;
datasourceId: string;
Expand All @@ -166,7 +168,7 @@ export class ExecuteSqlNode {
try {
await this.auditLogRepository.appendEvent({
phase: "governance",
eventType: "workspace.datasource.acl.denied",
eventType: "workspace.datasource.table-permissions.denied",
eventCode: input.error.code,
severity: "warning",
message: input.error.message,
Expand All @@ -183,7 +185,7 @@ export class ExecuteSqlNode {
});
} catch (auditError) {
throw new DomainError(
"ACL_AUDIT_WRITE_FAILED",
"TABLE_PERMISSIONS_AUDIT_WRITE_FAILED",
"授权拒绝审计写入失败,已拒绝执行。",
503,
{
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/modules/agent/nodes/safety-check.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DomainError } from "../../../common/domain-error";
import {
SqlTableAccessGuardService,
type SqlTableAccessContext
} from "../../data/query/sql-table-access-guard.service";
} from "../../platform/data/query/index";
import {
SqlSafetyGuard,
type SqlSafetyDecision
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ProviderRouterService } from "../../llm/provider-router.service";
import { SqlOutputExtractor } from "./sql-output-extractor";
import { SqlPromptBuilder } from "./sql-prompt.builder";
import type { RagRetrievalChunkPayload } from "../../rag/retrieval/rag-retrieval.types";
import { PromptTemplateService } from "../../settings/prompt-template.service";
import { PromptTemplateService } from "../../governance/settings/prompt-template.service";

export interface SqlDraft {
provider: string;
Expand Down
Loading
Loading