@contextecf/guardian-cli 0.1.6 → 0.1.9
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 +19 -14
- package/dist/packages/guardian-cli/src/bin.js +2602 -143
- package/dist/packages/guardian-cli/src/index.js +686 -95
- package/dist/packages/guardian-cli/src/runtime.d.ts +59 -7
- package/package.json +1 -1
|
@@ -16275,16 +16275,26 @@ function cloneList(values) {
|
|
|
16275
16275
|
}
|
|
16276
16276
|
|
|
16277
16277
|
// packages/guardian-cli/src/runtime.ts
|
|
16278
|
-
var GUARDIAN_CLI_VERSION = "0.1.
|
|
16278
|
+
var GUARDIAN_CLI_VERSION = "0.1.9";
|
|
16279
16279
|
var GUARDIAN_PROFILE_SCHEMA_VERSION = "contextecf/project-guardian-profile/v1";
|
|
16280
16280
|
var GUARDIAN_NPM_PACKAGE_NAME = "@contextecf/guardian-cli";
|
|
16281
16281
|
var GUARDIAN_NPM_REGISTRY = "https://registry.npmjs.org/";
|
|
16282
|
+
var GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH = "trusted_publisher";
|
|
16282
16283
|
var GUARDIAN_GLOBAL_INSTALL_COMMAND = `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}`;
|
|
16283
16284
|
var GUARDIAN_NPX_SETUP_COMMAND = `npx ${GUARDIAN_NPM_PACKAGE_NAME}@latest setup`;
|
|
16284
16285
|
var GUARDIAN_FIRST_RUN_COMMAND = "guardian setup";
|
|
16285
16286
|
var GUARDIAN_OPEN_CONTROL_TOWER_COMMAND = "guardian open";
|
|
16287
|
+
var GUARDIAN_HALO_CHROME_EXTENSION_ID = "dopkdppbiakhbglhgjfacfdhpheejkck";
|
|
16288
|
+
var GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL = `https://chromewebstore.google.com/detail/contextecf-halo/${GUARDIAN_HALO_CHROME_EXTENSION_ID}`;
|
|
16286
16289
|
var GUARDIAN_RELEASE_DISPATCH_WORKFLOW = "guardian-release-dispatch.yml";
|
|
16287
16290
|
var GUARDIAN_RELEASE_REPOSITORY = "Intelligent-Context-AI-Inc/ContextECF-GITHUB";
|
|
16291
|
+
var GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES = [
|
|
16292
|
+
"CHROME_WEB_STORE_CLIENT_ID",
|
|
16293
|
+
"CHROME_WEB_STORE_CLIENT_SECRET",
|
|
16294
|
+
"CHROME_WEB_STORE_REFRESH_TOKEN",
|
|
16295
|
+
"CHROME_WEB_STORE_PUBLISHER_ID",
|
|
16296
|
+
"CHROME_WEB_STORE_EXTENSION_ID"
|
|
16297
|
+
];
|
|
16288
16298
|
var GUARDIAN_CONTROL_TOWER_URL_ENV = "GUARDIAN_CONTROL_TOWER_URL";
|
|
16289
16299
|
var GUARDIAN_DEFAULT_CONTROL_TOWER_URL = "http://127.0.0.1:4317/control-tower";
|
|
16290
16300
|
var GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV = "GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY";
|
|
@@ -16301,6 +16311,195 @@ var GUARDIAN_WINDOWS_NATIVE_HOST_REGISTRY_PROOF_SCHEMA_VERSION = "contextecf/pro
|
|
|
16301
16311
|
var PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION2 = "contextecf/personal-fabric-contracts/v1";
|
|
16302
16312
|
var PROMPT_COACH_MODES = ["off", "quiet", "balanced", "hands_on"];
|
|
16303
16313
|
var DEFAULT_PROMPT_COACH_DAILY_SOFT_CARD_LIMIT = 6;
|
|
16314
|
+
var GUARDIAN_PROMPT_CARD_OPTIONS_CATALOG = [
|
|
16315
|
+
{
|
|
16316
|
+
disposition: "allow",
|
|
16317
|
+
cardStyle: "No visible card",
|
|
16318
|
+
whenShown: "Local Guardian approves the prompt before it leaves the browser.",
|
|
16319
|
+
actions: [
|
|
16320
|
+
{
|
|
16321
|
+
id: "auto-send",
|
|
16322
|
+
label: "Send prompt",
|
|
16323
|
+
role: "none",
|
|
16324
|
+
sendsPrompt: true,
|
|
16325
|
+
sendsRevisedPrompt: false,
|
|
16326
|
+
requiresConfirmation: false,
|
|
16327
|
+
visibleToUser: false
|
|
16328
|
+
}
|
|
16329
|
+
],
|
|
16330
|
+
sendAsIsAllowed: true,
|
|
16331
|
+
hardBlock: false,
|
|
16332
|
+
receiptExpected: true
|
|
16333
|
+
},
|
|
16334
|
+
{
|
|
16335
|
+
disposition: "warn",
|
|
16336
|
+
cardStyle: "Quick check",
|
|
16337
|
+
whenShown: "Guardian found a low or medium-risk concern, but policy still allows the user to continue.",
|
|
16338
|
+
actions: [
|
|
16339
|
+
{
|
|
16340
|
+
id: "send-as-is",
|
|
16341
|
+
label: "Send as-is",
|
|
16342
|
+
role: "allowed_override",
|
|
16343
|
+
sendsPrompt: true,
|
|
16344
|
+
sendsRevisedPrompt: false,
|
|
16345
|
+
requiresConfirmation: false,
|
|
16346
|
+
visibleToUser: true
|
|
16347
|
+
},
|
|
16348
|
+
{
|
|
16349
|
+
id: "edit-prompt",
|
|
16350
|
+
label: "Edit prompt",
|
|
16351
|
+
role: "safe_escape",
|
|
16352
|
+
sendsPrompt: false,
|
|
16353
|
+
sendsRevisedPrompt: false,
|
|
16354
|
+
requiresConfirmation: false,
|
|
16355
|
+
visibleToUser: true
|
|
16356
|
+
}
|
|
16357
|
+
],
|
|
16358
|
+
sendAsIsAllowed: true,
|
|
16359
|
+
hardBlock: false,
|
|
16360
|
+
receiptExpected: true
|
|
16361
|
+
},
|
|
16362
|
+
{
|
|
16363
|
+
disposition: "rewrite",
|
|
16364
|
+
cardStyle: "Safer version ready",
|
|
16365
|
+
whenShown: "Guardian prepared a safer prompt, usually by masking sensitive text or narrowing scope.",
|
|
16366
|
+
actions: [
|
|
16367
|
+
{
|
|
16368
|
+
id: "send-revised-prompt",
|
|
16369
|
+
label: "Send revised prompt",
|
|
16370
|
+
role: "recommended",
|
|
16371
|
+
sendsPrompt: true,
|
|
16372
|
+
sendsRevisedPrompt: true,
|
|
16373
|
+
requiresConfirmation: false,
|
|
16374
|
+
visibleToUser: true
|
|
16375
|
+
},
|
|
16376
|
+
{
|
|
16377
|
+
id: "send-as-is",
|
|
16378
|
+
label: "Send as-is",
|
|
16379
|
+
role: "allowed_override",
|
|
16380
|
+
sendsPrompt: true,
|
|
16381
|
+
sendsRevisedPrompt: false,
|
|
16382
|
+
requiresConfirmation: false,
|
|
16383
|
+
visibleToUser: true
|
|
16384
|
+
},
|
|
16385
|
+
{
|
|
16386
|
+
id: "edit-prompt",
|
|
16387
|
+
label: "Edit prompt",
|
|
16388
|
+
role: "safe_escape",
|
|
16389
|
+
sendsPrompt: false,
|
|
16390
|
+
sendsRevisedPrompt: false,
|
|
16391
|
+
requiresConfirmation: false,
|
|
16392
|
+
visibleToUser: true
|
|
16393
|
+
}
|
|
16394
|
+
],
|
|
16395
|
+
sendAsIsAllowed: true,
|
|
16396
|
+
hardBlock: false,
|
|
16397
|
+
receiptExpected: true
|
|
16398
|
+
},
|
|
16399
|
+
{
|
|
16400
|
+
disposition: "confirm",
|
|
16401
|
+
cardStyle: "Review needed",
|
|
16402
|
+
whenShown: "Guardian needs deliberate approval before sending higher-risk content or action requests.",
|
|
16403
|
+
actions: [
|
|
16404
|
+
{
|
|
16405
|
+
id: "approve-and-send",
|
|
16406
|
+
label: "Approve and send",
|
|
16407
|
+
role: "recommended",
|
|
16408
|
+
sendsPrompt: true,
|
|
16409
|
+
sendsRevisedPrompt: false,
|
|
16410
|
+
requiresConfirmation: true,
|
|
16411
|
+
visibleToUser: true
|
|
16412
|
+
},
|
|
16413
|
+
{
|
|
16414
|
+
id: "edit-prompt",
|
|
16415
|
+
label: "Edit prompt",
|
|
16416
|
+
role: "safe_escape",
|
|
16417
|
+
sendsPrompt: false,
|
|
16418
|
+
sendsRevisedPrompt: false,
|
|
16419
|
+
requiresConfirmation: false,
|
|
16420
|
+
visibleToUser: true
|
|
16421
|
+
}
|
|
16422
|
+
],
|
|
16423
|
+
sendAsIsAllowed: false,
|
|
16424
|
+
hardBlock: false,
|
|
16425
|
+
receiptExpected: true
|
|
16426
|
+
},
|
|
16427
|
+
{
|
|
16428
|
+
disposition: "block",
|
|
16429
|
+
cardStyle: "Blocked",
|
|
16430
|
+
whenShown: "The prompt violates policy, contains protected secrets, or targets a denied destination.",
|
|
16431
|
+
actions: [
|
|
16432
|
+
{
|
|
16433
|
+
id: "edit-prompt",
|
|
16434
|
+
label: "Edit prompt",
|
|
16435
|
+
role: "safe_escape",
|
|
16436
|
+
sendsPrompt: false,
|
|
16437
|
+
sendsRevisedPrompt: false,
|
|
16438
|
+
requiresConfirmation: false,
|
|
16439
|
+
visibleToUser: true
|
|
16440
|
+
}
|
|
16441
|
+
],
|
|
16442
|
+
sendAsIsAllowed: false,
|
|
16443
|
+
hardBlock: true,
|
|
16444
|
+
receiptExpected: true
|
|
16445
|
+
},
|
|
16446
|
+
{
|
|
16447
|
+
disposition: "unavailable",
|
|
16448
|
+
cardStyle: "Setup needed",
|
|
16449
|
+
whenShown: "The browser cannot reach Local Guardian, so the prompt is held back.",
|
|
16450
|
+
actions: [
|
|
16451
|
+
{
|
|
16452
|
+
id: "edit-prompt",
|
|
16453
|
+
label: "Edit prompt",
|
|
16454
|
+
role: "safe_escape",
|
|
16455
|
+
sendsPrompt: false,
|
|
16456
|
+
sendsRevisedPrompt: false,
|
|
16457
|
+
requiresConfirmation: false,
|
|
16458
|
+
visibleToUser: true
|
|
16459
|
+
}
|
|
16460
|
+
],
|
|
16461
|
+
sendAsIsAllowed: false,
|
|
16462
|
+
hardBlock: false,
|
|
16463
|
+
receiptExpected: false
|
|
16464
|
+
},
|
|
16465
|
+
{
|
|
16466
|
+
disposition: "live_sensitive_warning",
|
|
16467
|
+
cardStyle: "Early heads-up",
|
|
16468
|
+
whenShown: "Guardian notices sensitive text while the user is typing, before the formal send-time check.",
|
|
16469
|
+
actions: [
|
|
16470
|
+
{
|
|
16471
|
+
id: "use-placeholder",
|
|
16472
|
+
label: "Use placeholder",
|
|
16473
|
+
role: "recommended",
|
|
16474
|
+
sendsPrompt: false,
|
|
16475
|
+
sendsRevisedPrompt: true,
|
|
16476
|
+
requiresConfirmation: false,
|
|
16477
|
+
visibleToUser: true
|
|
16478
|
+
},
|
|
16479
|
+
{
|
|
16480
|
+
id: "send-as-is",
|
|
16481
|
+
label: "Send as-is",
|
|
16482
|
+
role: "allowed_override",
|
|
16483
|
+
sendsPrompt: true,
|
|
16484
|
+
sendsRevisedPrompt: false,
|
|
16485
|
+
requiresConfirmation: false,
|
|
16486
|
+
visibleToUser: true
|
|
16487
|
+
},
|
|
16488
|
+
{
|
|
16489
|
+
id: "keep-drafting",
|
|
16490
|
+
label: "Keep drafting",
|
|
16491
|
+
role: "safe_escape",
|
|
16492
|
+
sendsPrompt: false,
|
|
16493
|
+
sendsRevisedPrompt: false,
|
|
16494
|
+
requiresConfirmation: false,
|
|
16495
|
+
visibleToUser: true
|
|
16496
|
+
}
|
|
16497
|
+
],
|
|
16498
|
+
sendAsIsAllowed: true,
|
|
16499
|
+
hardBlock: false,
|
|
16500
|
+
receiptExpected: false
|
|
16501
|
+
}
|
|
16502
|
+
];
|
|
16304
16503
|
var GUARDIAN_POSTURE_PROFILE_IDS = [
|
|
16305
16504
|
"calm",
|
|
16306
16505
|
"balanced",
|
|
@@ -16780,6 +16979,45 @@ var MCP_CLIENTS = ["generic", "codex", "claude-desktop", "cursor"];
|
|
|
16780
16979
|
var NATIVE_HOST_BROWSERS = ["chrome", "chromium", "edge"];
|
|
16781
16980
|
var HELP_TEXT = `guardian \u2014 Project Guardian Personal Context Fabric
|
|
16782
16981
|
|
|
16982
|
+
Global install:
|
|
16983
|
+
${GUARDIAN_GLOBAL_INSTALL_COMMAND}
|
|
16984
|
+
|
|
16985
|
+
First run:
|
|
16986
|
+
${GUARDIAN_FIRST_RUN_COMMAND}
|
|
16987
|
+
|
|
16988
|
+
No global install:
|
|
16989
|
+
${GUARDIAN_NPX_SETUP_COMMAND}
|
|
16990
|
+
|
|
16991
|
+
Open Control Tower:
|
|
16992
|
+
${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}
|
|
16993
|
+
start aliases: guardian launch, guardian tower, guardian control-tower
|
|
16994
|
+
|
|
16995
|
+
Everyday commands:
|
|
16996
|
+
guardian --version
|
|
16997
|
+
guardian setup
|
|
16998
|
+
guardian launch
|
|
16999
|
+
guardian open
|
|
17000
|
+
guardian status
|
|
17001
|
+
guardian doctor
|
|
17002
|
+
guardian connect
|
|
17003
|
+
guardian coach options
|
|
17004
|
+
guardian policy list
|
|
17005
|
+
guardian marketplace list
|
|
17006
|
+
guardian posture list
|
|
17007
|
+
guardian privacy show
|
|
17008
|
+
|
|
17009
|
+
Recommended first run:
|
|
17010
|
+
${GUARDIAN_GLOBAL_INSTALL_COMMAND}
|
|
17011
|
+
guardian setup
|
|
17012
|
+
Open ContextECF Halo and click Connect.
|
|
17013
|
+
guardian open
|
|
17014
|
+
|
|
17015
|
+
Support and developer commands:
|
|
17016
|
+
guardian help --advanced
|
|
17017
|
+
|
|
17018
|
+
Defaults are local-first: raw capture, cloud sync, learning graph, and app autopilot stay off.`;
|
|
17019
|
+
var ADVANCED_HELP_TEXT = `guardian \u2014 Project Guardian Personal Context Fabric
|
|
17020
|
+
|
|
16783
17021
|
Global install:
|
|
16784
17022
|
${GUARDIAN_GLOBAL_INSTALL_COMMAND}
|
|
16785
17023
|
|
|
@@ -16796,7 +17034,7 @@ Open Control Tower:
|
|
|
16796
17034
|
Usage:
|
|
16797
17035
|
guardian --version
|
|
16798
17036
|
guardian version [--json]
|
|
16799
|
-
guardian setup [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--extension-id=<chrome-extension-id>]
|
|
17037
|
+
guardian setup [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--no-browser-connection] [--extension-id=<chrome-extension-id>]
|
|
16800
17038
|
guardian install [--json]
|
|
16801
17039
|
guardian doctor [--json]
|
|
16802
17040
|
guardian readiness [--json] [--strict]
|
|
@@ -16804,7 +17042,7 @@ Usage:
|
|
|
16804
17042
|
guardian release flow --version=<semver> [--json]
|
|
16805
17043
|
guardian release verify --version=<semver> [--json]
|
|
16806
17044
|
guardian release paste --version=<semver> [--json]
|
|
16807
|
-
guardian release command --version=<semver> [--publish|--dry-run=false] [--channels=all|npm|browser|evidence] [--run-docker-smoke=true|false] [--json]
|
|
17045
|
+
guardian release command --version=<semver> [--publish|--dry-run=false] [--channels=all|npm|browser|evidence] [--run-docker-smoke=true|false] [--publish-auth=token|trusted_publisher] [--browser-store-publish=manual|api] [--json]
|
|
16808
17046
|
guardian release secrets [--json]
|
|
16809
17047
|
guardian release browser-store [--json]
|
|
16810
17048
|
guardian open [--json] [--print] [--url=http://127.0.0.1:<port>]
|
|
@@ -16812,6 +17050,8 @@ Usage:
|
|
|
16812
17050
|
guardian start [--json] [--host=127.0.0.1] [--port=4317]
|
|
16813
17051
|
guardian launch|tower|control-tower [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317]
|
|
16814
17052
|
guardian stop [--json] [--url=http://127.0.0.1:<port>/control-tower]
|
|
17053
|
+
guardian pair [--json]
|
|
17054
|
+
guardian connect [--json] [--browser=chrome|chromium|edge] [--extension-id=<chrome-extension-id>] [--host=127.0.0.1] [--port=4317]
|
|
16815
17055
|
guardian service install [--json] [--platform=auto|launchd|systemd|windows-task-scheduler] [--force]
|
|
16816
17056
|
guardian service status [--json]
|
|
16817
17057
|
guardian service uninstall [--yes] [--json]
|
|
@@ -16820,6 +17060,7 @@ Usage:
|
|
|
16820
17060
|
guardian key-store uninstall [--yes] [--json]
|
|
16821
17061
|
guardian daemon serve [--host=127.0.0.1] [--port=4317]
|
|
16822
17062
|
guardian daemon pair [--json]
|
|
17063
|
+
guardian extension connect [--json] [--browser=chrome|chromium|edge] [--extension-id=<chrome-extension-id>]
|
|
16823
17064
|
guardian extension open-setup [--json] [--print] [--url=http://127.0.0.1:<port>/control-tower] [--extension-id=<chrome-extension-id>]
|
|
16824
17065
|
guardian extension native-host install --extension-id=<chrome-extension-id> [--browser=chrome|chromium|edge] [--target=/path/to/manifest] [--force] [--write-registry --yes] [--json]
|
|
16825
17066
|
guardian extension native-host status [--browser=chrome|chromium|edge] [--target=/path/to/manifest] [--json]
|
|
@@ -16835,6 +17076,7 @@ Usage:
|
|
|
16835
17076
|
guardian privacy mode on [--json]
|
|
16836
17077
|
guardian mcp install [--json] [--client=generic|codex|claude-desktop|cursor|all] [--write] [--target=/path/to/config] [--force]
|
|
16837
17078
|
guardian mcp serve
|
|
17079
|
+
guardian coach options [--json]
|
|
16838
17080
|
guardian policy list [--json]
|
|
16839
17081
|
guardian policy enable <pack-id> [--json]
|
|
16840
17082
|
guardian policy disable <pack-id> [--json]
|
|
@@ -16887,6 +17129,8 @@ async function runGuardianCli(argv, options = {}) {
|
|
|
16887
17129
|
return runReleaseCommand(argv.slice(1), flags, options);
|
|
16888
17130
|
case "open":
|
|
16889
17131
|
return runControlTowerOpenCommand(flags, options);
|
|
17132
|
+
case "connect":
|
|
17133
|
+
return runExtensionConnectCommand(flags, options);
|
|
16890
17134
|
case "status":
|
|
16891
17135
|
write(stdout, await statusGuardian(flags, options));
|
|
16892
17136
|
return 0;
|
|
@@ -16898,6 +17142,14 @@ async function runGuardianCli(argv, options = {}) {
|
|
|
16898
17142
|
return runLaunchCommand(flags, options);
|
|
16899
17143
|
case "stop":
|
|
16900
17144
|
return runStopCommand(flags, options);
|
|
17145
|
+
case "pair": {
|
|
17146
|
+
if (!flags.has("json")) {
|
|
17147
|
+
return runExtensionConnectCommand(flags, options);
|
|
17148
|
+
}
|
|
17149
|
+
const result = await daemonPair(flags, options);
|
|
17150
|
+
write(result.exitCode === 0 ? stdout : stderr, result.message);
|
|
17151
|
+
return result.exitCode;
|
|
17152
|
+
}
|
|
16901
17153
|
case "daemon":
|
|
16902
17154
|
return runDaemonCommand(argv.slice(1), flags, options);
|
|
16903
17155
|
case "service":
|
|
@@ -16920,6 +17172,9 @@ async function runGuardianCli(argv, options = {}) {
|
|
|
16920
17172
|
return runPrivacyCommand(argv.slice(1), flags, options);
|
|
16921
17173
|
case "mcp":
|
|
16922
17174
|
return runMcpCommand(argv.slice(1), flags, options);
|
|
17175
|
+
case "coach":
|
|
17176
|
+
case "prompt-coach":
|
|
17177
|
+
return runCoachCommand(argv.slice(1), flags, options);
|
|
16923
17178
|
case "policy":
|
|
16924
17179
|
return runPolicyCommand(argv.slice(1), flags, options);
|
|
16925
17180
|
case "marketplace":
|
|
@@ -16942,7 +17197,7 @@ async function runGuardianCli(argv, options = {}) {
|
|
|
16942
17197
|
case "help":
|
|
16943
17198
|
case "--help":
|
|
16944
17199
|
case "-h":
|
|
16945
|
-
write(stdout, `${HELP_TEXT}
|
|
17200
|
+
write(stdout, `${flags.has("advanced") ? ADVANCED_HELP_TEXT : HELP_TEXT}
|
|
16946
17201
|
`);
|
|
16947
17202
|
return 0;
|
|
16948
17203
|
default:
|
|
@@ -17021,11 +17276,13 @@ async function installGuardian(flags, options = {}) {
|
|
|
17021
17276
|
"guardian start",
|
|
17022
17277
|
"guardian open",
|
|
17023
17278
|
"guardian mcp install",
|
|
17024
|
-
"guardian daemon pair --json",
|
|
17025
17279
|
"guardian service install",
|
|
17026
17280
|
"guardian key-store install --yes",
|
|
17027
|
-
"guardian
|
|
17028
|
-
|
|
17281
|
+
"guardian connect"
|
|
17282
|
+
],
|
|
17283
|
+
advancedCommands: [
|
|
17284
|
+
`guardian extension native-host install --extension-id=${GUARDIAN_HALO_CHROME_EXTENSION_ID}`,
|
|
17285
|
+
"guardian pair --json"
|
|
17029
17286
|
]
|
|
17030
17287
|
};
|
|
17031
17288
|
return flags.has("json") ? `${JSON.stringify(result, null, 2)}
|
|
@@ -17038,7 +17295,8 @@ async function installGuardian(flags, options = {}) {
|
|
|
17038
17295
|
`First run: ${GUARDIAN_FIRST_RUN_COMMAND}`,
|
|
17039
17296
|
`Open Control Tower: ${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}`,
|
|
17040
17297
|
`No global install: ${GUARDIAN_NPX_SETUP_COMMAND}`,
|
|
17041
|
-
"Next: guardian setup;
|
|
17298
|
+
"Next: guardian setup; open ContextECF Halo and click Connect; guardian open",
|
|
17299
|
+
"Help: run guardian doctor if setup needs attention."
|
|
17042
17300
|
].join("\n")}
|
|
17043
17301
|
`;
|
|
17044
17302
|
}
|
|
@@ -17046,8 +17304,9 @@ async function runSetupCommand(flags, options) {
|
|
|
17046
17304
|
const stdout = options.stdout ?? process.stdout;
|
|
17047
17305
|
const stderr = options.stderr ?? process.stderr;
|
|
17048
17306
|
const home = resolveGuardianHome(options.env, options.platform);
|
|
17049
|
-
const
|
|
17050
|
-
|
|
17307
|
+
const requestedExtensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
|
|
17308
|
+
const extensionId = requestedExtensionId ?? GUARDIAN_HALO_CHROME_EXTENSION_ID;
|
|
17309
|
+
if (requestedExtensionId && !isValidChromeExtensionId(requestedExtensionId)) {
|
|
17051
17310
|
write(
|
|
17052
17311
|
stderr,
|
|
17053
17312
|
"Invalid --extension-id. Chrome extension ids must be 32 lowercase letters from a-p.\n"
|
|
@@ -17103,10 +17362,80 @@ async function runSetupCommand(flags, options) {
|
|
|
17103
17362
|
}
|
|
17104
17363
|
launch = JSON.parse(launchOutput);
|
|
17105
17364
|
}
|
|
17365
|
+
const requestedHost = stringFlag(flags, "host") ?? "127.0.0.1";
|
|
17366
|
+
const requestedPort = numberFlag(flags, "port") ?? 4317;
|
|
17367
|
+
const requestedControlTowerUrl = `${formatDaemonBaseUrl(requestedHost, requestedPort)}/control-tower`;
|
|
17106
17368
|
const resolvedControlTowerUrl = resolveControlTowerUrl(/* @__PURE__ */ new Map(), options.env, profile);
|
|
17107
|
-
const controlTowerUrl = launch?.controlTowerUrl ?? (resolvedControlTowerUrl.ok ? resolvedControlTowerUrl.url : GUARDIAN_DEFAULT_CONTROL_TOWER_URL);
|
|
17369
|
+
const controlTowerUrl = launch?.controlTowerUrl ?? (flags.has("host") || flags.has("port") ? requestedControlTowerUrl : resolvedControlTowerUrl.ok ? resolvedControlTowerUrl.url : GUARDIAN_DEFAULT_CONTROL_TOWER_URL);
|
|
17370
|
+
if (!launch && (flags.has("host") || flags.has("port"))) {
|
|
17371
|
+
profile.control_tower = {
|
|
17372
|
+
url: controlTowerUrl,
|
|
17373
|
+
source: "env_or_flag"
|
|
17374
|
+
};
|
|
17375
|
+
await writeProfile(home, profile);
|
|
17376
|
+
}
|
|
17108
17377
|
const setupUrl = buildControlTowerSetupUrl(controlTowerUrl);
|
|
17109
|
-
const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId
|
|
17378
|
+
const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId}`;
|
|
17379
|
+
let browserHelper;
|
|
17380
|
+
if (flags.has("no-browser-connection") || flags.has("no-browser-helper")) {
|
|
17381
|
+
browserHelper = {
|
|
17382
|
+
success: false,
|
|
17383
|
+
skipped: true,
|
|
17384
|
+
tokenPrinted: false
|
|
17385
|
+
};
|
|
17386
|
+
} else {
|
|
17387
|
+
let nativeHostOutput = "";
|
|
17388
|
+
let nativeHostError = "";
|
|
17389
|
+
const nativeHostFlags = new Map([
|
|
17390
|
+
["json", true],
|
|
17391
|
+
["force", true],
|
|
17392
|
+
["extension-id", extensionId],
|
|
17393
|
+
...copyStringFlags(flags, ["browser", "target"])
|
|
17394
|
+
]);
|
|
17395
|
+
if ((options.platform ?? process.platform) === "win32") {
|
|
17396
|
+
nativeHostFlags.set("write-registry", true);
|
|
17397
|
+
nativeHostFlags.set("yes", true);
|
|
17398
|
+
}
|
|
17399
|
+
const nativeHostExitCode = await runExtensionCommand(
|
|
17400
|
+
["native-host", "install"],
|
|
17401
|
+
nativeHostFlags,
|
|
17402
|
+
{
|
|
17403
|
+
...options,
|
|
17404
|
+
stdout: {
|
|
17405
|
+
write: (chunk) => {
|
|
17406
|
+
nativeHostOutput += chunk.toString();
|
|
17407
|
+
return true;
|
|
17408
|
+
}
|
|
17409
|
+
},
|
|
17410
|
+
stderr: {
|
|
17411
|
+
write: (chunk) => {
|
|
17412
|
+
nativeHostError += chunk.toString();
|
|
17413
|
+
return true;
|
|
17414
|
+
}
|
|
17415
|
+
}
|
|
17416
|
+
}
|
|
17417
|
+
);
|
|
17418
|
+
if (nativeHostExitCode === 0) {
|
|
17419
|
+
const nativeHost = JSON.parse(nativeHostOutput);
|
|
17420
|
+
browserHelper = {
|
|
17421
|
+
success: true,
|
|
17422
|
+
skipped: false,
|
|
17423
|
+
browser: nativeHost.browser,
|
|
17424
|
+
hostName: nativeHost.hostName,
|
|
17425
|
+
manifestPath: nativeHost.manifestPath,
|
|
17426
|
+
allowedOrigins: nativeHost.allowedOrigins,
|
|
17427
|
+
tokenPrinted: nativeHost.tokenPrinted
|
|
17428
|
+
};
|
|
17429
|
+
} else {
|
|
17430
|
+
browserHelper = {
|
|
17431
|
+
success: false,
|
|
17432
|
+
skipped: false,
|
|
17433
|
+
error: nativeHostError.trim() || "Guardian browser connection setup failed.",
|
|
17434
|
+
exitCode: nativeHostExitCode,
|
|
17435
|
+
tokenPrinted: false
|
|
17436
|
+
};
|
|
17437
|
+
}
|
|
17438
|
+
}
|
|
17110
17439
|
const result = {
|
|
17111
17440
|
schema_version: "contextecf/project-guardian-setup/v1",
|
|
17112
17441
|
success: true,
|
|
@@ -17156,10 +17485,14 @@ async function runSetupCommand(flags, options) {
|
|
|
17156
17485
|
},
|
|
17157
17486
|
browserSetup: {
|
|
17158
17487
|
setupUrl,
|
|
17159
|
-
extensionId
|
|
17488
|
+
extensionId,
|
|
17489
|
+
defaultExtensionId: GUARDIAN_HALO_CHROME_EXTENSION_ID,
|
|
17160
17490
|
opened: false,
|
|
17161
17491
|
tokenPrinted: false,
|
|
17162
|
-
nativeHostCommand
|
|
17492
|
+
nativeHostCommand,
|
|
17493
|
+
connectInstruction: "Open ContextECF Halo and click Connect. No setup code is needed.",
|
|
17494
|
+
manualFallbackCommand: "guardian pair --json",
|
|
17495
|
+
nativeHost: browserHelper
|
|
17163
17496
|
},
|
|
17164
17497
|
nextCommands: [
|
|
17165
17498
|
"guardian status",
|
|
@@ -17168,12 +17501,10 @@ async function runSetupCommand(flags, options) {
|
|
|
17168
17501
|
"guardian policy list",
|
|
17169
17502
|
"guardian posture list",
|
|
17170
17503
|
"guardian preferences show",
|
|
17171
|
-
"guardian extension open-setup",
|
|
17172
|
-
"guardian daemon pair --json",
|
|
17173
17504
|
"guardian service install",
|
|
17174
|
-
"guardian key-store install --yes"
|
|
17175
|
-
|
|
17176
|
-
]
|
|
17505
|
+
"guardian key-store install --yes"
|
|
17506
|
+
],
|
|
17507
|
+
advancedCommands: ["guardian extension connect", nativeHostCommand, "guardian pair --json"]
|
|
17177
17508
|
};
|
|
17178
17509
|
write(
|
|
17179
17510
|
stdout,
|
|
@@ -17186,8 +17517,11 @@ async function runSetupCommand(flags, options) {
|
|
|
17186
17517
|
result.launch.opened ? `Opening: ${result.launch.controlTowerUrl}` : void 0,
|
|
17187
17518
|
`MCP artifacts: ${result.mcp.writtenFiles.length > 0 ? result.mcp.writtenFiles.join(", ") : "skipped" in result.mcp && result.mcp.skipped ? "skipped" : "none"}`,
|
|
17188
17519
|
`Browser setup: ${result.browserSetup.setupUrl}`,
|
|
17520
|
+
result.browserSetup.nativeHost.success ? `Browser connection: ready for ContextECF Halo (${result.browserSetup.extensionId})` : result.browserSetup.nativeHost.skipped ? "Browser connection: skipped" : `Browser connection: needs attention${result.browserSetup.nativeHost.error ? ` (${result.browserSetup.nativeHost.error})` : ""}`,
|
|
17521
|
+
"Extension setup: open ContextECF Halo and click Connect. No setup code needed.",
|
|
17189
17522
|
"Token printed: no",
|
|
17190
|
-
`Next: ${result.nextCommands.join("; ")}
|
|
17523
|
+
`Next: ${result.nextCommands.join("; ")}`,
|
|
17524
|
+
"Help: run guardian connect if the browser says Local Guardian is not connected."
|
|
17191
17525
|
].filter(Boolean).join("\n")}
|
|
17192
17526
|
`
|
|
17193
17527
|
);
|
|
@@ -17262,8 +17596,8 @@ function buildGuardianDistributionReadiness(npmPreviewReady) {
|
|
|
17262
17596
|
},
|
|
17263
17597
|
aiToolIntegration: {
|
|
17264
17598
|
mcpInstallCommand: "guardian mcp install --client=all --write",
|
|
17265
|
-
browserSetupCommand: "guardian
|
|
17266
|
-
nativeHostInstallCommand:
|
|
17599
|
+
browserSetupCommand: "guardian connect",
|
|
17600
|
+
nativeHostInstallCommand: `guardian extension native-host install --extension-id=${GUARDIAN_HALO_CHROME_EXTENSION_ID}`
|
|
17267
17601
|
},
|
|
17268
17602
|
browserStoreHandoff: {
|
|
17269
17603
|
status: npmPreviewReady ? "operator_handoff_ready_not_submitted" : "blocked_until_preview_ready",
|
|
@@ -17279,15 +17613,17 @@ function buildGuardianDistributionReadiness(npmPreviewReady) {
|
|
|
17279
17613
|
workflow: GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
|
|
17280
17614
|
dryRunCommand: buildGuardianReleaseDispatchCommand(true),
|
|
17281
17615
|
publishCommand: buildGuardianReleaseDispatchCommand(false),
|
|
17282
|
-
|
|
17616
|
+
defaultPublishAuth: GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH,
|
|
17617
|
+
tokenFallbackCredentialName: "NPM_TOKEN",
|
|
17283
17618
|
channels: ["all", "npm", "browser", "evidence"],
|
|
17284
17619
|
defaultDockerSmoke: true,
|
|
17285
17620
|
provenance: "github_actions_oidc_supported",
|
|
17286
17621
|
status: npmPreviewReady ? "ready_for_dispatch_after_preview_evidence" : "blocked_until_preview_release_evidence_passes",
|
|
17287
17622
|
boundaries: [
|
|
17288
17623
|
"Use dry_run=true before public publication.",
|
|
17289
|
-
"dry_run=false
|
|
17290
|
-
"The
|
|
17624
|
+
"dry_run=false defaults to npm Trusted Publishing and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17625
|
+
"The token fallback route remains available with publish_auth=token and requires the repository secret NPM_TOKEN.",
|
|
17626
|
+
"The workflow can publish the npm preview package, upload evidence, submit future Chrome Web Store updates for review when browser_store_publish=api, and run public install smokes; it does not sign native installers or prove future browser-store approval.",
|
|
17291
17627
|
"GitHub Actions OIDC/provenance applies to CI release context; manual local publishes are recorded separately and should not claim CI provenance."
|
|
17292
17628
|
]
|
|
17293
17629
|
},
|
|
@@ -17308,12 +17644,16 @@ function buildGuardianReleaseDispatchCommand(dryRun) {
|
|
|
17308
17644
|
});
|
|
17309
17645
|
}
|
|
17310
17646
|
function buildGuardianReleaseDispatchCommandFor(input) {
|
|
17647
|
+
const publishAuth = input.publishAuth ?? GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH;
|
|
17648
|
+
const browserStorePublish = input.browserStorePublish ?? "manual";
|
|
17311
17649
|
return [
|
|
17312
17650
|
`gh workflow run ${GUARDIAN_RELEASE_DISPATCH_WORKFLOW} \\`,
|
|
17313
17651
|
` -f release_version=${input.releaseVersion} \\`,
|
|
17314
17652
|
` -f channels=${input.channels} \\`,
|
|
17315
17653
|
` -f dry_run=${input.dryRun ? "true" : "false"} \\`,
|
|
17316
|
-
` -f run_docker_smoke=${input.runDockerSmoke ? "true" : "false"}
|
|
17654
|
+
` -f run_docker_smoke=${input.runDockerSmoke ? "true" : "false"} \\`,
|
|
17655
|
+
` -f publish_auth=${publishAuth} \\`,
|
|
17656
|
+
` -f browser_store_publish=${browserStorePublish}`
|
|
17317
17657
|
].join("\n");
|
|
17318
17658
|
}
|
|
17319
17659
|
async function runReleaseCommand(argv, flags, options) {
|
|
@@ -17420,11 +17760,23 @@ async function runReleaseCommand(argv, flags, options) {
|
|
|
17420
17760
|
}
|
|
17421
17761
|
const dryRun = flags.has("publish") ? false : booleanFlag(flags, "dry-run", true);
|
|
17422
17762
|
const runDockerSmoke = booleanFlag(flags, "run-docker-smoke", true);
|
|
17763
|
+
const publishAuth = stringFlag(flags, "publish-auth") ?? GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH;
|
|
17764
|
+
if (!isValidReleasePublishAuth(publishAuth)) {
|
|
17765
|
+
write(stderr, "Invalid --publish-auth. Expected one of: token, trusted_publisher.\n");
|
|
17766
|
+
return 1;
|
|
17767
|
+
}
|
|
17768
|
+
const browserStorePublish = stringFlag(flags, "browser-store-publish") ?? "manual";
|
|
17769
|
+
if (!isValidBrowserStorePublish(browserStorePublish)) {
|
|
17770
|
+
write(stderr, "Invalid --browser-store-publish. Expected one of: manual, api.\n");
|
|
17771
|
+
return 1;
|
|
17772
|
+
}
|
|
17423
17773
|
const result = buildGuardianReleaseDispatchCommandResult({
|
|
17424
17774
|
releaseVersion,
|
|
17425
17775
|
channels,
|
|
17426
17776
|
dryRun,
|
|
17427
|
-
runDockerSmoke
|
|
17777
|
+
runDockerSmoke,
|
|
17778
|
+
publishAuth,
|
|
17779
|
+
browserStorePublish
|
|
17428
17780
|
});
|
|
17429
17781
|
write(stdout, renderGuardianReleaseDispatchCommand(result, flags));
|
|
17430
17782
|
return 0;
|
|
@@ -17492,6 +17844,7 @@ function renderGuardianReleaseHelp(result, flags) {
|
|
|
17492
17844
|
`;
|
|
17493
17845
|
}
|
|
17494
17846
|
function buildGuardianReleaseDispatchCommandResult(input) {
|
|
17847
|
+
const npmLaneSelected = input.channels === "all" || input.channels === "npm";
|
|
17495
17848
|
return {
|
|
17496
17849
|
schema_version: "contextecf/project-guardian-release-dispatch-command/v1",
|
|
17497
17850
|
cli_version: GUARDIAN_CLI_VERSION,
|
|
@@ -17500,13 +17853,21 @@ function buildGuardianReleaseDispatchCommandResult(input) {
|
|
|
17500
17853
|
channels: input.channels,
|
|
17501
17854
|
dryRun: input.dryRun,
|
|
17502
17855
|
runDockerSmoke: input.runDockerSmoke,
|
|
17856
|
+
publishAuth: input.publishAuth,
|
|
17857
|
+
browserStorePublish: input.browserStorePublish,
|
|
17503
17858
|
command: buildGuardianReleaseDispatchCommandFor(input),
|
|
17504
|
-
...input.dryRun ? {} : { requiredPublishCredentialName: "NPM_TOKEN" },
|
|
17859
|
+
...input.dryRun || input.publishAuth === "trusted_publisher" || !npmLaneSelected ? {} : { requiredPublishCredentialName: "NPM_TOKEN" },
|
|
17860
|
+
...input.browserStorePublish === "api" && !input.dryRun ? {
|
|
17861
|
+
requiredBrowserStoreCredentialNames: [...GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES]
|
|
17862
|
+
} : {},
|
|
17505
17863
|
provenance: "github_actions_oidc_supported",
|
|
17506
17864
|
boundaries: [
|
|
17507
17865
|
"Use dry_run=true before public publication.",
|
|
17508
|
-
"dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17509
|
-
"
|
|
17866
|
+
"dry_run=false with publish_auth=token requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17867
|
+
"dry_run=false with publish_auth=trusted_publisher requires npm Trusted Publishing to be configured for this GitHub Actions workflow and package.",
|
|
17868
|
+
"browser_store_publish=manual keeps Chrome Web Store upload as an operator ZIP handoff.",
|
|
17869
|
+
"browser_store_publish=api uploads an existing Chrome Web Store item update and submits it for review when Chrome Web Store API secrets are configured.",
|
|
17870
|
+
"This dispatch can publish the npm preview package, upload evidence, submit future Chrome Web Store updates for review, and run public install smokes; it does not sign native installers or prove future browser-store approval.",
|
|
17510
17871
|
"A release-dispatch command is operator guidance, not production-gate proof."
|
|
17511
17872
|
],
|
|
17512
17873
|
tokenPrinted: false,
|
|
@@ -17525,7 +17886,10 @@ function renderGuardianReleaseDispatchCommand(result, flags) {
|
|
|
17525
17886
|
`Workflow: ${result.workflow}`,
|
|
17526
17887
|
`Channels: ${result.channels}`,
|
|
17527
17888
|
`Docker smoke: ${result.runDockerSmoke ? "yes" : "no"}`,
|
|
17528
|
-
|
|
17889
|
+
`Publish auth: ${result.publishAuth}`,
|
|
17890
|
+
`Browser store publish: ${result.browserStorePublish}`,
|
|
17891
|
+
result.requiredPublishCredentialName ? `Required repository secret: ${result.requiredPublishCredentialName}` : result.publishAuth === "trusted_publisher" && !result.dryRun ? "Required npm setup: Trusted Publisher connection" : "Required repository secret: not needed for dry run",
|
|
17892
|
+
result.requiredBrowserStoreCredentialNames ? `Required browser-store secrets: ${result.requiredBrowserStoreCredentialNames.join(", ")}` : "Required browser-store secrets: not needed for manual browser handoff",
|
|
17529
17893
|
"Command:",
|
|
17530
17894
|
result.command,
|
|
17531
17895
|
"Boundaries:",
|
|
@@ -17540,6 +17904,7 @@ function buildGuardianBrowserStoreHandoffCommandResult() {
|
|
|
17540
17904
|
cli_version: GUARDIAN_CLI_VERSION,
|
|
17541
17905
|
status: "chrome_distribution_proven_next_submission_pack_ready",
|
|
17542
17906
|
primaryStore: "chrome_web_store",
|
|
17907
|
+
publicListingUrl: GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL,
|
|
17543
17908
|
productionGate: {
|
|
17544
17909
|
id: "browser-store-distribution",
|
|
17545
17910
|
status: "proven",
|
|
@@ -17606,6 +17971,7 @@ function renderGuardianBrowserStoreHandoffCommand(result, flags) {
|
|
|
17606
17971
|
"Project Guardian Browser Store Handoff",
|
|
17607
17972
|
`Status: ${result.status}`,
|
|
17608
17973
|
`Primary store: ${result.primaryStore}`,
|
|
17974
|
+
`Public listing: ${result.publicListingUrl}`,
|
|
17609
17975
|
`Production gate: ${result.productionGate.id} (${result.productionGate.status})`,
|
|
17610
17976
|
"1. Build submission pack:",
|
|
17611
17977
|
result.commands.submissionPack,
|
|
@@ -17626,15 +17992,25 @@ function renderGuardianBrowserStoreHandoffCommand(result, flags) {
|
|
|
17626
17992
|
`;
|
|
17627
17993
|
}
|
|
17628
17994
|
function buildGuardianReleaseSecretSetup() {
|
|
17995
|
+
const chromeWebStoreSecretMatcher = GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES.join("|");
|
|
17629
17996
|
return {
|
|
17630
17997
|
schema_version: "contextecf/project-guardian-release-secret-setup/v1",
|
|
17631
17998
|
cli_version: GUARDIAN_CLI_VERSION,
|
|
17632
17999
|
repository: GUARDIAN_RELEASE_REPOSITORY,
|
|
17633
|
-
|
|
18000
|
+
defaultPublishAuth: GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH,
|
|
18001
|
+
requiredForPublish: "npm_trusted_publisher_connection",
|
|
18002
|
+
tokenFallbackCredentialName: "NPM_TOKEN",
|
|
18003
|
+
requiredForBrowserStoreApi: GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES,
|
|
17634
18004
|
githubActionsSecretUrl: `https://github.com/${GUARDIAN_RELEASE_REPOSITORY}/settings/secrets/actions/new`,
|
|
17635
18005
|
commands: {
|
|
17636
18006
|
setNpmToken: `gh secret set NPM_TOKEN --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
18007
|
+
setChromeWebStoreClientId: `gh secret set CHROME_WEB_STORE_CLIENT_ID --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
18008
|
+
setChromeWebStoreClientSecret: `gh secret set CHROME_WEB_STORE_CLIENT_SECRET --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
18009
|
+
setChromeWebStoreRefreshToken: `gh secret set CHROME_WEB_STORE_REFRESH_TOKEN --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
18010
|
+
setChromeWebStorePublisherId: `gh secret set CHROME_WEB_STORE_PUBLISHER_ID --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
18011
|
+
setChromeWebStoreExtensionId: `gh secret set CHROME_WEB_STORE_EXTENSION_ID --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
17637
18012
|
verifyNpmTokenPresence: `gh secret list --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions | rg '^NPM_TOKEN\\b'`,
|
|
18013
|
+
verifyChromeWebStoreSecretsPresence: `gh secret list --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions | rg '^(${chromeWebStoreSecretMatcher})\\b'`,
|
|
17638
18014
|
dryRunDispatch: buildGuardianReleaseDispatchCommandFor({
|
|
17639
18015
|
dryRun: true,
|
|
17640
18016
|
releaseVersion: "<version>",
|
|
@@ -17646,13 +18022,24 @@ function buildGuardianReleaseSecretSetup() {
|
|
|
17646
18022
|
releaseVersion: "<version>",
|
|
17647
18023
|
channels: "all",
|
|
17648
18024
|
runDockerSmoke: true
|
|
18025
|
+
}),
|
|
18026
|
+
browserStoreApiPublishDispatch: buildGuardianReleaseDispatchCommandFor({
|
|
18027
|
+
dryRun: false,
|
|
18028
|
+
releaseVersion: "<version>",
|
|
18029
|
+
channels: "browser",
|
|
18030
|
+
runDockerSmoke: true,
|
|
18031
|
+
publishAuth: "trusted_publisher",
|
|
18032
|
+
browserStorePublish: "api"
|
|
17649
18033
|
})
|
|
17650
18034
|
},
|
|
17651
18035
|
boundaries: [
|
|
17652
|
-
"
|
|
18036
|
+
"npm Trusted Publishing is the default Guardian release path and uses this GitHub Actions workflow identity.",
|
|
18037
|
+
"NPM_TOKEN is a fallback credential only; when used, it belongs only in GitHub Actions repository secrets for guarded dry_run=false npm publication.",
|
|
18038
|
+
"Chrome Web Store API OAuth values belong only in GitHub Actions repository secrets for guarded browser_store_publish=api upload/submission.",
|
|
17653
18039
|
"Do not paste npm tokens, OTP values, .npmrc contents, signing keys, browser-store credentials, raw prompts, raw responses, private policy packs, or customer content into chat, PR bodies, release evidence, or CLI output.",
|
|
17654
|
-
"Use dry_run=true before dry_run=false; dry-run dispatch does not require
|
|
17655
|
-
"Adding NPM_TOKEN enables the npm preview publish lane only; it does not close signed-installer, browser-store, high-risk desktop, or autonomous app production gates."
|
|
18040
|
+
"Use dry_run=true before dry_run=false; dry-run dispatch does not require npm publish credentials.",
|
|
18041
|
+
"Adding NPM_TOKEN enables the npm preview publish lane only; it does not close signed-installer, browser-store, high-risk desktop, or autonomous app production gates.",
|
|
18042
|
+
"Chrome Web Store API secrets enable browser update upload/submission only; official review approval evidence is still required for production browser-store claims."
|
|
17656
18043
|
],
|
|
17657
18044
|
tokenPrinted: false,
|
|
17658
18045
|
rawContentIncluded: false
|
|
@@ -17666,16 +18053,28 @@ function renderGuardianReleaseSecretSetup(result, flags) {
|
|
|
17666
18053
|
return `${[
|
|
17667
18054
|
"Project Guardian Release Secret Setup",
|
|
17668
18055
|
`Repository: ${result.repository}`,
|
|
17669
|
-
|
|
18056
|
+
"Default npm publish setup: Trusted Publisher connection",
|
|
18057
|
+
`Fallback npm publish secret: ${result.tokenFallbackCredentialName}`,
|
|
18058
|
+
`Required for Chrome Web Store API: ${result.requiredForBrowserStoreApi.join(", ")}`,
|
|
17670
18059
|
`GitHub Actions secret page: ${result.githubActionsSecretUrl}`,
|
|
17671
|
-
"
|
|
18060
|
+
"NPM publish secret:",
|
|
17672
18061
|
result.commands.setNpmToken,
|
|
17673
|
-
"Verify secret presence:",
|
|
18062
|
+
"Verify npm secret presence:",
|
|
17674
18063
|
result.commands.verifyNpmTokenPresence,
|
|
18064
|
+
"Chrome Web Store API secrets:",
|
|
18065
|
+
result.commands.setChromeWebStoreClientId,
|
|
18066
|
+
result.commands.setChromeWebStoreClientSecret,
|
|
18067
|
+
result.commands.setChromeWebStoreRefreshToken,
|
|
18068
|
+
result.commands.setChromeWebStorePublisherId,
|
|
18069
|
+
result.commands.setChromeWebStoreExtensionId,
|
|
18070
|
+
"Verify Chrome Web Store API secret presence:",
|
|
18071
|
+
result.commands.verifyChromeWebStoreSecretsPresence,
|
|
17675
18072
|
"Dry-run release command:",
|
|
17676
18073
|
result.commands.dryRunDispatch,
|
|
17677
|
-
"
|
|
18074
|
+
"Default publish command with manual browser-store upload:",
|
|
17678
18075
|
result.commands.publishDispatch,
|
|
18076
|
+
"Browser-store API publish command:",
|
|
18077
|
+
result.commands.browserStoreApiPublishDispatch,
|
|
17679
18078
|
"Boundaries:",
|
|
17680
18079
|
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
17681
18080
|
"Token printed: no"
|
|
@@ -17706,7 +18105,8 @@ function buildGuardianReleaseChecklist(releaseVersion) {
|
|
|
17706
18105
|
browserStoreHandoff: "guardian release browser-store",
|
|
17707
18106
|
readiness: "guardian readiness"
|
|
17708
18107
|
},
|
|
17709
|
-
|
|
18108
|
+
defaultPublishAuth: GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH,
|
|
18109
|
+
tokenFallbackCredentialName: "NPM_TOKEN",
|
|
17710
18110
|
evidenceOutputs: [
|
|
17711
18111
|
"release/evidence/guardian-release-dispatch-summary.json",
|
|
17712
18112
|
"release/evidence/guardian-npm-publish-execution-summary.json",
|
|
@@ -17723,7 +18123,8 @@ function buildGuardianReleaseChecklist(releaseVersion) {
|
|
|
17723
18123
|
boundaries: [
|
|
17724
18124
|
"This checklist is an operator command surface for Guardian preview releases; it is not production-gate proof.",
|
|
17725
18125
|
"Run the dry-run dispatch before any dry_run=false publish dispatch.",
|
|
17726
|
-
"dry_run=false
|
|
18126
|
+
"dry_run=false defaults to npm Trusted Publishing and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
18127
|
+
"The token fallback route remains available with publish_auth=token and requires NPM_TOKEN in GitHub Actions repository secrets.",
|
|
17727
18128
|
"The checklist does not sign native installers, submit browser-store packages, execute high-risk desktop actions, or enable autonomous local app execution.",
|
|
17728
18129
|
"Full production claims remain blocked until every not-proven production gate has real validated external evidence."
|
|
17729
18130
|
],
|
|
@@ -17761,7 +18162,7 @@ function buildGuardianReleaseFlow(releaseVersion) {
|
|
|
17761
18162
|
},
|
|
17762
18163
|
{
|
|
17763
18164
|
id: "verify-secrets",
|
|
17764
|
-
label: "Verify npm
|
|
18165
|
+
label: "Verify npm Trusted Publisher setup or token fallback",
|
|
17765
18166
|
command: "guardian release secrets",
|
|
17766
18167
|
credentialRequired: false
|
|
17767
18168
|
},
|
|
@@ -17775,7 +18176,7 @@ function buildGuardianReleaseFlow(releaseVersion) {
|
|
|
17775
18176
|
id: "publish-dispatch",
|
|
17776
18177
|
label: "Run the guarded publish dispatch after dry-run evidence passes",
|
|
17777
18178
|
command: publishDispatch,
|
|
17778
|
-
credentialRequired:
|
|
18179
|
+
credentialRequired: false
|
|
17779
18180
|
},
|
|
17780
18181
|
{
|
|
17781
18182
|
id: "verify-public-release",
|
|
@@ -17811,7 +18212,8 @@ function buildGuardianReleaseFlow(releaseVersion) {
|
|
|
17811
18212
|
})),
|
|
17812
18213
|
boundaries: [
|
|
17813
18214
|
"This release flow is copy-paste operator guidance only; it is not release evidence or production-gate proof.",
|
|
17814
|
-
"Publish dispatch
|
|
18215
|
+
"Publish dispatch defaults to npm Trusted Publishing and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
18216
|
+
"The token fallback route remains available with publish_auth=token and requires NPM_TOKEN in GitHub Actions repository secrets.",
|
|
17815
18217
|
"Run the dry-run dispatch before the guarded dry_run=false publish dispatch.",
|
|
17816
18218
|
"Public npm preview publication and local install smoke prove the CLI preview lane only.",
|
|
17817
18219
|
"Signed native installers, high-risk desktop action execution, and autonomous local app execution remain separate not-proven production gates until real external evidence is collected and validated."
|
|
@@ -17860,7 +18262,8 @@ function renderGuardianReleaseChecklist(result, flags) {
|
|
|
17860
18262
|
`Release: ${result.releaseVersion}`,
|
|
17861
18263
|
`Repository: ${result.repository}`,
|
|
17862
18264
|
`Status: ${result.status}`,
|
|
17863
|
-
|
|
18265
|
+
"Default npm publish setup: Trusted Publisher connection",
|
|
18266
|
+
`Fallback npm publish secret: ${result.tokenFallbackCredentialName}`,
|
|
17864
18267
|
"1. Secret setup:",
|
|
17865
18268
|
result.operatorCommands.secretSetup,
|
|
17866
18269
|
"2. Dry-run dispatch:",
|
|
@@ -17896,9 +18299,9 @@ function buildGuardianReleaseVerify(releaseVersion) {
|
|
|
17896
18299
|
commands: {
|
|
17897
18300
|
registryVersion: `npm view ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion} version --registry=${GUARDIAN_NPM_REGISTRY}`,
|
|
17898
18301
|
publicInstall: `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion}`,
|
|
18302
|
+
chromeWebStoreListing: GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL,
|
|
17899
18303
|
installedVersion: "guardian --version",
|
|
17900
18304
|
setup: "guardian setup",
|
|
17901
|
-
launch: "guardian launch",
|
|
17902
18305
|
status: "guardian status",
|
|
17903
18306
|
openControlTower: "guardian open",
|
|
17904
18307
|
copyPasteLocalSmoke,
|
|
@@ -17927,9 +18330,8 @@ function buildGuardianReleasePaste(releaseVersion) {
|
|
|
17927
18330
|
"guardian --version",
|
|
17928
18331
|
"guardian stop",
|
|
17929
18332
|
"guardian setup",
|
|
17930
|
-
"guardian
|
|
17931
|
-
"guardian open"
|
|
17932
|
-
"guardian status"
|
|
18333
|
+
"guardian status",
|
|
18334
|
+
"guardian open"
|
|
17933
18335
|
];
|
|
17934
18336
|
return {
|
|
17935
18337
|
schema_version: "contextecf/project-guardian-release-paste/v1",
|
|
@@ -17940,9 +18342,9 @@ function buildGuardianReleasePaste(releaseVersion) {
|
|
|
17940
18342
|
command: commands.join("\n"),
|
|
17941
18343
|
commands,
|
|
17942
18344
|
boundaries: [
|
|
17943
|
-
"This paste block verifies public npm visibility, global install, first-run setup,
|
|
18345
|
+
"This paste block verifies public npm visibility, global install, stale-process cleanup, first-run setup, Local Guardian status, and Control Tower open.",
|
|
17944
18346
|
"It does not publish to npm and must not include npm tokens, OTP values, .npmrc contents, signing keys, browser-store credentials, raw prompts, raw responses, private policy packs, or customer content.",
|
|
17945
|
-
"guardian stop is included before setup so stale
|
|
18347
|
+
"guardian stop is included before setup so stale Local Guardian processes or local token mismatches are cleared before setup relaunches the local service."
|
|
17946
18348
|
],
|
|
17947
18349
|
tokenPrinted: false,
|
|
17948
18350
|
rawContentIncluded: false
|
|
@@ -17969,18 +18371,19 @@ function renderGuardianReleaseVerify(result, flags) {
|
|
|
17969
18371
|
`Status: ${result.status}`,
|
|
17970
18372
|
"1. Confirm registry visibility:",
|
|
17971
18373
|
result.commands.registryVersion,
|
|
17972
|
-
"2.
|
|
18374
|
+
"2. Confirm public Chrome Web Store listing:",
|
|
18375
|
+
result.commands.chromeWebStoreListing,
|
|
18376
|
+
"3. Install the published version:",
|
|
17973
18377
|
result.commands.publicInstall,
|
|
17974
|
-
"
|
|
18378
|
+
"4. Confirm installed CLI version:",
|
|
17975
18379
|
result.commands.installedVersion,
|
|
17976
|
-
"
|
|
18380
|
+
"5. Run first-use smoke:",
|
|
17977
18381
|
result.commands.setup,
|
|
17978
|
-
result.commands.launch,
|
|
17979
18382
|
result.commands.status,
|
|
17980
18383
|
result.commands.openControlTower,
|
|
17981
|
-
"
|
|
18384
|
+
"6. Copy-paste local smoke block:",
|
|
17982
18385
|
result.commands.copyPasteLocalSmoke,
|
|
17983
|
-
"
|
|
18386
|
+
"7. Verify release evidence:",
|
|
17984
18387
|
result.commands.publishStatusVerification,
|
|
17985
18388
|
result.commands.finishLineStatus,
|
|
17986
18389
|
"Evidence outputs:",
|
|
@@ -17997,6 +18400,12 @@ function isValidReleaseVersion(value) {
|
|
|
17997
18400
|
function isValidReleaseChannels(value) {
|
|
17998
18401
|
return ["all", "npm", "browser", "evidence"].includes(value);
|
|
17999
18402
|
}
|
|
18403
|
+
function isValidReleasePublishAuth(value) {
|
|
18404
|
+
return value === "token" || value === "trusted_publisher";
|
|
18405
|
+
}
|
|
18406
|
+
function isValidBrowserStorePublish(value) {
|
|
18407
|
+
return value === "manual" || value === "api";
|
|
18408
|
+
}
|
|
18000
18409
|
function renderGuardianProductionReadiness(result, flags) {
|
|
18001
18410
|
if (flags.has("json")) {
|
|
18002
18411
|
return `${JSON.stringify(result, null, 2)}
|
|
@@ -18099,9 +18508,9 @@ async function statusGuardian(flags, options) {
|
|
|
18099
18508
|
`Profile: ${home}`,
|
|
18100
18509
|
`Runtime profile: ${result.runtime.profileDaemonStatus}`,
|
|
18101
18510
|
`Control Tower: ${result.controlTowerUrl ?? "not configured"}`,
|
|
18102
|
-
`
|
|
18103
|
-
result.daemon.error ? `
|
|
18104
|
-
result.daemonVersionMismatch ? `
|
|
18511
|
+
`Local Guardian: ${result.daemon.status}${result.daemon.statusCode ? ` (HTTP ${result.daemon.statusCode})` : ""}`,
|
|
18512
|
+
result.daemon.error ? `Connection detail: ${result.daemon.error}` : void 0,
|
|
18513
|
+
result.daemonVersionMismatch ? `Local Guardian version: ${result.daemonVersionMismatch.daemonVersion} (this CLI is ${result.daemonVersionMismatch.cliVersion} \u2014 versions differ, likely because the CLI was reinstalled or changed version while Local Guardian kept running; run guardian stop && guardian launch to restart it on the current version)` : void 0,
|
|
18105
18514
|
`MCP stdio: ${result.runtime.mcpStdioAvailable ? "available" : "unavailable"}`,
|
|
18106
18515
|
`Posture Profile: ${result.postureProfile.selected}`,
|
|
18107
18516
|
`Prompt Coach: ${result.preferences.promptCoachMode}`,
|
|
@@ -18208,7 +18617,7 @@ async function runLaunchCommand(flags, options) {
|
|
|
18208
18617
|
nextCommands: [
|
|
18209
18618
|
"guardian open",
|
|
18210
18619
|
"guardian status",
|
|
18211
|
-
"
|
|
18620
|
+
"Open ContextECF Halo and click Connect",
|
|
18212
18621
|
"guardian policy list"
|
|
18213
18622
|
]
|
|
18214
18623
|
};
|
|
@@ -18217,7 +18626,7 @@ async function runLaunchCommand(flags, options) {
|
|
|
18217
18626
|
flags.has("json") ? `${JSON.stringify(result, null, 2)}
|
|
18218
18627
|
` : `${[
|
|
18219
18628
|
"Project Guardian launched.",
|
|
18220
|
-
`
|
|
18629
|
+
`Local Guardian: ${result.daemonUrl}${result.reusedExistingDaemon ? " (already running)" : ""}`,
|
|
18221
18630
|
`Control Tower: ${result.controlTowerUrl}`,
|
|
18222
18631
|
shouldOpen ? `Opening: ${result.controlTowerUrl}` : void 0,
|
|
18223
18632
|
"Next: guardian open; guardian status"
|
|
@@ -18328,14 +18737,14 @@ async function runStartCommand(flags, options) {
|
|
|
18328
18737
|
controlTowerUrl: requestedControlTowerUrl,
|
|
18329
18738
|
healthUrl,
|
|
18330
18739
|
healthStatus: "reachable",
|
|
18331
|
-
nextCommands: ["guardian open", "guardian status", "
|
|
18740
|
+
nextCommands: ["guardian open", "guardian status", "Open ContextECF Halo and click Connect"]
|
|
18332
18741
|
};
|
|
18333
18742
|
write(
|
|
18334
18743
|
stdout,
|
|
18335
18744
|
flags.has("json") ? `${JSON.stringify(result2, null, 2)}
|
|
18336
18745
|
` : `${[
|
|
18337
|
-
"Guardian
|
|
18338
|
-
`
|
|
18746
|
+
"Local Guardian already running.",
|
|
18747
|
+
`Local Guardian: ${requestedDaemonUrl}`,
|
|
18339
18748
|
`Control Tower: ${requestedControlTowerUrl}`,
|
|
18340
18749
|
"Next: guardian open"
|
|
18341
18750
|
].join("\n")}
|
|
@@ -18344,7 +18753,7 @@ async function runStartCommand(flags, options) {
|
|
|
18344
18753
|
return 0;
|
|
18345
18754
|
}
|
|
18346
18755
|
if (!options.startDetachedDaemon) {
|
|
18347
|
-
write(stderr, "Guardian
|
|
18756
|
+
write(stderr, "Guardian local background launcher is unavailable in this runtime.\n");
|
|
18348
18757
|
return 1;
|
|
18349
18758
|
}
|
|
18350
18759
|
const started = await options.startDetachedDaemon({ home, host, port: selected.port });
|
|
@@ -18365,14 +18774,14 @@ async function runStartCommand(flags, options) {
|
|
|
18365
18774
|
pid: started.pid,
|
|
18366
18775
|
healthUrl,
|
|
18367
18776
|
healthStatus: existing.error ? "unreachable" : "not_reachable",
|
|
18368
|
-
nextCommands: ["guardian open", "guardian status", "
|
|
18777
|
+
nextCommands: ["guardian open", "guardian status", "Open ContextECF Halo and click Connect"]
|
|
18369
18778
|
};
|
|
18370
18779
|
write(
|
|
18371
18780
|
stdout,
|
|
18372
18781
|
flags.has("json") ? `${JSON.stringify(result, null, 2)}
|
|
18373
18782
|
` : `${[
|
|
18374
|
-
"Guardian
|
|
18375
|
-
`
|
|
18783
|
+
"Local Guardian start requested.",
|
|
18784
|
+
`Local Guardian: ${daemonUrl}`,
|
|
18376
18785
|
`Control Tower: ${controlTowerUrl}`,
|
|
18377
18786
|
started.pid ? `PID: ${started.pid}` : void 0,
|
|
18378
18787
|
"Next: guardian open"
|
|
@@ -18383,8 +18792,8 @@ async function runStartCommand(flags, options) {
|
|
|
18383
18792
|
}
|
|
18384
18793
|
function renderDaemonTokenMismatchMessage(requestedDaemonUrl, port) {
|
|
18385
18794
|
return [
|
|
18386
|
-
`Guardian found another
|
|
18387
|
-
"This usually means an older Guardian
|
|
18795
|
+
`Guardian found another local service or container at ${requestedDaemonUrl}, but it rejected this profile's local connection token.`,
|
|
18796
|
+
"This usually means an older Guardian background service or Docker demo is still using the port.",
|
|
18388
18797
|
`Recovery: stop the other process/container, or run Guardian on a different port with guardian launch --port=${port + 1}.`,
|
|
18389
18798
|
`Diagnostics: guardian status; docker ps --filter publish=${port}`,
|
|
18390
18799
|
""
|
|
@@ -18417,7 +18826,7 @@ async function runStopCommand(flags, options) {
|
|
|
18417
18826
|
if (!stopped.ok) {
|
|
18418
18827
|
write(
|
|
18419
18828
|
stderr,
|
|
18420
|
-
`Guardian
|
|
18829
|
+
`Local Guardian did not stop cleanly${stopped.statusCode ? ` (HTTP ${stopped.statusCode})` : ""}: ${stopped.error ?? "unknown_error"}
|
|
18421
18830
|
`
|
|
18422
18831
|
);
|
|
18423
18832
|
return 1;
|
|
@@ -18428,12 +18837,12 @@ async function runStopCommand(flags, options) {
|
|
|
18428
18837
|
success: true,
|
|
18429
18838
|
daemonStatus: profile.runtime.daemon_status,
|
|
18430
18839
|
stopUrl: stopUrl.url,
|
|
18431
|
-
note: "Guardian
|
|
18840
|
+
note: "Local Guardian stop requested."
|
|
18432
18841
|
};
|
|
18433
18842
|
write(
|
|
18434
18843
|
stdout,
|
|
18435
18844
|
flags.has("json") ? `${JSON.stringify(result, null, 2)}
|
|
18436
|
-
` : `${["Guardian
|
|
18845
|
+
` : `${["Local Guardian stop requested.", "Status: not_started_mvp"].join("\n")}
|
|
18437
18846
|
`
|
|
18438
18847
|
);
|
|
18439
18848
|
return 0;
|
|
@@ -18505,7 +18914,7 @@ Proof: ${result2.proofPath}
|
|
|
18505
18914
|
}
|
|
18506
18915
|
const host = stringFlag(flags, "host") ?? "127.0.0.1";
|
|
18507
18916
|
if (!isLoopbackHost(host)) {
|
|
18508
|
-
write(stderr, "Guardian service supervision only accepts loopback
|
|
18917
|
+
write(stderr, "Guardian service supervision only accepts loopback Local Guardian hosts.\n");
|
|
18509
18918
|
return 1;
|
|
18510
18919
|
}
|
|
18511
18920
|
const port = numberFlag(flags, "port") ?? 4317;
|
|
@@ -18762,7 +19171,7 @@ async function daemonPair(flags, options) {
|
|
|
18762
19171
|
[GUARDIAN_BRIDGE_CONFIG_STORAGE_KEY]: bridgeConfig,
|
|
18763
19172
|
[GUARDIAN_BRIDGE_TOKEN_STORAGE_KEY]: token
|
|
18764
19173
|
},
|
|
18765
|
-
note: "
|
|
19174
|
+
note: "Advanced fallback only. Most users should run guardian setup, open ContextECF Halo, and click Connect."
|
|
18766
19175
|
};
|
|
18767
19176
|
if (flags.has("json")) {
|
|
18768
19177
|
return { exitCode: 0, message: `${JSON.stringify(pairing, null, 2)}
|
|
@@ -18771,13 +19180,10 @@ async function daemonPair(flags, options) {
|
|
|
18771
19180
|
return {
|
|
18772
19181
|
exitCode: 0,
|
|
18773
19182
|
message: `${[
|
|
18774
|
-
"Guardian browser
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
`Native host: ${pairing.nativeHostName}`,
|
|
18779
|
-
`Token: ${pairing.token}`,
|
|
18780
|
-
pairing.note
|
|
19183
|
+
"Guardian browser connection uses one-click setup now.",
|
|
19184
|
+
"Run guardian connect, then open ContextECF Halo and click Connect.",
|
|
19185
|
+
"Support setup codes are only printed by guardian pair --json.",
|
|
19186
|
+
"Token printed: no"
|
|
18781
19187
|
].join("\n")}
|
|
18782
19188
|
`
|
|
18783
19189
|
};
|
|
@@ -18786,6 +19192,9 @@ async function runExtensionCommand(argv, flags, options) {
|
|
|
18786
19192
|
const subcommand = argv[0] ?? "native-host";
|
|
18787
19193
|
const stdout = options.stdout ?? process.stdout;
|
|
18788
19194
|
const stderr = options.stderr ?? process.stderr;
|
|
19195
|
+
if (subcommand === "connect") {
|
|
19196
|
+
return runExtensionConnectCommand(flags, options);
|
|
19197
|
+
}
|
|
18789
19198
|
if (subcommand === "open-setup") {
|
|
18790
19199
|
return runExtensionOpenSetupCommand(flags, options);
|
|
18791
19200
|
}
|
|
@@ -18973,13 +19382,18 @@ Re-run with --force to replace it.
|
|
|
18973
19382
|
registryMutationRequested: writeRegistry,
|
|
18974
19383
|
registryProofPath,
|
|
18975
19384
|
tokenPrinted: false,
|
|
18976
|
-
nextCommands: [
|
|
19385
|
+
nextCommands: [
|
|
19386
|
+
"guardian launch",
|
|
19387
|
+
"Open ContextECF Halo and click Connect",
|
|
19388
|
+
"guardian extension native-host status"
|
|
19389
|
+
],
|
|
19390
|
+
advancedCommands: ["guardian pair --json"]
|
|
18977
19391
|
};
|
|
18978
19392
|
write(
|
|
18979
19393
|
stdout,
|
|
18980
19394
|
flags.has("json") ? `${JSON.stringify(result, null, 2)}
|
|
18981
19395
|
` : `${[
|
|
18982
|
-
"Guardian
|
|
19396
|
+
"Guardian browser connection installed.",
|
|
18983
19397
|
`Browser: ${browser}`,
|
|
18984
19398
|
`Host: ${plan.hostName}`,
|
|
18985
19399
|
`Manifest: ${plan.manifestPath}`,
|
|
@@ -18994,6 +19408,121 @@ Re-run with --force to replace it.
|
|
|
18994
19408
|
);
|
|
18995
19409
|
return 0;
|
|
18996
19410
|
}
|
|
19411
|
+
async function runExtensionConnectCommand(flags, options) {
|
|
19412
|
+
const stdout = options.stdout ?? process.stdout;
|
|
19413
|
+
const stderr = options.stderr ?? process.stderr;
|
|
19414
|
+
const requestedExtensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
|
|
19415
|
+
const extensionId = requestedExtensionId ?? GUARDIAN_HALO_CHROME_EXTENSION_ID;
|
|
19416
|
+
if (requestedExtensionId && !isValidChromeExtensionId(requestedExtensionId)) {
|
|
19417
|
+
write(
|
|
19418
|
+
stderr,
|
|
19419
|
+
"Invalid --extension-id. Chrome extension ids must be 32 lowercase letters from a-p.\n"
|
|
19420
|
+
);
|
|
19421
|
+
return 1;
|
|
19422
|
+
}
|
|
19423
|
+
const install = JSON.parse(await installGuardian(/* @__PURE__ */ new Map([["json", true]]), options));
|
|
19424
|
+
let launchOutput = "";
|
|
19425
|
+
const launchFlags = new Map([
|
|
19426
|
+
["json", true],
|
|
19427
|
+
["print", true],
|
|
19428
|
+
...copyStringFlags(flags, ["host", "port"])
|
|
19429
|
+
]);
|
|
19430
|
+
const launchExitCode = await runLaunchCommand(launchFlags, {
|
|
19431
|
+
...options,
|
|
19432
|
+
stdout: {
|
|
19433
|
+
write: (chunk) => {
|
|
19434
|
+
launchOutput += chunk.toString();
|
|
19435
|
+
return true;
|
|
19436
|
+
}
|
|
19437
|
+
},
|
|
19438
|
+
stderr
|
|
19439
|
+
});
|
|
19440
|
+
if (launchExitCode !== 0) {
|
|
19441
|
+
return launchExitCode;
|
|
19442
|
+
}
|
|
19443
|
+
const launch = JSON.parse(launchOutput);
|
|
19444
|
+
const helperFlags = new Map([
|
|
19445
|
+
["json", true],
|
|
19446
|
+
["force", true],
|
|
19447
|
+
["extension-id", extensionId],
|
|
19448
|
+
...copyStringFlags(flags, ["browser", "target"])
|
|
19449
|
+
]);
|
|
19450
|
+
if ((options.platform ?? process.platform) === "win32") {
|
|
19451
|
+
helperFlags.set("write-registry", true);
|
|
19452
|
+
helperFlags.set("yes", true);
|
|
19453
|
+
}
|
|
19454
|
+
let helperOutput = "";
|
|
19455
|
+
let helperError = "";
|
|
19456
|
+
const helperExitCode = await runExtensionCommand(["native-host", "install"], helperFlags, {
|
|
19457
|
+
...options,
|
|
19458
|
+
stdout: {
|
|
19459
|
+
write: (chunk) => {
|
|
19460
|
+
helperOutput += chunk.toString();
|
|
19461
|
+
return true;
|
|
19462
|
+
}
|
|
19463
|
+
},
|
|
19464
|
+
stderr: {
|
|
19465
|
+
write: (chunk) => {
|
|
19466
|
+
helperError += chunk.toString();
|
|
19467
|
+
return true;
|
|
19468
|
+
}
|
|
19469
|
+
}
|
|
19470
|
+
});
|
|
19471
|
+
if (helperExitCode !== 0) {
|
|
19472
|
+
write(
|
|
19473
|
+
stderr,
|
|
19474
|
+
helperError.trim() ? `${helperError.trim()}
|
|
19475
|
+
` : "Guardian could not prepare the browser connection. Run guardian setup, then try again.\n"
|
|
19476
|
+
);
|
|
19477
|
+
return helperExitCode;
|
|
19478
|
+
}
|
|
19479
|
+
const helper = JSON.parse(helperOutput);
|
|
19480
|
+
const result = {
|
|
19481
|
+
schema_version: "contextecf/project-guardian-browser-connect/v1",
|
|
19482
|
+
success: true,
|
|
19483
|
+
extensionId,
|
|
19484
|
+
defaultExtensionId: GUARDIAN_HALO_CHROME_EXTENSION_ID,
|
|
19485
|
+
install: {
|
|
19486
|
+
profileDir: install.profileDir,
|
|
19487
|
+
tokenCreated: install.tokenCreated,
|
|
19488
|
+
tokenPrinted: false
|
|
19489
|
+
},
|
|
19490
|
+
localGuardian: {
|
|
19491
|
+
running: true,
|
|
19492
|
+
opened: launch.opened,
|
|
19493
|
+
reusedExistingDaemon: launch.reusedExistingDaemon,
|
|
19494
|
+
daemonUrl: launch.daemonUrl,
|
|
19495
|
+
controlTowerUrl: launch.controlTowerUrl,
|
|
19496
|
+
pid: launch.pid,
|
|
19497
|
+
healthStatus: launch.healthStatus
|
|
19498
|
+
},
|
|
19499
|
+
browser: helper.browser,
|
|
19500
|
+
helperInstalled: true,
|
|
19501
|
+
helperStatus: {
|
|
19502
|
+
hostName: helper.hostName,
|
|
19503
|
+
manifestPath: helper.manifestPath,
|
|
19504
|
+
allowedOrigins: helper.allowedOrigins,
|
|
19505
|
+
tokenPrinted: helper.tokenPrinted
|
|
19506
|
+
},
|
|
19507
|
+
tokenPrinted: false,
|
|
19508
|
+
nextCommands: ["Open ContextECF Halo and click Connect", "guardian open", "guardian status"],
|
|
19509
|
+
supportCommands: ["guardian extension open-setup --print", "guardian pair --json"]
|
|
19510
|
+
};
|
|
19511
|
+
write(
|
|
19512
|
+
stdout,
|
|
19513
|
+
flags.has("json") ? `${JSON.stringify(result, null, 2)}
|
|
19514
|
+
` : `${[
|
|
19515
|
+
"Guardian browser connection is ready.",
|
|
19516
|
+
`Local Guardian: ${result.localGuardian.daemonUrl}${result.localGuardian.reusedExistingDaemon ? " (already running)" : ""}`,
|
|
19517
|
+
`Browser: ${result.browser}`,
|
|
19518
|
+
"Next: open ContextECF Halo and click Connect.",
|
|
19519
|
+
"No setup code needed.",
|
|
19520
|
+
"Token printed: no"
|
|
19521
|
+
].join("\n")}
|
|
19522
|
+
`
|
|
19523
|
+
);
|
|
19524
|
+
return 0;
|
|
19525
|
+
}
|
|
18997
19526
|
async function runExtensionOpenSetupCommand(flags, options) {
|
|
18998
19527
|
const stdout = options.stdout ?? process.stdout;
|
|
18999
19528
|
const stderr = options.stderr ?? process.stderr;
|
|
@@ -19003,8 +19532,9 @@ async function runExtensionOpenSetupCommand(flags, options) {
|
|
|
19003
19532
|
write(stderr, "Guardian is not installed. Run guardian install first.\n");
|
|
19004
19533
|
return 1;
|
|
19005
19534
|
}
|
|
19006
|
-
const
|
|
19007
|
-
|
|
19535
|
+
const requestedExtensionId = stringFlag(flags, "extension-id") ?? stringFlag(flags, "id");
|
|
19536
|
+
const extensionId = requestedExtensionId ?? GUARDIAN_HALO_CHROME_EXTENSION_ID;
|
|
19537
|
+
if (requestedExtensionId && !isValidChromeExtensionId(requestedExtensionId)) {
|
|
19008
19538
|
write(
|
|
19009
19539
|
stderr,
|
|
19010
19540
|
"Invalid --extension-id. Chrome extension ids must be 32 lowercase letters from a-p.\n"
|
|
@@ -19018,22 +19548,24 @@ async function runExtensionOpenSetupCommand(flags, options) {
|
|
|
19018
19548
|
return 1;
|
|
19019
19549
|
}
|
|
19020
19550
|
const setupUrl = buildControlTowerSetupUrl(resolved.url);
|
|
19021
|
-
const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId
|
|
19551
|
+
const nativeHostCommand = `guardian extension native-host install --extension-id=${extensionId}`;
|
|
19022
19552
|
const result = {
|
|
19023
19553
|
schema_version: "contextecf/project-guardian-extension-setup/v1",
|
|
19024
19554
|
success: true,
|
|
19025
19555
|
opened: !flags.has("print"),
|
|
19026
19556
|
controlTowerUrl: resolved.url,
|
|
19027
19557
|
setupUrl,
|
|
19028
|
-
extensionId
|
|
19558
|
+
extensionId,
|
|
19559
|
+
defaultExtensionId: GUARDIAN_HALO_CHROME_EXTENSION_ID,
|
|
19029
19560
|
tokenPrinted: false,
|
|
19030
19561
|
nextCommands: [
|
|
19031
19562
|
"guardian launch",
|
|
19032
|
-
"guardian daemon pair --json",
|
|
19033
19563
|
nativeHostCommand,
|
|
19034
|
-
"guardian extension native-host status"
|
|
19564
|
+
"guardian extension native-host status",
|
|
19565
|
+
"Open ContextECF Halo and click Connect"
|
|
19035
19566
|
],
|
|
19036
|
-
|
|
19567
|
+
advancedCommands: ["guardian pair --json"],
|
|
19568
|
+
note: extensionId ? "Guardian browser setup opened for ContextECF Halo." : "Guardian browser setup opened."
|
|
19037
19569
|
};
|
|
19038
19570
|
if (result.opened) {
|
|
19039
19571
|
const opener = options.openUrl ?? ((url2) => openUrlInDefaultBrowser(url2, options));
|
|
@@ -19045,7 +19577,8 @@ async function runExtensionOpenSetupCommand(flags, options) {
|
|
|
19045
19577
|
` : `${[
|
|
19046
19578
|
result.opened ? `Opening Guardian browser setup: ${setupUrl}` : `Guardian browser setup: ${setupUrl}`,
|
|
19047
19579
|
"Token printed: no",
|
|
19048
|
-
`Next: ${result.nextCommands.join("; ")}
|
|
19580
|
+
`Next: ${result.nextCommands.join("; ")}`,
|
|
19581
|
+
`Advanced fallback: ${result.advancedCommands.join("; ")}`
|
|
19049
19582
|
].join("\n")}
|
|
19050
19583
|
`
|
|
19051
19584
|
);
|
|
@@ -19572,7 +20105,7 @@ function buildGuardianServiceArtifact(input) {
|
|
|
19572
20105
|
if (input.platform === "systemd") {
|
|
19573
20106
|
return `${[
|
|
19574
20107
|
"[Unit]",
|
|
19575
|
-
"Description=Project Guardian
|
|
20108
|
+
"Description=Project Guardian Local Guardian background service",
|
|
19576
20109
|
"After=network.target",
|
|
19577
20110
|
"",
|
|
19578
20111
|
"[Service]",
|
|
@@ -19591,7 +20124,7 @@ function buildGuardianServiceArtifact(input) {
|
|
|
19591
20124
|
'<?xml version="1.0" encoding="UTF-16"?>',
|
|
19592
20125
|
'<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">',
|
|
19593
20126
|
" <RegistrationInfo>",
|
|
19594
|
-
" <Description>Project Guardian
|
|
20127
|
+
" <Description>Project Guardian Local Guardian background service</Description>",
|
|
19595
20128
|
" </RegistrationInfo>",
|
|
19596
20129
|
" <Triggers>",
|
|
19597
20130
|
" <LogonTrigger><Enabled>true</Enabled></LogonTrigger>",
|
|
@@ -20573,6 +21106,59 @@ async function runReceiptsCommand(argv, flags, options) {
|
|
|
20573
21106
|
write(stdout, await verifyReceipts(flags, options));
|
|
20574
21107
|
return 0;
|
|
20575
21108
|
}
|
|
21109
|
+
async function runCoachCommand(argv, flags, options) {
|
|
21110
|
+
const subcommand = argv[0] ?? "options";
|
|
21111
|
+
const stdout = options.stdout ?? process.stdout;
|
|
21112
|
+
const stderr = options.stderr ?? process.stderr;
|
|
21113
|
+
if (subcommand === "options" || subcommand === "catalog") {
|
|
21114
|
+
write(stdout, renderGuardianPromptCardOptions(buildGuardianPromptCardOptions(), flags));
|
|
21115
|
+
return 0;
|
|
21116
|
+
}
|
|
21117
|
+
write(stderr, `Unknown Guardian coach command: ${subcommand}
|
|
21118
|
+
`);
|
|
21119
|
+
return 1;
|
|
21120
|
+
}
|
|
21121
|
+
function buildGuardianPromptCardOptions() {
|
|
21122
|
+
return {
|
|
21123
|
+
schema_version: "contextecf/project-guardian-prompt-card-options/v1",
|
|
21124
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
21125
|
+
status: "catalog_ready",
|
|
21126
|
+
summary: "Guardian prompt cards keep the user in control: warnings and safer rewrites can be sent as-is, while hard blocks cannot.",
|
|
21127
|
+
catalog: GUARDIAN_PROMPT_CARD_OPTIONS_CATALOG,
|
|
21128
|
+
rules: [
|
|
21129
|
+
"Show a clear reason before asking the user to decide.",
|
|
21130
|
+
"Offer Send as-is for warnings and safer rewrites when policy allows override.",
|
|
21131
|
+
"Never offer Send as-is for hard blocks or unavailable Local Guardian checks.",
|
|
21132
|
+
"Keep Edit prompt available as the safe path for every visible send-time card.",
|
|
21133
|
+
"Do not store raw sensitive prompt text in this catalog or CLI output."
|
|
21134
|
+
],
|
|
21135
|
+
tokenPrinted: false,
|
|
21136
|
+
rawContentIncluded: false
|
|
21137
|
+
};
|
|
21138
|
+
}
|
|
21139
|
+
function renderGuardianPromptCardOptions(result, flags) {
|
|
21140
|
+
if (flags.has("json")) {
|
|
21141
|
+
return `${JSON.stringify(result, null, 2)}
|
|
21142
|
+
`;
|
|
21143
|
+
}
|
|
21144
|
+
return `${[
|
|
21145
|
+
"Guardian Prompt Card Options",
|
|
21146
|
+
result.summary,
|
|
21147
|
+
"",
|
|
21148
|
+
"Programmed cards:",
|
|
21149
|
+
...result.catalog.map((entry) => {
|
|
21150
|
+
const visibleActions = entry.actions.filter((action) => action.visibleToUser).map((action) => action.label);
|
|
21151
|
+
const labels = visibleActions.length > 0 ? visibleActions.join(", ") : "Prompt sends automatically";
|
|
21152
|
+
return `- ${entry.cardStyle}: ${labels}`;
|
|
21153
|
+
}),
|
|
21154
|
+
"",
|
|
21155
|
+
"Rules:",
|
|
21156
|
+
...result.rules.map((rule) => `- ${rule}`),
|
|
21157
|
+
"Token printed: no",
|
|
21158
|
+
"Raw prompt content included: no"
|
|
21159
|
+
].join("\n")}
|
|
21160
|
+
`;
|
|
21161
|
+
}
|
|
20576
21162
|
async function runPolicyCommand(argv, flags, options) {
|
|
20577
21163
|
const subcommand = argv[0] ?? "list";
|
|
20578
21164
|
const stdout = options.stdout ?? process.stdout;
|
|
@@ -23003,15 +23589,19 @@ function openUrlInDefaultBrowser(url2, options = {}) {
|
|
|
23003
23589
|
});
|
|
23004
23590
|
}
|
|
23005
23591
|
export {
|
|
23592
|
+
GUARDIAN_CHROME_WEB_STORE_API_SECRET_NAMES,
|
|
23006
23593
|
GUARDIAN_CLI_VERSION,
|
|
23007
23594
|
GUARDIAN_CONTROL_TOWER_URL_ENV,
|
|
23008
23595
|
GUARDIAN_DEFAULT_CONTROL_TOWER_URL,
|
|
23596
|
+
GUARDIAN_DEFAULT_NPM_PUBLISH_AUTH,
|
|
23009
23597
|
GUARDIAN_DESKTOP_ADAPTER_SIMULATE_OPEN_ENV,
|
|
23010
23598
|
GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_ID,
|
|
23011
23599
|
GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_PROOF_SCHEMA_VERSION,
|
|
23012
23600
|
GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_VERSION,
|
|
23013
23601
|
GUARDIAN_FIRST_RUN_COMMAND,
|
|
23014
23602
|
GUARDIAN_GLOBAL_INSTALL_COMMAND,
|
|
23603
|
+
GUARDIAN_HALO_CHROME_EXTENSION_ID,
|
|
23604
|
+
GUARDIAN_HALO_CHROME_WEB_STORE_LISTING_URL,
|
|
23015
23605
|
GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV,
|
|
23016
23606
|
GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV,
|
|
23017
23607
|
GUARDIAN_NOT_PROVEN_PRODUCTION_GATES,
|
|
@@ -23024,6 +23614,7 @@ export {
|
|
|
23024
23614
|
GUARDIAN_POSTURE_PROFILE_CATALOG,
|
|
23025
23615
|
GUARDIAN_POSTURE_PROFILE_IDS,
|
|
23026
23616
|
GUARDIAN_PROFILE_SCHEMA_VERSION,
|
|
23617
|
+
GUARDIAN_PROMPT_CARD_OPTIONS_CATALOG,
|
|
23027
23618
|
GUARDIAN_PROVIDER_IDS,
|
|
23028
23619
|
GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
|
|
23029
23620
|
GUARDIAN_RELEASE_REPOSITORY,
|