@indigoai-us/hq-cli 5.5.2 → 5.5.3

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 (121) hide show
  1. package/dist/bin/hq-auth-refresh.js +26 -13
  2. package/dist/commands/_patterns.d.ts +3 -0
  3. package/dist/commands/_patterns.js +6 -0
  4. package/dist/commands/add.js +4 -1
  5. package/dist/commands/auth.js +4 -1
  6. package/dist/commands/cloud.js +4 -1
  7. package/dist/commands/groups.d.ts +3 -0
  8. package/dist/commands/groups.js +344 -0
  9. package/dist/commands/list.js +4 -1
  10. package/dist/commands/login.js +4 -1
  11. package/dist/commands/logout.js +4 -1
  12. package/dist/commands/onboard.js +4 -1
  13. package/dist/commands/pack-install.js +4 -1
  14. package/dist/commands/pkg-install.js +4 -1
  15. package/dist/commands/pkg-list.js +4 -1
  16. package/dist/commands/pkg-remove.js +4 -1
  17. package/dist/commands/pkg-update.js +4 -1
  18. package/dist/commands/secrets.d.ts +9 -0
  19. package/dist/commands/secrets.js +263 -25
  20. package/dist/commands/sync.js +4 -1
  21. package/dist/commands/team-sync.js +4 -1
  22. package/dist/commands/update.js +4 -1
  23. package/dist/commands/whoami.js +4 -1
  24. package/dist/index.js +21 -2
  25. package/dist/sentry-before-send.d.ts +3 -0
  26. package/dist/sentry-before-send.js +219 -0
  27. package/dist/sentry-dsn.generated.d.ts +2 -0
  28. package/dist/sentry-dsn.generated.js +5 -0
  29. package/dist/sentry.d.ts +4 -0
  30. package/dist/sentry.js +22 -0
  31. package/dist/strategies/link.js +4 -1
  32. package/dist/strategies/merge.js +4 -1
  33. package/dist/types.js +4 -1
  34. package/dist/utils/cognito-session.js +4 -1
  35. package/dist/utils/git.js +4 -1
  36. package/dist/utils/hq-root.js +4 -1
  37. package/dist/utils/integrity.js +4 -1
  38. package/dist/utils/manifest.js +4 -1
  39. package/dist/utils/registry-client.js +4 -1
  40. package/dist/utils/registry.js +4 -1
  41. package/dist/utils/secrets-cache.js +6 -2
  42. package/package.json +4 -3
  43. package/scripts/generate-dsn.mjs +26 -0
  44. package/src/bin/hq-auth-refresh.ts +23 -16
  45. package/src/commands/_patterns.ts +2 -0
  46. package/src/commands/groups.ts +357 -0
  47. package/src/commands/secrets.ts +306 -26
  48. package/src/index.ts +17 -1
  49. package/src/sentry-before-send.test.ts +359 -0
  50. package/src/sentry-before-send.ts +221 -0
  51. package/src/sentry.test.ts +24 -0
  52. package/src/sentry.ts +19 -0
  53. package/src/utils/secrets-cache.ts +2 -1
  54. package/dist/bin/hq-auth-refresh.d.ts.map +0 -1
  55. package/dist/bin/hq-auth-refresh.js.map +0 -1
  56. package/dist/commands/add.d.ts.map +0 -1
  57. package/dist/commands/add.js.map +0 -1
  58. package/dist/commands/auth.d.ts.map +0 -1
  59. package/dist/commands/auth.js.map +0 -1
  60. package/dist/commands/cloud.d.ts.map +0 -1
  61. package/dist/commands/cloud.js.map +0 -1
  62. package/dist/commands/list.d.ts.map +0 -1
  63. package/dist/commands/list.js.map +0 -1
  64. package/dist/commands/login.d.ts.map +0 -1
  65. package/dist/commands/login.js.map +0 -1
  66. package/dist/commands/logout.d.ts.map +0 -1
  67. package/dist/commands/logout.js.map +0 -1
  68. package/dist/commands/onboard.d.ts.map +0 -1
  69. package/dist/commands/onboard.js.map +0 -1
  70. package/dist/commands/pack-install.d.ts.map +0 -1
  71. package/dist/commands/pack-install.js.map +0 -1
  72. package/dist/commands/pkg-install.d.ts.map +0 -1
  73. package/dist/commands/pkg-install.js.map +0 -1
  74. package/dist/commands/pkg-list.d.ts.map +0 -1
  75. package/dist/commands/pkg-list.js.map +0 -1
  76. package/dist/commands/pkg-remove.d.ts.map +0 -1
  77. package/dist/commands/pkg-remove.js.map +0 -1
  78. package/dist/commands/pkg-update.d.ts.map +0 -1
  79. package/dist/commands/pkg-update.js.map +0 -1
  80. package/dist/commands/secrets.d.ts.map +0 -1
  81. package/dist/commands/secrets.js.map +0 -1
  82. package/dist/commands/sync.d.ts.map +0 -1
  83. package/dist/commands/sync.js.map +0 -1
  84. package/dist/commands/team-sync.d.ts.map +0 -1
  85. package/dist/commands/team-sync.js.map +0 -1
  86. package/dist/commands/update.d.ts.map +0 -1
  87. package/dist/commands/update.js.map +0 -1
  88. package/dist/commands/whoami.d.ts.map +0 -1
  89. package/dist/commands/whoami.js.map +0 -1
  90. package/dist/index.d.ts.map +0 -1
  91. package/dist/index.js.map +0 -1
  92. package/dist/strategies/link.d.ts.map +0 -1
  93. package/dist/strategies/link.js.map +0 -1
  94. package/dist/strategies/merge.d.ts.map +0 -1
  95. package/dist/strategies/merge.js.map +0 -1
  96. package/dist/types.d.ts.map +0 -1
  97. package/dist/types.js.map +0 -1
  98. package/dist/utils/auth.d.ts +0 -27
  99. package/dist/utils/auth.d.ts.map +0 -1
  100. package/dist/utils/auth.js +0 -155
  101. package/dist/utils/auth.js.map +0 -1
  102. package/dist/utils/cognito-session.d.ts.map +0 -1
  103. package/dist/utils/cognito-session.js.map +0 -1
  104. package/dist/utils/git.d.ts.map +0 -1
  105. package/dist/utils/git.js.map +0 -1
  106. package/dist/utils/hq-root.d.ts.map +0 -1
  107. package/dist/utils/hq-root.js.map +0 -1
  108. package/dist/utils/integrity.d.ts.map +0 -1
  109. package/dist/utils/integrity.js.map +0 -1
  110. package/dist/utils/manifest.d.ts.map +0 -1
  111. package/dist/utils/manifest.js.map +0 -1
  112. package/dist/utils/registry-client.d.ts.map +0 -1
  113. package/dist/utils/registry-client.js.map +0 -1
  114. package/dist/utils/registry.d.ts.map +0 -1
  115. package/dist/utils/registry.js.map +0 -1
  116. package/dist/utils/secrets-cache.d.ts.map +0 -1
  117. package/dist/utils/secrets-cache.js.map +0 -1
  118. package/dist/utils/token-store.d.ts +0 -28
  119. package/dist/utils/token-store.d.ts.map +0 -1
  120. package/dist/utils/token-store.js +0 -68
  121. package/dist/utils/token-store.js.map +0 -1
@@ -0,0 +1,219 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d9f4f042-d671-5ca3-8b43-d26395fc0189")}catch(e){}}();
3
+ const SENSITIVE_FIELD_NAMES = new Set([
4
+ "password", "secret", "apikey", "api_key", "token",
5
+ // Cognito token-response fields captured as error context.
6
+ "idtoken", "accesstoken", "refreshtoken",
7
+ ]);
8
+ // Stored lowercased; membership tested against `name.toLowerCase()`.
9
+ // MUST cover BOTH Auth.js v5 (current in hq-console, pinned to
10
+ // next-auth@5.0.0-beta.25 which resolves @auth/core@0.37.2) AND legacy
11
+ // NextAuth v4 name spaces — covering both is cheap and survives accidental
12
+ // downgrades or mixed-version repos. Grounded against @auth/core@0.37.2's
13
+ // src/lib/utils/cookie.ts (re-ground via `grep -nE
14
+ // '(sessionToken|callbackUrl|csrfToken|pkceCodeVerifier|state|nonce|webauthnChallenge): \{'
15
+ // node_modules/.pnpm/@auth+core@0.37.2/node_modules/@auth/core/src/lib/utils/cookie.ts`
16
+ // — seven matches, one per cookie family): two distinct prefixing patterns
17
+ // coexist there, and the entries below mirror BOTH exactly:
18
+ // • session-token / callback-url / pkce.code_verifier / state / nonce /
19
+ // challenge each pair the bare form (HTTP dev, cookiePrefix="") with
20
+ // the __Secure- form (HTTPS prod, cookiePrefix="__Secure-").
21
+ // • csrf-token is special: the source explicitly uses __Host- (NOT
22
+ // __Secure-) under HTTPS for stricter cookie scoping (the csrfToken
23
+ // entry in @auth/core's cookie.ts is the only one whose name template
24
+ // uses `__Host-` instead of `${cookiePrefix}`; the comment above it
25
+ // reads "Default to __Host- for CSRF token for additional protection
26
+ // if using useSecureCookies"). The set therefore pairs the bare form
27
+ // with __Host-, and does NOT include __Secure-authjs.csrf-token
28
+ // because @auth/core never emits that name. The legacy v4 entry mirrors
29
+ // the same pattern (bare next-auth.csrf-token + __Host-next-auth.csrf-token,
30
+ // no __Secure- variant).
31
+ // Missing any of the four OAuth-state families (pkce.code_verifier, state,
32
+ // nonce, challenge) ships a cookie-leak in the same class as the v4-only
33
+ // defect Round-4 called out. This set is the single authoritative spec;
34
+ // all of Steps 3/8/9a/12/13 reproduce it identically.
35
+ //
36
+ // MAINTAINER NOTE: Do NOT extend this set by mechanically pairing every
37
+ // cookie with bare + __Secure- + __Host-. The pairing follows the source:
38
+ // session-style cookies use __Secure-; csrf-style cookies use __Host-.
39
+ // New entries added in the future must be grounded against the actual
40
+ // emitter (Auth.js source for v5/v4, vendor docs for Clerk, etc.) rather
41
+ // than copied from the existing pattern.
42
+ const SENSITIVE_COOKIE_NAMES = new Set([
43
+ // ==== Auth.js v5 (next-auth@5 / @auth/core) ====
44
+ // Session JWT — bare + __Secure-
45
+ "authjs.session-token",
46
+ "__secure-authjs.session-token",
47
+ // CSRF double-submit token — bare + __Host- ONLY (@auth/core's cookie.ts
48
+ // csrfToken entry uses __Host-, never __Secure-)
49
+ "authjs.csrf-token",
50
+ "__host-authjs.csrf-token",
51
+ // Post-auth redirect URL — bare + __Secure-
52
+ "authjs.callback-url",
53
+ "__secure-authjs.callback-url",
54
+ // OAuth PKCE verifier — leaking this enables interception of an in-flight
55
+ // OAuth code exchange.
56
+ "authjs.pkce.code_verifier",
57
+ "__secure-authjs.pkce.code_verifier",
58
+ // OAuth CSRF/replay protection
59
+ "authjs.state",
60
+ "__secure-authjs.state",
61
+ // OpenID Connect nonce — replay protection
62
+ "authjs.nonce",
63
+ "__secure-authjs.nonce",
64
+ // OAuth WebAuthn challenge
65
+ "authjs.challenge",
66
+ "__secure-authjs.challenge",
67
+ // ==== NextAuth v4 legacy names (kept so accidental downgrades /
68
+ // mixed-version monorepos don't silently leak). Same prefix
69
+ // discipline as v5: csrf-token uses __Host-, others use __Secure-. ====
70
+ "next-auth.session-token",
71
+ "__secure-next-auth.session-token",
72
+ "next-auth.csrf-token",
73
+ "__host-next-auth.csrf-token",
74
+ "next-auth.callback-url",
75
+ "__secure-next-auth.callback-url",
76
+ "next-auth.pkce.code_verifier",
77
+ "__secure-next-auth.pkce.code_verifier",
78
+ "next-auth.state",
79
+ "__secure-next-auth.state",
80
+ // ==== Clerk (documented for future; no-op today) ====
81
+ "__clerk_db_jwt", "__session",
82
+ ]);
83
+ const REDACTED = "[Filtered]";
84
+ const SENSITIVE_HEADER_NAMES = new Set([
85
+ "authorization", "proxy-authorization",
86
+ "cookie", "set-cookie",
87
+ "x-api-key", "x-auth-token", "x-access-token", "x-session-token",
88
+ ]);
89
+ function scrubHeaders(h) {
90
+ if (!h)
91
+ return h;
92
+ const out = {};
93
+ for (const [k, v] of Object.entries(h)) {
94
+ out[k] = SENSITIVE_HEADER_NAMES.has(k.toLowerCase()) ? REDACTED : v;
95
+ }
96
+ return out;
97
+ }
98
+ function scrubCookies(c) {
99
+ if (!c)
100
+ return c;
101
+ if (typeof c === "string")
102
+ return REDACTED; // raw Cookie header — wholesale redact
103
+ const out = {};
104
+ for (const [k, v] of Object.entries(c)) {
105
+ out[k] = SENSITIVE_COOKIE_NAMES.has(k.toLowerCase()) ? REDACTED : v;
106
+ }
107
+ return out;
108
+ }
109
+ const SENSITIVE_STRING_PATTERNS = [
110
+ // kv pairs; `(?:id|access|refresh)[_-]?token` catches Cognito-style free-text
111
+ // `accessToken=...`, `refreshToken: ...`, `id_token=...` which bare `\btoken` misses.
112
+ /\b(password|secret|api[_-]?key|(?:id|access|refresh)[_-]?token|token)\s*[:=]\s*[^\s&"'<>]+/gi,
113
+ /\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]+/gi,
114
+ /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,
115
+ ];
116
+ function scrubString(s) {
117
+ let out = s;
118
+ for (const re of SENSITIVE_STRING_PATTERNS) {
119
+ out = out.replace(re, (m) => {
120
+ const sep = m.search(/[:=\s]/);
121
+ return sep > 0 ? `${m.slice(0, sep + 1)}${REDACTED}` : REDACTED;
122
+ });
123
+ }
124
+ return out;
125
+ }
126
+ function scrubQueryString(qs) {
127
+ try {
128
+ const params = new URLSearchParams(qs.startsWith("?") ? qs.slice(1) : qs);
129
+ const out = [];
130
+ for (const [k, v] of params) {
131
+ out.push(`${k}=${SENSITIVE_FIELD_NAMES.has(k.toLowerCase()) ? REDACTED : v}`);
132
+ }
133
+ const joined = out.join("&");
134
+ return qs.startsWith("?") ? `?${joined}` : joined;
135
+ }
136
+ catch {
137
+ return scrubString(qs);
138
+ }
139
+ }
140
+ function scrubFields(value, memo = new Map()) {
141
+ if (value === null || typeof value !== "object")
142
+ return value;
143
+ const obj = value;
144
+ // On cycle revisit, return the SAME scrubbed copy built on first visit —
145
+ // NOT the original. Returning the original would leak fields reachable
146
+ // only through the cycle (e.g., a.self.token).
147
+ if (memo.has(obj))
148
+ return memo.get(obj);
149
+ if (Array.isArray(value)) {
150
+ const arr = [];
151
+ memo.set(obj, arr);
152
+ for (const v of value)
153
+ arr.push(scrubFields(v, memo));
154
+ return arr;
155
+ }
156
+ const out = {};
157
+ memo.set(obj, out);
158
+ for (const [k, v] of Object.entries(value)) {
159
+ if (SENSITIVE_FIELD_NAMES.has(k.toLowerCase())) {
160
+ out[k] = REDACTED;
161
+ }
162
+ else if (v !== null && typeof v === "object") {
163
+ out[k] = scrubFields(v, memo);
164
+ }
165
+ else if (typeof v === "string") {
166
+ // SCALAR-STRING DEFENSE-IN-DEPTH. A stringified log line stashed via
167
+ // setExtra / setContext / setUser can embed `password=...` or a Bearer
168
+ // token even when the outer key (`note`, `bio`, `log_line`, …) isn't
169
+ // in SENSITIVE_FIELD_NAMES. Route scalar strings through scrubString so
170
+ // these don't bypass the scrubber on their way into Sentry.
171
+ out[k] = scrubString(v);
172
+ }
173
+ else {
174
+ out[k] = v;
175
+ }
176
+ }
177
+ return out;
178
+ }
179
+ export function beforeSend(event, _hint) {
180
+ if (event.request) {
181
+ const req = event.request;
182
+ event.request = {
183
+ ...event.request,
184
+ headers: scrubHeaders(req.headers),
185
+ cookies: scrubCookies(req.cookies),
186
+ data: scrubFields(req.data),
187
+ query_string: typeof req.query_string === "string"
188
+ ? scrubQueryString(req.query_string)
189
+ : req.query_string,
190
+ };
191
+ }
192
+ if (typeof event.message === "string")
193
+ event.message = scrubString(event.message);
194
+ if (event.exception?.values) {
195
+ event.exception = {
196
+ ...event.exception,
197
+ values: event.exception.values.map((v) => ({
198
+ ...v,
199
+ value: typeof v.value === "string" ? scrubString(v.value) : v.value,
200
+ })),
201
+ };
202
+ }
203
+ if (event.user)
204
+ event.user = scrubFields(event.user);
205
+ if (event.breadcrumbs) {
206
+ event.breadcrumbs = event.breadcrumbs.map((b) => ({
207
+ ...b,
208
+ message: typeof b.message === "string" ? scrubString(b.message) : b.message,
209
+ data: b.data ? scrubFields(b.data) : b.data,
210
+ }));
211
+ }
212
+ if (event.extra)
213
+ event.extra = scrubFields(event.extra);
214
+ if (event.contexts)
215
+ event.contexts = scrubFields(event.contexts);
216
+ return event;
217
+ }
218
+ //# sourceMappingURL=sentry-before-send.js.map
219
+ //# debugId=d9f4f042-d671-5ca3-8b43-d26395fc0189
@@ -0,0 +1,2 @@
1
+ export declare const BUNDLED_DSN = "https://ed8c1f7624b67945b43d485bbf98d0f7@o4507292345892864.ingest.us.sentry.io/4511263744786432";
2
+ //# sourceMappingURL=sentry-dsn.generated.d.ts.map
@@ -0,0 +1,5 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="55f2362e-5cf7-5dac-b6a3-ef0f9ccde645")}catch(e){}}();
3
+ export const BUNDLED_DSN = "https://ed8c1f7624b67945b43d485bbf98d0f7@o4507292345892864.ingest.us.sentry.io/4511263744786432";
4
+ //# sourceMappingURL=sentry-dsn.generated.js.map
5
+ //# debugId=55f2362e-5cf7-5dac-b6a3-ef0f9ccde645
@@ -0,0 +1,4 @@
1
+ import * as Sentry from "@sentry/node";
2
+ export declare function initSentry(): void;
3
+ export { Sentry };
4
+ //# sourceMappingURL=sentry.d.ts.map
package/dist/sentry.js ADDED
@@ -0,0 +1,22 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9a31fb53-8cc1-5394-ac16-e96b82fa6caa")}catch(e){}}();
3
+ import * as Sentry from "@sentry/node";
4
+ import { BUNDLED_DSN } from "./sentry-dsn.generated.js";
5
+ import { beforeSend } from "./sentry-before-send.js";
6
+ export function initSentry() {
7
+ const dsn = BUNDLED_DSN || process.env.SENTRY_DSN;
8
+ if (!dsn)
9
+ return;
10
+ Sentry.init({
11
+ dsn,
12
+ release: `hq-cli@${process.env.npm_package_version ?? "0.0.0"}`,
13
+ environment: process.env.HQ_CLI_ENV ?? "production",
14
+ initialScope: {
15
+ tags: { repo: "hq-cli" },
16
+ },
17
+ beforeSend,
18
+ });
19
+ }
20
+ export { Sentry };
21
+ //# sourceMappingURL=sentry.js.map
22
+ //# debugId=9a31fb53-8cc1-5394-ac16-e96b82fa6caa
@@ -2,6 +2,8 @@
2
2
  * Link Sync Strategy (US-006)
3
3
  * Symlinks module paths into HQ tree
4
4
  */
5
+
6
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="602c865a-033c-5b7c-8839-11a66b9a6bc5")}catch(e){}}();
5
7
  import * as fs from 'fs';
6
8
  import * as path from 'path';
7
9
  export async function linkSync(module, moduleDir, hqRoot) {
@@ -48,4 +50,5 @@ export async function linkSync(module, moduleDir, hqRoot) {
48
50
  filesChanged,
49
51
  };
50
52
  }
51
- //# sourceMappingURL=link.js.map
53
+ //# sourceMappingURL=link.js.map
54
+ //# debugId=602c865a-033c-5b7c-8839-11a66b9a6bc5
@@ -2,6 +2,8 @@
2
2
  * Merge Sync Strategy (US-007)
3
3
  * Copies files from module into HQ, tracks state for conflict detection
4
4
  */
5
+
6
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7a161796-4e72-58d8-89f3-a1010add7d0f")}catch(e){}}();
5
7
  import * as fs from 'fs';
6
8
  import * as path from 'path';
7
9
  import * as crypto from 'crypto';
@@ -107,4 +109,5 @@ export async function mergeSync(module, moduleDir, hqRoot) {
107
109
  filesChanged: filesChanged.count,
108
110
  };
109
111
  }
110
- //# sourceMappingURL=merge.js.map
112
+ //# sourceMappingURL=merge.js.map
113
+ //# debugId=7a161796-4e72-58d8-89f3-a1010add7d0f
package/dist/types.js CHANGED
@@ -7,5 +7,8 @@
7
7
  * (new in hq-core v12.0.0; see
8
8
  * knowledge/public/hq-core/package-yaml-spec.md)
9
9
  */
10
+
11
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="42a2c1bd-8924-5fcf-8f50-72086dab7a97")}catch(e){}}();
10
12
  export {};
11
- //# sourceMappingURL=types.js.map
13
+ //# sourceMappingURL=types.js.map
14
+ //# debugId=42a2c1bd-8924-5fcf-8f50-72086dab7a97
@@ -16,6 +16,8 @@
16
16
  * HQ_COGNITO_CALLBACK_PORT — Loopback OAuth callback port
17
17
  * HQ_VAULT_API_URL — vault-service API Gateway URL
18
18
  */
19
+
20
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="95513873-e956-5318-8115-e2088c581155")}catch(e){}}();
19
21
  import * as os from "os";
20
22
  import * as path from "path";
21
23
  import chalk from "chalk";
@@ -96,4 +98,5 @@ export async function refreshCachedSession() {
96
98
  };
97
99
  }
98
100
  }
99
- //# sourceMappingURL=cognito-session.js.map
101
+ //# sourceMappingURL=cognito-session.js.map
102
+ //# debugId=95513873-e956-5318-8115-e2088c581155
package/dist/utils/git.js CHANGED
@@ -1,3 +1,5 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6ee15d43-ad5e-5f40-b27b-8bd389e0dad7")}catch(e){}}();
1
3
  import * as fs from 'fs';
2
4
  import * as path from 'path';
3
5
  import simpleGit from 'simple-git';
@@ -67,4 +69,5 @@ export function ensureGitignore(hqRoot, entry) {
67
69
  fs.writeFileSync(gitignorePath, content);
68
70
  }
69
71
  }
70
- //# sourceMappingURL=git.js.map
72
+ //# sourceMappingURL=git.js.map
73
+ //# debugId=6ee15d43-ad5e-5f40-b27b-8bd389e0dad7
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * HQ root detection — walks up from cwd looking for HQ markers (US-004)
3
3
  */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="aebb967b-5f70-5107-9d81-bb495be1c405")}catch(e){}}();
4
6
  import * as fs from 'fs';
5
7
  import * as path from 'path';
6
8
  /**
@@ -19,4 +21,5 @@ export function findHqRoot() {
19
21
  }
20
22
  throw new Error('Could not find HQ root. Run this command from within your HQ directory.');
21
23
  }
22
- //# sourceMappingURL=hq-root.js.map
24
+ //# sourceMappingURL=hq-root.js.map
25
+ //# debugId=aebb967b-5f70-5107-9d81-bb495be1c405
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Integrity verification — SHA256 hash and RSA signature checks (US-005)
3
3
  */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="19765c32-6c3d-5477-bf80-0f7d08197d29")}catch(e){}}();
4
6
  import * as crypto from 'crypto';
5
7
  import * as fs from 'fs';
6
8
  import * as path from 'path';
@@ -37,4 +39,5 @@ export function verifyRsaSignature(sha256Hash, signature, publicKeyPath) {
37
39
  verifier.end();
38
40
  return verifier.verify(publicKey, Buffer.from(signature, 'base64'));
39
41
  }
40
- //# sourceMappingURL=integrity.js.map
42
+ //# sourceMappingURL=integrity.js.map
43
+ //# debugId=19765c32-6c3d-5477-bf80-0f7d08197d29
@@ -1,3 +1,5 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ea38913d-4086-56ca-872a-9a85ccf9c453")}catch(e){}}();
1
3
  import * as fs from 'fs';
2
4
  import * as path from 'path';
3
5
  import * as yaml from 'js-yaml';
@@ -112,4 +114,5 @@ export function parseRepoName(repoUrl) {
112
114
  export function isValidRepoUrl(url) {
113
115
  return url.startsWith('https://') || url.startsWith('git@');
114
116
  }
115
- //# sourceMappingURL=manifest.js.map
117
+ //# sourceMappingURL=manifest.js.map
118
+ //# debugId=ea38913d-4086-56ca-872a-9a85ccf9c453
@@ -4,6 +4,8 @@
4
4
  *
5
5
  * Auth tokens are NEVER written to stdout or logs.
6
6
  */
7
+
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ffe2dc58-fb20-5566-a56c-1b1c26999bba")}catch(e){}}();
7
9
  import * as fs from 'fs';
8
10
  import * as path from 'path';
9
11
  import * as yaml from 'js-yaml';
@@ -99,4 +101,5 @@ export class RegistryClient {
99
101
  return this.request('GET', `/packages/${encodeURIComponent(slug)}/download${qs ? `?${qs}` : ''}`, { auth: true });
100
102
  }
101
103
  }
102
- //# sourceMappingURL=registry-client.js.map
104
+ //# sourceMappingURL=registry-client.js.map
105
+ //# debugId=ffe2dc58-fb20-5566-a56c-1b1c26999bba
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Registry YAML helpers — read/write packages/registry.yaml (US-005)
3
3
  */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3fb6a06d-7cbe-5764-be4f-6c8189de649c")}catch(e){}}();
4
6
  import * as fs from 'fs';
5
7
  import * as path from 'path';
6
8
  import * as yaml from 'js-yaml';
@@ -55,4 +57,5 @@ export function removeFromRegistry(hqRoot, slug) {
55
57
  const entries = readRegistry(hqRoot).filter((e) => e.slug !== slug);
56
58
  writeRegistry(hqRoot, entries);
57
59
  }
58
- //# sourceMappingURL=registry.js.map
60
+ //# sourceMappingURL=registry.js.map
61
+ //# debugId=3fb6a06d-7cbe-5764-be4f-6c8189de649c
@@ -1,3 +1,5 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="263d7b10-622e-56c3-8c82-ebb294510b1b")}catch(e){}}();
1
3
  import * as crypto from "node:crypto";
2
4
  import * as fs from "node:fs";
3
5
  import * as path from "node:path";
@@ -15,7 +17,7 @@ function ensureCacheDir(companyUid) {
15
17
  function validateInputs(companyUid, name) {
16
18
  if (!companyUid || companyUid.includes("/") || companyUid.includes(".."))
17
19
  return false;
18
- if (!/^[A-Z][A-Z0-9_]*$/.test(name))
20
+ if (!/^[A-Z][A-Z0-9_]*(?:\/[A-Z][A-Z0-9_]+)*$/.test(name))
19
21
  return false;
20
22
  return true;
21
23
  }
@@ -101,6 +103,7 @@ export function writeCache(companyUid, name, value) {
101
103
  timestamp.writeBigInt64BE(BigInt(Date.now()));
102
104
  const out = Buffer.concat([timestamp, iv, authTag, encrypted]);
103
105
  const filePath = path.join(CACHE_DIR, companyUid, name);
106
+ fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
104
107
  const tmpPath = `${filePath}.tmp.${process.pid}`;
105
108
  fs.writeFileSync(tmpPath, out, { mode: 0o600 });
106
109
  fs.renameSync(tmpPath, filePath);
@@ -131,4 +134,5 @@ export function clearAllCache() {
131
134
  }
132
135
  return { removed };
133
136
  }
134
- //# sourceMappingURL=secrets-cache.js.map
137
+ //# sourceMappingURL=secrets-cache.js.map
138
+ //# debugId=263d7b10-622e-56c3-8c82-ebb294510b1b
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.5.2",
3
+ "version": "5.5.3",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -8,14 +8,15 @@
8
8
  "hq-auth-refresh": "dist/bin/hq-auth-refresh.js"
9
9
  },
10
10
  "scripts": {
11
- "build": "tsc",
11
+ "build": "node scripts/generate-dsn.mjs && tsc",
12
12
  "typecheck": "tsc --noEmit",
13
13
  "test": "vitest run",
14
14
  "clean": "rm -rf dist"
15
15
  },
16
16
  "dependencies": {
17
+ "@sentry/node": "^10.49.0",
17
18
  "@indigoai-us/hq-cloud": "^5.1.0",
18
- "@indigoai-us/hq-onboarding": "^0.1.1",
19
+ "@indigoai-us/hq-onboarding": "^0.1.0",
19
20
  "chalk": "^5.3.0",
20
21
  "commander": "^12.1.0",
21
22
  "js-yaml": "^4.1.0",
@@ -0,0 +1,26 @@
1
+ import { writeFileSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+
7
+ const isGitHubActions = process.env.GITHUB_ACTIONS === "true";
8
+ const isPublishJob = process.env.GITHUB_JOB === "publish";
9
+ const dsn = process.env.HQ_CLI_PUBLISH_SENTRY_DSN ?? "";
10
+
11
+ if (isGitHubActions && isPublishJob && !dsn) {
12
+ process.stderr.write(
13
+ "[generate-dsn] FATAL: GITHUB_ACTIONS=true, GITHUB_JOB=publish, " +
14
+ "but HQ_CLI_PUBLISH_SENTRY_DSN is not set. " +
15
+ "Add the repo secret HQ_CLI_PUBLISH_SENTRY_DSN before publishing.\n",
16
+ );
17
+ process.exit(1);
18
+ }
19
+
20
+ const outPath = join(__dirname, "../src/sentry-dsn.generated.ts");
21
+ const content = `export const BUNDLED_DSN = "${dsn}";\n`;
22
+
23
+ writeFileSync(outPath, content, "utf8");
24
+ process.stdout.write(
25
+ `[generate-dsn] Wrote BUNDLED_DSN="${dsn ? "[DSN set]" : ""}" to ${outPath}\n`,
26
+ );
@@ -11,22 +11,29 @@
11
11
  * Writes the refreshed tokens to ~/.hq/cognito-tokens.json.
12
12
  */
13
13
 
14
+ import { initSentry, Sentry } from "../sentry.js";
14
15
  import { refreshCachedSession } from "../utils/cognito-session.js";
15
16
 
16
- async function main(): Promise<void> {
17
- const result = await refreshCachedSession();
18
- if (result.refreshed) {
19
- process.exit(0);
20
- }
21
- if (result.reason) {
22
- process.stderr.write(`hq-auth-refresh: ${result.reason}\n`);
23
- }
24
- process.exit(1);
25
- }
17
+ initSentry();
26
18
 
27
- main().catch((err) => {
28
- process.stderr.write(
29
- `hq-auth-refresh: ${err instanceof Error ? err.message : String(err)}\n`,
30
- );
31
- process.exit(1);
32
- });
19
+ (async () => {
20
+ let exitCode = 1;
21
+ try {
22
+ const result = await refreshCachedSession();
23
+ if (result.refreshed) {
24
+ exitCode = 0;
25
+ } else {
26
+ if (result.reason) {
27
+ process.stderr.write(`hq-auth-refresh: ${result.reason}\n`);
28
+ }
29
+ }
30
+ } catch (err) {
31
+ Sentry.captureException(err);
32
+ process.stderr.write(
33
+ `hq-auth-refresh: ${err instanceof Error ? err.message : String(err)}\n`,
34
+ );
35
+ } finally {
36
+ await Sentry.flush(2000);
37
+ process.exit(exitCode);
38
+ }
39
+ })();
@@ -0,0 +1,2 @@
1
+ export const SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*(?:\/[A-Z][A-Z0-9_]+)*$/;
2
+ export const GROUP_ID_PATTERN = /^grp_[A-Za-z0-9_-]+$/;