dsh-workbuddy-connect 0.6.2 → 0.6.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/lib/index.d.ts CHANGED
@@ -20,9 +20,9 @@ type WorkBuddySignedOutReasonCode =
20
20
  'credential-region-mismatch' |
21
21
  /** An encrypted credential exists but could not be opened (wrong key, GCM failure, helper crash). */
22
22
  'encrypted-credential-unreadable' |
23
- /** CN/macOS: discovery ran to completion and produced no usable candidate. */
23
+ /** A product on a supported platform: discovery ran to completion and found no usable candidate. */
24
24
  'electron-binary-not-found' |
25
- /** CN/macOS: discovery found more than one distinct usable app. */
25
+ /** A product on a supported platform: discovery found more than one distinct usable app. */
26
26
  'electron-binary-ambiguous' |
27
27
  /** No auto-discovery for this product/platform and no explicit path configured. */
28
28
  'electron-binary-unavailable' |
@@ -31,145 +31,6 @@ type WorkBuddySignedOutReasonCode =
31
31
  /** Discovery could not finish: tool missing, timeout, output overflow, unreadable plist. */
32
32
  'electron-discovery-incomplete';
33
33
  //#endregion
34
- //#region src/desktop-credential-protection.d.ts
35
- /** The four states a desktop auth document can be read as. */
36
- type DesktopAuthFormat = 'absent' | 'plaintext' | 'encrypted' | 'unrecognized';
37
- /** The spawned helper. Separated from the provider so tests can stand it in. */
38
- type WorkBuddyKeyPayloadSource = () => Promise<string>;
39
- /**
40
- * Which automatic discovery, if any, this provider may run when no explicit
41
- * binary is configured.
42
- *
43
- * `none` is the safe default: a provider that has not been told which product
44
- * it serves must not reach for another product's app. `macos-workbuddy` is the
45
- * CN line — the only one whose at-rest credentials and app layout have been
46
- * verified live — and resolves the platform default and then Spotlight.
47
- */
48
- type WorkBuddyElectronDiscovery = 'none' | 'macos-workbuddy';
49
- /** Seams the discovery flow runs through, so tests never spawn a process. */
50
- interface WorkBuddyDiscoveryTools {
51
- /** Candidate `.app` bundles for the CN bundle id, or a throw for an unusable tool. */
52
- findApps: (signal: AbortSignal) => Promise<readonly string[]>;
53
- /**
54
- * `CFBundleIdentifier` of a bundle, or `undefined` when the tool could not
55
- * read it — which is "we could not check this candidate", never "it does not
56
- * match". A successful read of a *different* id returns that id, and the
57
- * caller excludes the candidate.
58
- */
59
- bundleIdentifier: (bundlePath: string, signal: AbortSignal) => Promise<string | undefined>;
60
- /** Display version, best effort; `undefined` when unavailable. */
61
- bundleVersion: (bundlePath: string, signal: AbortSignal) => Promise<string | undefined>;
62
- }
63
- /** Provider options. */
64
- interface WorkBuddyAtRestKeyProviderOptions {
65
- /** Explicit Electron binary; overrides the platform default and env. */
66
- electronPath?: string;
67
- /** Helper timeout in milliseconds; default 10s. */
68
- timeoutMs?: number;
69
- /**
70
- * Where the payload comes from. Defaults to spawning WorkBuddy's own
71
- * Electron with `ELECTRON_RUN_AS_NODE=1`; tests supply a stand-in so no
72
- * test ever touches the real binary or a real key. Supplying this replaces
73
- * path *resolution* too, so tests about resolution use
74
- * {@link spawnHelper} instead.
75
- */
76
- source?: WorkBuddyKeyPayloadSource;
77
- /**
78
- * Runs the helper at the resolved path. Distinct from {@link source}, which
79
- * replaces the whole payload path: this seam keeps resolution — explicit
80
- * config, platform default, discovery — real, so tests can exercise it
81
- * without spawning anything.
82
- */
83
- spawnHelper?: (electronPath: string) => Promise<string>;
84
- /**
85
- * Automatic discovery budget; defaults to `'none'` (see
86
- * {@link WorkBuddyElectronDiscovery}). Passed explicitly per variant at the
87
- * composition root, never inferred from the environment.
88
- */
89
- discovery?: WorkBuddyElectronDiscovery;
90
- /**
91
- * Platform default binary, consulted only when `discovery` is enabled and no
92
- * explicit path is configured. Injectable so tests can force the fallback
93
- * branch without moving the real app; `null` means "no default here".
94
- */
95
- defaultElectronPath?: string | undefined;
96
- /** Discovery subprocesses; injectable so tests never spawn. */
97
- tools?: WorkBuddyDiscoveryTools;
98
- /**
99
- * Total budget for one discovery run, covering the search and every
100
- * candidate check. Injectable so tests can exercise exhaustion without
101
- * waiting out the production 10s.
102
- */
103
- discoveryBudgetMs?: number;
104
- }
105
- /**
106
- * In-memory protector-key resolver: one spawn per key id, single-flight, never
107
- * persisted. The cache is keyed by the id envelopes ask for, so an envelope
108
- * sealed under a rotated key triggers exactly one fresh resolution.
109
- */ declare class WorkBuddyAtRestKeyProvider {
110
- /**
111
- * The explicit binary, when one was configured. `undefined` here means "the
112
- * caller did not name one", which is what lets discovery run — an explicit
113
- * path that turns out to be unusable is an error, never a reason to look for
114
- * a different app.
115
- */
116
- private readonly explicitPath;
117
- private readonly defaultPath;
118
- private readonly discovery;
119
- private readonly tools;
120
- private readonly discoveryBudgetMs;
121
- private readonly timeoutMs;
122
- private readonly source;
123
- private readonly spawnHelper;
124
- /**
125
- * The path discovery settled on, cached only on success. A failure leaves
126
- * this unset so the next attempt tries again — the user may install or move
127
- * the app without restarting DSH.
128
- */
129
- private discoveredPath;
130
- private cache;
131
- private inflight;
132
- constructor(options?: WorkBuddyAtRestKeyProviderOptions);
133
- /**
134
- * The binary the default helper would use, for diagnostics.
135
- *
136
- * Reports a *discovery result* once one exists, so diagnostics describe what
137
- * would actually run rather than the default that was bypassed. Discovery
138
- * itself stays in {@link resolveElectronPath}: this accessor never triggers a
139
- * search (the constructor must remain I/O-free, and callers may ask before
140
- * any resolution has happened).
141
- */
142
- helperPath(): string | undefined;
143
- /**
144
- * A protector key matching one of the requested envelope key ids. The first
145
- * id the cache answers wins; otherwise one spawn resolves the current key,
146
- * which must match a request — a mismatch means the envelopes were sealed by
147
- * a different install than the one this machine now runs, and no key we can
148
- * reach will open them.
149
- */
150
- protectorKeyFor(requested: readonly string[]): Promise<Buffer>;
151
- private ingest;
152
- /**
153
- * The binary to spawn, or a diagnosable error saying why there is none.
154
- *
155
- * Order is the contract: an explicit path is used as-is and never falls back;
156
- * discovery runs only for a provider that was configured for it, and only
157
- * after the platform default has been tried and found unusable.
158
- */
159
- private resolveElectronPath;
160
- /**
161
- * Resolve the CN app through Spotlight, then prove each candidate's identity
162
- * before it can be executed.
163
- *
164
- * The whole flow shares one budget: a hang in one candidate must not extend
165
- * the wait for the others, and running out of budget is reported as an
166
- * unfinished check rather than an absent app.
167
- */
168
- private discoverMacosApp;
169
- private spawnPayload;
170
- private spawnAt;
171
- }
172
- //#endregion
173
34
  //#region src/app-version.d.ts
174
35
  /** Basename of the saved version under `$DSH_HOME`. */
175
36
  declare const WORKBUDDY_APP_VERSION_FILENAME = ".workbuddy-ai-version.json";
@@ -260,7 +121,7 @@ declare const FALLBACK_CN_APP_VERSION = "5.5.6";
260
121
  declare const CN_APP_VERSION_FILENAME = ".workbuddy-app-version.json";
261
122
  /** The resolved identity a chat request presents as. */
262
123
  interface ChatIdentity {
263
- /** Desktop App version; drives both `WorkBuddy/<v>` product tokens. */
124
+ /** Desktop App version; drives the desktop UA and `X-IDE-Version`. */
264
125
  clientVersion: string;
265
126
  /** Bundled agent-CLI version; absent drops the `CLI/…` UA token. */
266
127
  cliVersion?: string;
@@ -758,6 +619,15 @@ interface WorkBuddyVariant {
758
619
  region: WorkBuddyRegion;
759
620
  /** Env var overriding the desktop auth-file location. */
760
621
  env: string;
622
+ /**
623
+ * How this product's Electron helper is identified and located.
624
+ *
625
+ * Optional for source compatibility: `WorkBuddyVariant` is a public type and
626
+ * existing callers construct their own descriptors without it. Resolution
627
+ * falls back to {@link electronProfileFor}, keyed by variant id — an
628
+ * unknown id stays on the CN profile, the store's other legacy default.
629
+ */
630
+ electron?: WorkBuddyElectronProduct;
761
631
  /** Basename of the desktop app's own auth file in the shared auth directory. */
762
632
  desktopFilename: string;
763
633
  /** Basename of the plugin-owned credential copy under `$DSH_HOME`. */
@@ -786,6 +656,39 @@ interface WorkBuddyVariant {
786
656
  /** Same-origin probe-control route consumed by this variant's card. */
787
657
  probePath: string;
788
658
  }
659
+ /**
660
+ * How one product's Electron key helper is identified on each platform, and
661
+ * which env var names an explicit binary for it (issues #59/#60).
662
+ *
663
+ * The profile is the *only* place product identity enters helper resolution —
664
+ * never the discovery setting, which only says whether a platform may be
665
+ * searched at all: two products on the same platform differ by bundle id /
666
+ * registry name / exe basename, so a discovery that matches one can never
667
+ * legitimately execute the other's binary.
668
+ */
669
+ interface WorkBuddyElectronProduct {
670
+ /** Product name for helper diagnostics and error copy, e.g. `WorkBuddy AI`. */
671
+ productName: string;
672
+ /** Env var naming an explicit Electron binary for this product alone. */
673
+ envVar: string;
674
+ /** macOS identity and default install layout, verified per product. */
675
+ macOS: {
676
+ bundleId: string;
677
+ defaultPath: string;
678
+ };
679
+ /**
680
+ * Windows identity from the uninstall registry and the exe it names.
681
+ * `defaultPathSegments` exists only where the default install location has
682
+ * been measured (CN); the international app has only been seen in
683
+ * user-chosen locations, so it stays registry-only — an unverified default
684
+ * is a guess, and guessing is how the wrong app gets executed.
685
+ */
686
+ windows: {
687
+ displayNamePattern: RegExp;
688
+ exeBasename: string;
689
+ defaultPathSegments?: readonly string[];
690
+ };
691
+ }
789
692
  /** CN WorkBuddy first: the existing provider keeps its id, paths, and copy. */
790
693
  declare const WORKBUDDY_VARIANTS: readonly WorkBuddyVariant[];
791
694
  /** The CN variant; the plugin's long-standing default and compatibility anchor. */
@@ -795,6 +698,173 @@ declare const AI_VARIANT: WorkBuddyVariant;
795
698
  /** Look up a variant by provider id. */
796
699
  declare function variantFor(id: string): WorkBuddyVariant | undefined;
797
700
  //#endregion
701
+ //#region src/desktop-credential-protection.d.ts
702
+ /** The four states a desktop auth document can be read as. */
703
+ type DesktopAuthFormat = 'absent' | 'plaintext' | 'encrypted' | 'unrecognized';
704
+ /** The spawned helper. Separated from the provider so tests can stand it in. */
705
+ type WorkBuddyKeyPayloadSource = () => Promise<string>;
706
+ /**
707
+ * Which automatic discovery, if any, this provider may run when no explicit
708
+ * binary is configured.
709
+ *
710
+ * The value says which *platform* may be searched, never which product: two
711
+ * products on the same platform are told apart by the product profile
712
+ * ({@link WorkBuddyElectronProduct} — bundle id, registry name, exe basename),
713
+ * so a search for one can never execute the other's binary. `none` remains the
714
+ * safe default for platforms without a verified layout (Linux today).
715
+ */
716
+ type WorkBuddyElectronDiscovery = 'none' | 'macos-workbuddy' | 'windows-workbuddy';
717
+ /** Seams the discovery flow runs through, so tests never spawn a process. */
718
+ interface WorkBuddyDiscoveryTools {
719
+ /** Candidate `.app` bundles for the product's bundle id, or a throw for an unusable tool. */
720
+ findApps: (signal: AbortSignal) => Promise<readonly string[]>;
721
+ /**
722
+ * `CFBundleIdentifier` of a bundle, or `undefined` when the tool could not
723
+ * read it — which is "we could not check this candidate", never "it does not
724
+ * match". A successful read of a *different* id returns that id, and the
725
+ * caller excludes the candidate.
726
+ */
727
+ bundleIdentifier: (bundlePath: string, signal: AbortSignal) => Promise<string | undefined>;
728
+ /** Display version, best effort; `undefined` when unavailable. */
729
+ bundleVersion: (bundlePath: string, signal: AbortSignal) => Promise<string | undefined>;
730
+ }
731
+ /** Windows-only seam for querying one uninstall registry root. */
732
+ interface WorkBuddyWindowsDiscoveryTools {
733
+ queryUninstallRoot: (root: string, signal: AbortSignal) => Promise<string>;
734
+ }
735
+ /** Provider options. */
736
+ interface WorkBuddyAtRestKeyProviderOptions {
737
+ /**
738
+ * Which product's Electron this provider resolves. Required and the only
739
+ * source of product identity: it names the explicit-path env var, the bundle
740
+ * id / registry name / exe basename discovery must match, and the platform
741
+ * default. Without it the provider could not even decide which env var to
742
+ * read — the discovery setting alone cannot carry this (both products are
743
+ * `none` on Linux, yet each must read its own variable).
744
+ */
745
+ product: WorkBuddyElectronProduct;
746
+ /** Explicit Electron binary; overrides the platform default and env. */
747
+ electronPath?: string;
748
+ /** Helper timeout in milliseconds; default 10s. */
749
+ timeoutMs?: number;
750
+ /**
751
+ * Where the payload comes from. Defaults to spawning WorkBuddy's own
752
+ * Electron with `ELECTRON_RUN_AS_NODE=1`; tests supply a stand-in so no
753
+ * test ever touches the real binary or a real key. Supplying this replaces
754
+ * path *resolution* too, so tests about resolution use
755
+ * {@link spawnHelper} instead.
756
+ */
757
+ source?: WorkBuddyKeyPayloadSource;
758
+ /**
759
+ * Runs the helper at the resolved path. Distinct from {@link source}, which
760
+ * replaces the whole payload path: this seam keeps resolution — explicit
761
+ * config, platform default, discovery — real, so tests can exercise it
762
+ * without spawning anything.
763
+ */
764
+ spawnHelper?: (electronPath: string) => Promise<string>;
765
+ /**
766
+ * Automatic discovery budget; defaults to `'none'` (see
767
+ * {@link WorkBuddyElectronDiscovery}). Passed explicitly per variant at the
768
+ * composition root, never inferred from the environment.
769
+ */
770
+ discovery?: WorkBuddyElectronDiscovery;
771
+ /**
772
+ * Platform default binary, consulted only when `discovery` is enabled and no
773
+ * explicit path is configured. Injectable so tests can force the fallback
774
+ * branch without moving the real app; `null` means "no default here".
775
+ */
776
+ defaultElectronPath?: string | undefined;
777
+ /** Discovery subprocesses; injectable so tests never spawn. */
778
+ tools?: WorkBuddyDiscoveryTools;
779
+ /** Windows registry discovery subprocess; injectable so tests never spawn. */
780
+ windowsTools?: WorkBuddyWindowsDiscoveryTools;
781
+ /** Platform override for deterministic discovery tests. */
782
+ platform?: NodeJS.Platform;
783
+ /**
784
+ * Total budget for one discovery run, covering the search and every
785
+ * candidate check. Injectable so tests can exercise exhaustion without
786
+ * waiting out the production 10s.
787
+ */
788
+ discoveryBudgetMs?: number;
789
+ }
790
+ /**
791
+ * In-memory protector-key resolver: one spawn per key id, single-flight, never
792
+ * persisted. The cache is keyed by the id envelopes ask for, so an envelope
793
+ * sealed under a rotated key triggers exactly one fresh resolution.
794
+ */ declare class WorkBuddyAtRestKeyProvider {
795
+ /**
796
+ * The explicit binary, when one was configured. `undefined` here means "the
797
+ * caller did not name one", which is what lets discovery run — an explicit
798
+ * path that turns out to be unusable is an error, never a reason to look for
799
+ * a different app.
800
+ */
801
+ private readonly explicitPath;
802
+ private readonly product;
803
+ private readonly defaultPath;
804
+ private readonly discovery;
805
+ private readonly tools;
806
+ private readonly windowsTools;
807
+ private readonly platform;
808
+ private readonly discoveryBudgetMs;
809
+ private readonly timeoutMs;
810
+ private readonly source;
811
+ private readonly spawnHelper;
812
+ /**
813
+ * The path discovery settled on, cached only on success. A failure leaves
814
+ * this unset so the next attempt tries again — the user may install or move
815
+ * the app without restarting DSH.
816
+ */
817
+ private discoveredPath;
818
+ private cache;
819
+ private inflight;
820
+ constructor(options: WorkBuddyAtRestKeyProviderOptions);
821
+ /**
822
+ * The binary the default helper would use, for diagnostics.
823
+ *
824
+ * Reports a *discovery result* once one exists, so diagnostics describe what
825
+ * would actually run rather than the default that was bypassed. Discovery
826
+ * itself stays in {@link resolveElectronPath}: this accessor never triggers a
827
+ * search (the constructor must remain I/O-free, and callers may ask before
828
+ * any resolution has happened).
829
+ */
830
+ helperPath(): string | undefined;
831
+ /**
832
+ * A protector key matching one of the requested envelope key ids. The first
833
+ * id the cache answers wins; otherwise one spawn resolves the current key,
834
+ * which must match a request — a mismatch means the envelopes were sealed by
835
+ * a different install than the one this machine now runs, and no key we can
836
+ * reach will open them.
837
+ */
838
+ protectorKeyFor(requested: readonly string[]): Promise<Buffer>;
839
+ private ingest;
840
+ /**
841
+ * The binary to spawn, or a diagnosable error saying why there is none.
842
+ *
843
+ * Order is the contract: an explicit path is used as-is and never falls back;
844
+ * discovery runs only for a provider that was configured for it, and only
845
+ * after the platform default has been tried and found unusable.
846
+ */
847
+ private resolveElectronPath;
848
+ /**
849
+ * Resolve this product's app through Spotlight, then prove each candidate's
850
+ * identity before it can be executed.
851
+ *
852
+ * The whole flow shares one budget: a hang in one candidate must not extend
853
+ * the wait for the others, and running out of budget is reported as an
854
+ * unfinished check rather than an absent app.
855
+ */
856
+ private discoverMacosApp;
857
+ /**
858
+ * Resolve this product's app through Windows uninstall records. Registry
859
+ * entries provide hints, not trust: every DisplayIcon candidate must still
860
+ * be the product's Electron binary with the known Electron layout before
861
+ * execution.
862
+ */
863
+ private discoverWindowsApp;
864
+ private spawnPayload;
865
+ private spawnAt;
866
+ }
867
+ //#endregion
798
868
  //#region src/auth.d.ts
799
869
  /** Normalized WorkBuddy credential, timestamps in epoch milliseconds. */
800
870
  interface WorkBuddyCredential {