@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,475 @@
|
|
|
1
|
+
import { lstatSync, readFileSync, realpathSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { CommercialArtifactError, RELEASE_MANIFEST_PURPOSE, managedInstallationLayoutBinding, readVerifiedActiveCommercialArtifact, reestablishCommercialIntegrityAuthority, resolveManagedInstallationLayout, verifyOfflineArtifactImportAuthorization, } from '@aopslabs/artifact-trust-contracts';
|
|
5
|
+
import { installCommercialArtifactBundle, readActiveCommercialArtifact, rollbackCommercialArtifact, } from '@aopslabs/artifact-trust-contracts';
|
|
6
|
+
import { parseLeaseTrustBundleFile } from './commercial-license.js';
|
|
7
|
+
import { setupInstallerReleaseBinding, verifySetupInstallerReleaseManifest, } from '../lib/setup-installer-release.js';
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
function exactKeys(value, expected, reason) {
|
|
12
|
+
const actual = Object.keys(value).sort();
|
|
13
|
+
if (JSON.stringify(actual) !== JSON.stringify([...expected].sort()))
|
|
14
|
+
throw new Error(reason);
|
|
15
|
+
}
|
|
16
|
+
function regularFile(filePath, reason) {
|
|
17
|
+
const absolute = path.resolve(process.cwd(), filePath);
|
|
18
|
+
const stat = lstatSync(absolute);
|
|
19
|
+
if (stat.isSymbolicLink() || !stat.isFile())
|
|
20
|
+
throw new Error(reason);
|
|
21
|
+
return realpathSync.native(absolute);
|
|
22
|
+
}
|
|
23
|
+
function jsonFile(filePath, reason) {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(readFileSync(regularFile(filePath, reason), 'utf8'));
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof Error && error.message === reason)
|
|
29
|
+
throw error;
|
|
30
|
+
throw new Error(reason);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function requiredOption(value, reason) {
|
|
34
|
+
const normalized = value?.trim();
|
|
35
|
+
if (!normalized)
|
|
36
|
+
throw new Error(reason);
|
|
37
|
+
return normalized;
|
|
38
|
+
}
|
|
39
|
+
function optionalEpoch(value) {
|
|
40
|
+
if (value === undefined)
|
|
41
|
+
return undefined;
|
|
42
|
+
const parsed = Number(value);
|
|
43
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
44
|
+
throw new Error('minimum_revocation_epoch_invalid');
|
|
45
|
+
}
|
|
46
|
+
return parsed;
|
|
47
|
+
}
|
|
48
|
+
export function loadReleaseTrustBundleFile(filePath) {
|
|
49
|
+
const resolved = regularFile(filePath, 'release_trust_bundle_unsafe');
|
|
50
|
+
let value;
|
|
51
|
+
try {
|
|
52
|
+
value = JSON.parse(readFileSync(resolved, 'utf8'));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
throw new Error('release_trust_bundle_json_invalid');
|
|
56
|
+
}
|
|
57
|
+
if (!isRecord(value))
|
|
58
|
+
throw new Error('release_trust_bundle_schema_invalid');
|
|
59
|
+
exactKeys(value, ['schemaVersion', 'objectType', 'purpose', 'keys'], 'release_trust_bundle_schema_invalid');
|
|
60
|
+
if (value.schemaVersion !== 1 ||
|
|
61
|
+
value.objectType !== 'aops-release-trust-bundle-v1' ||
|
|
62
|
+
value.purpose !== RELEASE_MANIFEST_PURPOSE ||
|
|
63
|
+
!Array.isArray(value.keys) ||
|
|
64
|
+
value.keys.length === 0)
|
|
65
|
+
throw new Error('release_trust_bundle_schema_invalid');
|
|
66
|
+
const keys = value.keys.map((candidate) => {
|
|
67
|
+
if (!isRecord(candidate))
|
|
68
|
+
throw new Error('release_trust_key_invalid');
|
|
69
|
+
const actualKeys = Object.keys(candidate).sort();
|
|
70
|
+
const legacyKeys = ['alg', 'kid', 'publicKeyPem', 'purpose'];
|
|
71
|
+
const rotatingKeys = [
|
|
72
|
+
'alg', 'kid', 'notAfter', 'notBefore', 'publicKeyPem', 'purpose', 'status',
|
|
73
|
+
];
|
|
74
|
+
const rotating = actualKeys.length === rotatingKeys.length &&
|
|
75
|
+
actualKeys.every((key, index) => key === rotatingKeys[index]);
|
|
76
|
+
if (!rotating &&
|
|
77
|
+
(actualKeys.length !== legacyKeys.length ||
|
|
78
|
+
actualKeys.some((key, index) => key !== legacyKeys[index])))
|
|
79
|
+
throw new Error('release_trust_key_invalid');
|
|
80
|
+
if (typeof candidate.kid !== 'string' ||
|
|
81
|
+
!/^release\/[A-Za-z0-9._~-]{1,160}$/.test(candidate.kid) ||
|
|
82
|
+
candidate.purpose !== RELEASE_MANIFEST_PURPOSE ||
|
|
83
|
+
candidate.alg !== 'EdDSA' ||
|
|
84
|
+
typeof candidate.publicKeyPem !== 'string' ||
|
|
85
|
+
!candidate.publicKeyPem.startsWith('-----BEGIN PUBLIC KEY-----') ||
|
|
86
|
+
(rotating &&
|
|
87
|
+
!['active', 'verify-only', 'retired', 'revoked'].includes(String(candidate.status))) ||
|
|
88
|
+
(rotating &&
|
|
89
|
+
candidate.notBefore !== null &&
|
|
90
|
+
typeof candidate.notBefore !== 'string') ||
|
|
91
|
+
(rotating &&
|
|
92
|
+
candidate.notAfter !== null &&
|
|
93
|
+
typeof candidate.notAfter !== 'string'))
|
|
94
|
+
throw new Error('release_trust_key_invalid');
|
|
95
|
+
if (candidate.kid.toLowerCase().includes('test-ephemeral')) {
|
|
96
|
+
throw new Error('release_trust_test_key_refused');
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
kid: candidate.kid,
|
|
100
|
+
purpose: RELEASE_MANIFEST_PURPOSE,
|
|
101
|
+
alg: 'EdDSA',
|
|
102
|
+
publicKeyPem: candidate.publicKeyPem,
|
|
103
|
+
...(rotating ? {
|
|
104
|
+
status: candidate.status,
|
|
105
|
+
...(candidate.notBefore === null
|
|
106
|
+
? {}
|
|
107
|
+
: { notBefore: candidate.notBefore }),
|
|
108
|
+
...(candidate.notAfter === null
|
|
109
|
+
? {}
|
|
110
|
+
: { notAfter: candidate.notAfter }),
|
|
111
|
+
} : {}),
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
if (new Set(keys.map((key) => key.kid)).size !== keys.length) {
|
|
115
|
+
throw new Error('release_trust_key_duplicate');
|
|
116
|
+
}
|
|
117
|
+
return { filePath: resolved, keys: Object.freeze(keys) };
|
|
118
|
+
}
|
|
119
|
+
function storeRoot(options) {
|
|
120
|
+
const configured = options.storeRoot?.trim() || process.env.AOPS_COMMERCIAL_ARTIFACT_STORE?.trim();
|
|
121
|
+
return path.resolve(configured || resolveManagedInstallationLayout().storeRoot);
|
|
122
|
+
}
|
|
123
|
+
function managedIntegrityStateRoot(selectedStoreRoot, layout = resolveManagedInstallationLayout()) {
|
|
124
|
+
return path.resolve(selectedStoreRoot) === path.resolve(layout.storeRoot)
|
|
125
|
+
? layout.stateRoot
|
|
126
|
+
: undefined;
|
|
127
|
+
}
|
|
128
|
+
function commercialIntegrityStatus(managed, active, metrics) {
|
|
129
|
+
if (!active) {
|
|
130
|
+
return Object.freeze({
|
|
131
|
+
verificationMode: managed ? 'routine' : 'full',
|
|
132
|
+
scheduledVerification: managed
|
|
133
|
+
? 'listener-readiness-worker-24h'
|
|
134
|
+
: 'not-applicable-custom-store',
|
|
135
|
+
authorityDecision: null,
|
|
136
|
+
fastPathEnabled: false,
|
|
137
|
+
fullVerificationPerformed: false,
|
|
138
|
+
customerVisibleRoutineStartupBudgetMs: 15000,
|
|
139
|
+
startupBudgetEvidenceClass: 'cold-process-real-time-antivirus-enabled-supported-machine',
|
|
140
|
+
reason: 'commercial_artifact_inactive',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (!managed) {
|
|
144
|
+
return Object.freeze({
|
|
145
|
+
verificationMode: 'full',
|
|
146
|
+
scheduledVerification: 'not-applicable-custom-store',
|
|
147
|
+
authorityDecision: null,
|
|
148
|
+
fastPathEnabled: false,
|
|
149
|
+
fullVerificationPerformed: true,
|
|
150
|
+
customerVisibleRoutineStartupBudgetMs: 15000,
|
|
151
|
+
startupBudgetEvidenceClass: 'cold-process-real-time-antivirus-enabled-supported-machine',
|
|
152
|
+
reason: 'commercial_integrity_custom_store_full_verification',
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const authorityDecision = metrics?.authorityDecision ?? null;
|
|
156
|
+
const reasons = {
|
|
157
|
+
verified: 'commercial_integrity_fast_path_verified',
|
|
158
|
+
'full-fallback-authority-unavailable': 'commercial_integrity_authority_unavailable_full_verification',
|
|
159
|
+
'full-fallback-authority-behind': 'commercial_integrity_authority_behind_full_verification',
|
|
160
|
+
'full-fallback-size-drift': 'commercial_integrity_size_drift_full_verification',
|
|
161
|
+
'full-heal-forward': 'commercial_integrity_pending_healed_by_full_verification',
|
|
162
|
+
};
|
|
163
|
+
return Object.freeze({
|
|
164
|
+
verificationMode: 'routine',
|
|
165
|
+
scheduledVerification: 'listener-readiness-worker-24h',
|
|
166
|
+
authorityDecision,
|
|
167
|
+
fastPathEnabled: authorityDecision === 'verified',
|
|
168
|
+
fullVerificationPerformed: metrics?.fullVerificationPerformed ?? true,
|
|
169
|
+
customerVisibleRoutineStartupBudgetMs: 15000,
|
|
170
|
+
startupBudgetEvidenceClass: 'cold-process-real-time-antivirus-enabled-supported-machine',
|
|
171
|
+
reason: authorityDecision === null
|
|
172
|
+
? 'commercial_integrity_diagnostics_unavailable'
|
|
173
|
+
: reasons[authorityDecision],
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function print(value) {
|
|
177
|
+
console.log(JSON.stringify(value, null, 2));
|
|
178
|
+
}
|
|
179
|
+
function handleError(error) {
|
|
180
|
+
if (error instanceof CommercialArtifactError) {
|
|
181
|
+
print({
|
|
182
|
+
ok: false,
|
|
183
|
+
stage: error.stage,
|
|
184
|
+
decision: error.decision,
|
|
185
|
+
reason: error.reason,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
print({
|
|
190
|
+
ok: false,
|
|
191
|
+
stage: 'command-input',
|
|
192
|
+
decision: 'deny',
|
|
193
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
process.exitCode = 1;
|
|
197
|
+
}
|
|
198
|
+
export function runCommercialArtifactInstall(options) {
|
|
199
|
+
try {
|
|
200
|
+
const bundleRoot = realpathSync.native(path.resolve(process.cwd(), options.from));
|
|
201
|
+
const trust = loadReleaseTrustBundleFile(options.trustBundle);
|
|
202
|
+
const trustRelative = path.relative(bundleRoot, trust.filePath);
|
|
203
|
+
if (!trustRelative.startsWith('..') && !path.isAbsolute(trustRelative)) {
|
|
204
|
+
throw new Error('release_trust_bundle_must_be_host_pinned_outside_artifact_bundle');
|
|
205
|
+
}
|
|
206
|
+
const managedLayout = options.bootstrapJson
|
|
207
|
+
? (options.managedLayout ?? resolveManagedInstallationLayout())
|
|
208
|
+
: undefined;
|
|
209
|
+
const selectedStoreRoot = storeRoot(options);
|
|
210
|
+
if (managedLayout &&
|
|
211
|
+
path.resolve(selectedStoreRoot) !== path.resolve(managedLayout.storeRoot))
|
|
212
|
+
throw new Error('customer_managed_store_root_override_refused');
|
|
213
|
+
let offlineAuthorization;
|
|
214
|
+
let installerRelease;
|
|
215
|
+
if (options.bootstrapJson) {
|
|
216
|
+
const challengeFile = requiredOption(options.activationChallengeFile, 'offline_activation_challenge_file_required');
|
|
217
|
+
const leaseTrustFile = requiredOption(options.leaseTrustBundle, 'lease_trust_bundle_required');
|
|
218
|
+
const leaseTrust = regularFile(leaseTrustFile, 'lease_trust_bundle_invalid');
|
|
219
|
+
const leaseTrustRelative = path.relative(bundleRoot, leaseTrust);
|
|
220
|
+
if (!leaseTrustRelative.startsWith('..') && !path.isAbsolute(leaseTrustRelative)) {
|
|
221
|
+
throw new Error('lease_trust_bundle_must_be_host_pinned_outside_artifact_bundle');
|
|
222
|
+
}
|
|
223
|
+
const envelope = jsonFile(path.join(bundleRoot, 'release-manifest.json'), 'release_manifest_invalid');
|
|
224
|
+
const activationResponse = jsonFile(path.join(bundleRoot, 'offline-activation-response.json'), 'offline_activation_response_invalid');
|
|
225
|
+
const activationChallengeToken = readFileSync(regularFile(challengeFile, 'offline_activation_challenge_file_invalid'), 'utf8').trim();
|
|
226
|
+
const hostProtocolVersion = options.hostProtocolVersion;
|
|
227
|
+
const minimumRevocationEpoch = optionalEpoch(options.minimumRevocationEpoch);
|
|
228
|
+
offlineAuthorization = verifyOfflineArtifactImportAuthorization({
|
|
229
|
+
manifestEnvelope: envelope,
|
|
230
|
+
releaseTrustKeys: trust.keys,
|
|
231
|
+
hostProtocolVersion,
|
|
232
|
+
activationResponse,
|
|
233
|
+
activationChallengeToken,
|
|
234
|
+
leaseTrustKeys: parseLeaseTrustBundleFile(leaseTrust),
|
|
235
|
+
leaseIssuer: requiredOption(options.leaseIssuer, 'lease_issuer_required'),
|
|
236
|
+
expected: {
|
|
237
|
+
tenantId: requiredOption(options.tenantId, 'tenant_id_required'),
|
|
238
|
+
installationId: options.installationId,
|
|
239
|
+
hostInstanceId: options.hostInstanceId,
|
|
240
|
+
productId: requiredOption(options.productId, 'product_id_required'),
|
|
241
|
+
...(minimumRevocationEpoch === undefined
|
|
242
|
+
? {}
|
|
243
|
+
: { minimumRevocationEpoch }),
|
|
244
|
+
},
|
|
245
|
+
now: options.now,
|
|
246
|
+
});
|
|
247
|
+
installerRelease = verifySetupInstallerReleaseManifest(envelope, {
|
|
248
|
+
trustKeys: trust.keys,
|
|
249
|
+
hostProtocolVersion,
|
|
250
|
+
now: options.now,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const receipt = installCommercialArtifactBundle({
|
|
254
|
+
storeRoot: selectedStoreRoot,
|
|
255
|
+
bundleRoot,
|
|
256
|
+
installationId: options.installationId,
|
|
257
|
+
hostInstanceId: options.hostInstanceId,
|
|
258
|
+
hostProtocolVersion: options.hostProtocolVersion,
|
|
259
|
+
trustKeys: trust.keys,
|
|
260
|
+
now: options.now,
|
|
261
|
+
customerMode: options.bootstrapJson === true,
|
|
262
|
+
...(offlineAuthorization === undefined ? {} : { offlineAuthorization }),
|
|
263
|
+
requireRetainedRevocationEpoch: options.recovery === true,
|
|
264
|
+
...(managedLayout === undefined ? {} : { managedLayout }),
|
|
265
|
+
});
|
|
266
|
+
if (options.bootstrapJson) {
|
|
267
|
+
if (!installerRelease)
|
|
268
|
+
throw new Error('installer_release_binding_required');
|
|
269
|
+
if (!managedLayout)
|
|
270
|
+
throw new Error('managed_installation_layout_required');
|
|
271
|
+
print({
|
|
272
|
+
schemaVersion: 1,
|
|
273
|
+
action: 'commercial-artifact.offline-install',
|
|
274
|
+
mode: 'offline',
|
|
275
|
+
ok: true,
|
|
276
|
+
decision: 'activated',
|
|
277
|
+
installationId: receipt.installationId,
|
|
278
|
+
hostInstanceId: receipt.hostInstanceId,
|
|
279
|
+
layout: managedInstallationLayoutBinding(managedLayout),
|
|
280
|
+
release: setupInstallerReleaseBinding(installerRelease),
|
|
281
|
+
artifact: {
|
|
282
|
+
packageName: receipt.packageName,
|
|
283
|
+
version: receipt.version,
|
|
284
|
+
manifestDigest: receipt.manifestDigest,
|
|
285
|
+
closureDigest: receipt.closureDigest,
|
|
286
|
+
activationGeneration: receipt.activation.generation,
|
|
287
|
+
},
|
|
288
|
+
verification: {
|
|
289
|
+
manifestSignature: receipt.verification.manifestSignatureDecision,
|
|
290
|
+
closureReadback: receipt.verification.closureReadbackDecision,
|
|
291
|
+
hostAbi: receipt.hostAbiReadback.decision,
|
|
292
|
+
antiDowngrade: 'enforced',
|
|
293
|
+
entitlement: 'verified',
|
|
294
|
+
revocationEpoch: 'retained',
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
print({
|
|
300
|
+
ok: true,
|
|
301
|
+
action: 'commercial-artifact.install',
|
|
302
|
+
decision: 'activated',
|
|
303
|
+
storeRoot: selectedStoreRoot,
|
|
304
|
+
receipt,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
handleError(error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
export function runCommercialArtifactStatus(options) {
|
|
312
|
+
try {
|
|
313
|
+
const selectedStoreRoot = storeRoot(options);
|
|
314
|
+
const integrityStateRoot = managedIntegrityStateRoot(selectedStoreRoot, options.managedLayout);
|
|
315
|
+
let routineVerification;
|
|
316
|
+
const receipt = readActiveCommercialArtifact({
|
|
317
|
+
storeRoot: selectedStoreRoot,
|
|
318
|
+
integrityStateRoot,
|
|
319
|
+
verificationMode: integrityStateRoot ? 'routine' : 'full',
|
|
320
|
+
onRoutineVerified: (metrics) => { routineVerification = metrics; },
|
|
321
|
+
});
|
|
322
|
+
print({
|
|
323
|
+
ok: true,
|
|
324
|
+
action: 'commercial-artifact.status',
|
|
325
|
+
storeRoot: selectedStoreRoot,
|
|
326
|
+
active: receipt,
|
|
327
|
+
integrity: commercialIntegrityStatus(integrityStateRoot !== undefined, receipt !== null, routineVerification),
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
handleError(error);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
export function runCommercialArtifactVerify(options) {
|
|
335
|
+
try {
|
|
336
|
+
const selectedStoreRoot = storeRoot(options);
|
|
337
|
+
const integrityStateRoot = managedIntegrityStateRoot(selectedStoreRoot, options.managedLayout);
|
|
338
|
+
if (!integrityStateRoot)
|
|
339
|
+
throw new Error('commercial_integrity_verify_requires_managed_store');
|
|
340
|
+
const trust = loadReleaseTrustBundleFile(options.trustBundle);
|
|
341
|
+
const active = readVerifiedActiveCommercialArtifact({
|
|
342
|
+
storeRoot: selectedStoreRoot,
|
|
343
|
+
integrityStateRoot,
|
|
344
|
+
verificationMode: 'scheduled',
|
|
345
|
+
trustKeys: trust.keys,
|
|
346
|
+
expectedIdentity: {
|
|
347
|
+
installationId: options.installationId,
|
|
348
|
+
hostInstanceId: options.hostInstanceId,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
if (!active)
|
|
352
|
+
throw new Error('commercial_artifact_not_active');
|
|
353
|
+
print({
|
|
354
|
+
ok: true,
|
|
355
|
+
action: 'commercial-artifact.verify-full',
|
|
356
|
+
decision: 'verified',
|
|
357
|
+
receiptId: active.receipt.receiptId,
|
|
358
|
+
closureDigest: active.receipt.closureDigest,
|
|
359
|
+
activationGeneration: active.receipt.activation.generation,
|
|
360
|
+
nextScheduledVerificationAfterHours: 24,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
handleError(error);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
export function runCommercialArtifactReestablishAuthority(options) {
|
|
368
|
+
try {
|
|
369
|
+
if (options.confirmAuthorityReestablish !== 'REESTABLISH-INTEGRITY-AUTHORITY') {
|
|
370
|
+
throw new Error('commercial_integrity_authority_reestablish_confirmation_required');
|
|
371
|
+
}
|
|
372
|
+
const selectedStoreRoot = storeRoot(options);
|
|
373
|
+
const integrityStateRoot = managedIntegrityStateRoot(selectedStoreRoot, options.managedLayout);
|
|
374
|
+
if (!integrityStateRoot) {
|
|
375
|
+
throw new Error('commercial_integrity_authority_reestablish_requires_managed_store');
|
|
376
|
+
}
|
|
377
|
+
const trust = loadReleaseTrustBundleFile(options.trustBundle);
|
|
378
|
+
const result = reestablishCommercialIntegrityAuthority({
|
|
379
|
+
storeRoot: selectedStoreRoot,
|
|
380
|
+
integrityStateRoot,
|
|
381
|
+
trustKeys: trust.keys,
|
|
382
|
+
expectedIdentity: {
|
|
383
|
+
installationId: options.installationId,
|
|
384
|
+
hostInstanceId: options.hostInstanceId,
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
print({
|
|
388
|
+
ok: true,
|
|
389
|
+
action: 'commercial-artifact.reestablish-integrity-authority',
|
|
390
|
+
decision: 'authority-reestablished-restart-required',
|
|
391
|
+
receiptId: result.authority.receiptId,
|
|
392
|
+
closureDigest: result.authority.closureDigest,
|
|
393
|
+
activationGeneration: result.authority.activationGeneration,
|
|
394
|
+
authorityReestablished: result.authority.authorityReestablished,
|
|
395
|
+
previousAnchorUnknown: result.authority.previousAnchorUnknown,
|
|
396
|
+
evidencePath: result.evidencePath,
|
|
397
|
+
nextAction: 'restart_aops_server_and_confirm_commercial_integrity_readback',
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
handleError(error);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
export function runCommercialArtifactRollback(options) {
|
|
405
|
+
try {
|
|
406
|
+
const trust = loadReleaseTrustBundleFile(options.trustBundle);
|
|
407
|
+
const selectedStoreRoot = storeRoot(options);
|
|
408
|
+
const receipt = rollbackCommercialArtifact({
|
|
409
|
+
storeRoot: selectedStoreRoot,
|
|
410
|
+
integrityStateRoot: managedIntegrityStateRoot(selectedStoreRoot, options.managedLayout),
|
|
411
|
+
trustKeys: trust.keys,
|
|
412
|
+
});
|
|
413
|
+
print({
|
|
414
|
+
ok: true,
|
|
415
|
+
action: 'commercial-artifact.rollback',
|
|
416
|
+
decision: 'activated-previous',
|
|
417
|
+
storeRoot: selectedStoreRoot,
|
|
418
|
+
receipt,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
handleError(error);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function withStoreRoot(command) {
|
|
426
|
+
return command
|
|
427
|
+
.option('--store-root <path>', 'Operator-mode artifact store override; customer bootstrap uses the canonical managed per-user root')
|
|
428
|
+
.option('--json', 'Print JSON output');
|
|
429
|
+
}
|
|
430
|
+
export function makeCommercialArtifactCommand() {
|
|
431
|
+
const command = new Command('commercial-artifact')
|
|
432
|
+
.description('Verify, install, inspect, and roll back signed private artifact closures');
|
|
433
|
+
withStoreRoot(command
|
|
434
|
+
.command('install')
|
|
435
|
+
.description('Verify a signed release bundle into CAS and atomically activate its receipt')
|
|
436
|
+
.requiredOption('--from <path>', 'Bundle directory containing release-manifest.json and objects/sha256')
|
|
437
|
+
.requiredOption('--trust-bundle <path>', 'Host-pinned release trust bundle outside the artifact bundle')
|
|
438
|
+
.requiredOption('--installation-id <id>', 'License-bound installation identity')
|
|
439
|
+
.requiredOption('--host-instance-id <id>', 'Host instance identity')
|
|
440
|
+
.option('--host-protocol-version <version>', 'Host commercial artifact ABI protocol', '1')
|
|
441
|
+
.option('--activation-challenge-file <path>', 'Customer offline mode: installation-signed challenge token file')
|
|
442
|
+
.option('--lease-trust-bundle <path>', 'Customer offline mode: host-pinned South lease trust bundle')
|
|
443
|
+
.option('--lease-issuer <issuer>', 'Customer offline mode: expected South lease issuer')
|
|
444
|
+
.option('--tenant-id <id>', 'Customer offline mode: expected tenant identity')
|
|
445
|
+
.option('--product-id <id>', 'Customer offline mode: expected licensed product identity')
|
|
446
|
+
.option('--minimum-revocation-epoch <epoch>', 'Customer offline mode: optional external epoch floor')
|
|
447
|
+
.option('--recovery', 'Require an existing retained revocation epoch before repair')
|
|
448
|
+
.option('--bootstrap-json', 'Print the strict secret-free native bootstrap receipt')
|
|
449
|
+
.action((options) => runCommercialArtifactInstall(options)));
|
|
450
|
+
withStoreRoot(command
|
|
451
|
+
.command('status')
|
|
452
|
+
.description('Verify and print the active host-owned installation receipt')
|
|
453
|
+
.action((options) => runCommercialArtifactStatus(options)));
|
|
454
|
+
withStoreRoot(command
|
|
455
|
+
.command('verify-full')
|
|
456
|
+
.description('Run an explicit full closure verification and refresh scheduled integrity authority')
|
|
457
|
+
.requiredOption('--trust-bundle <path>', 'Host-pinned release trust bundle')
|
|
458
|
+
.requiredOption('--installation-id <id>', 'Expected installation identity')
|
|
459
|
+
.requiredOption('--host-instance-id <id>', 'Expected host instance identity')
|
|
460
|
+
.action((options) => runCommercialArtifactVerify(options)));
|
|
461
|
+
withStoreRoot(command
|
|
462
|
+
.command('reestablish-integrity-authority')
|
|
463
|
+
.description('Guarded full verification that creates a new local integrity anchor after authority loss')
|
|
464
|
+
.requiredOption('--trust-bundle <path>', 'Host-pinned release trust bundle')
|
|
465
|
+
.requiredOption('--installation-id <id>', 'Expected installation identity')
|
|
466
|
+
.requiredOption('--host-instance-id <id>', 'Expected host instance identity')
|
|
467
|
+
.requiredOption('--confirm-authority-reestablish <phrase>', 'Must equal REESTABLISH-INTEGRITY-AUTHORITY; the prior local anchor becomes explicitly unknown')
|
|
468
|
+
.action((options) => runCommercialArtifactReestablishAuthority(options)));
|
|
469
|
+
withStoreRoot(command
|
|
470
|
+
.command('rollback')
|
|
471
|
+
.description('Re-verify the previous manifest and CAS closure before activation')
|
|
472
|
+
.requiredOption('--trust-bundle <path>', 'Host-pinned release trust bundle')
|
|
473
|
+
.action((options) => runCommercialArtifactRollback(options)));
|
|
474
|
+
return command;
|
|
475
|
+
}
|