@indigoai-us/hq-cloud 6.14.47 → 6.14.48

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.
@@ -162,6 +162,7 @@ export declare const _testing: {
162
162
  collectFiles: typeof collectFiles;
163
163
  resolveNamedPath: typeof resolveNamedPath;
164
164
  isWithinLexicalOrReal: typeof isWithinLexicalOrReal;
165
+ defaultConsoleLogger: typeof defaultConsoleLogger;
165
166
  };
166
167
  export interface ShareOptions {
167
168
  /** Path(s) to share (files or directories) */
@@ -303,8 +304,10 @@ export interface ShareOptions {
303
304
  * belong in THIS bucket regardless of local state" and uses the same
304
305
  * DeleteObject + journal-removal path as `propagateDeletes`.
305
306
  *
306
- * Honors `propagateDeletePolicy` `"owned-only"` (default) only
307
- * decommissions journal entries with `direction === "up"`, so a
307
+ * Honors `propagateDeletePolicy`. Under `"owned-only"` (this function's
308
+ * own fallback when the caller passes nothing; every live caller passes
309
+ * `resolveDeletePolicy()`, which defaults to `"currency-gated"`) only
310
+ * journal entries with `direction === "up"` are decommissioned, so a
308
311
  * misconfigured caller never erases content pulled from elsewhere.
309
312
  *
310
313
  * Independent of `propagateDeletes`: callers can opt into decommission
@@ -516,7 +519,7 @@ export interface ShareResult {
516
519
  pathResults?: SharePathResult[];
517
520
  aborted: boolean;
518
521
  }
519
- export type ShareDeleteRefusalReason = "stale-etag" | "legacy-no-etag" | "bulk-asymmetry" | "divergent-local" | "missing-delete-intent" | "intent-changed" | "transfer-error";
522
+ export type ShareDeleteRefusalReason = "stale-etag" | "legacy-no-etag" | "bulk-asymmetry" | "divergent-local" | "missing-delete-intent" | "intent-changed" | "recreated-locally" | "transfer-error";
520
523
  export interface SharePathResult {
521
524
  path: string;
522
525
  status: "accepted" | "refused";
@@ -535,6 +538,11 @@ export declare function wrapFilterWithIgnoreVisibility(underlying: (absPath: str
535
538
  * Share local file(s) to the entity vault.
536
539
  */
537
540
  export declare function share(options: ShareOptions): Promise<ShareResult>;
541
+ /**
542
+ * Default human-readable share output. Preserves the exact format the CLI
543
+ * emitted before `onEvent` was added — tty users see no change.
544
+ */
545
+ declare function defaultConsoleLogger(event: SyncProgressEvent): void;
538
546
  /**
539
547
  * One entry produced by collectFiles/walkDir. Files describe regular
540
548
  * payloads that get hashed + size-checked + uploaded via uploadFile;
@@ -1 +1 @@
1
- {"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../../src/cli/share.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../../src/cli/share.ts"],"names":[],"mappings":"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"}
package/dist/cli/share.js CHANGED
@@ -12,7 +12,7 @@ import { createSyncProgressRecorder } from "../sync-progress.js";
12
12
  import { localPathForVaultKey, vaultKeyForLocalPath } from "../local-path-codec.js";
13
13
  import { uploadFile, uploadSymlink, toPosixKey, headRemoteFile, deleteRemoteFile, downloadFile, primeObjectTransport, primeUploads, } from "../s3.js";
14
14
  import * as crypto from "crypto";
15
- import { readJournal, writeJournal, hashFile, hashSymlinkTarget, updateEntry, removeEntry, normalizeEtag, PERSONAL_VAULT_JOURNAL_SLUG, migratePersonalVaultJournal, } from "../journal.js";
15
+ import { readJournal, writeJournal, hashFile, hashSymlinkTarget, updateEntry, removeEntry, isTombstone, normalizeEtag, PERSONAL_VAULT_JOURNAL_SLUG, migratePersonalVaultJournal, } from "../journal.js";
16
16
  import { createIgnoreFilter, hasControlCharacters, isExpectedIgnore, isWithinSizeLimit, } from "../ignore.js";
17
17
  import { wrapFilterWithPersonalVaultDefaults, } from "../personal-vault-exclusions.js";
18
18
  import { isGeneratedCoreMirrorKey, isPersonalVaultDeletionExcluded, } from "../personal-vault.js";
@@ -235,6 +235,7 @@ export const _testing = {
235
235
  collectFiles,
236
236
  resolveNamedPath,
237
237
  isWithinLexicalOrReal,
238
+ defaultConsoleLogger,
238
239
  };
239
240
  /**
240
241
  * Pure Stage-1 pass for push: walk the candidate file list, hash each one,
@@ -489,7 +490,7 @@ export async function share(options) {
489
490
  const REFUSED_STALE_PATH_CAP = 50;
490
491
  async function createPushRunContext(options) {
491
492
  const { paths, company, message, onConflict, vaultConfig, entityContext, hqRoot, skipUnchanged, propagateDeletes } = options;
492
- let propagateDeletePolicy = options.propagateDeletePolicy ?? "owned-only";
493
+ const propagateDeletePolicy = options.propagateDeletePolicy ?? "owned-only";
493
494
  const baseEmit = options.onEvent ?? defaultConsoleLogger;
494
495
  if (vaultConfig && entityContext) {
495
496
  throw new Error("share() requires exactly one of `vaultConfig` or `entityContext`, not both. " +
@@ -507,9 +508,30 @@ async function createPushRunContext(options) {
507
508
  const ctx = entityContext
508
509
  ? entityContext
509
510
  : await resolveEntityContext(companyRef, vaultConfig);
510
- if (ctx.uid.startsWith("prs_") && propagateDeletePolicy === "owned-only") {
511
- propagateDeletePolicy = "currency-gated";
512
- }
511
+ // NOTE (removed 6.14.48): a `prs_`-scoped coercion used to silently rewrite
512
+ // `owned-only` -> `currency-gated` here (366721b). It was correct for the
513
+ // problem it was written against and is now actively harmful, for three
514
+ // reasons that only became true later:
515
+ //
516
+ // 1. Its ONLY reachable effect in production was to override an EXPLICIT
517
+ // `owned-only`. Every live caller passes a policy
518
+ // (`sync-runner-company.ts` -> `resolveDeletePolicy()`), and that
519
+ // resolver already defaults to `currency-gated`. So the coercion never
520
+ // fired on a default run — it fired exactly when an operator had set
521
+ // `HQ_SYNC_DELETE_POLICY=owned-only`, i.e. the documented rollback.
522
+ // 2. Once delete authorization moved to ETag currency (no watcher-minted
523
+ // intent required), that override stopped being cosmetic: an operator
524
+ // reaching for the rollback because deletes were misbehaving would keep
525
+ // getting intent-less etag-only deletes on their personal vault. A
526
+ // rollback knob that silently exempts a vault is not a rollback knob.
527
+ // 3. Its motivating bug — the May-27 `personal/.obsidian/*.drift-*` leak —
528
+ // is fixed twice over by mechanisms that postdate it: the vault-litter
529
+ // drain (6.0.2) drains `.drift-*` markers ahead of every policy gate,
530
+ // and etag-gated deletes propagate an intent-less `direction:"down"`
531
+ // removal under the default policy without needing any coercion.
532
+ //
533
+ // So `owned-only` now means owned-only on every vault kind. It is the strict
534
+ // rollback path and must stay strictly stricter than the default everywhere.
513
535
  // Mirror push progress into the shared cross-process snapshot (see sync.ts).
514
536
  // Record the friendly company slug, or null for the personal vault so the
515
537
  // menubar shows "Personal" — never the raw prs_/cmp_ UID.
@@ -856,7 +878,11 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
856
878
  }
857
879
  if (freshContentConverged) {
858
880
  const lstat = fs.lstatSync(absolutePath);
859
- updateEntry(run.journal, relativePath, localHash, lstat.size, "up", remoteMeta.etag, lstat.mtimeMs, undefined, item.kind);
881
+ updateEntry(run.journal, relativePath, localHash, lstat.size, "up", absolutePath, {
882
+ remoteEtag: remoteMeta.etag,
883
+ mtimeMs: lstat.mtimeMs,
884
+ kind: item.kind,
885
+ });
860
886
  run.emit({ type: "reconciled", path: relativePath, direction: "push" });
861
887
  counters.filesSkipped++;
862
888
  return;
@@ -922,7 +948,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
922
948
  const { etag } = isSymlinkUpload
923
949
  ? await uploadSymlink(run.ctx, item.target, relativePath, run.options.author, pc)
924
950
  : await uploadFile(run.ctx, absolutePath, relativePath, run.options.author, pc);
925
- updateEntry(run.journal, relativePath, localHash, size, "up", etag, mtimeMs, undefined, item.kind);
951
+ updateEntry(run.journal, relativePath, localHash, size, "up", absolutePath, { remoteEtag: etag, mtimeMs, kind: item.kind });
926
952
  if (run.message) {
927
953
  run.journal.files[relativePath] = {
928
954
  ...run.journal.files[relativePath],
@@ -1070,19 +1096,32 @@ async function executeDeletes(run, deletePlan, decommissionPlan, counters, files
1070
1096
  }
1071
1097
  try {
1072
1098
  const entry = run.journal.files[relativePath];
1073
- if (!item.decommission &&
1099
+ // Last-second absence re-check. Applies to EVERY propagated delete,
1100
+ // intent-backed or etag-only: a pull leg or the user can recreate the
1101
+ // file between planning and applying, and deleting it remotely then
1102
+ // destroys a file that exists locally right now. This used to sit inside
1103
+ // the intent-version check, which meant it was skipped for any item
1104
+ // carrying `intentVersion: null` — harmless while that only covered
1105
+ // litter and decommission, but not once etag-only candidates travel that
1106
+ // way too.
1107
+ //
1108
+ // Codec boundary: journal keys are canonical; the probe must use the
1109
+ // ENCODED local path or a win32 colon key always looks absent (a raw `:`
1110
+ // name can never exist on disk) and the remote delete proceeds while the
1111
+ // encoded local file is still present.
1112
+ const recreatedLocally = !item.decommission &&
1113
+ !isLocallyAbsent(localPathForVaultKey(run.syncRoot, relativePath));
1114
+ const intentChanged = !item.decommission &&
1074
1115
  item.intentVersion !== null &&
1075
1116
  (!hasCurrentLocalDeleteIntent(entry) ||
1076
- entry.localDeleteIntent.version !== item.intentVersion ||
1077
- // Codec boundary: journal keys are canonical; the last-second
1078
- // absence re-check must probe the ENCODED local path or a win32
1079
- // colon key always looks absent (a raw `:` name can never exist
1080
- // on disk) and the remote delete proceeds while the encoded local
1081
- // file is still present.
1082
- !isLocallyAbsent(localPathForVaultKey(run.syncRoot, relativePath)))) {
1117
+ entry.localDeleteIntent.version !== item.intentVersion);
1118
+ if (recreatedLocally || intentChanged) {
1083
1119
  if (entry?.localDeleteIntent) {
1084
1120
  delete entry.localDeleteIntent;
1085
1121
  }
1122
+ const refusalReason = recreatedLocally
1123
+ ? "recreated-locally"
1124
+ : "intent-changed";
1086
1125
  counters.filesRefusedStale++;
1087
1126
  if (filesRefusedStalePaths.length < REFUSED_STALE_PATH_CAP) {
1088
1127
  filesRefusedStalePaths.push(relativePath);
@@ -1092,13 +1131,13 @@ async function executeDeletes(run, deletePlan, decommissionPlan, counters, files
1092
1131
  path: relativePath,
1093
1132
  journalEtag: entry?.remoteEtag ?? "<missing-delete-intent>",
1094
1133
  remoteEtag: "<not-checked>",
1095
- reason: "intent-changed",
1134
+ reason: refusalReason,
1096
1135
  });
1097
1136
  pathResults.push({
1098
1137
  path: relativePath,
1099
1138
  status: "refused",
1100
1139
  operation: "delete",
1101
- reason: "intent-changed",
1140
+ reason: refusalReason,
1102
1141
  });
1103
1142
  continue;
1104
1143
  }
@@ -1431,6 +1470,29 @@ function defaultConsoleLogger(event) {
1431
1470
  // the summary banner.
1432
1471
  console.error(` ⚠ bulk-asymmetry refusal, kept on remote: ${event.path}`);
1433
1472
  }
1473
+ else if (event.reason === "missing-delete-intent") {
1474
+ // NEITHER etag is meaningful here: no HEAD was issued, so `remoteEtag`
1475
+ // is the `<not-checked>` sentinel, and `journalEtag` is the entry's
1476
+ // real recorded etag. Printing them under the `stale-etag` wording
1477
+ // (which this branch used to fall through to) reads as an etag
1478
+ // conflict and has repeatedly sent operators chasing a currency bug
1479
+ // that does not exist — the actual cause is that no watcher observed
1480
+ // the removal, so no delete authorization was ever recorded.
1481
+ console.error(` ⚠ no-delete-authorization, kept on remote: ${event.path} ` +
1482
+ `(the sync watcher did not observe this removal, so the delete was never authorized)`);
1483
+ }
1484
+ else if (event.reason === "recreated-locally") {
1485
+ console.error(` ⚠ recreated-locally, kept on remote: ${event.path} ` +
1486
+ `(the file exists locally again, so the delete was abandoned)`);
1487
+ }
1488
+ else if (event.reason === "divergent-local") {
1489
+ // Same trap as above — `remoteEtag` is `<not-checked>`. The entry's
1490
+ // recorded etag was stamped only to silence a re-fired conflict; the
1491
+ // local copy never matched it, so propagating the delete would destroy
1492
+ // divergent remote work.
1493
+ console.error(` ⚠ divergent-local, kept on remote: ${event.path} ` +
1494
+ `(the local copy never matched the recorded remote version; pull to reconcile first)`);
1495
+ }
1434
1496
  else {
1435
1497
  console.error(` ⚠ stale-etag, kept on remote: ${event.path} (journal=${event.journalEtag}, remote=${event.remoteEtag})`);
1436
1498
  }
@@ -2260,6 +2322,40 @@ companyScoped = true) {
2260
2322
  relativeKey.startsWith(`${root}/`));
2261
2323
  if (!inScope)
2262
2324
  continue;
2325
+ // A tombstoned entry has ALREADY had its disposition decided — by a scope
2326
+ // shrink, `hq sync narrow --apply`, a manual prune, or a pull-side
2327
+ // intentional-delete record. It must never be re-evaluated as a fresh
2328
+ // delete candidate.
2329
+ //
2330
+ // This matters most for `all` -> `shared`: `tombstoneEntry` deliberately
2331
+ // KEEPS `hash`, `direction` and `remoteEtag` (so a recovery flow can see
2332
+ // what was there), and the shrink removes the file locally. Every one of
2333
+ // those entries therefore presents as locally-absent, intent-less and
2334
+ // etag-current — which, now that authorization is etag-only, is an
2335
+ // instruction to delete another member's files out of the shared company
2336
+ // vault, for the crime of having narrowed one's own sync scope.
2337
+ //
2338
+ // Until now the ONLY thing standing in the way was `shouldSync` happening
2339
+ // to carry a `prefixSet` (see `createPushRunContext`); any run that
2340
+ // resolved no prefix set — a degraded scope lookup, a caller that does not
2341
+ // set one — would have walked straight through. That is far too load-
2342
+ // bearing for an implicit dependency, so the invariant is stated here
2343
+ // directly.
2344
+ //
2345
+ // `local-delete` is the ONE reason that must pass: the pull leg stamps it
2346
+ // as a deliberate producer hand-off ("the user removed this; push leg,
2347
+ // finish the job"), and skipping it would strand exactly the deletes this
2348
+ // change exists to enable. Every other reason — scope_shrink,
2349
+ // narrow_apply, manual, or an absent/unrecognised one — means "stop
2350
+ // tracking, do NOT touch the remote", so the test is written fail-closed:
2351
+ // only the explicit hand-off is let through.
2352
+ //
2353
+ // Skipped BEFORE `inScopeJournalEntries++` so these inflate neither the
2354
+ // numerator nor the denominator of the bulk-asymmetry ratio. Excluding
2355
+ // them from the denominator can only make the breaker MORE likely to trip,
2356
+ // which is the safe direction.
2357
+ if (isTombstone(entry) && entry.removedReason !== "local-delete")
2358
+ continue;
2263
2359
  inScopeJournalEntries++;
2264
2360
  const localPath = localPathForVaultKey(syncRoot, relativeKey);
2265
2361
  // Scope-invalid journal keys (incident 2026-07-11): in a COMPANY-scoped
@@ -2335,11 +2431,78 @@ companyScoped = true) {
2335
2431
  continue;
2336
2432
  }
2337
2433
  if (!hasCurrentLocalDeleteIntent(entry)) {
2338
- if (policy === "currency-gated" ||
2339
- (policy === "owned-only" && entry.direction === "up")) {
2434
+ // A delete intent is minted ONLY by a live watcher, at the instant it
2435
+ // observes the unlink. Three of the four ways HQ syncs never construct a
2436
+ // watcher at all — outpost/agent boxes run a one-shot runner, `hq sync
2437
+ // now` is one-shot, and the desktop app drops `--event-push` (and with it
2438
+ // the whole TreeWatcher) whenever Instant-sync is off. On those surfaces
2439
+ // an intent can never exist, so requiring one made deletes structurally
2440
+ // impossible rather than merely gated. Files deleted while no watcher was
2441
+ // running also stranded permanently: the file is already gone, so no
2442
+ // watcher can ever retroactively witness it.
2443
+ //
2444
+ // `currency-gated` therefore authorizes on ETag currency alone. The
2445
+ // per-file question it answers is unchanged — "is the remote object still
2446
+ // exactly what this journal recorded, i.e. has no peer touched it since"
2447
+ // — and a mismatch still refuses (`stale-etag`) so a peer's newer work is
2448
+ // never destroyed.
2449
+ //
2450
+ // The whole-set question ("does my local mirror look catastrophically
2451
+ // empty") is NOT answered by the ETag, and must not be conflated with it:
2452
+ // in the steady state nobody has overwritten anything, so a moved hqRoot,
2453
+ // unmounted volume, fresh clone or partial restore presents mass-ENOENT
2454
+ // with perfectly matching ETags. That is exactly how the 2026-05-25
2455
+ // indigo vault mass-delete destroyed 559 objects. The bulk-asymmetry
2456
+ // breaker below is the guard for that class and is deliberately left
2457
+ // intact — these candidates are counted into `bulkCandidatePicks` on the
2458
+ // SAME line as intent-backed ones, so relaxing the per-file gate cannot
2459
+ // weaken the whole-set one. See policy `sync-delete-bulk-asymmetry-guard`
2460
+ // (hard) and workspace/reports/indigo-vault-mass-delete-debug.md.
2461
+ //
2462
+ // `owned-only` keeps requiring an intent: it is the documented rollback
2463
+ // knob, and an operator who selects it is asking for the stricter path.
2464
+ if (policy === "owned-only") {
2465
+ // Still counted into the breaker exactly as before: an owned-only run
2466
+ // whose mirror has gone missing must trip the whole-set guard even
2467
+ // though each individual key is refused for want of an intent.
2468
+ if (entry.direction === "up") {
2469
+ bulkCandidatePicks++;
2470
+ intentlessKeys.add(relativeKey);
2471
+ }
2472
+ plan.refusedStale.push({
2473
+ key: relativeKey,
2474
+ journalEtag: entry.remoteEtag ?? "<missing-delete-intent>",
2475
+ remoteEtag: "<not-checked>",
2476
+ reason: "missing-delete-intent",
2477
+ });
2478
+ continue;
2479
+ }
2480
+ if (policy === "currency-gated") {
2340
2481
  bulkCandidatePicks++;
2341
2482
  intentlessKeys.add(relativeKey);
2483
+ // No etag on record ⇒ nothing to compare ⇒ no authorization. Refused
2484
+ // for the same reason an intent-backed legacy entry is (below).
2485
+ if (!entry.remoteEtag) {
2486
+ plan.refusedStale.push({
2487
+ key: relativeKey,
2488
+ journalEtag: "<legacy-no-etag>",
2489
+ remoteEtag: "<unknown>",
2490
+ reason: "legacy-no-etag",
2491
+ });
2492
+ continue;
2493
+ }
2494
+ headCandidates.push({
2495
+ key: relativeKey,
2496
+ journalEtag: entry.remoteEtag,
2497
+ intentVersion: null,
2498
+ });
2499
+ continue;
2342
2500
  }
2501
+ // policy === "all" is deliberately NOT relaxed here. It already skips the
2502
+ // bulk-asymmetry breaker, so letting it skip the intent gate too would
2503
+ // make it a wholly unguarded mass delete — a strictly larger blast radius
2504
+ // than this change is scoped to. It keeps refusing intent-less entries
2505
+ // exactly as before.
2343
2506
  plan.refusedStale.push({
2344
2507
  key: relativeKey,
2345
2508
  journalEtag: entry.remoteEtag ?? "<missing-delete-intent>",