@indigoai-us/hq-cli 5.77.14 → 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 (308) hide show
  1. package/CHANGELOG.md +23 -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 +42 -2
  33. package/dist/commands/pkg-install.js +39 -2
  34. package/dist/commands/run.js +6 -2
  35. package/dist/commands/secrets.js +120 -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 -2256
  144. package/src/commands/pack-update-cache.test.ts +0 -149
  145. package/src/commands/packs-update-api-key.test.ts +0 -105
  146. package/src/commands/packs.test.ts +0 -88
  147. package/src/commands/packs.ts +0 -622
  148. package/src/commands/people.test.ts +0 -807
  149. package/src/commands/people.ts +0 -422
  150. package/src/commands/pkg-install.dispatch.test.ts +0 -103
  151. package/src/commands/pkg-install.ts +0 -221
  152. package/src/commands/pkg-list.test.ts +0 -79
  153. package/src/commands/pkg-list.ts +0 -13
  154. package/src/commands/pkg-remove.ts +0 -71
  155. package/src/commands/pkg-update.ts +0 -189
  156. package/src/commands/publish.test.ts +0 -650
  157. package/src/commands/publish.ts +0 -580
  158. package/src/commands/reindex.test.ts +0 -259
  159. package/src/commands/reindex.ts +0 -274
  160. package/src/commands/rescue.test.ts +0 -39
  161. package/src/commands/rescue.ts +0 -210
  162. package/src/commands/run.env-local.test.ts +0 -88
  163. package/src/commands/run.test.ts +0 -45
  164. package/src/commands/run.ts +0 -190
  165. package/src/commands/safe-extract.test.ts +0 -459
  166. package/src/commands/safe-extract.ts +0 -444
  167. package/src/commands/secrets-scope.test.ts +0 -56
  168. package/src/commands/secrets-scope.ts +0 -32
  169. package/src/commands/secrets.parse-destination.test.ts +0 -38
  170. package/src/commands/secrets.test.ts +0 -2050
  171. package/src/commands/secrets.ts +0 -2249
  172. package/src/commands/signals.ts +0 -351
  173. package/src/commands/skill.test.ts +0 -770
  174. package/src/commands/skill.ts +0 -796
  175. package/src/commands/sources.ts +0 -362
  176. package/src/commands/sync-mode.test.ts +0 -366
  177. package/src/commands/sync-mode.ts +0 -387
  178. package/src/commands/sync-narrow.test.ts +0 -633
  179. package/src/commands/sync-narrow.ts +0 -555
  180. package/src/commands/sync.ts +0 -165
  181. package/src/commands/team-sync.ts +0 -628
  182. package/src/commands/update.ts +0 -71
  183. package/src/commands/whoami.ts +0 -83
  184. package/src/commands/workers.test.ts +0 -158
  185. package/src/commands/workers.ts +0 -301
  186. package/src/index.test.ts +0 -32
  187. package/src/index.ts +0 -20
  188. package/src/lib/db/control-plane.test.ts +0 -59
  189. package/src/lib/db/control-plane.ts +0 -113
  190. package/src/lib/db/local.test.ts +0 -81
  191. package/src/lib/db/local.ts +0 -148
  192. package/src/lib/db/migrate.test.ts +0 -133
  193. package/src/lib/db/migrate.ts +0 -137
  194. package/src/lib/db/paths.test.ts +0 -112
  195. package/src/lib/db/paths.ts +0 -128
  196. package/src/lib/db/remote-engine.test.ts +0 -44
  197. package/src/lib/db/remote-engine.ts +0 -148
  198. package/src/lib/db/remote-sql.test.ts +0 -32
  199. package/src/lib/db/remote-sql.ts +0 -62
  200. package/src/lib/db/sql.test.ts +0 -106
  201. package/src/lib/db/sql.ts +0 -192
  202. package/src/lib/hq-cloud-dep.smoke.test.ts +0 -75
  203. package/src/lib/local-tree-diff.test.ts +0 -301
  204. package/src/lib/local-tree-diff.ts +0 -362
  205. package/src/lib/narrow-hint-banner.test.ts +0 -235
  206. package/src/lib/narrow-hint-banner.ts +0 -212
  207. package/src/lib/plan-limit-nag.test.ts +0 -317
  208. package/src/lib/plan-limit-nag.ts +0 -264
  209. package/src/main.ts +0 -371
  210. package/src/node-preflight.test.ts +0 -60
  211. package/src/node-preflight.ts +0 -67
  212. package/src/outpost/session-heartbeat-bounds.test.ts +0 -195
  213. package/src/outpost/session-heartbeat-guard.test.ts +0 -105
  214. package/src/outpost/session-heartbeat-publisher.test.ts +0 -178
  215. package/src/outpost/session-heartbeat-publisher.ts +0 -186
  216. package/src/outpost/session-heartbeat-retain-guard.test.ts +0 -126
  217. package/src/outpost/session-heartbeat.test.ts +0 -459
  218. package/src/outpost/session-heartbeat.ts +0 -877
  219. package/src/packaging.test.ts +0 -109
  220. package/src/run/__fixtures__/discover-schemas/example.env.schema +0 -4
  221. package/src/run/discover-schemas.test.ts +0 -153
  222. package/src/run/discover-schemas.ts +0 -79
  223. package/src/run/hq-plugin.test.ts +0 -371
  224. package/src/run/hq-plugin.ts +0 -277
  225. package/src/run/varlock-shape.test.ts +0 -57
  226. package/src/schemas/hq-package.schema.json +0 -155
  227. package/src/sentry-before-send.test.ts +0 -359
  228. package/src/sentry-before-send.ts +0 -221
  229. package/src/sentry-epipe.test.ts +0 -37
  230. package/src/sentry-release.test.ts +0 -54
  231. package/src/sentry.test.ts +0 -24
  232. package/src/sentry.ts +0 -54
  233. package/src/strategies/link.ts +0 -62
  234. package/src/strategies/merge.ts +0 -142
  235. package/src/types.ts +0 -146
  236. package/src/utils/__fixtures__/scan-packages.generated-block.sh +0 -23
  237. package/src/utils/auth-error.test.ts +0 -40
  238. package/src/utils/auth-error.ts +0 -42
  239. package/src/utils/billing-gate.test.ts +0 -95
  240. package/src/utils/billing-gate.ts +0 -228
  241. package/src/utils/breadcrumb-buffer.ts +0 -18
  242. package/src/utils/cli-telemetry.test.ts +0 -153
  243. package/src/utils/cli-telemetry.ts +0 -61
  244. package/src/utils/cognito-session.machine.test.ts +0 -109
  245. package/src/utils/cognito-session.refresh.test.ts +0 -84
  246. package/src/utils/cognito-session.test.ts +0 -328
  247. package/src/utils/cognito-session.ts +0 -448
  248. package/src/utils/company-selection-error.test.ts +0 -42
  249. package/src/utils/company-selection-error.ts +0 -45
  250. package/src/utils/contribution-table.ts +0 -83
  251. package/src/utils/environmental-error.test.ts +0 -45
  252. package/src/utils/environmental-error.ts +0 -39
  253. package/src/utils/epipe.test.ts +0 -28
  254. package/src/utils/epipe.ts +0 -29
  255. package/src/utils/expected-cli-error.test.ts +0 -28
  256. package/src/utils/expected-cli-error.ts +0 -39
  257. package/src/utils/feedback-diagnostics.test.ts +0 -183
  258. package/src/utils/feedback-diagnostics.ts +0 -123
  259. package/src/utils/feedback-screenshots.test.ts +0 -134
  260. package/src/utils/feedback-screenshots.ts +0 -124
  261. package/src/utils/feedback-versions.test.ts +0 -98
  262. package/src/utils/feedback-versions.ts +0 -68
  263. package/src/utils/git.ts +0 -74
  264. package/src/utils/integrity.ts +0 -59
  265. package/src/utils/intercepted-process-exit.test.ts +0 -37
  266. package/src/utils/intercepted-process-exit.ts +0 -36
  267. package/src/utils/login-provider.test.ts +0 -42
  268. package/src/utils/login-provider.ts +0 -30
  269. package/src/utils/manifest.test.ts +0 -167
  270. package/src/utils/manifest.ts +0 -131
  271. package/src/utils/pack-contributions.test.ts +0 -603
  272. package/src/utils/pack-contributions.ts +0 -450
  273. package/src/utils/people.ts +0 -215
  274. package/src/utils/registry-client.ts +0 -204
  275. package/src/utils/registry.ts +0 -90
  276. package/src/utils/resolve-vault-credential.test.ts +0 -69
  277. package/src/utils/resolve-vault-credential.ts +0 -60
  278. package/src/utils/sandbox-runner-client.test.ts +0 -279
  279. package/src/utils/sandbox-runner-client.ts +0 -260
  280. package/src/utils/secrets-cache.ts +0 -183
  281. package/src/utils/sentry-identity.ts +0 -45
  282. package/src/utils/settle-with-timeout.test.ts +0 -21
  283. package/src/utils/settle-with-timeout.ts +0 -22
  284. package/src/utils/user-yaml-error.test.ts +0 -24
  285. package/src/utils/user-yaml-error.ts +0 -30
  286. package/src/utils/vault-api.test.ts +0 -536
  287. package/src/utils/vault-api.ts +0 -382
  288. package/src/utils/version-check.test.ts +0 -176
  289. package/src/utils/version-check.ts +0 -155
  290. package/src/utils/version-gate.test.ts +0 -1024
  291. package/src/utils/version-gate.ts +0 -702
  292. package/test/commands/db-tenant-isolation.test.ts +0 -94
  293. package/test/commands/db.test.ts +0 -85
  294. package/test/commands/signals.test.ts +0 -207
  295. package/test/commands/sources.test.ts +0 -231
  296. package/test/e2e/smoke-install-mcp.sh +0 -113
  297. package/test/fixtures/hq-pack-smoke-mcp/mcp/smoke-http.json +0 -1
  298. package/test/fixtures/hq-pack-smoke-mcp/package.yaml +0 -11
  299. package/test/fixtures/signals/action_item/sample.md +0 -16
  300. package/test/fixtures/signals/summary/sample.md +0 -12
  301. package/test/fixtures/sources/meetings/sample.md +0 -25
  302. package/test/helpers/cli-runner.ts +0 -150
  303. package/test/helpers/s3-list-mock.ts +0 -79
  304. package/test/helpers/vault-service-mock.ts +0 -295
  305. package/test/sources-signals/smoke.test.ts +0 -228
  306. package/tsconfig.json +0 -20
  307. package/vitest.config.ts +0 -11
  308. 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
- });