@knowzai/cli 0.4.0 → 0.5.1
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/README.md +68 -0
- package/assets/portable/releases.json +66 -2
- package/assets/portable/runtime-contract.json +2 -2
- package/assets/selfhosted/docker-compose.yml +8 -2
- package/assets/selfhosted/releases.json +130 -5
- package/bin/run.js +7 -2
- package/bin/wasm-runtime.js +27 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/base-command.d.ts +2 -0
- package/dist/base-command.d.ts.map +1 -1
- package/dist/base-command.js +11 -1
- package/dist/base-command.js.map +1 -1
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +2 -0
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/backup.d.ts +1 -0
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +29 -10
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/chat.d.ts +2 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +10 -4
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/down.d.ts +14 -27
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +6 -31
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/knowledge/amend.d.ts +2 -2
- package/dist/commands/knowledge/amend.d.ts.map +1 -1
- package/dist/commands/knowledge/amend.js +5 -0
- package/dist/commands/knowledge/amend.js.map +1 -1
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +21 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/menu.js +1 -1
- package/dist/commands/menu.js.map +1 -1
- package/dist/commands/platform/destroy.d.ts +15 -5
- package/dist/commands/platform/destroy.d.ts.map +1 -1
- package/dist/commands/platform/destroy.js +6 -33
- package/dist/commands/platform/destroy.js.map +1 -1
- package/dist/commands/platform/doctor.d.ts +18 -3
- package/dist/commands/platform/doctor.d.ts.map +1 -1
- package/dist/commands/platform/doctor.js +4 -10
- package/dist/commands/platform/doctor.js.map +1 -1
- package/dist/commands/platform/down.d.ts +15 -15
- package/dist/commands/platform/down.d.ts.map +1 -1
- package/dist/commands/platform/down.js +4 -8
- package/dist/commands/platform/down.js.map +1 -1
- package/dist/commands/platform/logs.d.ts +15 -14
- package/dist/commands/platform/logs.d.ts.map +1 -1
- package/dist/commands/platform/logs.js +5 -16
- package/dist/commands/platform/logs.js.map +1 -1
- package/dist/commands/platform/reset.d.ts +16 -13
- package/dist/commands/platform/reset.d.ts.map +1 -1
- package/dist/commands/platform/reset.js +7 -36
- package/dist/commands/platform/reset.js.map +1 -1
- package/dist/commands/platform/setup.d.ts +1 -0
- package/dist/commands/platform/setup.d.ts.map +1 -1
- package/dist/commands/platform/setup.js +1 -1
- package/dist/commands/platform/setup.js.map +1 -1
- package/dist/commands/platform/status.d.ts +14 -16
- package/dist/commands/platform/status.d.ts.map +1 -1
- package/dist/commands/platform/status.js +4 -29
- package/dist/commands/platform/status.js.map +1 -1
- package/dist/commands/restore.d.ts +10 -1
- package/dist/commands/restore.d.ts.map +1 -1
- package/dist/commands/restore.js +56 -13
- package/dist/commands/restore.js.map +1 -1
- package/dist/commands/runtime/destroy.d.ts +29 -0
- package/dist/commands/runtime/destroy.d.ts.map +1 -0
- package/dist/commands/runtime/destroy.js +13 -0
- package/dist/commands/runtime/destroy.js.map +1 -0
- package/dist/commands/runtime/doctor.d.ts +27 -0
- package/dist/commands/runtime/doctor.d.ts.map +1 -0
- package/dist/commands/runtime/doctor.js +11 -0
- package/dist/commands/runtime/doctor.js.map +1 -0
- package/dist/commands/runtime/logs.d.ts +28 -0
- package/dist/commands/runtime/logs.d.ts.map +1 -0
- package/dist/commands/runtime/logs.js +12 -0
- package/dist/commands/runtime/logs.js.map +1 -0
- package/dist/commands/runtime/status.d.ts +27 -0
- package/dist/commands/runtime/status.d.ts.map +1 -0
- package/dist/commands/runtime/status.js +11 -0
- package/dist/commands/runtime/status.js.map +1 -0
- package/dist/commands/runtime/upgrade.d.ts +28 -0
- package/dist/commands/runtime/upgrade.d.ts.map +1 -0
- package/dist/commands/runtime/upgrade.js +12 -0
- package/dist/commands/runtime/upgrade.js.map +1 -0
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/transfer.js +1 -1
- package/dist/commands/transfer.js.map +1 -1
- package/dist/commands/up.d.ts +3 -11
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +48 -37
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/hooks/init/launch-menu.d.ts.map +1 -1
- package/dist/hooks/init/launch-menu.js +2 -0
- package/dist/hooks/init/launch-menu.js.map +1 -1
- package/dist/lib/anonymous-registry.d.ts +3 -0
- package/dist/lib/anonymous-registry.d.ts.map +1 -0
- package/dist/lib/anonymous-registry.js +25 -0
- package/dist/lib/anonymous-registry.js.map +1 -0
- package/dist/lib/async-process.d.ts +15 -0
- package/dist/lib/async-process.d.ts.map +1 -0
- package/dist/lib/async-process.js +145 -0
- package/dist/lib/async-process.js.map +1 -0
- package/dist/lib/backup-process.d.ts +4 -0
- package/dist/lib/backup-process.d.ts.map +1 -0
- package/dist/lib/backup-process.js +20 -0
- package/dist/lib/backup-process.js.map +1 -0
- package/dist/lib/brand.d.ts +25 -0
- package/dist/lib/brand.d.ts.map +1 -0
- package/dist/lib/brand.js +105 -0
- package/dist/lib/brand.js.map +1 -0
- package/dist/lib/chat.d.ts +1 -0
- package/dist/lib/chat.d.ts.map +1 -1
- package/dist/lib/chat.js +12 -3
- package/dist/lib/chat.js.map +1 -1
- package/dist/lib/compose-status.d.ts +14 -0
- package/dist/lib/compose-status.d.ts.map +1 -0
- package/dist/lib/compose-status.js +31 -0
- package/dist/lib/compose-status.js.map +1 -0
- package/dist/lib/container-engine.js +2 -2
- package/dist/lib/container-engine.js.map +1 -1
- package/dist/lib/local-engine-context.d.ts +16 -0
- package/dist/lib/local-engine-context.d.ts.map +1 -0
- package/dist/lib/local-engine-context.js +123 -0
- package/dist/lib/local-engine-context.js.map +1 -0
- package/dist/lib/local-mcp-server.d.ts.map +1 -1
- package/dist/lib/local-mcp-server.js +18 -2
- package/dist/lib/local-mcp-server.js.map +1 -1
- package/dist/lib/login-guided.d.ts.map +1 -1
- package/dist/lib/login-guided.js +2 -1
- package/dist/lib/login-guided.js.map +1 -1
- package/dist/lib/login.d.ts +3 -0
- package/dist/lib/login.d.ts.map +1 -1
- package/dist/lib/login.js +25 -5
- package/dist/lib/login.js.map +1 -1
- package/dist/lib/oci-registry-probe.d.ts +43 -0
- package/dist/lib/oci-registry-probe.d.ts.map +1 -0
- package/dist/lib/oci-registry-probe.js +110 -0
- package/dist/lib/oci-registry-probe.js.map +1 -0
- package/dist/lib/peer-command.d.ts.map +1 -1
- package/dist/lib/peer-command.js +3 -1
- package/dist/lib/peer-command.js.map +1 -1
- package/dist/lib/platform-acquisition.d.ts +27 -0
- package/dist/lib/platform-acquisition.d.ts.map +1 -0
- package/dist/lib/platform-acquisition.js +21 -0
- package/dist/lib/platform-acquisition.js.map +1 -0
- package/dist/lib/platform-backup.d.ts +1 -0
- package/dist/lib/platform-backup.d.ts.map +1 -1
- package/dist/lib/platform-backup.js +375 -157
- package/dist/lib/platform-backup.js.map +1 -1
- package/dist/lib/platform-command-shared.d.ts +2 -0
- package/dist/lib/platform-command-shared.d.ts.map +1 -1
- package/dist/lib/platform-command-shared.js +13 -5
- package/dist/lib/platform-command-shared.js.map +1 -1
- package/dist/lib/platform-edition.d.ts +3 -6
- package/dist/lib/platform-edition.d.ts.map +1 -1
- package/dist/lib/platform-edition.js +9 -17
- package/dist/lib/platform-edition.js.map +1 -1
- package/dist/lib/platform-frontdoor-runtime.d.ts.map +1 -1
- package/dist/lib/platform-frontdoor-runtime.js +42 -10
- package/dist/lib/platform-frontdoor-runtime.js.map +1 -1
- package/dist/lib/platform-frontdoor.d.ts +32 -5
- package/dist/lib/platform-frontdoor.d.ts.map +1 -1
- package/dist/lib/platform-frontdoor.js +249 -171
- package/dist/lib/platform-frontdoor.js.map +1 -1
- package/dist/lib/platform-image-admission.d.ts +16 -0
- package/dist/lib/platform-image-admission.d.ts.map +1 -0
- package/dist/lib/platform-image-admission.js +73 -0
- package/dist/lib/platform-image-admission.js.map +1 -0
- package/dist/lib/platform-image-source.d.ts.map +1 -1
- package/dist/lib/platform-image-source.js +2 -0
- package/dist/lib/platform-image-source.js.map +1 -1
- package/dist/lib/platform-lifecycle.d.ts +4 -0
- package/dist/lib/platform-lifecycle.d.ts.map +1 -1
- package/dist/lib/platform-lifecycle.js +42 -8
- package/dist/lib/platform-lifecycle.js.map +1 -1
- package/dist/lib/platform-onboarding.d.ts.map +1 -1
- package/dist/lib/platform-onboarding.js +1 -1
- package/dist/lib/platform-onboarding.js.map +1 -1
- package/dist/lib/platform-preflight.d.ts +6 -3
- package/dist/lib/platform-preflight.d.ts.map +1 -1
- package/dist/lib/platform-preflight.js +52 -19
- package/dist/lib/platform-preflight.js.map +1 -1
- package/dist/lib/platform-release-manifest.d.ts +6 -1
- package/dist/lib/platform-release-manifest.d.ts.map +1 -1
- package/dist/lib/platform-release-manifest.js +10 -0
- package/dist/lib/platform-release-manifest.js.map +1 -1
- package/dist/lib/platform-runtime.d.ts +5 -2
- package/dist/lib/platform-runtime.d.ts.map +1 -1
- package/dist/lib/platform-runtime.js +7 -40
- package/dist/lib/platform-runtime.js.map +1 -1
- package/dist/lib/portability-shared.d.ts +1 -1
- package/dist/lib/portability-shared.d.ts.map +1 -1
- package/dist/lib/portability-shared.js +6 -2
- package/dist/lib/portability-shared.js.map +1 -1
- package/dist/lib/portable-release-digests.d.ts +5 -0
- package/dist/lib/portable-release-digests.d.ts.map +1 -0
- package/dist/lib/portable-release-digests.js +53 -0
- package/dist/lib/portable-release-digests.js.map +1 -0
- package/dist/lib/release-pin-matrix.d.ts +29 -0
- package/dist/lib/release-pin-matrix.d.ts.map +1 -0
- package/dist/lib/release-pin-matrix.js +67 -0
- package/dist/lib/release-pin-matrix.js.map +1 -0
- package/dist/lib/repo-local-mcp-backend.d.ts +2 -5
- package/dist/lib/repo-local-mcp-backend.d.ts.map +1 -1
- package/dist/lib/repo-local-mcp-backend.js +61 -44
- package/dist/lib/repo-local-mcp-backend.js.map +1 -1
- package/dist/lib/runtime-backup-archive.d.ts +20 -0
- package/dist/lib/runtime-backup-archive.d.ts.map +1 -0
- package/dist/lib/runtime-backup-archive.js +269 -0
- package/dist/lib/runtime-backup-archive.js.map +1 -0
- package/dist/lib/runtime-command.d.ts +37 -0
- package/dist/lib/runtime-command.d.ts.map +1 -0
- package/dist/lib/runtime-command.js +50 -0
- package/dist/lib/runtime-command.js.map +1 -0
- package/dist/lib/runtime-discovery.d.ts +18 -0
- package/dist/lib/runtime-discovery.d.ts.map +1 -0
- package/dist/lib/runtime-discovery.js +56 -0
- package/dist/lib/runtime-discovery.js.map +1 -0
- package/dist/lib/runtime-lock.d.ts +3 -0
- package/dist/lib/runtime-lock.d.ts.map +1 -0
- package/dist/lib/runtime-lock.js +50 -0
- package/dist/lib/runtime-lock.js.map +1 -0
- package/dist/lib/runtime-operations.d.ts +98 -0
- package/dist/lib/runtime-operations.d.ts.map +1 -0
- package/dist/lib/runtime-operations.js +182 -0
- package/dist/lib/runtime-operations.js.map +1 -0
- package/dist/lib/runtime-provider.d.ts +17 -0
- package/dist/lib/runtime-provider.d.ts.map +1 -0
- package/dist/lib/runtime-provider.js +52 -0
- package/dist/lib/runtime-provider.js.map +1 -0
- package/dist/lib/runtime-status.d.ts +24 -0
- package/dist/lib/runtime-status.d.ts.map +1 -0
- package/dist/lib/runtime-status.js +128 -0
- package/dist/lib/runtime-status.js.map +1 -0
- package/dist/lib/selfhosted-backup.d.ts +37 -0
- package/dist/lib/selfhosted-backup.d.ts.map +1 -0
- package/dist/lib/selfhosted-backup.js +446 -0
- package/dist/lib/selfhosted-backup.js.map +1 -0
- package/dist/lib/selfhosted-keyring.d.ts +19 -0
- package/dist/lib/selfhosted-keyring.d.ts.map +1 -0
- package/dist/lib/selfhosted-keyring.js +193 -0
- package/dist/lib/selfhosted-keyring.js.map +1 -0
- package/dist/lib/selfhosted-lifecycle.d.ts +45 -7
- package/dist/lib/selfhosted-lifecycle.d.ts.map +1 -1
- package/dist/lib/selfhosted-lifecycle.js +214 -31
- package/dist/lib/selfhosted-lifecycle.js.map +1 -1
- package/dist/lib/selfhosted-login.d.ts +34 -0
- package/dist/lib/selfhosted-login.d.ts.map +1 -0
- package/dist/lib/selfhosted-login.js +116 -0
- package/dist/lib/selfhosted-login.js.map +1 -0
- package/dist/lib/selfhosted-readiness.d.ts +3 -0
- package/dist/lib/selfhosted-readiness.d.ts.map +1 -0
- package/dist/lib/selfhosted-readiness.js +24 -0
- package/dist/lib/selfhosted-readiness.js.map +1 -0
- package/dist/lib/setup-capabilities.d.ts +15 -0
- package/dist/lib/setup-capabilities.d.ts.map +1 -0
- package/dist/lib/setup-capabilities.js +21 -0
- package/dist/lib/setup-capabilities.js.map +1 -0
- package/dist/lib/setup-console.d.ts +8 -0
- package/dist/lib/setup-console.d.ts.map +1 -1
- package/dist/lib/setup-console.js +104 -74
- package/dist/lib/setup-console.js.map +1 -1
- package/dist/lib/setup-page.d.ts +12 -0
- package/dist/lib/setup-page.d.ts.map +1 -1
- package/dist/lib/setup-page.js +40 -22
- package/dist/lib/setup-page.js.map +1 -1
- package/dist/lib/setup-plan.d.ts +1 -0
- package/dist/lib/setup-plan.d.ts.map +1 -1
- package/dist/lib/setup-plan.js +3 -0
- package/dist/lib/setup-plan.js.map +1 -1
- package/dist/lib/setup-server.d.ts +11 -2
- package/dist/lib/setup-server.d.ts.map +1 -1
- package/dist/lib/setup-server.js +139 -28
- package/dist/lib/setup-server.js.map +1 -1
- package/dist/lib/ui.d.ts +3 -1
- package/dist/lib/ui.d.ts.map +1 -1
- package/dist/lib/ui.js +39 -7
- package/dist/lib/ui.js.map +1 -1
- package/dist/lib/up-result.d.ts +3 -0
- package/dist/lib/up-result.d.ts.map +1 -1
- package/dist/lib/up-result.js.map +1 -1
- package/dist/menu/run.js +1 -1
- package/dist/menu/run.js.map +1 -1
- package/dist/menu/should-launch.d.ts +0 -14
- package/dist/menu/should-launch.d.ts.map +1 -1
- package/dist/menu/should-launch.js +5 -1
- package/dist/menu/should-launch.js.map +1 -1
- package/oclif.manifest.json +5490 -3263
- package/package.json +14 -11
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validateSelfHostedSetupOptions } from './setup-capabilities.js';
|
|
2
|
+
import { hasAdmittedPlatformImages } from './platform-image-admission.js';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
4
|
import { join } from 'node:path';
|
|
3
5
|
import { registerSecret, getPlatformDefaultProvider, setPlatformDefaultProvider, } from '@knowzai/core';
|
|
4
6
|
import { applyPlatform, resolvePackagedAssetsDir, } from './platform-lifecycle.js';
|
|
5
7
|
import { parseEnv, redactPlatformSecrets, } from './platform-runtime.js';
|
|
6
8
|
import { resolveProviderSelection, } from './platform-provider-prompt.js';
|
|
7
|
-
import { acquireGhcrLogin,
|
|
9
|
+
import { acquireGhcrLogin, resolveImageSource } from './platform-image-source.js';
|
|
8
10
|
import { resolveEditionIntent, shouldUseSelfHostedEdition } from './platform-edition.js';
|
|
9
|
-
import { STABLE_SELFHOSTED_RELEASE,
|
|
11
|
+
import { STABLE_SELFHOSTED_RELEASE, applySelfHostedAsync, resolvePackagedSelfHostedAssetsDir, selfHostedToPlatformResult, } from './selfhosted-lifecycle.js';
|
|
10
12
|
import { runOnboarding, runOnboardingProviderProbe, waitForOnboardingReady, DEFAULT_LOCAL_PROFILE, } from './platform-onboarding.js';
|
|
11
13
|
import { ensureEngineReady as ensureContainerEngineReady, } from './container-engine.js';
|
|
12
14
|
import { withSpinner } from './ui.js';
|
|
13
15
|
import { buildRegistryLoginInvocation } from './platform-image-source.js';
|
|
14
|
-
import { parsePlatformReleaseManifest, PlatformReleaseCatalogHttpError, releaseFreshnessNotice, resolvePlatformRelease, SelfServeResolutionError, } from './platform-release-manifest.js';
|
|
16
|
+
import { catalogStaleError, newestManifestVersion, parsePlatformReleaseManifest, PlatformReleaseCatalogHttpError, releaseFreshnessNotice, resolvePlatformRelease, SelfServeResolutionError, } from './platform-release-manifest.js';
|
|
17
|
+
import { pullRegistryOriginFromSource, registryNotOciError, } from './oci-registry-probe.js';
|
|
18
|
+
import { catalogLagsPackagedPin } from './release-pin-matrix.js';
|
|
15
19
|
import { normalizeMothershipOrigin, } from './activate.js';
|
|
20
|
+
import { discoverRuntime } from './runtime-discovery.js';
|
|
16
21
|
import { AGE_ELIGIBILITY_TEXT, AGE_ELIGIBILITY_UNDER_13_MESSAGE } from './login.js';
|
|
17
22
|
import { KnowzError, ExitCode } from '@knowzai/core';
|
|
18
23
|
/**
|
|
@@ -36,7 +41,7 @@ import { KnowzError, ExitCode } from '@knowzai/core';
|
|
|
36
41
|
* up.test.ts anti-rot tripwire). The /release-platform skill bumps BOTH in the
|
|
37
42
|
* same release commit; bump one without the other and the tripwire goes red.
|
|
38
43
|
*/
|
|
39
|
-
export const STABLE_PORTABLE_RELEASE = '0.
|
|
44
|
+
export const STABLE_PORTABLE_RELEASE = '0.47.8';
|
|
40
45
|
export const DEFAULT_PORTABLE_VERSION = STABLE_PORTABLE_RELEASE;
|
|
41
46
|
const DEFAULT_INSTANCE_NAME = 'knowz';
|
|
42
47
|
/**
|
|
@@ -102,6 +107,88 @@ function licenseRequiredError(preflight) {
|
|
|
102
107
|
const detail = sanitizeProblemDetail(preflight.detail);
|
|
103
108
|
return new SelfServeResolutionError(`${detail ?? LICENSE_REQUIRED_FALLBACK} ${LICENSE_REQUIRED_REMEDIATION}`, 'LICENSE_REQUIRED');
|
|
104
109
|
}
|
|
110
|
+
function registryAuthUnreachable(mothershipUrl) {
|
|
111
|
+
return new SelfServeResolutionError(`Could not reach the Knowz image authorization service at ${mothershipUrl}/api/v1/registry/token. ` +
|
|
112
|
+
'Check your network connection, then retry.', 'REGISTRY_AUTH_UNREACHABLE');
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Commercial grant / entitlement preflight for paid portable pulls.
|
|
116
|
+
* `GHCR_PULL_TOKEN` may authenticate to GHCR after this returns; it must never skip this gate.
|
|
117
|
+
*/
|
|
118
|
+
async function resolveEntitledInstallation(input) {
|
|
119
|
+
const { deps, mothershipUrl, log } = input;
|
|
120
|
+
if (!deps.loadStoredActivation || !deps.preflightRegistryCredential) {
|
|
121
|
+
throw new Error('Portable image authorization dependencies are not configured.');
|
|
122
|
+
}
|
|
123
|
+
let activation = await deps.loadStoredActivation({
|
|
124
|
+
projectName: input.projectName,
|
|
125
|
+
configDir: input.configDir,
|
|
126
|
+
engine: input.engine,
|
|
127
|
+
});
|
|
128
|
+
let activatedNow = false;
|
|
129
|
+
if (!activation) {
|
|
130
|
+
if (input.json || !deps.activateInstallation)
|
|
131
|
+
throw activationRequired();
|
|
132
|
+
log("This device isn't linked to a Knowz account yet.");
|
|
133
|
+
log('Linking is free and takes about a minute — your browser will open so you can approve this device.');
|
|
134
|
+
log('');
|
|
135
|
+
try {
|
|
136
|
+
activation = await deps.activateInstallation({
|
|
137
|
+
projectName: input.projectName,
|
|
138
|
+
configDir: input.configDir,
|
|
139
|
+
mothershipUrl,
|
|
140
|
+
engine: input.engine,
|
|
141
|
+
});
|
|
142
|
+
activatedNow = true;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
throw e5();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
let preflight = await deps.preflightRegistryCredential({ mothershipUrl, activation });
|
|
149
|
+
if (preflight.kind === 'transport-failure')
|
|
150
|
+
throw registryAuthUnreachable(mothershipUrl);
|
|
151
|
+
let preflightStatus = preflight.status;
|
|
152
|
+
if (preflightStatus === 403)
|
|
153
|
+
throw licenseRequiredError(preflight);
|
|
154
|
+
if (preflightStatus === 410)
|
|
155
|
+
throw e4(activation.installationId);
|
|
156
|
+
if (preflightStatus === 401) {
|
|
157
|
+
if (activatedNow || !input.canPrompt || !deps.confirmReactivation || !deps.activateInstallation) {
|
|
158
|
+
throw new SelfServeResolutionError(`Stored installation ${activation.installationId} is no longer valid. Run 'knowz activate' to link this device again.`, 'INSTALLATION_INVALID');
|
|
159
|
+
}
|
|
160
|
+
const accepted = await deps.confirmReactivation(activation.installationId);
|
|
161
|
+
if (!accepted)
|
|
162
|
+
throw e5();
|
|
163
|
+
try {
|
|
164
|
+
activation = await deps.activateInstallation({
|
|
165
|
+
projectName: input.projectName,
|
|
166
|
+
configDir: input.configDir,
|
|
167
|
+
mothershipUrl,
|
|
168
|
+
engine: input.engine,
|
|
169
|
+
});
|
|
170
|
+
activatedNow = true;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
throw e5();
|
|
174
|
+
}
|
|
175
|
+
preflight = await deps.preflightRegistryCredential({ mothershipUrl, activation });
|
|
176
|
+
if (preflight.kind === 'transport-failure')
|
|
177
|
+
throw registryAuthUnreachable(mothershipUrl);
|
|
178
|
+
preflightStatus = preflight.status;
|
|
179
|
+
if (preflightStatus === 403)
|
|
180
|
+
throw licenseRequiredError(preflight);
|
|
181
|
+
if (preflightStatus === 410)
|
|
182
|
+
throw e4(activation.installationId);
|
|
183
|
+
}
|
|
184
|
+
if (preflightStatus !== 200) {
|
|
185
|
+
throw new SelfServeResolutionError(`Knowz could not authorize installation ${activation.installationId} for image pulls (HTTP ${preflightStatus}).`, 'INSTALLATION_INVALID');
|
|
186
|
+
}
|
|
187
|
+
registerSecret(activation.credential);
|
|
188
|
+
if (activatedNow)
|
|
189
|
+
log(`✓ Linked — installation "${input.projectName}"`);
|
|
190
|
+
return activation;
|
|
191
|
+
}
|
|
105
192
|
function sanitizeProblemDetail(detail) {
|
|
106
193
|
if (typeof detail !== 'string' || detail.length === 0)
|
|
107
194
|
return undefined;
|
|
@@ -188,19 +275,28 @@ function emitNextSteps(log) {
|
|
|
188
275
|
}
|
|
189
276
|
export async function runFrontDoor(input, deps) {
|
|
190
277
|
const log = input.json
|
|
191
|
-
? (_line) => { }
|
|
278
|
+
? deps.progressLog ?? ((_line) => { })
|
|
192
279
|
: deps.log ?? ((line) => console.log(line));
|
|
280
|
+
const explicitIntent = resolveEditionIntent({ flags: { edition: input.edition }, env: deps.env });
|
|
281
|
+
const existing = discoverRuntime({ name: input.base.name, configDir: input.base.configDir, edition: explicitIntent.explicit ? explicitIntent.edition : undefined });
|
|
282
|
+
const editionIntent = resolveEditionIntent({ flags: { edition: input.edition }, env: deps.env, existingEdition: existing?.edition });
|
|
283
|
+
const useSelfHosted = shouldUseSelfHostedEdition({ intent: editionIntent, imageFlags: input.imageFlags });
|
|
284
|
+
if (useSelfHosted)
|
|
285
|
+
validateSelfHostedSetupOptions({ provider: input.providerFlags.ai, storage: input.base.storage, publicUrls: input.base.publicUrls, orgName: input.base.orgName, seedDemo: input.seedDemo, components: input.base.components, axes: input.base.axes });
|
|
286
|
+
const checkCanceled = () => { if (input.signal?.aborted)
|
|
287
|
+
throw Object.assign(new Error('Setup canceled. Runtime data has been preserved.'), { code: 'SETUP_CANCELED', exitCode: 130 }); };
|
|
288
|
+
checkCanceled();
|
|
193
289
|
const ports = {
|
|
194
|
-
api: input.base.ports?.api ?? 5000,
|
|
195
|
-
web: input.base.ports?.web ?? 3000,
|
|
196
|
-
mcp: input.base.ports?.mcp ?? 3001,
|
|
197
|
-
publicSite: input.base.ports?.publicSite ?? 3002,
|
|
290
|
+
api: input.base.ports?.api ?? existing?.state.ports.api ?? 5000,
|
|
291
|
+
web: input.base.ports?.web ?? existing?.state.ports.web ?? 3000,
|
|
292
|
+
mcp: input.base.ports?.mcp ?? existing?.state.ports.mcp ?? 3001,
|
|
293
|
+
publicSite: input.base.ports?.publicSite ?? existing?.state.ports.publicSite ?? 3002,
|
|
198
294
|
};
|
|
199
295
|
// 0) Environment-only preflight. It deliberately runs before config loading
|
|
200
296
|
// or provider prompting so credentials are never collected on an unusable host.
|
|
201
297
|
let engine;
|
|
202
298
|
if (deps.preflight) {
|
|
203
|
-
let report = await deps.preflight({ name: input.base.name, configDir: input.base.configDir, ports });
|
|
299
|
+
let report = await deps.preflight({ name: input.base.name, configDir: input.base.configDir, ports, components: input.base.components ?? existing?.state.components, edition: editionIntent.edition });
|
|
204
300
|
engine = report.engine;
|
|
205
301
|
if (!report.ok) {
|
|
206
302
|
const machineIsFixable = report.engine?.engine === 'podman'
|
|
@@ -212,7 +308,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
212
308
|
? withSpinner
|
|
213
309
|
: async (_text, run) => run();
|
|
214
310
|
await (deps.ensureEngineReady ?? ensureContainerEngineReady)(report.engine, deps.runner, progress);
|
|
215
|
-
report = await deps.preflight({ name: input.base.name, configDir: input.base.configDir, ports });
|
|
311
|
+
report = await deps.preflight({ name: input.base.name, configDir: input.base.configDir, ports, components: input.base.components ?? existing?.state.components, edition: editionIntent.edition });
|
|
216
312
|
engine = report.engine;
|
|
217
313
|
if (!report.ok)
|
|
218
314
|
throwPreflightFailure(report);
|
|
@@ -220,7 +316,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
220
316
|
}
|
|
221
317
|
// 1) AI-provider picker (flags → persisted default → interactive → offline fallback).
|
|
222
318
|
const cfg = deps.loadConfig();
|
|
223
|
-
const cfgDefault = getPlatformDefaultProvider(cfg);
|
|
319
|
+
const cfgDefault = existing?.state.provider ?? getPlatformDefaultProvider(cfg);
|
|
224
320
|
const canPrompt = deps.isTty && !input.json;
|
|
225
321
|
const interactivePromptOccurred = canPrompt &&
|
|
226
322
|
!input.providerFlags.offline &&
|
|
@@ -277,6 +373,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
277
373
|
}
|
|
278
374
|
const applyInput = {
|
|
279
375
|
...input.base,
|
|
376
|
+
version: input.versionExplicit ? input.base.version : existing?.state.version ?? input.base.version,
|
|
280
377
|
provider: selection.provider,
|
|
281
378
|
azure: selection.azure ?? input.base.azure,
|
|
282
379
|
gcp: selection.gcp ?? input.base.gcp,
|
|
@@ -286,80 +383,57 @@ export async function runFrontDoor(input, deps) {
|
|
|
286
383
|
};
|
|
287
384
|
// 2) Edition then image source. Unentitled `knowz up` uses public selfhosted
|
|
288
385
|
// images; the portable resolver is unchanged when edition is portable.
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// preflight. 403/401/410/transport stay selfhosted and MUST NOT reactivate.
|
|
304
|
-
if (useSelfHosted &&
|
|
305
|
-
!editionIntent.explicit &&
|
|
306
|
-
deps.loadStoredActivation &&
|
|
307
|
-
deps.preflightRegistryCredential) {
|
|
308
|
-
const mothershipUrl = normalizeMothershipOrigin(deps.env.KNOWZ_LICENSING_MOTHERSHIP_URL?.trim() || DEFAULT_MOTHERSHIP_URL);
|
|
309
|
-
try {
|
|
310
|
-
const stored = await deps.loadStoredActivation({
|
|
311
|
-
projectName: input.base.name,
|
|
312
|
-
configDir: input.base.configDir,
|
|
313
|
-
engine: engine ?? LEGACY_DOCKER_ENGINE,
|
|
314
|
-
});
|
|
315
|
-
if (stored) {
|
|
316
|
-
const preflight = await deps.preflightRegistryCredential({
|
|
317
|
-
mothershipUrl,
|
|
318
|
-
activation: stored,
|
|
319
|
-
});
|
|
320
|
-
if (preflight.kind === 'http-response' && preflight.status === 200) {
|
|
321
|
-
useSelfHosted = false;
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
log('Stored installation is not entitled for portable images; using public selfhosted.');
|
|
325
|
-
}
|
|
386
|
+
const savedRuntimeEnv = existing && existsSync(existing.paths.envFile) ? parseEnv(readFileSync(existing.paths.envFile, 'utf8')) : {};
|
|
387
|
+
const envForEdition = { ...deps.env, KNOWZ_REGISTRY: deps.env.KNOWZ_REGISTRY ?? savedRuntimeEnv.KNOWZ_REGISTRY, ...(input.ghcrToken ? { GHCR_PULL_TOKEN: input.ghcrToken } : {}) };
|
|
388
|
+
const cachedRestart = !useSelfHosted && existing && input.base.action === 'up'
|
|
389
|
+
&& (!input.versionExplicit || input.base.version === existing.state.version)
|
|
390
|
+
&& !input.imageFlags.build && !input.imageFlags.pull && !deps.env.KNOWZ_REGISTRY
|
|
391
|
+
&& await (deps.admittedImages ?? hasAdmittedPlatformImages)({ name: input.base.name, version: existing.state.version, paths: existing.paths, engine: engine ?? LEGACY_DOCKER_ENGINE, components: existing.state.components ?? { mcp: true, publicSite: false } }, deps.asyncRunner ?? deps.runner);
|
|
392
|
+
const source = cachedRestart
|
|
393
|
+
? { mode: 'preloaded', composeFile: existing.paths.composeFile, projectDir: existing.paths.runtimeDir, composePlan: 'config-up' }
|
|
394
|
+
: useSelfHosted
|
|
395
|
+
? {
|
|
396
|
+
mode: 'pull',
|
|
397
|
+
composeFile: 'selfhosted',
|
|
398
|
+
projectDir: 'selfhosted',
|
|
399
|
+
composePlan: 'config-pull-up',
|
|
326
400
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
composeFile: 'selfhosted',
|
|
336
|
-
projectDir: 'selfhosted',
|
|
337
|
-
composePlan: 'config-pull-up',
|
|
338
|
-
}
|
|
339
|
-
: resolveImageSource({
|
|
340
|
-
cwd: deps.cwd,
|
|
341
|
-
flags: input.imageFlags,
|
|
342
|
-
canPrompt: deps.isTty && Boolean(deps.ghcrPrompt),
|
|
343
|
-
pathExists: deps.pathExists,
|
|
344
|
-
packagedAssetsDir: deps.packagedAssetsDir,
|
|
345
|
-
env: envForEdition,
|
|
346
|
-
});
|
|
401
|
+
: resolveImageSource({
|
|
402
|
+
cwd: deps.cwd,
|
|
403
|
+
flags: input.imageFlags,
|
|
404
|
+
canPrompt: deps.isTty && Boolean(deps.ghcrPrompt),
|
|
405
|
+
pathExists: deps.pathExists,
|
|
406
|
+
packagedAssetsDir: deps.packagedAssetsDir,
|
|
407
|
+
env: envForEdition,
|
|
408
|
+
});
|
|
347
409
|
const seam = source.mode === 'build'
|
|
348
410
|
? { composeFile: source.composeFile, projectDir: source.projectDir, composePlan: source.composePlan }
|
|
349
411
|
: source.mode === 'pull'
|
|
350
412
|
? { composePlan: source.composePlan, registry: 'registry' in source ? source.registry ?? null : null }
|
|
351
413
|
: { composePlan: source.composePlan };
|
|
414
|
+
const resultImageMode = cachedRestart ? existing.state.imageMode ?? 'pull' : source.mode;
|
|
415
|
+
if (input.imageFlags.pull)
|
|
416
|
+
seam.forceAcquisition = true;
|
|
352
417
|
// §2026-08-31 R7: portable images are linux/amd64-only. Selfhosted GHCR is multi-arch.
|
|
353
418
|
const hostArch = deps.hostArch ?? process.arch;
|
|
354
419
|
if (!useSelfHosted && hostArch === 'arm64' && (source.mode === 'pull' || source.mode === 'preloaded')) {
|
|
355
420
|
log('Note: knowz images run under amd64 emulation on this Mac; native arm64 images are not yet published.');
|
|
356
421
|
}
|
|
357
422
|
const selfServePlan = source.loginPlan?.kind === 'self-serve' ? source.loginPlan : undefined;
|
|
423
|
+
// #862: fail closed when the advertised facade is SPA HTML, not OCI.
|
|
424
|
+
// Skip when probeRegistry is omitted so injected unit tests stay network-free.
|
|
425
|
+
const pullOrigin = pullRegistryOriginFromSource(source);
|
|
426
|
+
if (pullOrigin && deps.probeRegistry) {
|
|
427
|
+
const probe = await deps.probeRegistry(pullOrigin);
|
|
428
|
+
if (!probe.ok)
|
|
429
|
+
throw registryNotOciError(pullOrigin, probe);
|
|
430
|
+
}
|
|
358
431
|
if (selfServePlan) {
|
|
359
432
|
const mothershipUrl = normalizeMothershipOrigin(deps.env.KNOWZ_LICENSING_MOTHERSHIP_URL?.trim() || DEFAULT_MOTHERSHIP_URL);
|
|
360
433
|
const manifestUrl = `${mothershipUrl}${RELEASE_MANIFEST_PATH}`;
|
|
361
434
|
log('◇ Checking Knowz releases…');
|
|
362
435
|
let manifest;
|
|
436
|
+
let catalogFromMothership = true;
|
|
363
437
|
try {
|
|
364
438
|
const raw = await (deps.fetchReleaseManifest ?? defaultFetchReleaseManifest)(manifestUrl);
|
|
365
439
|
// Parsing stays outside the fallback contract: a malformed 200 is a server
|
|
@@ -390,6 +464,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
390
464
|
? await deps.loadPackagedReleaseManifest(fallbackPath)
|
|
391
465
|
: JSON.parse(readFileSync(fallbackPath, 'utf8'));
|
|
392
466
|
manifest = parsePlatformReleaseManifest(fallback);
|
|
467
|
+
catalogFromMothership = false;
|
|
393
468
|
}
|
|
394
469
|
catch {
|
|
395
470
|
throw e1(manifestUrl);
|
|
@@ -397,6 +472,37 @@ export async function runFrontDoor(input, deps) {
|
|
|
397
472
|
log(`Warning: could not reach the Knowz release catalog at ${manifestUrl} — using the release list packaged with this CLI, which may be out of date.`);
|
|
398
473
|
}
|
|
399
474
|
const flavor = selection.provider === 'gcp' ? 'portable-gcp' : 'portable';
|
|
475
|
+
// #865: a successful but stale mothership catalog must not silently pin an
|
|
476
|
+
// older blessed row. Skip packaged-fallback, empty catalog (existing
|
|
477
|
+
// RELEASE_NOT_PUBLISHED), and an explicit pin that is still blessed.
|
|
478
|
+
if (!input.versionExplicit && catalogFromMothership) {
|
|
479
|
+
const catalogNewest = newestManifestVersion(manifest, flavor);
|
|
480
|
+
if (catalogNewest) {
|
|
481
|
+
try {
|
|
482
|
+
const packagedPath = join(source.projectDir, 'releases.json');
|
|
483
|
+
const packagedRaw = deps.loadPackagedReleaseManifest
|
|
484
|
+
? await deps.loadPackagedReleaseManifest(packagedPath)
|
|
485
|
+
: JSON.parse(readFileSync(packagedPath, 'utf8'));
|
|
486
|
+
const packaged = parsePlatformReleaseManifest(packagedRaw);
|
|
487
|
+
const stale = catalogLagsPackagedPin({
|
|
488
|
+
catalogNewest,
|
|
489
|
+
packagedNewest: newestManifestVersion(packaged, flavor),
|
|
490
|
+
});
|
|
491
|
+
if (stale.stale && stale.packagedNewest) {
|
|
492
|
+
throw catalogStaleError({
|
|
493
|
+
manifestUrl,
|
|
494
|
+
catalogNewest: stale.catalogNewest,
|
|
495
|
+
packagedNewest: stale.packagedNewest,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
catch (staleError) {
|
|
500
|
+
if (staleError instanceof SelfServeResolutionError)
|
|
501
|
+
throw staleError;
|
|
502
|
+
// Packaged list unreadable — keep catalog resolution; do not invent a pin.
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
400
506
|
const resolved = resolvePlatformRelease({
|
|
401
507
|
manifest,
|
|
402
508
|
requestedVersion: input.versionExplicit ? input.base.version : undefined,
|
|
@@ -405,6 +511,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
405
511
|
manifestUrl,
|
|
406
512
|
});
|
|
407
513
|
applyInput.version = resolved.release.version;
|
|
514
|
+
seam.expectedDigests = resolved.release.digests;
|
|
408
515
|
if (resolved.note)
|
|
409
516
|
log(resolved.note);
|
|
410
517
|
log(`✓ Knowz Platform ${resolved.release.version} (${flavor}) — released ${resolved.release.releasedAt.slice(0, 10)}`);
|
|
@@ -422,7 +529,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
422
529
|
}
|
|
423
530
|
}
|
|
424
531
|
else if (selection.provider !== 'offline' &&
|
|
425
|
-
(source.mode === 'preloaded' || source.loginPlan?.kind === 'ghcr') &&
|
|
532
|
+
!cachedRestart && (source.mode === 'preloaded' || source.loginPlan?.kind === 'ghcr') &&
|
|
426
533
|
deps.fetchReleaseManifest) {
|
|
427
534
|
// §2026-08-31 R4 (ghcr-token / preloaded): no manifest resolution runs on these
|
|
428
535
|
// paths, so the version about to boot is the pin/explicit choice. Advisory-only
|
|
@@ -435,6 +542,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
435
542
|
loadPackagedReleaseManifest: deps.loadPackagedReleaseManifest,
|
|
436
543
|
});
|
|
437
544
|
if (advisoryManifest) {
|
|
545
|
+
seam.expectedDigests = advisoryManifest.releases.find(release => release.version === (applyInput.version ?? DEFAULT_PORTABLE_VERSION) && release.flavors.includes(selection.provider === 'gcp' ? 'portable-gcp' : 'portable'))?.digests;
|
|
438
546
|
const freshness = releaseFreshnessNotice({
|
|
439
547
|
currentVersion: applyInput.version ?? DEFAULT_PORTABLE_VERSION,
|
|
440
548
|
manifest: advisoryManifest,
|
|
@@ -459,7 +567,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
459
567
|
if (shouldConfirm) {
|
|
460
568
|
const accepted = await deps.confirmPrompt({
|
|
461
569
|
provider: selection.provider,
|
|
462
|
-
imageMode:
|
|
570
|
+
imageMode: resultImageMode,
|
|
463
571
|
version: applyInput.version ?? DEFAULT_PORTABLE_VERSION,
|
|
464
572
|
ports,
|
|
465
573
|
profileName: input.profileName ?? DEFAULT_LOCAL_PROFILE,
|
|
@@ -472,7 +580,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
472
580
|
setPlatformDefaultProvider(cfg, selection.provider);
|
|
473
581
|
deps.saveConfig(cfg);
|
|
474
582
|
const applyDeps = {
|
|
475
|
-
runner: deps.runner,
|
|
583
|
+
runner: deps.asyncRunner ?? deps.runner,
|
|
476
584
|
assetsDir: deps.assetsDir,
|
|
477
585
|
randomBytes: deps.randomBytes,
|
|
478
586
|
now: deps.now,
|
|
@@ -482,27 +590,58 @@ export async function runFrontDoor(input, deps) {
|
|
|
482
590
|
engine: engine ?? LEGACY_DOCKER_ENGINE,
|
|
483
591
|
};
|
|
484
592
|
// 3) Bring the stack up; anonymous pull first, authenticate + retry once on auth failure.
|
|
593
|
+
// Paid GHCR pulls still require mothership grant preflight first — the token is
|
|
594
|
+
// registry auth only and must not skip commercial entitlement (#863).
|
|
595
|
+
const entitledInstallationInput = {
|
|
596
|
+
projectName: input.base.name,
|
|
597
|
+
configDir: input.base.configDir,
|
|
598
|
+
json: input.json,
|
|
599
|
+
mothershipUrl: normalizeMothershipOrigin(deps.env.KNOWZ_LICENSING_MOTHERSHIP_URL?.trim() || DEFAULT_MOTHERSHIP_URL),
|
|
600
|
+
engine: engine ?? LEGACY_DOCKER_ENGINE,
|
|
601
|
+
canPrompt,
|
|
602
|
+
log,
|
|
603
|
+
deps,
|
|
604
|
+
};
|
|
605
|
+
let entitledActivation;
|
|
606
|
+
applyDeps.authorizeAcquisition = async () => {
|
|
607
|
+
entitledActivation ??= await resolveEntitledInstallation(entitledInstallationInput);
|
|
608
|
+
return { installationId: entitledActivation.installationId, authorizedAt: new Date().toISOString() };
|
|
609
|
+
};
|
|
485
610
|
let applied;
|
|
486
611
|
if (useSelfHosted) {
|
|
487
612
|
log('Using public selfhosted images. Portable platform requires --edition=portable and an entitled key.');
|
|
488
613
|
const selfhostedVersion = input.versionExplicit && applyInput.version
|
|
489
614
|
? applyInput.version
|
|
490
|
-
: (deps.env.KNOWZ_SELFHOSTED_VERSION?.trim() || STABLE_SELFHOSTED_RELEASE);
|
|
491
|
-
const selfhosted =
|
|
615
|
+
: (deps.env.KNOWZ_SELFHOSTED_VERSION?.trim() || existing?.state.version || STABLE_SELFHOSTED_RELEASE);
|
|
616
|
+
const selfhosted = await applySelfHostedAsync({
|
|
492
617
|
name: input.base.name,
|
|
493
618
|
version: selfhostedVersion,
|
|
494
619
|
configDir: input.base.configDir,
|
|
495
620
|
ports,
|
|
496
621
|
openAiCompatible: applyInput.openAiCompatible,
|
|
497
622
|
adminPassword: applyInput.superAdminPassphrase,
|
|
623
|
+
provider: selection.provider,
|
|
624
|
+
providerSettingsExplicit: Boolean(input.providerFlags.offline || input.providerFlags.ai || [input.providerFlags.azure, input.providerFlags.openAiCompatible].some(values => values && Object.values(values).some(value => value !== undefined && value !== ''))),
|
|
625
|
+
disableAI: input.providerFlags.offline || input.providerFlags.ai === 'offline' ? true : input.providerFlags.ai ? false : undefined,
|
|
626
|
+
azure: applyInput.azure,
|
|
627
|
+
components: applyInput.components,
|
|
498
628
|
}, {
|
|
499
|
-
runner: deps.runner,
|
|
629
|
+
runner: deps.asyncRunner ?? deps.runner,
|
|
630
|
+
engine: engine ?? LEGACY_DOCKER_ENGINE,
|
|
631
|
+
signal: input.signal,
|
|
632
|
+
progress: log,
|
|
633
|
+
waitUntilReady: async (apiUrl, signal) => {
|
|
634
|
+
const ready = await waitForOnboardingReady({}, deps.onboardingDepsFor(apiUrl));
|
|
635
|
+
return ready && !signal?.aborted;
|
|
636
|
+
},
|
|
500
637
|
randomBytes: deps.randomBytes,
|
|
501
638
|
packagedAssetsDir: deps.selfHostedAssetsDir ?? resolvePackagedSelfHostedAssetsDir(),
|
|
502
639
|
});
|
|
503
640
|
applied = selfHostedToPlatformResult(selfhosted, selection.provider, deps.now);
|
|
504
641
|
}
|
|
505
642
|
else {
|
|
643
|
+
if (!cachedRestart)
|
|
644
|
+
await applyDeps.authorizeAcquisition({ name: input.base.name, mode: source.mode, engine: engine ?? LEGACY_DOCKER_ENGINE, env: deps.env });
|
|
506
645
|
if (selfServePlan)
|
|
507
646
|
log(`◇ Pulling images from ${selfServePlan.registry}…`);
|
|
508
647
|
try {
|
|
@@ -524,84 +663,7 @@ export async function runFrontDoor(input, deps) {
|
|
|
524
663
|
applied = await (deps.applyPlatform ?? applyPlatform)(applyInput, applyDeps, { ...seam, login });
|
|
525
664
|
}
|
|
526
665
|
else if (source.mode === 'pull' && selfServePlan && isRegistryAuthError(error)) {
|
|
527
|
-
const
|
|
528
|
-
const mothershipUrl = normalizeMothershipOrigin(deps.env.KNOWZ_LICENSING_MOTHERSHIP_URL?.trim() || DEFAULT_MOTHERSHIP_URL);
|
|
529
|
-
if (!deps.loadStoredActivation ||
|
|
530
|
-
!deps.activateInstallation ||
|
|
531
|
-
!deps.preflightRegistryCredential) {
|
|
532
|
-
throw new Error('Self-serve registry authentication dependencies are not configured.');
|
|
533
|
-
}
|
|
534
|
-
let activation = await deps.loadStoredActivation({
|
|
535
|
-
projectName: input.base.name,
|
|
536
|
-
configDir: input.base.configDir,
|
|
537
|
-
engine: activeEngine,
|
|
538
|
-
});
|
|
539
|
-
let activatedNow = false;
|
|
540
|
-
if (!activation) {
|
|
541
|
-
if (input.json)
|
|
542
|
-
throw activationRequired();
|
|
543
|
-
log("This device isn't linked to a Knowz account yet.");
|
|
544
|
-
log('Linking is free and takes about a minute — your browser will open so you can approve this device.');
|
|
545
|
-
log('');
|
|
546
|
-
try {
|
|
547
|
-
activation = await deps.activateInstallation({
|
|
548
|
-
projectName: input.base.name,
|
|
549
|
-
configDir: input.base.configDir,
|
|
550
|
-
mothershipUrl,
|
|
551
|
-
engine: activeEngine,
|
|
552
|
-
});
|
|
553
|
-
activatedNow = true;
|
|
554
|
-
}
|
|
555
|
-
catch {
|
|
556
|
-
throw e5();
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
let preflight = await deps.preflightRegistryCredential({ mothershipUrl, activation });
|
|
560
|
-
if (preflight.kind === 'transport-failure') {
|
|
561
|
-
throw new SelfServeResolutionError(`Could not reach the Knowz image authorization service at ${mothershipUrl}/api/v1/registry/token. ` +
|
|
562
|
-
'Check your network connection, then retry.', 'REGISTRY_AUTH_UNREACHABLE');
|
|
563
|
-
}
|
|
564
|
-
let preflightStatus = preflight.status;
|
|
565
|
-
if (preflightStatus === 403)
|
|
566
|
-
throw licenseRequiredError(preflight);
|
|
567
|
-
if (preflightStatus === 410)
|
|
568
|
-
throw e4(activation.installationId);
|
|
569
|
-
if (preflightStatus === 401) {
|
|
570
|
-
if (activatedNow || !canPrompt || !deps.confirmReactivation) {
|
|
571
|
-
throw new SelfServeResolutionError(`Stored installation ${activation.installationId} is no longer valid. Run 'knowz activate' to link this device again.`, 'INSTALLATION_INVALID');
|
|
572
|
-
}
|
|
573
|
-
const accepted = await deps.confirmReactivation(activation.installationId);
|
|
574
|
-
if (!accepted)
|
|
575
|
-
throw e5();
|
|
576
|
-
try {
|
|
577
|
-
activation = await deps.activateInstallation({
|
|
578
|
-
projectName: input.base.name,
|
|
579
|
-
configDir: input.base.configDir,
|
|
580
|
-
mothershipUrl,
|
|
581
|
-
engine: activeEngine,
|
|
582
|
-
});
|
|
583
|
-
activatedNow = true;
|
|
584
|
-
}
|
|
585
|
-
catch {
|
|
586
|
-
throw e5();
|
|
587
|
-
}
|
|
588
|
-
preflight = await deps.preflightRegistryCredential({ mothershipUrl, activation });
|
|
589
|
-
if (preflight.kind === 'transport-failure') {
|
|
590
|
-
throw new SelfServeResolutionError(`Could not reach the Knowz image authorization service at ${mothershipUrl}/api/v1/registry/token. ` +
|
|
591
|
-
'Check your network connection, then retry.', 'REGISTRY_AUTH_UNREACHABLE');
|
|
592
|
-
}
|
|
593
|
-
preflightStatus = preflight.status;
|
|
594
|
-
if (preflightStatus === 403)
|
|
595
|
-
throw licenseRequiredError(preflight);
|
|
596
|
-
if (preflightStatus === 410)
|
|
597
|
-
throw e4(activation.installationId);
|
|
598
|
-
}
|
|
599
|
-
if (preflightStatus !== 200) {
|
|
600
|
-
throw new SelfServeResolutionError(`Knowz could not authorize installation ${activation.installationId} for image pulls (HTTP ${preflightStatus}).`, 'INSTALLATION_INVALID');
|
|
601
|
-
}
|
|
602
|
-
registerSecret(activation.credential);
|
|
603
|
-
if (activatedNow)
|
|
604
|
-
log(`✓ Linked — installation "${input.base.name}"`);
|
|
666
|
+
const activation = entitledActivation ?? await resolveEntitledInstallation(entitledInstallationInput);
|
|
605
667
|
const login = buildRegistryLoginInvocation(selfServePlan.registry, activation.installationId, activation.credential);
|
|
606
668
|
try {
|
|
607
669
|
applied = await (deps.applyPlatform ?? applyPlatform)(applyInput, applyDeps, {
|
|
@@ -627,9 +689,10 @@ export async function runFrontDoor(input, deps) {
|
|
|
627
689
|
}
|
|
628
690
|
}
|
|
629
691
|
}
|
|
692
|
+
checkCanceled();
|
|
630
693
|
for (const line of applied.output.split('\n'))
|
|
631
694
|
log(line);
|
|
632
|
-
const profileName = input.profileName ??
|
|
695
|
+
const profileName = input.profileName ?? localProfileNameFor(input.base.name);
|
|
633
696
|
const apiUrl = applied.state.serviceUrls.api;
|
|
634
697
|
const webUrl = applied.state.serviceUrls.web;
|
|
635
698
|
const renderedEnv = parseEnv(readFileSync(applied.paths.envFile, 'utf8'));
|
|
@@ -653,24 +716,37 @@ export async function runFrontDoor(input, deps) {
|
|
|
653
716
|
// 4a) The same bounded health gate precedes every credential path, including
|
|
654
717
|
// profile reuse. Passing the result into onboarding avoids a second poll.
|
|
655
718
|
const apiReady = await waitForOnboardingReady({}, onboardingDeps);
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
719
|
+
checkCanceled();
|
|
720
|
+
if (!apiReady)
|
|
721
|
+
throw new Error('Runtime health check did not become ready. Inspect knowz runtime doctor and logs, then retry setup.');
|
|
722
|
+
if (useSelfHosted) {
|
|
723
|
+
let profile = null;
|
|
724
|
+
let nextAction;
|
|
725
|
+
try {
|
|
726
|
+
const reused = await deps.reuseExistingProfile?.(profileName, apiUrl, { dialect: 'selfhosted', signal: input.signal });
|
|
727
|
+
if (reused)
|
|
728
|
+
profile = profileName;
|
|
729
|
+
else if (deps.selfHostedLogin) {
|
|
730
|
+
const login = await deps.selfHostedLogin({ profile: profileName, apiUrl, username: renderedEnv.ADMIN_USERNAME || 'admin', password: renderedEnv.ADMIN_PASSWORD || '', signal: input.signal });
|
|
731
|
+
profile = login.profile;
|
|
732
|
+
}
|
|
733
|
+
else
|
|
734
|
+
nextAction = `Run knowz login --self-hosted --api-url ${apiUrl} --profile ${profileName} to finish CLI access.`;
|
|
735
|
+
}
|
|
736
|
+
catch (error) {
|
|
737
|
+
nextAction = `${redactPlatformSecrets(errorMessage(error), Object.values(renderedEnv))} Sign in with the current administrator password: knowz login --self-hosted --username ${renderedEnv.ADMIN_USERNAME || 'admin'} --api-url ${apiUrl} --profile ${profileName}.`;
|
|
738
|
+
}
|
|
739
|
+
checkCanceled();
|
|
740
|
+
if (input.open)
|
|
741
|
+
onboardingDeps.openBrowser(webUrl);
|
|
742
|
+
if (nextAction)
|
|
743
|
+
log(nextAction);
|
|
744
|
+
return { status: profile ? 'complete' : 'attention-required', ...(profile ? {} : { code: 'SETUP_ACTION_REQUIRED', nextAction }), state: applied.state, imageMode: 'pull', provider: selection.provider, profile, loginMode: profile ? 'existing' : 'manual', seeded: false, edition: 'selfhosted' };
|
|
669
745
|
}
|
|
670
746
|
// 4b) If a prior `up` already signed the CLI profile in and its key still authenticates,
|
|
671
747
|
// skip the register/onboarding dance entirely — avoids the register → "Email already
|
|
672
748
|
// registered" → manual-degrade noise on every idempotent re-up.
|
|
673
|
-
const reused = deps.reuseExistingProfile ? await deps.reuseExistingProfile(profileName, apiUrl) : null;
|
|
749
|
+
const reused = deps.reuseExistingProfile ? await deps.reuseExistingProfile(profileName, apiUrl, { dialect: 'platform' }) : null;
|
|
674
750
|
if (reused) {
|
|
675
751
|
await runOnboardingProviderProbe(selection.provider, () => onboardingDeps.apiClientFor(profileName), onboardingDeps);
|
|
676
752
|
log(`Already signed in — reusing the '${profileName}' CLI profile${reused.tenantId ? ` (tenant ${reused.tenantId})` : ''}.`);
|
|
@@ -678,15 +754,17 @@ export async function runFrontDoor(input, deps) {
|
|
|
678
754
|
log(` API: ${apiUrl}`);
|
|
679
755
|
if (input.open)
|
|
680
756
|
onboardingDeps.openBrowser(webUrl);
|
|
681
|
-
return { state: applied.state, imageMode:
|
|
757
|
+
return { status: 'complete', state: applied.state, imageMode: resultImageMode, provider: selection.provider, profile: profileName, loginMode: 'existing', seeded: false, edition: useSelfHosted ? 'selfhosted' : 'portable' };
|
|
682
758
|
}
|
|
683
759
|
// 4c) Onboarding: bootstrap → register fallback → manual degrade.
|
|
684
760
|
identity = await collectRegistrationIdentity();
|
|
685
761
|
const onboarding = await runOnboarding({ ...onboardingInput, register: identity, apiReady }, onboardingDeps);
|
|
686
762
|
emitNextSteps(log);
|
|
687
763
|
return {
|
|
764
|
+
status: onboarding.profile ? 'complete' : 'attention-required',
|
|
765
|
+
...(onboarding.profile ? {} : { code: 'SETUP_ACTION_REQUIRED', nextAction: 'Finish account sign-in with knowz login for this endpoint.' }),
|
|
688
766
|
state: applied.state,
|
|
689
|
-
imageMode:
|
|
767
|
+
imageMode: resultImageMode,
|
|
690
768
|
provider: selection.provider,
|
|
691
769
|
profile: onboarding.profile ?? null,
|
|
692
770
|
loginMode: onboarding.loginMode,
|