@aopslabs/aops 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/NOTICE +7 -0
- package/README.md +203 -0
- package/assets/agent-assets/core/SKILL.md +49 -0
- package/assets/agent-assets/core/references/agentspace/SKILL.md +78 -0
- package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +108 -0
- package/assets/agent-assets/core/references/chatv3/SKILL.md +48 -0
- package/assets/agent-assets/core/references/collaborative-work/SKILL.md +85 -0
- package/assets/agent-assets/core/references/discuss/SKILL.md +66 -0
- package/assets/agent-assets/core/references/docman/SKILL.md +69 -0
- package/assets/agent-assets/core/references/hosted-chat/SKILL.md +64 -0
- package/assets/agent-assets/core/references/mission/SKILL.md +54 -0
- package/assets/agent-assets/core/references/projectman/SKILL.md +86 -0
- package/assets/agent-assets/core/references/sys/SKILL.md +36 -0
- package/assets/agent-assets/core/references/view/SKILL.md +58 -0
- package/assets/agent-assets/core/references/working-disciplines/SKILL.md +69 -0
- package/assets/agent-assets/core/user-guides/agent-assets.md +81 -0
- package/assets/agent-assets/core/user-guides/agentspace.md +1098 -0
- package/assets/agent-assets/core/user-guides/aops-cli.md +1107 -0
- package/assets/agent-assets/core/user-guides/aops-system.md +63 -0
- package/assets/agent-assets/core/user-guides/chatv3.md +113 -0
- package/assets/agent-assets/core/user-guides/docman.md +162 -0
- package/assets/agent-assets/core/user-guides/projectman.md +212 -0
- package/assets/agent-assets/core/user-guides/sys.md +94 -0
- package/assets/agent-assets/core/user-guides/working-disciplines.md +588 -0
- package/assets/agent-assets/gateway/aops/SKILL.md +14 -0
- package/assets/r6-remote-session-baseline.json +19 -0
- package/assets/skills/aops-install/SKILL.md +231 -0
- package/assets/skills/aops-install/agents/openai.yaml +4 -0
- package/dist/commands/activity.js +352 -0
- package/dist/commands/agent-profile.js +653 -0
- package/dist/commands/agent.js +710 -0
- package/dist/commands/agents-md.js +125 -0
- package/dist/commands/api.js +84 -0
- package/dist/commands/archive.js +873 -0
- package/dist/commands/artifact.js +535 -0
- package/dist/commands/assets.js +1414 -0
- package/dist/commands/auth/device-login.js +1 -0
- package/dist/commands/auth/legacy-export.js +177 -0
- package/dist/commands/auth/login.js +426 -0
- package/dist/commands/chat.js +1363 -0
- package/dist/commands/chatv3.js +1684 -0
- package/dist/commands/checkpoint.js +549 -0
- package/dist/commands/commercial-artifact.js +475 -0
- package/dist/commands/commercial-license.js +594 -0
- package/dist/commands/community-auth.js +62 -0
- package/dist/commands/community-cockpit.js +185 -0
- package/dist/commands/community-console.js +109 -0
- package/dist/commands/community-doctor.js +335 -0
- package/dist/commands/community-server.js +2062 -0
- package/dist/commands/community-setup.js +284 -0
- package/dist/commands/discuss.js +1448 -0
- package/dist/commands/doc.js +5219 -0
- package/dist/commands/experience.js +922 -0
- package/dist/commands/host.js +1127 -0
- package/dist/commands/init.js +118 -0
- package/dist/commands/memory.js +3129 -0
- package/dist/commands/mission.js +562 -0
- package/dist/commands/official-catalog.js +134 -0
- package/dist/commands/plan.js +84 -0
- package/dist/commands/playbook.js +415 -0
- package/dist/commands/pm/context.js +6 -0
- package/dist/commands/pm/index.js +701 -0
- package/dist/commands/pm/projectman.js +6266 -0
- package/dist/commands/project.js +1080 -0
- package/dist/commands/prompt.js +1024 -0
- package/dist/commands/repo-sync.js +1907 -0
- package/dist/commands/resource.js +527 -0
- package/dist/commands/skill.js +1211 -0
- package/dist/commands/start-disciplines.js +510 -0
- package/dist/commands/start.js +1343 -0
- package/dist/commands/target.js +309 -0
- package/dist/commands/version.js +42 -0
- package/dist/commands/view.js +1852 -0
- package/dist/launchers/cockpit.js +28 -0
- package/dist/launchers/options.js +74 -0
- package/dist/launchers/server.js +41 -0
- package/dist/lib/agent-assets/envelope.js +83 -0
- package/dist/lib/agent-assets/gateway.js +15 -0
- package/dist/lib/agent-assets/guards.js +23 -0
- package/dist/lib/agent-assets/hosted-discovery.js +148 -0
- package/dist/lib/agent-assets/hosted-package-input.js +154 -0
- package/dist/lib/agent-assets/legacy-pointer-migration.js +677 -0
- package/dist/lib/agent-assets/native-fs.js +589 -0
- package/dist/lib/agent-assets/package-manifest.js +324 -0
- package/dist/lib/agent-assets/portable-path.js +67 -0
- package/dist/lib/agent-assets/release-input.js +177 -0
- package/dist/lib/agent-assets/roots.js +45 -0
- package/dist/lib/agent-assets/runtime-binding-reader.js +545 -0
- package/dist/lib/agent-assets/runtime-targets.js +50 -0
- package/dist/lib/agent-assets/store-reader.js +1212 -0
- package/dist/lib/agent-assets/store-types.js +1 -0
- package/dist/lib/agent-assets/store-writer.js +1484 -0
- package/dist/lib/agent-assets/types.js +1 -0
- package/dist/lib/agent-assets/unicode-case-folding-v15-1.generated.js +1548 -0
- package/dist/lib/commercial-final-readiness.js +504 -0
- package/dist/lib/commercial-lifecycle-smoke-isolation.js +236 -0
- package/dist/lib/commercial-managed-postgres-docker-adapter.js +274 -0
- package/dist/lib/commercial-setup-readiness-adapter.js +179 -0
- package/dist/lib/community-client-contract.js +164 -0
- package/dist/lib/community-cockpit-lifecycle.js +601 -0
- package/dist/lib/community-command-abort.js +59 -0
- package/dist/lib/community-diagnostic.js +237 -0
- package/dist/lib/community-docker-adapter.js +498 -0
- package/dist/lib/community-home.js +31 -0
- package/dist/lib/community-instance-contract.js +148 -0
- package/dist/lib/community-instance-layout.js +97 -0
- package/dist/lib/community-lifecycle.js +1631 -0
- package/dist/lib/community-migration-snapshot.js +770 -0
- package/dist/lib/community-native-application-recovery.js +425 -0
- package/dist/lib/community-native-child.js +240 -0
- package/dist/lib/community-native-database-recovery.js +456 -0
- package/dist/lib/community-native-lifecycle.js +2458 -0
- package/dist/lib/community-native-migration.js +339 -0
- package/dist/lib/community-native-postgres.js +596 -0
- package/dist/lib/community-operation-journal.js +773 -0
- package/dist/lib/community-operation-lock.js +596 -0
- package/dist/lib/community-release-resolver.js +291 -0
- package/dist/lib/community-release-verifier.js +475 -0
- package/dist/lib/community-repo-discovery.js +252 -0
- package/dist/lib/community-setup-server-env.js +203 -0
- package/dist/lib/external-url.js +110 -0
- package/dist/lib/official-catalog-gateway.js +108 -0
- package/dist/lib/official-catalog.js +364 -0
- package/dist/lib/server-bootstrap.js +240 -0
- package/dist/lib/setup-agent-assets-bridge.js +176 -0
- package/dist/lib/setup-agent-assets-release.js +52 -0
- package/dist/lib/setup-external-postgres.js +108 -0
- package/dist/lib/setup-init-orchestrator.js +990 -0
- package/dist/lib/setup-install-guide.js +52 -0
- package/dist/lib/setup-installer-release.js +47 -0
- package/dist/lib/setup-local-postgres.js +329 -0
- package/dist/lib/setup-official-catalog-bridge.js +148 -0
- package/dist/lib/setup-readiness.js +888 -0
- package/dist/lib/tui-launcher.js +59 -0
- package/dist/main.js +150 -0
- package/dist/seeds/agents-md.js +54 -0
- package/dist/utils/agent-gateway.js +275 -0
- package/dist/utils/agents-md.js +281 -0
- package/dist/utils/api.js +255 -0
- package/dist/utils/chatv3-session-store.js +185 -0
- package/dist/utils/command.js +67 -0
- package/dist/utils/community-host-runtime.js +376 -0
- package/dist/utils/config.js +1015 -0
- package/dist/utils/discussion-workspace.js +552 -0
- package/dist/utils/experience-workspace.js +326 -0
- package/dist/utils/guide-paths.js +67 -0
- package/dist/utils/hosted-sugar.js +56 -0
- package/dist/utils/hosted-workspace.js +229 -0
- package/dist/utils/memory-workspace.js +537 -0
- package/dist/utils/operator-runtime.js +199 -0
- package/dist/utils/password-crypto.js +39 -0
- package/dist/utils/playbook-workspace.js +479 -0
- package/dist/utils/project-context.js +255 -0
- package/dist/utils/prompts.js +70 -0
- package/dist/utils/refresh-race.js +28 -0
- package/dist/utils/repo-config.js +109 -0
- package/dist/utils/repo-first-projectman.js +194 -0
- package/dist/utils/repo-first-storage.js +13 -0
- package/dist/utils/repo-first-view.js +305 -0
- package/dist/utils/session-guidance.js +278 -0
- package/dist/utils/session-state.js +137 -0
- package/dist/utils/table.js +39 -0
- package/dist/utils/transient-fs.js +49 -0
- package/dist/utils/workspace-root.js +1 -0
- package/launchers/aops-cockpit.ps1 +15 -0
- package/launchers/aops-cockpit.sh +16 -0
- package/launchers/aops-server.ps1 +15 -0
- package/launchers/aops-server.sh +16 -0
- package/native/tui/win32-x64/aops-tui.exe +0 -0
- package/package.json +81 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { applyCommunityStrictPgSchema, planCommunityStrictPgSchema, } from '@aopslabs/aops-pg-bootstrap';
|
|
2
|
+
import { lstatSync, readFileSync, realpathSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { asCommunityDiagnosticError, } from './community-diagnostic.js';
|
|
5
|
+
export const COMMUNITY_NATIVE_MIGRATION_POLICY_PATH = 'apps/aops-server/scripts/community-migration-policy-v1.json';
|
|
6
|
+
export const COMMUNITY_NATIVE_PACKAGE_MIGRATION_POLICY_PATH = 'scripts/community-migration-policy-package-v1.json';
|
|
7
|
+
const MAX_POLICY_BYTES = 2 * 1024 * 1024;
|
|
8
|
+
const INSTANCE_NAME = /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$/;
|
|
9
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
10
|
+
const PREFIXED_SHA256 = /^sha256:[a-f0-9]{64}$/;
|
|
11
|
+
const RAW_SHA256 = /^[a-f0-9]{64}$/;
|
|
12
|
+
function isRecord(value) {
|
|
13
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
function exactKeys(value, expected) {
|
|
16
|
+
const actual = Object.keys(value).sort();
|
|
17
|
+
const wanted = [...expected].sort();
|
|
18
|
+
return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
|
|
19
|
+
}
|
|
20
|
+
function isWithin(root, candidate) {
|
|
21
|
+
const relative = path.relative(path.resolve(root), path.resolve(candidate));
|
|
22
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
23
|
+
}
|
|
24
|
+
function throwIfAborted(signal) {
|
|
25
|
+
if (signal?.aborted)
|
|
26
|
+
throw new Error('community_operation_aborted');
|
|
27
|
+
}
|
|
28
|
+
export function readCommunityNativeMigrationPolicy(sourceRoot) {
|
|
29
|
+
const resolvedRoot = path.resolve(sourceRoot);
|
|
30
|
+
const rootStats = lstatSync(resolvedRoot);
|
|
31
|
+
if (!rootStats.isDirectory() || rootStats.isSymbolicLink()) {
|
|
32
|
+
throw new Error('community_native_migration_source_root_invalid');
|
|
33
|
+
}
|
|
34
|
+
const canonicalRoot = realpathSync.native(resolvedRoot);
|
|
35
|
+
if (path.relative(resolvedRoot, canonicalRoot) !== '' || path.relative(canonicalRoot, resolvedRoot) !== '') {
|
|
36
|
+
throw new Error('community_native_migration_source_root_alias_refused');
|
|
37
|
+
}
|
|
38
|
+
const manifest = (() => {
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(readFileSync(path.join(canonicalRoot, 'package.json'), 'utf8'));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
})();
|
|
46
|
+
const relativePolicyPath = manifest.name === '@aopslabs/aops-server'
|
|
47
|
+
? COMMUNITY_NATIVE_PACKAGE_MIGRATION_POLICY_PATH
|
|
48
|
+
: COMMUNITY_NATIVE_MIGRATION_POLICY_PATH;
|
|
49
|
+
const policyPath = path.resolve(canonicalRoot, ...relativePolicyPath.split('/'));
|
|
50
|
+
if (!isWithin(canonicalRoot, policyPath))
|
|
51
|
+
throw new Error('community_native_migration_policy_path_escape');
|
|
52
|
+
const stats = lstatSync(policyPath);
|
|
53
|
+
if (!stats.isFile() || stats.isSymbolicLink() || stats.size < 1 || stats.size > MAX_POLICY_BYTES) {
|
|
54
|
+
throw new Error('community_native_migration_policy_file_invalid');
|
|
55
|
+
}
|
|
56
|
+
const canonicalPolicyPath = realpathSync.native(policyPath);
|
|
57
|
+
if (!isWithin(canonicalRoot, canonicalPolicyPath) || path.relative(policyPath, canonicalPolicyPath) !== '') {
|
|
58
|
+
throw new Error('community_native_migration_policy_path_unsafe');
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse(readFileSync(canonicalPolicyPath, 'utf8'));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
throw new Error('community_native_migration_policy_json_invalid');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export async function planCommunityNativeMigration(params, dependencies = {}) {
|
|
68
|
+
if (!path.isAbsolute(params.sourceRoot) || !params.repoUrl) {
|
|
69
|
+
throw new Error('community_native_migration_planning_invocation_invalid');
|
|
70
|
+
}
|
|
71
|
+
throwIfAborted(params.signal);
|
|
72
|
+
let policy;
|
|
73
|
+
try {
|
|
74
|
+
policy = readCommunityNativeMigrationPolicy(params.sourceRoot);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw asCommunityDiagnosticError(error, {
|
|
78
|
+
code: 'community_native_migration_configuration_failed',
|
|
79
|
+
phase: 'configuration',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
let planning;
|
|
83
|
+
try {
|
|
84
|
+
planning = await (dependencies.planStrictPgSchema ?? planCommunityStrictPgSchema)({
|
|
85
|
+
repoUrl: params.repoUrl,
|
|
86
|
+
workspaceRoot: params.sourceRoot,
|
|
87
|
+
policy,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throw asCommunityDiagnosticError(error, {
|
|
92
|
+
code: 'community_native_migration_planning_failed',
|
|
93
|
+
phase: 'inspect-schema',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
throwIfAborted(params.signal);
|
|
97
|
+
return { planning, policy };
|
|
98
|
+
}
|
|
99
|
+
export function assertCommunityNativeMigrationReceiptV1(value) {
|
|
100
|
+
if (!isRecord(value) || !exactKeys(value, [
|
|
101
|
+
'schemaVersion', 'status', 'instanceName', 'installId', 'sourceFingerprint', 'completedAt',
|
|
102
|
+
'policyId', 'targetLineageId', 'resultLineageId', 'action', 'pendingMigrationCount',
|
|
103
|
+
'policySha256', 'bundleSha256', 'acceptedPlanSha256', 'sourceMigrationStateFingerprintSha256',
|
|
104
|
+
'resultSchemaFingerprintSha256', 'resultReceiptFingerprintSha256',
|
|
105
|
+
'resultMigrationStateFingerprintSha256', 'durableAcceptanceAction', 'durableAcceptanceAt',
|
|
106
|
+
'snapshotEvidenceKind', 'snapshotEvidenceSha256', 'latestAppliedPlanSha256',
|
|
107
|
+
'latestAppliedSourceMigrationStateFingerprintSha256',
|
|
108
|
+
'latestAppliedResultStateFingerprintSha256',
|
|
109
|
+
'latestAppliedEvidenceKind', 'latestAppliedEvidenceSha256', 'latestAppliedAt',
|
|
110
|
+
'recoveredAppliedPlanSha256', 'migrationLogCount',
|
|
111
|
+
])) {
|
|
112
|
+
throw new Error('community_native_migration_receipt_schema_invalid');
|
|
113
|
+
}
|
|
114
|
+
if (value.schemaVersion !== 1 || value.status !== 'community-native-migration-verified' ||
|
|
115
|
+
!INSTANCE_NAME.test(String(value.instanceName)) || !UUID.test(String(value.installId)) ||
|
|
116
|
+
!PREFIXED_SHA256.test(String(value.sourceFingerprint)) ||
|
|
117
|
+
Number.isNaN(Date.parse(String(value.completedAt))) ||
|
|
118
|
+
typeof value.policyId !== 'string' || value.policyId.length < 1 ||
|
|
119
|
+
typeof value.targetLineageId !== 'string' || value.targetLineageId.length < 1 ||
|
|
120
|
+
typeof value.resultLineageId !== 'string' || value.resultLineageId.length < 1 ||
|
|
121
|
+
(value.action !== 'migrate' && value.action !== 'verify-only') ||
|
|
122
|
+
(value.durableAcceptanceAction !== 'migrate' && value.durableAcceptanceAction !== 'verify-only') ||
|
|
123
|
+
Number.isNaN(Date.parse(String(value.durableAcceptanceAt))) ||
|
|
124
|
+
!['managed-verified-backup', 'external-snapshot-attestation', null]
|
|
125
|
+
.includes(value.snapshotEvidenceKind) ||
|
|
126
|
+
!['managed-verified-backup', 'external-snapshot-attestation', null]
|
|
127
|
+
.includes(value.latestAppliedEvidenceKind) ||
|
|
128
|
+
(value.latestAppliedAt !== null && Number.isNaN(Date.parse(String(value.latestAppliedAt)))) ||
|
|
129
|
+
!Number.isSafeInteger(value.pendingMigrationCount) || Number(value.pendingMigrationCount) < 0 ||
|
|
130
|
+
!Number.isSafeInteger(value.migrationLogCount) || Number(value.migrationLogCount) < 0 ||
|
|
131
|
+
![
|
|
132
|
+
value.policySha256,
|
|
133
|
+
value.bundleSha256,
|
|
134
|
+
value.acceptedPlanSha256,
|
|
135
|
+
value.sourceMigrationStateFingerprintSha256,
|
|
136
|
+
value.resultSchemaFingerprintSha256,
|
|
137
|
+
value.resultReceiptFingerprintSha256,
|
|
138
|
+
value.resultMigrationStateFingerprintSha256,
|
|
139
|
+
].every((digest) => RAW_SHA256.test(String(digest)))
|
|
140
|
+
|| ![value.snapshotEvidenceSha256, value.latestAppliedPlanSha256,
|
|
141
|
+
value.latestAppliedSourceMigrationStateFingerprintSha256,
|
|
142
|
+
value.latestAppliedResultStateFingerprintSha256,
|
|
143
|
+
value.latestAppliedEvidenceSha256, value.recoveredAppliedPlanSha256]
|
|
144
|
+
.every((digest) => digest === null || RAW_SHA256.test(String(digest)))
|
|
145
|
+
|| (value.snapshotEvidenceKind === null) !== (value.snapshotEvidenceSha256 === null)
|
|
146
|
+
|| (value.latestAppliedEvidenceKind === null) !== (value.latestAppliedEvidenceSha256 === null)
|
|
147
|
+
|| (value.latestAppliedPlanSha256 === null) !== (value.latestAppliedAt === null)
|
|
148
|
+
|| (value.latestAppliedPlanSha256 === null) !==
|
|
149
|
+
(value.latestAppliedSourceMigrationStateFingerprintSha256 === null)
|
|
150
|
+
|| (value.latestAppliedPlanSha256 === null) !==
|
|
151
|
+
(value.latestAppliedResultStateFingerprintSha256 === null)
|
|
152
|
+
|| value.action !== value.durableAcceptanceAction
|
|
153
|
+
|| (value.action === 'migrate' && value.latestAppliedPlanSha256 !== null &&
|
|
154
|
+
value.latestAppliedPlanSha256 !== value.acceptedPlanSha256)
|
|
155
|
+
|| (value.action === 'migrate' && value.latestAppliedPlanSha256 !== null && (value.latestAppliedSourceMigrationStateFingerprintSha256 !==
|
|
156
|
+
value.sourceMigrationStateFingerprintSha256 ||
|
|
157
|
+
value.latestAppliedResultStateFingerprintSha256 !==
|
|
158
|
+
value.resultMigrationStateFingerprintSha256 ||
|
|
159
|
+
value.latestAppliedEvidenceKind !== value.snapshotEvidenceKind ||
|
|
160
|
+
value.latestAppliedEvidenceSha256 !== value.snapshotEvidenceSha256 ||
|
|
161
|
+
value.latestAppliedAt !== value.durableAcceptanceAt))
|
|
162
|
+
|| (value.recoveredAppliedPlanSha256 !== null &&
|
|
163
|
+
value.recoveredAppliedPlanSha256 !== value.latestAppliedPlanSha256)) {
|
|
164
|
+
throw new Error('community_native_migration_receipt_schema_invalid');
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
function receiptFromResult(invocation, result, completedAt, migrationLogCount) {
|
|
169
|
+
let recoveredAppliedPlanSha256 = null;
|
|
170
|
+
const prior = invocation.priorIntentExpectation;
|
|
171
|
+
if (prior) {
|
|
172
|
+
const latest = result.latestAppliedAcceptance;
|
|
173
|
+
if (!latest || latest.acceptedPlanSha256 !== prior.acceptedPlanSha256 ||
|
|
174
|
+
latest.sourceFingerprintSha256 !== prior.sourceMigrationStateFingerprintSha256 ||
|
|
175
|
+
latest.evidenceKind !== prior.snapshotEvidenceKind ||
|
|
176
|
+
latest.evidenceSha256 !== prior.snapshotEvidenceSha256) {
|
|
177
|
+
throw new Error('community_native_migration_intent_not_reconciled');
|
|
178
|
+
}
|
|
179
|
+
recoveredAppliedPlanSha256 = prior.acceptedPlanSha256;
|
|
180
|
+
}
|
|
181
|
+
const latestAppliedAt = result.latestAppliedAcceptance?.acceptedAt ?? null;
|
|
182
|
+
return assertCommunityNativeMigrationReceiptV1({
|
|
183
|
+
schemaVersion: 1,
|
|
184
|
+
status: 'community-native-migration-verified',
|
|
185
|
+
instanceName: invocation.instanceName,
|
|
186
|
+
installId: invocation.installId,
|
|
187
|
+
sourceFingerprint: invocation.sourceFingerprint,
|
|
188
|
+
completedAt,
|
|
189
|
+
policyId: result.policyId,
|
|
190
|
+
targetLineageId: result.migrationPlan.target.lineageId,
|
|
191
|
+
resultLineageId: result.lineageId,
|
|
192
|
+
action: result.migrationPlan.action,
|
|
193
|
+
pendingMigrationCount: result.migrationPlan.pendingMigrations.length,
|
|
194
|
+
policySha256: result.migrationPlan.policySha256,
|
|
195
|
+
bundleSha256: result.migrationPlan.bundleSha256,
|
|
196
|
+
acceptedPlanSha256: result.acceptedPlanSha256,
|
|
197
|
+
sourceMigrationStateFingerprintSha256: result.sourceFingerprintSha256,
|
|
198
|
+
resultSchemaFingerprintSha256: result.schemaFingerprintSha256,
|
|
199
|
+
resultReceiptFingerprintSha256: result.receiptFingerprintSha256,
|
|
200
|
+
resultMigrationStateFingerprintSha256: result.stateFingerprintSha256,
|
|
201
|
+
durableAcceptanceAction: result.durableAcceptance.action,
|
|
202
|
+
durableAcceptanceAt: latestAppliedAt ?? result.durableAcceptance.acceptedAt,
|
|
203
|
+
snapshotEvidenceKind: result.durableAcceptance.evidenceKind,
|
|
204
|
+
snapshotEvidenceSha256: result.durableAcceptance.evidenceSha256,
|
|
205
|
+
latestAppliedPlanSha256: result.latestAppliedPlanSha256,
|
|
206
|
+
latestAppliedSourceMigrationStateFingerprintSha256: result.latestAppliedAcceptance?.sourceFingerprintSha256 ?? null,
|
|
207
|
+
latestAppliedResultStateFingerprintSha256: result.latestAppliedAcceptance?.resultStateFingerprintSha256 ?? null,
|
|
208
|
+
latestAppliedEvidenceKind: result.latestAppliedAcceptance?.evidenceKind ?? null,
|
|
209
|
+
latestAppliedEvidenceSha256: result.latestAppliedAcceptance?.evidenceSha256 ?? null,
|
|
210
|
+
latestAppliedAt,
|
|
211
|
+
recoveredAppliedPlanSha256,
|
|
212
|
+
migrationLogCount,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
export async function runCommunityNativeMigration(invocation, dependencies = {}) {
|
|
216
|
+
const prior = invocation.priorIntentExpectation;
|
|
217
|
+
if (!path.isAbsolute(invocation.sourceRoot) || !invocation.repoUrl ||
|
|
218
|
+
!INSTANCE_NAME.test(invocation.instanceName) || !UUID.test(invocation.installId) ||
|
|
219
|
+
!PREFIXED_SHA256.test(invocation.sourceFingerprint) ||
|
|
220
|
+
(prior !== undefined && prior !== null && (!RAW_SHA256.test(prior.acceptedPlanSha256) ||
|
|
221
|
+
!RAW_SHA256.test(prior.sourceMigrationStateFingerprintSha256) ||
|
|
222
|
+
!['managed-verified-backup', 'external-snapshot-attestation', null]
|
|
223
|
+
.includes(prior.snapshotEvidenceKind) ||
|
|
224
|
+
(prior.snapshotEvidenceSha256 !== null && !RAW_SHA256.test(prior.snapshotEvidenceSha256)) ||
|
|
225
|
+
(prior.snapshotEvidenceKind === null) !== (prior.snapshotEvidenceSha256 === null))) ||
|
|
226
|
+
(invocation.requiredPlanSha256 !== undefined && !RAW_SHA256.test(invocation.requiredPlanSha256)) ||
|
|
227
|
+
(invocation.requiredAction !== undefined && invocation.requiredAction !== 'verify-only')) {
|
|
228
|
+
throw new Error('community_native_migration_invocation_invalid');
|
|
229
|
+
}
|
|
230
|
+
throwIfAborted(invocation.signal);
|
|
231
|
+
let policy;
|
|
232
|
+
try {
|
|
233
|
+
policy = readCommunityNativeMigrationPolicy(invocation.sourceRoot);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
throw asCommunityDiagnosticError(error, {
|
|
237
|
+
code: 'community_native_migration_configuration_failed',
|
|
238
|
+
phase: 'configuration',
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
const logs = [];
|
|
242
|
+
let planning;
|
|
243
|
+
let evidence = null;
|
|
244
|
+
if (invocation.snapshotEvidenceProvider || invocation.requiredPlanSha256 || invocation.requiredAction) {
|
|
245
|
+
try {
|
|
246
|
+
planning = await (dependencies.planStrictPgSchema ?? planCommunityStrictPgSchema)({
|
|
247
|
+
repoUrl: invocation.repoUrl,
|
|
248
|
+
workspaceRoot: invocation.sourceRoot,
|
|
249
|
+
policy,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
throw asCommunityDiagnosticError(error, {
|
|
254
|
+
code: 'community_native_migration_planning_failed',
|
|
255
|
+
phase: 'inspect-schema',
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
throwIfAborted(invocation.signal);
|
|
259
|
+
if (invocation.requiredPlanSha256 !== undefined &&
|
|
260
|
+
planning.acceptedPlanSha256 !== invocation.requiredPlanSha256) {
|
|
261
|
+
throw new Error(`community_native_required_migration_plan_mismatch:expected=${invocation.requiredPlanSha256}:actual=${planning.acceptedPlanSha256}`);
|
|
262
|
+
}
|
|
263
|
+
if (invocation.requiredAction !== undefined && planning.migrationPlan.action !== invocation.requiredAction) {
|
|
264
|
+
throw new Error(`community_native_required_migration_action_mismatch:${planning.migrationPlan.action}`);
|
|
265
|
+
}
|
|
266
|
+
if (invocation.snapshotEvidenceProvider) {
|
|
267
|
+
try {
|
|
268
|
+
evidence = await invocation.snapshotEvidenceProvider({
|
|
269
|
+
planning,
|
|
270
|
+
policy,
|
|
271
|
+
sourceRoot: invocation.sourceRoot,
|
|
272
|
+
repoUrl: invocation.repoUrl,
|
|
273
|
+
signal: invocation.signal,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
throw asCommunityDiagnosticError(error, {
|
|
278
|
+
code: 'community_native_migration_snapshot_failed',
|
|
279
|
+
phase: 'snapshot',
|
|
280
|
+
details: {
|
|
281
|
+
migrationAction: planning.migrationPlan.action,
|
|
282
|
+
pendingMigrationCount: planning.migrationPlan.pendingMigrations.length,
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
throwIfAborted(invocation.signal);
|
|
287
|
+
if (planning.requiresSnapshotEvidence && evidence === null) {
|
|
288
|
+
throw new Error('community_native_snapshot_evidence_required');
|
|
289
|
+
}
|
|
290
|
+
if (evidence && !path.isAbsolute(evidence.path)) {
|
|
291
|
+
throw new Error('community_native_snapshot_evidence_path_invalid');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
let result;
|
|
296
|
+
let migrationPhase = 'inspect-schema';
|
|
297
|
+
try {
|
|
298
|
+
result = await (dependencies.applyStrictPgSchema ?? applyCommunityStrictPgSchema)({
|
|
299
|
+
repoUrl: invocation.repoUrl,
|
|
300
|
+
workspaceRoot: invocation.sourceRoot,
|
|
301
|
+
policy,
|
|
302
|
+
expectedPlanSha256: planning?.acceptedPlanSha256,
|
|
303
|
+
snapshotEvidencePath: evidence?.path,
|
|
304
|
+
snapshotPolicy: evidence?.policy,
|
|
305
|
+
onPlanAccepted: async (context) => {
|
|
306
|
+
migrationPhase = context.migrationPlan.action === 'migrate' ? 'apply' : 'verify';
|
|
307
|
+
await invocation.onPlanAccepted?.(context);
|
|
308
|
+
},
|
|
309
|
+
logs,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
if (invocation.signal?.aborted)
|
|
314
|
+
throw new Error('community_operation_aborted');
|
|
315
|
+
throw asCommunityDiagnosticError(error, {
|
|
316
|
+
code: 'community_native_migration_failed',
|
|
317
|
+
phase: migrationPhase,
|
|
318
|
+
details: planning ? {
|
|
319
|
+
migrationAction: planning.migrationPlan.action,
|
|
320
|
+
pendingMigrationCount: planning.migrationPlan.pendingMigrations.length,
|
|
321
|
+
} : undefined,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
throwIfAborted(invocation.signal);
|
|
325
|
+
throwIfAborted(invocation.signal);
|
|
326
|
+
try {
|
|
327
|
+
return receiptFromResult(invocation, result, (dependencies.now ?? (() => new Date()))().toISOString(), logs.length);
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
throw asCommunityDiagnosticError(error, {
|
|
331
|
+
code: 'community_native_migration_result_failed',
|
|
332
|
+
phase: 'verify',
|
|
333
|
+
details: {
|
|
334
|
+
migrationAction: result.migrationPlan.action,
|
|
335
|
+
pendingMigrationCount: result.migrationPlan.pendingMigrations.length,
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|