@indigoai-us/hq-cli 5.77.13 → 5.78.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 (307) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/assets/scaffold/core/scripts/archive-old-threads.sh +86 -0
  3. package/assets/scaffold/core/scripts/backfill-company-skill-mirrors.sh +73 -0
  4. package/assets/scaffold/core/scripts/backfill-workspace-mirror.sh +51 -0
  5. package/assets/scaffold/core/scripts/codex-skill-bridge.sh +550 -0
  6. package/assets/scaffold/core/scripts/detect-stale-core-policy-mirror.sh +185 -0
  7. package/assets/scaffold/core/scripts/hq-status-summary.sh +187 -0
  8. package/assets/scaffold/core/scripts/ontology-readme-drift.sh +264 -0
  9. package/assets/scaffold/core/scripts/qmd-reindex-after-sync.sh +93 -0
  10. package/assets/scaffold/core/scripts/rebuild-all-indexes.sh +69 -0
  11. package/assets/scaffold/core/scripts/rebuild-companies-index.sh +206 -0
  12. package/assets/scaffold/core/scripts/rebuild-company-knowledge-index.sh +127 -0
  13. package/assets/scaffold/core/scripts/rebuild-orchestrator-index.sh +86 -0
  14. package/assets/scaffold/core/scripts/rebuild-projects-index.sh +105 -0
  15. package/assets/scaffold/core/scripts/rebuild-public-knowledge-index.sh +83 -0
  16. package/assets/scaffold/core/scripts/rebuild-reports-index.sh +114 -0
  17. package/assets/scaffold/core/scripts/rebuild-social-drafts-index.sh +135 -0
  18. package/assets/scaffold/core/scripts/rebuild-threads-index.sh +82 -0
  19. package/assets/scaffold/core/scripts/rebuild-workers-index.sh +97 -0
  20. package/assets/scaffold/core/scripts/resize-screenshot.sh +47 -0
  21. package/assets/scaffold/core/scripts/token-usage-report.sh +254 -0
  22. package/assets/scaffold/core/scripts/worktree.sh +136 -0
  23. package/dist/commands/agents.js +28 -12
  24. package/dist/commands/api-keys.js +100 -20
  25. package/dist/commands/core.d.ts +90 -0
  26. package/dist/commands/core.js +279 -0
  27. package/dist/commands/files-browse.d.ts +21 -0
  28. package/dist/commands/files-browse.js +145 -24
  29. package/dist/commands/files.js +33 -7
  30. package/dist/commands/members.js +16 -5
  31. package/dist/commands/pack-install.d.ts +14 -0
  32. package/dist/commands/pack-install.js +51 -2
  33. package/dist/commands/pkg-install.js +43 -0
  34. package/dist/commands/run.js +8 -0
  35. package/dist/commands/secrets.js +125 -65
  36. package/dist/main.js +6 -0
  37. package/dist/utils/api-key-command-gate.d.ts +45 -0
  38. package/dist/utils/api-key-command-gate.js +51 -0
  39. package/dist/utils/hq-roots.d.ts +91 -0
  40. package/dist/utils/hq-roots.js +212 -0
  41. package/dist/utils/resolve-vault-credential.d.ts +63 -3
  42. package/dist/utils/resolve-vault-credential.js +152 -6
  43. package/dist/utils/run-bundled-script.d.ts +66 -0
  44. package/dist/utils/run-bundled-script.js +80 -0
  45. package/dist/utils/vault-api.d.ts +21 -0
  46. package/dist/utils/vault-api.js +74 -3
  47. package/package.json +7 -1
  48. package/.claude/policies/hq-cli-interactive-reads-use-sts-vend.md +0 -49
  49. package/.github/workflows/ci.yml +0 -46
  50. package/.github/workflows/publish.yml +0 -36
  51. package/.github/workflows/scripts/smoke-test-pkg.sh +0 -97
  52. package/e2e/cli.test.ts +0 -128
  53. package/eslint.config.js +0 -37
  54. package/pnpm-workspace.yaml +0 -4
  55. package/scripts/chmod-bins.mjs +0 -49
  56. package/scripts/generate-dsn.mjs +0 -26
  57. package/scripts/generate-scan-packages-table.mjs +0 -113
  58. package/scripts/smoke-sources-signals.sh +0 -103
  59. package/src/bin/hq-auth-refresh.ts +0 -43
  60. package/src/cli-version.ts +0 -13
  61. package/src/commands/__fixtures__/make-tar.ts +0 -126
  62. package/src/commands/_patterns.ts +0 -10
  63. package/src/commands/add.ts +0 -75
  64. package/src/commands/agents.test.ts +0 -527
  65. package/src/commands/agents.ts +0 -923
  66. package/src/commands/api-keys.test.ts +0 -291
  67. package/src/commands/api-keys.ts +0 -382
  68. package/src/commands/artifact-verify.test.ts +0 -177
  69. package/src/commands/auth.test.ts +0 -82
  70. package/src/commands/auth.ts +0 -213
  71. package/src/commands/billing.test.ts +0 -158
  72. package/src/commands/billing.ts +0 -146
  73. package/src/commands/channels.test.ts +0 -74
  74. package/src/commands/channels.ts +0 -91
  75. package/src/commands/cloud-demote.test.ts +0 -401
  76. package/src/commands/cloud-demote.ts +0 -278
  77. package/src/commands/cloud-provision.test.ts +0 -1117
  78. package/src/commands/cloud-provision.ts +0 -942
  79. package/src/commands/cloud.pull-all.test.ts +0 -711
  80. package/src/commands/cloud.pull-per-company.test.ts +0 -188
  81. package/src/commands/cloud.push-all.test.ts +0 -485
  82. package/src/commands/cloud.scope-excluded-warning.test.ts +0 -22
  83. package/src/commands/cloud.selectors.test.ts +0 -208
  84. package/src/commands/cloud.status.test.ts +0 -160
  85. package/src/commands/cloud.test.ts +0 -41
  86. package/src/commands/cloud.ts +0 -2130
  87. package/src/commands/company.test.ts +0 -202
  88. package/src/commands/company.ts +0 -148
  89. package/src/commands/creators.test.ts +0 -60
  90. package/src/commands/creators.ts +0 -117
  91. package/src/commands/crm.test.ts +0 -179
  92. package/src/commands/crm.ts +0 -236
  93. package/src/commands/db-migrate.ts +0 -55
  94. package/src/commands/db-provision.ts +0 -114
  95. package/src/commands/db-sql.ts +0 -124
  96. package/src/commands/db-status.ts +0 -108
  97. package/src/commands/db.ts +0 -26
  98. package/src/commands/dm.test.ts +0 -748
  99. package/src/commands/dm.ts +0 -1226
  100. package/src/commands/feedback.test.ts +0 -413
  101. package/src/commands/feedback.ts +0 -169
  102. package/src/commands/files-browse.test.ts +0 -1249
  103. package/src/commands/files-browse.ts +0 -1506
  104. package/src/commands/files-delete.test.ts +0 -484
  105. package/src/commands/files-recovery.test.ts +0 -370
  106. package/src/commands/files.test.ts +0 -722
  107. package/src/commands/files.ts +0 -1446
  108. package/src/commands/group-grants.test.ts +0 -330
  109. package/src/commands/group-grants.ts +0 -455
  110. package/src/commands/groups.test.ts +0 -44
  111. package/src/commands/groups.ts +0 -368
  112. package/src/commands/integrations.test.ts +0 -633
  113. package/src/commands/integrations.ts +0 -507
  114. package/src/commands/list.ts +0 -85
  115. package/src/commands/login.ts +0 -52
  116. package/src/commands/logout.ts +0 -30
  117. package/src/commands/marketplace-install.test.ts +0 -543
  118. package/src/commands/marketplace-security.test.ts +0 -646
  119. package/src/commands/mcp-registration.test.ts +0 -2787
  120. package/src/commands/mcp-registration.ts +0 -2612
  121. package/src/commands/mcp-status.test.ts +0 -483
  122. package/src/commands/mcp-status.ts +0 -575
  123. package/src/commands/mcp-status.us011.test.ts +0 -243
  124. package/src/commands/meetings.test.ts +0 -522
  125. package/src/commands/meetings.ts +0 -789
  126. package/src/commands/members.test.ts +0 -1474
  127. package/src/commands/members.ts +0 -1181
  128. package/src/commands/onboard-identity-guard.test.ts +0 -99
  129. package/src/commands/onboard-identity-guard.ts +0 -103
  130. package/src/commands/onboard-join.test.ts +0 -96
  131. package/src/commands/onboard-join.ts +0 -101
  132. package/src/commands/onboard-warning.test.ts +0 -26
  133. package/src/commands/onboard-warning.ts +0 -12
  134. package/src/commands/onboard.ts +0 -267
  135. package/src/commands/outposts-heartbeat.test.ts +0 -299
  136. package/src/commands/outposts-heartbeat.ts +0 -310
  137. package/src/commands/outposts-replica-sync.test.ts +0 -272
  138. package/src/commands/outposts-self-deploy.test.ts +0 -243
  139. package/src/commands/outposts.test.ts +0 -1039
  140. package/src/commands/outposts.ts +0 -1935
  141. package/src/commands/pack-install-secret-authorization.test.ts +0 -115
  142. package/src/commands/pack-install.test.ts +0 -1469
  143. package/src/commands/pack-install.ts +0 -2247
  144. package/src/commands/pack-update-cache.test.ts +0 -149
  145. package/src/commands/packs.test.ts +0 -88
  146. package/src/commands/packs.ts +0 -622
  147. package/src/commands/people.test.ts +0 -807
  148. package/src/commands/people.ts +0 -422
  149. package/src/commands/pkg-install.dispatch.test.ts +0 -71
  150. package/src/commands/pkg-install.ts +0 -215
  151. package/src/commands/pkg-list.test.ts +0 -79
  152. package/src/commands/pkg-list.ts +0 -13
  153. package/src/commands/pkg-remove.ts +0 -71
  154. package/src/commands/pkg-update.ts +0 -189
  155. package/src/commands/publish.test.ts +0 -650
  156. package/src/commands/publish.ts +0 -580
  157. package/src/commands/reindex.test.ts +0 -259
  158. package/src/commands/reindex.ts +0 -274
  159. package/src/commands/rescue.test.ts +0 -39
  160. package/src/commands/rescue.ts +0 -210
  161. package/src/commands/run.env-local.test.ts +0 -88
  162. package/src/commands/run.test.ts +0 -45
  163. package/src/commands/run.ts +0 -184
  164. package/src/commands/safe-extract.test.ts +0 -459
  165. package/src/commands/safe-extract.ts +0 -444
  166. package/src/commands/secrets-scope.test.ts +0 -56
  167. package/src/commands/secrets-scope.ts +0 -32
  168. package/src/commands/secrets.parse-destination.test.ts +0 -38
  169. package/src/commands/secrets.test.ts +0 -2037
  170. package/src/commands/secrets.ts +0 -2240
  171. package/src/commands/signals.ts +0 -351
  172. package/src/commands/skill.test.ts +0 -770
  173. package/src/commands/skill.ts +0 -796
  174. package/src/commands/sources.ts +0 -362
  175. package/src/commands/sync-mode.test.ts +0 -366
  176. package/src/commands/sync-mode.ts +0 -387
  177. package/src/commands/sync-narrow.test.ts +0 -633
  178. package/src/commands/sync-narrow.ts +0 -555
  179. package/src/commands/sync.ts +0 -165
  180. package/src/commands/team-sync.ts +0 -628
  181. package/src/commands/update.ts +0 -71
  182. package/src/commands/whoami.ts +0 -83
  183. package/src/commands/workers.test.ts +0 -158
  184. package/src/commands/workers.ts +0 -301
  185. package/src/index.test.ts +0 -32
  186. package/src/index.ts +0 -20
  187. package/src/lib/db/control-plane.test.ts +0 -59
  188. package/src/lib/db/control-plane.ts +0 -113
  189. package/src/lib/db/local.test.ts +0 -81
  190. package/src/lib/db/local.ts +0 -148
  191. package/src/lib/db/migrate.test.ts +0 -133
  192. package/src/lib/db/migrate.ts +0 -137
  193. package/src/lib/db/paths.test.ts +0 -112
  194. package/src/lib/db/paths.ts +0 -128
  195. package/src/lib/db/remote-engine.test.ts +0 -44
  196. package/src/lib/db/remote-engine.ts +0 -148
  197. package/src/lib/db/remote-sql.test.ts +0 -32
  198. package/src/lib/db/remote-sql.ts +0 -62
  199. package/src/lib/db/sql.test.ts +0 -106
  200. package/src/lib/db/sql.ts +0 -192
  201. package/src/lib/hq-cloud-dep.smoke.test.ts +0 -75
  202. package/src/lib/local-tree-diff.test.ts +0 -301
  203. package/src/lib/local-tree-diff.ts +0 -362
  204. package/src/lib/narrow-hint-banner.test.ts +0 -235
  205. package/src/lib/narrow-hint-banner.ts +0 -212
  206. package/src/lib/plan-limit-nag.test.ts +0 -317
  207. package/src/lib/plan-limit-nag.ts +0 -264
  208. package/src/main.ts +0 -371
  209. package/src/node-preflight.test.ts +0 -60
  210. package/src/node-preflight.ts +0 -67
  211. package/src/outpost/session-heartbeat-bounds.test.ts +0 -195
  212. package/src/outpost/session-heartbeat-guard.test.ts +0 -105
  213. package/src/outpost/session-heartbeat-publisher.test.ts +0 -178
  214. package/src/outpost/session-heartbeat-publisher.ts +0 -186
  215. package/src/outpost/session-heartbeat-retain-guard.test.ts +0 -126
  216. package/src/outpost/session-heartbeat.test.ts +0 -459
  217. package/src/outpost/session-heartbeat.ts +0 -877
  218. package/src/packaging.test.ts +0 -109
  219. package/src/run/__fixtures__/discover-schemas/example.env.schema +0 -4
  220. package/src/run/discover-schemas.test.ts +0 -153
  221. package/src/run/discover-schemas.ts +0 -79
  222. package/src/run/hq-plugin.test.ts +0 -371
  223. package/src/run/hq-plugin.ts +0 -277
  224. package/src/run/varlock-shape.test.ts +0 -57
  225. package/src/schemas/hq-package.schema.json +0 -155
  226. package/src/sentry-before-send.test.ts +0 -359
  227. package/src/sentry-before-send.ts +0 -221
  228. package/src/sentry-epipe.test.ts +0 -37
  229. package/src/sentry-release.test.ts +0 -54
  230. package/src/sentry.test.ts +0 -24
  231. package/src/sentry.ts +0 -54
  232. package/src/strategies/link.ts +0 -62
  233. package/src/strategies/merge.ts +0 -142
  234. package/src/types.ts +0 -146
  235. package/src/utils/__fixtures__/scan-packages.generated-block.sh +0 -23
  236. package/src/utils/auth-error.test.ts +0 -40
  237. package/src/utils/auth-error.ts +0 -42
  238. package/src/utils/billing-gate.test.ts +0 -95
  239. package/src/utils/billing-gate.ts +0 -228
  240. package/src/utils/breadcrumb-buffer.ts +0 -18
  241. package/src/utils/cli-telemetry.test.ts +0 -153
  242. package/src/utils/cli-telemetry.ts +0 -61
  243. package/src/utils/cognito-session.machine.test.ts +0 -109
  244. package/src/utils/cognito-session.refresh.test.ts +0 -84
  245. package/src/utils/cognito-session.test.ts +0 -328
  246. package/src/utils/cognito-session.ts +0 -448
  247. package/src/utils/company-selection-error.test.ts +0 -42
  248. package/src/utils/company-selection-error.ts +0 -45
  249. package/src/utils/contribution-table.ts +0 -83
  250. package/src/utils/environmental-error.test.ts +0 -45
  251. package/src/utils/environmental-error.ts +0 -39
  252. package/src/utils/epipe.test.ts +0 -28
  253. package/src/utils/epipe.ts +0 -29
  254. package/src/utils/expected-cli-error.test.ts +0 -28
  255. package/src/utils/expected-cli-error.ts +0 -39
  256. package/src/utils/feedback-diagnostics.test.ts +0 -183
  257. package/src/utils/feedback-diagnostics.ts +0 -123
  258. package/src/utils/feedback-screenshots.test.ts +0 -134
  259. package/src/utils/feedback-screenshots.ts +0 -124
  260. package/src/utils/feedback-versions.test.ts +0 -98
  261. package/src/utils/feedback-versions.ts +0 -68
  262. package/src/utils/git.ts +0 -74
  263. package/src/utils/integrity.ts +0 -59
  264. package/src/utils/intercepted-process-exit.test.ts +0 -37
  265. package/src/utils/intercepted-process-exit.ts +0 -36
  266. package/src/utils/login-provider.test.ts +0 -42
  267. package/src/utils/login-provider.ts +0 -30
  268. package/src/utils/manifest.test.ts +0 -167
  269. package/src/utils/manifest.ts +0 -131
  270. package/src/utils/pack-contributions.test.ts +0 -603
  271. package/src/utils/pack-contributions.ts +0 -450
  272. package/src/utils/people.ts +0 -215
  273. package/src/utils/registry-client.ts +0 -204
  274. package/src/utils/registry.ts +0 -90
  275. package/src/utils/resolve-vault-credential.test.ts +0 -69
  276. package/src/utils/resolve-vault-credential.ts +0 -60
  277. package/src/utils/sandbox-runner-client.test.ts +0 -279
  278. package/src/utils/sandbox-runner-client.ts +0 -260
  279. package/src/utils/secrets-cache.ts +0 -183
  280. package/src/utils/sentry-identity.ts +0 -45
  281. package/src/utils/settle-with-timeout.test.ts +0 -21
  282. package/src/utils/settle-with-timeout.ts +0 -22
  283. package/src/utils/user-yaml-error.test.ts +0 -24
  284. package/src/utils/user-yaml-error.ts +0 -30
  285. package/src/utils/vault-api.test.ts +0 -536
  286. package/src/utils/vault-api.ts +0 -382
  287. package/src/utils/version-check.test.ts +0 -176
  288. package/src/utils/version-check.ts +0 -155
  289. package/src/utils/version-gate.test.ts +0 -1024
  290. package/src/utils/version-gate.ts +0 -702
  291. package/test/commands/db-tenant-isolation.test.ts +0 -94
  292. package/test/commands/db.test.ts +0 -85
  293. package/test/commands/signals.test.ts +0 -207
  294. package/test/commands/sources.test.ts +0 -231
  295. package/test/e2e/smoke-install-mcp.sh +0 -113
  296. package/test/fixtures/hq-pack-smoke-mcp/mcp/smoke-http.json +0 -1
  297. package/test/fixtures/hq-pack-smoke-mcp/package.yaml +0 -11
  298. package/test/fixtures/signals/action_item/sample.md +0 -16
  299. package/test/fixtures/signals/summary/sample.md +0 -12
  300. package/test/fixtures/sources/meetings/sample.md +0 -25
  301. package/test/helpers/cli-runner.ts +0 -150
  302. package/test/helpers/s3-list-mock.ts +0 -79
  303. package/test/helpers/vault-service-mock.ts +0 -295
  304. package/test/sources-signals/smoke.test.ts +0 -228
  305. package/tsconfig.json +0 -20
  306. package/vitest.config.ts +0 -11
  307. package/vitest.e2e.config.ts +0 -7
@@ -1,57 +0,0 @@
1
- import { beforeAll, describe, expect, it } from 'vitest';
2
- import { internal } from 'varlock';
3
- // Resolver is a type-only export in varlock@1.0.0's plugin-lib.js (d.ts/JS mismatch);
4
- // the value is extracted at runtime from graph.registeredResolverFunctions below.
5
- import type { Resolver } from 'varlock/plugin-lib';
6
-
7
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
- let RuntimeResolver: typeof Resolver;
9
-
10
- beforeAll(async () => {
11
- // Spin up a minimal graph to access built-in resolvers registered by varlock.
12
- // No schema files are needed — varlock registers built-in resolvers in afterInit.
13
- await internal.loadEnvGraph({
14
- entryFilePaths: [],
15
- afterInit: async (graph) => {
16
- const fns = (graph as any).registeredResolverFunctions as Record<string, unknown>;
17
- const firstClass = Object.values(fns)[0];
18
- if (firstClass == null) throw new Error('registeredResolverFunctions is empty — varlock API shape changed');
19
- // Each registered class extends Resolver; its prototype chain gives us the base class.
20
- RuntimeResolver = Object.getPrototypeOf(firstClass) as typeof Resolver;
21
- },
22
- });
23
- });
24
-
25
- describe('varlock 1.0.0 API shape smoke test', () => {
26
- it('internal.loadEnvGraph is a function', () => {
27
- expect(typeof internal.loadEnvGraph).toBe('function');
28
- });
29
-
30
- it('internal.EnvGraph is a function (class)', () => {
31
- expect(typeof internal.EnvGraph).toBe('function');
32
- });
33
-
34
- it('EnvGraph.prototype.registerRootDecorator exists', () => {
35
- expect(typeof internal.EnvGraph.prototype.registerRootDecorator).toBe('function');
36
- });
37
-
38
- it('EnvGraph.prototype.registerResolver exists', () => {
39
- expect(typeof internal.EnvGraph.prototype.registerResolver).toBe('function');
40
- });
41
-
42
- it('EnvGraph.prototype.registerItemDecorator exists', () => {
43
- expect(typeof internal.EnvGraph.prototype.registerItemDecorator).toBe('function');
44
- });
45
-
46
- it('EnvGraph.prototype.registerDataType exists', () => {
47
- expect(typeof internal.EnvGraph.prototype.registerDataType).toBe('function');
48
- });
49
-
50
- it('Resolver.prototype.process exists', () => {
51
- expect(typeof RuntimeResolver.prototype.process).toBe('function');
52
- });
53
-
54
- it('Resolver.prototype.resolve exists', () => {
55
- expect(typeof RuntimeResolver.prototype.resolve).toBe('function');
56
- });
57
- });
@@ -1,155 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "title": "hq-package.yaml",
4
- "description": "Manifest schema for HQ packages — versioned bundles of workers, commands, skills, and knowledge installable via hq install.",
5
- "type": "object",
6
- "required": ["name", "type", "version", "description", "author", "exposes"],
7
- "additionalProperties": false,
8
- "properties": {
9
- "name": {
10
- "type": "string",
11
- "description": "Package slug — lowercase alphanumeric with hyphens. Used as the registry identifier and install target directory name.",
12
- "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$",
13
- "minLength": 1
14
- },
15
- "type": {
16
- "type": "string",
17
- "description": "Package type. Controls install target routing for all exposes entries.",
18
- "enum": ["worker-pack", "command-set", "skill-bundle", "knowledge-base", "company-template"]
19
- },
20
- "version": {
21
- "type": "string",
22
- "description": "Semver version string for this release.",
23
- "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
24
- },
25
- "minHQVersion": {
26
- "type": "string",
27
- "description": "Minimum HQ version required to install this package. Installer aborts if installed HQ version is below this value.",
28
- "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
29
- },
30
- "description": {
31
- "type": "string",
32
- "description": "Short human-readable description of what this package provides.",
33
- "minLength": 1,
34
- "maxLength": 500
35
- },
36
- "author": {
37
- "type": "string",
38
- "description": "Author name or organization that created and maintains this package.",
39
- "minLength": 1
40
- },
41
- "repo": {
42
- "type": "string",
43
- "description": "Git repository URL for the package source. Used as offline fallback when the registry is unavailable.",
44
- "pattern": "^(https?://|git@|ssh://).+"
45
- },
46
- "requires": {
47
- "type": "object",
48
- "description": "External dependencies this package needs at runtime.",
49
- "additionalProperties": false,
50
- "properties": {
51
- "packages": {
52
- "type": "array",
53
- "description": "HQ package slugs this package depends on. Installed before this package.",
54
- "items": {
55
- "type": "string",
56
- "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$"
57
- },
58
- "uniqueItems": true
59
- },
60
- "services": {
61
- "type": "array",
62
- "description": "Service slugs required at runtime. Installer warns if not configured in the target HQ installation.",
63
- "items": {
64
- "type": "string",
65
- "minLength": 1
66
- },
67
- "uniqueItems": true
68
- }
69
- }
70
- },
71
- "exposes": {
72
- "type": "object",
73
- "description": "Declares what this package installs into the HQ workspace. At least one sub-array must be non-empty.",
74
- "additionalProperties": false,
75
- "properties": {
76
- "workers": {
77
- "type": "array",
78
- "description": "Paths within the tarball to worker.yaml files to install.",
79
- "items": {
80
- "type": "string",
81
- "minLength": 1
82
- },
83
- "uniqueItems": true
84
- },
85
- "commands": {
86
- "type": "array",
87
- "description": "Paths within the tarball to command .md files to install.",
88
- "items": {
89
- "type": "string",
90
- "minLength": 1
91
- },
92
- "uniqueItems": true
93
- },
94
- "skills": {
95
- "type": "array",
96
- "description": "Paths within the tarball to skill .md files to install.",
97
- "items": {
98
- "type": "string",
99
- "minLength": 1
100
- },
101
- "uniqueItems": true
102
- },
103
- "knowledge": {
104
- "type": "array",
105
- "description": "Paths within the tarball to knowledge directories or files to install.",
106
- "items": {
107
- "type": "string",
108
- "minLength": 1
109
- },
110
- "uniqueItems": true
111
- }
112
- }
113
- },
114
- "hooks": {
115
- "type": "object",
116
- "description": "Shell scripts run at install lifecycle events. Each value is a path within the tarball to an executable shell script.",
117
- "additionalProperties": false,
118
- "properties": {
119
- "on-install": {
120
- "type": "string",
121
- "description": "Path to shell script run after all files are installed.",
122
- "minLength": 1
123
- },
124
- "on-update": {
125
- "type": "string",
126
- "description": "Path to shell script run after an existing installation is updated.",
127
- "minLength": 1
128
- },
129
- "on-remove": {
130
- "type": "string",
131
- "description": "Path to shell script run before files are removed from the HQ workspace.",
132
- "minLength": 1
133
- }
134
- }
135
- },
136
- "initialization": {
137
- "type": "object",
138
- "description": "Optional post-install onboarding. `entrypoint` is the pack's primary get-started action (a skill or command that must resolve to one of this package's exposes.skills / exposes.commands entries); HQ surfaces a safe auto-generated 'get started' line from it after install. `prompt` is optional free-text the user can copy/paste into their agent to begin setup — treated as UNTRUSTED instruction text, surfaced only after marketplace injection-scan/moderation (suppressed for non-marketplace installs).",
139
- "additionalProperties": false,
140
- "properties": {
141
- "entrypoint": {
142
- "type": "string",
143
- "minLength": 1,
144
- "description": "Primary get-started action — a skill or command name (with or without a leading slash) that must resolve to a declared exposes.skills / exposes.commands entry."
145
- },
146
- "prompt": {
147
- "type": "string",
148
- "maxLength": 2000,
149
- "description": "Optional copy/paste setup prompt. Untrusted; surfaced only after moderation for marketplace packs, suppressed for local/git installs."
150
- }
151
- },
152
- "required": ["entrypoint"]
153
- }
154
- }
155
- }
@@ -1,359 +0,0 @@
1
- // src/sentry-before-send.test.ts — canonical fleet Vitest suite.
2
- // This file is byte-identical across every consumer repo (no per-repo
3
- // line-1 variation, unlike sentry-before-send.ts). The body-identity
4
- // gate each consumer runs is `diff hq-console/src/sentry-before-send.test.ts
5
- // <consumer>/src/sentry-before-send.test.ts` returns empty (no tail -n +2).
6
- import { describe, expect, it } from "vitest";
7
- import type { ErrorEvent, EventHint } from "@sentry/nextjs";
8
- import { beforeSend } from "./sentry-before-send";
9
-
10
- const REDACTED = "[Filtered]";
11
-
12
- function run(event: ErrorEvent): ErrorEvent {
13
- const result = beforeSend(event, {} as EventHint);
14
- if (!result) throw new Error("beforeSend dropped event unexpectedly");
15
- return result;
16
- }
17
-
18
- describe("scrubHeaders — SENSITIVE_HEADER_NAMES case-insensitive redaction", () => {
19
- const sensitiveHeaders = [
20
- "authorization",
21
- "proxy-authorization",
22
- "cookie",
23
- "set-cookie",
24
- "x-api-key",
25
- "x-auth-token",
26
- "x-access-token",
27
- "x-session-token",
28
- ];
29
-
30
- it.each(sensitiveHeaders)("redacts %s header (and case variants)", (name) => {
31
- const upper = name.toUpperCase();
32
- const out = run({
33
- request: {
34
- headers: { [upper]: "leaky-value", "x-trace-id": "keep-me" },
35
- },
36
- } as unknown as ErrorEvent);
37
- expect((out.request!.headers as Record<string, unknown>)[upper]).toBe(REDACTED);
38
- expect((out.request!.headers as Record<string, unknown>)["x-trace-id"]).toBe("keep-me");
39
- });
40
-
41
- it("redacts a raw Cookie header that lands on request.headers.cookie", () => {
42
- const out = run({
43
- request: {
44
- headers: {
45
- Cookie: "authjs.session-token=abc; other=keep",
46
- "x-trace-id": "keep-me",
47
- },
48
- },
49
- } as unknown as ErrorEvent);
50
- expect((out.request!.headers as Record<string, unknown>).Cookie).toBe(REDACTED);
51
- expect((out.request!.headers as Record<string, unknown>)["x-trace-id"]).toBe("keep-me");
52
- });
53
- });
54
-
55
- describe("scrubCookies — SENSITIVE_COOKIE_NAMES (Auth.js v5 + v4 legacy + Clerk) + raw-string fallback", () => {
56
- // v5 (Auth.js): session / callback-url use __Secure-; csrf-token uses
57
- // __Host- (NOT __Secure-). OAuth-state families (pkce / state / nonce /
58
- // challenge) each pair bare + __Secure-.
59
- const v5Names = [
60
- "authjs.session-token",
61
- "__secure-authjs.session-token",
62
- "authjs.csrf-token",
63
- "__host-authjs.csrf-token",
64
- "authjs.callback-url",
65
- "__secure-authjs.callback-url",
66
- "authjs.pkce.code_verifier",
67
- "__secure-authjs.pkce.code_verifier",
68
- "authjs.state",
69
- "__secure-authjs.state",
70
- "authjs.nonce",
71
- "__secure-authjs.nonce",
72
- "authjs.challenge",
73
- "__secure-authjs.challenge",
74
- ];
75
-
76
- // v4 (NextAuth legacy): same prefix discipline — csrf uses __Host-, others
77
- // use __Secure-. Kept in the set so accidental downgrades / mixed-version
78
- // monorepos don't silently leak.
79
- const v4Names = [
80
- "next-auth.session-token",
81
- "__secure-next-auth.session-token",
82
- "next-auth.csrf-token",
83
- "__host-next-auth.csrf-token",
84
- "next-auth.callback-url",
85
- "__secure-next-auth.callback-url",
86
- "next-auth.pkce.code_verifier",
87
- "__secure-next-auth.pkce.code_verifier",
88
- "next-auth.state",
89
- "__secure-next-auth.state",
90
- ];
91
-
92
- const clerkNames = ["__clerk_db_jwt", "__session"];
93
-
94
- it.each([...v5Names, ...v4Names, ...clerkNames])(
95
- "redacts cookie %s (case-insensitive)",
96
- (name) => {
97
- const out = run({
98
- request: {
99
- cookies: { [name.toUpperCase()]: "secret-session-value", keep_me: "ok" },
100
- },
101
- } as unknown as ErrorEvent);
102
- const cookies = out.request!.cookies as Record<string, unknown>;
103
- expect(cookies[name.toUpperCase()]).toBe(REDACTED);
104
- expect(cookies.keep_me).toBe("ok");
105
- },
106
- );
107
-
108
- it("does NOT include a __Secure-authjs.csrf-token assertion — Auth.js v5 never emits that name (uses __Host- instead)", () => {
109
- // This test is a read-through spec comment: the set MUST NOT have an
110
- // entry for __Secure-authjs.csrf-token. If a maintainer ever adds one
111
- // mechanically-by-pattern, this test documents why it is wrong.
112
- const out = run({
113
- request: {
114
- cookies: { "__Secure-authjs.csrf-token": "does-not-exist-in-prod" },
115
- },
116
- } as unknown as ErrorEvent);
117
- // The value is NOT redacted because the set does not contain that name.
118
- // This is deliberate — see SENSITIVE_COOKIE_NAMES comment in the module.
119
- const cookies = out.request!.cookies as Record<string, unknown>;
120
- expect(cookies["__Secure-authjs.csrf-token"]).toBe("does-not-exist-in-prod");
121
- });
122
-
123
- it("wholesale-redacts a raw-string Cookie header", () => {
124
- const out = run({
125
- request: { cookies: "anything=here; other=keep" },
126
- } as unknown as ErrorEvent);
127
- expect(out.request!.cookies).toBe(REDACTED);
128
- });
129
-
130
- it("leaves undefined cookies alone", () => {
131
- const out = run({ request: { headers: {} } } as unknown as ErrorEvent);
132
- expect(out.request!.cookies).toBeUndefined();
133
- });
134
- });
135
-
136
- describe("scrubFields — recursive redaction with case-insensitivity, arrays, nested, cycles", () => {
137
- it("redacts top-level sensitive field names case-insensitively", () => {
138
- const out = run({
139
- extra: {
140
- token: "abc",
141
- Password: "pw",
142
- APIKEY: "k",
143
- api_key: "k2",
144
- IdToken: "id",
145
- ACCESSTOKEN: "at",
146
- RefreshToken: "rt",
147
- keep: "yes",
148
- },
149
- } as unknown as ErrorEvent);
150
- const extra = out.extra as Record<string, unknown>;
151
- expect(extra.token).toBe(REDACTED);
152
- expect(extra.Password).toBe(REDACTED);
153
- expect(extra.APIKEY).toBe(REDACTED);
154
- expect(extra.api_key).toBe(REDACTED);
155
- expect(extra.IdToken).toBe(REDACTED);
156
- expect(extra.ACCESSTOKEN).toBe(REDACTED);
157
- expect(extra.RefreshToken).toBe(REDACTED);
158
- expect(extra.keep).toBe("yes");
159
- });
160
-
161
- it("recurses into nested objects and arrays", () => {
162
- const out = run({
163
- extra: {
164
- nested: { deeper: { token: "t", safe: 1 } },
165
- items: [{ password: "pw" }, { other: "ok" }],
166
- },
167
- } as unknown as ErrorEvent);
168
- const extra = out.extra as Record<string, any>;
169
- expect(extra.nested.deeper.token).toBe(REDACTED);
170
- expect(extra.nested.deeper.safe).toBe(1);
171
- expect(extra.items[0].password).toBe(REDACTED);
172
- expect(extra.items[1].other).toBe("ok");
173
- });
174
-
175
- it("handles circular references without stack overflow and scrubs fields reachable only through the cycle", () => {
176
- const cyclic: Record<string, unknown> = { token: "leak" };
177
- cyclic.self = cyclic;
178
- const out = run({ extra: { outer: cyclic } } as unknown as ErrorEvent);
179
- const outer = (out.extra as any).outer;
180
- // Top-level field is scrubbed.
181
- expect(outer.token).toBe(REDACTED);
182
- // The Map<original, scrubbed> cycle fix means re-visits return the
183
- // memoized scrubbed copy, not the un-scrubbed original — so
184
- // `outer.self.token` is ALSO [Filtered], not the leaked value.
185
- expect(outer.self.token).toBe(REDACTED);
186
- expect(outer.self).toBe(outer);
187
- });
188
-
189
- it("scalar-string defense-in-depth: redacts embedded credentials in extra.note even when the key is NOT in SENSITIVE_FIELD_NAMES", () => {
190
- const out = run({
191
- extra: { note: "Something broke, password=hunter2 failed" },
192
- } as unknown as ErrorEvent);
193
- const extra = out.extra as Record<string, unknown>;
194
- expect(extra.note).toContain(`password=${REDACTED}`);
195
- expect(extra.note).not.toContain("hunter2");
196
- });
197
-
198
- it("scalar-string defense-in-depth: redacts a Bearer in user.bio (key NOT in SENSITIVE_FIELD_NAMES)", () => {
199
- const out = run({
200
- user: { id: "u1", email: "a@b.c", bio: "authorization: Bearer leak" },
201
- } as unknown as ErrorEvent);
202
- const user = out.user as Record<string, unknown>;
203
- expect(user.id).toBe("u1");
204
- expect(user.email).toBe("a@b.c");
205
- expect(user.bio).toContain(`Bearer ${REDACTED}`);
206
- expect(user.bio).not.toContain("leak");
207
- });
208
- });
209
-
210
- describe("scrubString — regex passes for kv, scheme+credential, JWT triplets", () => {
211
- it("redacts key=value and key: value pairs", () => {
212
- const out = run({
213
- message: "password=hunter2 and api-key: abc123 should be redacted",
214
- } as unknown as ErrorEvent);
215
- expect(out.message).toContain(`password=${REDACTED}`);
216
- expect(out.message).toContain(`api-key:${REDACTED}`);
217
- expect(out.message).not.toContain("hunter2");
218
- expect(out.message).not.toContain("abc123");
219
- });
220
-
221
- it("redacts Bearer / Basic credentials", () => {
222
- const out = run({
223
- message: "Got header Bearer abcDEF._~+/=- and Basic Zm9vOmJhcg==",
224
- } as unknown as ErrorEvent);
225
- expect(out.message).toContain(`Bearer ${REDACTED}`);
226
- expect(out.message).toContain(`Basic ${REDACTED}`);
227
- });
228
-
229
- it("redacts non-JWT-shaped accessToken/refreshToken/id_token values in free text", () => {
230
- const out = run({
231
- message:
232
- "refreshToken=opaqueBase64NotAJwt-xyz and accessToken: anotherOpaqueValue and id_token=short",
233
- } as unknown as ErrorEvent);
234
- expect(out.message).toContain(`refreshToken=${REDACTED}`);
235
- expect(out.message).toContain(`accessToken:${REDACTED}`);
236
- expect(out.message).toContain(`id_token=${REDACTED}`);
237
- expect(out.message).not.toContain("opaqueBase64NotAJwt-xyz");
238
- expect(out.message).not.toContain("anotherOpaqueValue");
239
- expect(out.message).not.toContain("=short");
240
- });
241
-
242
- it("redacts bare JWT triplets", () => {
243
- const jwt = "eyJhbGciOi12345.eyJzdWIiOi67890.sig_abcdef1234";
244
- const out = run({ message: `token was ${jwt} yeah` } as unknown as ErrorEvent);
245
- expect(out.message).not.toContain(jwt);
246
- expect(out.message).toContain(REDACTED);
247
- });
248
- });
249
-
250
- describe("scrubQueryString — parse + fallback", () => {
251
- it("parses well-formed query strings with a leading ? and redacts sensitive keys", () => {
252
- const out = run({
253
- request: {
254
- query_string: "?foo=bar&token=leak&password=pw&keep=me",
255
- },
256
- } as unknown as ErrorEvent);
257
- const qs = out.request!.query_string as string;
258
- expect(qs.startsWith("?")).toBe(true);
259
- expect(qs).toContain("foo=bar");
260
- expect(qs).toContain(`token=${REDACTED}`);
261
- expect(qs).toContain(`password=${REDACTED}`);
262
- expect(qs).toContain("keep=me");
263
- });
264
-
265
- it("parses no-leading-? strings as well", () => {
266
- const out = run({
267
- request: { query_string: "token=leak&keep=1" },
268
- } as unknown as ErrorEvent);
269
- const qs = out.request!.query_string as string;
270
- expect(qs.startsWith("?")).toBe(false);
271
- expect(qs).toContain(`token=${REDACTED}`);
272
- expect(qs).toContain("keep=1");
273
- });
274
-
275
- it("leaves non-string query_string alone", () => {
276
- const out = run({
277
- request: { query_string: undefined },
278
- } as unknown as ErrorEvent);
279
- expect(out.request!.query_string).toBeUndefined();
280
- });
281
- });
282
-
283
- describe("event-level walk — exception.values, message, breadcrumbs, user, extra, contexts, request.data", () => {
284
- it("scrubs exception.values[].value strings", () => {
285
- const out = run({
286
- exception: {
287
- values: [
288
- { type: "Error", value: "password=sekret failed" },
289
- { type: "Error", value: "clean" },
290
- ],
291
- },
292
- } as unknown as ErrorEvent);
293
- expect(out.exception!.values![0].value).toContain(`password=${REDACTED}`);
294
- expect(out.exception!.values![0].value).not.toContain("sekret");
295
- expect(out.exception!.values![1].value).toBe("clean");
296
- });
297
-
298
- it("scrubs event.message", () => {
299
- const out = run({ message: "Bearer leaked.jwt.token" } as unknown as ErrorEvent);
300
- expect(out.message).toContain(`Bearer ${REDACTED}`);
301
- });
302
-
303
- it("scrubs breadcrumbs.message (string) and breadcrumbs.data (structured)", () => {
304
- const out = run({
305
- breadcrumbs: [
306
- {
307
- category: "fetch",
308
- message: "GET /api?token=abc",
309
- data: { url: "/api", password: "leak" },
310
- },
311
- ],
312
- } as unknown as ErrorEvent);
313
- const bc = out.breadcrumbs![0];
314
- expect(bc.message).toContain(`token=${REDACTED}`);
315
- expect((bc.data as Record<string, unknown>).password).toBe(REDACTED);
316
- expect((bc.data as Record<string, unknown>).url).toBe("/api");
317
- });
318
-
319
- it("scrubs event.user fields", () => {
320
- const out = run({
321
- user: { id: "u1", email: "a@b.c", token: "bad", IdToken: "cognito" },
322
- } as unknown as ErrorEvent);
323
- const user = out.user as Record<string, unknown>;
324
- expect(user.id).toBe("u1");
325
- expect(user.email).toBe("a@b.c");
326
- expect(user.token).toBe(REDACTED);
327
- expect(user.IdToken).toBe(REDACTED);
328
- });
329
-
330
- it("scrubs event.extra", () => {
331
- const out = run({ extra: { password: "x", safe: "y" } } as unknown as ErrorEvent);
332
- expect((out.extra as Record<string, unknown>).password).toBe(REDACTED);
333
- expect((out.extra as Record<string, unknown>).safe).toBe("y");
334
- });
335
-
336
- it("scrubs event.contexts", () => {
337
- const out = run({
338
- contexts: {
339
- auth: { token: "x", scheme: "bearer" },
340
- runtime: { name: "node", version: "22" },
341
- },
342
- } as unknown as ErrorEvent);
343
- const auth = (out.contexts as any).auth;
344
- const runtime = (out.contexts as any).runtime;
345
- expect(auth.token).toBe(REDACTED);
346
- expect(auth.scheme).toBe("bearer");
347
- expect(runtime.name).toBe("node");
348
- });
349
-
350
- it("scrubs structured request body via request.data", () => {
351
- const out = run({
352
- request: { data: { username: "u", password: "pw", nested: { token: "t" } } },
353
- } as unknown as ErrorEvent);
354
- const data = out.request!.data as Record<string, any>;
355
- expect(data.username).toBe("u");
356
- expect(data.password).toBe(REDACTED);
357
- expect(data.nested.token).toBe(REDACTED);
358
- });
359
- });