@indigoai-us/hq-cloud 5.22.0 → 5.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/bin/sync-runner.d.ts +20 -0
  2. package/dist/bin/sync-runner.d.ts.map +1 -1
  3. package/dist/bin/sync-runner.js +18 -0
  4. package/dist/bin/sync-runner.js.map +1 -1
  5. package/dist/bin/sync-runner.test.js +46 -2
  6. package/dist/bin/sync-runner.test.js.map +1 -1
  7. package/dist/cli/share.d.ts +77 -20
  8. package/dist/cli/share.d.ts.map +1 -1
  9. package/dist/cli/share.js +278 -61
  10. package/dist/cli/share.js.map +1 -1
  11. package/dist/cli/share.test.js +484 -3
  12. package/dist/cli/share.test.js.map +1 -1
  13. package/dist/cli/sync.d.ts +27 -0
  14. package/dist/cli/sync.d.ts.map +1 -1
  15. package/dist/cli/sync.js.map +1 -1
  16. package/dist/index.d.ts +9 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +9 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/journal.d.ts +76 -1
  21. package/dist/journal.d.ts.map +1 -1
  22. package/dist/journal.js +148 -1
  23. package/dist/journal.js.map +1 -1
  24. package/dist/journal.test.js +251 -5
  25. package/dist/journal.test.js.map +1 -1
  26. package/dist/prefix-coalesce.d.ts +38 -0
  27. package/dist/prefix-coalesce.d.ts.map +1 -0
  28. package/dist/prefix-coalesce.js +69 -0
  29. package/dist/prefix-coalesce.js.map +1 -0
  30. package/dist/prefix-coalesce.test.d.ts +2 -0
  31. package/dist/prefix-coalesce.test.d.ts.map +1 -0
  32. package/dist/prefix-coalesce.test.js +77 -0
  33. package/dist/prefix-coalesce.test.js.map +1 -0
  34. package/dist/public-surface.test.d.ts +15 -0
  35. package/dist/public-surface.test.d.ts.map +1 -0
  36. package/dist/public-surface.test.js +105 -0
  37. package/dist/public-surface.test.js.map +1 -0
  38. package/dist/remote-pull.d.ts +145 -1
  39. package/dist/remote-pull.d.ts.map +1 -1
  40. package/dist/remote-pull.js +258 -1
  41. package/dist/remote-pull.js.map +1 -1
  42. package/dist/remote-pull.test.js +470 -2
  43. package/dist/remote-pull.test.js.map +1 -1
  44. package/dist/scope-shrink.d.ts +109 -0
  45. package/dist/scope-shrink.d.ts.map +1 -0
  46. package/dist/scope-shrink.js +196 -0
  47. package/dist/scope-shrink.js.map +1 -0
  48. package/dist/scope-shrink.test.d.ts +13 -0
  49. package/dist/scope-shrink.test.d.ts.map +1 -0
  50. package/dist/scope-shrink.test.js +342 -0
  51. package/dist/scope-shrink.test.js.map +1 -0
  52. package/dist/types.d.ts +48 -1
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/vault-client.d.ts +178 -0
  55. package/dist/vault-client.d.ts.map +1 -1
  56. package/dist/vault-client.js +73 -0
  57. package/dist/vault-client.js.map +1 -1
  58. package/dist/vault-client.test.js +226 -0
  59. package/dist/vault-client.test.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/bin/sync-runner.test.ts +56 -2
  62. package/src/bin/sync-runner.ts +39 -0
  63. package/src/cli/share.test.ts +577 -3
  64. package/src/cli/share.ts +395 -85
  65. package/src/cli/sync.ts +28 -0
  66. package/src/index.ts +67 -0
  67. package/src/journal.test.ts +284 -5
  68. package/src/journal.ts +167 -2
  69. package/src/prefix-coalesce.test.ts +95 -0
  70. package/src/prefix-coalesce.ts +72 -0
  71. package/src/public-surface.test.ts +112 -0
  72. package/src/remote-pull.test.ts +540 -3
  73. package/src/remote-pull.ts +419 -2
  74. package/src/scope-shrink.test.ts +402 -0
  75. package/src/scope-shrink.ts +264 -0
  76. package/src/types.ts +49 -1
  77. package/src/vault-client.test.ts +335 -0
  78. package/src/vault-client.ts +223 -0
package/dist/journal.js CHANGED
@@ -16,6 +16,10 @@ import * as fs from "fs";
16
16
  import * as os from "os";
17
17
  import * as path from "path";
18
18
  import * as crypto from "crypto";
19
+ /** Tombstone retention. 30 days in milliseconds — roughly two release cycles. */
20
+ export const TOMBSTONE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
21
+ /** Current journal schema version written by all v2-aware writers. */
22
+ export const JOURNAL_VERSION_CURRENT = "2";
19
23
  const JOURNAL_FILE_PREFIX = "sync-journal.";
20
24
  const JOURNAL_FILE_SUFFIX = ".json";
21
25
  /**
@@ -44,15 +48,53 @@ function sanitizeSlug(slug) {
44
48
  export function getJournalPath(slug) {
45
49
  return path.join(getStateDir(), `${JOURNAL_FILE_PREFIX}${sanitizeSlug(slug)}${JOURNAL_FILE_SUFFIX}`);
46
50
  }
51
+ /**
52
+ * Read a per-company journal from disk.
53
+ *
54
+ * Back-compat (US-005, v1 → v2): a v1 file on disk is returned as-is with
55
+ * `version: "1"` and no `pulls` field. The in-place migration to v2 happens
56
+ * the first time `writeJournal` runs — `migrateToV2` ensures any journal
57
+ * passed to the writer carries `version: "2"`, `pulls: []`, and the rest of
58
+ * the v2 shape. This keeps `readJournal` deterministic + cheap and confines
59
+ * the side effect (schema bump on disk) to writes.
60
+ *
61
+ * When the file doesn't exist, we return a fresh v2 journal directly — new
62
+ * installs never pass through v1 on disk.
63
+ */
47
64
  export function readJournal(slug) {
48
65
  const journalPath = getJournalPath(slug);
49
66
  if (fs.existsSync(journalPath)) {
50
67
  const content = fs.readFileSync(journalPath, "utf-8");
51
68
  return JSON.parse(content);
52
69
  }
53
- return { version: "1", lastSync: "", files: {} };
70
+ return { version: JOURNAL_VERSION_CURRENT, lastSync: "", files: {}, pulls: [] };
71
+ }
72
+ /**
73
+ * Coerce any-version journal into a v2 shape. Idempotent for v2 inputs.
74
+ * Mutates the input and returns it for chainable use. Call this immediately
75
+ * after `readJournal` if your code-path needs the v2 fields.
76
+ *
77
+ * v1 → v2 contract: every existing `files[]` entry is preserved as-is; no
78
+ * tombstone fields are inserted (legacy entries are NOT scope-shrink
79
+ * tombstones). `pulls` becomes `[]` (empty history → treat last scope as
80
+ * "all" in the scope-shrink algorithm).
81
+ */
82
+ export function migrateToV2(journal) {
83
+ if (journal.version === "2" && Array.isArray(journal.pulls)) {
84
+ return journal;
85
+ }
86
+ journal.version = JOURNAL_VERSION_CURRENT;
87
+ if (!Array.isArray(journal.pulls))
88
+ journal.pulls = [];
89
+ return journal;
54
90
  }
91
+ /**
92
+ * Write a journal to disk, migrating to the current schema version in-place.
93
+ * `migrateToV2` mutates the passed-in object — callers that hold a reference
94
+ * after the write will see the v2 shape.
95
+ */
55
96
  export function writeJournal(slug, journal) {
97
+ migrateToV2(journal);
56
98
  const journalPath = getJournalPath(slug);
57
99
  fs.mkdirSync(path.dirname(journalPath), { recursive: true });
58
100
  fs.writeFileSync(journalPath, JSON.stringify(journal, null, 2));
@@ -121,4 +163,109 @@ export function getEntry(journal, relativePath) {
121
163
  export function removeEntry(journal, relativePath) {
122
164
  delete journal.files[relativePath];
123
165
  }
166
+ // ─── Journal v2 (US-005): pulls, tombstones, GC ─────────────────────────────
167
+ /** Crockford base32 alphabet (ULID-compatible). */
168
+ const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
169
+ /**
170
+ * Generate a ULID-shaped 26-char identifier without adding a runtime dep.
171
+ * Format: 10-char base32 of the current millisecond timestamp + 16-char
172
+ * base32 of random bytes. Lexically sortable, time-prefixed — same property
173
+ * that makes ULIDs useful for `pulls[]` ordering.
174
+ *
175
+ * We don't need full ULID spec compliance (monotonic counter, randomness
176
+ * spec) — just sortable + collision-resistant enough that two pulls
177
+ * issued in the same millisecond by different processes don't clash.
178
+ * 80 bits of randomness is plenty.
179
+ */
180
+ export function generatePullId(now = Date.now()) {
181
+ let time = now;
182
+ const timeChars = [];
183
+ for (let i = 0; i < 10; i++) {
184
+ timeChars.unshift(CROCKFORD[time % 32]);
185
+ time = Math.floor(time / 32);
186
+ }
187
+ const randBytes = crypto.randomBytes(10); // 80 bits
188
+ const randChars = [];
189
+ // Encode 10 random bytes (80 bits) into 16 base32 chars.
190
+ let buf = 0;
191
+ let bits = 0;
192
+ for (let i = 0; i < randBytes.length; i++) {
193
+ buf = (buf << 8) | randBytes[i];
194
+ bits += 8;
195
+ while (bits >= 5) {
196
+ bits -= 5;
197
+ randChars.push(CROCKFORD[(buf >> bits) & 0x1f]);
198
+ }
199
+ }
200
+ if (bits > 0) {
201
+ randChars.push(CROCKFORD[(buf << (5 - bits)) & 0x1f]);
202
+ }
203
+ return timeChars.join("") + randChars.slice(0, 16).join("");
204
+ }
205
+ /**
206
+ * Find the most-recent `PullRecord` for a company in the journal. Returns
207
+ * `undefined` when no record exists — scope-shrink callers treat that as
208
+ * "no prior scope; nothing to shrink".
209
+ *
210
+ * Order by `completedAt` descending — `pullId` is lexically sortable but
211
+ * `completedAt` is what semantically represents "most recent successful
212
+ * pull state at last close".
213
+ */
214
+ export function lastPullRecord(journal, companyUid) {
215
+ if (!journal.pulls || journal.pulls.length === 0)
216
+ return undefined;
217
+ let best;
218
+ for (const p of journal.pulls) {
219
+ if (p.companyUid !== companyUid)
220
+ continue;
221
+ if (!best || p.completedAt > best.completedAt)
222
+ best = p;
223
+ }
224
+ return best;
225
+ }
226
+ /** Append a `PullRecord` (mutates `journal.pulls`). */
227
+ export function appendPullRecord(journal, record) {
228
+ migrateToV2(journal);
229
+ journal.pulls.push(record);
230
+ }
231
+ /**
232
+ * Write a journal tombstone entry for `relativePath`. Used by the scope-
233
+ * shrink algorithm (US-005) and by `hq sync narrow --apply` (US-007).
234
+ *
235
+ * Tombstones intentionally keep the old `hash` / `size` / `syncedAt` /
236
+ * `direction` so a recovery flow could see what was there before pruning.
237
+ * They are GC'd after `TOMBSTONE_TTL_MS` via `gcTombstones`.
238
+ */
239
+ export function tombstoneEntry(journal, relativePath, reason, now = new Date().toISOString()) {
240
+ const entry = journal.files[relativePath];
241
+ if (!entry)
242
+ return;
243
+ entry.removedAt = now;
244
+ entry.removedReason = reason;
245
+ }
246
+ /** True if the entry is a tombstone (set by `tombstoneEntry`). */
247
+ export function isTombstone(entry) {
248
+ return !!entry && typeof entry.removedAt === "string";
249
+ }
250
+ /**
251
+ * Garbage-collect tombstones older than `TOMBSTONE_TTL_MS` from
252
+ * `journal.files`. Returns the number removed. Cheap — single pass over
253
+ * the files map, no I/O. Safe to call at the start AND end of every
254
+ * `pullAll` per-company leg; both runs are idempotent.
255
+ */
256
+ export function gcTombstones(journal, now = Date.now()) {
257
+ let removed = 0;
258
+ for (const [path, entry] of Object.entries(journal.files)) {
259
+ if (!entry.removedAt)
260
+ continue;
261
+ const removedTime = Date.parse(entry.removedAt);
262
+ if (Number.isNaN(removedTime))
263
+ continue;
264
+ if (now - removedTime > TOMBSTONE_TTL_MS) {
265
+ delete journal.files[path];
266
+ removed++;
267
+ }
268
+ }
269
+ return removed;
270
+ }
124
271
  //# sourceMappingURL=journal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"journal.js","sourceRoot":"","sources":["../src/journal.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ import { describe, it, expect, beforeEach, afterEach } from "vitest";
9
9
  import * as fs from "fs";
10
10
  import * as os from "os";
11
11
  import * as path from "path";
12
- import { getJournalPath, getStateDir, readJournal, writeJournal, updateEntry, } from "./journal.js";
12
+ import { getJournalPath, getStateDir, readJournal, writeJournal, updateEntry, migrateToV2, appendPullRecord, lastPullRecord, tombstoneEntry, isTombstone, gcTombstones, generatePullId, TOMBSTONE_TTL_MS, } from "./journal.js";
13
13
  describe("journal", () => {
14
14
  let stateDir;
15
15
  beforeEach(() => {
@@ -48,13 +48,16 @@ describe("journal", () => {
48
48
  });
49
49
  });
50
50
  describe("readJournal", () => {
51
- it("returns an empty journal when the file doesn't exist", () => {
51
+ it("returns an empty v2 journal when the file doesn't exist", () => {
52
52
  const j = readJournal("indigo");
53
- expect(j.version).toBe("1");
53
+ expect(j.version).toBe("2");
54
54
  expect(j.files).toEqual({});
55
55
  expect(j.lastSync).toBe("");
56
+ expect(j.pulls).toEqual([]);
56
57
  });
57
- it("reads a journal written with writeJournal", () => {
58
+ it("reads a journal written with writeJournal (round-trips through v2 migration)", () => {
59
+ // writeJournal upgrades the schema in-place to v2, so the read side
60
+ // sees v2 even if the caller handed a v1 shape.
58
61
  const original = {
59
62
  version: "1",
60
63
  lastSync: "2026-04-19T00:00:00.000Z",
@@ -69,7 +72,10 @@ describe("journal", () => {
69
72
  };
70
73
  writeJournal("indigo", original);
71
74
  const roundTripped = readJournal("indigo");
72
- expect(roundTripped).toEqual(original);
75
+ expect(roundTripped.version).toBe("2");
76
+ expect(roundTripped.lastSync).toBe("2026-04-19T00:00:00.000Z");
77
+ expect(roundTripped.files).toEqual(original.files);
78
+ expect(roundTripped.pulls).toEqual([]);
73
79
  });
74
80
  });
75
81
  describe("writeJournal", () => {
@@ -110,5 +116,245 @@ describe("journal", () => {
110
116
  expect(j.files["foo.md"]?.syncedAt).not.toBe("");
111
117
  });
112
118
  });
119
+ // ── Journal v2 (US-005): pulls, tombstones, GC, migration ─────────────────
120
+ describe("migrateToV2", () => {
121
+ it("upgrades a v1 journal in place", () => {
122
+ const j = { version: "1", lastSync: "", files: {} };
123
+ migrateToV2(j);
124
+ expect(j.version).toBe("2");
125
+ expect(j.pulls).toEqual([]);
126
+ });
127
+ it("is idempotent on a v2 journal", () => {
128
+ const j = {
129
+ version: "2",
130
+ lastSync: "",
131
+ files: {},
132
+ pulls: [],
133
+ };
134
+ const before = JSON.stringify(j);
135
+ migrateToV2(j);
136
+ expect(JSON.stringify(j)).toBe(before);
137
+ });
138
+ it("preserves all files when migrating v1 → v2", () => {
139
+ const j = {
140
+ version: "1",
141
+ lastSync: "2026-05-01",
142
+ files: {
143
+ "a.md": {
144
+ hash: "h",
145
+ size: 1,
146
+ syncedAt: "2026-05-01",
147
+ direction: "down",
148
+ },
149
+ },
150
+ };
151
+ migrateToV2(j);
152
+ expect(j.files["a.md"]).toBeDefined();
153
+ expect(j.files["a.md"]?.removedAt).toBeUndefined(); // not a tombstone
154
+ });
155
+ it("writeJournal upgrades v1 → v2 on disk", () => {
156
+ writeJournal("indigo", { version: "1", lastSync: "", files: {} });
157
+ const raw = JSON.parse(fs.readFileSync(getJournalPath("indigo"), "utf-8"));
158
+ expect(raw.version).toBe("2");
159
+ expect(raw.pulls).toEqual([]);
160
+ });
161
+ });
162
+ describe("generatePullId", () => {
163
+ it("produces a 26-char identifier", () => {
164
+ expect(generatePullId()).toHaveLength(26);
165
+ });
166
+ it("is time-prefixed and lexically sortable", () => {
167
+ const t0 = Date.parse("2026-01-01T00:00:00.000Z");
168
+ const t1 = Date.parse("2026-06-01T00:00:00.000Z");
169
+ const id0 = generatePullId(t0);
170
+ const id1 = generatePullId(t1);
171
+ expect(id0 < id1).toBe(true);
172
+ });
173
+ it("uses crockford base32 alphabet (no I, L, O, U)", () => {
174
+ const id = generatePullId();
175
+ expect(id).toMatch(/^[0-9A-HJKMNP-TV-Z]+$/);
176
+ });
177
+ });
178
+ describe("appendPullRecord + lastPullRecord", () => {
179
+ function pull(partial) {
180
+ return {
181
+ pullId: generatePullId(),
182
+ companyUid: "cmp_indigo",
183
+ startedAt: "2026-05-20T00:00:00.000Z",
184
+ completedAt: "2026-05-20T00:00:05.000Z",
185
+ syncMode: "all",
186
+ prefixSet: [],
187
+ scopeChangeDetected: false,
188
+ orphansRemoved: 0,
189
+ orphansBlocked: 0,
190
+ ...partial,
191
+ };
192
+ }
193
+ it("appends to pulls[] (auto-migrates v1)", () => {
194
+ const j = { version: "1", lastSync: "", files: {} };
195
+ appendPullRecord(j, pull({}));
196
+ expect(j.version).toBe("2");
197
+ expect(j.pulls).toHaveLength(1);
198
+ });
199
+ it("lastPullRecord returns undefined when no records exist", () => {
200
+ const j = {
201
+ version: "2",
202
+ lastSync: "",
203
+ files: {},
204
+ pulls: [],
205
+ };
206
+ expect(lastPullRecord(j, "cmp_indigo")).toBeUndefined();
207
+ });
208
+ it("lastPullRecord returns the most-recent by completedAt", () => {
209
+ const j = {
210
+ version: "2",
211
+ lastSync: "",
212
+ files: {},
213
+ pulls: [
214
+ pull({ completedAt: "2026-05-19T00:00:00.000Z", syncMode: "all" }),
215
+ pull({ completedAt: "2026-05-20T00:00:00.000Z", syncMode: "shared" }),
216
+ pull({ completedAt: "2026-05-18T00:00:00.000Z", syncMode: "all" }),
217
+ ],
218
+ };
219
+ expect(lastPullRecord(j, "cmp_indigo")?.syncMode).toBe("shared");
220
+ });
221
+ it("lastPullRecord filters by companyUid", () => {
222
+ const j = {
223
+ version: "2",
224
+ lastSync: "",
225
+ files: {},
226
+ pulls: [
227
+ pull({ companyUid: "cmp_a", completedAt: "2026-05-20T00:00:00.000Z" }),
228
+ pull({ companyUid: "cmp_b", completedAt: "2026-05-21T00:00:00.000Z" }),
229
+ ],
230
+ };
231
+ expect(lastPullRecord(j, "cmp_a")?.completedAt).toBe("2026-05-20T00:00:00.000Z");
232
+ });
233
+ });
234
+ describe("tombstoneEntry + isTombstone", () => {
235
+ it("marks an entry with removedAt + removedReason", () => {
236
+ const j = {
237
+ version: "2",
238
+ lastSync: "",
239
+ files: {
240
+ "a.md": {
241
+ hash: "h",
242
+ size: 1,
243
+ syncedAt: "2026-05-01T00:00:00.000Z",
244
+ direction: "down",
245
+ },
246
+ },
247
+ pulls: [],
248
+ };
249
+ tombstoneEntry(j, "a.md", "scope_shrink", "2026-05-20T00:00:00.000Z");
250
+ expect(j.files["a.md"]?.removedAt).toBe("2026-05-20T00:00:00.000Z");
251
+ expect(j.files["a.md"]?.removedReason).toBe("scope_shrink");
252
+ expect(isTombstone(j.files["a.md"])).toBe(true);
253
+ });
254
+ it("is a no-op for missing entries", () => {
255
+ const j = {
256
+ version: "2",
257
+ lastSync: "",
258
+ files: {},
259
+ pulls: [],
260
+ };
261
+ expect(() => tombstoneEntry(j, "missing.md", "scope_shrink")).not.toThrow();
262
+ });
263
+ it("preserves the original hash/size/syncedAt (forensic trail)", () => {
264
+ const j = {
265
+ version: "2",
266
+ lastSync: "",
267
+ files: {
268
+ "a.md": {
269
+ hash: "old-hash",
270
+ size: 42,
271
+ syncedAt: "2026-05-01T00:00:00.000Z",
272
+ direction: "down",
273
+ },
274
+ },
275
+ pulls: [],
276
+ };
277
+ tombstoneEntry(j, "a.md", "scope_shrink");
278
+ expect(j.files["a.md"]?.hash).toBe("old-hash");
279
+ expect(j.files["a.md"]?.size).toBe(42);
280
+ });
281
+ });
282
+ describe("gcTombstones", () => {
283
+ it("removes tombstones older than TOMBSTONE_TTL_MS", () => {
284
+ const now = Date.parse("2026-06-01T00:00:00.000Z");
285
+ const old = new Date(now - TOMBSTONE_TTL_MS - 1000).toISOString();
286
+ const fresh = new Date(now - 1000).toISOString();
287
+ const j = {
288
+ version: "2",
289
+ lastSync: "",
290
+ files: {
291
+ "old-tombstone.md": {
292
+ hash: "h",
293
+ size: 1,
294
+ syncedAt: "2026-04-01T00:00:00.000Z",
295
+ direction: "down",
296
+ removedAt: old,
297
+ removedReason: "scope_shrink",
298
+ },
299
+ "fresh-tombstone.md": {
300
+ hash: "h",
301
+ size: 1,
302
+ syncedAt: "2026-05-01T00:00:00.000Z",
303
+ direction: "down",
304
+ removedAt: fresh,
305
+ removedReason: "scope_shrink",
306
+ },
307
+ "live.md": {
308
+ hash: "h",
309
+ size: 1,
310
+ syncedAt: "2026-05-01T00:00:00.000Z",
311
+ direction: "down",
312
+ },
313
+ },
314
+ pulls: [],
315
+ };
316
+ const removed = gcTombstones(j, now);
317
+ expect(removed).toBe(1);
318
+ expect(j.files["old-tombstone.md"]).toBeUndefined();
319
+ expect(j.files["fresh-tombstone.md"]).toBeDefined();
320
+ expect(j.files["live.md"]).toBeDefined();
321
+ });
322
+ it("never removes non-tombstone entries", () => {
323
+ const j = {
324
+ version: "2",
325
+ lastSync: "",
326
+ files: {
327
+ "live.md": {
328
+ hash: "h",
329
+ size: 1,
330
+ syncedAt: "1970-01-01T00:00:00.000Z",
331
+ direction: "down",
332
+ },
333
+ },
334
+ pulls: [],
335
+ };
336
+ expect(gcTombstones(j, Date.now())).toBe(0);
337
+ expect(j.files["live.md"]).toBeDefined();
338
+ });
339
+ it("ignores tombstones with un-parseable removedAt", () => {
340
+ const j = {
341
+ version: "2",
342
+ lastSync: "",
343
+ files: {
344
+ "bogus.md": {
345
+ hash: "h",
346
+ size: 1,
347
+ syncedAt: "",
348
+ direction: "down",
349
+ removedAt: "not-a-date",
350
+ removedReason: "scope_shrink",
351
+ },
352
+ },
353
+ pulls: [],
354
+ };
355
+ expect(gcTombstones(j, Date.now())).toBe(0);
356
+ expect(j.files["bogus.md"]).toBeDefined();
357
+ });
358
+ });
113
359
  });
114
360
  //# sourceMappingURL=journal.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"journal.test.js","sourceRoot":"","sources":["../src/journal.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"journal.test.js","sourceRoot":"","sources":["../src/journal.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Pure helper: coalesce a set of S3 key prefixes into the minimal set that
3
+ * covers the same paths with no redundancy.
4
+ *
5
+ * Why it lives in hq-cloud (not the SDK): the engine — both the sync path
6
+ * (US-005) and the explicit `hq sync narrow` ritual (US-007) — is the only
7
+ * thing that needs to fan ListObjectsV2 calls out across a coalesced grant
8
+ * graph. The vault-service API returns raw `ExplicitGrant[]` rows; consumer
9
+ * code is responsible for deduping nested/overlapping prefixes before
10
+ * issuing STS vends.
11
+ *
12
+ * Contract (cover the corner cases the unit tests pin):
13
+ * - **Nested:** `["a/", "a/b/"]` → `["a/"]` (broader covers narrower).
14
+ * - **Overlapping (siblings):** `["a/b/", "a/c/"]` → both kept.
15
+ * - **Identical:** `["a/", "a/"]` → `["a/"]` (dedup).
16
+ * - **Case-sensitive:** `["A/", "a/"]` → both kept (S3 keys are case-sensitive).
17
+ * - **Empty input:** `[]` → `[]`.
18
+ * - **Empty string entry:** dropped (an empty prefix covers everything and is
19
+ * never a valid grant; if a caller wants "broad list" they should pass
20
+ * `companies/{co}/`, not "").
21
+ * - **Determinism:** output is sorted lexicographically so the journal's
22
+ * `prefixSet` stays diff-stable across runs.
23
+ *
24
+ * Coverage rule: `a` covers `b` iff `a === b` OR `b.startsWith(a)`. This is a
25
+ * literal string-prefix relation — it does NOT understand S3 "folders". A
26
+ * caller that wants `a/` to NOT cover `ab/` must pass trailing-slash-bounded
27
+ * prefixes (the grants endpoint already does — every ACL row ends in `/`).
28
+ */
29
+ export declare function coalescePrefixes(prefixes: readonly string[]): string[];
30
+ /**
31
+ * Predicate companion: does any prefix in `prefixSet` cover `path`?
32
+ *
33
+ * Used by the journal scope-shrink algorithm to test whether a journaled
34
+ * file is still in scope under the current pull's `prefixSet`. Same
35
+ * `startsWith` semantics as `coalescePrefixes`.
36
+ */
37
+ export declare function isCoveredByAny(path: string, prefixSet: readonly string[]): boolean;
38
+ //# sourceMappingURL=prefix-coalesce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix-coalesce.d.ts","sourceRoot":"","sources":["../src/prefix-coalesce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAyBtE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,OAAO,CAKT"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Pure helper: coalesce a set of S3 key prefixes into the minimal set that
3
+ * covers the same paths with no redundancy.
4
+ *
5
+ * Why it lives in hq-cloud (not the SDK): the engine — both the sync path
6
+ * (US-005) and the explicit `hq sync narrow` ritual (US-007) — is the only
7
+ * thing that needs to fan ListObjectsV2 calls out across a coalesced grant
8
+ * graph. The vault-service API returns raw `ExplicitGrant[]` rows; consumer
9
+ * code is responsible for deduping nested/overlapping prefixes before
10
+ * issuing STS vends.
11
+ *
12
+ * Contract (cover the corner cases the unit tests pin):
13
+ * - **Nested:** `["a/", "a/b/"]` → `["a/"]` (broader covers narrower).
14
+ * - **Overlapping (siblings):** `["a/b/", "a/c/"]` → both kept.
15
+ * - **Identical:** `["a/", "a/"]` → `["a/"]` (dedup).
16
+ * - **Case-sensitive:** `["A/", "a/"]` → both kept (S3 keys are case-sensitive).
17
+ * - **Empty input:** `[]` → `[]`.
18
+ * - **Empty string entry:** dropped (an empty prefix covers everything and is
19
+ * never a valid grant; if a caller wants "broad list" they should pass
20
+ * `companies/{co}/`, not "").
21
+ * - **Determinism:** output is sorted lexicographically so the journal's
22
+ * `prefixSet` stays diff-stable across runs.
23
+ *
24
+ * Coverage rule: `a` covers `b` iff `a === b` OR `b.startsWith(a)`. This is a
25
+ * literal string-prefix relation — it does NOT understand S3 "folders". A
26
+ * caller that wants `a/` to NOT cover `ab/` must pass trailing-slash-bounded
27
+ * prefixes (the grants endpoint already does — every ACL row ends in `/`).
28
+ */
29
+ export function coalescePrefixes(prefixes) {
30
+ // Dedup + drop empties.
31
+ const unique = new Set();
32
+ for (const p of prefixes) {
33
+ if (typeof p === "string" && p !== "") {
34
+ unique.add(p);
35
+ }
36
+ }
37
+ if (unique.size === 0)
38
+ return [];
39
+ // Sort lexicographically so a broader prefix (`a/`) appears before its
40
+ // narrower descendants (`a/b/`). Then a single pass keeps the broadest in
41
+ // each cover chain.
42
+ const sorted = [...unique].sort();
43
+ const result = [];
44
+ let lastKept = null;
45
+ for (const p of sorted) {
46
+ if (lastKept !== null && p.startsWith(lastKept)) {
47
+ // `lastKept` already covers `p`; skip.
48
+ continue;
49
+ }
50
+ result.push(p);
51
+ lastKept = p;
52
+ }
53
+ return result;
54
+ }
55
+ /**
56
+ * Predicate companion: does any prefix in `prefixSet` cover `path`?
57
+ *
58
+ * Used by the journal scope-shrink algorithm to test whether a journaled
59
+ * file is still in scope under the current pull's `prefixSet`. Same
60
+ * `startsWith` semantics as `coalescePrefixes`.
61
+ */
62
+ export function isCoveredByAny(path, prefixSet) {
63
+ for (const p of prefixSet) {
64
+ if (p === "" || path.startsWith(p))
65
+ return true;
66
+ }
67
+ return false;
68
+ }
69
+ //# sourceMappingURL=prefix-coalesce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix-coalesce.js","sourceRoot":"","sources":["../src/prefix-coalesce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,UAAU,gBAAgB,CAAC,QAA2B;IAC1D,wBAAwB;IACxB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,uEAAuE;IACvE,0EAA0E;IAC1E,oBAAoB;IACpB,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,uCAAuC;YACvC,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,SAA4B;IAE5B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prefix-coalesce.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix-coalesce.test.d.ts","sourceRoot":"","sources":["../src/prefix-coalesce.test.ts"],"names":[],"mappings":""}