@contextecf/guardian-cli 0.1.2 → 0.1.4
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 +93 -15
- package/dist/packages/guardian-cli/src/bin.js +1073 -49
- package/dist/packages/guardian-cli/src/index.js +885 -43
- package/dist/packages/guardian-cli/src/runtime.d.ts +214 -2
- package/package.json +2 -2
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __esm = (fn, res) => function __init() {
|
|
5
|
-
|
|
4
|
+
var __esm = (fn, res, err) => function __init() {
|
|
5
|
+
if (err) throw err[0];
|
|
6
|
+
try {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
} catch (e) {
|
|
9
|
+
throw err = [e], e;
|
|
10
|
+
}
|
|
6
11
|
};
|
|
7
12
|
var __export = (target, all) => {
|
|
8
13
|
for (var name in all)
|
|
@@ -73,7 +78,7 @@ var init_core = __esm({
|
|
|
73
78
|
NEVER = /* @__PURE__ */ Object.freeze({
|
|
74
79
|
status: "aborted"
|
|
75
80
|
});
|
|
76
|
-
$brand = Symbol("zod_brand");
|
|
81
|
+
$brand = /* @__PURE__ */ Symbol("zod_brand");
|
|
77
82
|
$ZodAsyncError = class extends Error {
|
|
78
83
|
constructor() {
|
|
79
84
|
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
|
@@ -10242,8 +10247,8 @@ function registry() {
|
|
|
10242
10247
|
var _a2, $output, $input, $ZodRegistry, globalRegistry;
|
|
10243
10248
|
var init_registries = __esm({
|
|
10244
10249
|
"node_modules/zod/v4/core/registries.js"() {
|
|
10245
|
-
$output = Symbol("ZodOutput");
|
|
10246
|
-
$input = Symbol("ZodInput");
|
|
10250
|
+
$output = /* @__PURE__ */ Symbol("ZodOutput");
|
|
10251
|
+
$input = /* @__PURE__ */ Symbol("ZodInput");
|
|
10247
10252
|
$ZodRegistry = class {
|
|
10248
10253
|
constructor() {
|
|
10249
10254
|
this._map = /* @__PURE__ */ new WeakMap();
|
|
@@ -17052,6 +17057,8 @@ async function runGuardianCli(argv, options = {}) {
|
|
|
17052
17057
|
write(stdout, renderGuardianProductionReadiness(readiness, flags));
|
|
17053
17058
|
return flags.has("strict") && (readiness.npmPreview.status !== "ready" || readiness.fullProduction.status !== "ready") ? 1 : 0;
|
|
17054
17059
|
}
|
|
17060
|
+
case "release":
|
|
17061
|
+
return runReleaseCommand(argv.slice(1), flags, options);
|
|
17055
17062
|
case "open":
|
|
17056
17063
|
return runControlTowerOpenCommand(flags, options);
|
|
17057
17064
|
case "status":
|
|
@@ -17205,7 +17212,7 @@ async function installGuardian(flags, options = {}) {
|
|
|
17205
17212
|
`First run: ${GUARDIAN_FIRST_RUN_COMMAND}`,
|
|
17206
17213
|
`Open Control Tower: ${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}`,
|
|
17207
17214
|
`No global install: ${GUARDIAN_NPX_SETUP_COMMAND}`,
|
|
17208
|
-
"Next: guardian setup; guardian doctor; guardian readiness; guardian launch; guardian mcp install; guardian extension open-setup; guardian daemon pair --json; guardian extension native-host install --extension-id=<browser-extension-id>"
|
|
17215
|
+
"Next: guardian setup; guardian doctor; guardian readiness; guardian launch; guardian open; guardian mcp install; guardian extension open-setup; guardian daemon pair --json; guardian extension native-host install --extension-id=<browser-extension-id>"
|
|
17209
17216
|
].join("\n")}
|
|
17210
17217
|
`;
|
|
17211
17218
|
}
|
|
@@ -17252,7 +17259,7 @@ async function runSetupCommand(flags, options) {
|
|
|
17252
17259
|
["json", true],
|
|
17253
17260
|
...copyStringFlags(flags, ["host", "port"])
|
|
17254
17261
|
]);
|
|
17255
|
-
if (flags.has("print")) {
|
|
17262
|
+
if (!flags.has("open") || flags.has("print")) {
|
|
17256
17263
|
launchFlags.set("print", true);
|
|
17257
17264
|
}
|
|
17258
17265
|
const launchExitCode = await runLaunchCommand(launchFlags, {
|
|
@@ -17331,6 +17338,7 @@ async function runSetupCommand(flags, options) {
|
|
|
17331
17338
|
nextCommands: [
|
|
17332
17339
|
"guardian status",
|
|
17333
17340
|
"guardian readiness",
|
|
17341
|
+
"guardian open",
|
|
17334
17342
|
"guardian policy list",
|
|
17335
17343
|
"guardian posture list",
|
|
17336
17344
|
"guardian preferences show",
|
|
@@ -17408,10 +17416,761 @@ async function buildGuardianProductionReadinessStatus(home, profile, env = proce
|
|
|
17408
17416
|
productionGateEvidenceStatus: protectedEvidence.productionGateEvidence?.status ?? "not_recorded",
|
|
17409
17417
|
productionGateEvidencePath: protectedEvidence.productionGateEvidence?.evidencePath
|
|
17410
17418
|
},
|
|
17419
|
+
distribution: buildGuardianDistributionReadiness(npmPreviewReady),
|
|
17420
|
+
tokenPrinted: false,
|
|
17421
|
+
rawContentIncluded: false
|
|
17422
|
+
};
|
|
17423
|
+
}
|
|
17424
|
+
function buildGuardianDistributionReadiness(npmPreviewReady) {
|
|
17425
|
+
return {
|
|
17426
|
+
status: npmPreviewReady ? "preview_install_ready" : "setup_or_release_evidence_required",
|
|
17427
|
+
oneLineInstallCommand: GUARDIAN_GLOBAL_INSTALL_COMMAND,
|
|
17428
|
+
oneLineTryCommand: GUARDIAN_NPX_SETUP_COMMAND,
|
|
17429
|
+
openControlTowerCommand: GUARDIAN_OPEN_CONTROL_TOWER_COMMAND,
|
|
17430
|
+
localUserCommands: {
|
|
17431
|
+
setup: GUARDIAN_FIRST_RUN_COMMAND,
|
|
17432
|
+
launch: "guardian launch",
|
|
17433
|
+
open: "guardian open",
|
|
17434
|
+
status: "guardian status",
|
|
17435
|
+
readiness: "guardian readiness"
|
|
17436
|
+
},
|
|
17437
|
+
aiToolIntegration: {
|
|
17438
|
+
mcpInstallCommand: "guardian mcp install --client=all --write",
|
|
17439
|
+
browserSetupCommand: "guardian extension open-setup",
|
|
17440
|
+
nativeHostInstallCommand: "guardian extension native-host install --extension-id=<browser-extension-id>"
|
|
17441
|
+
},
|
|
17442
|
+
browserStoreHandoff: {
|
|
17443
|
+
status: npmPreviewReady ? "operator_handoff_ready_not_submitted" : "blocked_until_preview_ready",
|
|
17444
|
+
submissionPackCommand: "npm run guardian:browser-store:submission-pack",
|
|
17445
|
+
closeoutChecklistPath: "release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json",
|
|
17446
|
+
productionGateStatus: "not_proven"
|
|
17447
|
+
},
|
|
17448
|
+
enterpriseDeployment: {
|
|
17449
|
+
status: "managed_rollout_ready_for_customer_pack",
|
|
17450
|
+
note: "Use enterprise policy packs, managed browser deployment, and customer evidence as a separate company or school-district rollout lane; it does not prove public browser-store distribution."
|
|
17451
|
+
},
|
|
17452
|
+
releaseAutomation: {
|
|
17453
|
+
workflow: GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
|
|
17454
|
+
dryRunCommand: buildGuardianReleaseDispatchCommand(true),
|
|
17455
|
+
publishCommand: buildGuardianReleaseDispatchCommand(false),
|
|
17456
|
+
requiredPublishCredentialName: "NPM_TOKEN",
|
|
17457
|
+
channels: ["all", "npm", "browser", "evidence"],
|
|
17458
|
+
defaultDockerSmoke: true,
|
|
17459
|
+
provenance: "github_actions_oidc_supported",
|
|
17460
|
+
status: npmPreviewReady ? "ready_for_dispatch_after_preview_evidence" : "blocked_until_preview_release_evidence_passes",
|
|
17461
|
+
boundaries: [
|
|
17462
|
+
"Use dry_run=true before public publication.",
|
|
17463
|
+
"dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17464
|
+
"The workflow can publish the npm preview package, upload evidence, and run public install smokes; it does not sign native installers or approve future browser-store listings.",
|
|
17465
|
+
"GitHub Actions OIDC/provenance applies to CI release context; manual local publishes are recorded separately and should not claim CI provenance."
|
|
17466
|
+
]
|
|
17467
|
+
},
|
|
17468
|
+
boundaries: [
|
|
17469
|
+
"One-line npm install and Control Tower launch prove preview distribution only.",
|
|
17470
|
+
"Chrome Web Store distribution is proven for the evidenced ContextECF Halo listing; future store submissions still require fresh official review evidence.",
|
|
17471
|
+
"Enterprise managed deployment can support company or school-district rollout but remains a separate rollout lane.",
|
|
17472
|
+
"MCP and browser setup commands must not print runtime tokens, raw prompts, raw responses, source archives, source maps, credentials, or private policy packs."
|
|
17473
|
+
]
|
|
17474
|
+
};
|
|
17475
|
+
}
|
|
17476
|
+
function buildGuardianReleaseDispatchCommand(dryRun) {
|
|
17477
|
+
return buildGuardianReleaseDispatchCommandFor({
|
|
17478
|
+
dryRun,
|
|
17479
|
+
releaseVersion: "<version>",
|
|
17480
|
+
channels: "all",
|
|
17481
|
+
runDockerSmoke: true
|
|
17482
|
+
});
|
|
17483
|
+
}
|
|
17484
|
+
function buildGuardianReleaseDispatchCommandFor(input2) {
|
|
17485
|
+
return [
|
|
17486
|
+
`gh workflow run ${GUARDIAN_RELEASE_DISPATCH_WORKFLOW} \\`,
|
|
17487
|
+
` -f release_version=${input2.releaseVersion} \\`,
|
|
17488
|
+
` -f channels=${input2.channels} \\`,
|
|
17489
|
+
` -f dry_run=${input2.dryRun ? "true" : "false"} \\`,
|
|
17490
|
+
` -f run_docker_smoke=${input2.runDockerSmoke ? "true" : "false"}`
|
|
17491
|
+
].join("\n");
|
|
17492
|
+
}
|
|
17493
|
+
async function runReleaseCommand(argv, flags, options) {
|
|
17494
|
+
const subcommand = argv[0];
|
|
17495
|
+
const stdout = options.stdout ?? process.stdout;
|
|
17496
|
+
const stderr = options.stderr ?? process.stderr;
|
|
17497
|
+
if (!subcommand || subcommand === "help" || subcommand === "quickstart") {
|
|
17498
|
+
write(stdout, renderGuardianReleaseHelp(buildGuardianReleaseHelp(), flags));
|
|
17499
|
+
return 0;
|
|
17500
|
+
}
|
|
17501
|
+
if (subcommand === "browser-store" || subcommand === "browser-store-handoff" || subcommand === "store") {
|
|
17502
|
+
write(
|
|
17503
|
+
stdout,
|
|
17504
|
+
renderGuardianBrowserStoreHandoffCommand(
|
|
17505
|
+
buildGuardianBrowserStoreHandoffCommandResult(),
|
|
17506
|
+
flags
|
|
17507
|
+
)
|
|
17508
|
+
);
|
|
17509
|
+
return 0;
|
|
17510
|
+
}
|
|
17511
|
+
if (subcommand === "secrets" || subcommand === "secret-setup" || subcommand === "npm-token") {
|
|
17512
|
+
write(stdout, renderGuardianReleaseSecretSetup(buildGuardianReleaseSecretSetup(), flags));
|
|
17513
|
+
return 0;
|
|
17514
|
+
}
|
|
17515
|
+
if (subcommand === "checklist" || subcommand === "plan") {
|
|
17516
|
+
const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
|
|
17517
|
+
if (!releaseVersion2) {
|
|
17518
|
+
write(
|
|
17519
|
+
stderr,
|
|
17520
|
+
"Missing release version. Usage: guardian release checklist --version=<semver>\n"
|
|
17521
|
+
);
|
|
17522
|
+
return 1;
|
|
17523
|
+
}
|
|
17524
|
+
if (!isValidReleaseVersion(releaseVersion2)) {
|
|
17525
|
+
write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
|
|
17526
|
+
return 1;
|
|
17527
|
+
}
|
|
17528
|
+
write(
|
|
17529
|
+
stdout,
|
|
17530
|
+
renderGuardianReleaseChecklist(buildGuardianReleaseChecklist(releaseVersion2), flags)
|
|
17531
|
+
);
|
|
17532
|
+
return 0;
|
|
17533
|
+
}
|
|
17534
|
+
if (subcommand === "flow" || subcommand === "train" || subcommand === "next") {
|
|
17535
|
+
const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
|
|
17536
|
+
if (!releaseVersion2) {
|
|
17537
|
+
write(stderr, "Missing release version. Usage: guardian release flow --version=<semver>\n");
|
|
17538
|
+
return 1;
|
|
17539
|
+
}
|
|
17540
|
+
if (!isValidReleaseVersion(releaseVersion2)) {
|
|
17541
|
+
write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
|
|
17542
|
+
return 1;
|
|
17543
|
+
}
|
|
17544
|
+
write(stdout, renderGuardianReleaseFlow(buildGuardianReleaseFlow(releaseVersion2), flags));
|
|
17545
|
+
return 0;
|
|
17546
|
+
}
|
|
17547
|
+
if (subcommand === "verify" || subcommand === "post-release") {
|
|
17548
|
+
const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
|
|
17549
|
+
if (!releaseVersion2) {
|
|
17550
|
+
write(stderr, "Missing release version. Usage: guardian release verify --version=<semver>\n");
|
|
17551
|
+
return 1;
|
|
17552
|
+
}
|
|
17553
|
+
if (!isValidReleaseVersion(releaseVersion2)) {
|
|
17554
|
+
write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
|
|
17555
|
+
return 1;
|
|
17556
|
+
}
|
|
17557
|
+
write(stdout, renderGuardianReleaseVerify(buildGuardianReleaseVerify(releaseVersion2), flags));
|
|
17558
|
+
return 0;
|
|
17559
|
+
}
|
|
17560
|
+
if (subcommand === "paste" || subcommand === "smoke" || subcommand === "install-smoke") {
|
|
17561
|
+
const releaseVersion2 = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
|
|
17562
|
+
if (!releaseVersion2) {
|
|
17563
|
+
write(stderr, "Missing release version. Usage: guardian release paste --version=<semver>\n");
|
|
17564
|
+
return 1;
|
|
17565
|
+
}
|
|
17566
|
+
if (!isValidReleaseVersion(releaseVersion2)) {
|
|
17567
|
+
write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
|
|
17568
|
+
return 1;
|
|
17569
|
+
}
|
|
17570
|
+
write(stdout, renderGuardianReleasePaste(buildGuardianReleasePaste(releaseVersion2), flags));
|
|
17571
|
+
return 0;
|
|
17572
|
+
}
|
|
17573
|
+
if (subcommand !== "command" && subcommand !== "dispatch") {
|
|
17574
|
+
write(stderr, `Unknown Guardian release command: ${subcommand}
|
|
17575
|
+
`);
|
|
17576
|
+
return 1;
|
|
17577
|
+
}
|
|
17578
|
+
const releaseVersion = stringFlag(flags, "version") ?? stringFlag(flags, "release-version");
|
|
17579
|
+
if (!releaseVersion) {
|
|
17580
|
+
write(
|
|
17581
|
+
stderr,
|
|
17582
|
+
"Missing release version. Usage: guardian release command --version=<semver> [--publish|--dry-run=false]\n"
|
|
17583
|
+
);
|
|
17584
|
+
return 1;
|
|
17585
|
+
}
|
|
17586
|
+
if (!isValidReleaseVersion(releaseVersion)) {
|
|
17587
|
+
write(stderr, "Invalid --version. Expected a semver value like 0.1.4 or 0.1.4-beta.1.\n");
|
|
17588
|
+
return 1;
|
|
17589
|
+
}
|
|
17590
|
+
const channels = stringFlag(flags, "channels") ?? "all";
|
|
17591
|
+
if (!isValidReleaseChannels(channels)) {
|
|
17592
|
+
write(stderr, "Invalid --channels. Expected one of: all, npm, browser, evidence.\n");
|
|
17593
|
+
return 1;
|
|
17594
|
+
}
|
|
17595
|
+
const dryRun = flags.has("publish") ? false : booleanFlag(flags, "dry-run", true);
|
|
17596
|
+
const runDockerSmoke = booleanFlag(flags, "run-docker-smoke", true);
|
|
17597
|
+
const result = buildGuardianReleaseDispatchCommandResult({
|
|
17598
|
+
releaseVersion,
|
|
17599
|
+
channels,
|
|
17600
|
+
dryRun,
|
|
17601
|
+
runDockerSmoke
|
|
17602
|
+
});
|
|
17603
|
+
write(stdout, renderGuardianReleaseDispatchCommand(result, flags));
|
|
17604
|
+
return 0;
|
|
17605
|
+
}
|
|
17606
|
+
function buildGuardianReleaseHelp() {
|
|
17607
|
+
return {
|
|
17608
|
+
schema_version: "contextecf/project-guardian-release-help/v1",
|
|
17609
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
17610
|
+
repository: GUARDIAN_RELEASE_REPOSITORY,
|
|
17611
|
+
status: "release_owner_quickstart",
|
|
17612
|
+
commands: {
|
|
17613
|
+
checklist: "guardian release checklist --version=<version>",
|
|
17614
|
+
flow: "guardian release flow --version=<version>",
|
|
17615
|
+
secrets: "guardian release secrets",
|
|
17616
|
+
dryRunDispatch: "guardian release command --version=<version>",
|
|
17617
|
+
publishDispatch: "guardian release command --version=<version> --publish",
|
|
17618
|
+
verifyPublishedVersion: "guardian release verify --version=<version>",
|
|
17619
|
+
pasteLocalSmoke: "guardian release paste --version=<version>",
|
|
17620
|
+
browserStoreHandoff: "guardian release browser-store",
|
|
17621
|
+
readiness: "guardian readiness"
|
|
17622
|
+
},
|
|
17623
|
+
suggestedOrder: [
|
|
17624
|
+
"Run the checklist for the target version.",
|
|
17625
|
+
"Set or verify the repository publish credential if this is a public npm release.",
|
|
17626
|
+
"Run the dry-run dispatch before any publish dispatch.",
|
|
17627
|
+
"Run the publish dispatch only after dry-run evidence passes.",
|
|
17628
|
+
"Verify the published version and refresh release evidence.",
|
|
17629
|
+
"Use browser-store handoff only for submission/review evidence; it does not upload or approve listings."
|
|
17630
|
+
],
|
|
17631
|
+
boundaries: [
|
|
17632
|
+
"Release quickstart output is operator guidance only, not release evidence or production-gate proof.",
|
|
17633
|
+
"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 release commands, chat, PR bodies, or evidence.",
|
|
17634
|
+
"Public npm preview publication does not close signed-installer, browser-store, high-risk desktop action, or autonomous local app execution production gates.",
|
|
17635
|
+
"Full production claims remain blocked until every not-proven production gate has real validated external evidence."
|
|
17636
|
+
],
|
|
17637
|
+
tokenPrinted: false,
|
|
17638
|
+
rawContentIncluded: false
|
|
17639
|
+
};
|
|
17640
|
+
}
|
|
17641
|
+
function renderGuardianReleaseHelp(result, flags) {
|
|
17642
|
+
if (flags.has("json")) {
|
|
17643
|
+
return `${JSON.stringify(result, null, 2)}
|
|
17644
|
+
`;
|
|
17645
|
+
}
|
|
17646
|
+
return `${[
|
|
17647
|
+
"Project Guardian Release Quickstart",
|
|
17648
|
+
`Repository: ${result.repository}`,
|
|
17649
|
+
`Status: ${result.status}`,
|
|
17650
|
+
"Commands:",
|
|
17651
|
+
`- Checklist: ${result.commands.checklist}`,
|
|
17652
|
+
`- Flow: ${result.commands.flow}`,
|
|
17653
|
+
`- Secrets: ${result.commands.secrets}`,
|
|
17654
|
+
`- Dry run: ${result.commands.dryRunDispatch}`,
|
|
17655
|
+
`- Publish: ${result.commands.publishDispatch}`,
|
|
17656
|
+
`- Verify published version: ${result.commands.verifyPublishedVersion}`,
|
|
17657
|
+
`- Copy-paste local smoke: ${result.commands.pasteLocalSmoke}`,
|
|
17658
|
+
`- Browser-store handoff: ${result.commands.browserStoreHandoff}`,
|
|
17659
|
+
`- Readiness: ${result.commands.readiness}`,
|
|
17660
|
+
"Suggested order:",
|
|
17661
|
+
...result.suggestedOrder.map((step, index) => `${index + 1}. ${step}`),
|
|
17662
|
+
"Boundaries:",
|
|
17663
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
17664
|
+
"Token printed: no"
|
|
17665
|
+
].join("\n")}
|
|
17666
|
+
`;
|
|
17667
|
+
}
|
|
17668
|
+
function buildGuardianReleaseDispatchCommandResult(input2) {
|
|
17669
|
+
return {
|
|
17670
|
+
schema_version: "contextecf/project-guardian-release-dispatch-command/v1",
|
|
17671
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
17672
|
+
workflow: GUARDIAN_RELEASE_DISPATCH_WORKFLOW,
|
|
17673
|
+
releaseVersion: input2.releaseVersion,
|
|
17674
|
+
channels: input2.channels,
|
|
17675
|
+
dryRun: input2.dryRun,
|
|
17676
|
+
runDockerSmoke: input2.runDockerSmoke,
|
|
17677
|
+
command: buildGuardianReleaseDispatchCommandFor(input2),
|
|
17678
|
+
...input2.dryRun ? {} : { requiredPublishCredentialName: "NPM_TOKEN" },
|
|
17679
|
+
provenance: "github_actions_oidc_supported",
|
|
17680
|
+
boundaries: [
|
|
17681
|
+
"Use dry_run=true before public publication.",
|
|
17682
|
+
"dry_run=false requires the repository secret NPM_TOKEN and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17683
|
+
"This dispatch can publish the npm preview package, upload evidence, and run public install smokes; it does not sign native installers or approve future browser-store listings.",
|
|
17684
|
+
"A release-dispatch command is operator guidance, not production-gate proof."
|
|
17685
|
+
],
|
|
17686
|
+
tokenPrinted: false,
|
|
17687
|
+
rawContentIncluded: false
|
|
17688
|
+
};
|
|
17689
|
+
}
|
|
17690
|
+
function renderGuardianReleaseDispatchCommand(result, flags) {
|
|
17691
|
+
if (flags.has("json")) {
|
|
17692
|
+
return `${JSON.stringify(result, null, 2)}
|
|
17693
|
+
`;
|
|
17694
|
+
}
|
|
17695
|
+
return `${[
|
|
17696
|
+
"Project Guardian Release Dispatch Command",
|
|
17697
|
+
`Release: ${result.releaseVersion}`,
|
|
17698
|
+
`Mode: ${result.dryRun ? "dry run" : "publish"}`,
|
|
17699
|
+
`Workflow: ${result.workflow}`,
|
|
17700
|
+
`Channels: ${result.channels}`,
|
|
17701
|
+
`Docker smoke: ${result.runDockerSmoke ? "yes" : "no"}`,
|
|
17702
|
+
result.requiredPublishCredentialName ? `Required repository secret: ${result.requiredPublishCredentialName}` : "Required repository secret: not needed for dry run",
|
|
17703
|
+
"Command:",
|
|
17704
|
+
result.command,
|
|
17705
|
+
"Boundaries:",
|
|
17706
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
17707
|
+
"Token printed: no"
|
|
17708
|
+
].join("\n")}
|
|
17709
|
+
`;
|
|
17710
|
+
}
|
|
17711
|
+
function buildGuardianBrowserStoreHandoffCommandResult() {
|
|
17712
|
+
return {
|
|
17713
|
+
schema_version: "contextecf/project-guardian-browser-store-handoff-command/v1",
|
|
17714
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
17715
|
+
status: "chrome_distribution_proven_next_submission_pack_ready",
|
|
17716
|
+
primaryStore: "chrome_web_store",
|
|
17717
|
+
productionGate: {
|
|
17718
|
+
id: "browser-store-distribution",
|
|
17719
|
+
status: "proven",
|
|
17720
|
+
nextSubmissionRequiresFreshOfficialReviewEvidence: true
|
|
17721
|
+
},
|
|
17722
|
+
commands: {
|
|
17723
|
+
submissionPack: "npm run guardian:browser-store:submission-pack -- --json --output-dir release/evidence/guardian-browser-store-submission-pack",
|
|
17724
|
+
preSubmissionSmoke: "GUARDIAN_BROWSER_STORE_SMOKE_WORKSPACE=/tmp/guardian-browser-store-pre-submission-smoke bash release/evidence/guardian-browser-store-submission-pack/run-pre-submission-readiness-smoke.sh",
|
|
17725
|
+
preSubmissionReadiness: [
|
|
17726
|
+
"npm run guardian:browser-store:readiness:collect -- \\",
|
|
17727
|
+
" --package artifacts/guardian-browser-store/guardian-browser-extension-<version>.zip \\",
|
|
17728
|
+
" --assert-pre-submission-only \\",
|
|
17729
|
+
" --assert-mv3-validation-passed \\",
|
|
17730
|
+
" --assert-source-archive-excluded \\",
|
|
17731
|
+
" --assert-store-credentials-excluded \\",
|
|
17732
|
+
" --output release/evidence/guardian-browser-store-submission-pack/pre-submission-readiness.json"
|
|
17733
|
+
].join("\n"),
|
|
17734
|
+
reviewPreflightAfterApproval: [
|
|
17735
|
+
"npm run guardian:browser-store:review-preflight -- \\",
|
|
17736
|
+
" --store-evidence release/evidence/guardian-browser-store-submission-pack/browser-store-evidence-input.json \\",
|
|
17737
|
+
" --assert-metadata-only \\",
|
|
17738
|
+
" --assert-no-store-credentials \\",
|
|
17739
|
+
" --assert-approved-review-status \\",
|
|
17740
|
+
" --assert-public-listing-url \\",
|
|
17741
|
+
" --output release/evidence/guardian-browser-store-submission-pack/browser-store-review-preflight.json"
|
|
17742
|
+
].join("\n"),
|
|
17743
|
+
collectorAfterApproval: [
|
|
17744
|
+
"npm run guardian:production-gates:collect:browser-store -- \\",
|
|
17745
|
+
" --store-evidence release/evidence/guardian-browser-store-submission-pack/browser-store-evidence-input.json \\",
|
|
17746
|
+
" --review-preflight-summary release/evidence/guardian-browser-store-submission-pack/browser-store-review-preflight.json \\",
|
|
17747
|
+
" --assert-no-source-archives \\",
|
|
17748
|
+
" --assert-package-digest-matches-release \\",
|
|
17749
|
+
" --assert-listing-matches-release-boundary \\",
|
|
17750
|
+
" --assert-listing-names-not-proven-gates \\",
|
|
17751
|
+
" --assert-production-claim-absent \\",
|
|
17752
|
+
" --output release/evidence/guardian-production-gates/browser-store-distribution.json"
|
|
17753
|
+
].join("\n"),
|
|
17754
|
+
finalGateValidation: "npm run validate:guardian-production-gates -- --claim production"
|
|
17755
|
+
},
|
|
17756
|
+
evidence: {
|
|
17757
|
+
submissionPackDir: "release/evidence/guardian-browser-store-submission-pack",
|
|
17758
|
+
closeoutChecklistPath: "release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json",
|
|
17759
|
+
preSubmissionChecklistPath: "docs/project-guardian/browser-store-pre-submission-checklist.md",
|
|
17760
|
+
readinessOutput: "release/evidence/guardian-browser-store-submission-pack/pre-submission-readiness.json",
|
|
17761
|
+
reviewPreflightOutput: "release/evidence/guardian-browser-store-submission-pack/browser-store-review-preflight.json",
|
|
17762
|
+
productionGatePacket: "release/evidence/guardian-production-gates/browser-store-distribution.json"
|
|
17763
|
+
},
|
|
17764
|
+
boundaries: [
|
|
17765
|
+
"This command surface prepares browser-store submission handoff for future extension versions; it does not upload, submit, approve, or distribute the extension.",
|
|
17766
|
+
"Chrome Web Store distribution is proven for the evidenced ContextECF Halo listing; each future extension package still needs fresh review/submission evidence before updating that proof.",
|
|
17767
|
+
"Do not place browser-store credentials, dashboard cookies, source archives, source maps, runtime tokens, private policy packs, raw prompts, raw responses, or customer content in browser-store evidence.",
|
|
17768
|
+
"Enterprise managed browser deployment is a separate customer rollout lane and does not replace public store review evidence for public listings."
|
|
17769
|
+
],
|
|
17770
|
+
tokenPrinted: false,
|
|
17771
|
+
rawContentIncluded: false
|
|
17772
|
+
};
|
|
17773
|
+
}
|
|
17774
|
+
function renderGuardianBrowserStoreHandoffCommand(result, flags) {
|
|
17775
|
+
if (flags.has("json")) {
|
|
17776
|
+
return `${JSON.stringify(result, null, 2)}
|
|
17777
|
+
`;
|
|
17778
|
+
}
|
|
17779
|
+
return `${[
|
|
17780
|
+
"Project Guardian Browser Store Handoff",
|
|
17781
|
+
`Status: ${result.status}`,
|
|
17782
|
+
`Primary store: ${result.primaryStore}`,
|
|
17783
|
+
`Production gate: ${result.productionGate.id} (${result.productionGate.status})`,
|
|
17784
|
+
"1. Build submission pack:",
|
|
17785
|
+
result.commands.submissionPack,
|
|
17786
|
+
"2. Run pre-submission smoke:",
|
|
17787
|
+
result.commands.preSubmissionSmoke,
|
|
17788
|
+
"3. Record pre-submission readiness:",
|
|
17789
|
+
result.commands.preSubmissionReadiness,
|
|
17790
|
+
"4. After official approval, run review preflight:",
|
|
17791
|
+
result.commands.reviewPreflightAfterApproval,
|
|
17792
|
+
"5. After official approval, collect production-gate evidence:",
|
|
17793
|
+
result.commands.collectorAfterApproval,
|
|
17794
|
+
`Closeout checklist: ${result.evidence.closeoutChecklistPath}`,
|
|
17795
|
+
`Pre-submission checklist: ${result.evidence.preSubmissionChecklistPath}`,
|
|
17796
|
+
"Boundaries:",
|
|
17797
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
17798
|
+
"Token printed: no"
|
|
17799
|
+
].join("\n")}
|
|
17800
|
+
`;
|
|
17801
|
+
}
|
|
17802
|
+
function buildGuardianReleaseSecretSetup() {
|
|
17803
|
+
return {
|
|
17804
|
+
schema_version: "contextecf/project-guardian-release-secret-setup/v1",
|
|
17805
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
17806
|
+
repository: GUARDIAN_RELEASE_REPOSITORY,
|
|
17807
|
+
requiredForPublish: "NPM_TOKEN",
|
|
17808
|
+
githubActionsSecretUrl: `https://github.com/${GUARDIAN_RELEASE_REPOSITORY}/settings/secrets/actions/new`,
|
|
17809
|
+
commands: {
|
|
17810
|
+
setNpmToken: `gh secret set NPM_TOKEN --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions`,
|
|
17811
|
+
verifyNpmTokenPresence: `gh secret list --repo ${GUARDIAN_RELEASE_REPOSITORY} --app actions | rg '^NPM_TOKEN\\b'`,
|
|
17812
|
+
dryRunDispatch: buildGuardianReleaseDispatchCommandFor({
|
|
17813
|
+
dryRun: true,
|
|
17814
|
+
releaseVersion: "<version>",
|
|
17815
|
+
channels: "all",
|
|
17816
|
+
runDockerSmoke: true
|
|
17817
|
+
}),
|
|
17818
|
+
publishDispatch: buildGuardianReleaseDispatchCommandFor({
|
|
17819
|
+
dryRun: false,
|
|
17820
|
+
releaseVersion: "<version>",
|
|
17821
|
+
channels: "all",
|
|
17822
|
+
runDockerSmoke: true
|
|
17823
|
+
})
|
|
17824
|
+
},
|
|
17825
|
+
boundaries: [
|
|
17826
|
+
"NPM_TOKEN belongs only in GitHub Actions repository secrets for guarded dry_run=false npm publication.",
|
|
17827
|
+
"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.",
|
|
17828
|
+
"Use dry_run=true before dry_run=false; dry-run dispatch does not require NPM_TOKEN.",
|
|
17829
|
+
"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."
|
|
17830
|
+
],
|
|
17831
|
+
tokenPrinted: false,
|
|
17832
|
+
rawContentIncluded: false
|
|
17833
|
+
};
|
|
17834
|
+
}
|
|
17835
|
+
function renderGuardianReleaseSecretSetup(result, flags) {
|
|
17836
|
+
if (flags.has("json")) {
|
|
17837
|
+
return `${JSON.stringify(result, null, 2)}
|
|
17838
|
+
`;
|
|
17839
|
+
}
|
|
17840
|
+
return `${[
|
|
17841
|
+
"Project Guardian Release Secret Setup",
|
|
17842
|
+
`Repository: ${result.repository}`,
|
|
17843
|
+
`Required for publish: ${result.requiredForPublish}`,
|
|
17844
|
+
`GitHub Actions secret page: ${result.githubActionsSecretUrl}`,
|
|
17845
|
+
"Set secret:",
|
|
17846
|
+
result.commands.setNpmToken,
|
|
17847
|
+
"Verify secret presence:",
|
|
17848
|
+
result.commands.verifyNpmTokenPresence,
|
|
17849
|
+
"Dry-run release command:",
|
|
17850
|
+
result.commands.dryRunDispatch,
|
|
17851
|
+
"Publish release command:",
|
|
17852
|
+
result.commands.publishDispatch,
|
|
17853
|
+
"Boundaries:",
|
|
17854
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
17855
|
+
"Token printed: no"
|
|
17856
|
+
].join("\n")}
|
|
17857
|
+
`;
|
|
17858
|
+
}
|
|
17859
|
+
function buildGuardianReleaseChecklist(releaseVersion) {
|
|
17860
|
+
return {
|
|
17861
|
+
schema_version: "contextecf/project-guardian-release-checklist/v1",
|
|
17862
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
17863
|
+
releaseVersion,
|
|
17864
|
+
repository: GUARDIAN_RELEASE_REPOSITORY,
|
|
17865
|
+
status: "preview_release_operator_ready_full_production_blocked",
|
|
17866
|
+
operatorCommands: {
|
|
17867
|
+
secretSetup: "guardian release secrets",
|
|
17868
|
+
dryRunDispatch: buildGuardianReleaseDispatchCommandFor({
|
|
17869
|
+
dryRun: true,
|
|
17870
|
+
releaseVersion,
|
|
17871
|
+
channels: "all",
|
|
17872
|
+
runDockerSmoke: true
|
|
17873
|
+
}),
|
|
17874
|
+
publishDispatch: buildGuardianReleaseDispatchCommandFor({
|
|
17875
|
+
dryRun: false,
|
|
17876
|
+
releaseVersion,
|
|
17877
|
+
channels: "all",
|
|
17878
|
+
runDockerSmoke: true
|
|
17879
|
+
}),
|
|
17880
|
+
browserStoreHandoff: "guardian release browser-store",
|
|
17881
|
+
readiness: "guardian readiness"
|
|
17882
|
+
},
|
|
17883
|
+
requiredRepositoryCredentialName: "NPM_TOKEN",
|
|
17884
|
+
evidenceOutputs: [
|
|
17885
|
+
"release/evidence/guardian-release-dispatch-summary.json",
|
|
17886
|
+
"release/evidence/guardian-npm-publish-execution-summary.json",
|
|
17887
|
+
"release/evidence/guardian-npm-publish-status-verification.json",
|
|
17888
|
+
"release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json",
|
|
17889
|
+
"release/evidence/guardian-finish-line-status.json"
|
|
17890
|
+
],
|
|
17891
|
+
notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES.map((gate) => ({
|
|
17892
|
+
id: gate.id,
|
|
17893
|
+
label: gate.label,
|
|
17894
|
+
owner: gate.owner,
|
|
17895
|
+
releaseBoundary: gate.releaseBoundary
|
|
17896
|
+
})),
|
|
17897
|
+
boundaries: [
|
|
17898
|
+
"This checklist is an operator command surface for Guardian preview releases; it is not production-gate proof.",
|
|
17899
|
+
"Run the dry-run dispatch before any dry_run=false publish dispatch.",
|
|
17900
|
+
"dry_run=false requires NPM_TOKEN in GitHub Actions repository secrets and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17901
|
+
"The checklist does not sign native installers, submit browser-store packages, execute high-risk desktop actions, or enable autonomous local app execution.",
|
|
17902
|
+
"Full production claims remain blocked until every not-proven production gate has real validated external evidence."
|
|
17903
|
+
],
|
|
17411
17904
|
tokenPrinted: false,
|
|
17412
17905
|
rawContentIncluded: false
|
|
17413
17906
|
};
|
|
17414
17907
|
}
|
|
17908
|
+
function buildGuardianReleaseFlow(releaseVersion) {
|
|
17909
|
+
const checklist = buildGuardianReleaseChecklist(releaseVersion);
|
|
17910
|
+
const verify = buildGuardianReleaseVerify(releaseVersion);
|
|
17911
|
+
const dryRunDispatch = buildGuardianReleaseDispatchCommandFor({
|
|
17912
|
+
dryRun: true,
|
|
17913
|
+
releaseVersion,
|
|
17914
|
+
channels: "all",
|
|
17915
|
+
runDockerSmoke: true
|
|
17916
|
+
});
|
|
17917
|
+
const publishDispatch = buildGuardianReleaseDispatchCommandFor({
|
|
17918
|
+
dryRun: false,
|
|
17919
|
+
releaseVersion,
|
|
17920
|
+
channels: "all",
|
|
17921
|
+
runDockerSmoke: true
|
|
17922
|
+
});
|
|
17923
|
+
return {
|
|
17924
|
+
schema_version: "contextecf/project-guardian-release-flow/v1",
|
|
17925
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
17926
|
+
releaseVersion,
|
|
17927
|
+
repository: GUARDIAN_RELEASE_REPOSITORY,
|
|
17928
|
+
status: "release_owner_flow_ready_full_production_blocked",
|
|
17929
|
+
steps: [
|
|
17930
|
+
{
|
|
17931
|
+
id: "review-checklist",
|
|
17932
|
+
label: "Review the release checklist",
|
|
17933
|
+
command: `guardian release checklist --version=${releaseVersion}`,
|
|
17934
|
+
credentialRequired: false
|
|
17935
|
+
},
|
|
17936
|
+
{
|
|
17937
|
+
id: "verify-secrets",
|
|
17938
|
+
label: "Verify npm publish secret setup",
|
|
17939
|
+
command: "guardian release secrets",
|
|
17940
|
+
credentialRequired: false
|
|
17941
|
+
},
|
|
17942
|
+
{
|
|
17943
|
+
id: "dry-run-dispatch",
|
|
17944
|
+
label: "Run the GitHub Actions dry run",
|
|
17945
|
+
command: dryRunDispatch,
|
|
17946
|
+
credentialRequired: false
|
|
17947
|
+
},
|
|
17948
|
+
{
|
|
17949
|
+
id: "publish-dispatch",
|
|
17950
|
+
label: "Run the guarded publish dispatch after dry-run evidence passes",
|
|
17951
|
+
command: publishDispatch,
|
|
17952
|
+
credentialRequired: true
|
|
17953
|
+
},
|
|
17954
|
+
{
|
|
17955
|
+
id: "verify-public-release",
|
|
17956
|
+
label: "Verify the published package and local install smoke",
|
|
17957
|
+
command: `guardian release verify --version=${releaseVersion}`,
|
|
17958
|
+
credentialRequired: false
|
|
17959
|
+
},
|
|
17960
|
+
{
|
|
17961
|
+
id: "copy-paste-local-smoke",
|
|
17962
|
+
label: "Copy-paste the local end-user smoke block",
|
|
17963
|
+
command: `guardian release paste --version=${releaseVersion}`,
|
|
17964
|
+
credentialRequired: false
|
|
17965
|
+
},
|
|
17966
|
+
{
|
|
17967
|
+
id: "browser-store-handoff",
|
|
17968
|
+
label: "Prepare browser-store submission handoff",
|
|
17969
|
+
command: "guardian release browser-store",
|
|
17970
|
+
credentialRequired: false
|
|
17971
|
+
}
|
|
17972
|
+
],
|
|
17973
|
+
copyPasteLocalSmoke: verify.commands.copyPasteLocalSmoke,
|
|
17974
|
+
evidenceOutputs: Array.from(
|
|
17975
|
+
/* @__PURE__ */ new Set([
|
|
17976
|
+
...checklist.evidenceOutputs,
|
|
17977
|
+
...verify.evidenceOutputs,
|
|
17978
|
+
"release/evidence/guardian-browser-store-submission-pack/browser-store-closeout-checklist.json"
|
|
17979
|
+
])
|
|
17980
|
+
),
|
|
17981
|
+
notProvenProductionGates: checklist.notProvenProductionGates.map((gate) => ({
|
|
17982
|
+
id: gate.id,
|
|
17983
|
+
label: gate.label,
|
|
17984
|
+
releaseBoundary: gate.releaseBoundary
|
|
17985
|
+
})),
|
|
17986
|
+
boundaries: [
|
|
17987
|
+
"This release flow is copy-paste operator guidance only; it is not release evidence or production-gate proof.",
|
|
17988
|
+
"Publish dispatch requires NPM_TOKEN in GitHub Actions repository secrets and must not print npm tokens, OTP values, or .npmrc contents.",
|
|
17989
|
+
"Run the dry-run dispatch before the guarded dry_run=false publish dispatch.",
|
|
17990
|
+
"Public npm preview publication and local install smoke prove the CLI preview lane only.",
|
|
17991
|
+
"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."
|
|
17992
|
+
],
|
|
17993
|
+
tokenPrinted: false,
|
|
17994
|
+
rawContentIncluded: false
|
|
17995
|
+
};
|
|
17996
|
+
}
|
|
17997
|
+
function renderGuardianReleaseFlow(result, flags) {
|
|
17998
|
+
if (flags.has("json")) {
|
|
17999
|
+
return `${JSON.stringify(result, null, 2)}
|
|
18000
|
+
`;
|
|
18001
|
+
}
|
|
18002
|
+
const lines = [
|
|
18003
|
+
"Project Guardian Release Flow",
|
|
18004
|
+
`Release: ${result.releaseVersion}`,
|
|
18005
|
+
`Repository: ${result.repository}`,
|
|
18006
|
+
`Status: ${result.status}`,
|
|
18007
|
+
"Steps:",
|
|
18008
|
+
...result.steps.flatMap((step, index) => [
|
|
18009
|
+
`${index + 1}. ${step.label}${step.credentialRequired ? " (requires NPM_TOKEN secret)" : ""}:`,
|
|
18010
|
+
step.command
|
|
18011
|
+
]),
|
|
18012
|
+
"Post-publish copy-paste local smoke:",
|
|
18013
|
+
result.copyPasteLocalSmoke,
|
|
18014
|
+
"Evidence outputs:",
|
|
18015
|
+
...result.evidenceOutputs.map((output2) => `- ${output2}`),
|
|
18016
|
+
"Not-proven production gates:",
|
|
18017
|
+
...result.notProvenProductionGates.map(
|
|
18018
|
+
(gate) => `- ${gate.label}: ${gate.releaseBoundary ?? "not proven"}`
|
|
18019
|
+
),
|
|
18020
|
+
"Boundaries:",
|
|
18021
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
18022
|
+
"Token printed: no"
|
|
18023
|
+
];
|
|
18024
|
+
return `${lines.join("\n")}
|
|
18025
|
+
`;
|
|
18026
|
+
}
|
|
18027
|
+
function renderGuardianReleaseChecklist(result, flags) {
|
|
18028
|
+
if (flags.has("json")) {
|
|
18029
|
+
return `${JSON.stringify(result, null, 2)}
|
|
18030
|
+
`;
|
|
18031
|
+
}
|
|
18032
|
+
return `${[
|
|
18033
|
+
"Project Guardian Release Checklist",
|
|
18034
|
+
`Release: ${result.releaseVersion}`,
|
|
18035
|
+
`Repository: ${result.repository}`,
|
|
18036
|
+
`Status: ${result.status}`,
|
|
18037
|
+
`Required repository credential: ${result.requiredRepositoryCredentialName}`,
|
|
18038
|
+
"1. Secret setup:",
|
|
18039
|
+
result.operatorCommands.secretSetup,
|
|
18040
|
+
"2. Dry-run dispatch:",
|
|
18041
|
+
result.operatorCommands.dryRunDispatch,
|
|
18042
|
+
"3. Publish dispatch:",
|
|
18043
|
+
result.operatorCommands.publishDispatch,
|
|
18044
|
+
"4. Browser-store handoff:",
|
|
18045
|
+
result.operatorCommands.browserStoreHandoff,
|
|
18046
|
+
"5. Readiness check:",
|
|
18047
|
+
result.operatorCommands.readiness,
|
|
18048
|
+
"Evidence outputs:",
|
|
18049
|
+
...result.evidenceOutputs.map((output2) => `- ${output2}`),
|
|
18050
|
+
"Not-proven production gates:",
|
|
18051
|
+
...result.notProvenProductionGates.map(
|
|
18052
|
+
(gate) => `- ${gate.label}: ${gate.releaseBoundary ?? "not proven"}`
|
|
18053
|
+
),
|
|
18054
|
+
"Boundaries:",
|
|
18055
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
18056
|
+
"Token printed: no"
|
|
18057
|
+
].join("\n")}
|
|
18058
|
+
`;
|
|
18059
|
+
}
|
|
18060
|
+
function buildGuardianReleaseVerify(releaseVersion) {
|
|
18061
|
+
const copyPasteLocalSmoke = buildGuardianReleasePaste(releaseVersion).command;
|
|
18062
|
+
return {
|
|
18063
|
+
schema_version: "contextecf/project-guardian-release-verify/v1",
|
|
18064
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
18065
|
+
releaseVersion,
|
|
18066
|
+
repository: GUARDIAN_RELEASE_REPOSITORY,
|
|
18067
|
+
packageName: GUARDIAN_NPM_PACKAGE_NAME,
|
|
18068
|
+
registry: GUARDIAN_NPM_REGISTRY,
|
|
18069
|
+
status: "post_release_verification_required",
|
|
18070
|
+
commands: {
|
|
18071
|
+
registryVersion: `npm view ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion} version --registry=${GUARDIAN_NPM_REGISTRY}`,
|
|
18072
|
+
publicInstall: `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion}`,
|
|
18073
|
+
installedVersion: "guardian --version",
|
|
18074
|
+
setup: "guardian setup",
|
|
18075
|
+
launch: "guardian launch",
|
|
18076
|
+
status: "guardian status",
|
|
18077
|
+
openControlTower: "guardian open",
|
|
18078
|
+
copyPasteLocalSmoke,
|
|
18079
|
+
publishStatusVerification: "npm run guardian:npm:publish:verify-status -- --status release/evidence/guardian-npm-publish-status.json --assert-ready --verify-artifacts --output release/evidence/guardian-npm-publish-status-verification.json",
|
|
18080
|
+
finishLineStatus: "npm run guardian:finish-line:status -- --npm-publish-status release/evidence/guardian-npm-publish-status.json --json --output release/evidence/guardian-finish-line-status.json"
|
|
18081
|
+
},
|
|
18082
|
+
evidenceOutputs: [
|
|
18083
|
+
"release/evidence/guardian-npm-publish-status.json",
|
|
18084
|
+
"release/evidence/guardian-npm-publish-status-verification.json",
|
|
18085
|
+
"release/evidence/guardian-finish-line-status.json"
|
|
18086
|
+
],
|
|
18087
|
+
boundaries: [
|
|
18088
|
+
"This command surface verifies public preview release visibility and installability; it does not publish to npm.",
|
|
18089
|
+
"Do not print npm tokens, OTP values, .npmrc contents, signing keys, browser-store credentials, raw prompts, raw responses, private policy packs, or customer content in release verification evidence.",
|
|
18090
|
+
"A passing public npm install smoke proves the CLI preview lane only; signed installers, high-risk desktop action execution, and autonomous app execution remain separate production gates.",
|
|
18091
|
+
"Full production claims remain blocked until every not-proven production gate has real validated external evidence."
|
|
18092
|
+
],
|
|
18093
|
+
tokenPrinted: false,
|
|
18094
|
+
rawContentIncluded: false
|
|
18095
|
+
};
|
|
18096
|
+
}
|
|
18097
|
+
function buildGuardianReleasePaste(releaseVersion) {
|
|
18098
|
+
const commands = [
|
|
18099
|
+
`npm view ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion} version --registry=${GUARDIAN_NPM_REGISTRY}`,
|
|
18100
|
+
`npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}@${releaseVersion}`,
|
|
18101
|
+
"guardian --version",
|
|
18102
|
+
"guardian stop",
|
|
18103
|
+
"guardian setup",
|
|
18104
|
+
"guardian launch",
|
|
18105
|
+
"guardian open",
|
|
18106
|
+
"guardian status"
|
|
18107
|
+
];
|
|
18108
|
+
return {
|
|
18109
|
+
schema_version: "contextecf/project-guardian-release-paste/v1",
|
|
18110
|
+
cli_version: GUARDIAN_CLI_VERSION,
|
|
18111
|
+
releaseVersion,
|
|
18112
|
+
packageName: GUARDIAN_NPM_PACKAGE_NAME,
|
|
18113
|
+
registry: GUARDIAN_NPM_REGISTRY,
|
|
18114
|
+
command: commands.join("\n"),
|
|
18115
|
+
commands,
|
|
18116
|
+
boundaries: [
|
|
18117
|
+
"This paste block verifies public npm visibility, global install, first-run setup, daemon launch, Control Tower open, and status.",
|
|
18118
|
+
"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.",
|
|
18119
|
+
"guardian stop is included before setup so stale local daemons or local token mismatches are cleared before launch."
|
|
18120
|
+
],
|
|
18121
|
+
tokenPrinted: false,
|
|
18122
|
+
rawContentIncluded: false
|
|
18123
|
+
};
|
|
18124
|
+
}
|
|
18125
|
+
function renderGuardianReleasePaste(result, flags) {
|
|
18126
|
+
if (flags.has("json")) {
|
|
18127
|
+
return `${JSON.stringify(result, null, 2)}
|
|
18128
|
+
`;
|
|
18129
|
+
}
|
|
18130
|
+
return `${result.command}
|
|
18131
|
+
`;
|
|
18132
|
+
}
|
|
18133
|
+
function renderGuardianReleaseVerify(result, flags) {
|
|
18134
|
+
if (flags.has("json")) {
|
|
18135
|
+
return `${JSON.stringify(result, null, 2)}
|
|
18136
|
+
`;
|
|
18137
|
+
}
|
|
18138
|
+
return `${[
|
|
18139
|
+
"Project Guardian Release Verification",
|
|
18140
|
+
`Release: ${result.releaseVersion}`,
|
|
18141
|
+
`Package: ${result.packageName}`,
|
|
18142
|
+
`Registry: ${result.registry}`,
|
|
18143
|
+
`Status: ${result.status}`,
|
|
18144
|
+
"1. Confirm registry visibility:",
|
|
18145
|
+
result.commands.registryVersion,
|
|
18146
|
+
"2. Install the published version:",
|
|
18147
|
+
result.commands.publicInstall,
|
|
18148
|
+
"3. Confirm installed CLI version:",
|
|
18149
|
+
result.commands.installedVersion,
|
|
18150
|
+
"4. Run first-use smoke:",
|
|
18151
|
+
result.commands.setup,
|
|
18152
|
+
result.commands.launch,
|
|
18153
|
+
result.commands.status,
|
|
18154
|
+
result.commands.openControlTower,
|
|
18155
|
+
"5. Copy-paste local smoke block:",
|
|
18156
|
+
result.commands.copyPasteLocalSmoke,
|
|
18157
|
+
"6. Verify release evidence:",
|
|
18158
|
+
result.commands.publishStatusVerification,
|
|
18159
|
+
result.commands.finishLineStatus,
|
|
18160
|
+
"Evidence outputs:",
|
|
18161
|
+
...result.evidenceOutputs.map((output2) => `- ${output2}`),
|
|
18162
|
+
"Boundaries:",
|
|
18163
|
+
...result.boundaries.map((boundary) => `- ${boundary}`),
|
|
18164
|
+
"Token printed: no"
|
|
18165
|
+
].join("\n")}
|
|
18166
|
+
`;
|
|
18167
|
+
}
|
|
18168
|
+
function isValidReleaseVersion(value) {
|
|
18169
|
+
return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(value);
|
|
18170
|
+
}
|
|
18171
|
+
function isValidReleaseChannels(value) {
|
|
18172
|
+
return ["all", "npm", "browser", "evidence"].includes(value);
|
|
18173
|
+
}
|
|
17415
18174
|
function renderGuardianProductionReadiness(result, flags) {
|
|
17416
18175
|
if (flags.has("json")) {
|
|
17417
18176
|
return `${JSON.stringify(result, null, 2)}
|
|
@@ -17424,6 +18183,18 @@ function renderGuardianProductionReadiness(result, flags) {
|
|
|
17424
18183
|
`Doctor: ${result.doctorOverall.toUpperCase()}`,
|
|
17425
18184
|
`NPM preview install: ${result.npmPreview.status.toUpperCase()} - ${result.npmPreview.reason}`,
|
|
17426
18185
|
result.npmPreview.publishCommand ? `NPM publish command: ${result.npmPreview.publishCommand}` : "NPM publish command: not available until publish dry-run evidence passes",
|
|
18186
|
+
`Distribution: ${result.distribution.status}`,
|
|
18187
|
+
`Install: ${result.distribution.oneLineInstallCommand}`,
|
|
18188
|
+
`Try without global install: ${result.distribution.oneLineTryCommand}`,
|
|
18189
|
+
`Open Control Tower: ${result.distribution.openControlTowerCommand}`,
|
|
18190
|
+
`AI tool setup: ${result.distribution.aiToolIntegration.mcpInstallCommand}; ${result.distribution.aiToolIntegration.browserSetupCommand}`,
|
|
18191
|
+
`Browser-store handoff: ${result.distribution.browserStoreHandoff.status}; gate ${result.distribution.browserStoreHandoff.productionGateStatus}`,
|
|
18192
|
+
`Browser-store checklist: ${result.distribution.browserStoreHandoff.closeoutChecklistPath}`,
|
|
18193
|
+
`Release workflow: ${result.distribution.releaseAutomation.workflow}; status=${result.distribution.releaseAutomation.status}`,
|
|
18194
|
+
`Release dry run:
|
|
18195
|
+
${result.distribution.releaseAutomation.dryRunCommand}`,
|
|
18196
|
+
`Release publish:
|
|
18197
|
+
${result.distribution.releaseAutomation.publishCommand}`,
|
|
17427
18198
|
`Full production release: ${result.fullProduction.status.toUpperCase()} - ${result.fullProduction.reason}`,
|
|
17428
18199
|
`Production gate evidence: ${result.fullProduction.productionGateEvidenceStatus}`,
|
|
17429
18200
|
`Blocked production gates: ${result.fullProduction.blockedGateCount}`,
|
|
@@ -17443,6 +18214,19 @@ async function statusGuardian(flags, options) {
|
|
|
17443
18214
|
const releaseEvidence = await buildGuardianReleaseEvidenceStatus(home);
|
|
17444
18215
|
const serviceSupervision = await buildGuardianServiceSupervisionStatus(home);
|
|
17445
18216
|
const osKeyStorage = await buildGuardianOsKeyStorageStatus(home);
|
|
18217
|
+
const privacy = {
|
|
18218
|
+
rawContentCaptureEnabled: profile?.privacy.raw_content_capture_enabled ?? false,
|
|
18219
|
+
cloudSyncEnabled: profile?.privacy.cloud_sync_enabled ?? false,
|
|
18220
|
+
localAppAutopilotEnabled: profile?.privacy.local_app_autopilot_enabled ?? false
|
|
18221
|
+
};
|
|
18222
|
+
const nextCommands = buildGuardianStatusNextCommands({
|
|
18223
|
+
installed: profile !== void 0,
|
|
18224
|
+
daemonStatus: daemonHealth.daemon.status
|
|
18225
|
+
});
|
|
18226
|
+
const daemonVersionMismatch = daemonHealth.daemon.status === "reachable" && daemonHealth.daemon.version !== void 0 && daemonHealth.daemon.version !== GUARDIAN_CLI_VERSION ? { cliVersion: GUARDIAN_CLI_VERSION, daemonVersion: daemonHealth.daemon.version } : null;
|
|
18227
|
+
if (daemonVersionMismatch) {
|
|
18228
|
+
nextCommands.push("guardian stop", "guardian launch");
|
|
18229
|
+
}
|
|
17446
18230
|
const result = {
|
|
17447
18231
|
schema_version: "contextecf/project-guardian-status/v1",
|
|
17448
18232
|
cli_version: GUARDIAN_CLI_VERSION,
|
|
@@ -17456,11 +18240,7 @@ async function statusGuardian(flags, options) {
|
|
|
17456
18240
|
controlTowerUrl: daemonHealth.controlTowerUrl,
|
|
17457
18241
|
controlTowerUrlSource: profile?.control_tower?.source ?? "default_loopback",
|
|
17458
18242
|
daemon: daemonHealth.daemon,
|
|
17459
|
-
privacy
|
|
17460
|
-
rawContentCaptureEnabled: profile?.privacy.raw_content_capture_enabled ?? false,
|
|
17461
|
-
cloudSyncEnabled: profile?.privacy.cloud_sync_enabled ?? false,
|
|
17462
|
-
localAppAutopilotEnabled: profile?.privacy.local_app_autopilot_enabled ?? false
|
|
17463
|
-
},
|
|
18243
|
+
privacy,
|
|
17464
18244
|
preferences: {
|
|
17465
18245
|
promptCoachMode: profile?.prompt_coach_mode ?? "not_installed",
|
|
17466
18246
|
learningGraphEnabled: profile?.learning_graph.enabled ?? false
|
|
@@ -17479,7 +18259,9 @@ async function statusGuardian(flags, options) {
|
|
|
17479
18259
|
releaseEvidence,
|
|
17480
18260
|
serviceSupervision,
|
|
17481
18261
|
osKeyStorage,
|
|
17482
|
-
notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES
|
|
18262
|
+
notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES,
|
|
18263
|
+
daemonVersionMismatch,
|
|
18264
|
+
nextCommands
|
|
17483
18265
|
};
|
|
17484
18266
|
if (flags.has("json")) {
|
|
17485
18267
|
return `${JSON.stringify(result, null, 2)}
|
|
@@ -17493,6 +18275,7 @@ async function statusGuardian(flags, options) {
|
|
|
17493
18275
|
`Control Tower: ${result.controlTowerUrl ?? "not configured"}`,
|
|
17494
18276
|
`Daemon health: ${result.daemon.status}${result.daemon.statusCode ? ` (HTTP ${result.daemon.statusCode})` : ""}`,
|
|
17495
18277
|
result.daemon.error ? `Daemon detail: ${result.daemon.error}` : void 0,
|
|
18278
|
+
result.daemonVersionMismatch ? `Daemon version: ${result.daemonVersionMismatch.daemonVersion} (this CLI is ${result.daemonVersionMismatch.cliVersion} \u2014 versions differ, likely because the CLI was reinstalled or changed version while this daemon kept running; run guardian stop && guardian launch to restart it on the current version)` : void 0,
|
|
17496
18279
|
`MCP stdio: ${result.runtime.mcpStdioAvailable ? "available" : "unavailable"}`,
|
|
17497
18280
|
`Posture Profile: ${result.postureProfile.selected}`,
|
|
17498
18281
|
`Prompt Coach: ${result.preferences.promptCoachMode}`,
|
|
@@ -17502,11 +18285,36 @@ async function statusGuardian(flags, options) {
|
|
|
17502
18285
|
`Service supervision: ${result.serviceSupervision.status}`,
|
|
17503
18286
|
`OS key storage: ${result.osKeyStorage.status}`,
|
|
17504
18287
|
`Not-proven production gates: ${result.notProvenProductionGates.length}`,
|
|
17505
|
-
|
|
17506
|
-
|
|
18288
|
+
formatGuardianPrivacyStatus(result.privacy),
|
|
18289
|
+
`Next: ${result.nextCommands.join("; ")}`
|
|
17507
18290
|
].filter(Boolean).join("\n")}
|
|
17508
18291
|
`;
|
|
17509
18292
|
}
|
|
18293
|
+
function buildGuardianStatusNextCommands(input2) {
|
|
18294
|
+
if (!input2.installed) {
|
|
18295
|
+
return ["guardian install"];
|
|
18296
|
+
}
|
|
18297
|
+
if (input2.daemonStatus === "reachable") {
|
|
18298
|
+
return ["guardian open", "guardian readiness", "guardian extension open-setup"];
|
|
18299
|
+
}
|
|
18300
|
+
if (input2.daemonStatus === "unauthorized") {
|
|
18301
|
+
return ["guardian stop", "guardian launch --port=4322", "guardian status"];
|
|
18302
|
+
}
|
|
18303
|
+
if (input2.daemonStatus === "token_missing" || input2.daemonStatus === "invalid_control_tower_url") {
|
|
18304
|
+
return ["guardian setup", "guardian launch", "guardian status"];
|
|
18305
|
+
}
|
|
18306
|
+
return ["guardian launch", "guardian status"];
|
|
18307
|
+
}
|
|
18308
|
+
function formatGuardianPrivacyStatus(input2) {
|
|
18309
|
+
return [
|
|
18310
|
+
`Privacy: raw capture ${formatOnOff(input2.rawContentCaptureEnabled)}`,
|
|
18311
|
+
`cloud sync ${formatOnOff(input2.cloudSyncEnabled)}`,
|
|
18312
|
+
`local app autopilot ${formatOnOff(input2.localAppAutopilotEnabled)}`
|
|
18313
|
+
].join(", ");
|
|
18314
|
+
}
|
|
18315
|
+
function formatOnOff(enabled) {
|
|
18316
|
+
return enabled ? "on" : "off";
|
|
18317
|
+
}
|
|
17510
18318
|
async function runControlTowerOpenCommand(flags, options) {
|
|
17511
18319
|
const stdout = options.stdout ?? process.stdout;
|
|
17512
18320
|
const stderr = options.stderr ?? process.stderr;
|
|
@@ -17557,7 +18365,7 @@ async function runLaunchCommand(flags, options) {
|
|
|
17557
18365
|
return startExitCode;
|
|
17558
18366
|
}
|
|
17559
18367
|
const start = JSON.parse(startOutput);
|
|
17560
|
-
const shouldOpen = !flags.has("print");
|
|
18368
|
+
const shouldOpen = flags.has("open") && !flags.has("print");
|
|
17561
18369
|
if (shouldOpen) {
|
|
17562
18370
|
const opener = options.openUrl ?? ((url2) => openUrlInDefaultBrowser(url2, options));
|
|
17563
18371
|
await opener(start.controlTowerUrl);
|
|
@@ -17571,7 +18379,12 @@ async function runLaunchCommand(flags, options) {
|
|
|
17571
18379
|
controlTowerUrl: start.controlTowerUrl,
|
|
17572
18380
|
pid: start.pid,
|
|
17573
18381
|
healthStatus: start.healthStatus,
|
|
17574
|
-
nextCommands: [
|
|
18382
|
+
nextCommands: [
|
|
18383
|
+
"guardian open",
|
|
18384
|
+
"guardian status",
|
|
18385
|
+
"guardian daemon pair --json",
|
|
18386
|
+
"guardian policy list"
|
|
18387
|
+
]
|
|
17575
18388
|
};
|
|
17576
18389
|
write(
|
|
17577
18390
|
stdout,
|
|
@@ -17581,7 +18394,7 @@ async function runLaunchCommand(flags, options) {
|
|
|
17581
18394
|
`Daemon: ${result.daemonUrl}${result.reusedExistingDaemon ? " (already running)" : ""}`,
|
|
17582
18395
|
`Control Tower: ${result.controlTowerUrl}`,
|
|
17583
18396
|
shouldOpen ? `Opening: ${result.controlTowerUrl}` : void 0,
|
|
17584
|
-
"Next: guardian status"
|
|
18397
|
+
"Next: guardian open; guardian status"
|
|
17585
18398
|
].filter(Boolean).join("\n")}
|
|
17586
18399
|
`
|
|
17587
18400
|
);
|
|
@@ -18005,6 +18818,7 @@ function requestGuardianDaemonHealth(request) {
|
|
|
18005
18818
|
const parsedBody = parseJsonObject(body);
|
|
18006
18819
|
const service = typeof parsedBody?.service === "string" ? parsedBody.service : void 0;
|
|
18007
18820
|
const rawContentPersistence = typeof parsedBody?.rawContentPersistence === "boolean" ? parsedBody.rawContentPersistence : void 0;
|
|
18821
|
+
const version2 = typeof parsedBody?.version === "string" ? parsedBody.version : void 0;
|
|
18008
18822
|
const error51 = typeof parsedBody?.error === "string" ? parsedBody.error : void 0;
|
|
18009
18823
|
const ok = typeof statusCode === "number" && statusCode >= 200 && statusCode < 300;
|
|
18010
18824
|
resolve({
|
|
@@ -18013,6 +18827,7 @@ function requestGuardianDaemonHealth(request) {
|
|
|
18013
18827
|
statusCode,
|
|
18014
18828
|
service,
|
|
18015
18829
|
rawContentPersistence,
|
|
18830
|
+
version: version2,
|
|
18016
18831
|
error: ok ? void 0 : error51 ?? "daemon_health_failed"
|
|
18017
18832
|
});
|
|
18018
18833
|
});
|
|
@@ -21711,6 +22526,7 @@ async function buildDaemonHealthStatus(home, flags, options, profile) {
|
|
|
21711
22526
|
statusCode: checked.statusCode,
|
|
21712
22527
|
service: checked.service,
|
|
21713
22528
|
rawContentPersistence: checked.rawContentPersistence,
|
|
22529
|
+
version: checked.version,
|
|
21714
22530
|
error: checked.error
|
|
21715
22531
|
}
|
|
21716
22532
|
};
|
|
@@ -22023,6 +22839,18 @@ async function buildGuardianDoctorStatus(home, profile, env = process.env) {
|
|
|
22023
22839
|
rawContentIncluded: false
|
|
22024
22840
|
};
|
|
22025
22841
|
}
|
|
22842
|
+
function isGuardianSupportedNodeVersion(nodeVersion) {
|
|
22843
|
+
const parts = nodeVersion.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10));
|
|
22844
|
+
const [major = 0, minor = 0, patch = 0] = parts;
|
|
22845
|
+
const [minMajor, minMinor, minPatch] = GUARDIAN_MIN_SUPPORTED_NODE_VERSION;
|
|
22846
|
+
if (major !== minMajor) {
|
|
22847
|
+
return major > minMajor;
|
|
22848
|
+
}
|
|
22849
|
+
if (minor !== minMinor) {
|
|
22850
|
+
return minor > minMinor;
|
|
22851
|
+
}
|
|
22852
|
+
return patch >= minPatch;
|
|
22853
|
+
}
|
|
22026
22854
|
async function buildDoctorChecks(home, profile, env = process.env) {
|
|
22027
22855
|
const encryption = buildGuardianLocalDataEncryptionStatus(
|
|
22028
22856
|
env,
|
|
@@ -22032,6 +22860,12 @@ async function buildDoctorChecks(home, profile, env = process.env) {
|
|
|
22032
22860
|
const serviceSupervision = await buildGuardianServiceSupervisionStatus(home);
|
|
22033
22861
|
const osKeyStorage = await buildGuardianOsKeyStorageStatus(home);
|
|
22034
22862
|
return [
|
|
22863
|
+
{
|
|
22864
|
+
id: "node-runtime",
|
|
22865
|
+
label: "Node.js runtime",
|
|
22866
|
+
status: isGuardianSupportedNodeVersion(process.version) ? "pass" : "warn",
|
|
22867
|
+
detail: isGuardianSupportedNodeVersion(process.version) ? `Node ${process.version} meets the >=20.20.0 floor` : `Node ${process.version} is below the supported >=20.20.0 floor; upgrade to Node 20.20+ or 22 LTS`
|
|
22868
|
+
},
|
|
22035
22869
|
{
|
|
22036
22870
|
id: "profile",
|
|
22037
22871
|
label: "Guardian profile",
|
|
@@ -22133,6 +22967,26 @@ function stringFlag(flags, key) {
|
|
|
22133
22967
|
const value = flags.get(key);
|
|
22134
22968
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
22135
22969
|
}
|
|
22970
|
+
function booleanFlag(flags, key, defaultValue) {
|
|
22971
|
+
const value = flags.get(key);
|
|
22972
|
+
if (value === void 0) {
|
|
22973
|
+
return defaultValue;
|
|
22974
|
+
}
|
|
22975
|
+
if (value === true) {
|
|
22976
|
+
return true;
|
|
22977
|
+
}
|
|
22978
|
+
if (typeof value !== "string") {
|
|
22979
|
+
return defaultValue;
|
|
22980
|
+
}
|
|
22981
|
+
const normalized = value.trim().toLowerCase();
|
|
22982
|
+
if (["1", "true", "yes", "on"].includes(normalized)) {
|
|
22983
|
+
return true;
|
|
22984
|
+
}
|
|
22985
|
+
if (["0", "false", "no", "off"].includes(normalized)) {
|
|
22986
|
+
return false;
|
|
22987
|
+
}
|
|
22988
|
+
return defaultValue;
|
|
22989
|
+
}
|
|
22136
22990
|
function copyStringFlags(flags, keys) {
|
|
22137
22991
|
return keys.flatMap((key) => {
|
|
22138
22992
|
const value = stringFlag(flags, key);
|
|
@@ -22280,19 +23134,22 @@ function openUrlInDefaultBrowser(url2, options = {}) {
|
|
|
22280
23134
|
});
|
|
22281
23135
|
});
|
|
22282
23136
|
}
|
|
22283
|
-
var GUARDIAN_CLI_VERSION, GUARDIAN_PROFILE_SCHEMA_VERSION, GUARDIAN_NPM_PACKAGE_NAME, GUARDIAN_GLOBAL_INSTALL_COMMAND, GUARDIAN_NPX_SETUP_COMMAND, GUARDIAN_FIRST_RUN_COMMAND, GUARDIAN_OPEN_CONTROL_TOWER_COMMAND, GUARDIAN_DEFAULT_CONTROL_TOWER_URL, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ID_ENV, GUARDIAN_DESKTOP_ADAPTER_SIMULATE_OPEN_ENV, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_ID, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_VERSION, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_PROOF_SCHEMA_VERSION, GUARDIAN_SERVICE_PROOF_SCHEMA_VERSION, GUARDIAN_OS_KEY_STORAGE_PROOF_SCHEMA_VERSION, GUARDIAN_WINDOWS_NATIVE_HOST_REGISTRY_PROOF_SCHEMA_VERSION, PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION2, PROMPT_COACH_MODES, DEFAULT_PROMPT_COACH_DAILY_SOFT_CARD_LIMIT, GUARDIAN_POSTURE_PROFILE_IDS, GUARDIAN_POSTURE_PROFILE_CATALOG, GUARDIAN_POLICY_PACK_MARKETPLACE_CATALOG, GUARDIAN_PROVIDER_IDS, GUARDIAN_SOURCE_TYPES, GUARDIAN_NOT_PROVEN_PRODUCTION_GATES, DEFAULT_POLICY_PACKS, GUARDIAN_BRIDGE_CONFIG_STORAGE_KEY, GUARDIAN_BRIDGE_TOKEN_STORAGE_KEY, GUARDIAN_BRIDGE_CONFIG_SCHEMA_VERSION, GUARDIAN_NATIVE_HOST_NAME, MCP_CLIENTS, NATIVE_HOST_BROWSERS, HELP_TEXT, normalizeGuardianPreferences, GUARDIAN_DATA_FILE_NAMES, GUARDIAN_DATA_DIR_NAMES;
|
|
23137
|
+
var GUARDIAN_CLI_VERSION, GUARDIAN_PROFILE_SCHEMA_VERSION, GUARDIAN_NPM_PACKAGE_NAME, GUARDIAN_NPM_REGISTRY, GUARDIAN_GLOBAL_INSTALL_COMMAND, GUARDIAN_NPX_SETUP_COMMAND, GUARDIAN_FIRST_RUN_COMMAND, GUARDIAN_OPEN_CONTROL_TOWER_COMMAND, GUARDIAN_RELEASE_DISPATCH_WORKFLOW, GUARDIAN_RELEASE_REPOSITORY, GUARDIAN_DEFAULT_CONTROL_TOWER_URL, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV, GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ENV, GUARDIAN_SQLITE_PAGE_ENCRYPTION_KEY_ID_ENV, GUARDIAN_DESKTOP_ADAPTER_SIMULATE_OPEN_ENV, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_ID, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_VERSION, GUARDIAN_DESKTOP_URL_OPEN_ADAPTER_PROOF_SCHEMA_VERSION, GUARDIAN_SERVICE_PROOF_SCHEMA_VERSION, GUARDIAN_OS_KEY_STORAGE_PROOF_SCHEMA_VERSION, GUARDIAN_WINDOWS_NATIVE_HOST_REGISTRY_PROOF_SCHEMA_VERSION, PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION2, PROMPT_COACH_MODES, DEFAULT_PROMPT_COACH_DAILY_SOFT_CARD_LIMIT, GUARDIAN_POSTURE_PROFILE_IDS, GUARDIAN_POSTURE_PROFILE_CATALOG, GUARDIAN_POLICY_PACK_MARKETPLACE_CATALOG, GUARDIAN_PROVIDER_IDS, GUARDIAN_SOURCE_TYPES, GUARDIAN_NOT_PROVEN_PRODUCTION_GATES, DEFAULT_POLICY_PACKS, GUARDIAN_BRIDGE_CONFIG_STORAGE_KEY, GUARDIAN_BRIDGE_TOKEN_STORAGE_KEY, GUARDIAN_BRIDGE_CONFIG_SCHEMA_VERSION, GUARDIAN_NATIVE_HOST_NAME, MCP_CLIENTS, NATIVE_HOST_BROWSERS, HELP_TEXT, normalizeGuardianPreferences, GUARDIAN_DATA_FILE_NAMES, GUARDIAN_DATA_DIR_NAMES, GUARDIAN_MIN_SUPPORTED_NODE_VERSION;
|
|
22284
23138
|
var init_runtime = __esm({
|
|
22285
23139
|
"packages/guardian-cli/src/runtime.ts"() {
|
|
22286
23140
|
"use strict";
|
|
22287
23141
|
init_src();
|
|
22288
23142
|
init_src2();
|
|
22289
|
-
GUARDIAN_CLI_VERSION = "0.1.
|
|
23143
|
+
GUARDIAN_CLI_VERSION = "0.1.4";
|
|
22290
23144
|
GUARDIAN_PROFILE_SCHEMA_VERSION = "contextecf/project-guardian-profile/v1";
|
|
22291
23145
|
GUARDIAN_NPM_PACKAGE_NAME = "@contextecf/guardian-cli";
|
|
23146
|
+
GUARDIAN_NPM_REGISTRY = "https://registry.npmjs.org/";
|
|
22292
23147
|
GUARDIAN_GLOBAL_INSTALL_COMMAND = `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}`;
|
|
22293
23148
|
GUARDIAN_NPX_SETUP_COMMAND = `npx ${GUARDIAN_NPM_PACKAGE_NAME}@latest setup`;
|
|
22294
23149
|
GUARDIAN_FIRST_RUN_COMMAND = "guardian setup";
|
|
22295
|
-
GUARDIAN_OPEN_CONTROL_TOWER_COMMAND = "guardian
|
|
23150
|
+
GUARDIAN_OPEN_CONTROL_TOWER_COMMAND = "guardian open";
|
|
23151
|
+
GUARDIAN_RELEASE_DISPATCH_WORKFLOW = "guardian-release-dispatch.yml";
|
|
23152
|
+
GUARDIAN_RELEASE_REPOSITORY = "Intelligent-Context-AI-Inc/ContextECF-GITHUB";
|
|
22296
23153
|
GUARDIAN_DEFAULT_CONTROL_TOWER_URL = "http://127.0.0.1:4317/control-tower";
|
|
22297
23154
|
GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ENV = "GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY";
|
|
22298
23155
|
GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID_ENV = "GUARDIAN_LOCAL_DATA_ENCRYPTION_KEY_ID";
|
|
@@ -22718,28 +23575,6 @@ var init_runtime = __esm({
|
|
|
22718
23575
|
"Release evidence includes artifact digests without signing secrets."
|
|
22719
23576
|
]
|
|
22720
23577
|
},
|
|
22721
|
-
{
|
|
22722
|
-
id: "browser-store-distribution",
|
|
22723
|
-
label: "Browser store distribution",
|
|
22724
|
-
boundary: "Pending store submission, review, and release evidence.",
|
|
22725
|
-
owner: "browser-release",
|
|
22726
|
-
runtimeBoundary: "Pending store submission, review, and release evidence.",
|
|
22727
|
-
releaseBoundary: "Browser store approval and listing evidence are not yet proven.",
|
|
22728
|
-
evidencePacket: "browser-store-distribution",
|
|
22729
|
-
evidenceRequiredFields: [
|
|
22730
|
-
"stores",
|
|
22731
|
-
"submitted_versions",
|
|
22732
|
-
"review_status",
|
|
22733
|
-
"package_digest_matches_release",
|
|
22734
|
-
"listing_boundary_proof"
|
|
22735
|
-
],
|
|
22736
|
-
closesWhen: [
|
|
22737
|
-
"Chrome Web Store package id, version, and approval state are recorded.",
|
|
22738
|
-
"Any claimed Edge or Firefox store distribution has matching approval evidence.",
|
|
22739
|
-
"Store package digest matches the validated MV3 release artifact.",
|
|
22740
|
-
"Store listing text uses the same proven/not-proven boundary."
|
|
22741
|
-
]
|
|
22742
|
-
},
|
|
22743
23578
|
{
|
|
22744
23579
|
id: "high-risk-desktop-action-execution",
|
|
22745
23580
|
label: "High-risk desktop action execution after authorization",
|
|
@@ -22820,19 +23655,26 @@ No global install:
|
|
|
22820
23655
|
|
|
22821
23656
|
Open Control Tower:
|
|
22822
23657
|
${GUARDIAN_OPEN_CONTROL_TOWER_COMMAND}
|
|
22823
|
-
aliases: guardian tower, guardian control-tower
|
|
23658
|
+
start aliases: guardian launch, guardian tower, guardian control-tower
|
|
22824
23659
|
|
|
22825
23660
|
Usage:
|
|
22826
23661
|
guardian --version
|
|
22827
23662
|
guardian version [--json]
|
|
22828
|
-
guardian setup [--json] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--extension-id=<chrome-extension-id>]
|
|
23663
|
+
guardian setup [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317] [--no-launch] [--no-mcp] [--extension-id=<chrome-extension-id>]
|
|
22829
23664
|
guardian install [--json]
|
|
22830
23665
|
guardian doctor [--json]
|
|
22831
23666
|
guardian readiness [--json] [--strict]
|
|
23667
|
+
guardian release checklist --version=<semver> [--json]
|
|
23668
|
+
guardian release flow --version=<semver> [--json]
|
|
23669
|
+
guardian release verify --version=<semver> [--json]
|
|
23670
|
+
guardian release paste --version=<semver> [--json]
|
|
23671
|
+
guardian release command --version=<semver> [--publish|--dry-run=false] [--channels=all|npm|browser|evidence] [--run-docker-smoke=true|false] [--json]
|
|
23672
|
+
guardian release secrets [--json]
|
|
23673
|
+
guardian release browser-store [--json]
|
|
22832
23674
|
guardian open [--json] [--print] [--url=http://127.0.0.1:<port>]
|
|
22833
23675
|
guardian status [--json]
|
|
22834
23676
|
guardian start [--json] [--host=127.0.0.1] [--port=4317]
|
|
22835
|
-
guardian launch|tower|control-tower [--json] [--print] [--host=127.0.0.1] [--port=4317]
|
|
23677
|
+
guardian launch|tower|control-tower [--json] [--open] [--print] [--host=127.0.0.1] [--port=4317]
|
|
22836
23678
|
guardian stop [--json] [--url=http://127.0.0.1:<port>/control-tower]
|
|
22837
23679
|
guardian service install [--json] [--platform=auto|launchd|systemd|windows-task-scheduler] [--force]
|
|
22838
23680
|
guardian service status [--json]
|
|
@@ -22888,6 +23730,7 @@ Defaults are local-first: raw capture, cloud sync, learning graph, and app autop
|
|
|
22888
23730
|
"permissions.json"
|
|
22889
23731
|
];
|
|
22890
23732
|
GUARDIAN_DATA_DIR_NAMES = ["ecl", "receipts", "mcp"];
|
|
23733
|
+
GUARDIAN_MIN_SUPPORTED_NODE_VERSION = [20, 20, 0];
|
|
22891
23734
|
}
|
|
22892
23735
|
});
|
|
22893
23736
|
|
|
@@ -23806,10 +24649,16 @@ function confirmationTokenFor(receipt, actionRequest) {
|
|
|
23806
24649
|
return `guardian-confirm:${stableId(
|
|
23807
24650
|
receipt.receipt_hash,
|
|
23808
24651
|
actionRequest.action_id,
|
|
24652
|
+
actionRequest.app_id,
|
|
23809
24653
|
actionRequest.action_type,
|
|
23810
|
-
actionRequest.
|
|
24654
|
+
actionRequest.target_ref,
|
|
24655
|
+
actionRequest.payload_hash,
|
|
24656
|
+
normalizedPolicyPackBinding(actionRequest.policy_pack_ids)
|
|
23811
24657
|
)}`;
|
|
23812
24658
|
}
|
|
24659
|
+
function normalizedPolicyPackBinding(policyPackIds) {
|
|
24660
|
+
return [...new Set(policyPackIds)].sort().join(",");
|
|
24661
|
+
}
|
|
23813
24662
|
function buildLocalActionExecutionPlan(actionRequest, receipt, now) {
|
|
23814
24663
|
const core = {
|
|
23815
24664
|
action_id: actionRequest.action_id,
|
|
@@ -24906,6 +25755,7 @@ __export(daemon_exports, {
|
|
|
24906
25755
|
processGuardianControlTowerSourcePermissionRequest: () => processGuardianControlTowerSourcePermissionRequest,
|
|
24907
25756
|
processGuardianDaemonHealthRequest: () => processGuardianDaemonHealthRequest,
|
|
24908
25757
|
processGuardianDaemonStopRequest: () => processGuardianDaemonStopRequest,
|
|
25758
|
+
processGuardianLiveCoachEventRequest: () => processGuardianLiveCoachEventRequest,
|
|
24909
25759
|
readGuardianDaemonJsonBody: () => readGuardianDaemonJsonBody,
|
|
24910
25760
|
renderControlTowerStatusPage: () => renderControlTowerStatusPage,
|
|
24911
25761
|
startGuardianDaemonLoopback: () => startGuardianDaemonLoopback
|
|
@@ -25032,7 +25882,8 @@ async function handleRequest(input2) {
|
|
|
25032
25882
|
writeJson(input2.response, 200, {
|
|
25033
25883
|
ok: true,
|
|
25034
25884
|
service: "project-guardian-daemon",
|
|
25035
|
-
rawContentPersistence: false
|
|
25885
|
+
rawContentPersistence: false,
|
|
25886
|
+
version: GUARDIAN_CLI_VERSION
|
|
25036
25887
|
});
|
|
25037
25888
|
return;
|
|
25038
25889
|
}
|
|
@@ -25186,6 +26037,24 @@ async function handleRequest(input2) {
|
|
|
25186
26037
|
writeAdminResponse(input2.response, result2.statusCode, result2.body, parsedBody2.redirect);
|
|
25187
26038
|
return;
|
|
25188
26039
|
}
|
|
26040
|
+
if (input2.request.method === "POST" && input2.request.url === "/v1/guardian/live-coach-event") {
|
|
26041
|
+
const suppliedToken2 = headerValue(input2.request, ADMIN_HEADER);
|
|
26042
|
+
const parsedBody2 = await readGuardianDaemonJsonBody(input2.request);
|
|
26043
|
+
if (!parsedBody2.ok) {
|
|
26044
|
+
writeJson(input2.response, parsedBody2.statusCode, parsedBody2.body);
|
|
26045
|
+
return;
|
|
26046
|
+
}
|
|
26047
|
+
const result2 = await processGuardianLiveCoachEventRequest({
|
|
26048
|
+
profile: input2.profile,
|
|
26049
|
+
token: input2.token,
|
|
26050
|
+
suppliedToken: suppliedToken2,
|
|
26051
|
+
body: parsedBody2.body,
|
|
26052
|
+
now: input2.now,
|
|
26053
|
+
store: input2.store
|
|
26054
|
+
});
|
|
26055
|
+
writeJson(input2.response, result2.statusCode, result2.body);
|
|
26056
|
+
return;
|
|
26057
|
+
}
|
|
25189
26058
|
if (input2.request.method !== "POST" || input2.request.url !== "/v1/guardian/process-prompt") {
|
|
25190
26059
|
writeJson(input2.response, 404, { ok: false, error: "not_found" });
|
|
25191
26060
|
return;
|
|
@@ -25221,7 +26090,8 @@ function processGuardianDaemonHealthRequest(input2) {
|
|
|
25221
26090
|
body: {
|
|
25222
26091
|
ok: true,
|
|
25223
26092
|
service: "project-guardian-daemon",
|
|
25224
|
-
rawContentPersistence: false
|
|
26093
|
+
rawContentPersistence: false,
|
|
26094
|
+
version: GUARDIAN_CLI_VERSION
|
|
25225
26095
|
}
|
|
25226
26096
|
};
|
|
25227
26097
|
}
|
|
@@ -25637,6 +26507,44 @@ async function processGuardianBrowserBridgeRequest(input2) {
|
|
|
25637
26507
|
});
|
|
25638
26508
|
return { statusCode: 200, body: { ok: true, decision } };
|
|
25639
26509
|
}
|
|
26510
|
+
async function processGuardianLiveCoachEventRequest(input2) {
|
|
26511
|
+
if (!isAuthorized(input2.token, input2.suppliedToken)) {
|
|
26512
|
+
return {
|
|
26513
|
+
statusCode: 401,
|
|
26514
|
+
body: {
|
|
26515
|
+
ok: false,
|
|
26516
|
+
error: "unauthorized"
|
|
26517
|
+
}
|
|
26518
|
+
};
|
|
26519
|
+
}
|
|
26520
|
+
const envelope = parseLiveCoachEventEnvelope(input2.body);
|
|
26521
|
+
if (!envelope.ok) {
|
|
26522
|
+
return {
|
|
26523
|
+
statusCode: 400,
|
|
26524
|
+
body: {
|
|
26525
|
+
ok: false,
|
|
26526
|
+
error: envelope.error
|
|
26527
|
+
}
|
|
26528
|
+
};
|
|
26529
|
+
}
|
|
26530
|
+
const timestamp = validDateTime(envelope.request.capturedAt) ?? input2.now().toISOString();
|
|
26531
|
+
const transactionId = `txn:browser-live-coach:${digest4(
|
|
26532
|
+
`${envelope.request.provider}:${envelope.request.destination}:${envelope.request.category}:${timestamp}`
|
|
26533
|
+
).slice(0, 20)}`;
|
|
26534
|
+
const receipt = buildLiveCoachReceipt(envelope.request, transactionId, timestamp);
|
|
26535
|
+
await input2.store.putReceipt(receipt);
|
|
26536
|
+
await input2.store.appendEvent(
|
|
26537
|
+
buildLiveCoachEvent(envelope.request, transactionId, timestamp, receipt)
|
|
26538
|
+
);
|
|
26539
|
+
return {
|
|
26540
|
+
statusCode: 200,
|
|
26541
|
+
body: {
|
|
26542
|
+
ok: true,
|
|
26543
|
+
receipt_id: receipt.receipt_id,
|
|
26544
|
+
raw_content_included: false
|
|
26545
|
+
}
|
|
26546
|
+
};
|
|
26547
|
+
}
|
|
25640
26548
|
async function processBrowserPrompt(input2) {
|
|
25641
26549
|
const timestamp = validDateTime(input2.request.capturedAt) ?? input2.now().toISOString();
|
|
25642
26550
|
const transactionId = `txn:browser:${digest4(`${input2.request.promptText}:${timestamp}`).slice(0, 20)}`;
|
|
@@ -25815,6 +26723,95 @@ function parseBridgeEnvelope(value) {
|
|
|
25815
26723
|
}
|
|
25816
26724
|
};
|
|
25817
26725
|
}
|
|
26726
|
+
function parseLiveCoachEventEnvelope(value) {
|
|
26727
|
+
if (typeof value !== "object" || value === null) {
|
|
26728
|
+
return { ok: false, error: "invalid_json_body" };
|
|
26729
|
+
}
|
|
26730
|
+
const envelope = value;
|
|
26731
|
+
if (envelope.adapter !== "browser_mv3" || typeof envelope.request !== "object" || envelope.request === null) {
|
|
26732
|
+
return { ok: false, error: "invalid_guardian_adapter_envelope" };
|
|
26733
|
+
}
|
|
26734
|
+
const candidate = envelope.request;
|
|
26735
|
+
if ("promptText" in candidate || "rawPrompt" in candidate || "detectedValue" in candidate) {
|
|
26736
|
+
return { ok: false, error: "raw_content_not_allowed_for_live_coach_event" };
|
|
26737
|
+
}
|
|
26738
|
+
const provider = parseProvider(candidate.provider);
|
|
26739
|
+
const destination = stringField(candidate, "destination");
|
|
26740
|
+
const pageOrigin = stringField(candidate, "pageOrigin");
|
|
26741
|
+
const category = parseLiveCoachCategory(candidate.category);
|
|
26742
|
+
const capturedAt = stringField(candidate, "capturedAt");
|
|
26743
|
+
if (!destination || !pageOrigin || !category || !capturedAt) {
|
|
26744
|
+
return { ok: false, error: "missing_required_live_coach_event_fields" };
|
|
26745
|
+
}
|
|
26746
|
+
return {
|
|
26747
|
+
ok: true,
|
|
26748
|
+
request: {
|
|
26749
|
+
provider,
|
|
26750
|
+
destination,
|
|
26751
|
+
pageOrigin,
|
|
26752
|
+
category,
|
|
26753
|
+
capturedAt
|
|
26754
|
+
}
|
|
26755
|
+
};
|
|
26756
|
+
}
|
|
26757
|
+
function parseLiveCoachCategory(value) {
|
|
26758
|
+
return value === "ssn" || value === "password" || value === "secret" || value === "payment" || value === "health" ? value : void 0;
|
|
26759
|
+
}
|
|
26760
|
+
function buildLiveCoachReceipt(request, transactionId, timestamp) {
|
|
26761
|
+
const core = {
|
|
26762
|
+
transaction_id: transactionId,
|
|
26763
|
+
provider: request.provider,
|
|
26764
|
+
destination_hash: digest4(request.destination),
|
|
26765
|
+
page_origin_hash: digest4(request.pageOrigin),
|
|
26766
|
+
category: request.category,
|
|
26767
|
+
created_at: timestamp,
|
|
26768
|
+
raw_content_included: false
|
|
26769
|
+
};
|
|
26770
|
+
return {
|
|
26771
|
+
schema_version: PERSONAL_FABRIC_CONTRACTS_SCHEMA_VERSION,
|
|
26772
|
+
receipt_id: `receipt:${transactionId}:live-coach`,
|
|
26773
|
+
transaction_id: transactionId,
|
|
26774
|
+
receipt_type: "policy",
|
|
26775
|
+
disposition: "warn",
|
|
26776
|
+
policy_basis: [
|
|
26777
|
+
"live-sensitive-prompt-coach",
|
|
26778
|
+
`category:${request.category}`,
|
|
26779
|
+
`provider:${request.provider}`
|
|
26780
|
+
],
|
|
26781
|
+
receipt_hash: `sha256:${digest4(JSON.stringify(core))}`,
|
|
26782
|
+
raw_content_included: false,
|
|
26783
|
+
created_at: timestamp,
|
|
26784
|
+
summary: `Guardian flagged ${liveCoachCategoryLabel(request.category)} while drafting in ${providerDisplayName(request.provider)}.`
|
|
26785
|
+
};
|
|
26786
|
+
}
|
|
26787
|
+
function buildLiveCoachEvent(request, transactionId, timestamp, receipt) {
|
|
26788
|
+
const payload = {
|
|
26789
|
+
provider: request.provider,
|
|
26790
|
+
destination_hash: digest4(request.destination),
|
|
26791
|
+
page_origin_hash: digest4(request.pageOrigin),
|
|
26792
|
+
category: request.category,
|
|
26793
|
+
raw_content_included: false
|
|
26794
|
+
};
|
|
26795
|
+
return {
|
|
26796
|
+
event_id: `event:${transactionId}:live-coach`,
|
|
26797
|
+
transaction_id: transactionId,
|
|
26798
|
+
event_type: "coach_presented",
|
|
26799
|
+
occurred_at: timestamp,
|
|
26800
|
+
actor: "guardian-daemon",
|
|
26801
|
+
summary: `Live Prompt Coach presented ${request.category} warning.`,
|
|
26802
|
+
payload_hash: `sha256:${digest4(JSON.stringify(payload))}`,
|
|
26803
|
+
receipt_id: receipt.receipt_id,
|
|
26804
|
+
graph_refs: [`provider:${request.provider}`, `receipt:${receipt.receipt_id}`],
|
|
26805
|
+
redaction_state: "metadata_only"
|
|
26806
|
+
};
|
|
26807
|
+
}
|
|
26808
|
+
function liveCoachCategoryLabel(category) {
|
|
26809
|
+
if (category === "ssn") return "possible SSN sharing";
|
|
26810
|
+
if (category === "password") return "possible credential sharing";
|
|
26811
|
+
if (category === "secret") return "possible secret sharing";
|
|
26812
|
+
if (category === "payment") return "possible financial data";
|
|
26813
|
+
return "possible health information";
|
|
26814
|
+
}
|
|
25818
26815
|
function parseProvider(value) {
|
|
25819
26816
|
return value === "chatgpt" || value === "claude" || value === "gemini" || value === "perplexity" ? value : "unknown";
|
|
25820
26817
|
}
|
|
@@ -26573,6 +27570,7 @@ function renderControlTowerStatusPage(profile, receipts = [], searchGraph = { no
|
|
|
26573
27570
|
.activity-heading { justify-content: space-between; gap: 16px; margin-bottom: 12px; }
|
|
26574
27571
|
.activity-heading h2 { margin: 0; }
|
|
26575
27572
|
.filter-chips { gap: 8px; flex-wrap: wrap; }
|
|
27573
|
+
.activity-filter-status { margin: 0 0 12px; color: #91a1b8; font-size: 14px; font-weight: 650; }
|
|
26576
27574
|
.chip {
|
|
26577
27575
|
min-width: auto;
|
|
26578
27576
|
min-height: 36px;
|
|
@@ -26686,6 +27684,7 @@ ${heroMetricCards}
|
|
|
26686
27684
|
<button type="button" class="chip" data-activity-filter="allowed" aria-pressed="false">Allowed</button>
|
|
26687
27685
|
</div>
|
|
26688
27686
|
</div>
|
|
27687
|
+
<p class="activity-filter-status" data-activity-filter-status aria-live="polite">Showing all local Guardian activity.</p>
|
|
26689
27688
|
<div class="activity-list" data-activity-list>
|
|
26690
27689
|
${activityFeedHtml}
|
|
26691
27690
|
<div class="empty-filter-state" data-activity-empty hidden>No activity matches this filter yet.</div>
|
|
@@ -26950,12 +27949,37 @@ ${learningEventRows}
|
|
|
26950
27949
|
const filters = Array.from(document.querySelectorAll('[data-activity-filter]'));
|
|
26951
27950
|
const list = document.querySelector('[data-activity-list]');
|
|
26952
27951
|
const emptyState = document.querySelector('[data-activity-empty]');
|
|
27952
|
+
const filterStatus = document.querySelector('[data-activity-filter-status]');
|
|
27953
|
+
const filterCopy = {
|
|
27954
|
+
all: {
|
|
27955
|
+
status: 'Showing all local Guardian activity.',
|
|
27956
|
+
empty: 'No Guardian activity recorded yet.',
|
|
27957
|
+
},
|
|
27958
|
+
blocked: {
|
|
27959
|
+
status: 'Showing blocked Guardian decisions.',
|
|
27960
|
+
empty: 'No blocked activity recorded yet.',
|
|
27961
|
+
},
|
|
27962
|
+
flagged: {
|
|
27963
|
+
status: 'Showing flagged Guardian decisions.',
|
|
27964
|
+
empty: 'No flagged activity recorded yet.',
|
|
27965
|
+
},
|
|
27966
|
+
allowed: {
|
|
27967
|
+
status: 'Showing allowed Guardian decisions.',
|
|
27968
|
+
empty: 'No allowed activity recorded yet.',
|
|
27969
|
+
},
|
|
27970
|
+
};
|
|
27971
|
+
const setFilterCopy = (selectedFilter) => {
|
|
27972
|
+
const copy = filterCopy[selectedFilter] || filterCopy.all;
|
|
27973
|
+
if (filterStatus) filterStatus.textContent = copy.status;
|
|
27974
|
+
if (emptyState) emptyState.textContent = copy.empty;
|
|
27975
|
+
};
|
|
26953
27976
|
const setSelectedFilter = (selectedFilter) => {
|
|
26954
27977
|
for (const filter of filters) {
|
|
26955
27978
|
const selected = filter.getAttribute('data-activity-filter') === selectedFilter;
|
|
26956
27979
|
filter.classList.toggle('is-active', selected);
|
|
26957
27980
|
filter.setAttribute('aria-pressed', selected ? 'true' : 'false');
|
|
26958
27981
|
}
|
|
27982
|
+
setFilterCopy(selectedFilter);
|
|
26959
27983
|
};
|
|
26960
27984
|
const createActivityCard = (activity) => {
|
|
26961
27985
|
const card = document.createElement('article');
|