@singbox-iac/cli 0.1.6 → 0.1.7

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.
Files changed (52) hide show
  1. package/dist/cli/commands/apply.js +21 -9
  2. package/dist/cli/commands/apply.js.map +1 -1
  3. package/dist/cli/commands/history.d.ts +2 -0
  4. package/dist/cli/commands/history.js +21 -0
  5. package/dist/cli/commands/history.js.map +1 -0
  6. package/dist/cli/commands/rollback.d.ts +2 -0
  7. package/dist/cli/commands/rollback.js +38 -0
  8. package/dist/cli/commands/rollback.js.map +1 -0
  9. package/dist/cli/commands/verify.js +72 -20
  10. package/dist/cli/commands/verify.js.map +1 -1
  11. package/dist/cli/index.js +6 -0
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/domain/dns-plan.d.ts +27 -0
  14. package/dist/domain/dns-plan.js +2 -0
  15. package/dist/domain/dns-plan.js.map +1 -0
  16. package/dist/domain/intent.d.ts +61 -0
  17. package/dist/domain/intent.js +2 -0
  18. package/dist/domain/intent.js.map +1 -0
  19. package/dist/domain/transaction.d.ts +12 -0
  20. package/dist/domain/transaction.js +2 -0
  21. package/dist/domain/transaction.js.map +1 -0
  22. package/dist/domain/verification-plan.d.ts +34 -0
  23. package/dist/domain/verification-plan.js +2 -0
  24. package/dist/domain/verification-plan.js.map +1 -0
  25. package/dist/modules/authoring/index.d.ts +2 -0
  26. package/dist/modules/authoring/index.js +32 -17
  27. package/dist/modules/authoring/index.js.map +1 -1
  28. package/dist/modules/build/index.d.ts +3 -0
  29. package/dist/modules/build/index.js +8 -1
  30. package/dist/modules/build/index.js.map +1 -1
  31. package/dist/modules/compiler/index.d.ts +2 -2
  32. package/dist/modules/compiler/index.js +38 -53
  33. package/dist/modules/compiler/index.js.map +1 -1
  34. package/dist/modules/dns-plan/index.d.ts +10 -0
  35. package/dist/modules/dns-plan/index.js +104 -0
  36. package/dist/modules/dns-plan/index.js.map +1 -0
  37. package/dist/modules/intent/index.d.ts +7 -0
  38. package/dist/modules/intent/index.js +101 -0
  39. package/dist/modules/intent/index.js.map +1 -0
  40. package/dist/modules/transactions/index.d.ts +20 -0
  41. package/dist/modules/transactions/index.js +150 -0
  42. package/dist/modules/transactions/index.js.map +1 -0
  43. package/dist/modules/update/index.d.ts +1 -0
  44. package/dist/modules/update/index.js +22 -6
  45. package/dist/modules/update/index.js.map +1 -1
  46. package/dist/modules/verification/index.d.ts +42 -0
  47. package/dist/modules/verification/index.js +274 -0
  48. package/dist/modules/verification/index.js.map +1 -1
  49. package/dist/modules/verification-plan/index.d.ts +9 -0
  50. package/dist/modules/verification-plan/index.js +117 -0
  51. package/dist/modules/verification-plan/index.js.map +1 -0
  52. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { applyConfig } from "../../modules/manager/index.js";
2
+ import { applyWithTransaction } from "../../modules/transactions/index.js";
2
3
  import { resolveBuilderConfig } from "../command-helpers.js";
3
4
  export function registerApplyCommand(program) {
4
5
  program
@@ -18,15 +19,26 @@ export function registerApplyCommand(program) {
18
19
  if (!stagingPath || !livePath) {
19
20
  throw new Error("Unable to resolve staging/live paths. Pass --input/--live-path or provide a builder config.");
20
21
  }
21
- await applyConfig({
22
- stagingPath,
23
- livePath,
24
- ...(backupPath ? { backupPath } : {}),
25
- ...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
26
- ...(options.reload !== undefined ? { reload: options.reload } : {}),
27
- ...(builderConfig?.runtime.reload ? { runtime: builderConfig.runtime.reload } : {}),
28
- });
29
- process.stdout.write(`Applied config.\nSource: ${stagingPath}\nLive: ${livePath}\n${backupPath ? `Backup: ${backupPath}\n` : ""}`);
22
+ const transaction = builderConfig
23
+ ? await applyWithTransaction({
24
+ config: builderConfig,
25
+ generatedPath: stagingPath,
26
+ livePath,
27
+ backupPath: backupPath ?? builderConfig.output.backupPath,
28
+ verificationSummary: {},
29
+ apply: async () => {
30
+ await applyConfig({
31
+ stagingPath,
32
+ livePath,
33
+ ...(backupPath ? { backupPath } : {}),
34
+ ...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
35
+ ...(options.reload !== undefined ? { reload: options.reload } : {}),
36
+ ...(builderConfig?.runtime.reload ? { runtime: builderConfig.runtime.reload } : {}),
37
+ });
38
+ },
39
+ })
40
+ : undefined;
41
+ process.stdout.write(`Applied config.\nSource: ${stagingPath}\nLive: ${livePath}\n${backupPath ? `Backup: ${backupPath}\n` : ""}${transaction ? `Transaction: ${transaction.txId}\n` : ""}`);
30
42
  });
31
43
  }
32
44
  //# sourceMappingURL=apply.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/cli/commands/apply.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SAC5D,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;SAC3D,MAAM,CAAC,oBAAoB,EAAE,2BAA2B,CAAC;SACzD,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAC7D,MAAM,CAAC,uBAAuB,EAAE,yBAAyB,CAAC;SAC1D,MAAM,CAAC,UAAU,EAAE,+BAA+B,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC;QACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC;QACpE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC;QAE1E,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,CAAC;YAChB,WAAW;YACX,QAAQ;YACR,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4BAA4B,WAAW,WAAW,QAAQ,KACxD,UAAU,CAAC,CAAC,CAAC,WAAW,UAAU,IAAI,CAAC,CAAC,CAAC,EAC3C,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/cli/commands/apply.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SAC5D,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;SAC3D,MAAM,CAAC,oBAAoB,EAAE,2BAA2B,CAAC;SACzD,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAC7D,MAAM,CAAC,uBAAuB,EAAE,yBAAyB,CAAC;SAC1D,MAAM,CAAC,UAAU,EAAE,+BAA+B,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC;QACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC;QACpE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC;QAE1E,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,aAAa;YAC/B,CAAC,CAAC,MAAM,oBAAoB,CAAC;gBACzB,MAAM,EAAE,aAAa;gBACrB,aAAa,EAAE,WAAW;gBAC1B,QAAQ;gBACR,UAAU,EAAE,UAAU,IAAI,aAAa,CAAC,MAAM,CAAC,UAAU;gBACzD,mBAAmB,EAAE,EAAE;gBACvB,KAAK,EAAE,KAAK,IAAI,EAAE;oBAChB,MAAM,WAAW,CAAC;wBAChB,WAAW;wBACX,QAAQ;wBACR,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACrC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACpE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACnE,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACpF,CAAC,CAAC;gBACL,CAAC;aACF,CAAC;YACJ,CAAC,CAAC,SAAS,CAAC;QAEd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4BAA4B,WAAW,WAAW,QAAQ,KACxD,UAAU,CAAC,CAAC,CAAC,WAAW,UAAU,IAAI,CAAC,CAAC,CAAC,EAC3C,GAAG,WAAW,CAAC,CAAC,CAAC,gBAAgB,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerHistoryCommand(program: Command): void;
@@ -0,0 +1,21 @@
1
+ import { listTransactionHistory } from "../../modules/transactions/index.js";
2
+ import { resolveBuilderConfig } from "../command-helpers.js";
3
+ export function registerHistoryCommand(program) {
4
+ program
5
+ .command("history")
6
+ .description("Show recent publish transactions.")
7
+ .option("-c, --config <path>", "path to builder config YAML")
8
+ .action(async (options) => {
9
+ const builderConfig = await resolveBuilderConfig(options);
10
+ if (!builderConfig) {
11
+ throw new Error("history requires a builder config.");
12
+ }
13
+ const entries = await listTransactionHistory(builderConfig);
14
+ const lines = [
15
+ `Transactions: ${entries.length}`,
16
+ ...entries.map((entry) => `- ${entry.txId} ${entry.status} ${entry.startedAt} ${entry.generatedPath} -> ${entry.livePath}`),
17
+ ];
18
+ process.stdout.write(`${lines.join("\n")}\n`);
19
+ });
20
+ }
21
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/cli/commands/history.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,OAAqC,EAAE,EAAE;QACtD,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,aAAa,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG;YACZ,iBAAiB,OAAO,CAAC,MAAM,EAAE;YACjC,GAAG,OAAO,CAAC,GAAG,CACZ,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,aAAa,OAAO,KAAK,CAAC,QAAQ,EAAE,CACnG;SACF,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerRollbackCommand(program: Command): void;
@@ -0,0 +1,38 @@
1
+ import { reloadRuntime, resolveSingBoxBinary } from "../../modules/manager/index.js";
2
+ import { rollbackToPrevious } from "../../modules/transactions/index.js";
3
+ import { resolveBuilderConfig } from "../command-helpers.js";
4
+ export function registerRollbackCommand(program) {
5
+ program
6
+ .command("rollback")
7
+ .description("Rollback the live config to the previous published snapshot.")
8
+ .option("-c, --config <path>", "path to builder config YAML")
9
+ .option("--to <target>", 'rollback target, currently only "previous"', "previous")
10
+ .option("--sing-box-bin <path>", "path to sing-box binary")
11
+ .option("--reload", "reload sing-box after restoring the previous snapshot")
12
+ .action(async (options) => {
13
+ if (options.to !== "previous") {
14
+ throw new Error('Only "--to previous" is currently supported.');
15
+ }
16
+ const builderConfig = await resolveBuilderConfig(options);
17
+ if (!builderConfig) {
18
+ throw new Error("rollback requires a builder config.");
19
+ }
20
+ const afterRestore = options.reload || options.singBoxBin
21
+ ? async () => {
22
+ await resolveSingBoxBinary(options.singBoxBin);
23
+ if (options.reload) {
24
+ await reloadRuntime({
25
+ ...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
26
+ runtime: builderConfig.runtime.reload,
27
+ });
28
+ }
29
+ }
30
+ : undefined;
31
+ const transaction = await rollbackToPrevious({
32
+ config: builderConfig,
33
+ ...(afterRestore ? { afterRestore } : {}),
34
+ });
35
+ process.stdout.write(`Rollback complete.\nTransaction: ${transaction.txId}\nLive: ${transaction.livePath}\nSnapshot: ${transaction.snapshotPath}\n`);
36
+ });
37
+ }
38
+ //# sourceMappingURL=rollback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../../src/cli/commands/rollback.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,8DAA8D,CAAC;SAC3E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SAC5D,MAAM,CAAC,eAAe,EAAE,4CAA4C,EAAE,UAAU,CAAC;SACjF,MAAM,CAAC,uBAAuB,EAAE,yBAAyB,CAAC;SAC1D,MAAM,CAAC,UAAU,EAAE,uDAAuD,CAAC;SAC3E,MAAM,CAAC,KAAK,EAAE,OAA+B,EAAE,EAAE;QAChD,IAAI,OAAO,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU;YAClC,CAAC,CAAC,KAAK,IAAI,EAAE;gBACT,MAAM,oBAAoB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC/C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACnB,MAAM,aAAa,CAAC;wBAClB,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACpE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM;qBACtC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACH,CAAC,CAAC,SAAS,CAAC;QAEhB,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC;YAC3C,MAAM,EAAE,aAAa;YACrB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oCAAoC,WAAW,CAAC,IAAI,WAAW,WAAW,CAAC,QAAQ,eAAe,WAAW,CAAC,YAAY,IAAI,CAC/H,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,19 +1,25 @@
1
- import { buildConfigArtifact } from "../../modules/build/index.js";
2
- import { assertVerificationReportPassed, verifyConfigRoutes, } from "../../modules/verification/index.js";
1
+ import { existsSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
+ import { buildConfigArtifact, resolveEffectiveIntent } from "../../modules/build/index.js";
4
+ import { buildDnsPlan } from "../../modules/dns-plan/index.js";
5
+ import { buildVerificationPlan } from "../../modules/verification-plan/index.js";
6
+ import { assertVerificationReportPassed, verifyAppPlan, verifyConfigRoutes, verifyDnsPlan, verifyEgressPlan, verifyProtocolPlan, } from "../../modules/verification/index.js";
3
7
  import { resolveBuilderConfig } from "../command-helpers.js";
4
8
  export function registerVerifyCommand(program) {
5
9
  program
6
10
  .command("verify")
7
11
  .description("Build and run closed-loop route verification with sing-box and Chrome.")
12
+ .argument("[mode]", "verification scope: all, route, dns, egress, app, protocol", "all")
8
13
  .option("-c, --config <path>", "path to builder config YAML")
9
14
  .option("-i, --input <path>", "path to an existing config JSON to verify")
10
15
  .option("--subscription-url <url>", "override subscription URL when rebuilding")
11
16
  .option("--subscription-file <path>", "use a local subscription file instead of fetching")
12
17
  .option("--sing-box-bin <path>", "path to sing-box binary")
13
18
  .option("--chrome-bin <path>", "path to Chrome binary")
14
- .action(async (options) => {
19
+ .action(async (mode, options) => {
15
20
  let configPath = options.input;
16
21
  const builderConfig = await resolveBuilderConfig(options);
22
+ let effectiveIntent = builderConfig ? await resolveEffectiveIntent(builderConfig) : undefined;
17
23
  if (!configPath) {
18
24
  if (!builderConfig) {
19
25
  throw new Error("Verification requires --input or a builder config.");
@@ -24,26 +30,72 @@ export function registerVerifyCommand(program) {
24
30
  ...(options.subscriptionUrl ? { subscriptionUrl: options.subscriptionUrl } : {}),
25
31
  });
26
32
  configPath = result.outputPath;
33
+ effectiveIntent = result.intent;
27
34
  }
28
- const report = await verifyConfigRoutes({
29
- configPath,
30
- ...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
31
- ...(options.chromeBin ? { chromeBinary: options.chromeBin } : {}),
32
- ...(builderConfig ? { configuredScenarios: builderConfig.verification.scenarios } : {}),
35
+ if (!builderConfig || !effectiveIntent) {
36
+ throw new Error("Verification requires a builder config so the verification plan can be built.");
37
+ }
38
+ const dnsPlan = buildDnsPlan({
39
+ config: builderConfig,
40
+ intent: effectiveIntent,
41
+ activeRuleSetTags: builderConfig.ruleSets
42
+ .filter((ruleSet) => existsSync(ruleSet.path))
43
+ .map((ruleSet) => ruleSet.tag),
44
+ });
45
+ const verificationPlan = buildVerificationPlan({
46
+ config: builderConfig,
47
+ intent: effectiveIntent,
48
+ dnsPlan,
33
49
  });
34
- const lines = [
35
- `Verified config: ${report.configPath}`,
36
- `Verification config: ${report.verifyConfigPath}`,
37
- `sing-box log: ${report.logPath}`,
38
- "",
39
- "Static checks:",
40
- ...report.checks.map((check) => `- ${check.passed ? "PASS" : "FAIL"} ${check.name}: ${check.details}`),
41
- "",
42
- "Runtime scenarios:",
43
- ...report.scenarios.map((scenario) => `- ${scenario.passed ? "PASS" : "FAIL"} ${scenario.name} -> ${scenario.expectedOutboundTag} (${scenario.inboundTag})`),
44
- ];
50
+ const rawConfig = JSON.parse(await readFile(configPath, "utf8"));
51
+ const lines = [`Verified config: ${configPath}`, `Mode: ${mode}`];
52
+ if (mode === "all" || mode === "route") {
53
+ const report = await verifyConfigRoutes({
54
+ configPath,
55
+ ...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
56
+ ...(options.chromeBin ? { chromeBinary: options.chromeBin } : {}),
57
+ configuredScenarios: builderConfig.verification.scenarios,
58
+ });
59
+ lines.push("");
60
+ lines.push("Route checks:");
61
+ lines.push(...report.scenarios.map((scenario) => `- ${scenario.passed ? "PASS" : "FAIL"} ${scenario.name}: ${scenario.expectedOutboundTag} via ${scenario.inboundTag}`));
62
+ assertVerificationReportPassed(report);
63
+ }
64
+ if (mode === "all" || mode === "dns") {
65
+ lines.push("");
66
+ lines.push("DNS checks:");
67
+ lines.push(...formatDnsChecks(verifyDnsPlan(verificationPlan, dnsPlan)));
68
+ }
69
+ if (mode === "all" || mode === "app") {
70
+ lines.push("");
71
+ lines.push("App checks:");
72
+ lines.push(...verifyAppPlan(verificationPlan, rawConfig).map((check) => `- ${check.passed ? "PASS" : "FAIL"} ${check.app}: ${check.expectedInbound} -> ${check.expectedOutboundGroup}`));
73
+ }
74
+ if (mode === "all" || mode === "protocol") {
75
+ lines.push("");
76
+ lines.push("Protocol checks:");
77
+ lines.push(...formatProtocolChecks(verifyProtocolPlan(verificationPlan, rawConfig)));
78
+ }
79
+ if (mode === "all" || mode === "egress") {
80
+ const egressResults = await verifyEgressPlan({
81
+ configPath,
82
+ checks: verificationPlan.egressChecks,
83
+ ...(options.singBoxBin ? { singBoxBinary: options.singBoxBin } : {}),
84
+ });
85
+ lines.push("");
86
+ lines.push("Egress checks:");
87
+ lines.push(...formatEgressChecks(egressResults));
88
+ }
45
89
  process.stdout.write(`${lines.join("\n")}\n`);
46
- assertVerificationReportPassed(report);
47
90
  });
48
91
  }
92
+ function formatDnsChecks(checks) {
93
+ return checks.map((check) => `- ${check.passed ? "PASS" : "FAIL"} ${check.domain}: ${check.actualMode} via ${check.resolver}`);
94
+ }
95
+ function formatProtocolChecks(checks) {
96
+ return checks.map((check) => `- ${check.passed ? "PASS" : "FAIL"} ${new URL(check.target).hostname}: ${check.details}`);
97
+ }
98
+ function formatEgressChecks(checks) {
99
+ return checks.map((check) => `- ${check.passed ? "PASS" : "FAIL"} ${check.expectedOutboundGroup}: ${check.ip ?? "unknown-ip"} ${check.country ?? ""} ${check.asn ?? ""}`.trim());
100
+ }
49
101
  //# sourceMappingURL=verify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/cli/commands/verify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/cli/commands/verify.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -8,10 +8,12 @@ import { registerBuildCommand } from "./commands/build.js";
8
8
  import { registerCheckCommand } from "./commands/check.js";
9
9
  import { registerDoctorCommand } from "./commands/doctor.js";
10
10
  import { registerGoCommand } from "./commands/go.js";
11
+ import { registerHistoryCommand } from "./commands/history.js";
11
12
  import { registerInitCommand } from "./commands/init.js";
12
13
  import { registerProxifierCommand } from "./commands/proxifier.js";
13
14
  import { registerQuickstartCommand } from "./commands/quickstart.js";
14
15
  import { registerReloadCommand } from "./commands/reload.js";
16
+ import { registerRollbackCommand } from "./commands/rollback.js";
15
17
  import { registerRunCommand } from "./commands/run.js";
16
18
  import { registerScheduleCommand } from "./commands/schedule.js";
17
19
  import { registerSetupCommand } from "./commands/setup.js";
@@ -44,7 +46,9 @@ export function createProgram() {
44
46
  registerBuildCommand(program);
45
47
  registerCheckCommand(program);
46
48
  registerApplyCommand(program);
49
+ registerHistoryCommand(program);
47
50
  registerRunCommand(program);
51
+ registerRollbackCommand(program);
48
52
  registerVerifyCommand(program);
49
53
  registerDoctorCommand(program);
50
54
  registerProxifierCommand(program);
@@ -63,7 +67,9 @@ function hideAdvancedCommands(program) {
63
67
  "build",
64
68
  "check",
65
69
  "apply",
70
+ "history",
66
71
  "run",
72
+ "rollback",
67
73
  "verify",
68
74
  "doctor",
69
75
  "proxifier",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface DnsPlanServer {
2
+ readonly type: "local" | "tcp";
3
+ readonly tag: string;
4
+ readonly server?: string;
5
+ readonly serverPort?: number;
6
+ readonly preferGo?: boolean;
7
+ }
8
+ export interface DnsPlanRule {
9
+ readonly match: {
10
+ readonly domain?: readonly string[];
11
+ readonly domainSuffix?: readonly string[];
12
+ readonly ruleSet?: readonly string[];
13
+ };
14
+ readonly resolvers: readonly string[];
15
+ }
16
+ export interface DNSPlan {
17
+ readonly mode: "real-ip" | "fake-ip";
18
+ readonly defaultResolvers: readonly string[];
19
+ readonly directResolvers: readonly string[];
20
+ readonly proxyResolvers: readonly string[];
21
+ readonly fallbackResolvers: readonly string[];
22
+ readonly servers: readonly DnsPlanServer[];
23
+ readonly nameserverPolicy: readonly DnsPlanRule[];
24
+ readonly fakeIpFilter: readonly string[];
25
+ readonly localHosts?: Record<string, string>;
26
+ readonly strategy: "prefer_ipv4" | "prefer_ipv6";
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dns-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dns-plan.js","sourceRoot":"","sources":["../../src/domain/dns-plan.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ export type IntentVersion = "v1";
2
+ export type IntentPlacement = "beforeBuiltins" | "afterBuiltins";
3
+ export interface IntentVerifyHint {
4
+ readonly expectedCountry?: readonly string[];
5
+ readonly expectedASN?: readonly string[];
6
+ readonly probeUrls?: readonly string[];
7
+ }
8
+ export interface IntentSiteMatch {
9
+ readonly inbound?: readonly string[];
10
+ readonly protocol?: string;
11
+ readonly network?: "tcp" | "udp";
12
+ readonly port?: number;
13
+ readonly domain?: readonly string[];
14
+ readonly domainSuffix?: readonly string[];
15
+ readonly ruleSet?: readonly string[];
16
+ readonly category?: readonly string[];
17
+ }
18
+ export type IntentSiteAction = {
19
+ readonly type: "route";
20
+ readonly outboundGroup: string;
21
+ } | {
22
+ readonly type: "reject";
23
+ };
24
+ export interface IntentSitePolicy {
25
+ readonly placement: IntentPlacement;
26
+ readonly name?: string;
27
+ readonly match: IntentSiteMatch;
28
+ readonly action: IntentSiteAction;
29
+ readonly verify?: IntentVerifyHint;
30
+ }
31
+ export interface IntentProcessMatch {
32
+ readonly bundleId?: readonly string[];
33
+ readonly processName?: readonly string[];
34
+ }
35
+ export interface IntentProcessPolicy {
36
+ readonly name?: string;
37
+ readonly match: IntentProcessMatch;
38
+ readonly inbound: "in-proxifier" | "in-default";
39
+ readonly outboundGroup: string;
40
+ readonly verify?: {
41
+ readonly expectProxyHit?: boolean;
42
+ };
43
+ }
44
+ export interface IntentLocalOverride {
45
+ readonly hosts?: Record<string, string>;
46
+ readonly dnsPolicy?: readonly {
47
+ readonly domainSuffix: readonly string[];
48
+ readonly server: readonly string[];
49
+ }[];
50
+ }
51
+ export interface IntentIR {
52
+ readonly version: IntentVersion;
53
+ readonly globals: {
54
+ readonly updateIntervalMinutes?: number;
55
+ readonly preferIPv6?: boolean;
56
+ readonly enableTUN?: boolean;
57
+ };
58
+ readonly sitePolicies: readonly IntentSitePolicy[];
59
+ readonly processPolicies: readonly IntentProcessPolicy[];
60
+ readonly localOverrides: IntentLocalOverride;
61
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/domain/intent.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ export interface ApplyTransaction {
2
+ readonly txId: string;
3
+ readonly generatedPath: string;
4
+ readonly livePath: string;
5
+ readonly backupPath: string;
6
+ readonly snapshotPath?: string;
7
+ readonly startedAt: string;
8
+ readonly completedAt?: string;
9
+ readonly status: "pending" | "applied" | "rolled-back" | "failed";
10
+ readonly verificationSummary: Record<string, unknown>;
11
+ readonly error?: string;
12
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/domain/transaction.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ export interface VerificationPlan {
2
+ readonly dnsChecks: readonly {
3
+ readonly domain: string;
4
+ readonly expectedMode: "fake-ip" | "real-ip";
5
+ readonly expectedResolver?: string;
6
+ }[];
7
+ readonly routeChecks: readonly {
8
+ readonly id: string;
9
+ readonly name: string;
10
+ readonly target: string;
11
+ readonly inbound: "in-mixed" | "in-proxifier";
12
+ readonly expectedOutboundGroup: string;
13
+ readonly expectedRuleHint?: string;
14
+ }[];
15
+ readonly egressChecks: readonly {
16
+ readonly id: string;
17
+ readonly target: string;
18
+ readonly inbound: "in-mixed" | "in-proxifier";
19
+ readonly expectedOutboundGroup: string;
20
+ readonly expectedCountry?: readonly string[];
21
+ readonly expectedASN?: readonly string[];
22
+ }[];
23
+ readonly appChecks: readonly {
24
+ readonly id: string;
25
+ readonly app: string;
26
+ readonly expectedInbound: "in-proxifier" | "in-default";
27
+ readonly expectedOutboundGroup: string;
28
+ }[];
29
+ readonly protocolChecks: readonly {
30
+ readonly id: string;
31
+ readonly target: string;
32
+ readonly expectTCPOnly?: boolean;
33
+ }[];
34
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verification-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-plan.js","sourceRoot":"","sources":["../../src/domain/verification-plan.ts"],"names":[],"mappings":""}
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import type { BuilderConfig } from "../../config/schema.js";
3
+ import type { IntentIR } from "../../domain/intent.js";
3
4
  import { type NaturalLanguagePlan } from "../natural-language/index.js";
4
5
  declare const providerSchema: z.ZodEnum<["deterministic", "auto", "claude", "exec"]>;
5
6
  export type AuthoringProvider = z.infer<typeof providerSchema>;
@@ -27,6 +28,7 @@ export interface GenerateAuthoringPlanInput {
27
28
  }
28
29
  export interface GenerateAuthoringPlanResult {
29
30
  readonly plan: NaturalLanguagePlan;
31
+ readonly intent: IntentIR;
30
32
  readonly providerRequested: AuthoringProvider;
31
33
  readonly providerUsed: Exclude<AuthoringProvider, "auto">;
32
34
  }
@@ -4,6 +4,7 @@ import { access, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { tmpdir } from "node:os";
5
5
  import path from "node:path";
6
6
  import { z } from "zod";
7
+ import { intentFromNaturalLanguagePlan } from "../intent/index.js";
7
8
  import { generateRulesFromPrompt, } from "../natural-language/index.js";
8
9
  import { mergeRuleTemplates } from "../rule-templates/index.js";
9
10
  const providerSchema = z.enum(["deterministic", "auto", "claude", "exec"]);
@@ -90,27 +91,33 @@ export async function generateAuthoringPlan(input) {
90
91
  const timeoutMs = input.timeoutMs ?? input.config?.authoring.timeoutMs ?? defaultTimeoutMs;
91
92
  const runner = input.runner ?? runAuthoringCommand;
92
93
  if (providerRequested === "deterministic") {
94
+ const plan = generateRulesFromPrompt(input.prompt);
93
95
  return {
94
96
  providerRequested,
95
97
  providerUsed: "deterministic",
96
- plan: generateRulesFromPrompt(input.prompt),
98
+ plan,
99
+ intent: intentFromNaturalLanguagePlan(plan),
97
100
  };
98
101
  }
99
102
  if (providerRequested === "claude") {
103
+ const plan = await generateWithClaude(input.prompt, input.config, timeoutMs, runner);
100
104
  return {
101
105
  providerRequested,
102
106
  providerUsed: "claude",
103
- plan: await generateWithClaude(input.prompt, input.config, timeoutMs, runner),
107
+ plan,
108
+ intent: intentFromNaturalLanguagePlan(plan),
104
109
  };
105
110
  }
106
111
  if (providerRequested === "exec") {
112
+ const plan = await generateWithExec(input.prompt, input.config, {
113
+ command: input.execCommand ?? input.config?.authoring.exec?.command,
114
+ args: input.execArgs ?? input.config?.authoring.exec?.args,
115
+ }, timeoutMs, runner);
107
116
  return {
108
117
  providerRequested,
109
118
  providerUsed: "exec",
110
- plan: await generateWithExec(input.prompt, input.config, {
111
- command: input.execCommand ?? input.config?.authoring.exec?.command,
112
- args: input.execArgs ?? input.config?.authoring.exec?.args,
113
- }, timeoutMs, runner),
119
+ plan,
120
+ intent: intentFromNaturalLanguagePlan(plan),
114
121
  };
115
122
  }
116
123
  return generateWithAuto(input.prompt, input.config, input.execCommand, input.execArgs, timeoutMs, runner);
@@ -156,13 +163,15 @@ export async function detectLocalAiClis() {
156
163
  async function generateWithAuto(prompt, config, execCommand, execArgs, timeoutMs, runner) {
157
164
  if (execCommand || config?.authoring.exec?.command) {
158
165
  try {
166
+ const plan = await generateWithExec(prompt, config, {
167
+ command: execCommand ?? config?.authoring.exec?.command,
168
+ args: execArgs ?? config?.authoring.exec?.args,
169
+ }, timeoutMs, runner);
159
170
  return {
160
171
  providerRequested: "auto",
161
172
  providerUsed: "exec",
162
- plan: await generateWithExec(prompt, config, {
163
- command: execCommand ?? config?.authoring.exec?.command,
164
- args: execArgs ?? config?.authoring.exec?.args,
165
- }, timeoutMs, runner),
173
+ plan,
174
+ intent: intentFromNaturalLanguagePlan(plan),
166
175
  };
167
176
  }
168
177
  catch (error) {
@@ -172,22 +181,26 @@ async function generateWithAuto(prompt, config, execCommand, execArgs, timeoutMs
172
181
  const claudePath = await resolveExecutable("claude");
173
182
  if (claudePath) {
174
183
  try {
184
+ const plan = await generateWithClaude(prompt, config, timeoutMs, runner, claudePath);
175
185
  return {
176
186
  providerRequested: "auto",
177
187
  providerUsed: "claude",
178
- plan: await generateWithClaude(prompt, config, timeoutMs, runner, claudePath),
188
+ plan,
189
+ intent: intentFromNaturalLanguagePlan(plan),
179
190
  };
180
191
  }
181
192
  catch (error) {
182
193
  return fallbackDeterministic(prompt, "claude", error instanceof Error ? error.message : String(error));
183
194
  }
184
195
  }
196
+ const plan = appendNotes(generateRulesFromPrompt(prompt), [
197
+ "Auto authoring fell back to the built-in deterministic parser because no supported local AI CLI was available.",
198
+ ]);
185
199
  return {
186
200
  providerRequested: "auto",
187
201
  providerUsed: "deterministic",
188
- plan: appendNotes(generateRulesFromPrompt(prompt), [
189
- "Auto authoring fell back to the built-in deterministic parser because no supported local AI CLI was available.",
190
- ]),
202
+ plan,
203
+ intent: intentFromNaturalLanguagePlan(plan),
191
204
  };
192
205
  }
193
206
  async function generateWithClaude(prompt, config, timeoutMs, runner, explicitCommand) {
@@ -414,12 +427,14 @@ function buildPortableExecPrompt(config, prompt) {
414
427
  ].join("\n");
415
428
  }
416
429
  function fallbackDeterministic(prompt, providerUsed, reason) {
430
+ const plan = appendNotes(generateRulesFromPrompt(prompt), [
431
+ `Auto authoring fell back from ${providerUsed} to the deterministic parser: ${reason}`,
432
+ ]);
417
433
  return {
418
434
  providerRequested: "auto",
419
435
  providerUsed: "deterministic",
420
- plan: appendNotes(generateRulesFromPrompt(prompt), [
421
- `Auto authoring fell back from ${providerUsed} to the deterministic parser: ${reason}`,
422
- ]),
436
+ plan,
437
+ intent: intentFromNaturalLanguagePlan(plan),
423
438
  };
424
439
  }
425
440
  function appendNotes(plan, extraNotes) {