@astrasyncai/verification-gateway 5.17.2 → 5.18.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/CHANGELOG.md +1878 -0
- package/README.md +141 -7
- package/dist/adapters/express.d.mts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +30 -12
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +30 -12
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/kit-express.d.mts +63 -0
- package/dist/adapters/kit-express.d.ts +63 -0
- package/dist/adapters/kit-express.js +88 -0
- package/dist/adapters/kit-express.js.map +1 -0
- package/dist/adapters/kit-express.mjs +61 -0
- package/dist/adapters/kit-express.mjs.map +1 -0
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.d.ts +1 -1
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +1 -1
- package/dist/adapters/nextjs.d.ts +1 -1
- package/dist/adapters/nextjs.js +18 -8
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +18 -8
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +1 -1
- package/dist/adapters/sdk.d.ts +1 -1
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +1 -1
- package/dist/bin/astrasync-codex-hook.js +1 -1
- package/dist/bin/astrasync-guard.js +330 -112
- package/dist/bin/astrasync.js +359 -113
- package/dist/browser/background.js +1 -1
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +1 -1
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +1 -1
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +1 -1
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +1 -1
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +1 -1
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +1 -1
- package/dist/edge-config.d.ts +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +5 -4
- package/dist/edge-core/index.d.ts +5 -4
- package/dist/edge-core/index.js +18 -8
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +18 -8
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +1 -1
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +1 -1
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +1 -1
- package/dist/git-trigger/git-hooks.d.ts +1 -1
- package/dist/index.d.mts +391 -13
- package/dist/index.d.ts +391 -13
- package/dist/index.js +766 -230
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +749 -222
- package/dist/index.mjs.map +1 -1
- package/dist/registration/index.d.mts +1 -1
- package/dist/registration/index.d.ts +1 -1
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.d.mts +4 -3
- package/dist/transport/index.d.ts +4 -3
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-vNBvYD7Z.d.mts → types-3ObBpsnf.d.mts} +7 -0
- package/dist/{types-DA8LzAOB.d.ts → types-BoxZEYPS.d.ts} +7 -0
- package/dist/{types-DRb_plOh.d.mts → types-Cns4l8gX.d.mts} +17 -0
- package/dist/{types-DRb_plOh.d.ts → types-Cns4l8gX.d.ts} +17 -0
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/verify.d.mts +1 -1
- package/dist/verify.d.ts +1 -1
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +8 -2
package/dist/bin/astrasync.js
CHANGED
|
@@ -36,7 +36,7 @@ var SDK_VERSION;
|
|
|
36
36
|
var init_version = __esm({
|
|
37
37
|
"src/version.ts"() {
|
|
38
38
|
"use strict";
|
|
39
|
-
SDK_VERSION = "5.
|
|
39
|
+
SDK_VERSION = "5.18.1";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -3474,115 +3474,115 @@ function validatePolicy(policy) {
|
|
|
3474
3474
|
}
|
|
3475
3475
|
return { valid: errors.length === 0, errors };
|
|
3476
3476
|
}
|
|
3477
|
-
function validatePurpose(purpose,
|
|
3477
|
+
function validatePurpose(purpose, path3) {
|
|
3478
3478
|
const errors = [];
|
|
3479
3479
|
if (!purpose || typeof purpose !== "object") {
|
|
3480
|
-
return [{ path:
|
|
3480
|
+
return [{ path: path3, message: "purpose must be an object" }];
|
|
3481
3481
|
}
|
|
3482
3482
|
const p = purpose;
|
|
3483
3483
|
if (typeof p.id !== "string" || !p.id) {
|
|
3484
|
-
errors.push({ path: `${
|
|
3484
|
+
errors.push({ path: `${path3}.id`, message: "id is required and must be a non-empty string" });
|
|
3485
3485
|
}
|
|
3486
3486
|
if (typeof p.allowed !== "boolean") {
|
|
3487
|
-
errors.push({ path: `${
|
|
3487
|
+
errors.push({ path: `${path3}.allowed`, message: "allowed is required and must be a boolean" });
|
|
3488
3488
|
}
|
|
3489
3489
|
if (p.targets !== void 0 && !isStringArray(p.targets)) {
|
|
3490
|
-
errors.push({ path: `${
|
|
3490
|
+
errors.push({ path: `${path3}.targets`, message: "targets must be an array of strings" });
|
|
3491
3491
|
}
|
|
3492
3492
|
if (p.blockedPatterns !== void 0 && !isStringArray(p.blockedPatterns)) {
|
|
3493
3493
|
errors.push({
|
|
3494
|
-
path: `${
|
|
3494
|
+
path: `${path3}.blockedPatterns`,
|
|
3495
3495
|
message: "blockedPatterns must be an array of strings"
|
|
3496
3496
|
});
|
|
3497
3497
|
}
|
|
3498
3498
|
if (p.requiresApproval !== void 0 && typeof p.requiresApproval !== "boolean") {
|
|
3499
3499
|
errors.push({
|
|
3500
|
-
path: `${
|
|
3500
|
+
path: `${path3}.requiresApproval`,
|
|
3501
3501
|
message: "requiresApproval must be a boolean"
|
|
3502
3502
|
});
|
|
3503
3503
|
}
|
|
3504
3504
|
return errors;
|
|
3505
3505
|
}
|
|
3506
|
-
function validateScope(scope,
|
|
3506
|
+
function validateScope(scope, path3) {
|
|
3507
3507
|
const errors = [];
|
|
3508
3508
|
if (typeof scope !== "object" || scope === null) {
|
|
3509
|
-
return [{ path:
|
|
3509
|
+
return [{ path: path3, message: "scope must be an object" }];
|
|
3510
3510
|
}
|
|
3511
3511
|
const s = scope;
|
|
3512
3512
|
for (const field of ["allowedDomains", "blockedDomains", "blockedResources"]) {
|
|
3513
3513
|
if (s[field] !== void 0 && !isStringArray(s[field])) {
|
|
3514
|
-
errors.push({ path: `${
|
|
3514
|
+
errors.push({ path: `${path3}.${field}`, message: `${field} must be an array of strings` });
|
|
3515
3515
|
}
|
|
3516
3516
|
}
|
|
3517
3517
|
return errors;
|
|
3518
3518
|
}
|
|
3519
|
-
function validateLimits(limits,
|
|
3519
|
+
function validateLimits(limits, path3) {
|
|
3520
3520
|
const errors = [];
|
|
3521
3521
|
if (typeof limits !== "object" || limits === null) {
|
|
3522
|
-
return [{ path:
|
|
3522
|
+
return [{ path: path3, message: "limits must be an object" }];
|
|
3523
3523
|
}
|
|
3524
3524
|
const l = limits;
|
|
3525
3525
|
if (l.autonomousThreshold !== void 0 && typeof l.autonomousThreshold !== "number") {
|
|
3526
3526
|
errors.push({
|
|
3527
|
-
path: `${
|
|
3527
|
+
path: `${path3}.autonomousThreshold`,
|
|
3528
3528
|
message: "autonomousThreshold must be a number"
|
|
3529
3529
|
});
|
|
3530
3530
|
}
|
|
3531
3531
|
if (l.maxTransactionAmount !== void 0 && typeof l.maxTransactionAmount !== "number") {
|
|
3532
3532
|
errors.push({
|
|
3533
|
-
path: `${
|
|
3533
|
+
path: `${path3}.maxTransactionAmount`,
|
|
3534
3534
|
message: "maxTransactionAmount must be a number"
|
|
3535
3535
|
});
|
|
3536
3536
|
}
|
|
3537
3537
|
if (typeof l.autonomousThreshold === "number" && typeof l.maxTransactionAmount === "number" && l.autonomousThreshold > l.maxTransactionAmount) {
|
|
3538
3538
|
errors.push({
|
|
3539
|
-
path: `${
|
|
3539
|
+
path: `${path3}.autonomousThreshold`,
|
|
3540
3540
|
message: "autonomousThreshold (Autonomous Limit) must be <= maxTransactionAmount (Hard Limit)"
|
|
3541
3541
|
});
|
|
3542
3542
|
}
|
|
3543
3543
|
if (l.maxRequestsPerHour !== void 0 && typeof l.maxRequestsPerHour !== "number") {
|
|
3544
3544
|
errors.push({
|
|
3545
|
-
path: `${
|
|
3545
|
+
path: `${path3}.maxRequestsPerHour`,
|
|
3546
3546
|
message: "maxRequestsPerHour must be a number"
|
|
3547
3547
|
});
|
|
3548
3548
|
}
|
|
3549
3549
|
if (l.currency !== void 0 && typeof l.currency !== "string") {
|
|
3550
|
-
errors.push({ path: `${
|
|
3550
|
+
errors.push({ path: `${path3}.currency`, message: "currency must be a string" });
|
|
3551
3551
|
}
|
|
3552
3552
|
return errors;
|
|
3553
3553
|
}
|
|
3554
|
-
function validateRiskThresholds(thresholds,
|
|
3554
|
+
function validateRiskThresholds(thresholds, path3) {
|
|
3555
3555
|
const errors = [];
|
|
3556
3556
|
if (typeof thresholds !== "object" || thresholds === null) {
|
|
3557
|
-
return [{ path:
|
|
3557
|
+
return [{ path: path3, message: "riskThresholds must be an object" }];
|
|
3558
3558
|
}
|
|
3559
3559
|
const t = thresholds;
|
|
3560
3560
|
for (const range of ["autoAllow", "requireApproval", "autoBlock"]) {
|
|
3561
3561
|
if (!t[range] || typeof t[range] !== "object") {
|
|
3562
3562
|
errors.push({
|
|
3563
|
-
path: `${
|
|
3563
|
+
path: `${path3}.${range}`,
|
|
3564
3564
|
message: `${range} is required and must be an object with min and max`
|
|
3565
3565
|
});
|
|
3566
3566
|
continue;
|
|
3567
3567
|
}
|
|
3568
3568
|
const r = t[range];
|
|
3569
3569
|
if (typeof r.min !== "number" || typeof r.max !== "number") {
|
|
3570
|
-
errors.push({ path: `${
|
|
3570
|
+
errors.push({ path: `${path3}.${range}`, message: `${range} must have numeric min and max` });
|
|
3571
3571
|
} else if (r.min > r.max) {
|
|
3572
|
-
errors.push({ path: `${
|
|
3572
|
+
errors.push({ path: `${path3}.${range}`, message: `${range}.min must be <= ${range}.max` });
|
|
3573
3573
|
}
|
|
3574
3574
|
}
|
|
3575
3575
|
if (isValidThresholdShape(t)) {
|
|
3576
3576
|
const thresholdObj = t;
|
|
3577
3577
|
if (thresholdObj.autoAllow.max + 1 !== thresholdObj.requireApproval.min) {
|
|
3578
3578
|
errors.push({
|
|
3579
|
-
path: `${
|
|
3579
|
+
path: `${path3}`,
|
|
3580
3580
|
message: `Gap between autoAllow.max (${thresholdObj.autoAllow.max}) and requireApproval.min (${thresholdObj.requireApproval.min}). Ranges must be contiguous.`
|
|
3581
3581
|
});
|
|
3582
3582
|
}
|
|
3583
3583
|
if (thresholdObj.requireApproval.max + 1 !== thresholdObj.autoBlock.min) {
|
|
3584
3584
|
errors.push({
|
|
3585
|
-
path: `${
|
|
3585
|
+
path: `${path3}`,
|
|
3586
3586
|
message: `Gap between requireApproval.max (${thresholdObj.requireApproval.max}) and autoBlock.min (${thresholdObj.autoBlock.min}). Ranges must be contiguous.`
|
|
3587
3587
|
});
|
|
3588
3588
|
}
|
|
@@ -3962,8 +3962,8 @@ ${category.label}
|
|
|
3962
3962
|
async runAndSave(outputPath) {
|
|
3963
3963
|
const policy = await this.run();
|
|
3964
3964
|
const yaml2 = toYaml(policy);
|
|
3965
|
-
const
|
|
3966
|
-
|
|
3965
|
+
const fs3 = await import("fs");
|
|
3966
|
+
fs3.writeFileSync(outputPath, yaml2, "utf-8");
|
|
3967
3967
|
this.print(`
|
|
3968
3968
|
Policy saved to ${outputPath}`);
|
|
3969
3969
|
this.print(" AstraSync Local Guard is now protecting your agent.\n");
|
|
@@ -6644,6 +6644,13 @@ var init_report_amount = __esm({
|
|
|
6644
6644
|
}
|
|
6645
6645
|
});
|
|
6646
6646
|
|
|
6647
|
+
// src/ucp/kit-shared.ts
|
|
6648
|
+
var init_kit_shared = __esm({
|
|
6649
|
+
"src/ucp/kit-shared.ts"() {
|
|
6650
|
+
"use strict";
|
|
6651
|
+
}
|
|
6652
|
+
});
|
|
6653
|
+
|
|
6647
6654
|
// src/ucp/checkout-kit.ts
|
|
6648
6655
|
var import_jose3;
|
|
6649
6656
|
var init_checkout_kit = __esm({
|
|
@@ -6659,6 +6666,7 @@ var init_checkout_kit = __esm({
|
|
|
6659
6666
|
init_profile();
|
|
6660
6667
|
init_signatures();
|
|
6661
6668
|
init_report_amount();
|
|
6669
|
+
init_kit_shared();
|
|
6662
6670
|
}
|
|
6663
6671
|
});
|
|
6664
6672
|
|
|
@@ -6733,6 +6741,7 @@ var init_checkout_kit2 = __esm({
|
|
|
6733
6741
|
"use strict";
|
|
6734
6742
|
init_idempotency();
|
|
6735
6743
|
init_report_amount();
|
|
6744
|
+
init_kit_shared();
|
|
6736
6745
|
}
|
|
6737
6746
|
});
|
|
6738
6747
|
|
|
@@ -6744,6 +6753,14 @@ var init_acp2 = __esm({
|
|
|
6744
6753
|
}
|
|
6745
6754
|
});
|
|
6746
6755
|
|
|
6756
|
+
// src/adapters/kit-express.ts
|
|
6757
|
+
var init_kit_express = __esm({
|
|
6758
|
+
"src/adapters/kit-express.ts"() {
|
|
6759
|
+
"use strict";
|
|
6760
|
+
init_kit_shared();
|
|
6761
|
+
}
|
|
6762
|
+
});
|
|
6763
|
+
|
|
6747
6764
|
// src/http-signatures/index.ts
|
|
6748
6765
|
var init_http_signatures = __esm({
|
|
6749
6766
|
"src/http-signatures/index.ts"() {
|
|
@@ -6790,6 +6807,7 @@ var init_src = __esm({
|
|
|
6790
6807
|
init_payments();
|
|
6791
6808
|
init_aep();
|
|
6792
6809
|
init_acp2();
|
|
6810
|
+
init_kit_express();
|
|
6793
6811
|
init_mandates();
|
|
6794
6812
|
init_http_signatures();
|
|
6795
6813
|
init_idempotency();
|
|
@@ -7807,29 +7825,29 @@ function loadEnrolment(paths) {
|
|
|
7807
7825
|
[paths.machineDevice, "machine"],
|
|
7808
7826
|
[paths.userDevice, "user"]
|
|
7809
7827
|
];
|
|
7810
|
-
for (const [
|
|
7811
|
-
if (!(0, import_fs6.existsSync)(
|
|
7828
|
+
for (const [path3, scope] of candidates) {
|
|
7829
|
+
if (!(0, import_fs6.existsSync)(path3)) continue;
|
|
7812
7830
|
try {
|
|
7813
|
-
const parsed = JSON.parse((0, import_fs6.readFileSync)(
|
|
7831
|
+
const parsed = JSON.parse((0, import_fs6.readFileSync)(path3, "utf-8"));
|
|
7814
7832
|
if (isEnrolment(parsed)) return { enrolment: parsed, scope };
|
|
7815
7833
|
} catch {
|
|
7816
7834
|
}
|
|
7817
|
-
return { corrupt: true, path:
|
|
7835
|
+
return { corrupt: true, path: path3 };
|
|
7818
7836
|
}
|
|
7819
7837
|
return null;
|
|
7820
7838
|
}
|
|
7821
|
-
function writeFileMode(
|
|
7822
|
-
(0, import_fs6.mkdirSync)((0, import_path5.dirname)(
|
|
7823
|
-
(0, import_fs6.writeFileSync)(
|
|
7839
|
+
function writeFileMode(path3, content, mode) {
|
|
7840
|
+
(0, import_fs6.mkdirSync)((0, import_path5.dirname)(path3), { recursive: true, mode: 448 });
|
|
7841
|
+
(0, import_fs6.writeFileSync)(path3, content, { encoding: "utf-8", mode });
|
|
7824
7842
|
try {
|
|
7825
|
-
(0, import_fs6.chmodSync)(
|
|
7843
|
+
(0, import_fs6.chmodSync)(path3, mode);
|
|
7826
7844
|
} catch {
|
|
7827
7845
|
}
|
|
7828
7846
|
}
|
|
7829
7847
|
function saveEnrolment(paths, enrolment, scope) {
|
|
7830
|
-
const
|
|
7831
|
-
writeFileMode(
|
|
7832
|
-
return
|
|
7848
|
+
const path3 = scope === "machine" ? paths.machineDevice : paths.userDevice;
|
|
7849
|
+
writeFileMode(path3, JSON.stringify(enrolment, null, 2), scope === "machine" ? 420 : 384);
|
|
7850
|
+
return path3;
|
|
7833
7851
|
}
|
|
7834
7852
|
function readCachedPolicies(paths) {
|
|
7835
7853
|
const out = [];
|
|
@@ -8157,12 +8175,12 @@ function formatFleetStatus(status) {
|
|
|
8157
8175
|
if (status.lastError) lines.push(` Last sync error: ${status.lastError}`);
|
|
8158
8176
|
return lines;
|
|
8159
8177
|
}
|
|
8160
|
-
function managedHookCommand(target,
|
|
8178
|
+
function managedHookCommand(target, os3) {
|
|
8161
8179
|
const bin = target === "claude" ? "astrasync-claude-hook" : "astrasync-codex-hook";
|
|
8162
|
-
if (
|
|
8180
|
+
if (os3 === "win32") return `"C:\\Program Files\\nodejs\\${bin}.cmd"`;
|
|
8163
8181
|
return `/usr/local/bin/${bin}`;
|
|
8164
8182
|
}
|
|
8165
|
-
function buildClaudeManagedSettings(
|
|
8183
|
+
function buildClaudeManagedSettings(os3) {
|
|
8166
8184
|
return {
|
|
8167
8185
|
allowManagedHooksOnly: true,
|
|
8168
8186
|
env: { ASTRASYNC_FLEET_REQUIRED: "1" },
|
|
@@ -8170,7 +8188,7 @@ function buildClaudeManagedSettings(os2) {
|
|
|
8170
8188
|
PreToolUse: [
|
|
8171
8189
|
{
|
|
8172
8190
|
matcher: HOOK_MATCHER,
|
|
8173
|
-
hooks: [{ type: "command", command: managedHookCommand("claude",
|
|
8191
|
+
hooks: [{ type: "command", command: managedHookCommand("claude", os3), timeout: 10 }]
|
|
8174
8192
|
}
|
|
8175
8193
|
]
|
|
8176
8194
|
},
|
|
@@ -8180,11 +8198,11 @@ function buildClaudeManagedSettings(os2) {
|
|
|
8180
8198
|
function tomlString(value) {
|
|
8181
8199
|
return JSON.stringify(value);
|
|
8182
8200
|
}
|
|
8183
|
-
function buildCodexRequirementsToml(
|
|
8184
|
-
const command =
|
|
8201
|
+
function buildCodexRequirementsToml(os3) {
|
|
8202
|
+
const command = os3 === "win32" ? `set ASTRASYNC_FLEET_REQUIRED=1&& ${managedHookCommand("codex", os3)}` : `ASTRASYNC_FLEET_REQUIRED=1 ${managedHookCommand("codex", os3)}`;
|
|
8185
8203
|
return [
|
|
8186
8204
|
"# AstraSync Local Guard \u2014 managed hook (generated by `astrasync guard managed-settings --codex`)",
|
|
8187
|
-
`# Install at: ${MANAGED_SETTINGS_LOCATIONS.codex[
|
|
8205
|
+
`# Install at: ${MANAGED_SETTINGS_LOCATIONS.codex[os3]}`,
|
|
8188
8206
|
"allow_managed_hooks_only = true",
|
|
8189
8207
|
"",
|
|
8190
8208
|
"[features]",
|
|
@@ -8204,14 +8222,14 @@ function buildCodexRequirementsToml(os2) {
|
|
|
8204
8222
|
function buildManagedSettingsFiles(targets) {
|
|
8205
8223
|
const out = [];
|
|
8206
8224
|
for (const target of targets) {
|
|
8207
|
-
for (const
|
|
8208
|
-
const content = target === "claude" ? `${JSON.stringify(buildClaudeManagedSettings(
|
|
8209
|
-
` : buildCodexRequirementsToml(
|
|
8225
|
+
for (const os3 of ["darwin", "linux", "win32"]) {
|
|
8226
|
+
const content = target === "claude" ? `${JSON.stringify(buildClaudeManagedSettings(os3), null, 2)}
|
|
8227
|
+
` : buildCodexRequirementsToml(os3);
|
|
8210
8228
|
out.push({
|
|
8211
8229
|
target,
|
|
8212
|
-
os:
|
|
8213
|
-
installPath: MANAGED_SETTINGS_LOCATIONS[target][
|
|
8214
|
-
fileName: `${target}-${
|
|
8230
|
+
os: os3,
|
|
8231
|
+
installPath: MANAGED_SETTINGS_LOCATIONS[target][os3],
|
|
8232
|
+
fileName: `${target}-${os3}-${target === "claude" ? "managed-settings.json" : "requirements.toml"}`,
|
|
8215
8233
|
content
|
|
8216
8234
|
});
|
|
8217
8235
|
}
|
|
@@ -8417,7 +8435,8 @@ function createLocalCert(hosts, days = 30) {
|
|
|
8417
8435
|
${b64}
|
|
8418
8436
|
-----END CERTIFICATE-----
|
|
8419
8437
|
`,
|
|
8420
|
-
key: privateKey.export({ type: "pkcs8", format: "pem" }).toString()
|
|
8438
|
+
key: privateKey.export({ type: "pkcs8", format: "pem" }).toString(),
|
|
8439
|
+
spkiSha256: import_node_crypto5.default.createHash("sha256").update(spki).digest("base64")
|
|
8421
8440
|
};
|
|
8422
8441
|
}
|
|
8423
8442
|
var import_node_crypto5, tlv, seq2, set2, ctx, ECDSA_SHA256;
|
|
@@ -8433,16 +8452,204 @@ var init_local_cert = __esm({
|
|
|
8433
8452
|
}
|
|
8434
8453
|
});
|
|
8435
8454
|
|
|
8455
|
+
// src/fleet/open-browser.ts
|
|
8456
|
+
function isWsl(env = process.env, platform2 = process.platform, readVersion = () => import_node_fs.default.readFileSync("/proc/version", "utf8")) {
|
|
8457
|
+
if (platform2 !== "linux") return false;
|
|
8458
|
+
if (env.WSL_DISTRO_NAME) return true;
|
|
8459
|
+
try {
|
|
8460
|
+
return /microsoft/i.test(readVersion());
|
|
8461
|
+
} catch {
|
|
8462
|
+
return false;
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8465
|
+
function findChromium(env = process.env, platform2 = process.platform, exists = (p) => import_node_fs.default.existsSync(p), wsl = isWsl(env, platform2), listDir = (dir) => import_node_fs.default.readdirSync(dir)) {
|
|
8466
|
+
let candidates;
|
|
8467
|
+
if (platform2 === "darwin") {
|
|
8468
|
+
candidates = MAC_PATHS;
|
|
8469
|
+
} else if (platform2 === "win32") {
|
|
8470
|
+
const bases = [
|
|
8471
|
+
env.ProgramFiles,
|
|
8472
|
+
env["ProgramFiles(x86)"],
|
|
8473
|
+
env.LOCALAPPDATA ?? env.LocalAppData
|
|
8474
|
+
].filter((b) => !!b);
|
|
8475
|
+
candidates = [
|
|
8476
|
+
...bases.map((b) => import_node_path.default.win32.join(b, "Google", "Chrome", "Application", "chrome.exe")),
|
|
8477
|
+
...bases.map((b) => import_node_path.default.win32.join(b, "Microsoft", "Edge", "Application", "msedge.exe"))
|
|
8478
|
+
];
|
|
8479
|
+
} else {
|
|
8480
|
+
const dirs = (env.PATH ?? "").split(":").filter(Boolean);
|
|
8481
|
+
candidates = LINUX_NAMES.flatMap((n) => dirs.map((d) => import_node_path.default.posix.join(d, n)));
|
|
8482
|
+
const cache2 = env.PLAYWRIGHT_BROWSERS_PATH ?? (env.HOME ? `${env.HOME}/.cache/ms-playwright` : "");
|
|
8483
|
+
if (cache2) {
|
|
8484
|
+
let builds = [];
|
|
8485
|
+
try {
|
|
8486
|
+
builds = listDir(cache2).filter((d) => /^chromium-\d+$/.test(d));
|
|
8487
|
+
} catch {
|
|
8488
|
+
}
|
|
8489
|
+
builds.sort((a, b) => Number(b.split("-")[1]) - Number(a.split("-")[1]));
|
|
8490
|
+
for (const b of builds)
|
|
8491
|
+
candidates.push(
|
|
8492
|
+
import_node_path.default.posix.join(cache2, b, "chrome-linux64", "chrome"),
|
|
8493
|
+
import_node_path.default.posix.join(cache2, b, "chrome-linux", "chrome")
|
|
8494
|
+
);
|
|
8495
|
+
}
|
|
8496
|
+
if (wsl) candidates = [...candidates, ...WSL_WINDOWS_PATHS];
|
|
8497
|
+
}
|
|
8498
|
+
return candidates.find((c) => exists(c)) ?? null;
|
|
8499
|
+
}
|
|
8500
|
+
function isWindowsExeFromWsl(browserPath) {
|
|
8501
|
+
return /^\/mnt\/[a-z]\//i.test(browserPath) && /\.exe$/i.test(browserPath);
|
|
8502
|
+
}
|
|
8503
|
+
function browserName(browserPath) {
|
|
8504
|
+
const b = browserPath.toLowerCase();
|
|
8505
|
+
if (b.includes("edge")) return "Edge";
|
|
8506
|
+
if (b.includes("chromium")) return "Chromium";
|
|
8507
|
+
return "Chrome";
|
|
8508
|
+
}
|
|
8509
|
+
function profileDirFor(proxyPort) {
|
|
8510
|
+
return import_node_path.default.join(import_node_os.default.tmpdir(), `astrasync-agent-browser-${proxyPort}`);
|
|
8511
|
+
}
|
|
8512
|
+
function windowsProfileDir(profileDir) {
|
|
8513
|
+
if (/^\/mnt\/[a-z]\//i.test(profileDir)) {
|
|
8514
|
+
try {
|
|
8515
|
+
return (0, import_node_child_process.execFileSync)("wslpath", ["-w", profileDir], { encoding: "utf8" }).trim();
|
|
8516
|
+
} catch {
|
|
8517
|
+
}
|
|
8518
|
+
}
|
|
8519
|
+
return `C:\\Temp\\${import_node_path.default.basename(profileDir)}`;
|
|
8520
|
+
}
|
|
8521
|
+
function certFlag(certSpki) {
|
|
8522
|
+
return `--ignore-certificate-errors-spki-list=${certSpki}`;
|
|
8523
|
+
}
|
|
8524
|
+
function launchBrowser(browserPath, proxyPort, url, certSpki, profileDir = profileDirFor(proxyPort), onError) {
|
|
8525
|
+
const dir = isWindowsExeFromWsl(browserPath) ? windowsProfileDir(profileDir) : profileDir;
|
|
8526
|
+
const child = (0, import_node_child_process.spawn)(
|
|
8527
|
+
browserPath,
|
|
8528
|
+
[
|
|
8529
|
+
`--proxy-server=http://127.0.0.1:${proxyPort}`,
|
|
8530
|
+
certFlag(certSpki),
|
|
8531
|
+
`--user-data-dir=${dir}`,
|
|
8532
|
+
"--no-first-run",
|
|
8533
|
+
"--new-window",
|
|
8534
|
+
url
|
|
8535
|
+
],
|
|
8536
|
+
{ detached: true, stdio: "ignore" }
|
|
8537
|
+
);
|
|
8538
|
+
child.on("error", (err) => onError?.(err));
|
|
8539
|
+
child.unref();
|
|
8540
|
+
return child;
|
|
8541
|
+
}
|
|
8542
|
+
function browserCommand(platform2, port, url, certSpki, wsl = false) {
|
|
8543
|
+
const proxy = `--proxy-server="http://127.0.0.1:${port}" ${certFlag(certSpki)}`;
|
|
8544
|
+
if (platform2 === "win32" || wsl) {
|
|
8545
|
+
return `& "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ${proxy} --user-data-dir="$env:TEMP\\astrasync-agent-${port}" '${url}'`;
|
|
8546
|
+
}
|
|
8547
|
+
const exe = platform2 === "darwin" ? '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"' : "google-chrome";
|
|
8548
|
+
return `${exe} ${proxy} --user-data-dir="\${TMPDIR:-/tmp}/astrasync-agent-${port}" '${url}'`;
|
|
8549
|
+
}
|
|
8550
|
+
function browserCommandLines(platform2, port, url, certSpki, wsl = isWsl(process.env, platform2)) {
|
|
8551
|
+
if (wsl) {
|
|
8552
|
+
return [
|
|
8553
|
+
" In PowerShell (Windows):",
|
|
8554
|
+
` ${browserCommand("win32", port, url, certSpki)}`,
|
|
8555
|
+
" Or inside WSL (with Chromium installed):",
|
|
8556
|
+
` ${browserCommand("linux", port, url, certSpki)}`,
|
|
8557
|
+
` ${CERT_FLAG_NOTE}`
|
|
8558
|
+
];
|
|
8559
|
+
}
|
|
8560
|
+
return [` ${browserCommand(platform2, port, url, certSpki)}`, ` ${CERT_FLAG_NOTE}`];
|
|
8561
|
+
}
|
|
8562
|
+
function openThroughProxy(opts) {
|
|
8563
|
+
const log = opts.log ?? ((l) => console.log(l));
|
|
8564
|
+
const platform2 = opts.platform ?? process.platform;
|
|
8565
|
+
const env = opts.env ?? process.env;
|
|
8566
|
+
const wsl = opts.wsl ?? isWsl(env, platform2);
|
|
8567
|
+
const found = opts.find ? opts.find() : findChromium(env, platform2, void 0, wsl);
|
|
8568
|
+
if (!found) {
|
|
8569
|
+
log("No Chrome/Edge/Chromium found. Start one through the proxy with:");
|
|
8570
|
+
for (const l of browserCommandLines(platform2, opts.port, opts.url, opts.certSpki, wsl)) log(l);
|
|
8571
|
+
return false;
|
|
8572
|
+
}
|
|
8573
|
+
(opts.launch ?? launchBrowser)(
|
|
8574
|
+
found,
|
|
8575
|
+
opts.port,
|
|
8576
|
+
opts.url,
|
|
8577
|
+
opts.certSpki,
|
|
8578
|
+
profileDirFor(opts.port),
|
|
8579
|
+
(err) => log(`Couldn't start ${browserName(found)}: ${err.message}`)
|
|
8580
|
+
);
|
|
8581
|
+
log(`Opened ${browserName(found)} through the proxy.`);
|
|
8582
|
+
log(CERT_FLAG_NOTE);
|
|
8583
|
+
if (wsl && isWindowsExeFromWsl(found)) {
|
|
8584
|
+
log(
|
|
8585
|
+
"If the Windows browser can't reach the proxy, install Chromium inside WSL (e.g. npx playwright install chromium)."
|
|
8586
|
+
);
|
|
8587
|
+
}
|
|
8588
|
+
return true;
|
|
8589
|
+
}
|
|
8590
|
+
var import_node_child_process, import_node_fs, import_node_os, import_node_path, MAC_PATHS, LINUX_NAMES, WSL_WINDOWS_PATHS, CERT_FLAG_NOTE;
|
|
8591
|
+
var init_open_browser = __esm({
|
|
8592
|
+
"src/fleet/open-browser.ts"() {
|
|
8593
|
+
"use strict";
|
|
8594
|
+
import_node_child_process = require("child_process");
|
|
8595
|
+
import_node_fs = __toESM(require("fs"));
|
|
8596
|
+
import_node_os = __toESM(require("os"));
|
|
8597
|
+
import_node_path = __toESM(require("path"));
|
|
8598
|
+
MAC_PATHS = [
|
|
8599
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
8600
|
+
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
8601
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium"
|
|
8602
|
+
];
|
|
8603
|
+
LINUX_NAMES = [
|
|
8604
|
+
"google-chrome",
|
|
8605
|
+
"google-chrome-stable",
|
|
8606
|
+
"chromium",
|
|
8607
|
+
"chromium-browser",
|
|
8608
|
+
"microsoft-edge"
|
|
8609
|
+
];
|
|
8610
|
+
WSL_WINDOWS_PATHS = [
|
|
8611
|
+
"/mnt/c/Program Files/Google/Chrome/Application/chrome.exe",
|
|
8612
|
+
"/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
|
|
8613
|
+
"/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe",
|
|
8614
|
+
"/mnt/c/Program Files/Microsoft/Edge/Application/msedge.exe"
|
|
8615
|
+
];
|
|
8616
|
+
CERT_FLAG_NOTE = "Chrome shows a warning bar about the --ignore-certificate-errors-spki-list flag. That is expected (it trusts only this proxy's certificate); close the bar.";
|
|
8617
|
+
}
|
|
8618
|
+
});
|
|
8619
|
+
|
|
8436
8620
|
// src/fleet/browse-proxy.ts
|
|
8437
8621
|
function cleanHeaders(h) {
|
|
8438
8622
|
const out = {};
|
|
8439
8623
|
for (const [k, v] of Object.entries(h)) if (!HOP_BY_HOP.has(k) && v !== void 0) out[k] = v;
|
|
8440
8624
|
return out;
|
|
8441
8625
|
}
|
|
8626
|
+
function helpPage(port, certSpki) {
|
|
8627
|
+
const proxy = `http://127.0.0.1:${port}`;
|
|
8628
|
+
return `<!doctype html>
|
|
8629
|
+
<html lang="en"><head><meta charset="utf-8"><title>AstraSync device proxy</title>
|
|
8630
|
+
<style>body{font:16px/1.5 system-ui,sans-serif;max-width:40rem;margin:2rem auto;padding:0 1rem}code{background:#f2f2f2;padding:0 .25rem}</style>
|
|
8631
|
+
</head><body>
|
|
8632
|
+
<h1>AstraSync device proxy</h1>
|
|
8633
|
+
<p>This is AstraSync's Local Guard device proxy. It only works as a browser proxy — it isn't a page to open.</p>
|
|
8634
|
+
<h2>Open the sign-in link</h2>
|
|
8635
|
+
<ul>
|
|
8636
|
+
<li>Run <code>astrasync guard browse --open</code> — it opens a browser that goes through this proxy.</li>
|
|
8637
|
+
<li>Or start Chrome, Edge or Chromium with <code>--proxy-server=${proxy} ${certFlag(certSpki)}</code> and a separate profile (<code>--user-data-dir=<an empty folder></code>), then open the sign-in link in it.</li>
|
|
8638
|
+
</ul>
|
|
8639
|
+
<p>Chrome shows a warning bar about that flag. That is expected — it trusts only this proxy's certificate — so close the bar.</p>
|
|
8640
|
+
<p>Keep <code>astrasync guard browse</code> running while you use the session.</p>
|
|
8641
|
+
</body></html>
|
|
8642
|
+
`;
|
|
8643
|
+
}
|
|
8442
8644
|
async function startBrowseProxy(opts) {
|
|
8443
8645
|
const hosts = new Set(opts.hosts.map((h) => h.toLowerCase()));
|
|
8444
8646
|
const deviceHeader = `Device ${opts.deviceCredential}`;
|
|
8445
|
-
const { cert, key } = createLocalCert([...hosts]);
|
|
8647
|
+
const { cert, key, spkiSha256 } = createLocalCert([...hosts]);
|
|
8648
|
+
const sockets = /* @__PURE__ */ new Set();
|
|
8649
|
+
const track = (s) => {
|
|
8650
|
+
sockets.add(s);
|
|
8651
|
+
s.once("close", () => sockets.delete(s));
|
|
8652
|
+
};
|
|
8446
8653
|
function forward(req, res, target) {
|
|
8447
8654
|
const headers = cleanHeaders(req.headers);
|
|
8448
8655
|
headers["x-astra-device"] = deviceHeader;
|
|
@@ -8494,6 +8701,7 @@ async function startBrowseProxy(opts) {
|
|
|
8494
8701
|
},
|
|
8495
8702
|
onConnect
|
|
8496
8703
|
) : import_node_net.default.connect(target.port, target.host, onConnect);
|
|
8704
|
+
track(upstream);
|
|
8497
8705
|
upstream.on("error", () => socket.destroy());
|
|
8498
8706
|
socket.on("error", () => upstream.destroy());
|
|
8499
8707
|
}
|
|
@@ -8525,6 +8733,16 @@ async function startBrowseProxy(opts) {
|
|
|
8525
8733
|
});
|
|
8526
8734
|
});
|
|
8527
8735
|
const server = import_node_http.default.createServer((req, res) => {
|
|
8736
|
+
if ((req.url ?? "").startsWith("/")) {
|
|
8737
|
+
if (req.url === "/favicon.ico") {
|
|
8738
|
+
res.writeHead(404).end();
|
|
8739
|
+
return;
|
|
8740
|
+
}
|
|
8741
|
+
const listening = server.address()?.port ?? 0;
|
|
8742
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
8743
|
+
res.end(helpPage(listening, spkiSha256));
|
|
8744
|
+
return;
|
|
8745
|
+
}
|
|
8528
8746
|
let url;
|
|
8529
8747
|
try {
|
|
8530
8748
|
url = new URL(req.url ?? "");
|
|
@@ -8617,18 +8835,22 @@ async function startBrowseProxy(opts) {
|
|
|
8617
8835
|
upstream.pipe(socket);
|
|
8618
8836
|
socket.pipe(upstream);
|
|
8619
8837
|
});
|
|
8838
|
+
track(upstream);
|
|
8620
8839
|
upstream.on("error", () => socket.destroy());
|
|
8621
8840
|
socket.on("error", () => upstream.destroy());
|
|
8622
8841
|
});
|
|
8842
|
+
server.on("connection", track);
|
|
8623
8843
|
await new Promise((resolve) => server.listen(opts.port ?? 0, "127.0.0.1", resolve));
|
|
8624
8844
|
const port = server.address().port;
|
|
8625
8845
|
return {
|
|
8626
8846
|
port,
|
|
8847
|
+
certSpki: spkiSha256,
|
|
8627
8848
|
close: () => new Promise((resolve) => {
|
|
8628
8849
|
inner.close();
|
|
8629
8850
|
plainInner.close();
|
|
8630
8851
|
server.close(() => resolve());
|
|
8631
8852
|
server.closeAllConnections?.();
|
|
8853
|
+
for (const s of sockets) s.destroy();
|
|
8632
8854
|
})
|
|
8633
8855
|
};
|
|
8634
8856
|
}
|
|
@@ -8641,6 +8863,7 @@ var init_browse_proxy = __esm({
|
|
|
8641
8863
|
import_node_net = __toESM(require("net"));
|
|
8642
8864
|
import_node_tls = __toESM(require("tls"));
|
|
8643
8865
|
init_local_cert();
|
|
8866
|
+
init_open_browser();
|
|
8644
8867
|
HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
8645
8868
|
"connection",
|
|
8646
8869
|
"proxy-connection",
|
|
@@ -8736,6 +8959,18 @@ async function runBrowse(paths, opts) {
|
|
|
8736
8959
|
log(
|
|
8737
8960
|
`Device proxy: http://127.0.0.1:${proxy.port} (adds this machine's credential for ${hosts.join(", ")})`
|
|
8738
8961
|
);
|
|
8962
|
+
if (!opts.open) {
|
|
8963
|
+
log("Open it in a browser through the proxy:");
|
|
8964
|
+
for (const l of browserCommandLines(
|
|
8965
|
+
opts.platform ?? process.platform,
|
|
8966
|
+
proxy.port,
|
|
8967
|
+
openUrl,
|
|
8968
|
+
proxy.certSpki,
|
|
8969
|
+
opts.wsl
|
|
8970
|
+
))
|
|
8971
|
+
log(l);
|
|
8972
|
+
log(" (or re-run with --open)");
|
|
8973
|
+
}
|
|
8739
8974
|
log("Playwright:");
|
|
8740
8975
|
log(
|
|
8741
8976
|
` chromium.launch({ proxy: { server: 'http://127.0.0.1:${proxy.port}' } }) + newContext({ ignoreHTTPSErrors: true })`
|
|
@@ -8752,6 +8987,7 @@ var init_browse = __esm({
|
|
|
8752
8987
|
"use strict";
|
|
8753
8988
|
init_enrolment_store();
|
|
8754
8989
|
init_browse_proxy();
|
|
8990
|
+
init_open_browser();
|
|
8755
8991
|
}
|
|
8756
8992
|
});
|
|
8757
8993
|
|
|
@@ -8781,7 +9017,7 @@ async function cmdSetup() {
|
|
|
8781
9017
|
}
|
|
8782
9018
|
async function cmdUpgrade() {
|
|
8783
9019
|
const policyPath = process.argv[4] || DEFAULT_POLICY_PATH;
|
|
8784
|
-
if (!
|
|
9020
|
+
if (!fs2.existsSync(policyPath)) {
|
|
8785
9021
|
console.error(`No policy file found at ${policyPath}`);
|
|
8786
9022
|
console.error('Run "astrasync guard setup" first to create a policy.');
|
|
8787
9023
|
process.exit(1);
|
|
@@ -8809,13 +9045,13 @@ async function cmdUpgrade() {
|
|
|
8809
9045
|
prompt: (message) => prompt.question(message),
|
|
8810
9046
|
print: (message) => console.log(message),
|
|
8811
9047
|
writeConfig: async (filePath, content) => {
|
|
8812
|
-
const dir =
|
|
8813
|
-
if (!
|
|
8814
|
-
|
|
9048
|
+
const dir = path2.dirname(filePath);
|
|
9049
|
+
if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
|
|
9050
|
+
fs2.writeFileSync(filePath, content, "utf-8");
|
|
8815
9051
|
},
|
|
8816
9052
|
readConfig: async (filePath) => {
|
|
8817
9053
|
try {
|
|
8818
|
-
return
|
|
9054
|
+
return fs2.readFileSync(filePath, "utf-8");
|
|
8819
9055
|
} catch {
|
|
8820
9056
|
return null;
|
|
8821
9057
|
}
|
|
@@ -8836,13 +9072,13 @@ async function cmdStart() {
|
|
|
8836
9072
|
let gatewayConfig;
|
|
8837
9073
|
const upgraded = await isUpgraded(DEFAULT_CONFIG_DIR, async (p) => {
|
|
8838
9074
|
try {
|
|
8839
|
-
return
|
|
9075
|
+
return fs2.readFileSync(p, "utf-8");
|
|
8840
9076
|
} catch {
|
|
8841
9077
|
return null;
|
|
8842
9078
|
}
|
|
8843
9079
|
});
|
|
8844
9080
|
if (upgraded) {
|
|
8845
|
-
const config = JSON.parse(
|
|
9081
|
+
const config = JSON.parse(fs2.readFileSync(`${DEFAULT_CONFIG_DIR}/config`, "utf-8"));
|
|
8846
9082
|
gatewayConfig = {
|
|
8847
9083
|
mode: config.mode,
|
|
8848
9084
|
apiBaseUrl: config.platformUrl ? `${config.platformUrl}/api/v1` : void 0,
|
|
@@ -8850,7 +9086,7 @@ async function cmdStart() {
|
|
|
8850
9086
|
};
|
|
8851
9087
|
console.log(`[AstraSync] Starting in ${config.mode} mode (agent: ${config.agentId})`);
|
|
8852
9088
|
} else {
|
|
8853
|
-
if (!
|
|
9089
|
+
if (!fs2.existsSync(policyPath)) {
|
|
8854
9090
|
console.error(`No policy file found at ${policyPath}`);
|
|
8855
9091
|
console.error('Run "astrasync guard setup" first.');
|
|
8856
9092
|
process.exit(1);
|
|
@@ -8887,7 +9123,7 @@ async function cmdStatus() {
|
|
|
8887
9123
|
const policyPath = process.argv[4] || DEFAULT_POLICY_PATH;
|
|
8888
9124
|
const upgraded = await isUpgraded(DEFAULT_CONFIG_DIR, async (p) => {
|
|
8889
9125
|
try {
|
|
8890
|
-
return
|
|
9126
|
+
return fs2.readFileSync(p, "utf-8");
|
|
8891
9127
|
} catch {
|
|
8892
9128
|
return null;
|
|
8893
9129
|
}
|
|
@@ -8897,7 +9133,7 @@ async function cmdStatus() {
|
|
|
8897
9133
|
console.log(` ${line}`);
|
|
8898
9134
|
}
|
|
8899
9135
|
if (upgraded) {
|
|
8900
|
-
const config = JSON.parse(
|
|
9136
|
+
const config = JSON.parse(fs2.readFileSync(`${DEFAULT_CONFIG_DIR}/config`, "utf-8"));
|
|
8901
9137
|
console.log(` Mode: ${config.mode}`);
|
|
8902
9138
|
console.log(` Agent: ${config.agentId}`);
|
|
8903
9139
|
console.log(` Platform: ${config.platformUrl}`);
|
|
@@ -8905,7 +9141,7 @@ async function cmdStatus() {
|
|
|
8905
9141
|
} else {
|
|
8906
9142
|
console.log(" Mode: local (free tier)");
|
|
8907
9143
|
}
|
|
8908
|
-
if (
|
|
9144
|
+
if (fs2.existsSync(policyPath)) {
|
|
8909
9145
|
const parsed = parseFile(policyPath);
|
|
8910
9146
|
if (parsed.validation.valid && parsed.policy) {
|
|
8911
9147
|
const p = parsed.policy;
|
|
@@ -8930,7 +9166,7 @@ async function cmdCheck() {
|
|
|
8930
9166
|
(a) => !a.startsWith("--") && a !== "guard" && a !== "check" && a !== process.argv[0] && a !== process.argv[1]
|
|
8931
9167
|
) || DEFAULT_POLICY_PATH;
|
|
8932
9168
|
const trigger = process.argv.find((a) => a.startsWith("--trigger="))?.split("=")[1] || "pre-push";
|
|
8933
|
-
if (!
|
|
9169
|
+
if (!fs2.existsSync(policyPath)) {
|
|
8934
9170
|
console.log("[AstraSync] No policy file \u2014 skipping check");
|
|
8935
9171
|
process.exit(0);
|
|
8936
9172
|
}
|
|
@@ -8942,9 +9178,9 @@ async function cmdCheck() {
|
|
|
8942
9178
|
}
|
|
8943
9179
|
let enforcement = "warn";
|
|
8944
9180
|
const configPath = `${DEFAULT_CONFIG_DIR}/config`;
|
|
8945
|
-
if (
|
|
9181
|
+
if (fs2.existsSync(configPath)) {
|
|
8946
9182
|
try {
|
|
8947
|
-
const config = JSON.parse(
|
|
9183
|
+
const config = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
8948
9184
|
enforcement = config.gitTriggerEnforcement || "warn";
|
|
8949
9185
|
} catch {
|
|
8950
9186
|
}
|
|
@@ -9007,8 +9243,8 @@ async function cmdUninstallHooks() {
|
|
|
9007
9243
|
}
|
|
9008
9244
|
}
|
|
9009
9245
|
function resolveClaudeHookCommand() {
|
|
9010
|
-
const sibling =
|
|
9011
|
-
if (
|
|
9246
|
+
const sibling = path2.join(__dirname, "astrasync-claude-hook.js");
|
|
9247
|
+
if (fs2.existsSync(sibling)) {
|
|
9012
9248
|
return `"${process.execPath}" "${sibling}"`;
|
|
9013
9249
|
}
|
|
9014
9250
|
return "astrasync-claude-hook";
|
|
@@ -9024,19 +9260,19 @@ function parseClaudeCodeFlags() {
|
|
|
9024
9260
|
};
|
|
9025
9261
|
}
|
|
9026
9262
|
function claudeCodePaths(project) {
|
|
9027
|
-
const root = project ? process.cwd() :
|
|
9263
|
+
const root = project ? process.cwd() : os2.homedir();
|
|
9028
9264
|
return {
|
|
9029
|
-
settingsPath:
|
|
9030
|
-
astrasyncDir:
|
|
9265
|
+
settingsPath: path2.join(root, ".claude", "settings.json"),
|
|
9266
|
+
astrasyncDir: path2.join(root, ".astrasync")
|
|
9031
9267
|
};
|
|
9032
9268
|
}
|
|
9033
9269
|
async function cmdInstallClaudeCode() {
|
|
9034
9270
|
const flags = parseClaudeCodeFlags();
|
|
9035
9271
|
const { settingsPath, astrasyncDir } = claudeCodePaths(flags.project);
|
|
9036
|
-
const policyPath = flags.policyOverride ||
|
|
9037
|
-
const guardJsonPath =
|
|
9272
|
+
const policyPath = flags.policyOverride || path2.join(astrasyncDir, "policy.yaml");
|
|
9273
|
+
const guardJsonPath = path2.join(astrasyncDir, "guard.json");
|
|
9038
9274
|
console.log("\nAstraSync Local Guard for Claude Code \u2014 install\n");
|
|
9039
|
-
if (
|
|
9275
|
+
if (fs2.existsSync(policyPath)) {
|
|
9040
9276
|
console.log(` Policy: using existing ${policyPath}`);
|
|
9041
9277
|
if (ensureGuardSelfProtection(policyPath)) {
|
|
9042
9278
|
console.log(" added guard self-protection patterns to file.write");
|
|
@@ -9044,7 +9280,7 @@ async function cmdInstallClaudeCode() {
|
|
|
9044
9280
|
} else if (flags.wizard) {
|
|
9045
9281
|
const prompt = createPrompt();
|
|
9046
9282
|
try {
|
|
9047
|
-
|
|
9283
|
+
fs2.mkdirSync(path2.dirname(policyPath), { recursive: true });
|
|
9048
9284
|
const wizard = new SetupWizard(prompt);
|
|
9049
9285
|
await wizard.runAndSave(policyPath);
|
|
9050
9286
|
} finally {
|
|
@@ -9053,17 +9289,17 @@ async function cmdInstallClaudeCode() {
|
|
|
9053
9289
|
ensureGuardSelfProtection(policyPath);
|
|
9054
9290
|
console.log(` Policy: created via wizard at ${policyPath}`);
|
|
9055
9291
|
} else {
|
|
9056
|
-
|
|
9057
|
-
|
|
9292
|
+
fs2.mkdirSync(path2.dirname(policyPath), { recursive: true });
|
|
9293
|
+
fs2.writeFileSync(policyPath, toYaml(buildDefaultClaudeCodePolicy()), "utf-8");
|
|
9058
9294
|
console.log(` Policy: default coding-agent policy written to ${policyPath}`);
|
|
9059
9295
|
console.log(" (re-run with --wizard for the interactive setup instead)");
|
|
9060
9296
|
}
|
|
9061
|
-
if (!
|
|
9297
|
+
if (!fs2.existsSync(guardJsonPath)) {
|
|
9062
9298
|
const guardSettings = {
|
|
9063
9299
|
posture: flags.active ? "active" : "passive",
|
|
9064
9300
|
governMcp: false
|
|
9065
9301
|
};
|
|
9066
|
-
|
|
9302
|
+
fs2.writeFileSync(guardJsonPath, `${JSON.stringify(guardSettings, null, 2)}
|
|
9067
9303
|
`, "utf-8");
|
|
9068
9304
|
console.log(
|
|
9069
9305
|
` Guard: ${guardJsonPath} (posture: ${guardSettings.posture}, governMcp: false)`
|
|
@@ -9093,7 +9329,7 @@ async function cmdInstallClaudeCode() {
|
|
|
9093
9329
|
}
|
|
9094
9330
|
console.log("\n Next steps:");
|
|
9095
9331
|
console.log(" 1. Start a NEW Claude Code session (settings load at startup).");
|
|
9096
|
-
console.log(` 2. Watch decisions: tail -f ${
|
|
9332
|
+
console.log(` 2. Watch decisions: tail -f ${path2.join(astrasyncDir, "traces")}/*.jsonl`);
|
|
9097
9333
|
console.log(` 3. When the traces look right, set "posture": "active" in ${guardJsonPath}`);
|
|
9098
9334
|
console.log(" to enforce (denies block, approvals use Claude Code's own prompt).");
|
|
9099
9335
|
console.log(' 4. To govern MCP tools too, set "governMcp": true and add');
|
|
@@ -9123,26 +9359,26 @@ async function cmdUninstallClaudeCode() {
|
|
|
9123
9359
|
);
|
|
9124
9360
|
}
|
|
9125
9361
|
function resolveCodexHookCommand() {
|
|
9126
|
-
const sibling =
|
|
9127
|
-
if (
|
|
9362
|
+
const sibling = path2.join(__dirname, "astrasync-codex-hook.js");
|
|
9363
|
+
if (fs2.existsSync(sibling)) {
|
|
9128
9364
|
return `"${process.execPath}" "${sibling}"`;
|
|
9129
9365
|
}
|
|
9130
9366
|
return "astrasync-codex-hook";
|
|
9131
9367
|
}
|
|
9132
9368
|
function codexPaths(project) {
|
|
9133
|
-
const root = project ? process.cwd() :
|
|
9369
|
+
const root = project ? process.cwd() : os2.homedir();
|
|
9134
9370
|
return {
|
|
9135
|
-
hooksPath:
|
|
9136
|
-
astrasyncDir:
|
|
9371
|
+
hooksPath: path2.join(root, ".codex", "hooks.json"),
|
|
9372
|
+
astrasyncDir: path2.join(root, ".astrasync")
|
|
9137
9373
|
};
|
|
9138
9374
|
}
|
|
9139
9375
|
async function cmdInstallCodex() {
|
|
9140
9376
|
const flags = parseClaudeCodeFlags();
|
|
9141
9377
|
const { hooksPath, astrasyncDir } = codexPaths(flags.project);
|
|
9142
|
-
const policyPath = flags.policyOverride ||
|
|
9143
|
-
const guardJsonPath =
|
|
9378
|
+
const policyPath = flags.policyOverride || path2.join(astrasyncDir, "policy.yaml");
|
|
9379
|
+
const guardJsonPath = path2.join(astrasyncDir, "guard.json");
|
|
9144
9380
|
console.log("\nAstraSync Local Guard for Codex CLI \u2014 install\n");
|
|
9145
|
-
if (
|
|
9381
|
+
if (fs2.existsSync(policyPath)) {
|
|
9146
9382
|
console.log(` Policy: using existing ${policyPath} (shared across adapters)`);
|
|
9147
9383
|
if (ensureGuardSelfProtection(policyPath)) {
|
|
9148
9384
|
console.log(" added guard self-protection patterns to file.write");
|
|
@@ -9150,7 +9386,7 @@ async function cmdInstallCodex() {
|
|
|
9150
9386
|
} else if (flags.wizard) {
|
|
9151
9387
|
const prompt = createPrompt();
|
|
9152
9388
|
try {
|
|
9153
|
-
|
|
9389
|
+
fs2.mkdirSync(path2.dirname(policyPath), { recursive: true });
|
|
9154
9390
|
const wizard = new SetupWizard(prompt);
|
|
9155
9391
|
await wizard.runAndSave(policyPath);
|
|
9156
9392
|
} finally {
|
|
@@ -9159,17 +9395,17 @@ async function cmdInstallCodex() {
|
|
|
9159
9395
|
ensureGuardSelfProtection(policyPath);
|
|
9160
9396
|
console.log(` Policy: created via wizard at ${policyPath}`);
|
|
9161
9397
|
} else {
|
|
9162
|
-
|
|
9163
|
-
|
|
9398
|
+
fs2.mkdirSync(path2.dirname(policyPath), { recursive: true });
|
|
9399
|
+
fs2.writeFileSync(policyPath, toYaml(buildDefaultClaudeCodePolicy()), "utf-8");
|
|
9164
9400
|
console.log(` Policy: default coding-agent policy written to ${policyPath}`);
|
|
9165
9401
|
console.log(" (re-run with --wizard for the interactive setup instead)");
|
|
9166
9402
|
}
|
|
9167
|
-
if (!
|
|
9403
|
+
if (!fs2.existsSync(guardJsonPath)) {
|
|
9168
9404
|
const guardSettings = {
|
|
9169
9405
|
posture: flags.active ? "active" : "passive",
|
|
9170
9406
|
governMcp: false
|
|
9171
9407
|
};
|
|
9172
|
-
|
|
9408
|
+
fs2.writeFileSync(guardJsonPath, `${JSON.stringify(guardSettings, null, 2)}
|
|
9173
9409
|
`, "utf-8");
|
|
9174
9410
|
console.log(
|
|
9175
9411
|
` Guard: ${guardJsonPath} (posture: ${guardSettings.posture}, governMcp: false)`
|
|
@@ -9188,7 +9424,7 @@ async function cmdInstallCodex() {
|
|
|
9188
9424
|
}
|
|
9189
9425
|
console.log("\n Next steps:");
|
|
9190
9426
|
console.log(" 1. Start a NEW Codex session (hooks load at startup; /hooks to inspect).");
|
|
9191
|
-
console.log(` 2. Watch decisions: tail -f ${
|
|
9427
|
+
console.log(` 2. Watch decisions: tail -f ${path2.join(astrasyncDir, "traces")}/*.jsonl`);
|
|
9192
9428
|
console.log(` 3. When the traces look right, set "posture": "active" in ${guardJsonPath}.`);
|
|
9193
9429
|
console.log(" Denies block; approvals fall through to Codex's own prompt \u2014");
|
|
9194
9430
|
console.log(" except in dontAsk/bypassPermissions modes, where they deny.");
|
|
@@ -9213,13 +9449,13 @@ function printCodexStatus() {
|
|
|
9213
9449
|
const { hooksPath, astrasyncDir } = codexPaths(scope === "project");
|
|
9214
9450
|
let hookInstalled = false;
|
|
9215
9451
|
try {
|
|
9216
|
-
const content =
|
|
9452
|
+
const content = fs2.readFileSync(hooksPath, "utf-8");
|
|
9217
9453
|
hookInstalled = content.includes(ASTRASYNC_CODEX_HOOK_MARKER);
|
|
9218
9454
|
} catch {
|
|
9219
9455
|
}
|
|
9220
9456
|
if (hookInstalled) {
|
|
9221
|
-
const policyPath =
|
|
9222
|
-
const policy =
|
|
9457
|
+
const policyPath = path2.join(astrasyncDir, "policy.yaml");
|
|
9458
|
+
const policy = fs2.existsSync(policyPath) ? `policy: ${policyPath}` : "policy: missing";
|
|
9223
9459
|
console.log(` Codex CLI (${scope}): hook installed, ${policy}`);
|
|
9224
9460
|
}
|
|
9225
9461
|
}
|
|
@@ -9229,24 +9465,24 @@ function printClaudeCodeStatus() {
|
|
|
9229
9465
|
const { settingsPath, astrasyncDir } = claudeCodePaths(scope === "project");
|
|
9230
9466
|
let hookInstalled = false;
|
|
9231
9467
|
try {
|
|
9232
|
-
const content =
|
|
9468
|
+
const content = fs2.readFileSync(settingsPath, "utf-8");
|
|
9233
9469
|
hookInstalled = content.includes(ASTRASYNC_HOOK_MARKER);
|
|
9234
9470
|
} catch {
|
|
9235
9471
|
}
|
|
9236
|
-
const policyPath =
|
|
9237
|
-
const guardJsonPath =
|
|
9472
|
+
const policyPath = path2.join(astrasyncDir, "policy.yaml");
|
|
9473
|
+
const guardJsonPath = path2.join(astrasyncDir, "guard.json");
|
|
9238
9474
|
let posture = "";
|
|
9239
|
-
if (
|
|
9475
|
+
if (fs2.existsSync(guardJsonPath)) {
|
|
9240
9476
|
try {
|
|
9241
|
-
const settings = JSON.parse(
|
|
9477
|
+
const settings = JSON.parse(fs2.readFileSync(guardJsonPath, "utf-8"));
|
|
9242
9478
|
posture = settings.posture ? `, posture: ${settings.posture}` : "";
|
|
9243
9479
|
} catch {
|
|
9244
9480
|
posture = ", guard.json unreadable";
|
|
9245
9481
|
}
|
|
9246
9482
|
}
|
|
9247
|
-
if (hookInstalled ||
|
|
9483
|
+
if (hookInstalled || fs2.existsSync(policyPath)) {
|
|
9248
9484
|
const hook = hookInstalled ? "hook installed" : "hook NOT installed";
|
|
9249
|
-
const policy =
|
|
9485
|
+
const policy = fs2.existsSync(policyPath) ? `policy: ${policyPath}` : "policy: missing";
|
|
9250
9486
|
console.log(` Claude Code (${scope}): ${hook}, ${policy}${posture}`);
|
|
9251
9487
|
}
|
|
9252
9488
|
}
|
|
@@ -9292,14 +9528,21 @@ async function cmdFleetStatus() {
|
|
|
9292
9528
|
async function cmdBrowse() {
|
|
9293
9529
|
try {
|
|
9294
9530
|
const port = flagValue("--port");
|
|
9295
|
-
const
|
|
9531
|
+
const open = process.argv.includes("--open");
|
|
9532
|
+
const { proxy, openUrl } = await runBrowse(fleetPaths(), {
|
|
9296
9533
|
checkpoint: flagValue("--checkpoint") ?? "",
|
|
9297
9534
|
slug: flagValue("--slug") ?? "",
|
|
9298
9535
|
upstream: flagValue("--upstream"),
|
|
9299
9536
|
port: port ? Number(port) : void 0,
|
|
9300
|
-
extraHosts: flagValue("--host") ? [flagValue("--host")] : []
|
|
9537
|
+
extraHosts: flagValue("--host") ? [flagValue("--host")] : [],
|
|
9538
|
+
open
|
|
9301
9539
|
});
|
|
9540
|
+
if (open) openThroughProxy({ port: proxy.port, url: openUrl, certSpki: proxy.certSpki });
|
|
9541
|
+
let stopping = false;
|
|
9302
9542
|
const stop = async () => {
|
|
9543
|
+
if (stopping) process.exit(0);
|
|
9544
|
+
stopping = true;
|
|
9545
|
+
setTimeout(() => process.exit(0), 2e3).unref();
|
|
9303
9546
|
await proxy.close();
|
|
9304
9547
|
process.exit(0);
|
|
9305
9548
|
};
|
|
@@ -9334,7 +9577,7 @@ async function cmdGitRoute() {
|
|
|
9334
9577
|
}
|
|
9335
9578
|
async function cmdGitCredential() {
|
|
9336
9579
|
const action = process.argv[process.argv.indexOf("git-credential") + 1] ?? "";
|
|
9337
|
-
const input =
|
|
9580
|
+
const input = fs2.readFileSync(0, "utf-8");
|
|
9338
9581
|
process.stdout.write(runGitCredential(action, input));
|
|
9339
9582
|
}
|
|
9340
9583
|
async function cmdManagedSettings() {
|
|
@@ -9438,8 +9681,9 @@ async function main() {
|
|
|
9438
9681
|
" browse Sign an agent in to your dashboard from this machine and"
|
|
9439
9682
|
);
|
|
9440
9683
|
console.log(
|
|
9441
|
-
" run its device proxy (--checkpoint <url> --slug <agent
|
|
9684
|
+
" run its device proxy (--checkpoint <url> --slug <agent>;"
|
|
9442
9685
|
);
|
|
9686
|
+
console.log(" --open to start a browser through the proxy)");
|
|
9443
9687
|
console.log(" enroll <token> Enrol this machine in your organisation fleet");
|
|
9444
9688
|
console.log(" (--api-base-url <url>, --system for machine scope)");
|
|
9445
9689
|
console.log(" fleet-status Show fleet enrolment, signed policy and heartbeat");
|
|
@@ -9453,13 +9697,13 @@ async function main() {
|
|
|
9453
9697
|
process.exit(command ? 1 : 0);
|
|
9454
9698
|
}
|
|
9455
9699
|
}
|
|
9456
|
-
var
|
|
9700
|
+
var fs2, os2, path2, readline, DEFAULT_POLICY_PATH, DEFAULT_CONFIG_DIR;
|
|
9457
9701
|
var init_guard = __esm({
|
|
9458
9702
|
"src/cli/guard.ts"() {
|
|
9459
9703
|
"use strict";
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9704
|
+
fs2 = __toESM(require("fs"));
|
|
9705
|
+
os2 = __toESM(require("os"));
|
|
9706
|
+
path2 = __toESM(require("path"));
|
|
9463
9707
|
readline = __toESM(require("readline"));
|
|
9464
9708
|
init_wizard();
|
|
9465
9709
|
init_upgrade();
|
|
@@ -9473,6 +9717,7 @@ var init_guard = __esm({
|
|
|
9473
9717
|
init_enrolment_store();
|
|
9474
9718
|
init_git_route();
|
|
9475
9719
|
init_browse();
|
|
9720
|
+
init_open_browser();
|
|
9476
9721
|
DEFAULT_POLICY_PATH = "./local-policy.yaml";
|
|
9477
9722
|
DEFAULT_CONFIG_DIR = ".astrasync";
|
|
9478
9723
|
main().catch((err) => {
|
|
@@ -9509,6 +9754,7 @@ COMMANDS:
|
|
|
9509
9754
|
(--api-base-url <url>, --system for machine scope)
|
|
9510
9755
|
guard fleet-status Fleet enrolment, signed policy and heartbeat state
|
|
9511
9756
|
guard browse Sign an agent in to your dashboard via this machine's device proxy
|
|
9757
|
+
(--checkpoint <url> --slug <agent>; --open starts a browser through it)
|
|
9512
9758
|
guard managed-settings MDM templates for Claude Code / Codex (--claude, --codex, --out <dir>)
|
|
9513
9759
|
|
|
9514
9760
|
REGISTER OPTIONS:
|