@astrasyncai/verification-gateway 5.15.0 → 5.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/adapters/express.d.mts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +17 -2
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +17 -2
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.d.ts +1 -1
- package/dist/adapters/mcp.js +4 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +4 -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 +17 -2
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +17 -2
- 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 +4 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +4 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +69 -54
- package/dist/agent/index.d.ts +69 -54
- package/dist/agent/index.js +24 -14
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +24 -14
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +4 -1
- package/dist/bin/astrasync-codex-hook.js +4 -1
- package/dist/bin/astrasync-guard.js +544 -25
- package/dist/bin/astrasync.js +590 -33
- package/dist/browser/background.js +4 -1
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +4 -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 +4 -1
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +4 -1
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +4 -1
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +4 -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 +1 -1
- package/dist/edge-core/index.d.ts +1 -1
- package/dist/edge-core/index.js +5 -2
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +5 -2
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +4 -1
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +4 -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 +96 -57
- package/dist/index.d.ts +96 -57
- package/dist/index.js +43 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -15
- package/dist/index.mjs.map +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.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-Dxf9DBpr.d.mts → types-Blz520bR.d.mts} +10 -0
- package/dist/{types-Dxf9DBpr.d.ts → types-Blz520bR.d.ts} +10 -0
- package/dist/{types-DtJjlW4O.d.ts → types-Bm1QvGqI.d.ts} +10 -0
- package/dist/{types-Eg6VoBNH.d.mts → types-DBe4hgfT.d.mts} +10 -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 +4 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +4 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
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.17.0";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -49,10 +49,10 @@ function withUserAgent(initHeaders) {
|
|
|
49
49
|
return copy;
|
|
50
50
|
}
|
|
51
51
|
if (Array.isArray(initHeaders)) {
|
|
52
|
-
const has2 = initHeaders.some(([
|
|
52
|
+
const has2 = initHeaders.some(([name2]) => name2.toLowerCase() === "user-agent");
|
|
53
53
|
return has2 ? initHeaders : [...initHeaders, ["user-agent", SDK_USER_AGENT]];
|
|
54
54
|
}
|
|
55
|
-
const has = Object.keys(initHeaders).some((
|
|
55
|
+
const has = Object.keys(initHeaders).some((name2) => name2.toLowerCase() === "user-agent");
|
|
56
56
|
return has ? initHeaders : { "user-agent": SDK_USER_AGENT, ...initHeaders };
|
|
57
57
|
}
|
|
58
58
|
var SDK_USER_AGENT, sdkFetch;
|
|
@@ -611,9 +611,9 @@ function requireType() {
|
|
|
611
611
|
}
|
|
612
612
|
function Type2(tag, options) {
|
|
613
613
|
options = options || {};
|
|
614
|
-
Object.keys(options).forEach(function(
|
|
615
|
-
if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(
|
|
616
|
-
throw new YAMLException2('Unknown option "' +
|
|
614
|
+
Object.keys(options).forEach(function(name2) {
|
|
615
|
+
if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name2) === -1) {
|
|
616
|
+
throw new YAMLException2('Unknown option "' + name2 + '" is met in definition of "' + tag + '" YAML type.');
|
|
617
617
|
}
|
|
618
618
|
});
|
|
619
619
|
this.options = options;
|
|
@@ -644,9 +644,9 @@ function requireSchema() {
|
|
|
644
644
|
hasRequiredSchema = 1;
|
|
645
645
|
const YAMLException2 = requireException();
|
|
646
646
|
const Type2 = requireType();
|
|
647
|
-
function compileList(schema2,
|
|
647
|
+
function compileList(schema2, name2) {
|
|
648
648
|
const result = [];
|
|
649
|
-
schema2[
|
|
649
|
+
schema2[name2].forEach(function(currentType) {
|
|
650
650
|
let newIndex = result.length;
|
|
651
651
|
result.forEach(function(previousType, previousIndex) {
|
|
652
652
|
if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) {
|
|
@@ -1520,18 +1520,18 @@ function requireLoader() {
|
|
|
1520
1520
|
state.onWarning.call(null, generateError(state, message));
|
|
1521
1521
|
}
|
|
1522
1522
|
}
|
|
1523
|
-
function storeAnchor(state,
|
|
1523
|
+
function storeAnchor(state, name2, value) {
|
|
1524
1524
|
const transactions = state.anchorMapTransactions;
|
|
1525
1525
|
if (transactions.length !== 0) {
|
|
1526
1526
|
const transaction = transactions[transactions.length - 1];
|
|
1527
|
-
if (!_hasOwnProperty.call(transaction,
|
|
1528
|
-
transaction[
|
|
1529
|
-
existed: _hasOwnProperty.call(state.anchorMap,
|
|
1530
|
-
value: state.anchorMap[
|
|
1527
|
+
if (!_hasOwnProperty.call(transaction, name2)) {
|
|
1528
|
+
transaction[name2] = {
|
|
1529
|
+
existed: _hasOwnProperty.call(state.anchorMap, name2),
|
|
1530
|
+
value: state.anchorMap[name2]
|
|
1531
1531
|
};
|
|
1532
1532
|
}
|
|
1533
1533
|
}
|
|
1534
|
-
state.anchorMap[
|
|
1534
|
+
state.anchorMap[name2] = value;
|
|
1535
1535
|
}
|
|
1536
1536
|
function beginAnchorTransaction(state) {
|
|
1537
1537
|
state.anchorMapTransactions.push(/* @__PURE__ */ Object.create(null));
|
|
@@ -1543,9 +1543,9 @@ function requireLoader() {
|
|
|
1543
1543
|
const parent = transactions[transactions.length - 1];
|
|
1544
1544
|
const names = Object.keys(transaction);
|
|
1545
1545
|
for (let index = 0, length = names.length; index < length; index += 1) {
|
|
1546
|
-
const
|
|
1547
|
-
if (!_hasOwnProperty.call(parent,
|
|
1548
|
-
parent[
|
|
1546
|
+
const name2 = names[index];
|
|
1547
|
+
if (!_hasOwnProperty.call(parent, name2)) {
|
|
1548
|
+
parent[name2] = transaction[name2];
|
|
1549
1549
|
}
|
|
1550
1550
|
}
|
|
1551
1551
|
}
|
|
@@ -1586,7 +1586,7 @@ function requireLoader() {
|
|
|
1586
1586
|
state.result = snapshot.result;
|
|
1587
1587
|
}
|
|
1588
1588
|
const directiveHandlers = {
|
|
1589
|
-
YAML: function handleYamlDirective(state,
|
|
1589
|
+
YAML: function handleYamlDirective(state, name2, args) {
|
|
1590
1590
|
if (state.version !== null) {
|
|
1591
1591
|
throwError(state, "duplication of %YAML directive");
|
|
1592
1592
|
}
|
|
@@ -1608,7 +1608,7 @@ function requireLoader() {
|
|
|
1608
1608
|
throwWarning(state, "unsupported YAML version of the document");
|
|
1609
1609
|
}
|
|
1610
1610
|
},
|
|
1611
|
-
TAG: function handleTagDirective(state,
|
|
1611
|
+
TAG: function handleTagDirective(state, name2, args) {
|
|
1612
1612
|
let prefix;
|
|
1613
1613
|
if (args.length !== 2) {
|
|
1614
1614
|
throwError(state, "TAG directive accepts exactly two arguments");
|
|
@@ -3938,10 +3938,10 @@ ${category.label}
|
|
|
3938
3938
|
scope.blockedResources = additionalBlocked;
|
|
3939
3939
|
}
|
|
3940
3940
|
this.print("");
|
|
3941
|
-
const
|
|
3941
|
+
const name2 = (await this.ask("Policy name [default: local-guard]: ")).trim() || "local-guard";
|
|
3942
3942
|
const policy = {
|
|
3943
3943
|
version: "1.0",
|
|
3944
|
-
name,
|
|
3944
|
+
name: name2,
|
|
3945
3945
|
purposes,
|
|
3946
3946
|
...scope && { scope },
|
|
3947
3947
|
...limits && { limits },
|
|
@@ -4662,8 +4662,8 @@ function extractBacktickSubstitutions(text, collect) {
|
|
|
4662
4662
|
}
|
|
4663
4663
|
function basename(token) {
|
|
4664
4664
|
const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
|
|
4665
|
-
const
|
|
4666
|
-
return
|
|
4665
|
+
const name2 = slash === -1 ? token : token.slice(slash + 1);
|
|
4666
|
+
return name2.replace(/\.(exe|cmd|bat|ps1)$/i, "");
|
|
4667
4667
|
}
|
|
4668
4668
|
function matchSegment(segment, list) {
|
|
4669
4669
|
const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
|
|
@@ -5030,6 +5030,13 @@ var init_local = __esm({
|
|
|
5030
5030
|
}
|
|
5031
5031
|
});
|
|
5032
5032
|
|
|
5033
|
+
// src/types.ts
|
|
5034
|
+
var init_types2 = __esm({
|
|
5035
|
+
"src/types.ts"() {
|
|
5036
|
+
"use strict";
|
|
5037
|
+
}
|
|
5038
|
+
});
|
|
5039
|
+
|
|
5033
5040
|
// src/trust-levels.ts
|
|
5034
5041
|
function getTrustLevel(score) {
|
|
5035
5042
|
if (score >= 80) return "PLATINUM";
|
|
@@ -5161,6 +5168,8 @@ function getCacheKey(request2, counterpartyId) {
|
|
|
5161
5168
|
request2.durationRequired ?? "",
|
|
5162
5169
|
request2.invocationProtocol || "",
|
|
5163
5170
|
request2.enableRuntimeChallenge ? "1" : "0",
|
|
5171
|
+
// 5.16.0: route policy changes the verdict (owners / challenge).
|
|
5172
|
+
request2.routePolicy ? JSON.stringify(request2.routePolicy) : "",
|
|
5164
5173
|
// callerMetadata fields contribute to risk model; include the ones
|
|
5165
5174
|
// backend reads. sourceIp/userAgent/forwardedFor change per-request
|
|
5166
5175
|
// so their inclusion effectively forces a re-check for any varying
|
|
@@ -5331,6 +5340,7 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5331
5340
|
if (requestData.subAgentDepth !== void 0) body.subAgentDepth = requestData.subAgentDepth;
|
|
5332
5341
|
if (requestData.enableRuntimeChallenge)
|
|
5333
5342
|
body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
|
|
5343
|
+
if (requestData.routePolicy) body.routePolicy = requestData.routePolicy;
|
|
5334
5344
|
if (requestData.createSession) body.createSession = requestData.createSession;
|
|
5335
5345
|
if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
|
|
5336
5346
|
if (requestData.counterpartyType) body.counterpartyType = requestData.counterpartyType;
|
|
@@ -6092,6 +6102,7 @@ var init_express = __esm({
|
|
|
6092
6102
|
"src/adapters/express.ts"() {
|
|
6093
6103
|
"use strict";
|
|
6094
6104
|
init_commerce_detect();
|
|
6105
|
+
init_types2();
|
|
6095
6106
|
init_stepup_poll();
|
|
6096
6107
|
init_verify();
|
|
6097
6108
|
init_http2();
|
|
@@ -6114,6 +6125,7 @@ var init_nextjs = __esm({
|
|
|
6114
6125
|
"src/adapters/nextjs.ts"() {
|
|
6115
6126
|
"use strict";
|
|
6116
6127
|
init_commerce_detect();
|
|
6128
|
+
init_types2();
|
|
6117
6129
|
init_stepup_poll();
|
|
6118
6130
|
init_verify();
|
|
6119
6131
|
init_http2();
|
|
@@ -6362,7 +6374,7 @@ var init_extractor_registry = __esm({
|
|
|
6362
6374
|
});
|
|
6363
6375
|
|
|
6364
6376
|
// src/transport/registry/types.ts
|
|
6365
|
-
var
|
|
6377
|
+
var init_types3 = __esm({
|
|
6366
6378
|
"src/transport/registry/types.ts"() {
|
|
6367
6379
|
"use strict";
|
|
6368
6380
|
}
|
|
@@ -6420,7 +6432,7 @@ var init_transport = __esm({
|
|
|
6420
6432
|
init_vi_verify();
|
|
6421
6433
|
init_commerce_pipeline();
|
|
6422
6434
|
init_extractor_registry();
|
|
6423
|
-
|
|
6435
|
+
init_types3();
|
|
6424
6436
|
init_visa();
|
|
6425
6437
|
init_mastercard();
|
|
6426
6438
|
init_web_bot_auth();
|
|
@@ -6740,6 +6752,7 @@ var init_http_signatures = __esm({
|
|
|
6740
6752
|
var init_src = __esm({
|
|
6741
6753
|
"src/index.ts"() {
|
|
6742
6754
|
"use strict";
|
|
6755
|
+
init_types2();
|
|
6743
6756
|
init_trust_levels();
|
|
6744
6757
|
init_verify();
|
|
6745
6758
|
init_failure_posture();
|
|
@@ -7604,7 +7617,7 @@ function ensureGuardSelfProtection(policyPath) {
|
|
|
7604
7617
|
(0, import_fs5.writeFileSync)(policyPath, toYaml(parsed.policy), "utf-8");
|
|
7605
7618
|
return true;
|
|
7606
7619
|
}
|
|
7607
|
-
function buildDefaultClaudeCodePolicy(
|
|
7620
|
+
function buildDefaultClaudeCodePolicy(name2 = "claude-code-local-guard") {
|
|
7608
7621
|
const recommendedCommands = DEFAULT_BLOCKED_COMMANDS.filter((c) => c.recommended).map(
|
|
7609
7622
|
(c) => c.pattern
|
|
7610
7623
|
);
|
|
@@ -7612,7 +7625,7 @@ function buildDefaultClaudeCodePolicy(name = "claude-code-local-guard") {
|
|
|
7612
7625
|
const permissive = RISK_PRESETS.find((p) => p.name === "permissive");
|
|
7613
7626
|
return {
|
|
7614
7627
|
version: "1.0",
|
|
7615
|
-
name,
|
|
7628
|
+
name: name2,
|
|
7616
7629
|
description: "AstraSync Local Guard for Claude Code \u2014 default coding-agent policy. Edit freely; the hook re-reads this file on every tool call.",
|
|
7617
7630
|
purposes: [
|
|
7618
7631
|
{
|
|
@@ -7871,7 +7884,7 @@ var init_enrolment_store = __esm({
|
|
|
7871
7884
|
|
|
7872
7885
|
// src/fleet/types.ts
|
|
7873
7886
|
var FLEET_POLICY_TYP, FLEET_POLICY_AUD, FLEET_POLICY_ISS, FLEET_KEYS_TYP, FLEET_KEYS_AUD, DEFAULT_HEARTBEAT_INTERVAL_SEC;
|
|
7874
|
-
var
|
|
7887
|
+
var init_types4 = __esm({
|
|
7875
7888
|
"src/fleet/types.ts"() {
|
|
7876
7889
|
"use strict";
|
|
7877
7890
|
FLEET_POLICY_TYP = "fleet-policy+jwt";
|
|
@@ -8002,7 +8015,7 @@ var init_policy_verify = __esm({
|
|
|
8002
8015
|
import_crypto = require("crypto");
|
|
8003
8016
|
import_jose5 = require("jose");
|
|
8004
8017
|
init_pdlss_parser();
|
|
8005
|
-
|
|
8018
|
+
init_types4();
|
|
8006
8019
|
FleetPolicyError = class extends Error {
|
|
8007
8020
|
constructor(message) {
|
|
8008
8021
|
super(message);
|
|
@@ -8223,7 +8236,7 @@ var init_cli = __esm({
|
|
|
8223
8236
|
init_client2();
|
|
8224
8237
|
init_enrolment_store();
|
|
8225
8238
|
init_policy_verify();
|
|
8226
|
-
|
|
8239
|
+
init_types4();
|
|
8227
8240
|
DEFAULT_FLEET_API_BASE_URL = "https://astrasync.ai/api";
|
|
8228
8241
|
MANAGED_SETTINGS_LOCATIONS = {
|
|
8229
8242
|
// code.claude.com/docs/en/managed-settings
|
|
@@ -8242,6 +8255,479 @@ var init_cli = __esm({
|
|
|
8242
8255
|
}
|
|
8243
8256
|
});
|
|
8244
8257
|
|
|
8258
|
+
// src/fleet/git-route.ts
|
|
8259
|
+
function gitRouteConfig(opts) {
|
|
8260
|
+
const base2 = opts.checkpoint.replace(/\/+$/, "");
|
|
8261
|
+
if (!/^https:\/\//.test(base2) && !/^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(base2)) {
|
|
8262
|
+
throw new Error("--checkpoint must be an https:// URL");
|
|
8263
|
+
}
|
|
8264
|
+
if (!/^ASTRA-[A-Za-z0-9_-]{8,64}$/.test(opts.agent))
|
|
8265
|
+
throw new Error("--agent must be an ASTRA-id");
|
|
8266
|
+
if (!/^[A-Za-z0-9_-]{4,120}$/.test(opts.slug))
|
|
8267
|
+
throw new Error("--slug must be the connector slug");
|
|
8268
|
+
const upstream = opts.upstream ?? "github";
|
|
8269
|
+
return [
|
|
8270
|
+
[`url.${base2}/a/${opts.slug}/git/${upstream}/.insteadOf`, opts.host ?? "https://github.com/"],
|
|
8271
|
+
[`credential.${base2}.helper`, "!astrasync guard git-credential"],
|
|
8272
|
+
["astrasync.agent", opts.agent],
|
|
8273
|
+
["astrasync.checkpoint", base2]
|
|
8274
|
+
];
|
|
8275
|
+
}
|
|
8276
|
+
function applyGitRoute(opts, git = realGit) {
|
|
8277
|
+
const entries = gitRouteConfig(opts);
|
|
8278
|
+
for (const [key, value] of entries) git(["config", "--global", key, value]);
|
|
8279
|
+
return entries.map(([k, v]) => `${k} = ${v}`);
|
|
8280
|
+
}
|
|
8281
|
+
function removeGitRoute(git = realGit) {
|
|
8282
|
+
let base2 = "";
|
|
8283
|
+
try {
|
|
8284
|
+
base2 = git(["config", "--global", "--get", "astrasync.checkpoint"]).trim();
|
|
8285
|
+
} catch {
|
|
8286
|
+
return [];
|
|
8287
|
+
}
|
|
8288
|
+
const removed = [];
|
|
8289
|
+
const unset = (args) => {
|
|
8290
|
+
try {
|
|
8291
|
+
git(["config", "--global", ...args]);
|
|
8292
|
+
removed.push(args[args.length - 1]);
|
|
8293
|
+
} catch {
|
|
8294
|
+
}
|
|
8295
|
+
};
|
|
8296
|
+
let urls = "";
|
|
8297
|
+
try {
|
|
8298
|
+
urls = git(["config", "--global", "--get-regexp", "^url\\..*\\.insteadof$"]);
|
|
8299
|
+
} catch {
|
|
8300
|
+
}
|
|
8301
|
+
for (const line of urls.split("\n")) {
|
|
8302
|
+
const key = line.split(" ")[0];
|
|
8303
|
+
if (key && key.toLowerCase().startsWith(`url.${base2}/`.toLowerCase())) unset(["--unset", key]);
|
|
8304
|
+
}
|
|
8305
|
+
unset(["--unset", `credential.${base2}.helper`]);
|
|
8306
|
+
unset(["--unset", "astrasync.agent"]);
|
|
8307
|
+
unset(["--unset", "astrasync.checkpoint"]);
|
|
8308
|
+
return removed;
|
|
8309
|
+
}
|
|
8310
|
+
function gitCredentialAnswer(action, input, deps) {
|
|
8311
|
+
if (action !== "get" || !deps.agent || !deps.checkpoint || !deps.deviceCredential) return "";
|
|
8312
|
+
const fields = Object.fromEntries(
|
|
8313
|
+
input.split("\n").map((l) => l.split("=")).filter((p) => p.length >= 2).map(([k, ...v]) => [k, v.join("=")])
|
|
8314
|
+
);
|
|
8315
|
+
const host = new URL(deps.checkpoint).host;
|
|
8316
|
+
if (fields.host && fields.host !== host) return "";
|
|
8317
|
+
return `username=${deps.agent}
|
|
8318
|
+
password=${deps.deviceCredential}
|
|
8319
|
+
`;
|
|
8320
|
+
}
|
|
8321
|
+
function runGitCredential(action, input, git = realGit) {
|
|
8322
|
+
const read = (key) => {
|
|
8323
|
+
try {
|
|
8324
|
+
return git(["config", "--global", "--get", key]).trim();
|
|
8325
|
+
} catch {
|
|
8326
|
+
return void 0;
|
|
8327
|
+
}
|
|
8328
|
+
};
|
|
8329
|
+
const loaded = loadEnrolment(fleetPaths());
|
|
8330
|
+
const deviceCredential = loaded && "enrolment" in loaded ? loaded.enrolment.credential : void 0;
|
|
8331
|
+
return gitCredentialAnswer(action, input, {
|
|
8332
|
+
agent: read("astrasync.agent"),
|
|
8333
|
+
checkpoint: read("astrasync.checkpoint"),
|
|
8334
|
+
deviceCredential
|
|
8335
|
+
});
|
|
8336
|
+
}
|
|
8337
|
+
var import_child_process2, realGit;
|
|
8338
|
+
var init_git_route = __esm({
|
|
8339
|
+
"src/fleet/git-route.ts"() {
|
|
8340
|
+
"use strict";
|
|
8341
|
+
import_child_process2 = require("child_process");
|
|
8342
|
+
init_enrolment_store();
|
|
8343
|
+
realGit = (args) => (0, import_child_process2.execFileSync)("git", args, { encoding: "utf-8" });
|
|
8344
|
+
}
|
|
8345
|
+
});
|
|
8346
|
+
|
|
8347
|
+
// src/fleet/local-cert.ts
|
|
8348
|
+
function len(n) {
|
|
8349
|
+
if (n < 128) return Buffer.from([n]);
|
|
8350
|
+
const bytes = [];
|
|
8351
|
+
while (n > 0) {
|
|
8352
|
+
bytes.unshift(n & 255);
|
|
8353
|
+
n >>= 8;
|
|
8354
|
+
}
|
|
8355
|
+
return Buffer.from([128 | bytes.length, ...bytes]);
|
|
8356
|
+
}
|
|
8357
|
+
function oid(dotted) {
|
|
8358
|
+
const parts = dotted.split(".").map(Number);
|
|
8359
|
+
const out = [parts[0] * 40 + parts[1]];
|
|
8360
|
+
for (const p of parts.slice(2)) {
|
|
8361
|
+
const enc = [p & 127];
|
|
8362
|
+
let v = p >> 7;
|
|
8363
|
+
while (v > 0) {
|
|
8364
|
+
enc.unshift(v & 127 | 128);
|
|
8365
|
+
v >>= 7;
|
|
8366
|
+
}
|
|
8367
|
+
out.push(...enc);
|
|
8368
|
+
}
|
|
8369
|
+
return tlv(6, Buffer.from(out));
|
|
8370
|
+
}
|
|
8371
|
+
function integer(buf) {
|
|
8372
|
+
const b = buf[0] & 128 ? Buffer.concat([Buffer.from([0]), buf]) : buf;
|
|
8373
|
+
return tlv(2, b);
|
|
8374
|
+
}
|
|
8375
|
+
function utcTime(d) {
|
|
8376
|
+
const s = d.toISOString().replace(/[-:T]/g, "").slice(2, 14) + "Z";
|
|
8377
|
+
return tlv(23, Buffer.from(s, "ascii"));
|
|
8378
|
+
}
|
|
8379
|
+
function name(cn) {
|
|
8380
|
+
return seq2(set2(seq2(oid("2.5.4.3"), tlv(12, Buffer.from(cn, "utf8")))));
|
|
8381
|
+
}
|
|
8382
|
+
function createLocalCert(hosts, days = 30) {
|
|
8383
|
+
const { privateKey, publicKey } = import_node_crypto5.default.generateKeyPairSync("ec", { namedCurve: "P-256" });
|
|
8384
|
+
const spki = publicKey.export({ type: "spki", format: "der" });
|
|
8385
|
+
const now = Date.now();
|
|
8386
|
+
const san = seq2(...hosts.map((h) => tlv(130, Buffer.from(h, "ascii"))));
|
|
8387
|
+
const extensions = ctx(
|
|
8388
|
+
3,
|
|
8389
|
+
seq2(
|
|
8390
|
+
seq2(oid("2.5.29.17"), tlv(4, san)),
|
|
8391
|
+
// subjectAltName
|
|
8392
|
+
seq2(oid("2.5.29.19"), tlv(4, seq2()))
|
|
8393
|
+
// basicConstraints: not a CA
|
|
8394
|
+
)
|
|
8395
|
+
);
|
|
8396
|
+
const subject = name("AstraSync Local Guard (browse)");
|
|
8397
|
+
const tbs = seq2(
|
|
8398
|
+
ctx(0, integer(Buffer.from([2]))),
|
|
8399
|
+
// v3
|
|
8400
|
+
integer(import_node_crypto5.default.randomBytes(16)),
|
|
8401
|
+
ECDSA_SHA256,
|
|
8402
|
+
subject,
|
|
8403
|
+
seq2(utcTime(new Date(now - 6e4)), utcTime(new Date(now + days * 864e5))),
|
|
8404
|
+
subject,
|
|
8405
|
+
spki,
|
|
8406
|
+
extensions
|
|
8407
|
+
);
|
|
8408
|
+
const signature = import_node_crypto5.default.sign("sha256", tbs, privateKey);
|
|
8409
|
+
const der = seq2(tbs, ECDSA_SHA256, tlv(3, Buffer.concat([Buffer.from([0]), signature])));
|
|
8410
|
+
const b64 = der.toString("base64").match(/.{1,64}/g).join("\n");
|
|
8411
|
+
return {
|
|
8412
|
+
cert: `-----BEGIN CERTIFICATE-----
|
|
8413
|
+
${b64}
|
|
8414
|
+
-----END CERTIFICATE-----
|
|
8415
|
+
`,
|
|
8416
|
+
key: privateKey.export({ type: "pkcs8", format: "pem" }).toString()
|
|
8417
|
+
};
|
|
8418
|
+
}
|
|
8419
|
+
var import_node_crypto5, tlv, seq2, set2, ctx, ECDSA_SHA256;
|
|
8420
|
+
var init_local_cert = __esm({
|
|
8421
|
+
"src/fleet/local-cert.ts"() {
|
|
8422
|
+
"use strict";
|
|
8423
|
+
import_node_crypto5 = __toESM(require("crypto"));
|
|
8424
|
+
tlv = (tag, body) => Buffer.concat([Buffer.from([tag]), len(body.length), body]);
|
|
8425
|
+
seq2 = (...parts) => tlv(48, Buffer.concat(parts));
|
|
8426
|
+
set2 = (...parts) => tlv(49, Buffer.concat(parts));
|
|
8427
|
+
ctx = (n, body) => tlv(160 + n, body);
|
|
8428
|
+
ECDSA_SHA256 = seq2(oid("1.2.840.10045.4.3.2"));
|
|
8429
|
+
}
|
|
8430
|
+
});
|
|
8431
|
+
|
|
8432
|
+
// src/fleet/browse-proxy.ts
|
|
8433
|
+
function cleanHeaders(h) {
|
|
8434
|
+
const out = {};
|
|
8435
|
+
for (const [k, v] of Object.entries(h)) if (!HOP_BY_HOP.has(k) && v !== void 0) out[k] = v;
|
|
8436
|
+
return out;
|
|
8437
|
+
}
|
|
8438
|
+
async function startBrowseProxy(opts) {
|
|
8439
|
+
const hosts = new Set(opts.hosts.map((h) => h.toLowerCase()));
|
|
8440
|
+
const deviceHeader = `Device ${opts.deviceCredential}`;
|
|
8441
|
+
const { cert, key } = createLocalCert([...hosts]);
|
|
8442
|
+
function forward(req, res, target) {
|
|
8443
|
+
const headers = cleanHeaders(req.headers);
|
|
8444
|
+
headers["x-astra-device"] = deviceHeader;
|
|
8445
|
+
const mod = target.protocol === "https:" ? import_node_https.default : import_node_http.default;
|
|
8446
|
+
const upstream = mod.request(
|
|
8447
|
+
{
|
|
8448
|
+
host: target.host,
|
|
8449
|
+
port: target.port,
|
|
8450
|
+
method: req.method,
|
|
8451
|
+
path: target.path,
|
|
8452
|
+
headers,
|
|
8453
|
+
servername: target.protocol === "https:" ? String(req.headers.host ?? target.host).split(":")[0] : void 0,
|
|
8454
|
+
rejectUnauthorized: target.rejectUnauthorized ?? true
|
|
8455
|
+
},
|
|
8456
|
+
(up) => {
|
|
8457
|
+
res.writeHead(up.statusCode ?? 502, cleanHeaders(up.headers));
|
|
8458
|
+
up.pipe(res);
|
|
8459
|
+
}
|
|
8460
|
+
);
|
|
8461
|
+
upstream.on("error", () => {
|
|
8462
|
+
if (!res.headersSent) res.writeHead(502, { "content-type": "text/plain" });
|
|
8463
|
+
res.end("AstraSync browse proxy: upstream unreachable");
|
|
8464
|
+
});
|
|
8465
|
+
req.pipe(upstream);
|
|
8466
|
+
}
|
|
8467
|
+
function forwardUpgrade(req, socket, head, target) {
|
|
8468
|
+
const headers = { ...req.headers };
|
|
8469
|
+
delete headers["proxy-connection"];
|
|
8470
|
+
delete headers["proxy-authorization"];
|
|
8471
|
+
delete headers["x-astra-device"];
|
|
8472
|
+
if (target.addDevice) headers["x-astra-device"] = deviceHeader;
|
|
8473
|
+
const lines = [`${req.method} ${target.path} HTTP/1.1`];
|
|
8474
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
8475
|
+
if (v === void 0) continue;
|
|
8476
|
+
for (const one of Array.isArray(v) ? v : [v]) lines.push(`${k}: ${one}`);
|
|
8477
|
+
}
|
|
8478
|
+
const onConnect = () => {
|
|
8479
|
+
upstream.write(lines.join("\r\n") + "\r\n\r\n");
|
|
8480
|
+
if (head.length) upstream.write(head);
|
|
8481
|
+
upstream.pipe(socket);
|
|
8482
|
+
socket.pipe(upstream);
|
|
8483
|
+
};
|
|
8484
|
+
const upstream = target.protocol === "https:" ? import_node_tls.default.connect(
|
|
8485
|
+
{
|
|
8486
|
+
host: target.host,
|
|
8487
|
+
port: target.port,
|
|
8488
|
+
servername: String(req.headers.host ?? target.host).split(":")[0],
|
|
8489
|
+
rejectUnauthorized: target.rejectUnauthorized ?? true
|
|
8490
|
+
},
|
|
8491
|
+
onConnect
|
|
8492
|
+
) : import_node_net.default.connect(target.port, target.host, onConnect);
|
|
8493
|
+
upstream.on("error", () => socket.destroy());
|
|
8494
|
+
socket.on("error", () => upstream.destroy());
|
|
8495
|
+
}
|
|
8496
|
+
const inner = import_node_http.default.createServer((req, res) => {
|
|
8497
|
+
const hostHeader = String(req.headers.host ?? "");
|
|
8498
|
+
const [h, p] = hostHeader.split(":");
|
|
8499
|
+
const port2 = Number(p) || 443;
|
|
8500
|
+
const up = opts.upstreamFor?.(h, port2) ?? { host: h, port: port2 };
|
|
8501
|
+
forward(req, res, {
|
|
8502
|
+
protocol: "https:",
|
|
8503
|
+
host: up.host,
|
|
8504
|
+
port: up.port,
|
|
8505
|
+
path: req.url ?? "/",
|
|
8506
|
+
rejectUnauthorized: up.rejectUnauthorized
|
|
8507
|
+
});
|
|
8508
|
+
});
|
|
8509
|
+
const plainInner = import_node_http.default.createServer((req, res) => {
|
|
8510
|
+
const [h, p] = String(req.headers.host ?? "").split(":");
|
|
8511
|
+
forward(req, res, { protocol: "http:", host: h, port: Number(p) || 80, path: req.url ?? "/" });
|
|
8512
|
+
});
|
|
8513
|
+
plainInner.on("upgrade", (req, socket, head) => {
|
|
8514
|
+
const [h, p] = String(req.headers.host ?? "").split(":");
|
|
8515
|
+
forwardUpgrade(req, socket, head, {
|
|
8516
|
+
protocol: "http:",
|
|
8517
|
+
host: h,
|
|
8518
|
+
port: Number(p) || 80,
|
|
8519
|
+
path: req.url ?? "/",
|
|
8520
|
+
addDevice: true
|
|
8521
|
+
});
|
|
8522
|
+
});
|
|
8523
|
+
const server = import_node_http.default.createServer((req, res) => {
|
|
8524
|
+
let url;
|
|
8525
|
+
try {
|
|
8526
|
+
url = new URL(req.url ?? "");
|
|
8527
|
+
} catch {
|
|
8528
|
+
res.writeHead(400).end("absolute URL required");
|
|
8529
|
+
return;
|
|
8530
|
+
}
|
|
8531
|
+
if (hosts.has(url.hostname.toLowerCase())) {
|
|
8532
|
+
forward(req, res, {
|
|
8533
|
+
protocol: "http:",
|
|
8534
|
+
host: url.hostname,
|
|
8535
|
+
port: Number(url.port) || 80,
|
|
8536
|
+
path: `${url.pathname}${url.search}`
|
|
8537
|
+
});
|
|
8538
|
+
return;
|
|
8539
|
+
}
|
|
8540
|
+
const upstream = import_node_http.default.request(
|
|
8541
|
+
{
|
|
8542
|
+
host: url.hostname,
|
|
8543
|
+
port: Number(url.port) || 80,
|
|
8544
|
+
method: req.method,
|
|
8545
|
+
path: `${url.pathname}${url.search}`,
|
|
8546
|
+
headers: cleanHeaders(req.headers)
|
|
8547
|
+
},
|
|
8548
|
+
(up) => {
|
|
8549
|
+
res.writeHead(up.statusCode ?? 502, cleanHeaders(up.headers));
|
|
8550
|
+
up.pipe(res);
|
|
8551
|
+
}
|
|
8552
|
+
);
|
|
8553
|
+
upstream.on("error", () => res.writeHead(502).end());
|
|
8554
|
+
req.pipe(upstream);
|
|
8555
|
+
});
|
|
8556
|
+
inner.on("upgrade", (req, socket, head) => {
|
|
8557
|
+
const [h, p] = String(req.headers.host ?? "").split(":");
|
|
8558
|
+
const port2 = Number(p) || 443;
|
|
8559
|
+
const up = opts.upstreamFor?.(h, port2) ?? { host: h, port: port2 };
|
|
8560
|
+
forwardUpgrade(req, socket, head, {
|
|
8561
|
+
protocol: "https:",
|
|
8562
|
+
host: up.host,
|
|
8563
|
+
port: up.port,
|
|
8564
|
+
path: req.url ?? "/",
|
|
8565
|
+
addDevice: true,
|
|
8566
|
+
rejectUnauthorized: up.rejectUnauthorized
|
|
8567
|
+
});
|
|
8568
|
+
});
|
|
8569
|
+
server.on("upgrade", (req, socket, head) => {
|
|
8570
|
+
let url;
|
|
8571
|
+
try {
|
|
8572
|
+
url = new URL(req.url ?? "");
|
|
8573
|
+
} catch {
|
|
8574
|
+
socket.destroy();
|
|
8575
|
+
return;
|
|
8576
|
+
}
|
|
8577
|
+
forwardUpgrade(req, socket, head, {
|
|
8578
|
+
protocol: "http:",
|
|
8579
|
+
host: url.hostname,
|
|
8580
|
+
port: Number(url.port) || 80,
|
|
8581
|
+
path: `${url.pathname}${url.search}`,
|
|
8582
|
+
addDevice: hosts.has(url.hostname.toLowerCase())
|
|
8583
|
+
});
|
|
8584
|
+
});
|
|
8585
|
+
server.on("connect", (req, socket, head) => {
|
|
8586
|
+
const [host, portStr] = String(req.url ?? "").split(":");
|
|
8587
|
+
const port2 = Number(portStr) || 443;
|
|
8588
|
+
if (hosts.has(host.toLowerCase())) {
|
|
8589
|
+
socket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
8590
|
+
const start = (first) => {
|
|
8591
|
+
const s = socket;
|
|
8592
|
+
s.pause();
|
|
8593
|
+
s.unshift(first);
|
|
8594
|
+
if (first[0] === 22) {
|
|
8595
|
+
const tlsSocket = new import_node_tls.default.TLSSocket(s, {
|
|
8596
|
+
isServer: true,
|
|
8597
|
+
secureContext: import_node_tls.default.createSecureContext({ cert, key })
|
|
8598
|
+
});
|
|
8599
|
+
inner.emit("connection", tlsSocket);
|
|
8600
|
+
tlsSocket.on("error", () => socket.destroy());
|
|
8601
|
+
} else {
|
|
8602
|
+
plainInner.emit("connection", s);
|
|
8603
|
+
s.resume();
|
|
8604
|
+
}
|
|
8605
|
+
};
|
|
8606
|
+
if (head.length) start(head);
|
|
8607
|
+
else socket.once("data", (chunk) => start(chunk));
|
|
8608
|
+
return;
|
|
8609
|
+
}
|
|
8610
|
+
const upstream = import_node_net.default.connect(port2, host, () => {
|
|
8611
|
+
socket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
8612
|
+
if (head.length) upstream.write(head);
|
|
8613
|
+
upstream.pipe(socket);
|
|
8614
|
+
socket.pipe(upstream);
|
|
8615
|
+
});
|
|
8616
|
+
upstream.on("error", () => socket.destroy());
|
|
8617
|
+
socket.on("error", () => upstream.destroy());
|
|
8618
|
+
});
|
|
8619
|
+
await new Promise((resolve) => server.listen(opts.port ?? 0, "127.0.0.1", resolve));
|
|
8620
|
+
const port = server.address().port;
|
|
8621
|
+
return {
|
|
8622
|
+
port,
|
|
8623
|
+
close: () => new Promise((resolve) => {
|
|
8624
|
+
inner.close();
|
|
8625
|
+
plainInner.close();
|
|
8626
|
+
server.close(() => resolve());
|
|
8627
|
+
server.closeAllConnections?.();
|
|
8628
|
+
})
|
|
8629
|
+
};
|
|
8630
|
+
}
|
|
8631
|
+
var import_node_http, import_node_https, import_node_net, import_node_tls, HOP_BY_HOP;
|
|
8632
|
+
var init_browse_proxy = __esm({
|
|
8633
|
+
"src/fleet/browse-proxy.ts"() {
|
|
8634
|
+
"use strict";
|
|
8635
|
+
import_node_http = __toESM(require("http"));
|
|
8636
|
+
import_node_https = __toESM(require("https"));
|
|
8637
|
+
import_node_net = __toESM(require("net"));
|
|
8638
|
+
import_node_tls = __toESM(require("tls"));
|
|
8639
|
+
init_local_cert();
|
|
8640
|
+
HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
8641
|
+
"connection",
|
|
8642
|
+
"proxy-connection",
|
|
8643
|
+
"keep-alive",
|
|
8644
|
+
"transfer-encoding",
|
|
8645
|
+
"upgrade",
|
|
8646
|
+
"te",
|
|
8647
|
+
"trailer",
|
|
8648
|
+
"proxy-authorization"
|
|
8649
|
+
]);
|
|
8650
|
+
}
|
|
8651
|
+
});
|
|
8652
|
+
|
|
8653
|
+
// src/fleet/browse.ts
|
|
8654
|
+
async function runBrowse(paths, opts) {
|
|
8655
|
+
const log = opts.log ?? ((l) => console.log(l));
|
|
8656
|
+
const f = opts.fetchImpl ?? fetch;
|
|
8657
|
+
const loaded = loadEnrolment(paths);
|
|
8658
|
+
if (!loaded || !("enrolment" in loaded)) {
|
|
8659
|
+
throw new Error("This machine is not enrolled. Run: astrasync guard enroll <token>");
|
|
8660
|
+
}
|
|
8661
|
+
const { credential, apiBaseUrl } = loaded.enrolment;
|
|
8662
|
+
if (!opts.checkpoint || !opts.slug) throw new Error("--checkpoint and --slug are required");
|
|
8663
|
+
const appOrigin = new URL(apiBaseUrl).origin;
|
|
8664
|
+
const hosts = [new URL(apiBaseUrl).hostname, ...opts.extraHosts ?? []];
|
|
8665
|
+
const device = `Device ${credential}`;
|
|
8666
|
+
const proxy = await startBrowseProxy({ hosts, deviceCredential: credential, port: opts.port });
|
|
8667
|
+
try {
|
|
8668
|
+
const base2 = opts.checkpoint.replace(/\/+$/, "");
|
|
8669
|
+
const signin = await f(
|
|
8670
|
+
`${base2}/a/${encodeURIComponent(opts.slug)}/h/${encodeURIComponent(opts.upstream ?? "astrasync-api")}/agent-sessions`,
|
|
8671
|
+
{
|
|
8672
|
+
method: "POST",
|
|
8673
|
+
headers: { authorization: device, "content-type": "application/json" },
|
|
8674
|
+
body: "{}"
|
|
8675
|
+
}
|
|
8676
|
+
);
|
|
8677
|
+
const body = await signin.json().catch(() => ({}));
|
|
8678
|
+
if (signin.status !== 201 && signin.status !== 202) {
|
|
8679
|
+
throw new Error(
|
|
8680
|
+
`Sign-in refused (${signin.status}${body.code ? ` ${body.code}` : ""}): ${body.message ?? "no detail"}`
|
|
8681
|
+
);
|
|
8682
|
+
}
|
|
8683
|
+
const sessionId = String(body.data?.sessionId ?? "");
|
|
8684
|
+
let code = body.data?.code;
|
|
8685
|
+
if (!code) {
|
|
8686
|
+
log("Waiting for the owner to approve this sign-in with their passkey\u2026");
|
|
8687
|
+
const deadline = Date.now() + (opts.waitMs ?? 10 * 6e4);
|
|
8688
|
+
while (!code) {
|
|
8689
|
+
if (Date.now() > deadline) throw new Error("The owner did not approve in time.");
|
|
8690
|
+
await new Promise((r) => setTimeout(r, opts.pollIntervalMs ?? 3e3));
|
|
8691
|
+
const poll = await f(
|
|
8692
|
+
`${apiBaseUrl.replace(/\/+$/, "")}/agent-sessions/${sessionId}/status`,
|
|
8693
|
+
{
|
|
8694
|
+
headers: { "x-astra-device": device }
|
|
8695
|
+
}
|
|
8696
|
+
);
|
|
8697
|
+
const p = await poll.json().catch(() => ({}));
|
|
8698
|
+
const status = p.data?.status;
|
|
8699
|
+
if (status === "approved") code = p.data?.code;
|
|
8700
|
+
else if (status === "denied" || status === "ended")
|
|
8701
|
+
throw new Error(`Sign-in ${status === "denied" ? "was not approved" : "ended"}.`);
|
|
8702
|
+
}
|
|
8703
|
+
}
|
|
8704
|
+
const openUrl = `${appOrigin}/agent-session#code=${code}`;
|
|
8705
|
+
log("");
|
|
8706
|
+
log(`Signed in. Open this once (within 2 minutes), through the proxy:`);
|
|
8707
|
+
log(` ${openUrl}`);
|
|
8708
|
+
log("");
|
|
8709
|
+
log(
|
|
8710
|
+
`Device proxy: http://127.0.0.1:${proxy.port} (adds this machine's credential for ${hosts.join(", ")})`
|
|
8711
|
+
);
|
|
8712
|
+
log("Playwright:");
|
|
8713
|
+
log(
|
|
8714
|
+
` chromium.launch({ proxy: { server: 'http://127.0.0.1:${proxy.port}' } }) + newContext({ ignoreHTTPSErrors: true })`
|
|
8715
|
+
);
|
|
8716
|
+
log("Requests that skip the proxy end the session. Ctrl-C stops the proxy.");
|
|
8717
|
+
return { proxy, openUrl, sessionId };
|
|
8718
|
+
} catch (err) {
|
|
8719
|
+
await proxy.close();
|
|
8720
|
+
throw err;
|
|
8721
|
+
}
|
|
8722
|
+
}
|
|
8723
|
+
var init_browse = __esm({
|
|
8724
|
+
"src/fleet/browse.ts"() {
|
|
8725
|
+
"use strict";
|
|
8726
|
+
init_enrolment_store();
|
|
8727
|
+
init_browse_proxy();
|
|
8728
|
+
}
|
|
8729
|
+
});
|
|
8730
|
+
|
|
8245
8731
|
// src/cli/guard.ts
|
|
8246
8732
|
var guard_exports = {};
|
|
8247
8733
|
function createPrompt() {
|
|
@@ -8776,6 +9262,54 @@ async function cmdFleetStatus() {
|
|
|
8776
9262
|
const status = await getFleetStatus(fleetPaths());
|
|
8777
9263
|
for (const line of formatFleetStatus(status)) console.log(line);
|
|
8778
9264
|
}
|
|
9265
|
+
async function cmdBrowse() {
|
|
9266
|
+
try {
|
|
9267
|
+
const port = flagValue("--port");
|
|
9268
|
+
const { proxy } = await runBrowse(fleetPaths(), {
|
|
9269
|
+
checkpoint: flagValue("--checkpoint") ?? "",
|
|
9270
|
+
slug: flagValue("--slug") ?? "",
|
|
9271
|
+
upstream: flagValue("--upstream"),
|
|
9272
|
+
port: port ? Number(port) : void 0,
|
|
9273
|
+
extraHosts: flagValue("--host") ? [flagValue("--host")] : []
|
|
9274
|
+
});
|
|
9275
|
+
const stop = async () => {
|
|
9276
|
+
await proxy.close();
|
|
9277
|
+
process.exit(0);
|
|
9278
|
+
};
|
|
9279
|
+
process.on("SIGINT", stop);
|
|
9280
|
+
process.on("SIGTERM", stop);
|
|
9281
|
+
await new Promise(() => void 0);
|
|
9282
|
+
} catch (err) {
|
|
9283
|
+
console.error(`browse failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9284
|
+
process.exit(1);
|
|
9285
|
+
}
|
|
9286
|
+
}
|
|
9287
|
+
async function cmdGitRoute() {
|
|
9288
|
+
try {
|
|
9289
|
+
if (process.argv.includes("--undo")) {
|
|
9290
|
+
const removed = removeGitRoute();
|
|
9291
|
+
console.log(removed.length ? `Removed: ${removed.join(", ")}` : "No git route was set.");
|
|
9292
|
+
return;
|
|
9293
|
+
}
|
|
9294
|
+
const lines = applyGitRoute({
|
|
9295
|
+
checkpoint: flagValue("--checkpoint") ?? "",
|
|
9296
|
+
slug: flagValue("--slug") ?? "",
|
|
9297
|
+
agent: flagValue("--agent") ?? "",
|
|
9298
|
+
upstream: flagValue("--upstream")
|
|
9299
|
+
});
|
|
9300
|
+
console.log("git now fetches and pushes github.com through your Workforce Guard checkpoint:");
|
|
9301
|
+
for (const l of lines) console.log(` ${l}`);
|
|
9302
|
+
console.log("Commits still run your local hooks. Undo with: astrasync guard git-route --undo");
|
|
9303
|
+
} catch (err) {
|
|
9304
|
+
console.error(`git-route failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9305
|
+
process.exit(1);
|
|
9306
|
+
}
|
|
9307
|
+
}
|
|
9308
|
+
async function cmdGitCredential() {
|
|
9309
|
+
const action = process.argv[process.argv.indexOf("git-credential") + 1] ?? "";
|
|
9310
|
+
const input = fs.readFileSync(0, "utf-8");
|
|
9311
|
+
process.stdout.write(runGitCredential(action, input));
|
|
9312
|
+
}
|
|
8779
9313
|
async function cmdManagedSettings() {
|
|
8780
9314
|
const targets = [];
|
|
8781
9315
|
if (process.argv.includes("--claude")) targets.push("claude");
|
|
@@ -8844,6 +9378,15 @@ async function main() {
|
|
|
8844
9378
|
case "managed-settings":
|
|
8845
9379
|
await cmdManagedSettings();
|
|
8846
9380
|
break;
|
|
9381
|
+
case "git-route":
|
|
9382
|
+
await cmdGitRoute();
|
|
9383
|
+
break;
|
|
9384
|
+
case "browse":
|
|
9385
|
+
await cmdBrowse();
|
|
9386
|
+
break;
|
|
9387
|
+
case "git-credential":
|
|
9388
|
+
await cmdGitCredential();
|
|
9389
|
+
break;
|
|
8847
9390
|
default:
|
|
8848
9391
|
console.log("AstraSync Local Guard\n");
|
|
8849
9392
|
console.log("Usage: astrasync guard <command>\n");
|
|
@@ -8864,10 +9407,21 @@ async function main() {
|
|
|
8864
9407
|
console.log(" install-codex Install the Local Guard hook for OpenAI Codex CLI");
|
|
8865
9408
|
console.log(" (same flags; policy shared with Claude Code)");
|
|
8866
9409
|
console.log(" uninstall-codex Remove the Codex hook (--project for project scope)");
|
|
9410
|
+
console.log(
|
|
9411
|
+
" browse Sign an agent in to your dashboard from this machine and"
|
|
9412
|
+
);
|
|
9413
|
+
console.log(
|
|
9414
|
+
" run its device proxy (--checkpoint <url> --slug <agent>)"
|
|
9415
|
+
);
|
|
8867
9416
|
console.log(" enroll <token> Enrol this machine in your organisation fleet");
|
|
8868
9417
|
console.log(" (--api-base-url <url>, --system for machine scope)");
|
|
8869
9418
|
console.log(" fleet-status Show fleet enrolment, signed policy and heartbeat");
|
|
8870
9419
|
console.log(" managed-settings Print MDM templates (--claude, --codex, --out <dir>)");
|
|
9420
|
+
console.log(" git-route Route git through your Workforce Guard checkpoint");
|
|
9421
|
+
console.log(
|
|
9422
|
+
" (--checkpoint <url> --slug <connector> --agent <ASTRA-id>;"
|
|
9423
|
+
);
|
|
9424
|
+
console.log(" --undo to remove)");
|
|
8871
9425
|
console.log("");
|
|
8872
9426
|
process.exit(command ? 1 : 0);
|
|
8873
9427
|
}
|
|
@@ -8890,6 +9444,8 @@ var init_guard = __esm({
|
|
|
8890
9444
|
init_settings_installer2();
|
|
8891
9445
|
init_cli();
|
|
8892
9446
|
init_enrolment_store();
|
|
9447
|
+
init_git_route();
|
|
9448
|
+
init_browse();
|
|
8893
9449
|
DEFAULT_POLICY_PATH = "./local-policy.yaml";
|
|
8894
9450
|
DEFAULT_CONFIG_DIR = ".astrasync";
|
|
8895
9451
|
main().catch((err) => {
|
|
@@ -8925,6 +9481,7 @@ COMMANDS:
|
|
|
8925
9481
|
guard enroll <token> Enrol this machine in your organisation's fleet
|
|
8926
9482
|
(--api-base-url <url>, --system for machine scope)
|
|
8927
9483
|
guard fleet-status Fleet enrolment, signed policy and heartbeat state
|
|
9484
|
+
guard browse Sign an agent in to your dashboard via this machine's device proxy
|
|
8928
9485
|
guard managed-settings MDM templates for Claude Code / Codex (--claude, --codex, --out <dir>)
|
|
8929
9486
|
|
|
8930
9487
|
REGISTER OPTIONS:
|
|
@@ -9008,13 +9565,13 @@ async function main2() {
|
|
|
9008
9565
|
baseUrl: config.baseUrl
|
|
9009
9566
|
});
|
|
9010
9567
|
if (command === "register") {
|
|
9011
|
-
const
|
|
9012
|
-
if (!
|
|
9568
|
+
const name2 = commandArgs["name"];
|
|
9569
|
+
if (!name2) {
|
|
9013
9570
|
console.error("Error: --name is required for register command");
|
|
9014
9571
|
process.exit(1);
|
|
9015
9572
|
}
|
|
9016
9573
|
const options = {
|
|
9017
|
-
name,
|
|
9574
|
+
name: name2,
|
|
9018
9575
|
...commandArgs["description"] && { description: commandArgs["description"] },
|
|
9019
9576
|
...commandArgs["agent-type"] && { agentType: commandArgs["agent-type"] },
|
|
9020
9577
|
...commandArgs["api-endpoint"] && { apiEndpoint: commandArgs["api-endpoint"] }
|