fix(ql3): preserve target-native reconciliation domains

This commit is contained in:
whyour
2026-08-24 13:55:54 +08:00
parent d94ca02e0d
commit fd10f72aba
10 changed files with 244 additions and 125 deletions
@@ -16,6 +16,16 @@ import {
const MAX_SCHEMA_OBJECTS = 4_096;
const MAX_TABLES = 512;
const TARGET_AUTOMATION_TABLES = new Set([
'QingLong3LegacyAdoptions',
'QingLong3LegacyAdoptionTasks',
'QingLong3LocalExecutionContextRecipes',
'QingLong3LocalTaskExecutionRevisions',
]);
const TARGET_RUN_HISTORY_TABLES = new Set([
'QingLong3RunAttemptLogArtifactTombstones',
'QingLong3RunAttemptLogRetentionState',
]);
export interface LocalReconciliationDomainInventory {
readonly domain: LocalReconciliationPlanDomain;
@@ -85,6 +95,7 @@ function targetDomain(name: string): LocalReconciliationPlanDomain {
return 'schema_lineage';
}
if (
TARGET_AUTOMATION_TABLES.has(name) ||
name.includes('TaskDefinition') ||
name.includes('Trigger') ||
name.includes('Automation')
@@ -95,6 +106,7 @@ function targetDomain(name: string): LocalReconciliationPlanDomain {
return 'secret_and_config';
}
if (
TARGET_RUN_HISTORY_TABLES.has(name) ||
name === 'Runs' ||
name.startsWith('Run') ||
name.startsWith('StepRun') ||
@@ -175,10 +175,11 @@ function domainDisposition(
) {
return 'unsupported';
}
if (domain === 'identity_policy_audit' && legacyFacts > 0) {
return 'manual_required';
}
if (
(domain === 'secret_and_config' ||
domain === 'run_history' ||
domain === 'identity_policy_audit') &&
(domain === 'secret_and_config' || domain === 'run_history') &&
legacyFacts + targetFacts > 0
) {
return 'manual_required';
@@ -297,10 +297,14 @@ export function assertLocalReconciliationReviewDecisionMatchesFact(
!['retain_target', 'retain_both', 'defer', 'manual_external'].includes(
selected.disposition,
)) ||
((fact.domain === 'secret_and_config' ||
fact.domain === 'identity_policy_audit' ||
fact.domain === 'unknown') &&
!['defer', 'manual_external'].includes(selected.disposition))
((fact.domain === 'secret_and_config' || fact.domain === 'unknown') &&
!['defer', 'manual_external'].includes(selected.disposition)) ||
(fact.domain === 'identity_policy_audit' &&
!(
fact.database === 'target'
? ['retain_target', 'defer', 'manual_external']
: ['defer', 'manual_external']
).includes(selected.disposition))
) {
configurationError(
'decision disposition is not allowed for canonical fact',
@@ -195,6 +195,12 @@ function requirement(
});
}
if (domain === 'identity_policy_audit') {
if (database === 'target') {
return Object.freeze({
decisionRequirement: 'required' as const,
reason: 'reviewable_fact' as const,
});
}
return Object.freeze({
decisionRequirement: 'blocked' as const,
reason: 'identity_custody_required' as const,