@indigoai-us/hq-cloud 6.15.2 → 6.15.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.
Files changed (64) hide show
  1. package/dist/bin/sync-mutation.d.ts +1 -3
  2. package/dist/bin/sync-mutation.d.ts.map +1 -1
  3. package/dist/bin/sync-mutation.js +5 -5
  4. package/dist/bin/sync-mutation.js.map +1 -1
  5. package/dist/bin/sync-mutation.test.js +36 -137
  6. package/dist/bin/sync-mutation.test.js.map +1 -1
  7. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  8. package/dist/bin/sync-runner-company.js +15 -0
  9. package/dist/bin/sync-runner-company.js.map +1 -1
  10. package/dist/bin/sync-runner-company.test.js +71 -0
  11. package/dist/bin/sync-runner-company.test.js.map +1 -1
  12. package/dist/bin/sync-runner-events.test.js +21 -0
  13. package/dist/bin/sync-runner-events.test.js.map +1 -1
  14. package/dist/bin/sync-runner.d.ts +5 -0
  15. package/dist/bin/sync-runner.d.ts.map +1 -1
  16. package/dist/bin/sync-runner.js.map +1 -1
  17. package/dist/cli/share.d.ts.map +1 -1
  18. package/dist/cli/share.js +23 -6
  19. package/dist/cli/share.js.map +1 -1
  20. package/dist/cli/share.test.js +54 -1
  21. package/dist/cli/share.test.js.map +1 -1
  22. package/dist/cli/sync.d.ts +31 -6
  23. package/dist/cli/sync.d.ts.map +1 -1
  24. package/dist/cli/sync.js +58 -38
  25. package/dist/cli/sync.js.map +1 -1
  26. package/dist/cli/sync.test.js +180 -47
  27. package/dist/cli/sync.test.js.map +1 -1
  28. package/dist/s3.d.ts +36 -0
  29. package/dist/s3.d.ts.map +1 -1
  30. package/dist/s3.js +61 -1
  31. package/dist/s3.js.map +1 -1
  32. package/dist/s3.symlink-materialize.test.js +161 -1
  33. package/dist/s3.symlink-materialize.test.js.map +1 -1
  34. package/dist/sync/base-version-resolver.d.ts +11 -0
  35. package/dist/sync/base-version-resolver.d.ts.map +1 -0
  36. package/dist/sync/base-version-resolver.js +48 -0
  37. package/dist/sync/base-version-resolver.js.map +1 -0
  38. package/dist/sync/base-version-resolver.test.d.ts +2 -0
  39. package/dist/sync/base-version-resolver.test.d.ts.map +1 -0
  40. package/dist/sync/base-version-resolver.test.js +24 -0
  41. package/dist/sync/base-version-resolver.test.js.map +1 -0
  42. package/dist/sync/lease-client.d.ts +17 -0
  43. package/dist/sync/lease-client.d.ts.map +1 -1
  44. package/dist/sync/lease-client.js +46 -1
  45. package/dist/sync/lease-client.js.map +1 -1
  46. package/dist/sync/mutation-client.d.ts +2 -0
  47. package/dist/sync/mutation-client.d.ts.map +1 -1
  48. package/dist/sync/mutation-client.js +2 -0
  49. package/dist/sync/mutation-client.js.map +1 -1
  50. package/dist/sync/mutation-session.d.ts +49 -0
  51. package/dist/sync/mutation-session.d.ts.map +1 -0
  52. package/dist/sync/mutation-session.js +282 -0
  53. package/dist/sync/mutation-session.js.map +1 -0
  54. package/dist/sync/mutation-session.test.d.ts +2 -0
  55. package/dist/sync/mutation-session.test.d.ts.map +1 -0
  56. package/dist/sync/mutation-session.test.js +190 -0
  57. package/dist/sync/mutation-session.test.js.map +1 -0
  58. package/dist/sync/uploader-finalization.d.ts +20 -0
  59. package/dist/sync/uploader-finalization.d.ts.map +1 -1
  60. package/dist/sync/uploader-finalization.js +48 -0
  61. package/dist/sync/uploader-finalization.js.map +1 -1
  62. package/dist/sync/uploader-finalization.test.js +15 -0
  63. package/dist/sync/uploader-finalization.test.js.map +1 -1
  64. package/package.json +1 -1
@@ -27,6 +27,18 @@ vi.mock("../s3.js", () => ({
27
27
  headRemoteFile: vi.fn().mockResolvedValue(null),
28
28
  primeObjectTransport: vi.fn().mockResolvedValue(undefined),
29
29
  primeUploads: vi.fn().mockResolvedValue(undefined),
30
+ // Real exports share.ts now imports for the HQ-DESKTOP-54 privilege skip.
31
+ WINDOWS_SYMLINK_PRIVILEGE_REMEDY: "Enable Windows Developer Mode (Settings > Privacy & security > For developers) or run HQ sync once from an elevated terminal, then sync again.",
32
+ WindowsSymlinkPrivilegeError: class WindowsSymlinkPrivilegeError extends Error {
33
+ target;
34
+ code;
35
+ constructor(target, code) {
36
+ super(`symlink skipped: creating a file symlink to ${target} requires a Windows privilege`);
37
+ this.name = "WindowsSymlinkPrivilegeError";
38
+ this.target = target;
39
+ this.code = code;
40
+ }
41
+ },
30
42
  }));
31
43
  // Mock readline so the interactive-conflict serialization test can observe
32
44
  // prompt lifecycle (createInterface + close) without ever touching stdin.
@@ -40,7 +52,7 @@ vi.mock("readline", () => ({
40
52
  }));
41
53
  import * as readline from "readline";
42
54
  import { share, isForbiddenCompanyVaultKey, UnreachablePushPathsError, _testing as shareTesting } from "./share.js";
43
- import { deleteRemoteFile, downloadFile, headRemoteFile, uploadFile, uploadSymlink } from "../s3.js";
55
+ import { deleteRemoteFile, downloadFile, headRemoteFile, uploadFile, uploadSymlink, WindowsSymlinkPrivilegeError } from "../s3.js";
44
56
  import { VaultAuthError } from "../vault-client.js";
45
57
  import { hashFile } from "../journal.js";
46
58
  const mockConfig = {
@@ -879,6 +891,47 @@ describe("share", () => {
879
891
  expect(result.conflictPaths).toEqual(["v7b-abort.txt"]);
880
892
  expect(result.filesUploaded).toBe(0);
881
893
  });
894
+ it("HQ-DESKTOP-54: a privilege refusal while writing the push conflict mirror is a skip, not an error", async () => {
895
+ // The keep-mirror also materializes the remote object (to a .conflict-*
896
+ // file). On an unprivileged Windows host that throws the typed privilege
897
+ // error; it must be downgraded to the deliberate skip so the push stays
898
+ // complete and the runner exits 0 — never type:error. The conflict itself
899
+ // is still recorded and the local file is untouched.
900
+ const companyRoot = path.join(tmpDir, "companies", "acme");
901
+ fs.mkdirSync(companyRoot, { recursive: true });
902
+ const testFile = path.join(companyRoot, "v7b-priv.txt");
903
+ fs.writeFileSync(testFile, "local-collision-content");
904
+ vi.mocked(headRemoteFile).mockResolvedValueOnce({
905
+ lastModified: new Date(),
906
+ etag: '"remote-version-etag"',
907
+ size: 40,
908
+ });
909
+ // On a real unprivileged host BOTH the fresh-collision reconciled probe and
910
+ // the keep-mirror materialize the remote symlink, so both downloadFile calls
911
+ // refuse. The probe's catch returns "differs" (conflict) without erroring;
912
+ // the mirror must downgrade the refusal to the deliberate skip.
913
+ vi.mocked(downloadFile)
914
+ .mockRejectedValueOnce(new WindowsSymlinkPrivilegeError("../target.md", "EPERM"))
915
+ .mockRejectedValueOnce(new WindowsSymlinkPrivilegeError("../target.md", "EPERM"));
916
+ const events = [];
917
+ const result = await share({
918
+ paths: [testFile],
919
+ company: "acme",
920
+ vaultConfig: mockConfig,
921
+ hqRoot: tmpDir,
922
+ onConflict: "keep",
923
+ onEvent: (e) => events.push(e),
924
+ });
925
+ expect(events).toContainEqual(expect.objectContaining({
926
+ type: "skip-symlink-privilege",
927
+ path: "v7b-priv.txt",
928
+ target: "../target.md",
929
+ }));
930
+ expect(events.some((e) => e.type === "error")).toBe(false);
931
+ // The conflict is still recorded; the local file is preserved.
932
+ expect(result.conflictPaths).toEqual(["v7b-priv.txt"]);
933
+ expect(fs.readFileSync(testFile, "utf-8")).toBe("local-collision-content");
934
+ });
882
935
  it("fresh-install SSE-KMS etag: byte-identical remote is reconciled without a conflict", async () => {
883
936
  const companyRoot = path.join(tmpDir, "companies", "acme");
884
937
  fs.mkdirSync(companyRoot, { recursive: true });