vigthoria-cli 1.13.20 → 1.13.23
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/completions/_vigthoria +49 -0
- package/completions/vigthoria.bash +6 -0
- package/completions/vigthoria.fish +41 -0
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +63 -128
- package/dist/commands/background.d.ts +0 -2
- package/dist/commands/background.js +26 -34
- package/dist/commands/bridge.js +45 -41
- package/dist/commands/cancel.d.ts +1 -0
- package/dist/commands/cancel.js +22 -16
- package/dist/commands/chat.d.ts +3 -42
- package/dist/commands/chat.js +378 -1123
- package/dist/commands/coding-registration.d.ts +4 -0
- package/dist/commands/coding-registration.js +24 -0
- package/dist/commands/config.js +23 -29
- package/dist/commands/conversation-registration.d.ts +4 -0
- package/dist/commands/conversation-registration.js +122 -0
- package/dist/commands/deploy.d.ts +8 -2
- package/dist/commands/deploy.js +92 -90
- package/dist/commands/device.d.ts +1 -2
- package/dist/commands/device.js +37 -21
- package/dist/commands/doctor-registration.d.ts +4 -0
- package/dist/commands/doctor-registration.js +207 -0
- package/dist/commands/edit.js +22 -33
- package/dist/commands/explain.js +7 -10
- package/dist/commands/fork.d.ts +1 -2
- package/dist/commands/fork.js +72 -22
- package/dist/commands/game.d.ts +1 -1
- package/dist/commands/game.js +17 -6
- package/dist/commands/generate.js +7 -9
- package/dist/commands/history.js +11 -7
- package/dist/commands/hub.d.ts +2 -2
- package/dist/commands/hub.js +34 -35
- package/dist/commands/legion.d.ts +0 -1
- package/dist/commands/legion.js +62 -79
- package/dist/commands/music.d.ts +1 -2
- package/dist/commands/music.js +62 -27
- package/dist/commands/platform-registration.d.ts +4 -0
- package/dist/commands/platform-registration.js +45 -0
- package/dist/commands/preview.d.ts +0 -1
- package/dist/commands/preview.js +82 -35
- package/dist/commands/product-run-registration.d.ts +4 -0
- package/dist/commands/product-run-registration.js +490 -0
- package/dist/commands/replay.d.ts +1 -2
- package/dist/commands/replay.js +15 -11
- package/dist/commands/repo.d.ts +14 -7
- package/dist/commands/repo.js +244 -198
- package/dist/commands/review.js +9 -12
- package/dist/commands/security.d.ts +1 -2
- package/dist/commands/security.js +12 -6
- package/dist/commands/update-registration.d.ts +3 -0
- package/dist/commands/update-registration.js +368 -0
- package/dist/commands/v4-registration.d.ts +4 -0
- package/dist/commands/v4-registration.js +24 -0
- package/dist/commands/v4.d.ts +1 -1
- package/dist/commands/v4.js +46 -8
- package/dist/commands/wallet.d.ts +1 -3
- package/dist/commands/wallet.js +18 -45
- package/dist/commands/workflow.d.ts +2 -0
- package/dist/commands/workflow.js +52 -39
- package/dist/index.js +124 -1589
- package/dist/utils/agent-stream-state.d.ts +27 -0
- package/dist/utils/agent-stream-state.js +93 -0
- package/dist/utils/agentRoute.d.ts +2 -1
- package/dist/utils/agentRoute.js +22 -9
- package/dist/utils/agentRunOutcome.d.ts +16 -0
- package/dist/utils/agentRunOutcome.js +37 -2
- package/dist/utils/api-client-factory.d.ts +8 -0
- package/dist/utils/api-client-factory.js +8 -0
- package/dist/utils/api.d.ts +44 -266
- package/dist/utils/api.js +647 -3180
- package/dist/utils/auth-session.d.ts +41 -0
- package/dist/utils/auth-session.js +224 -0
- package/dist/utils/brain-hub-client.d.ts +0 -4
- package/dist/utils/brain-hub-client.js +6 -3
- package/dist/utils/bridge-client.js +2 -0
- package/dist/utils/capability-health-service.d.ts +48 -0
- package/dist/utils/capability-health-service.js +64 -0
- package/dist/utils/chat-prompt-policy.d.ts +18 -0
- package/dist/utils/chat-prompt-policy.js +61 -0
- package/dist/utils/chat-tool-call-parser.d.ts +11 -0
- package/dist/utils/chat-tool-call-parser.js +71 -0
- package/dist/utils/cli-state.d.ts +22 -4
- package/dist/utils/cli-state.js +105 -47
- package/dist/utils/code-operations-service.d.ts +104 -0
- package/dist/utils/code-operations-service.js +837 -0
- package/dist/utils/codebase-indexer.d.ts +1 -0
- package/dist/utils/codebase-indexer.js +28 -8
- package/dist/utils/command-contract.d.ts +61 -0
- package/dist/utils/command-contract.js +149 -0
- package/dist/utils/command-policy.d.ts +10 -0
- package/dist/utils/command-policy.js +54 -0
- package/dist/utils/config.d.ts +13 -5
- package/dist/utils/config.js +220 -94
- package/dist/utils/context-ranker.js +11 -2
- package/dist/utils/context-state.d.ts +39 -0
- package/dist/utils/context-state.js +52 -0
- package/dist/utils/deckEvents.d.ts +0 -5
- package/dist/utils/deckEvents.js +3 -2
- package/dist/utils/desktop-bridge-client.js +2 -0
- package/dist/utils/direct-output-policy.d.ts +3 -0
- package/dist/utils/direct-output-policy.js +76 -0
- package/dist/utils/durable-json.d.ts +57 -0
- package/dist/utils/durable-json.js +319 -0
- package/dist/utils/fastAgentRouter.d.ts +5 -6
- package/dist/utils/fastAgentRouter.js +17 -25
- package/dist/utils/files.js +21 -13
- package/dist/utils/frontend-preview-service.d.ts +76 -0
- package/dist/utils/frontend-preview-service.js +482 -0
- package/dist/utils/goaEvents.d.ts +0 -4
- package/dist/utils/goaEvents.js +5 -2
- package/dist/utils/logger.d.ts +2 -1
- package/dist/utils/logger.js +27 -20
- package/dist/utils/mcp-context-client.d.ts +24 -0
- package/dist/utils/mcp-context-client.js +58 -0
- package/dist/utils/model-governance.d.ts +18 -0
- package/dist/utils/model-governance.js +75 -0
- package/dist/utils/model-transport-service.d.ts +44 -0
- package/dist/utils/model-transport-service.js +111 -0
- package/dist/utils/mutation-journal.d.ts +42 -0
- package/dist/utils/mutation-journal.js +387 -0
- package/dist/utils/network-policy.d.ts +24 -0
- package/dist/utils/network-policy.js +202 -0
- package/dist/utils/operator-client.d.ts +45 -0
- package/dist/utils/operator-client.js +159 -0
- package/dist/utils/post-write-validator.js +7 -9
- package/dist/utils/preview-screenshot-adapter.d.ts +15 -0
- package/dist/utils/preview-screenshot-adapter.js +51 -0
- package/dist/utils/process-policy.d.ts +23 -0
- package/dist/utils/process-policy.js +284 -0
- package/dist/utils/project-memory.d.ts +13 -3
- package/dist/utils/project-memory.js +70 -17
- package/dist/utils/prompt-workspace-resolver.d.ts +14 -0
- package/dist/utils/prompt-workspace-resolver.js +64 -0
- package/dist/utils/release-install.d.ts +11 -0
- package/dist/utils/release-install.js +155 -0
- package/dist/utils/release-policy.d.ts +64 -0
- package/dist/utils/release-policy.js +293 -0
- package/dist/utils/requestIntent.js +22 -3
- package/dist/utils/runtime-capability.d.ts +8 -0
- package/dist/utils/runtime-capability.js +16 -0
- package/dist/utils/runtime-temp.d.ts +76 -0
- package/dist/utils/runtime-temp.js +492 -0
- package/dist/utils/secret-policy.d.ts +20 -0
- package/dist/utils/secret-policy.js +160 -0
- package/dist/utils/session.d.ts +17 -3
- package/dist/utils/session.js +354 -110
- package/dist/utils/tool-approval-service.d.ts +17 -0
- package/dist/utils/tool-approval-service.js +78 -0
- package/dist/utils/tool-capability-providers.d.ts +57 -0
- package/dist/utils/tool-capability-providers.js +57 -0
- package/dist/utils/tools.d.ts +2 -23
- package/dist/utils/tools.js +226 -512
- package/dist/utils/update-policy.d.ts +18 -0
- package/dist/utils/update-policy.js +137 -0
- package/dist/utils/v3-agent-client.d.ts +40 -0
- package/dist/utils/v3-agent-client.js +165 -0
- package/dist/utils/v3-workspace-service.d.ts +28 -0
- package/dist/utils/v3-workspace-service.js +279 -0
- package/dist/utils/vigflow-client.d.ts +95 -0
- package/dist/utils/vigflow-client.js +105 -0
- package/dist/utils/workspace-boundary.d.ts +45 -0
- package/dist/utils/workspace-boundary.js +377 -0
- package/dist/utils/workspace-brain-service.d.ts +2 -0
- package/dist/utils/workspace-brain-service.js +11 -1
- package/dist/utils/workspace-cache.js +37 -15
- package/dist/utils/workspace-stream.js +35 -10
- package/install.ps1 +115 -142
- package/install.sh +112 -81
- package/package.json +43 -9
- package/release-policy.json +43 -0
- package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
- package/scripts/release/generate-completions.mjs +24 -0
- package/scripts/release/install-release.mjs +10 -0
- package/scripts/release/publish-cli-release.mjs +116 -0
- package/scripts/release/publish-cli-release.sh +2 -70
- package/scripts/release/resolve-release-manifest.mjs +26 -0
- package/scripts/release/test-balanced-model-live.sh +45 -0
- package/scripts/release/validate-live-service-gates.sh +93 -0
- package/scripts/release/validate-no-go-gates.sh +145 -174
- package/scripts/release/verify-runtime-consistency.mjs +4 -1
- package/dist/commands/index.d.ts +0 -12
- package/dist/commands/index.js +0 -194
- package/dist/commands/update.d.ts +0 -9
- package/dist/commands/update.js +0 -301
- package/dist/utils/templateInstantPath.d.ts +0 -18
- package/dist/utils/templateInstantPath.js +0 -228
package/install.sh
CHANGED
|
@@ -28,32 +28,57 @@ fi
|
|
|
28
28
|
# Configuration
|
|
29
29
|
CLI_VERSION="1.13.20"
|
|
30
30
|
INSTALL_DIR="$HOME/.vigthoria"
|
|
31
|
-
REPO_URL="https://market.vigthoria.io/vigthoria/vigthoria-cli"
|
|
32
|
-
GIT_PACKAGE_URL="git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
|
|
33
31
|
MANIFEST_URL="${VIGTHORIA_UPDATE_MANIFEST_URL:-https://extension.vigthoria.io/downloads/manifest.json}"
|
|
34
32
|
HOSTED_TARBALL_URL="https://extension.vigthoria.io/downloads/vigthoria-cli-${CLI_VERSION}.tgz"
|
|
35
33
|
HOSTED_TARBALL_SHA256=""
|
|
34
|
+
INSTALLER_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd || true)"
|
|
35
|
+
RELEASE_RESOLVER="$INSTALLER_ROOT/scripts/release/resolve-release-manifest.mjs"
|
|
36
|
+
RELEASE_INSTALLER="$INSTALLER_ROOT/scripts/release/install-release.mjs"
|
|
37
|
+
|
|
38
|
+
validate_release_url() {
|
|
39
|
+
python3 - "$1" <<'PY'
|
|
40
|
+
import sys
|
|
41
|
+
from urllib.parse import urlsplit
|
|
42
|
+
allowed = {
|
|
43
|
+
'extension.vigthoria.io', 'landing.vigthoria.io', 'cli.vigthoria.io',
|
|
44
|
+
'coder.vigthoria.io', 'market.vigthoria.io', 'registry.npmjs.org',
|
|
45
|
+
}
|
|
46
|
+
try:
|
|
47
|
+
parsed = urlsplit(sys.argv[1])
|
|
48
|
+
valid = parsed.scheme == 'https' and parsed.hostname in allowed and parsed.port in (None, 443) and not parsed.username and not parsed.password and '\\' not in sys.argv[1]
|
|
49
|
+
except Exception:
|
|
50
|
+
valid = False
|
|
51
|
+
raise SystemExit(0 if valid else 1)
|
|
52
|
+
PY
|
|
53
|
+
}
|
|
36
54
|
|
|
37
55
|
resolve_release_manifest() {
|
|
38
|
-
|
|
56
|
+
# Direct artifacts are accepted only when the packaged shared verifier is
|
|
57
|
+
# present and validates the strict manifest plus detached Ed25519 signature.
|
|
58
|
+
# A curl-piped legacy installer therefore falls back to the exact pinned npm
|
|
59
|
+
# version instead of trusting an unsigned manifest.
|
|
60
|
+
if [[ ! -f "$RELEASE_RESOLVER" ]] || ! command -v node >/dev/null 2>&1 || ! command -v python3 >/dev/null 2>&1; then
|
|
39
61
|
return 0
|
|
40
62
|
fi
|
|
41
63
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
64
|
+
if ! validate_release_url "$MANIFEST_URL"; then
|
|
65
|
+
echo "Refusing untrusted release manifest URL" >&2
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
local resolved_json
|
|
69
|
+
resolved_json="$(node "$RELEASE_RESOLVER" "$MANIFEST_URL" stable 2>/dev/null || true)"
|
|
70
|
+
if [[ -z "$resolved_json" ]]; then
|
|
45
71
|
return 0
|
|
46
72
|
fi
|
|
47
73
|
|
|
48
74
|
local resolved
|
|
49
|
-
resolved="$(printf '%s' "$
|
|
75
|
+
resolved="$(printf '%s' "$resolved_json" | python3 -c "
|
|
50
76
|
import json, sys
|
|
51
77
|
try:
|
|
52
78
|
data = json.load(sys.stdin)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
sha256 = str(stable.get('sha256') or '').strip().lower()
|
|
79
|
+
version = str(data.get('version') or '').strip()
|
|
80
|
+
url = str(data.get('url') or '').strip()
|
|
81
|
+
sha256 = str(data.get('sha256') or '').strip().lower()
|
|
57
82
|
if version:
|
|
58
83
|
print(version)
|
|
59
84
|
if url:
|
|
@@ -74,6 +99,10 @@ except Exception:
|
|
|
74
99
|
CLI_VERSION="$manifest_version"
|
|
75
100
|
fi
|
|
76
101
|
if [[ -n "$manifest_url" ]]; then
|
|
102
|
+
if ! validate_release_url "$manifest_url"; then
|
|
103
|
+
echo "Refusing untrusted release artifact URL" >&2
|
|
104
|
+
exit 1
|
|
105
|
+
fi
|
|
77
106
|
HOSTED_TARBALL_URL="$manifest_url"
|
|
78
107
|
elif [[ -n "$manifest_version" ]]; then
|
|
79
108
|
HOSTED_TARBALL_URL="https://extension.vigthoria.io/downloads/vigthoria-cli-${CLI_VERSION}.tgz"
|
|
@@ -182,6 +211,41 @@ check_requirements() {
|
|
|
182
211
|
}
|
|
183
212
|
|
|
184
213
|
# Install CLI
|
|
214
|
+
prepare_temp_root() {
|
|
215
|
+
local requested_root="${VIGTHORIA_TEMP_DIR:-$HOME/.vigthoria/tmp}"
|
|
216
|
+
case "$requested_root" in
|
|
217
|
+
/*) ;;
|
|
218
|
+
*) echo -e "${RED}VIGTHORIA_TEMP_DIR must be an absolute local path${NC}" >&2; return 1 ;;
|
|
219
|
+
esac
|
|
220
|
+
if [[ "$requested_root" == "/" || "$requested_root" == "${TMPDIR:-/tmp}" ]]; then
|
|
221
|
+
echo -e "${RED}Refusing shared or filesystem-root temporary storage${NC}" >&2
|
|
222
|
+
return 1
|
|
223
|
+
fi
|
|
224
|
+
mkdir -p "$requested_root"
|
|
225
|
+
local path_cursor="$requested_root"
|
|
226
|
+
while [[ "$path_cursor" != "/" ]]; do
|
|
227
|
+
if [[ -L "$path_cursor" ]]; then
|
|
228
|
+
echo -e "${RED}Refusing a symbolic-link temporary storage path${NC}" >&2
|
|
229
|
+
return 1
|
|
230
|
+
fi
|
|
231
|
+
path_cursor="$(dirname -- "$path_cursor")"
|
|
232
|
+
done
|
|
233
|
+
local resolved_root resolved_home
|
|
234
|
+
resolved_root="$(cd "$requested_root" && pwd -P)"
|
|
235
|
+
resolved_home="$(cd "$HOME" && pwd -P)"
|
|
236
|
+
case "$resolved_root" in
|
|
237
|
+
/tmp|/var/tmp|/usr/tmp) echo -e "${RED}Refusing shared temporary storage${NC}" >&2; return 1 ;;
|
|
238
|
+
esac
|
|
239
|
+
if [[ -z "${VIGTHORIA_TEMP_DIR:-}" ]]; then
|
|
240
|
+
case "$resolved_root/" in
|
|
241
|
+
"$resolved_home/"*) ;;
|
|
242
|
+
*) echo -e "${RED}Default temporary storage escaped the user home${NC}" >&2; return 1 ;;
|
|
243
|
+
esac
|
|
244
|
+
fi
|
|
245
|
+
chmod 700 "$resolved_root"
|
|
246
|
+
printf '%s\n' "$resolved_root"
|
|
247
|
+
}
|
|
248
|
+
|
|
185
249
|
install_cli() {
|
|
186
250
|
echo -e "${CYAN}Installing Vigthoria CLI...${NC}"
|
|
187
251
|
|
|
@@ -191,9 +255,14 @@ install_cli() {
|
|
|
191
255
|
# Option 1: Download and verify the exact hosted release package.
|
|
192
256
|
if [[ -n "$HOSTED_TARBALL_SHA256" ]]; then
|
|
193
257
|
echo "Downloading checksum-verified hosted release package..."
|
|
194
|
-
|
|
258
|
+
VIGTHORIA_INSTALL_TEMP_ROOT="$(prepare_temp_root)" || return 1
|
|
259
|
+
RELEASE_TMP_DIR="$(mktemp -d "$VIGTHORIA_INSTALL_TEMP_ROOT/install.XXXXXX")"
|
|
195
260
|
RELEASE_ARCHIVE="$RELEASE_TMP_DIR/vigthoria-cli-${CLI_VERSION}.tgz"
|
|
196
|
-
if !
|
|
261
|
+
if ! validate_release_url "$HOSTED_TARBALL_URL"; then
|
|
262
|
+
echo -e "${RED}Refusing untrusted release artifact URL${NC}"
|
|
263
|
+
return 1
|
|
264
|
+
fi
|
|
265
|
+
if ! curl -fsS --proto '=https' --max-redirs 0 "$HOSTED_TARBALL_URL" -o "$RELEASE_ARCHIVE"; then
|
|
197
266
|
rm -rf "$RELEASE_TMP_DIR"
|
|
198
267
|
echo -e "${RED}✗ Failed to download verified release package${NC}"
|
|
199
268
|
exit 1
|
|
@@ -212,42 +281,23 @@ install_cli() {
|
|
|
212
281
|
echo -e "${RED}✗ Release checksum verification failed${NC}"
|
|
213
282
|
exit 1
|
|
214
283
|
fi
|
|
215
|
-
|
|
284
|
+
if [[ -f "$RELEASE_INSTALLER" ]]; then
|
|
285
|
+
node "$RELEASE_INSTALLER" "$RELEASE_ARCHIVE" "$CLI_VERSION"
|
|
286
|
+
else
|
|
287
|
+
echo -e "${RED}✗ Transactional release installer is unavailable${NC}"
|
|
288
|
+
exit 1
|
|
289
|
+
fi
|
|
216
290
|
rm -rf "$RELEASE_TMP_DIR"
|
|
217
|
-
elif npm view vigthoria-cli version &> /dev/null; then
|
|
218
|
-
echo "Installing from npm registry..."
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
echo "Installed from git package fallback."
|
|
222
|
-
else
|
|
223
|
-
# Option 2: Install from local or git
|
|
224
|
-
echo "Installing from source..."
|
|
225
|
-
|
|
226
|
-
# Check if we're in the CLI directory
|
|
227
|
-
if [ -f "package.json" ] && grep -q '"name": "vigthoria-cli"' package.json; then
|
|
228
|
-
echo "Installing from current directory..."
|
|
229
|
-
npm install
|
|
230
|
-
npm run build
|
|
231
|
-
npm link
|
|
291
|
+
elif npm view --registry=https://registry.npmjs.org/ "vigthoria-cli@${CLI_VERSION}" version &> /dev/null; then
|
|
292
|
+
echo "Installing exact version ${CLI_VERSION} from npm registry..."
|
|
293
|
+
if [[ -f "$RELEASE_INSTALLER" ]]; then
|
|
294
|
+
node "$RELEASE_INSTALLER" "vigthoria-cli@${CLI_VERSION}" "$CLI_VERSION"
|
|
232
295
|
else
|
|
233
|
-
|
|
234
|
-
echo "Cloning from repository..."
|
|
235
|
-
git clone "$REPO_URL" "$INSTALL_DIR/cli" 2>/dev/null || {
|
|
236
|
-
echo -e "${YELLOW}Repository not available, using local install${NC}"
|
|
237
|
-
# Copy local files for development
|
|
238
|
-
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
239
|
-
if [ -d "$SCRIPT_DIR/../src" ]; then
|
|
240
|
-
cp -r "$SCRIPT_DIR/.." "$INSTALL_DIR/cli"
|
|
241
|
-
fi
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if [ -d "$INSTALL_DIR/cli" ]; then
|
|
245
|
-
cd "$INSTALL_DIR/cli"
|
|
246
|
-
npm install
|
|
247
|
-
npm run build
|
|
248
|
-
npm link
|
|
249
|
-
fi
|
|
296
|
+
npm install -g --force --registry=https://registry.npmjs.org/ "vigthoria-cli@${CLI_VERSION}"
|
|
250
297
|
fi
|
|
298
|
+
else
|
|
299
|
+
echo -e "${RED}✗ No checksum-verified artifact or exact npm release ${CLI_VERSION} is available${NC}"
|
|
300
|
+
return 1
|
|
251
301
|
fi
|
|
252
302
|
|
|
253
303
|
echo -e "${GREEN}✓ Installation complete${NC}"
|
|
@@ -280,55 +330,36 @@ create_symlinks() {
|
|
|
280
330
|
# Setup shell completion
|
|
281
331
|
setup_completion() {
|
|
282
332
|
echo -e "${CYAN}Setting up shell completion...${NC}"
|
|
283
|
-
|
|
284
|
-
|
|
333
|
+
COMPLETION_ROOT="$INSTALLER_ROOT/completions"
|
|
334
|
+
if [[ ! -d "$COMPLETION_ROOT" ]] && [[ -d "$HOME/.vigthoria/cli/current/node_modules/vigthoria-cli/completions" ]]; then
|
|
335
|
+
COMPLETION_ROOT="$HOME/.vigthoria/cli/current/node_modules/vigthoria-cli/completions"
|
|
336
|
+
fi
|
|
337
|
+
if [[ ! -d "$COMPLETION_ROOT" ]]; then
|
|
338
|
+
echo -e "${YELLOW}⚠ Generated completions are unavailable; no stale static list was installed.${NC}"
|
|
339
|
+
return 0
|
|
340
|
+
fi
|
|
285
341
|
SHELL_NAME=$(basename "$SHELL")
|
|
286
|
-
|
|
287
342
|
case "$SHELL_NAME" in
|
|
288
343
|
bash)
|
|
289
344
|
COMPLETION_FILE="$HOME/.bash_completion.d/vigthoria"
|
|
290
345
|
mkdir -p "$HOME/.bash_completion.d"
|
|
291
|
-
|
|
292
|
-
_vigthoria_completions() {
|
|
293
|
-
local cur="${COMP_WORDS[COMP_CWORD]}"
|
|
294
|
-
local commands="chat edit generate explain fix review login logout status config init"
|
|
295
|
-
COMPREPLY=($(compgen -W "$commands" -- "$cur"))
|
|
296
|
-
}
|
|
297
|
-
complete -F _vigthoria_completions vigthoria
|
|
298
|
-
complete -F _vigthoria_completions vig
|
|
299
|
-
EOF
|
|
346
|
+
install -m 0644 "$COMPLETION_ROOT/vigthoria.bash" "$COMPLETION_FILE"
|
|
300
347
|
echo -e "${GREEN}✓ Bash completion installed${NC}"
|
|
301
348
|
echo " Run: source ~/.bash_completion.d/vigthoria"
|
|
302
349
|
;;
|
|
303
350
|
zsh)
|
|
304
351
|
COMPLETION_FILE="$HOME/.zsh/completion/_vigthoria"
|
|
305
352
|
mkdir -p "$HOME/.zsh/completion"
|
|
306
|
-
|
|
307
|
-
#compdef vigthoria vig
|
|
308
|
-
|
|
309
|
-
_vigthoria() {
|
|
310
|
-
local -a commands
|
|
311
|
-
commands=(
|
|
312
|
-
'chat:Start interactive chat with AI'
|
|
313
|
-
'edit:Edit a file with AI assistance'
|
|
314
|
-
'generate:Generate code from description'
|
|
315
|
-
'explain:Explain code in a file'
|
|
316
|
-
'fix:Fix issues in a file'
|
|
317
|
-
'review:Review code quality'
|
|
318
|
-
'login:Login to Vigthoria'
|
|
319
|
-
'logout:Logout from Vigthoria'
|
|
320
|
-
'status:Show account status'
|
|
321
|
-
'config:Configure settings'
|
|
322
|
-
'init:Initialize project'
|
|
323
|
-
)
|
|
324
|
-
_describe 'command' commands
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
_vigthoria "$@"
|
|
328
|
-
EOF
|
|
353
|
+
install -m 0644 "$COMPLETION_ROOT/_vigthoria" "$COMPLETION_FILE"
|
|
329
354
|
echo -e "${GREEN}✓ Zsh completion installed${NC}"
|
|
330
355
|
echo " Add to ~/.zshrc: fpath=(~/.zsh/completion \$fpath)"
|
|
331
356
|
;;
|
|
357
|
+
fish)
|
|
358
|
+
COMPLETION_FILE="$HOME/.config/fish/completions/vigthoria.fish"
|
|
359
|
+
mkdir -p "$HOME/.config/fish/completions"
|
|
360
|
+
install -m 0644 "$COMPLETION_ROOT/vigthoria.fish" "$COMPLETION_FILE"
|
|
361
|
+
echo -e "${GREEN}✓ Fish completion installed${NC}"
|
|
362
|
+
;;
|
|
332
363
|
*)
|
|
333
364
|
echo -e "${YELLOW}⚠ Shell completion not available for $SHELL_NAME${NC}"
|
|
334
365
|
;;
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigthoria-cli",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.23",
|
|
4
4
|
"description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
|
+
"completions",
|
|
10
|
+
"release-policy.json",
|
|
9
11
|
"scripts/release",
|
|
10
12
|
"README.md",
|
|
11
13
|
"SECURITY_HARDENING.md",
|
|
@@ -16,6 +18,8 @@
|
|
|
16
18
|
"publishConfig": {
|
|
17
19
|
"files": [
|
|
18
20
|
"dist/",
|
|
21
|
+
"completions/",
|
|
22
|
+
"release-policy.json",
|
|
19
23
|
"scripts/release/",
|
|
20
24
|
"README.md",
|
|
21
25
|
"SECURITY_HARDENING.md",
|
|
@@ -32,10 +36,14 @@
|
|
|
32
36
|
},
|
|
33
37
|
"scripts": {
|
|
34
38
|
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
35
|
-
"build": "npm run clean && tsc && node -e \"const fs=require('fs'); try { fs.chmodSync('dist/index.js', 0o755); } catch (error) { if (!error || error.code !== 'ENOENT') throw error; }\"",
|
|
39
|
+
"build": "npm run clean && tsc && node scripts/release/generate-completions.mjs && node -e \"const fs=require('fs'); try { fs.chmodSync('dist/index.js', 0o755); } catch (error) { if (!error || error.code !== 'ENOENT') throw error; }\"",
|
|
36
40
|
"start": "node dist/index.js",
|
|
37
41
|
"dev": "ts-node src/index.ts",
|
|
38
|
-
"test": "npm run test:
|
|
42
|
+
"test": "npm run test:hermetic",
|
|
43
|
+
"test:hermetic": "npm run validate:no-go",
|
|
44
|
+
"test:integration:local": "npm run build && node scripts/run-test-suite.mjs local",
|
|
45
|
+
"test:live:all": "npm run build && node scripts/run-test-suite.mjs live",
|
|
46
|
+
"test:suite:policy": "node scripts/run-test-suite.mjs check",
|
|
39
47
|
"test:agent:outcome": "npm run build && node scripts/test-agent-run-outcome.js",
|
|
40
48
|
"test:cli": "npm run build && npm run precheck:services && node scripts/test-cli-suite.js && npm run test:agent:outcome && npm run test:v3-stream-mutation",
|
|
41
49
|
"test:regression": "npm run build && node scripts/test-regression-1.6.22.js",
|
|
@@ -62,6 +70,8 @@
|
|
|
62
70
|
"test:repo:live": "npm run build && node scripts/test-live-repo-e2e.js",
|
|
63
71
|
"test:repo:auth-fallback": "node scripts/test-community-repo-auth-fallback.mjs",
|
|
64
72
|
"test:repo:payload-fallback": "node scripts/test-repo-payload-fallback.mjs",
|
|
73
|
+
"test:repo:public-clone": "npm run build && node scripts/test-public-repo-clone.mjs",
|
|
74
|
+
"test:command:timeouts": "npm run build && node scripts/test-timeout-cancellation.mjs",
|
|
65
75
|
"test:game:live": "npm run build && node scripts/test-live-game-push.js",
|
|
66
76
|
"proof:agent": "npm run build && node scripts/proof-agent-mode.js",
|
|
67
77
|
"test:fresh-install": "node scripts/test-fresh-install.js",
|
|
@@ -69,6 +79,8 @@
|
|
|
69
79
|
"precheck:services": "node scripts/precheck-local-services.js",
|
|
70
80
|
"test:model:governance": "npm run build && node scripts/test-model-governance-no-agent.js",
|
|
71
81
|
"validate:no-go": "bash scripts/release/validate-no-go-gates.sh",
|
|
82
|
+
"test:model:balanced-live": "bash scripts/release/test-balanced-model-live.sh",
|
|
83
|
+
"test:release:live-services": "bash scripts/release/validate-live-service-gates.sh",
|
|
72
84
|
"test:legion:billing:e2e": "npm run build && node scripts/test-legion-godmode-billing-e2e.js",
|
|
73
85
|
"test:windows:v3-sync": "npm run build && node scripts/test-windows-v3-sync-recovery.js",
|
|
74
86
|
"test:v3-workspace-path": "npm run build && node scripts/test-v3-workspace-path.js",
|
|
@@ -79,7 +91,22 @@
|
|
|
79
91
|
"test:context:budget": "npm run build && node scripts/test-context-budget.js",
|
|
80
92
|
"test:v3-client-tool-quality": "npm run build && node scripts/test-v3-client-tool-quality.mjs",
|
|
81
93
|
"test:pitfall:context": "npm run build && node scripts/test-pitfall-context-smoke.js",
|
|
82
|
-
"test:game:command": "node scripts/test-game-command.mjs"
|
|
94
|
+
"test:game:command": "node scripts/test-game-command.mjs",
|
|
95
|
+
"test:security:dependencies": "node scripts/test-dependency-security.mjs",
|
|
96
|
+
"test:security:network": "npm run build && node scripts/test-network-policy.mjs && node scripts/test-installer-trust-policy.mjs",
|
|
97
|
+
"test:security:workspace": "npm run build && node scripts/test-workspace-archive-containment.mjs",
|
|
98
|
+
"test:security:process": "npm run build && node scripts/test-process-approval-safety.mjs",
|
|
99
|
+
"test:security:mutation-preview": "npm run build && node scripts/test-mutation-preview-transaction.mjs",
|
|
100
|
+
"test:security:context-secrets": "npm run build && node scripts/test-context-secret-hygiene.mjs",
|
|
101
|
+
"test:architecture:vigflow": "npm run build && node scripts/test-vigflow-client.mjs",
|
|
102
|
+
"test:state:durable": "npm run build && node scripts/test-durable-json-state.mjs",
|
|
103
|
+
"test:state:auth": "npm run build && node scripts/test-auth-state.mjs",
|
|
104
|
+
"test:state:sessions": "npm run build && node scripts/test-session-durable-lifecycle.mjs && node scripts/test-session-project-match.mjs && node scripts/test-external-client-resume.mjs",
|
|
105
|
+
"test:state:context": "npm run build && node scripts/test-context-state-ownership.mjs && node scripts/test-context-secret-hygiene.mjs",
|
|
106
|
+
"test:phase3:command-contract": "npm run build && node scripts/test-command-contract.mjs",
|
|
107
|
+
"test:phase3:update-policy": "npm run build && node scripts/test-update-policy.mjs",
|
|
108
|
+
"test:phase6:delivery": "npm run build && node scripts/test-release-delivery.mjs",
|
|
109
|
+
"architecture:graph": "node scripts/architecture/verify-import-graph.mjs"
|
|
83
110
|
},
|
|
84
111
|
"keywords": [
|
|
85
112
|
"ai",
|
|
@@ -93,7 +120,6 @@
|
|
|
93
120
|
"author": "Vigthoria Technologies",
|
|
94
121
|
"license": "MIT",
|
|
95
122
|
"dependencies": {
|
|
96
|
-
"archiver": "^8.0.0",
|
|
97
123
|
"axios": "^1.6.0",
|
|
98
124
|
"chalk": "^5.3.0",
|
|
99
125
|
"chokidar": "^5.0.0",
|
|
@@ -105,12 +131,9 @@
|
|
|
105
131
|
"marked": "^11.0.0",
|
|
106
132
|
"marked-terminal": "^6.2.0",
|
|
107
133
|
"ora": "^7.0.1",
|
|
108
|
-
"rxjs": "^7.8.2",
|
|
109
|
-
"simple-git": "^3.21.0",
|
|
110
134
|
"ws": "^8.14.2"
|
|
111
135
|
},
|
|
112
136
|
"devDependencies": {
|
|
113
|
-
"@types/archiver": "^6.0.2",
|
|
114
137
|
"@types/diff": "^5.0.8",
|
|
115
138
|
"@types/inquirer": "^9.0.7",
|
|
116
139
|
"@types/node": "^20.10.0",
|
|
@@ -119,11 +142,22 @@
|
|
|
119
142
|
"ts-node": "^10.9.2",
|
|
120
143
|
"typescript": "^5.3.2"
|
|
121
144
|
},
|
|
145
|
+
"peerDependencies": {
|
|
146
|
+
"puppeteer": "^24.40.0"
|
|
147
|
+
},
|
|
148
|
+
"peerDependenciesMeta": {
|
|
149
|
+
"puppeteer": {
|
|
150
|
+
"optional": true
|
|
151
|
+
}
|
|
152
|
+
},
|
|
122
153
|
"engines": {
|
|
123
154
|
"node": ">=20.19.0"
|
|
124
155
|
},
|
|
125
156
|
"overrides": {
|
|
126
157
|
"glob": "^13.0.6",
|
|
127
|
-
"brace-expansion": "
|
|
158
|
+
"brace-expansion": "5.0.9",
|
|
159
|
+
"fast-uri": "3.1.5",
|
|
160
|
+
"ip-address": "10.3.1",
|
|
161
|
+
"js-yaml": "4.3.1"
|
|
128
162
|
}
|
|
129
163
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"packageName": "vigthoria-cli",
|
|
4
|
+
"manifest": {
|
|
5
|
+
"schemaVersion": 1,
|
|
6
|
+
"maximumBytes": 262144,
|
|
7
|
+
"requiredChannels": ["stable"],
|
|
8
|
+
"allowedChannels": ["stable", "candidate"]
|
|
9
|
+
},
|
|
10
|
+
"origins": {
|
|
11
|
+
"manifest": "https://extension.vigthoria.io/downloads/manifest.json",
|
|
12
|
+
"artifacts": "https://extension.vigthoria.io/downloads/",
|
|
13
|
+
"allowedHosts": [
|
|
14
|
+
"extension.vigthoria.io",
|
|
15
|
+
"cli.vigthoria.io",
|
|
16
|
+
"coder.vigthoria.io",
|
|
17
|
+
"landing.vigthoria.io",
|
|
18
|
+
"market.vigthoria.io"
|
|
19
|
+
],
|
|
20
|
+
"port": 443,
|
|
21
|
+
"maximumRedirects": 0
|
|
22
|
+
},
|
|
23
|
+
"artifact": {
|
|
24
|
+
"maximumBytes": 104857600,
|
|
25
|
+
"filenamePattern": "^vigthoria-cli-(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?\\.tgz$"
|
|
26
|
+
},
|
|
27
|
+
"signature": {
|
|
28
|
+
"algorithm": "Ed25519",
|
|
29
|
+
"trustedKeys": {
|
|
30
|
+
"vigthoria-release-2026-01": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAotTXdcHwZ+D1z5lJMdgAAeMU99BRdMCaCZ465DN2aug=\n-----END PUBLIC KEY-----\n"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"channels": {
|
|
34
|
+
"stable": { "allowPrerelease": false, "allowDowngrade": false },
|
|
35
|
+
"candidate": { "allowPrerelease": true, "allowDowngrade": false }
|
|
36
|
+
},
|
|
37
|
+
"installation": {
|
|
38
|
+
"versionsDirectory": ".vigthoria/cli/versions",
|
|
39
|
+
"currentLink": ".vigthoria/cli/current",
|
|
40
|
+
"binDirectory": ".local/bin",
|
|
41
|
+
"preservePrevious": 1
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
7
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(root, 'contracts/phase-0/command-manifest.json'), 'utf8'));
|
|
8
|
+
const commands = manifest.commands
|
|
9
|
+
.filter((command) => !command.path.includes(' '))
|
|
10
|
+
.map((command) => command.path)
|
|
11
|
+
.sort();
|
|
12
|
+
const descriptions = new Map(manifest.commands.filter((command) => !command.path.includes(' ')).map((command) => [command.path, command.description || 'Vigthoria command']));
|
|
13
|
+
if (commands.length !== new Set(commands).size || commands.length === 0) throw new Error('Authoritative command manifest has duplicate or missing top-level commands.');
|
|
14
|
+
|
|
15
|
+
const bash = `# Generated from contracts/phase-0/command-manifest.json; do not edit.\n_vigthoria_completions() {\n local cur="\${COMP_WORDS[COMP_CWORD]}"\n COMPREPLY=( $(compgen -W '${commands.join(' ')}' -- "$cur") )\n}\ncomplete -F _vigthoria_completions vigthoria vig vigthoria-chat\n`;
|
|
16
|
+
const zshRows = commands.map((command) => ` '${command.replaceAll("'", "''")}:${String(descriptions.get(command)).replaceAll("'", "''")}'`).join('\n');
|
|
17
|
+
const zsh = `#compdef vigthoria vig vigthoria-chat\n# Generated from contracts/phase-0/command-manifest.json; do not edit.\n_vigthoria() {\n local -a commands\n commands=(\n${zshRows}\n )\n _describe 'command' commands\n}\n_vigthoria "$@"\n`;
|
|
18
|
+
const fish = `# Generated from contracts/phase-0/command-manifest.json; do not edit.\n${commands.map((command) => `complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a '${command}' -d '${String(descriptions.get(command)).replaceAll("'", "\\'")}'`).join('\n')}\n`;
|
|
19
|
+
const output = path.join(root, 'completions');
|
|
20
|
+
fs.mkdirSync(output, { recursive: true });
|
|
21
|
+
fs.writeFileSync(path.join(output, 'vigthoria.bash'), bash);
|
|
22
|
+
fs.writeFileSync(path.join(output, '_vigthoria'), zsh);
|
|
23
|
+
fs.writeFileSync(path.join(output, 'vigthoria.fish'), fish);
|
|
24
|
+
console.log(`Generated bash, zsh, and fish completion definitions for ${commands.length} commands.`);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { installReleaseTransaction } from '../../dist/utils/release-install.js';
|
|
3
|
+
|
|
4
|
+
const packageSpec = String(process.argv[2] || '');
|
|
5
|
+
const expectedVersion = String(process.argv[3] || '');
|
|
6
|
+
if (!packageSpec || !expectedVersion) throw new Error('Usage: install-release.mjs <package-spec> <expected-version>');
|
|
7
|
+
const result = installReleaseTransaction(packageSpec, expectedVersion, {
|
|
8
|
+
...(packageSpec.startsWith('vigthoria-cli@') ? { npmRegistry: 'https://registry.npmjs.org/' } : {}),
|
|
9
|
+
});
|
|
10
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { createHash, createPrivateKey, createPublicKey, sign } from 'node:crypto';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import {
|
|
8
|
+
getReleasePolicy,
|
|
9
|
+
parseReleaseManifest,
|
|
10
|
+
releaseSignaturePayload,
|
|
11
|
+
verifyReleaseSignature,
|
|
12
|
+
} from '../../dist/utils/release-policy.js';
|
|
13
|
+
|
|
14
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
15
|
+
const version = String(process.argv[2] || '').trim();
|
|
16
|
+
const channel = String(process.env.CHANNEL || 'stable').trim();
|
|
17
|
+
const downloadsDirectory = String(process.env.HOST_DOWNLOADS_DIR || '');
|
|
18
|
+
const manifestFile = String(process.env.HOST_MANIFEST_FILE || '');
|
|
19
|
+
const privateKeyFile = String(process.env.RELEASE_SIGNING_PRIVATE_KEY_FILE || '');
|
|
20
|
+
const keyId = String(process.env.RELEASE_SIGNING_KEY_ID || '');
|
|
21
|
+
const sbomFile = String(process.env.RELEASE_SBOM_FILE || '');
|
|
22
|
+
const provenanceFile = String(process.env.RELEASE_PROVENANCE_FILE || '');
|
|
23
|
+
const policy = getReleasePolicy();
|
|
24
|
+
|
|
25
|
+
function stop(message) { throw new Error(message); }
|
|
26
|
+
function digest(file) { return createHash('sha256').update(fs.readFileSync(file)).digest('hex'); }
|
|
27
|
+
function requiredFile(file, label) { if (!file || !fs.statSync(file, { throwIfNoEntry: false })?.isFile()) stop(`${label} is required: ${file || '(unset)'}`); }
|
|
28
|
+
function exactPackageMetadata(archive) {
|
|
29
|
+
const result = spawnSync('tar', ['-xOf', archive, 'package/package.json'], {
|
|
30
|
+
cwd: root, encoding: 'utf8', timeout: 15_000, maxBuffer: 1024 * 1024,
|
|
31
|
+
});
|
|
32
|
+
if (result.status !== 0) stop(`Unable to inspect archive metadata: ${result.stderr || result.stdout}`);
|
|
33
|
+
const metadata = JSON.parse(result.stdout);
|
|
34
|
+
return { name: String(metadata.name || ''), version: String(metadata.version || '') };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!version) stop('Usage: publish-cli-release.sh <version>');
|
|
38
|
+
if (!downloadsDirectory || !manifestFile) stop('HOST_DOWNLOADS_DIR and HOST_MANIFEST_FILE are required.');
|
|
39
|
+
requiredFile(privateKeyFile, 'RELEASE_SIGNING_PRIVATE_KEY_FILE');
|
|
40
|
+
requiredFile(sbomFile, 'RELEASE_SBOM_FILE');
|
|
41
|
+
requiredFile(provenanceFile, 'RELEASE_PROVENANCE_FILE');
|
|
42
|
+
if (!Object.hasOwn(policy.signature.trustedKeys, keyId)) stop(`RELEASE_SIGNING_KEY_ID is not trusted by release-policy.json: ${keyId || '(unset)'}`);
|
|
43
|
+
|
|
44
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
45
|
+
const lock = JSON.parse(fs.readFileSync(path.join(root, 'package-lock.json'), 'utf8'));
|
|
46
|
+
if ([pkg.version, lock.version, lock.packages?.['']?.version].some((identity) => identity !== version)) stop('Requested version conflicts with package.json or package-lock.json.');
|
|
47
|
+
const runtime = spawnSync(process.execPath, ['dist/index.js', '--version'], { cwd: root, encoding: 'utf8', env: { ...process.env, VIGTHORIA_OFFLINE: '1', VIGTHORIA_NO_BANNER: '1' } });
|
|
48
|
+
if (runtime.status !== 0 || runtime.stdout.trim() !== version) stop('Requested version conflicts with the built CLI banner.');
|
|
49
|
+
|
|
50
|
+
const archiveFilename = `${policy.packageName}-${version}.tgz`;
|
|
51
|
+
const archive = path.join(root, archiveFilename);
|
|
52
|
+
requiredFile(archive, 'Release archive');
|
|
53
|
+
const metadata = exactPackageMetadata(archive);
|
|
54
|
+
if (metadata.name !== policy.packageName || metadata.version !== version) stop('Requested version conflicts with archive metadata.');
|
|
55
|
+
|
|
56
|
+
fs.mkdirSync(downloadsDirectory, { recursive: true });
|
|
57
|
+
fs.mkdirSync(path.dirname(manifestFile), { recursive: true });
|
|
58
|
+
const lockPath = `${manifestFile}.lock`;
|
|
59
|
+
let lockHandle;
|
|
60
|
+
const published = [];
|
|
61
|
+
try {
|
|
62
|
+
lockHandle = fs.openSync(lockPath, 'wx', 0o600);
|
|
63
|
+
const suffix = `${process.pid}-${Date.now()}`;
|
|
64
|
+
const publicBase = new URL(policy.origins.artifacts);
|
|
65
|
+
const signatureFilename = `${archiveFilename}.sig`;
|
|
66
|
+
const sbomFilename = `${archiveFilename}.sbom.json`;
|
|
67
|
+
const provenanceFilename = `${archiveFilename}.provenance.json`;
|
|
68
|
+
const entry = {
|
|
69
|
+
version,
|
|
70
|
+
url: new URL(archiveFilename, publicBase).toString(),
|
|
71
|
+
sha256: digest(archive),
|
|
72
|
+
size: fs.statSync(archive).size,
|
|
73
|
+
archiveFilename,
|
|
74
|
+
packageName: policy.packageName,
|
|
75
|
+
packageVersion: version,
|
|
76
|
+
publishedAt: new Date().toISOString(),
|
|
77
|
+
signature: { algorithm: policy.signature.algorithm, keyId, url: new URL(signatureFilename, publicBase).toString() },
|
|
78
|
+
sbom: { url: new URL(sbomFilename, publicBase).toString(), sha256: digest(sbomFile) },
|
|
79
|
+
provenance: { url: new URL(provenanceFilename, publicBase).toString(), sha256: digest(provenanceFile) },
|
|
80
|
+
notes: String(process.env.RELEASE_NOTES || 'Vigthoria CLI release'),
|
|
81
|
+
};
|
|
82
|
+
const privateKey = createPrivateKey(fs.readFileSync(privateKeyFile));
|
|
83
|
+
const configuredPublic = createPublicKey(policy.signature.trustedKeys[keyId]).export({ type: 'spki', format: 'der' });
|
|
84
|
+
const signingPublic = createPublicKey(privateKey).export({ type: 'spki', format: 'der' });
|
|
85
|
+
if (!configuredPublic.equals(signingPublic)) stop('Signing private key does not match the configured verification key.');
|
|
86
|
+
const detached = sign(null, releaseSignaturePayload(channel, entry), privateKey).toString('base64');
|
|
87
|
+
verifyReleaseSignature(channel, entry, detached);
|
|
88
|
+
|
|
89
|
+
let manifest = { schemaVersion: policy.manifest.schemaVersion, channels: {} };
|
|
90
|
+
if (fs.existsSync(manifestFile)) manifest = JSON.parse(fs.readFileSync(manifestFile, 'utf8'));
|
|
91
|
+
manifest.channels = { ...manifest.channels, [channel]: entry };
|
|
92
|
+
parseReleaseManifest(manifest, channel);
|
|
93
|
+
|
|
94
|
+
const inputs = [[archive, archiveFilename], [sbomFile, sbomFilename], [provenanceFile, provenanceFilename]];
|
|
95
|
+
const staged = [];
|
|
96
|
+
for (const [source, filename] of inputs) {
|
|
97
|
+
const temporary = path.join(downloadsDirectory, `.${filename}.${suffix}.tmp`);
|
|
98
|
+
fs.copyFileSync(source, temporary, fs.constants.COPYFILE_EXCL);
|
|
99
|
+
staged.push([temporary, path.join(downloadsDirectory, filename)]);
|
|
100
|
+
}
|
|
101
|
+
const signatureTemporary = path.join(downloadsDirectory, `.${signatureFilename}.${suffix}.tmp`);
|
|
102
|
+
fs.writeFileSync(signatureTemporary, `${detached}\n`, { flag: 'wx', mode: 0o644 });
|
|
103
|
+
staged.push([signatureTemporary, path.join(downloadsDirectory, signatureFilename)]);
|
|
104
|
+
for (const [, destination] of staged) if (fs.existsSync(destination)) stop(`Refusing to overwrite published release component: ${destination}`);
|
|
105
|
+
for (const [temporary, destination] of staged) { fs.renameSync(temporary, destination); published.push(destination); }
|
|
106
|
+
const manifestTemporary = `${manifestFile}.${suffix}.tmp`;
|
|
107
|
+
fs.writeFileSync(manifestTemporary, `${JSON.stringify(manifest, null, 2)}\n`, { flag: 'wx', mode: 0o644 });
|
|
108
|
+
fs.renameSync(manifestTemporary, manifestFile);
|
|
109
|
+
console.log(JSON.stringify({ status: 'published', channel, version, sha256: entry.sha256, size: entry.size, manifestFile }, null, 2));
|
|
110
|
+
} catch (error) {
|
|
111
|
+
for (const file of published.reverse()) { try { fs.unlinkSync(file); } catch {} }
|
|
112
|
+
throw error;
|
|
113
|
+
} finally {
|
|
114
|
+
if (lockHandle !== undefined) fs.closeSync(lockHandle);
|
|
115
|
+
try { fs.unlinkSync(lockPath); } catch {}
|
|
116
|
+
}
|