| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- from pathlib import Path
- from app.core.common.identifiers import new_governance_uid
- from app.core.data_rules.contracts import validate_dataflow_spec
- API = Path("frontend/src/api/dataRules.js")
- AUTHORING = Path("frontend/src/components/DataRules/RuleAuthoringPanel.vue")
- CATALOG = Path("frontend/src/components/DataRules/RuleCatalogPicker.vue")
- EVIDENCE = Path("frontend/src/components/DataRules/CompilationEvidence.vue")
- ASSEMBLER = Path(
- "frontend/src/components/DataRules/ProductionLineAssembler.vue"
- )
- STANDARD = Path(
- "frontend/src/views/dataGovernance/dataStandard/components/edit.vue"
- )
- DATAFLOW = Path(
- "frontend/src/views/dataGovernance/dataProcess/components/edit.vue"
- )
- FACTORY = Path(
- "frontend/src/views/dataFactory/workflow/ProductionLineDeployment.vue"
- )
- FACTORY_INDEX = Path("frontend/src/views/dataFactory/workflow/index.vue")
- def test_rule_api_client_exposes_versions_publish_and_server_side_release():
- source = API.read_text(encoding="utf-8")
- assert "http.get('/rules/capabilities')" in source
- assert "http.post('/rules/interpret'" in source
- assert "http.post('/rules/validate'" in source
- assert "http.post('/rules/production-lines/resolve'" in source
- assert "http.post('/rules/rule-versions'" in source
- assert "http.post(`/rules/rule-versions/${versionId}/publish`)" in source
- assert "http.post(`/rules/rule-versions/${versionId}/validate`" in source
- assert "http.post(`/rules/rule-versions/${versionId}/test`" in source
- assert "http.get('/rules/catalog'" in source
- assert "/rules/catalog/assets/${assetType}/${versionId}/evidence" in source
- assert "http.post('/rules/standard-versions'" in source
- assert "http.post(`/rules/standard-versions/${versionId}/publish`)" in source
- assert "http.post(`/rules/production-lines/${dataflowUid}/release`" in source
- assert "listDataFlowDeployments" in source
- assert "/deploy-disabled" in source
- assert "/canary" in source
- assert "/activate" in source
- assert "/rollback" in source
- def test_reusable_authoring_panel_preserves_human_review_gate():
- source = AUTHORING.read_text(encoding="utf-8")
- assert "authoringSurface" in source
- assert "interpretRule" in source
- assert "clarification_required" in source
- assert "$emit('candidate'" in source
- assert "createRuleVersion" in source
- assert "publishRuleVersion" in source
- assert "先生成并发布 RuleVersion" in source
- assert "rules:publish" in source
- assert "$emit('version'" in source
- assert "自动执行" not in source
- def test_authoring_panel_exposes_governed_ai_lifecycle_without_code_editor():
- source = AUTHORING.read_text(encoding="utf-8")
- for token in [
- "schemaContextReady",
- "generation_receipt",
- "assumptions",
- "ambiguities",
- "modelProvenance",
- "validateRuleVersion",
- "testRuleVersion",
- "CompilationEvidence",
- ]:
- assert token in source
- assert "candidatePreview" not in source
- assert "<pre>{{ candidate" not in source
- def test_catalog_picker_selects_fixed_published_asset_versions():
- source = CATALOG.read_text(encoding="utf-8")
- for token in [
- "searchPublishedCatalog",
- "assetType",
- "published",
- "schema_compatibility",
- "latest_evidence",
- "v-skeleton-loader",
- "aria-label",
- "keydown",
- ]:
- assert token in source
- assert "$emit('input', item.id)" in source
- assert "item.name" in source
- assert "rule_uid" in source
- assert "standard_uid" in source
- def test_compilation_evidence_shows_trusted_chain_without_sensitive_payloads():
- source = EVIDENCE.read_text(encoding="utf-8")
- for token in [
- "generation",
- "logical_compile",
- "dry_run",
- "publication",
- "physical",
- "getRuleVersionEvidence",
- ]:
- assert token in source
- for forbidden in ["raw_sample", "secret", "password", "token"]:
- assert forbidden not in source.lower()
- assert "'ready'" in source
- def test_standard_links_published_rules_and_keeps_legacy_code_read_only():
- standard = STANDARD.read_text(encoding="utf-8")
- assert 'authoring-surface="data_standard"' in standard
- assert '@version="handleRuleVersion"' in standard
- assert "RuleCatalogPicker" in standard
- assert "rule_version_id" in standard
- assert "legacyMigration" in standard
- assert "readonly" in standard
- assert "迁移" in standard
- assert "dataStandardCodeGenerate" not in standard
- assert "handleCodeGenerate" not in standard
- assert "rule_version_status" not in standard
- def test_dataflow_assembler_uses_published_catalog_ids_without_inline_rules():
- source = ASSEMBLER.read_text(encoding="utf-8")
- dataflow = DATAFLOW.read_text(encoding="utf-8")
- assert "RuleCatalogPicker" in source
- assert "standard_version_id" in source
- assert "rule_version_id" in source
- assert "schema_compatibility" in source
- assert "releaseReadiness" in source
- assert "component_kind" in source
- assert "rule_spec" not in source
- assert "operation_code" not in source
- assert "ProductionLineAssembler" in dataflow
- assert "dataflow_spec" in dataflow
- assert "migration_metadata" in dataflow
- assert "rule_spec" not in dataflow
- assert "v-model=\"changeObj.rule\"" not in dataflow
- assert "handleRuleCandidate" not in dataflow
- def test_assembler_emits_a_real_closed_dataflow_spec_for_every_station_kind():
- standard_version_id = new_governance_uid()
- apply_rule_version_id = new_governance_uid()
- quality_rule_version_id = new_governance_uid()
- normalized = validate_dataflow_spec(
- {
- "schema_version": "1.0",
- "dataflow_uid": new_governance_uid(),
- "name": "客户数据生产线",
- "description": "固定受治理资产版本",
- "input_schema_refs": ["bd:customer_raw:v1"],
- "output_schema_ref": "bd:customer_clean:v1",
- "components": [
- {
- "id": "station_1",
- "type": "standard.enforce",
- "standard_version_id": standard_version_id,
- "stage": "quality_gate",
- "order": 1,
- },
- {
- "id": "station_2",
- "type": "rule.apply",
- "rule_version_id": apply_rule_version_id,
- "stage": "transform",
- "order": 2,
- "idempotency": {
- "strategy": "partition_replace",
- "key": "run_partition",
- },
- },
- {
- "id": "station_3",
- "type": "quality.check",
- "rule_version_id": quality_rule_version_id,
- "stage": "quality_gate",
- "order": 3,
- },
- ],
- "parameters": {},
- }
- )
- assert "idempotency" not in normalized["components"][0]
- assert "idempotency" in normalized["components"][1]
- assert "idempotency" not in normalized["components"][2]
- source = ASSEMBLER.read_text(encoding="utf-8")
- assert "station.component_kind === 'rule.apply'" in source
- assert "component.idempotency" in source
- assert "idempotency: {" not in source
- def test_catalog_never_guesses_schema_compatibility_from_arbitrary_objects():
- source = CATALOG.read_text(encoding="utf-8")
- assembler = ASSEMBLER.read_text(encoding="utf-8")
- assert "normalizeCompatibility" in source
- assert "Object.keys(item.schema_compatibility).length" not in source
- assert "unknown" in source
- assert "schema_compatibility !== 'compatible'" in assembler
- assert "服务端发布预检" in assembler
- assert "requestSequence" in source
- assert "requestId !== this.requestSequence" in source
- assert "getPublishedCatalogAsset" in source
- assert "inputSchemaRefs" in source
- assert "outputSchemaRef" in source
- def test_production_line_editor_renews_expiring_receipts_and_retries_only_safe_errors():
- source = DATAFLOW.read_text(encoding="utf-8")
- request = Path("frontend/src/utils/request.js").read_text(encoding="utf-8")
- assert "governedDraftExpiresAt" in source
- assert "data.expires_at" in source
- assert "expiresAt - Date.now() <= 60000" in source
- assert "ensureFreshDraftReservation" in source
- assert "draft_reservation_refresh_required" in source
- assert "governedDraftReplayRequired" in source
- assert "if (this.governedDraftReplayRequired) return" in source
- assert "await this.ensureDataflowUid(true)" in source
- assert source.count("await api.addDataFlow(payload)") == 2
- assert "error.response?.data" in request
- def test_new_dataflow_gets_server_governed_uid_before_assembly():
- api = API.read_text(encoding="utf-8")
- dataflow = DATAFLOW.read_text(encoding="utf-8")
- assert "createProductionLineDraftIdentity" in api
- assert "/rules/production-lines/draft-identity" in api
- assert "ensureDataflowUid" in dataflow
- assert "if (!this.dataflowUid) await this.ensureDataflowUid()" in dataflow
- assert "persistedUid" in dataflow
- assert "dataflow_uid: null" not in dataflow
- def test_standard_authoring_does_not_forge_validated_state_client_side():
- source = AUTHORING.read_text(encoding="utf-8")
- assert "candidate.candidate_type === 'standard'" not in source or (
- "status: 'validated'" not in source
- )
- assert "先发布规则,再在标准条款中绑定" in source
- def test_data_factory_exposes_governed_trial_activation_and_rollback():
- page = FACTORY.read_text(encoding="utf-8")
- index = FACTORY_INDEX.read_text(encoding="utf-8")
- assert "数据生产线投产" in page
- assert "getRuleCapabilities" in page
- assert "data_factory_readiness" in page
- assert "listDataFlowDeployments" in page
- assert "listDataFlowDeploymentCandidates" in page
- assert "createDataFlowDeployment" in page
- assert "deployDataFlowDisabled" in page
- assert "runDataFlowCanary" in page
- assert "activateDataFlowDeployment" in page
- assert "rollbackDataFlowDeployment" in page
- assert "reconcileDataFlowDeploy" in page
- assert "reconcileDataFlowActivate" in page
- assert "reconcileDataFlowRollback" in page
- assert "dataflows:deploy" in page
- assert "dataflows:canary" in page
- assert "rules:execute" in page
- assert "dataflows:activate" in page
- assert "dataflows:rollback" in page
- assert "生产线包 Hash" in page
- assert "试生产证据" in page
- assert "状态履历" in page
- assert "生产线入厂" in page
- assert "window.localStorage.getItem(storageKey)" in page
- assert "window.localStorage.setItem(storageKey, value)" in page
- assert "error?.error?.code === 'terminal_conflict'" in page
- assert "Number(error?.code) === 409" not in page
- assert "unknown_operations" in page
- assert "v-dialog" in page
- assert "ProductionLineDeployment" in index
|