cxgrd 0.1.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 (238) hide show
  1. package/README.md +221 -0
  2. package/dist/auth/audit-usage.d.ts +30 -0
  3. package/dist/auth/audit-usage.d.ts.map +1 -0
  4. package/dist/auth/audit-usage.js +104 -0
  5. package/dist/auth/audit-usage.js.map +1 -0
  6. package/dist/auth/auth-session.d.ts +17 -0
  7. package/dist/auth/auth-session.d.ts.map +1 -0
  8. package/dist/auth/auth-session.js +102 -0
  9. package/dist/auth/auth-session.js.map +1 -0
  10. package/dist/auth/auth-store.d.ts +17 -0
  11. package/dist/auth/auth-store.d.ts.map +1 -0
  12. package/dist/auth/auth-store.js +44 -0
  13. package/dist/auth/auth-store.js.map +1 -0
  14. package/dist/auth/entitlements.d.ts +14 -0
  15. package/dist/auth/entitlements.d.ts.map +1 -0
  16. package/dist/auth/entitlements.js +62 -0
  17. package/dist/auth/entitlements.js.map +1 -0
  18. package/dist/auth/open-browser.d.ts +2 -0
  19. package/dist/auth/open-browser.d.ts.map +1 -0
  20. package/dist/auth/open-browser.js +20 -0
  21. package/dist/auth/open-browser.js.map +1 -0
  22. package/dist/auth/plans.d.ts +10 -0
  23. package/dist/auth/plans.d.ts.map +1 -0
  24. package/dist/auth/plans.js +37 -0
  25. package/dist/auth/plans.js.map +1 -0
  26. package/dist/auth/plans.test.d.ts +2 -0
  27. package/dist/auth/plans.test.d.ts.map +1 -0
  28. package/dist/auth/plans.test.js +23 -0
  29. package/dist/auth/plans.test.js.map +1 -0
  30. package/dist/cg-directory.d.ts +37 -0
  31. package/dist/cg-directory.d.ts.map +1 -0
  32. package/dist/cg-directory.js +129 -0
  33. package/dist/cg-directory.js.map +1 -0
  34. package/dist/check/check-runner.d.ts +3 -0
  35. package/dist/check/check-runner.d.ts.map +1 -0
  36. package/dist/check/check-runner.js +48 -0
  37. package/dist/check/check-runner.js.map +1 -0
  38. package/dist/check/compiler-service.d.ts +6 -0
  39. package/dist/check/compiler-service.d.ts.map +1 -0
  40. package/dist/check/compiler-service.js +69 -0
  41. package/dist/check/compiler-service.js.map +1 -0
  42. package/dist/check/parsers/cargo.d.ts +3 -0
  43. package/dist/check/parsers/cargo.d.ts.map +1 -0
  44. package/dist/check/parsers/cargo.js +34 -0
  45. package/dist/check/parsers/cargo.js.map +1 -0
  46. package/dist/check/parsers/parsers.test.d.ts +2 -0
  47. package/dist/check/parsers/parsers.test.d.ts.map +1 -0
  48. package/dist/check/parsers/parsers.test.js +51 -0
  49. package/dist/check/parsers/parsers.test.js.map +1 -0
  50. package/dist/check/parsers/pyright.d.ts +3 -0
  51. package/dist/check/parsers/pyright.d.ts.map +1 -0
  52. package/dist/check/parsers/pyright.js +27 -0
  53. package/dist/check/parsers/pyright.js.map +1 -0
  54. package/dist/check/parsers/tsc-cli.d.ts +3 -0
  55. package/dist/check/parsers/tsc-cli.d.ts.map +1 -0
  56. package/dist/check/parsers/tsc-cli.js +22 -0
  57. package/dist/check/parsers/tsc-cli.js.map +1 -0
  58. package/dist/check/project-tooling.d.ts +18 -0
  59. package/dist/check/project-tooling.d.ts.map +1 -0
  60. package/dist/check/project-tooling.js +105 -0
  61. package/dist/check/project-tooling.js.map +1 -0
  62. package/dist/check/run-command.d.ts +8 -0
  63. package/dist/check/run-command.d.ts.map +1 -0
  64. package/dist/check/run-command.js +50 -0
  65. package/dist/check/run-command.js.map +1 -0
  66. package/dist/check/scope.d.ts +11 -0
  67. package/dist/check/scope.d.ts.map +1 -0
  68. package/dist/check/scope.js +46 -0
  69. package/dist/check/scope.js.map +1 -0
  70. package/dist/check/scope.test.d.ts +2 -0
  71. package/dist/check/scope.test.d.ts.map +1 -0
  72. package/dist/check/scope.test.js +15 -0
  73. package/dist/check/scope.test.js.map +1 -0
  74. package/dist/check/strict-mode.d.ts +5 -0
  75. package/dist/check/strict-mode.d.ts.map +1 -0
  76. package/dist/check/strict-mode.js +32 -0
  77. package/dist/check/strict-mode.js.map +1 -0
  78. package/dist/check/strict-mode.test.d.ts +2 -0
  79. package/dist/check/strict-mode.test.d.ts.map +1 -0
  80. package/dist/check/strict-mode.test.js +53 -0
  81. package/dist/check/strict-mode.test.js.map +1 -0
  82. package/dist/check/structural-checks.d.ts +3 -0
  83. package/dist/check/structural-checks.d.ts.map +1 -0
  84. package/dist/check/structural-checks.js +111 -0
  85. package/dist/check/structural-checks.js.map +1 -0
  86. package/dist/check/types.d.ts +40 -0
  87. package/dist/check/types.d.ts.map +1 -0
  88. package/dist/check/types.js +2 -0
  89. package/dist/check/types.js.map +1 -0
  90. package/dist/check/verifiers/python.d.ts +7 -0
  91. package/dist/check/verifiers/python.d.ts.map +1 -0
  92. package/dist/check/verifiers/python.js +43 -0
  93. package/dist/check/verifiers/python.js.map +1 -0
  94. package/dist/check/verifiers/rust.d.ts +7 -0
  95. package/dist/check/verifiers/rust.d.ts.map +1 -0
  96. package/dist/check/verifiers/rust.js +39 -0
  97. package/dist/check/verifiers/rust.js.map +1 -0
  98. package/dist/check/verifiers/typescript.d.ts +7 -0
  99. package/dist/check/verifiers/typescript.d.ts.map +1 -0
  100. package/dist/check/verifiers/typescript.js +108 -0
  101. package/dist/check/verifiers/typescript.js.map +1 -0
  102. package/dist/commands/auth.d.ts +4 -0
  103. package/dist/commands/auth.d.ts.map +1 -0
  104. package/dist/commands/auth.js +51 -0
  105. package/dist/commands/auth.js.map +1 -0
  106. package/dist/commands/check.d.ts +9 -0
  107. package/dist/commands/check.d.ts.map +1 -0
  108. package/dist/commands/check.js +145 -0
  109. package/dist/commands/check.js.map +1 -0
  110. package/dist/commands/doctor.d.ts +2 -0
  111. package/dist/commands/doctor.d.ts.map +1 -0
  112. package/dist/commands/doctor.js +76 -0
  113. package/dist/commands/doctor.js.map +1 -0
  114. package/dist/commands/init-hooks.d.ts +15 -0
  115. package/dist/commands/init-hooks.d.ts.map +1 -0
  116. package/dist/commands/init-hooks.js +102 -0
  117. package/dist/commands/init-hooks.js.map +1 -0
  118. package/dist/commands/input.d.ts +2 -0
  119. package/dist/commands/input.d.ts.map +1 -0
  120. package/dist/commands/input.js +139 -0
  121. package/dist/commands/input.js.map +1 -0
  122. package/dist/commands/prompt.d.ts +2 -0
  123. package/dist/commands/prompt.d.ts.map +1 -0
  124. package/dist/commands/prompt.js +70 -0
  125. package/dist/commands/prompt.js.map +1 -0
  126. package/dist/commands/scan.d.ts +5 -0
  127. package/dist/commands/scan.d.ts.map +1 -0
  128. package/dist/commands/scan.js +163 -0
  129. package/dist/commands/scan.js.map +1 -0
  130. package/dist/commands/watch.d.ts +11 -0
  131. package/dist/commands/watch.d.ts.map +1 -0
  132. package/dist/commands/watch.js +74 -0
  133. package/dist/commands/watch.js.map +1 -0
  134. package/dist/config/env.d.ts +5 -0
  135. package/dist/config/env.d.ts.map +1 -0
  136. package/dist/config/env.js +60 -0
  137. package/dist/config/env.js.map +1 -0
  138. package/dist/graph.d.ts +34 -0
  139. package/dist/graph.d.ts.map +1 -0
  140. package/dist/graph.js +123 -0
  141. package/dist/graph.js.map +1 -0
  142. package/dist/index.d.ts +3 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +176 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/memory/pattern-analyzer.d.ts +17 -0
  147. package/dist/memory/pattern-analyzer.d.ts.map +1 -0
  148. package/dist/memory/pattern-analyzer.js +56 -0
  149. package/dist/memory/pattern-analyzer.js.map +1 -0
  150. package/dist/memory/repo-memory.d.ts +14 -0
  151. package/dist/memory/repo-memory.d.ts.map +1 -0
  152. package/dist/memory/repo-memory.js +71 -0
  153. package/dist/memory/repo-memory.js.map +1 -0
  154. package/dist/memory/types.d.ts +32 -0
  155. package/dist/memory/types.d.ts.map +1 -0
  156. package/dist/memory/types.js +2 -0
  157. package/dist/memory/types.js.map +1 -0
  158. package/dist/prompt/llm-client.d.ts +8 -0
  159. package/dist/prompt/llm-client.d.ts.map +1 -0
  160. package/dist/prompt/llm-client.js +96 -0
  161. package/dist/prompt/llm-client.js.map +1 -0
  162. package/dist/prompt/subgraph.d.ts +26 -0
  163. package/dist/prompt/subgraph.d.ts.map +1 -0
  164. package/dist/prompt/subgraph.js +96 -0
  165. package/dist/prompt/subgraph.js.map +1 -0
  166. package/dist/scanner.d.ts +13 -0
  167. package/dist/scanner.d.ts.map +1 -0
  168. package/dist/scanner.js +92 -0
  169. package/dist/scanner.js.map +1 -0
  170. package/dist/team/audit.d.ts +4 -0
  171. package/dist/team/audit.d.ts.map +1 -0
  172. package/dist/team/audit.js +16 -0
  173. package/dist/team/audit.js.map +1 -0
  174. package/dist/team/cloud-client.d.ts +7 -0
  175. package/dist/team/cloud-client.d.ts.map +1 -0
  176. package/dist/team/cloud-client.js +106 -0
  177. package/dist/team/cloud-client.js.map +1 -0
  178. package/dist/team/dev-store.d.ts +9 -0
  179. package/dist/team/dev-store.d.ts.map +1 -0
  180. package/dist/team/dev-store.js +69 -0
  181. package/dist/team/dev-store.js.map +1 -0
  182. package/dist/team/graph-sync.d.ts +10 -0
  183. package/dist/team/graph-sync.d.ts.map +1 -0
  184. package/dist/team/graph-sync.js +78 -0
  185. package/dist/team/graph-sync.js.map +1 -0
  186. package/dist/team/policy-cache.d.ts +7 -0
  187. package/dist/team/policy-cache.d.ts.map +1 -0
  188. package/dist/team/policy-cache.js +31 -0
  189. package/dist/team/policy-cache.js.map +1 -0
  190. package/dist/team/policy-engine.d.ts +3 -0
  191. package/dist/team/policy-engine.d.ts.map +1 -0
  192. package/dist/team/policy-engine.js +35 -0
  193. package/dist/team/policy-engine.js.map +1 -0
  194. package/dist/team/policy-engine.test.d.ts +2 -0
  195. package/dist/team/policy-engine.test.d.ts.map +1 -0
  196. package/dist/team/policy-engine.test.js +29 -0
  197. package/dist/team/policy-engine.test.js.map +1 -0
  198. package/dist/team/repo-identity.d.ts +7 -0
  199. package/dist/team/repo-identity.d.ts.map +1 -0
  200. package/dist/team/repo-identity.js +41 -0
  201. package/dist/team/repo-identity.js.map +1 -0
  202. package/dist/team/types.d.ts +53 -0
  203. package/dist/team/types.d.ts.map +1 -0
  204. package/dist/team/types.js +2 -0
  205. package/dist/team/types.js.map +1 -0
  206. package/dist/toolchain/probe.d.ts +9 -0
  207. package/dist/toolchain/probe.d.ts.map +1 -0
  208. package/dist/toolchain/probe.js +123 -0
  209. package/dist/toolchain/probe.js.map +1 -0
  210. package/dist/toolchain/project-languages.d.ts +4 -0
  211. package/dist/toolchain/project-languages.d.ts.map +1 -0
  212. package/dist/toolchain/project-languages.js +41 -0
  213. package/dist/toolchain/project-languages.js.map +1 -0
  214. package/dist/toolchain/types.d.ts +32 -0
  215. package/dist/toolchain/types.d.ts.map +1 -0
  216. package/dist/toolchain/types.js +2 -0
  217. package/dist/toolchain/types.js.map +1 -0
  218. package/dist/utils/blast-radius-analyzer.d.ts +95 -0
  219. package/dist/utils/blast-radius-analyzer.d.ts.map +1 -0
  220. package/dist/utils/blast-radius-analyzer.js +277 -0
  221. package/dist/utils/blast-radius-analyzer.js.map +1 -0
  222. package/dist/utils/change-detector.d.ts +43 -0
  223. package/dist/utils/change-detector.d.ts.map +1 -0
  224. package/dist/utils/change-detector.js +190 -0
  225. package/dist/utils/change-detector.js.map +1 -0
  226. package/dist/utils/cli-formatter.d.ts +80 -0
  227. package/dist/utils/cli-formatter.d.ts.map +1 -0
  228. package/dist/utils/cli-formatter.js +205 -0
  229. package/dist/utils/cli-formatter.js.map +1 -0
  230. package/dist/utils/git-hook-manager.d.ts +81 -0
  231. package/dist/utils/git-hook-manager.d.ts.map +1 -0
  232. package/dist/utils/git-hook-manager.js +243 -0
  233. package/dist/utils/git-hook-manager.js.map +1 -0
  234. package/dist/utils/project-watcher.d.ts +91 -0
  235. package/dist/utils/project-watcher.d.ts.map +1 -0
  236. package/dist/utils/project-watcher.js +215 -0
  237. package/dist/utils/project-watcher.js.map +1 -0
  238. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,221 @@
1
+ # CXGRD CLI
2
+
3
+ The TypeScript CLI provides user-friendly commands for dependency analysis and AI-safe code changes.
4
+
5
+ ## CLI Commands
6
+
7
+ ### cxgrd scan [path]
8
+ **Purpose:** Build complete dependency graph
9
+
10
+ **Syntax:**
11
+ ```bash
12
+ cxgrd scan [projectPath]
13
+ ```
14
+
15
+ **Options:**
16
+ - `projectPath` (optional): Path to analyze (default: current directory)
17
+
18
+ **Output:**
19
+ Creates `.cg/` directory containing:
20
+ - `graph.json` - Full dependency graph
21
+ - `symbols.json` - Exported symbols per file
22
+ - `arch.json` - Inferred architectural layers
23
+ - `meta.json` - Scan metadata
24
+ - `history.json` - Operation history
25
+ - `patterns.json` - Pattern analysis
26
+
27
+ **Example:**
28
+ ```bash
29
+ cxgrd scan /path/to/myapp
30
+ ```
31
+
32
+ ---
33
+
34
+ ### cxgrd input <description>
35
+ **Purpose:** Analyze blast radius of a change
36
+
37
+ **Syntax:**
38
+ ```bash
39
+ cxgrd input "description" [--path /project/path]
40
+ ```
41
+
42
+ **Options:**
43
+ - `description` (required): What you're planning to change
44
+ - `--path` or `-p` (optional): Project path
45
+
46
+ **Output:**
47
+ - List of affected files
48
+ - Severity levels (high/medium/low)
49
+ - Why each file is affected
50
+ - Total downstream impact
51
+
52
+ **Example:**
53
+ ```bash
54
+ cxgrd input "rename AuthService to AuthController" --path /myapp
55
+ ```
56
+
57
+ ---
58
+
59
+ ### cxgrd prompt <description>
60
+ **Purpose:** Generate enriched AI prompt
61
+
62
+ **Syntax:**
63
+ ```bash
64
+ cxgrd prompt "description" [--path /project/path]
65
+ ```
66
+
67
+ **Options:**
68
+ - `description` (required): What you want to build
69
+ - `--path` or `-p` (optional): Project path
70
+
71
+ **Output:**
72
+ - Original request
73
+ - Affected modules
74
+ - Architectural considerations
75
+ - Related symbols to consider
76
+ - Key dependencies
77
+ - AI-friendly recommendations
78
+
79
+ **Example:**
80
+ ```bash
81
+ cxgrd prompt "add OAuth2 authentication" --path /myapp
82
+ ```
83
+
84
+ ---
85
+
86
+ ### cxgrd check [path]
87
+ **Purpose:** Structural graph validation + compiler-backed semantic checks
88
+
89
+ **Syntax:**
90
+ ```bash
91
+ cxgrd check [projectPath] [--staged] [--changed] [--skip-compiler] [--skip-structural]
92
+ ```
93
+
94
+ **Options:**
95
+ - `projectPath` (optional): Path to analyze
96
+ - `--staged`: Only report issues in git staged files (used by pre-commit hooks)
97
+ - `--changed`: Staged + unstaged changed files
98
+ - `--skip-compiler`: Structural checks only
99
+ - `--skip-structural`: Compiler checks only
100
+ - `--strict`: Fail if a detected language's compiler was skipped (recommended for CI)
101
+
102
+ **Compiler tools (auto-detected per project):**
103
+ - TypeScript — programmatic `typescript` API per `tsconfig.json`
104
+ - Python — `pyright --outputjson` (skipped if pyright not on PATH)
105
+ - Rust — `cargo check --message-format=json`
106
+
107
+ **Output:**
108
+ - Structural: circular deps, orphans, layer violations
109
+ - Compiler: type/syntax errors with file, line, and diagnostic code
110
+ - `.cg/check-latest.json` with full result payload
111
+
112
+ **Examples:**
113
+ ```bash
114
+ cxgrd check /myapp
115
+ cxgrd check . --staged
116
+ cxgrd check . --skip-structural
117
+ cxgrd check . --strict # CI: fail if Pyright/cargo missing on detected projects
118
+ cxgrd doctor . # verify toolchain before enabling --strict
119
+ ```
120
+
121
+ ### cxgrd doctor [path]
122
+ **Purpose:** Verify Node/runtime tools and (optionally) project readiness for strict checks
123
+
124
+ **Syntax:**
125
+ ```bash
126
+ cxgrd doctor # global toolchain only
127
+ cxgrd doctor [path] # + project language detection and .cg status
128
+ ```
129
+
130
+ Exits with code 1 when the project cannot run `cxgrd check --strict` (missing Pyright on a Python repo, no scan, etc.).
131
+
132
+ ### cxgrd init-hooks
133
+ **Purpose:** Initialize pre-commit hooks to catch errors before commiting to git
134
+
135
+ **Syntax:**
136
+ ```bash
137
+ cxgrd init-hooks # initialize hook
138
+ cxgrd init-hooks --threshold 80 --block-critical #initialize hook with threshold
139
+ cxgrd init-hooks --uninstall # uninstall hook
140
+ ```
141
+
142
+ ### cxgrd watch
143
+ **Purpose:** Real time monitoring which works in background
144
+
145
+ **Syntax:**
146
+ ```bash
147
+ cxgrd watch
148
+ ```
149
+
150
+ ## Output Format
151
+
152
+ ### graph.json Structure
153
+ ```json
154
+ {
155
+ "files": {
156
+ "src/services/auth.ts": {
157
+ "path": "src/services/auth.ts",
158
+ "language": "typescript",
159
+ "dependencies": [
160
+ {
161
+ "from": "src/services/auth.ts",
162
+ "to": "./utils/crypto.ts",
163
+ "type": "import",
164
+ "line": 3
165
+ }
166
+ ],
167
+ "symbols": ["authenticate", "AuthService", "validateToken"]
168
+ }
169
+ },
170
+ "stats": {
171
+ "totalFiles": 42,
172
+ "totalDependencies": 156,
173
+ "languages": {
174
+ "typescript": 32,
175
+ "python": 10
176
+ }
177
+ }
178
+ }
179
+ ```
180
+
181
+ ## Development
182
+
183
+ ### Installation
184
+ ```bash
185
+ npm install
186
+ npm run build
187
+ ```
188
+
189
+ ### Basic Usage
190
+
191
+ #### Scan a Project
192
+ ```bash
193
+ npm run dev -- scan /path/to/project
194
+ ```
195
+ Analyzes the project and creates `.cg/` with dependency graph.
196
+
197
+ #### Analyze Blast Radius
198
+ ```bash
199
+ npm run dev -- input "describe your change here"
200
+ ```
201
+ Shows which files will be affected by your proposed change.
202
+
203
+ #### Generate AI Prompt
204
+ ```bash
205
+ npm run dev -- prompt "describe your feature here"
206
+ ```
207
+ Creates an architecturally-aware prompt for your AI assistant.
208
+
209
+ #### Validate Code
210
+ ```bash
211
+ npm run dev -- check /path/to/project
212
+ ```
213
+ Checks for circular dependencies, orphaned files, and architecture violations.
214
+
215
+ ## Architecture Overview
216
+
217
+ 1. **Scanner** - Recursively finds source files
218
+ 2. **Graph Builder** - Extracts dependencies and symbols
219
+ 3. **CG Directory** - Manages `.cg/` persistence
220
+ 4. **Commands** - User-facing CLI operations
221
+
@@ -0,0 +1,30 @@
1
+ export interface AuditUsageRecord {
2
+ year: number;
3
+ month: number;
4
+ count: number;
5
+ lastUpdated: number;
6
+ }
7
+ export declare class AuditUsageExceededError extends Error {
8
+ readonly used: number;
9
+ readonly limit: number;
10
+ constructor(used: number, limit: number);
11
+ }
12
+ export declare const FREE_MONTHLY_AUDIT_LIMIT = 50;
13
+ /**
14
+ * Get current month's audit count for free tier tracking
15
+ */
16
+ export declare function getCurrentMonthAuditCount(): Promise<number>;
17
+ /**
18
+ * Increment audit count (called after successful scan/check)
19
+ */
20
+ export declare function incrementAuditCount(): Promise<void>;
21
+ /**
22
+ * Check if free tier audit limit exceeded
23
+ * Returns true if limit OK, throws if exceeded
24
+ */
25
+ export declare function checkFreeAuditLimit(): Promise<void>;
26
+ /**
27
+ * Print current usage status to console
28
+ */
29
+ export declare function printAuditUsageStatus(): Promise<void>;
30
+ //# sourceMappingURL=audit-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-usage.d.ts","sourceRoot":"","sources":["../../src/auth/audit-usage.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;aAE9B,IAAI,EAAE,MAAM;aACZ,KAAK,EAAE,MAAM;gBADb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM;CAQhC;AAED,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAkC3C;;GAEG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAMjE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BzD;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKzD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAe3D"}
@@ -0,0 +1,104 @@
1
+ import { mkdir, readFile, writeFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ import chalk from 'chalk';
5
+ export class AuditUsageExceededError extends Error {
6
+ constructor(used, limit) {
7
+ super(`Monthly audit limit exceeded. Used: ${used}/${limit}\n` +
8
+ ` Upgrade to Pro for unlimited audits at https://cxgrd.com/pricing`);
9
+ this.used = used;
10
+ this.limit = limit;
11
+ this.name = 'AuditUsageExceededError';
12
+ }
13
+ }
14
+ export const FREE_MONTHLY_AUDIT_LIMIT = 50;
15
+ function getUsagePath() {
16
+ return join(homedir(), '.cg', 'usage.json');
17
+ }
18
+ async function readUsageFile() {
19
+ try {
20
+ const content = await readFile(getUsagePath(), 'utf-8');
21
+ return JSON.parse(content);
22
+ }
23
+ catch {
24
+ return [];
25
+ }
26
+ }
27
+ async function writeUsageFile(records) {
28
+ const path = getUsagePath();
29
+ const dir = join(homedir(), '.cg');
30
+ try {
31
+ await mkdir(dir, { recursive: true });
32
+ await writeFile(path, JSON.stringify(records, null, 2), 'utf-8');
33
+ }
34
+ catch {
35
+ // Silently fail if we can't write usage (e.g., permission issues)
36
+ // Don't block user from running commands
37
+ }
38
+ }
39
+ function getCurrentMonth() {
40
+ const now = new Date();
41
+ return {
42
+ year: now.getFullYear(),
43
+ month: now.getMonth() + 1, // getMonth() is 0-indexed
44
+ };
45
+ }
46
+ /**
47
+ * Get current month's audit count for free tier tracking
48
+ */
49
+ export async function getCurrentMonthAuditCount() {
50
+ const records = await readUsageFile();
51
+ const current = getCurrentMonth();
52
+ const record = records.find((r) => r.year === current.year && r.month === current.month);
53
+ return record?.count ?? 0;
54
+ }
55
+ /**
56
+ * Increment audit count (called after successful scan/check)
57
+ */
58
+ export async function incrementAuditCount() {
59
+ const records = await readUsageFile();
60
+ const current = getCurrentMonth();
61
+ const record = records.find((r) => r.year === current.year && r.month === current.month);
62
+ if (record) {
63
+ record.count++;
64
+ record.lastUpdated = Date.now();
65
+ }
66
+ else {
67
+ records.push({
68
+ year: current.year,
69
+ month: current.month,
70
+ count: 1,
71
+ lastUpdated: Date.now(),
72
+ });
73
+ }
74
+ // Clean up old records (keep last 12 months)
75
+ const thirteenMonthsAgo = new Date();
76
+ thirteenMonthsAgo.setMonth(thirteenMonthsAgo.getMonth() - 13);
77
+ const filtered = records.filter((r) => {
78
+ const recordDate = new Date(r.lastUpdated);
79
+ return recordDate > thirteenMonthsAgo;
80
+ });
81
+ await writeUsageFile(filtered);
82
+ }
83
+ /**
84
+ * Check if free tier audit limit exceeded
85
+ * Returns true if limit OK, throws if exceeded
86
+ */
87
+ export async function checkFreeAuditLimit() {
88
+ const count = await getCurrentMonthAuditCount();
89
+ if (count >= FREE_MONTHLY_AUDIT_LIMIT) {
90
+ throw new AuditUsageExceededError(count, FREE_MONTHLY_AUDIT_LIMIT);
91
+ }
92
+ }
93
+ /**
94
+ * Print current usage status to console
95
+ */
96
+ export async function printAuditUsageStatus() {
97
+ const count = await getCurrentMonthAuditCount();
98
+ const percent = Math.round((count / FREE_MONTHLY_AUDIT_LIMIT) * 100);
99
+ console.log(chalk.gray(` Audits this month: ${count}/${FREE_MONTHLY_AUDIT_LIMIT} (${percent}%)`));
100
+ if (count >= FREE_MONTHLY_AUDIT_LIMIT - 5) {
101
+ console.log(chalk.yellow(` ⚠ Approaching monthly limit — upgrade to Pro for unlimited audits`));
102
+ }
103
+ }
104
+ //# sourceMappingURL=audit-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-usage.js","sourceRoot":"","sources":["../../src/auth/audit-usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type StoredAuth } from './auth-store';
2
+ import { type SubscriptionPlan } from './plans';
3
+ import type { OrgRole } from '../team/types';
4
+ export interface ActiveSession {
5
+ token: string;
6
+ plan: SubscriptionPlan;
7
+ source: 'auth_file' | 'dev_override';
8
+ email?: string;
9
+ orgId?: string;
10
+ orgName?: string;
11
+ role: OrgRole;
12
+ }
13
+ export declare function resolveActiveSession(): Promise<ActiveSession | null>;
14
+ export declare function pollAuthSession(sessionId: string): Promise<StoredAuth>;
15
+ export declare function createCliSessionId(): string;
16
+ export declare function buildCliAuthUrl(sessionId: string): string;
17
+ //# sourceMappingURL=auth-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-session.d.ts","sourceRoot":"","sources":["../../src/auth/auth-session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAW7C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,WAAW,GAAG,cAAc,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA8B1E;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAiE5E;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGzD"}
@@ -0,0 +1,102 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { envString } from '../config/env';
3
+ import { readAuth } from './auth-store';
4
+ import { normalizePlan } from './plans';
5
+ function normalizeRole(role) {
6
+ const r = (role || 'member').toLowerCase();
7
+ if (r === 'lead' || r === 'admin')
8
+ return r;
9
+ return 'member';
10
+ }
11
+ const POLL_INTERVAL_MS = 2000;
12
+ const POLL_TIMEOUT_MS = 5 * 60 * 1000;
13
+ export async function resolveActiveSession() {
14
+ // Dev override — lets you test pro/team locally without real auth
15
+ const devPlan = envString('CXGRD_DEV_PLAN');
16
+ if (devPlan) {
17
+ const plan = normalizePlan(devPlan);
18
+ if (plan !== 'free') {
19
+ return {
20
+ token: envString('CXGRD_DEV_TOKEN', 'dev-local'),
21
+ plan,
22
+ source: 'dev_override',
23
+ orgId: envString('CXGRD_DEV_ORG_ID', 'org_dev'),
24
+ orgName: envString('CXGRD_DEV_ORG_NAME', 'Dev Org'),
25
+ role: normalizeRole(envString('CXGRD_DEV_ROLE', 'member')),
26
+ };
27
+ }
28
+ }
29
+ const stored = await readAuth();
30
+ if (!stored)
31
+ return null;
32
+ return {
33
+ token: stored.token,
34
+ plan: stored.plan,
35
+ source: 'auth_file',
36
+ email: stored.email,
37
+ // orgId/orgName/role only populated for team/enterprise — undefined for free+pro
38
+ orgId: stored.orgId,
39
+ orgName: stored.orgName,
40
+ role: normalizeRole(stored.role),
41
+ };
42
+ }
43
+ export async function pollAuthSession(sessionId) {
44
+ const baseUrl = envString('CXGRD_AUTH_BASE_URL', 'https://cxgrd.com').replace(/\/$/, '');
45
+ const url = `${baseUrl}/api/auth/cli/session/${sessionId}`;
46
+ const started = Date.now();
47
+ while (Date.now() - started < POLL_TIMEOUT_MS) {
48
+ const response = await fetch(url, {
49
+ method: 'GET',
50
+ headers: { Accept: 'application/json' },
51
+ });
52
+ if (response.status === 404 || response.status === 501) {
53
+ throw new Error('Auth API is not available yet. For local dev set CXGRD_DEV_PLAN=pro in .env');
54
+ }
55
+ // 202 = still pending, user hasn't completed GitHub login yet
56
+ if (response.status === 202) {
57
+ await sleep(POLL_INTERVAL_MS);
58
+ continue;
59
+ }
60
+ if (!response.ok) {
61
+ const body = await response.text().catch(() => '');
62
+ throw new Error(`Auth poll failed (${response.status}): ${body || response.statusText}`);
63
+ }
64
+ const data = (await response.json());
65
+ const token = data.token || data.access_token;
66
+ if (!token) {
67
+ await sleep(POLL_INTERVAL_MS);
68
+ continue;
69
+ }
70
+ const auth = {
71
+ token,
72
+ plan: normalizePlan(data.plan),
73
+ email: data.email,
74
+ // these are only set for team/enterprise accounts
75
+ orgId: data.org_id ?? data.orgId,
76
+ orgName: data.org_name ?? data.orgName,
77
+ role: normalizeRole(data.role),
78
+ expiresAt: normalizeExpiry(data.expires_at ?? data.expiresAt),
79
+ obtainedAt: Date.now(),
80
+ };
81
+ // Free and pro users both get a token — feature gates are enforced per-command
82
+ return auth;
83
+ }
84
+ throw new Error('Timed out waiting for browser login. Try again.');
85
+ }
86
+ export function createCliSessionId() {
87
+ return randomUUID();
88
+ }
89
+ export function buildCliAuthUrl(sessionId) {
90
+ const baseUrl = envString('CXGRD_AUTH_BASE_URL', 'https://cxgrd.com').replace(/\/$/, '');
91
+ return `${baseUrl}/auth/cli?session=${encodeURIComponent(sessionId)}`;
92
+ }
93
+ function sleep(ms) {
94
+ return new Promise((resolve) => setTimeout(resolve, ms));
95
+ }
96
+ function normalizeExpiry(expiresAt) {
97
+ if (!expiresAt || Number.isNaN(expiresAt))
98
+ return undefined;
99
+ // accept either epoch seconds or milliseconds
100
+ return expiresAt < 1000000000000 ? expiresAt * 1000 : expiresAt;
101
+ }
102
+ //# sourceMappingURL=auth-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-session.js","sourceRoot":"","sources":["../../src/auth/auth-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { SubscriptionPlan } from './plans';
2
+ import type { OrgRole } from '../team/types';
3
+ export interface StoredAuth {
4
+ token: string;
5
+ plan: SubscriptionPlan;
6
+ expiresAt?: number;
7
+ email?: string;
8
+ orgId?: string;
9
+ orgName?: string;
10
+ role?: OrgRole;
11
+ obtainedAt: number;
12
+ }
13
+ export declare function readAuth(): Promise<StoredAuth | null>;
14
+ export declare function writeAuth(auth: StoredAuth): Promise<void>;
15
+ export declare function clearAuth(): Promise<void>;
16
+ export declare function getAuthPath(): string;
17
+ //# sourceMappingURL=auth-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.d.ts","sourceRoot":"","sources":["../../src/auth/auth-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAsB,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAa3D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/D;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/C;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
@@ -0,0 +1,44 @@
1
+ import { mkdir, readFile, writeFile, unlink } from 'fs/promises';
2
+ import { homedir } from 'os';
3
+ import { join } from 'path';
4
+ import { normalizePlan } from './plans';
5
+ const AUTH_DIR = join(homedir(), '.cg');
6
+ const AUTH_PATH = join(AUTH_DIR, 'auth.json');
7
+ export async function readAuth() {
8
+ try {
9
+ const raw = await readFile(AUTH_PATH, 'utf-8');
10
+ const data = JSON.parse(raw);
11
+ if (!data.token)
12
+ return null;
13
+ const expiresAt = normalizeExpiry(data.expiresAt);
14
+ if (expiresAt && Date.now() > expiresAt) {
15
+ return null;
16
+ }
17
+ return { ...data, plan: normalizePlan(data.plan), expiresAt };
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ export async function writeAuth(auth) {
24
+ await mkdir(AUTH_DIR, { recursive: true });
25
+ await writeFile(AUTH_PATH, JSON.stringify(auth, null, 2), 'utf-8');
26
+ }
27
+ export async function clearAuth() {
28
+ try {
29
+ await unlink(AUTH_PATH);
30
+ }
31
+ catch {
32
+ // already cleared
33
+ }
34
+ }
35
+ export function getAuthPath() {
36
+ return AUTH_PATH;
37
+ }
38
+ function normalizeExpiry(expiresAt) {
39
+ if (!expiresAt || Number.isNaN(expiresAt)) {
40
+ return undefined;
41
+ }
42
+ return expiresAt < 1000000000000 ? expiresAt * 1000 : expiresAt;
43
+ }
44
+ //# sourceMappingURL=auth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../src/auth/auth-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAcxC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;AACxC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAC7B,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAgB;IAC9C,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,SAA6B;IACpD,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,GAAG,aAAiB,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACtE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type ProFeature, type TeamFeature } from './plans';
2
+ import { type ActiveSession } from './auth-session';
3
+ export declare class ProRequiredError extends Error {
4
+ readonly feature: ProFeature;
5
+ constructor(message: string, feature: ProFeature);
6
+ }
7
+ export declare class TeamRequiredError extends Error {
8
+ readonly feature: TeamFeature;
9
+ constructor(message: string, feature: TeamFeature);
10
+ }
11
+ export declare function requireProFeature(feature: ProFeature): Promise<ActiveSession>;
12
+ export declare function requireTeamFeature(feature: TeamFeature): Promise<ActiveSession>;
13
+ export declare function printSessionStatus(session: ActiveSession | null): void;
14
+ //# sourceMappingURL=entitlements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlements.d.ts","sourceRoot":"","sources":["../../src/auth/entitlements.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE1E,qBAAa,gBAAiB,SAAQ,KAAK;aAGvB,OAAO,EAAE,UAAU;gBADnC,OAAO,EAAE,MAAM,EACC,OAAO,EAAE,UAAU;CAKtC;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aAGxB,OAAO,EAAE,WAAW;gBADpC,OAAO,EAAE,MAAM,EACC,OAAO,EAAE,WAAW;CAKvC;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAqBnF;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CA4BrF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAwBtE"}
@@ -0,0 +1,62 @@
1
+ import chalk from 'chalk';
2
+ import { planIncludesFeature, planDisplayName, isTeamOrEnterprise, } from './plans';
3
+ import { resolveActiveSession } from './auth-session';
4
+ export class ProRequiredError extends Error {
5
+ constructor(message, feature) {
6
+ super(message);
7
+ this.feature = feature;
8
+ this.name = 'ProRequiredError';
9
+ }
10
+ }
11
+ export class TeamRequiredError extends Error {
12
+ constructor(message, feature) {
13
+ super(message);
14
+ this.feature = feature;
15
+ this.name = 'TeamRequiredError';
16
+ }
17
+ }
18
+ export async function requireProFeature(feature) {
19
+ const session = await resolveActiveSession();
20
+ if (!session) {
21
+ throw new ProRequiredError(`This feature requires a Pro, Team, or Enterprise plan.\n` +
22
+ ` Run ${chalk.cyan('cxgrd auth login')} or visit https://cxgrd.com/pricing\n` +
23
+ ` Local dev: set CXGRD_DEV_PLAN=pro in .env (see .env.example)`, feature);
24
+ }
25
+ if (!planIncludesFeature(session.plan, feature)) {
26
+ throw new ProRequiredError(`Your plan (${planDisplayName(session.plan)}) does not include this feature.\n` +
27
+ ` Upgrade at https://cxgrd.com/pricing`, feature);
28
+ }
29
+ return session;
30
+ }
31
+ export async function requireTeamFeature(feature) {
32
+ const session = await resolveActiveSession();
33
+ if (!session) {
34
+ throw new TeamRequiredError(`This feature requires Team or Enterprise.\n` +
35
+ ` Run ${chalk.cyan('cxgrd auth login')} after upgrading\n` +
36
+ ` Local dev: CXGRD_DEV_PLAN=team CXGRD_DEV_ORG_ID=org_dev CXGRD_DEV_CLOUD=1`, feature);
37
+ }
38
+ if (!planIncludesFeature(session.plan, feature)) {
39
+ throw new TeamRequiredError(`Your plan (${planDisplayName(session.plan)}) does not include team features.\n` +
40
+ ` Upgrade at https://cxgrd.com/pricing`, feature);
41
+ }
42
+ if (!session.orgId) {
43
+ throw new TeamRequiredError(`No organization linked to your account. Join or create a team workspace in the dashboard.`, feature);
44
+ }
45
+ return session;
46
+ }
47
+ export function printSessionStatus(session) {
48
+ if (!session) {
49
+ console.log(chalk.gray(' Not signed in (Free tier — scan, input, check available locally)'));
50
+ return;
51
+ }
52
+ const src = session.source === 'dev_override'
53
+ ? chalk.yellow(' (dev override via CXGRD_DEV_PLAN)')
54
+ : '';
55
+ console.log(chalk.green(` Signed in as ${session.email || 'user'} — ${planDisplayName(session.plan)} plan`) +
56
+ src);
57
+ console.log(chalk.gray(` Prompt: ${planIncludesFeature(session.plan, 'prompt') ? 'yes' : 'no'}`));
58
+ if (isTeamOrEnterprise(session.plan)) {
59
+ console.log(chalk.gray(` Org: ${session.orgName || session.orgId || '—'} · role: ${session.role} · sync: enabled`));
60
+ }
61
+ }
62
+ //# sourceMappingURL=entitlements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlements.js","sourceRoot":"","sources":["../../src/auth/entitlements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function openBrowser(url: string): void;
2
+ //# sourceMappingURL=open-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/auth/open-browser.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAiB7C"}