spidersan 0.2.2

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 (245) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/LICENSE +21 -0
  3. package/LICENSE.md +85 -0
  4. package/README.md +217 -0
  5. package/dist/bin/spidersan.d.ts +9 -0
  6. package/dist/bin/spidersan.d.ts.map +1 -0
  7. package/dist/bin/spidersan.js +152 -0
  8. package/dist/bin/spidersan.js.map +1 -0
  9. package/dist/commands/abandon.d.ts +8 -0
  10. package/dist/commands/abandon.d.ts.map +1 -0
  11. package/dist/commands/abandon.js +49 -0
  12. package/dist/commands/abandon.js.map +1 -0
  13. package/dist/commands/activate.d.ts +9 -0
  14. package/dist/commands/activate.d.ts.map +1 -0
  15. package/dist/commands/activate.js +45 -0
  16. package/dist/commands/activate.js.map +1 -0
  17. package/dist/commands/active-windows.d.ts +16 -0
  18. package/dist/commands/active-windows.d.ts.map +1 -0
  19. package/dist/commands/active-windows.js +373 -0
  20. package/dist/commands/active-windows.js.map +1 -0
  21. package/dist/commands/audit-mark.d.ts +12 -0
  22. package/dist/commands/audit-mark.d.ts.map +1 -0
  23. package/dist/commands/audit-mark.js +204 -0
  24. package/dist/commands/audit-mark.js.map +1 -0
  25. package/dist/commands/cleanup.d.ts +8 -0
  26. package/dist/commands/cleanup.d.ts.map +1 -0
  27. package/dist/commands/cleanup.js +41 -0
  28. package/dist/commands/cleanup.js.map +1 -0
  29. package/dist/commands/close.d.ts +9 -0
  30. package/dist/commands/close.d.ts.map +1 -0
  31. package/dist/commands/close.js +129 -0
  32. package/dist/commands/close.js.map +1 -0
  33. package/dist/commands/collab-sync.d.ts +14 -0
  34. package/dist/commands/collab-sync.d.ts.map +1 -0
  35. package/dist/commands/collab-sync.js +240 -0
  36. package/dist/commands/collab-sync.js.map +1 -0
  37. package/dist/commands/collab.d.ts +6 -0
  38. package/dist/commands/collab.d.ts.map +1 -0
  39. package/dist/commands/collab.js +103 -0
  40. package/dist/commands/collab.js.map +1 -0
  41. package/dist/commands/completions.d.ts +8 -0
  42. package/dist/commands/completions.d.ts.map +1 -0
  43. package/dist/commands/completions.js +83 -0
  44. package/dist/commands/completions.js.map +1 -0
  45. package/dist/commands/conflicts.d.ts +12 -0
  46. package/dist/commands/conflicts.d.ts.map +1 -0
  47. package/dist/commands/conflicts.js +426 -0
  48. package/dist/commands/conflicts.js.map +1 -0
  49. package/dist/commands/demo.d.ts +3 -0
  50. package/dist/commands/demo.d.ts.map +1 -0
  51. package/dist/commands/demo.js +113 -0
  52. package/dist/commands/demo.js.map +1 -0
  53. package/dist/commands/depends.d.ts +8 -0
  54. package/dist/commands/depends.d.ts.map +1 -0
  55. package/dist/commands/depends.js +44 -0
  56. package/dist/commands/depends.js.map +1 -0
  57. package/dist/commands/doctor.d.ts +8 -0
  58. package/dist/commands/doctor.d.ts.map +1 -0
  59. package/dist/commands/doctor.js +249 -0
  60. package/dist/commands/doctor.js.map +1 -0
  61. package/dist/commands/inbox.d.ts +3 -0
  62. package/dist/commands/inbox.d.ts.map +1 -0
  63. package/dist/commands/inbox.js +66 -0
  64. package/dist/commands/inbox.js.map +1 -0
  65. package/dist/commands/index.d.ts +43 -0
  66. package/dist/commands/index.d.ts.map +1 -0
  67. package/dist/commands/index.js +61 -0
  68. package/dist/commands/index.js.map +1 -0
  69. package/dist/commands/init.d.ts +8 -0
  70. package/dist/commands/init.d.ts.map +1 -0
  71. package/dist/commands/init.js +23 -0
  72. package/dist/commands/init.js.map +1 -0
  73. package/dist/commands/intent-scan.d.ts +17 -0
  74. package/dist/commands/intent-scan.d.ts.map +1 -0
  75. package/dist/commands/intent-scan.js +336 -0
  76. package/dist/commands/intent-scan.js.map +1 -0
  77. package/dist/commands/key-import.d.ts +3 -0
  78. package/dist/commands/key-import.d.ts.map +1 -0
  79. package/dist/commands/key-import.js +54 -0
  80. package/dist/commands/key-import.js.map +1 -0
  81. package/dist/commands/keygen.d.ts +3 -0
  82. package/dist/commands/keygen.d.ts.map +1 -0
  83. package/dist/commands/keygen.js +53 -0
  84. package/dist/commands/keygen.js.map +1 -0
  85. package/dist/commands/keys.d.ts +3 -0
  86. package/dist/commands/keys.d.ts.map +1 -0
  87. package/dist/commands/keys.js +56 -0
  88. package/dist/commands/keys.js.map +1 -0
  89. package/dist/commands/list.d.ts +3 -0
  90. package/dist/commands/list.d.ts.map +1 -0
  91. package/dist/commands/list.js +45 -0
  92. package/dist/commands/list.js.map +1 -0
  93. package/dist/commands/lock.d.ts +11 -0
  94. package/dist/commands/lock.d.ts.map +1 -0
  95. package/dist/commands/lock.js +220 -0
  96. package/dist/commands/lock.js.map +1 -0
  97. package/dist/commands/log.d.ts +8 -0
  98. package/dist/commands/log.d.ts.map +1 -0
  99. package/dist/commands/log.js +95 -0
  100. package/dist/commands/log.js.map +1 -0
  101. package/dist/commands/mcp-health.d.ts +3 -0
  102. package/dist/commands/mcp-health.d.ts.map +1 -0
  103. package/dist/commands/mcp-health.js +305 -0
  104. package/dist/commands/mcp-health.js.map +1 -0
  105. package/dist/commands/mcp-restart.d.ts +3 -0
  106. package/dist/commands/mcp-restart.d.ts.map +1 -0
  107. package/dist/commands/mcp-restart.js +176 -0
  108. package/dist/commands/mcp-restart.js.map +1 -0
  109. package/dist/commands/merge-order.d.ts +9 -0
  110. package/dist/commands/merge-order.d.ts.map +1 -0
  111. package/dist/commands/merge-order.js +138 -0
  112. package/dist/commands/merge-order.js.map +1 -0
  113. package/dist/commands/merged.d.ts +8 -0
  114. package/dist/commands/merged.d.ts.map +1 -0
  115. package/dist/commands/merged.js +39 -0
  116. package/dist/commands/merged.js.map +1 -0
  117. package/dist/commands/msg-read.d.ts +3 -0
  118. package/dist/commands/msg-read.d.ts.map +1 -0
  119. package/dist/commands/msg-read.js +70 -0
  120. package/dist/commands/msg-read.js.map +1 -0
  121. package/dist/commands/pulse.d.ts +9 -0
  122. package/dist/commands/pulse.d.ts.map +1 -0
  123. package/dist/commands/pulse.js +232 -0
  124. package/dist/commands/pulse.js.map +1 -0
  125. package/dist/commands/radar.d.ts +3 -0
  126. package/dist/commands/radar.d.ts.map +1 -0
  127. package/dist/commands/radar.js +147 -0
  128. package/dist/commands/radar.js.map +1 -0
  129. package/dist/commands/ready-check.d.ts +9 -0
  130. package/dist/commands/ready-check.d.ts.map +1 -0
  131. package/dist/commands/ready-check.js +156 -0
  132. package/dist/commands/ready-check.js.map +1 -0
  133. package/dist/commands/register.d.ts +3 -0
  134. package/dist/commands/register.d.ts.map +1 -0
  135. package/dist/commands/register.js +124 -0
  136. package/dist/commands/register.js.map +1 -0
  137. package/dist/commands/send.d.ts +3 -0
  138. package/dist/commands/send.d.ts.map +1 -0
  139. package/dist/commands/send.js +134 -0
  140. package/dist/commands/send.js.map +1 -0
  141. package/dist/commands/stale.d.ts +8 -0
  142. package/dist/commands/stale.d.ts.map +1 -0
  143. package/dist/commands/stale.js +38 -0
  144. package/dist/commands/stale.js.map +1 -0
  145. package/dist/commands/status.d.ts +9 -0
  146. package/dist/commands/status.d.ts.map +1 -0
  147. package/dist/commands/status.js +41 -0
  148. package/dist/commands/status.js.map +1 -0
  149. package/dist/commands/sync-all.d.ts +9 -0
  150. package/dist/commands/sync-all.d.ts.map +1 -0
  151. package/dist/commands/sync-all.js +180 -0
  152. package/dist/commands/sync-all.js.map +1 -0
  153. package/dist/commands/sync.d.ts +8 -0
  154. package/dist/commands/sync.d.ts.map +1 -0
  155. package/dist/commands/sync.js +49 -0
  156. package/dist/commands/sync.js.map +1 -0
  157. package/dist/commands/tension.d.ts +12 -0
  158. package/dist/commands/tension.d.ts.map +1 -0
  159. package/dist/commands/tension.js +242 -0
  160. package/dist/commands/tension.js.map +1 -0
  161. package/dist/commands/torrent.d.ts +9 -0
  162. package/dist/commands/torrent.d.ts.map +1 -0
  163. package/dist/commands/torrent.js +431 -0
  164. package/dist/commands/torrent.js.map +1 -0
  165. package/dist/commands/tui.d.ts +8 -0
  166. package/dist/commands/tui.d.ts.map +1 -0
  167. package/dist/commands/tui.js +15 -0
  168. package/dist/commands/tui.js.map +1 -0
  169. package/dist/commands/wake.d.ts +9 -0
  170. package/dist/commands/wake.d.ts.map +1 -0
  171. package/dist/commands/wake.js +188 -0
  172. package/dist/commands/wake.js.map +1 -0
  173. package/dist/commands/watch.d.ts +3 -0
  174. package/dist/commands/watch.d.ts.map +1 -0
  175. package/dist/commands/watch.js +245 -0
  176. package/dist/commands/watch.js.map +1 -0
  177. package/dist/commands/who-touched.d.ts +9 -0
  178. package/dist/commands/who-touched.d.ts.map +1 -0
  179. package/dist/commands/who-touched.js +186 -0
  180. package/dist/commands/who-touched.js.map +1 -0
  181. package/dist/index.d.ts +6 -0
  182. package/dist/index.d.ts.map +1 -0
  183. package/dist/index.js +6 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/lib/agent-errors.d.ts +41 -0
  186. package/dist/lib/agent-errors.d.ts.map +1 -0
  187. package/dist/lib/agent-errors.js +143 -0
  188. package/dist/lib/agent-errors.js.map +1 -0
  189. package/dist/lib/ast.d.ts +56 -0
  190. package/dist/lib/ast.d.ts.map +1 -0
  191. package/dist/lib/ast.js +134 -0
  192. package/dist/lib/ast.js.map +1 -0
  193. package/dist/lib/config.d.ts +33 -0
  194. package/dist/lib/config.d.ts.map +1 -0
  195. package/dist/lib/config.js +127 -0
  196. package/dist/lib/config.js.map +1 -0
  197. package/dist/lib/crdt.d.ts +83 -0
  198. package/dist/lib/crdt.d.ts.map +1 -0
  199. package/dist/lib/crdt.js +160 -0
  200. package/dist/lib/crdt.js.map +1 -0
  201. package/dist/lib/crypto.d.ts +71 -0
  202. package/dist/lib/crypto.d.ts.map +1 -0
  203. package/dist/lib/crypto.js +172 -0
  204. package/dist/lib/crypto.js.map +1 -0
  205. package/dist/lib/errors.d.ts +35 -0
  206. package/dist/lib/errors.d.ts.map +1 -0
  207. package/dist/lib/errors.js +71 -0
  208. package/dist/lib/errors.js.map +1 -0
  209. package/dist/lib/license.d.ts +61 -0
  210. package/dist/lib/license.d.ts.map +1 -0
  211. package/dist/lib/license.js +171 -0
  212. package/dist/lib/license.js.map +1 -0
  213. package/dist/lib/security.d.ts +53 -0
  214. package/dist/lib/security.d.ts.map +1 -0
  215. package/dist/lib/security.js +122 -0
  216. package/dist/lib/security.js.map +1 -0
  217. package/dist/lib/update-check.d.ts +11 -0
  218. package/dist/lib/update-check.d.ts.map +1 -0
  219. package/dist/lib/update-check.js +113 -0
  220. package/dist/lib/update-check.js.map +1 -0
  221. package/dist/storage/adapter.d.ts +58 -0
  222. package/dist/storage/adapter.d.ts.map +1 -0
  223. package/dist/storage/adapter.js +8 -0
  224. package/dist/storage/adapter.js.map +1 -0
  225. package/dist/storage/factory.d.ts +6 -0
  226. package/dist/storage/factory.d.ts.map +1 -0
  227. package/dist/storage/factory.js +22 -0
  228. package/dist/storage/factory.js.map +1 -0
  229. package/dist/storage/index.d.ts +5 -0
  230. package/dist/storage/index.d.ts.map +1 -0
  231. package/dist/storage/index.js +5 -0
  232. package/dist/storage/index.js.map +1 -0
  233. package/dist/storage/local.d.ts +24 -0
  234. package/dist/storage/local.d.ts.map +1 -0
  235. package/dist/storage/local.js +101 -0
  236. package/dist/storage/local.js.map +1 -0
  237. package/dist/storage/supabase.d.ts +52 -0
  238. package/dist/storage/supabase.d.ts.map +1 -0
  239. package/dist/storage/supabase.js +221 -0
  240. package/dist/storage/supabase.js.map +1 -0
  241. package/dist/tui/screen.d.ts +14 -0
  242. package/dist/tui/screen.d.ts.map +1 -0
  243. package/dist/tui/screen.js +136 -0
  244. package/dist/tui/screen.js.map +1 -0
  245. package/package.json +89 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Spidersan License Verification
3
+ *
4
+ * Ed25519-based license verification for Pro features.
5
+ * Public key is embedded; private key is kept by treebird for signing.
6
+ */
7
+ export declare const FREE_TIER_LIMITS: {
8
+ maxConcurrentBranches: number;
9
+ };
10
+ export type ProFeature = 'unlimited_branches' | 'mcp_server' | 'conflict_prediction' | 'team_sync';
11
+ export interface LicenseData {
12
+ email: string;
13
+ plan: 'free' | 'pro';
14
+ expiresAt: string;
15
+ issuedAt: string;
16
+ features: ProFeature[];
17
+ }
18
+ export interface License {
19
+ data: LicenseData;
20
+ isValid: boolean;
21
+ isExpired: boolean;
22
+ }
23
+ /**
24
+ * Verify a license string using Ed25519 detached signature
25
+ */
26
+ export declare function verifyLicense(licenseString: string): License | null;
27
+ /**
28
+ * Save a license key to disk
29
+ */
30
+ export declare function saveLicense(licenseString: string): boolean;
31
+ /**
32
+ * Load the saved license from disk
33
+ */
34
+ export declare function loadLicense(): License | null;
35
+ /**
36
+ * Check if user has a valid Pro license
37
+ */
38
+ export declare function isPro(): boolean;
39
+ /**
40
+ * Check if a specific Pro feature is enabled
41
+ */
42
+ export declare function hasFeature(feature: ProFeature): boolean;
43
+ /**
44
+ * Get license status summary
45
+ */
46
+ export declare function getLicenseStatus(): {
47
+ plan: 'free' | 'pro';
48
+ email?: string;
49
+ expiresAt?: string;
50
+ features: ProFeature[];
51
+ daysRemaining?: number;
52
+ };
53
+ /**
54
+ * Check branch limit and throw if exceeded (for free tier)
55
+ */
56
+ export declare function checkBranchLimit(currentBranchCount: number): Promise<void>;
57
+ /**
58
+ * Print Pro upsell message (soft sell)
59
+ */
60
+ export declare function printProUpsell(feature: string): void;
61
+ //# sourceMappingURL=license.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/lib/license.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH,eAAO,MAAM,gBAAgB;;CAE5B,CAAC;AAGF,MAAM,MAAM,UAAU,GAChB,oBAAoB,GACpB,YAAY,GACZ,qBAAqB,GACrB,WAAW,CAAC;AAElB,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,UAAU,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACtB;AAyBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA8BnE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAQ1D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,GAAG,IAAI,CAS5C;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,OAAO,CAM/B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAIvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI;IAChC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAqBA;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMpD"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Spidersan License Verification
3
+ *
4
+ * Ed25519-based license verification for Pro features.
5
+ * Public key is embedded; private key is kept by treebird for signing.
6
+ */
7
+ import nacl from 'tweetnacl';
8
+ import util from 'tweetnacl-util';
9
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
10
+ import { join } from 'path';
11
+ import { homedir } from 'os';
12
+ // License storage location
13
+ const LICENSE_DIR = join(homedir(), '.spidersan');
14
+ const LICENSE_FILE = join(LICENSE_DIR, 'license.key');
15
+ // Treebird's public key for license verification (Ed25519)
16
+ // This is the ONLY key that can sign valid licenses
17
+ const TREEBIRD_PUBLIC_KEY = 'XqIqSlybZGKkKemgLKKl8P9MepnObhcJcxxZHtgG8/o=';
18
+ // Free tier limits
19
+ export const FREE_TIER_LIMITS = {
20
+ maxConcurrentBranches: 5,
21
+ };
22
+ /**
23
+ * Ensure license directory exists
24
+ */
25
+ function ensureLicenseDir() {
26
+ if (!existsSync(LICENSE_DIR)) {
27
+ mkdirSync(LICENSE_DIR, { recursive: true });
28
+ }
29
+ }
30
+ /**
31
+ * Parse a license string into components
32
+ * Format: LICENSE_V1.BASE64_DATA.BASE64_SIGNATURE
33
+ */
34
+ function parseLicenseString(licenseString) {
35
+ const parts = licenseString.trim().split('.');
36
+ if (parts.length !== 3)
37
+ return null;
38
+ const [version, data, signature] = parts;
39
+ if (version !== 'LICENSE_V1')
40
+ return null;
41
+ return { version, data, signature };
42
+ }
43
+ /**
44
+ * Verify a license string using Ed25519 detached signature
45
+ */
46
+ export function verifyLicense(licenseString) {
47
+ try {
48
+ const parsed = parseLicenseString(licenseString);
49
+ if (!parsed)
50
+ return null;
51
+ const dataBytes = util.decodeBase64(parsed.data);
52
+ // Production mode - verify detached Ed25519 signature
53
+ const publicKey = util.decodeBase64(TREEBIRD_PUBLIC_KEY);
54
+ const signatureBytes = util.decodeBase64(parsed.signature);
55
+ // Verify the detached signature
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ const isValid = nacl.sign.detached.verify(dataBytes, signatureBytes, publicKey);
58
+ if (!isValid)
59
+ return null;
60
+ const dataString = util.encodeUTF8(dataBytes);
61
+ const data = JSON.parse(dataString);
62
+ const expiresAt = new Date(data.expiresAt);
63
+ const isExpired = expiresAt < new Date();
64
+ return {
65
+ data,
66
+ isValid: true,
67
+ isExpired,
68
+ };
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Save a license key to disk
76
+ */
77
+ export function saveLicense(licenseString) {
78
+ try {
79
+ ensureLicenseDir();
80
+ writeFileSync(LICENSE_FILE, licenseString.trim(), { mode: 0o600 });
81
+ return true;
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ /**
88
+ * Load the saved license from disk
89
+ */
90
+ export function loadLicense() {
91
+ if (!existsSync(LICENSE_FILE))
92
+ return null;
93
+ try {
94
+ const licenseString = readFileSync(LICENSE_FILE, 'utf-8');
95
+ return verifyLicense(licenseString);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ }
101
+ /**
102
+ * Check if user has a valid Pro license
103
+ */
104
+ export function isPro() {
105
+ const license = loadLicense();
106
+ if (!license)
107
+ return false;
108
+ if (!license.isValid)
109
+ return false;
110
+ if (license.isExpired)
111
+ return false;
112
+ return license.data.plan === 'pro';
113
+ }
114
+ /**
115
+ * Check if a specific Pro feature is enabled
116
+ */
117
+ export function hasFeature(feature) {
118
+ const license = loadLicense();
119
+ if (!license || !license.isValid || license.isExpired)
120
+ return false;
121
+ return license.data.features.includes(feature);
122
+ }
123
+ /**
124
+ * Get license status summary
125
+ */
126
+ export function getLicenseStatus() {
127
+ const license = loadLicense();
128
+ if (!license || !license.isValid || license.isExpired) {
129
+ return {
130
+ plan: 'free',
131
+ features: [],
132
+ };
133
+ }
134
+ const expiresAt = new Date(license.data.expiresAt);
135
+ const now = new Date();
136
+ const daysRemaining = Math.ceil((expiresAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
137
+ return {
138
+ plan: license.data.plan,
139
+ email: license.data.email,
140
+ expiresAt: license.data.expiresAt,
141
+ features: license.data.features,
142
+ daysRemaining,
143
+ };
144
+ }
145
+ /**
146
+ * Check branch limit and throw if exceeded (for free tier)
147
+ */
148
+ export async function checkBranchLimit(currentBranchCount) {
149
+ if (isPro())
150
+ return; // Pro has unlimited
151
+ if (currentBranchCount >= FREE_TIER_LIMITS.maxConcurrentBranches) {
152
+ console.error(`\n🕷️ Free tier limit reached: ${currentBranchCount}/${FREE_TIER_LIMITS.maxConcurrentBranches} branches`);
153
+ console.error('');
154
+ console.error(' Options:');
155
+ console.error(' • Clean up: spidersan merged <branch> or spidersan abandon <branch>');
156
+ console.error(' • Upgrade: spidersan.dev/pro for unlimited branches');
157
+ console.error('');
158
+ process.exit(1);
159
+ }
160
+ }
161
+ /**
162
+ * Print Pro upsell message (soft sell)
163
+ */
164
+ export function printProUpsell(feature) {
165
+ if (isPro())
166
+ return;
167
+ console.log('');
168
+ console.log(`💎 Pro tip: Upgrade for ${feature}`);
169
+ console.log(' spidersan.dev/pro');
170
+ }
171
+ //# sourceMappingURL=license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/lib/license.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Spidersan Security Utilities
3
+ *
4
+ * Input validation and sanitization for shell command safety.
5
+ * Prevents command injection attacks via agent IDs, branch names, etc.
6
+ *
7
+ * @module security
8
+ */
9
+ /**
10
+ * Validate agent ID (e.g., "sherlocksan", "watsan-1", "agent_01")
11
+ * @throws Error if invalid
12
+ */
13
+ export declare function validateAgentId(agentId: string): string;
14
+ /**
15
+ * Validate git branch name
16
+ * @throws Error if invalid
17
+ */
18
+ export declare function validateBranchName(branch: string): string;
19
+ /**
20
+ * Validate task ID (for torrent/task commands)
21
+ * @throws Error if invalid
22
+ */
23
+ export declare function validateTaskId(taskId: string): string;
24
+ /**
25
+ * Validate file path (basic safety check)
26
+ * @throws Error if invalid
27
+ */
28
+ export declare function validateFilePath(filePath: string): string;
29
+ /**
30
+ * Sanitize free-form text by removing shell metacharacters
31
+ * Use for message bodies, subjects, etc.
32
+ */
33
+ export declare function sanitizeText(text: string): string;
34
+ /**
35
+ * Sanitize an array of file paths
36
+ */
37
+ export declare function sanitizeFilePaths(files: string[]): string[];
38
+ /**
39
+ * Escape a string for safe use in git commands (minimal escaping)
40
+ */
41
+ export declare function escapeGitArg(arg: string): string;
42
+ export declare const patterns: {
43
+ VALID_AGENT_ID: RegExp;
44
+ VALID_BRANCH_NAME: RegExp;
45
+ VALID_TASK_ID: RegExp;
46
+ VALID_FILE_PATH: RegExp;
47
+ SHELL_METACHARACTERS: RegExp;
48
+ };
49
+ export declare const sanitizeAgentId: typeof validateAgentId;
50
+ export declare const sanitizeBranchName: typeof validateBranchName;
51
+ export declare const sanitizeFilePath: typeof validateFilePath;
52
+ export declare function isValidMessageId(messageId: string): boolean;
53
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYzD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAU3D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIhD;AAGD,eAAO,MAAM,QAAQ;;;;;;CAMpB,CAAA;AAGD,eAAO,MAAM,eAAe,wBAAkB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,2BAAqB,CAAC;AACrD,eAAO,MAAM,gBAAgB,yBAAmB,CAAC;AAIjD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Spidersan Security Utilities
3
+ *
4
+ * Input validation and sanitization for shell command safety.
5
+ * Prevents command injection attacks via agent IDs, branch names, etc.
6
+ *
7
+ * @module security
8
+ */
9
+ // Validation patterns
10
+ const VALID_AGENT_ID = /^[a-z0-9][a-z0-9_-]{0,30}$/i;
11
+ const VALID_BRANCH_NAME = /^[a-zA-Z0-9][a-zA-Z0-9/_.-]{0,99}$/;
12
+ const VALID_TASK_ID = /^[a-z0-9][a-z0-9_-]{0,50}$/i;
13
+ const VALID_FILE_PATH = /^[./a-zA-Z0-9][a-zA-Z0-9/_.@-]{0,200}$/;
14
+ // Shell metacharacters to remove from text
15
+ const SHELL_METACHARACTERS = /[`$(){}[\]|;&<>\\]/g;
16
+ /**
17
+ * Validate agent ID (e.g., "sherlocksan", "watsan-1", "agent_01")
18
+ * @throws Error if invalid
19
+ */
20
+ export function validateAgentId(agentId) {
21
+ if (!agentId || typeof agentId !== 'string') {
22
+ throw new Error('Agent ID is required');
23
+ }
24
+ if (!VALID_AGENT_ID.test(agentId)) {
25
+ throw new Error(`Invalid agent ID: "${agentId.slice(0, 20)}..." (must be alphanumeric with - or _)`);
26
+ }
27
+ return agentId;
28
+ }
29
+ /**
30
+ * Validate git branch name
31
+ * @throws Error if invalid
32
+ */
33
+ export function validateBranchName(branch) {
34
+ if (!branch || typeof branch !== 'string') {
35
+ throw new Error('Branch name is required');
36
+ }
37
+ if (!VALID_BRANCH_NAME.test(branch)) {
38
+ throw new Error(`Invalid branch name: "${branch.slice(0, 20)}..."`);
39
+ }
40
+ return branch;
41
+ }
42
+ /**
43
+ * Validate task ID (for torrent/task commands)
44
+ * @throws Error if invalid
45
+ */
46
+ export function validateTaskId(taskId) {
47
+ if (!taskId || typeof taskId !== 'string') {
48
+ throw new Error('Task ID is required');
49
+ }
50
+ if (!VALID_TASK_ID.test(taskId)) {
51
+ throw new Error(`Invalid task ID: "${taskId.slice(0, 20)}..." (must be alphanumeric with - or _)`);
52
+ }
53
+ return taskId;
54
+ }
55
+ /**
56
+ * Validate file path (basic safety check)
57
+ * @throws Error if invalid
58
+ */
59
+ export function validateFilePath(filePath) {
60
+ if (!filePath || typeof filePath !== 'string') {
61
+ throw new Error('File path is required');
62
+ }
63
+ // Block path traversal
64
+ if (filePath.includes('..')) {
65
+ throw new Error('Path traversal not allowed');
66
+ }
67
+ if (!VALID_FILE_PATH.test(filePath)) {
68
+ throw new Error(`Invalid file path: "${filePath.slice(0, 20)}..."`);
69
+ }
70
+ return filePath;
71
+ }
72
+ /**
73
+ * Sanitize free-form text by removing shell metacharacters
74
+ * Use for message bodies, subjects, etc.
75
+ */
76
+ export function sanitizeText(text) {
77
+ if (!text || typeof text !== 'string') {
78
+ return '';
79
+ }
80
+ return text.replace(SHELL_METACHARACTERS, '');
81
+ }
82
+ /**
83
+ * Sanitize an array of file paths
84
+ */
85
+ export function sanitizeFilePaths(files) {
86
+ return files.filter(f => {
87
+ try {
88
+ validateFilePath(f);
89
+ return true;
90
+ }
91
+ catch {
92
+ console.warn(`⚠️ Skipping invalid file path: ${f.slice(0, 30)}...`);
93
+ return false;
94
+ }
95
+ });
96
+ }
97
+ /**
98
+ * Escape a string for safe use in git commands (minimal escaping)
99
+ */
100
+ export function escapeGitArg(arg) {
101
+ // For use with execFileSync where no shell is invoked
102
+ // Just basic validation, no escaping needed
103
+ return arg;
104
+ }
105
+ // Export validation patterns for testing
106
+ export const patterns = {
107
+ VALID_AGENT_ID,
108
+ VALID_BRANCH_NAME,
109
+ VALID_TASK_ID,
110
+ VALID_FILE_PATH,
111
+ SHELL_METACHARACTERS,
112
+ };
113
+ // Test-compatible aliases for vitest security tests
114
+ export const sanitizeAgentId = validateAgentId;
115
+ export const sanitizeBranchName = validateBranchName;
116
+ export const sanitizeFilePath = validateFilePath;
117
+ // Message ID validation (for mycmail commands)
118
+ const VALID_MESSAGE_ID = /^[a-z0-9][a-z0-9_-]{0,64}$/i;
119
+ export function isValidMessageId(messageId) {
120
+ return typeof messageId === 'string' && VALID_MESSAGE_ID.test(messageId);
121
+ }
122
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Update Check Module
3
+ *
4
+ * Checks npm registry for newer versions and displays update notification.
5
+ * Non-blocking, fails silently.
6
+ */
7
+ /**
8
+ * Check for updates (non-blocking)
9
+ */
10
+ export declare function checkForUpdates(): Promise<void>;
11
+ //# sourceMappingURL=update-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../src/lib/update-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuEH;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCrD"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Update Check Module
3
+ *
4
+ * Checks npm registry for newer versions and displays update notification.
5
+ * Non-blocking, fails silently.
6
+ */
7
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+ const CONFIG_DIR = join(homedir(), '.spidersan');
11
+ const UPDATE_CACHE = join(CONFIG_DIR, 'update-cache.json');
12
+ const PACKAGE_NAME = 'spidersan';
13
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
14
+ /**
15
+ * Get current installed version
16
+ */
17
+ function getCurrentVersion() {
18
+ try {
19
+ const packagePath = new URL('../../package.json', import.meta.url);
20
+ const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
21
+ return pkg.version;
22
+ }
23
+ catch {
24
+ return '0.0.0';
25
+ }
26
+ }
27
+ /**
28
+ * Load update cache
29
+ */
30
+ function loadCache() {
31
+ try {
32
+ if (existsSync(UPDATE_CACHE)) {
33
+ return JSON.parse(readFileSync(UPDATE_CACHE, 'utf-8'));
34
+ }
35
+ }
36
+ catch {
37
+ // Ignore
38
+ }
39
+ return { lastCheck: 0, latestVersion: null };
40
+ }
41
+ /**
42
+ * Save update cache
43
+ */
44
+ function saveCache(cache) {
45
+ try {
46
+ if (!existsSync(CONFIG_DIR)) {
47
+ mkdirSync(CONFIG_DIR, { recursive: true });
48
+ }
49
+ writeFileSync(UPDATE_CACHE, JSON.stringify(cache));
50
+ }
51
+ catch {
52
+ // Ignore
53
+ }
54
+ }
55
+ /**
56
+ * Compare semantic versions
57
+ */
58
+ function isNewerVersion(current, latest) {
59
+ const currentParts = current.split('.').map(Number);
60
+ const latestParts = latest.split('.').map(Number);
61
+ for (let i = 0; i < 3; i++) {
62
+ if ((latestParts[i] || 0) > (currentParts[i] || 0))
63
+ return true;
64
+ if ((latestParts[i] || 0) < (currentParts[i] || 0))
65
+ return false;
66
+ }
67
+ return false;
68
+ }
69
+ /**
70
+ * Check for updates (non-blocking)
71
+ */
72
+ export async function checkForUpdates() {
73
+ try {
74
+ const cache = loadCache();
75
+ const now = Date.now();
76
+ // Only check once per day
77
+ if (now - cache.lastCheck < CHECK_INTERVAL_MS && cache.latestVersion) {
78
+ showUpdateNotification(cache.latestVersion);
79
+ return;
80
+ }
81
+ // Fetch latest version from npm (with timeout)
82
+ const controller = new AbortController();
83
+ const timeout = setTimeout(() => controller.abort(), 3000);
84
+ const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { signal: controller.signal });
85
+ clearTimeout(timeout);
86
+ if (!response.ok)
87
+ return;
88
+ const data = await response.json();
89
+ const latestVersion = data.version;
90
+ // Update cache
91
+ saveCache({ lastCheck: now, latestVersion });
92
+ // Show notification if newer
93
+ showUpdateNotification(latestVersion);
94
+ }
95
+ catch {
96
+ // Silent fail - don't interrupt user
97
+ }
98
+ }
99
+ /**
100
+ * Display update notification if newer version available
101
+ */
102
+ function showUpdateNotification(latestVersion) {
103
+ const currentVersion = getCurrentVersion();
104
+ if (isNewerVersion(currentVersion, latestVersion)) {
105
+ console.log('');
106
+ console.log('╭─────────────────────────────────────────────╮');
107
+ console.log(`│ 🕷️ Update available: ${currentVersion} → ${latestVersion.padEnd(10)} │`);
108
+ console.log('│ Run: npm install -g spidersan │');
109
+ console.log('╰─────────────────────────────────────────────╯');
110
+ console.log('');
111
+ }
112
+ }
113
+ //# sourceMappingURL=update-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/lib/update-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Storage Adapter Interface
3
+ *
4
+ * Abstract interface for branch registry storage.
5
+ * Implementations: LocalStorage (JSON), SupabaseStorage (Pro)
6
+ */
7
+ export interface Branch {
8
+ name: string;
9
+ files: string[];
10
+ registeredAt: Date;
11
+ agent?: string;
12
+ status: 'active' | 'completed' | 'abandoned';
13
+ description?: string;
14
+ }
15
+ export interface BranchRegistry {
16
+ branches: Record<string, Branch>;
17
+ version: string;
18
+ projectId?: string;
19
+ }
20
+ export interface StorageAdapter {
21
+ /**
22
+ * Initialize the storage (create directories, connect to DB, etc.)
23
+ */
24
+ init(): Promise<void>;
25
+ /**
26
+ * Check if storage is initialized
27
+ */
28
+ isInitialized(): Promise<boolean>;
29
+ /**
30
+ * Get all registered branches
31
+ */
32
+ list(): Promise<Branch[]>;
33
+ /**
34
+ * Register a new branch
35
+ */
36
+ register(branch: Omit<Branch, 'registeredAt'>): Promise<Branch>;
37
+ /**
38
+ * Update an existing branch
39
+ */
40
+ update(name: string, updates: Partial<Branch>): Promise<Branch | null>;
41
+ /**
42
+ * Unregister a branch
43
+ */
44
+ unregister(name: string): Promise<boolean>;
45
+ /**
46
+ * Get a specific branch by name
47
+ */
48
+ get(name: string): Promise<Branch | null>;
49
+ /**
50
+ * Find branches that touch specific files
51
+ */
52
+ findByFiles(files: string[]): Promise<Branch[]>;
53
+ /**
54
+ * Clean up old branches
55
+ */
56
+ cleanup(olderThan: Date): Promise<number>;
57
+ }
58
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/storage/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC3B;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAElC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEvE;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhD;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Storage Adapter Interface
3
+ *
4
+ * Abstract interface for branch registry storage.
5
+ * Implementations: LocalStorage (JSON), SupabaseStorage (Pro)
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/storage/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Storage factory - selects the right storage backend
3
+ */
4
+ import type { StorageAdapter } from './adapter.js';
5
+ export declare function getStorage(): Promise<StorageAdapter>;
6
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/storage/factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC,CAiB1D"}