@indigoai-us/hq-cli 5.77.14 → 5.79.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 (309) hide show
  1. package/CHANGELOG.md +31 -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/meetings.js +16 -9
  31. package/dist/commands/members.js +16 -5
  32. package/dist/commands/pack-install.d.ts +14 -0
  33. package/dist/commands/pack-install.js +42 -2
  34. package/dist/commands/pkg-install.js +39 -2
  35. package/dist/commands/run.js +6 -2
  36. package/dist/commands/secrets.js +120 -65
  37. package/dist/main.js +6 -0
  38. package/dist/utils/api-key-command-gate.d.ts +45 -0
  39. package/dist/utils/api-key-command-gate.js +51 -0
  40. package/dist/utils/hq-roots.d.ts +91 -0
  41. package/dist/utils/hq-roots.js +212 -0
  42. package/dist/utils/resolve-vault-credential.d.ts +63 -3
  43. package/dist/utils/resolve-vault-credential.js +152 -6
  44. package/dist/utils/run-bundled-script.d.ts +66 -0
  45. package/dist/utils/run-bundled-script.js +80 -0
  46. package/dist/utils/vault-api.d.ts +21 -0
  47. package/dist/utils/vault-api.js +74 -3
  48. package/package.json +7 -1
  49. package/.claude/policies/hq-cli-interactive-reads-use-sts-vend.md +0 -49
  50. package/.github/workflows/ci.yml +0 -46
  51. package/.github/workflows/publish.yml +0 -36
  52. package/.github/workflows/scripts/smoke-test-pkg.sh +0 -97
  53. package/e2e/cli.test.ts +0 -128
  54. package/eslint.config.js +0 -37
  55. package/pnpm-workspace.yaml +0 -4
  56. package/scripts/chmod-bins.mjs +0 -49
  57. package/scripts/generate-dsn.mjs +0 -26
  58. package/scripts/generate-scan-packages-table.mjs +0 -113
  59. package/scripts/smoke-sources-signals.sh +0 -103
  60. package/src/bin/hq-auth-refresh.ts +0 -43
  61. package/src/cli-version.ts +0 -13
  62. package/src/commands/__fixtures__/make-tar.ts +0 -126
  63. package/src/commands/_patterns.ts +0 -10
  64. package/src/commands/add.ts +0 -75
  65. package/src/commands/agents.test.ts +0 -527
  66. package/src/commands/agents.ts +0 -923
  67. package/src/commands/api-keys.test.ts +0 -291
  68. package/src/commands/api-keys.ts +0 -382
  69. package/src/commands/artifact-verify.test.ts +0 -177
  70. package/src/commands/auth.test.ts +0 -82
  71. package/src/commands/auth.ts +0 -213
  72. package/src/commands/billing.test.ts +0 -158
  73. package/src/commands/billing.ts +0 -146
  74. package/src/commands/channels.test.ts +0 -74
  75. package/src/commands/channels.ts +0 -91
  76. package/src/commands/cloud-demote.test.ts +0 -401
  77. package/src/commands/cloud-demote.ts +0 -278
  78. package/src/commands/cloud-provision.test.ts +0 -1117
  79. package/src/commands/cloud-provision.ts +0 -942
  80. package/src/commands/cloud.pull-all.test.ts +0 -711
  81. package/src/commands/cloud.pull-per-company.test.ts +0 -188
  82. package/src/commands/cloud.push-all.test.ts +0 -485
  83. package/src/commands/cloud.scope-excluded-warning.test.ts +0 -22
  84. package/src/commands/cloud.selectors.test.ts +0 -208
  85. package/src/commands/cloud.status.test.ts +0 -160
  86. package/src/commands/cloud.test.ts +0 -41
  87. package/src/commands/cloud.ts +0 -2130
  88. package/src/commands/company.test.ts +0 -202
  89. package/src/commands/company.ts +0 -148
  90. package/src/commands/creators.test.ts +0 -60
  91. package/src/commands/creators.ts +0 -117
  92. package/src/commands/crm.test.ts +0 -179
  93. package/src/commands/crm.ts +0 -236
  94. package/src/commands/db-migrate.ts +0 -55
  95. package/src/commands/db-provision.ts +0 -114
  96. package/src/commands/db-sql.ts +0 -124
  97. package/src/commands/db-status.ts +0 -108
  98. package/src/commands/db.ts +0 -26
  99. package/src/commands/dm.test.ts +0 -748
  100. package/src/commands/dm.ts +0 -1226
  101. package/src/commands/feedback.test.ts +0 -413
  102. package/src/commands/feedback.ts +0 -169
  103. package/src/commands/files-browse.test.ts +0 -1249
  104. package/src/commands/files-browse.ts +0 -1506
  105. package/src/commands/files-delete.test.ts +0 -484
  106. package/src/commands/files-recovery.test.ts +0 -370
  107. package/src/commands/files.test.ts +0 -722
  108. package/src/commands/files.ts +0 -1446
  109. package/src/commands/group-grants.test.ts +0 -330
  110. package/src/commands/group-grants.ts +0 -455
  111. package/src/commands/groups.test.ts +0 -44
  112. package/src/commands/groups.ts +0 -368
  113. package/src/commands/integrations.test.ts +0 -633
  114. package/src/commands/integrations.ts +0 -507
  115. package/src/commands/list.ts +0 -85
  116. package/src/commands/login.ts +0 -52
  117. package/src/commands/logout.ts +0 -30
  118. package/src/commands/marketplace-install.test.ts +0 -543
  119. package/src/commands/marketplace-security.test.ts +0 -646
  120. package/src/commands/mcp-registration.test.ts +0 -2787
  121. package/src/commands/mcp-registration.ts +0 -2612
  122. package/src/commands/mcp-status.test.ts +0 -483
  123. package/src/commands/mcp-status.ts +0 -575
  124. package/src/commands/mcp-status.us011.test.ts +0 -243
  125. package/src/commands/meetings.test.ts +0 -522
  126. package/src/commands/meetings.ts +0 -789
  127. package/src/commands/members.test.ts +0 -1474
  128. package/src/commands/members.ts +0 -1181
  129. package/src/commands/onboard-identity-guard.test.ts +0 -99
  130. package/src/commands/onboard-identity-guard.ts +0 -103
  131. package/src/commands/onboard-join.test.ts +0 -96
  132. package/src/commands/onboard-join.ts +0 -101
  133. package/src/commands/onboard-warning.test.ts +0 -26
  134. package/src/commands/onboard-warning.ts +0 -12
  135. package/src/commands/onboard.ts +0 -267
  136. package/src/commands/outposts-heartbeat.test.ts +0 -299
  137. package/src/commands/outposts-heartbeat.ts +0 -310
  138. package/src/commands/outposts-replica-sync.test.ts +0 -272
  139. package/src/commands/outposts-self-deploy.test.ts +0 -243
  140. package/src/commands/outposts.test.ts +0 -1039
  141. package/src/commands/outposts.ts +0 -1935
  142. package/src/commands/pack-install-secret-authorization.test.ts +0 -115
  143. package/src/commands/pack-install.test.ts +0 -1469
  144. package/src/commands/pack-install.ts +0 -2256
  145. package/src/commands/pack-update-cache.test.ts +0 -149
  146. package/src/commands/packs-update-api-key.test.ts +0 -105
  147. package/src/commands/packs.test.ts +0 -88
  148. package/src/commands/packs.ts +0 -622
  149. package/src/commands/people.test.ts +0 -807
  150. package/src/commands/people.ts +0 -422
  151. package/src/commands/pkg-install.dispatch.test.ts +0 -103
  152. package/src/commands/pkg-install.ts +0 -221
  153. package/src/commands/pkg-list.test.ts +0 -79
  154. package/src/commands/pkg-list.ts +0 -13
  155. package/src/commands/pkg-remove.ts +0 -71
  156. package/src/commands/pkg-update.ts +0 -189
  157. package/src/commands/publish.test.ts +0 -650
  158. package/src/commands/publish.ts +0 -580
  159. package/src/commands/reindex.test.ts +0 -259
  160. package/src/commands/reindex.ts +0 -274
  161. package/src/commands/rescue.test.ts +0 -39
  162. package/src/commands/rescue.ts +0 -210
  163. package/src/commands/run.env-local.test.ts +0 -88
  164. package/src/commands/run.test.ts +0 -45
  165. package/src/commands/run.ts +0 -190
  166. package/src/commands/safe-extract.test.ts +0 -459
  167. package/src/commands/safe-extract.ts +0 -444
  168. package/src/commands/secrets-scope.test.ts +0 -56
  169. package/src/commands/secrets-scope.ts +0 -32
  170. package/src/commands/secrets.parse-destination.test.ts +0 -38
  171. package/src/commands/secrets.test.ts +0 -2050
  172. package/src/commands/secrets.ts +0 -2249
  173. package/src/commands/signals.ts +0 -351
  174. package/src/commands/skill.test.ts +0 -770
  175. package/src/commands/skill.ts +0 -796
  176. package/src/commands/sources.ts +0 -362
  177. package/src/commands/sync-mode.test.ts +0 -366
  178. package/src/commands/sync-mode.ts +0 -387
  179. package/src/commands/sync-narrow.test.ts +0 -633
  180. package/src/commands/sync-narrow.ts +0 -555
  181. package/src/commands/sync.ts +0 -165
  182. package/src/commands/team-sync.ts +0 -628
  183. package/src/commands/update.ts +0 -71
  184. package/src/commands/whoami.ts +0 -83
  185. package/src/commands/workers.test.ts +0 -158
  186. package/src/commands/workers.ts +0 -301
  187. package/src/index.test.ts +0 -32
  188. package/src/index.ts +0 -20
  189. package/src/lib/db/control-plane.test.ts +0 -59
  190. package/src/lib/db/control-plane.ts +0 -113
  191. package/src/lib/db/local.test.ts +0 -81
  192. package/src/lib/db/local.ts +0 -148
  193. package/src/lib/db/migrate.test.ts +0 -133
  194. package/src/lib/db/migrate.ts +0 -137
  195. package/src/lib/db/paths.test.ts +0 -112
  196. package/src/lib/db/paths.ts +0 -128
  197. package/src/lib/db/remote-engine.test.ts +0 -44
  198. package/src/lib/db/remote-engine.ts +0 -148
  199. package/src/lib/db/remote-sql.test.ts +0 -32
  200. package/src/lib/db/remote-sql.ts +0 -62
  201. package/src/lib/db/sql.test.ts +0 -106
  202. package/src/lib/db/sql.ts +0 -192
  203. package/src/lib/hq-cloud-dep.smoke.test.ts +0 -75
  204. package/src/lib/local-tree-diff.test.ts +0 -301
  205. package/src/lib/local-tree-diff.ts +0 -362
  206. package/src/lib/narrow-hint-banner.test.ts +0 -235
  207. package/src/lib/narrow-hint-banner.ts +0 -212
  208. package/src/lib/plan-limit-nag.test.ts +0 -317
  209. package/src/lib/plan-limit-nag.ts +0 -264
  210. package/src/main.ts +0 -371
  211. package/src/node-preflight.test.ts +0 -60
  212. package/src/node-preflight.ts +0 -67
  213. package/src/outpost/session-heartbeat-bounds.test.ts +0 -195
  214. package/src/outpost/session-heartbeat-guard.test.ts +0 -105
  215. package/src/outpost/session-heartbeat-publisher.test.ts +0 -178
  216. package/src/outpost/session-heartbeat-publisher.ts +0 -186
  217. package/src/outpost/session-heartbeat-retain-guard.test.ts +0 -126
  218. package/src/outpost/session-heartbeat.test.ts +0 -459
  219. package/src/outpost/session-heartbeat.ts +0 -877
  220. package/src/packaging.test.ts +0 -109
  221. package/src/run/__fixtures__/discover-schemas/example.env.schema +0 -4
  222. package/src/run/discover-schemas.test.ts +0 -153
  223. package/src/run/discover-schemas.ts +0 -79
  224. package/src/run/hq-plugin.test.ts +0 -371
  225. package/src/run/hq-plugin.ts +0 -277
  226. package/src/run/varlock-shape.test.ts +0 -57
  227. package/src/schemas/hq-package.schema.json +0 -155
  228. package/src/sentry-before-send.test.ts +0 -359
  229. package/src/sentry-before-send.ts +0 -221
  230. package/src/sentry-epipe.test.ts +0 -37
  231. package/src/sentry-release.test.ts +0 -54
  232. package/src/sentry.test.ts +0 -24
  233. package/src/sentry.ts +0 -54
  234. package/src/strategies/link.ts +0 -62
  235. package/src/strategies/merge.ts +0 -142
  236. package/src/types.ts +0 -146
  237. package/src/utils/__fixtures__/scan-packages.generated-block.sh +0 -23
  238. package/src/utils/auth-error.test.ts +0 -40
  239. package/src/utils/auth-error.ts +0 -42
  240. package/src/utils/billing-gate.test.ts +0 -95
  241. package/src/utils/billing-gate.ts +0 -228
  242. package/src/utils/breadcrumb-buffer.ts +0 -18
  243. package/src/utils/cli-telemetry.test.ts +0 -153
  244. package/src/utils/cli-telemetry.ts +0 -61
  245. package/src/utils/cognito-session.machine.test.ts +0 -109
  246. package/src/utils/cognito-session.refresh.test.ts +0 -84
  247. package/src/utils/cognito-session.test.ts +0 -328
  248. package/src/utils/cognito-session.ts +0 -448
  249. package/src/utils/company-selection-error.test.ts +0 -42
  250. package/src/utils/company-selection-error.ts +0 -45
  251. package/src/utils/contribution-table.ts +0 -83
  252. package/src/utils/environmental-error.test.ts +0 -45
  253. package/src/utils/environmental-error.ts +0 -39
  254. package/src/utils/epipe.test.ts +0 -28
  255. package/src/utils/epipe.ts +0 -29
  256. package/src/utils/expected-cli-error.test.ts +0 -28
  257. package/src/utils/expected-cli-error.ts +0 -39
  258. package/src/utils/feedback-diagnostics.test.ts +0 -183
  259. package/src/utils/feedback-diagnostics.ts +0 -123
  260. package/src/utils/feedback-screenshots.test.ts +0 -134
  261. package/src/utils/feedback-screenshots.ts +0 -124
  262. package/src/utils/feedback-versions.test.ts +0 -98
  263. package/src/utils/feedback-versions.ts +0 -68
  264. package/src/utils/git.ts +0 -74
  265. package/src/utils/integrity.ts +0 -59
  266. package/src/utils/intercepted-process-exit.test.ts +0 -37
  267. package/src/utils/intercepted-process-exit.ts +0 -36
  268. package/src/utils/login-provider.test.ts +0 -42
  269. package/src/utils/login-provider.ts +0 -30
  270. package/src/utils/manifest.test.ts +0 -167
  271. package/src/utils/manifest.ts +0 -131
  272. package/src/utils/pack-contributions.test.ts +0 -603
  273. package/src/utils/pack-contributions.ts +0 -450
  274. package/src/utils/people.ts +0 -215
  275. package/src/utils/registry-client.ts +0 -204
  276. package/src/utils/registry.ts +0 -90
  277. package/src/utils/resolve-vault-credential.test.ts +0 -69
  278. package/src/utils/resolve-vault-credential.ts +0 -60
  279. package/src/utils/sandbox-runner-client.test.ts +0 -279
  280. package/src/utils/sandbox-runner-client.ts +0 -260
  281. package/src/utils/secrets-cache.ts +0 -183
  282. package/src/utils/sentry-identity.ts +0 -45
  283. package/src/utils/settle-with-timeout.test.ts +0 -21
  284. package/src/utils/settle-with-timeout.ts +0 -22
  285. package/src/utils/user-yaml-error.test.ts +0 -24
  286. package/src/utils/user-yaml-error.ts +0 -30
  287. package/src/utils/vault-api.test.ts +0 -536
  288. package/src/utils/vault-api.ts +0 -382
  289. package/src/utils/version-check.test.ts +0 -176
  290. package/src/utils/version-check.ts +0 -155
  291. package/src/utils/version-gate.test.ts +0 -1024
  292. package/src/utils/version-gate.ts +0 -702
  293. package/test/commands/db-tenant-isolation.test.ts +0 -94
  294. package/test/commands/db.test.ts +0 -85
  295. package/test/commands/signals.test.ts +0 -207
  296. package/test/commands/sources.test.ts +0 -231
  297. package/test/e2e/smoke-install-mcp.sh +0 -113
  298. package/test/fixtures/hq-pack-smoke-mcp/mcp/smoke-http.json +0 -1
  299. package/test/fixtures/hq-pack-smoke-mcp/package.yaml +0 -11
  300. package/test/fixtures/signals/action_item/sample.md +0 -16
  301. package/test/fixtures/signals/summary/sample.md +0 -12
  302. package/test/fixtures/sources/meetings/sample.md +0 -25
  303. package/test/helpers/cli-runner.ts +0 -150
  304. package/test/helpers/s3-list-mock.ts +0 -79
  305. package/test/helpers/vault-service-mock.ts +0 -295
  306. package/test/sources-signals/smoke.test.ts +0 -228
  307. package/tsconfig.json +0 -20
  308. package/vitest.config.ts +0 -11
  309. 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
- });