@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.
- package/CHANGELOG.md +34 -0
- package/assets/scaffold/core/scripts/archive-old-threads.sh +86 -0
- package/assets/scaffold/core/scripts/backfill-company-skill-mirrors.sh +73 -0
- package/assets/scaffold/core/scripts/backfill-workspace-mirror.sh +51 -0
- package/assets/scaffold/core/scripts/codex-skill-bridge.sh +550 -0
- package/assets/scaffold/core/scripts/detect-stale-core-policy-mirror.sh +185 -0
- package/assets/scaffold/core/scripts/hq-status-summary.sh +187 -0
- package/assets/scaffold/core/scripts/ontology-readme-drift.sh +264 -0
- package/assets/scaffold/core/scripts/qmd-reindex-after-sync.sh +93 -0
- package/assets/scaffold/core/scripts/rebuild-all-indexes.sh +69 -0
- package/assets/scaffold/core/scripts/rebuild-companies-index.sh +206 -0
- package/assets/scaffold/core/scripts/rebuild-company-knowledge-index.sh +127 -0
- package/assets/scaffold/core/scripts/rebuild-orchestrator-index.sh +86 -0
- package/assets/scaffold/core/scripts/rebuild-projects-index.sh +105 -0
- package/assets/scaffold/core/scripts/rebuild-public-knowledge-index.sh +83 -0
- package/assets/scaffold/core/scripts/rebuild-reports-index.sh +114 -0
- package/assets/scaffold/core/scripts/rebuild-social-drafts-index.sh +135 -0
- package/assets/scaffold/core/scripts/rebuild-threads-index.sh +82 -0
- package/assets/scaffold/core/scripts/rebuild-workers-index.sh +97 -0
- package/assets/scaffold/core/scripts/resize-screenshot.sh +47 -0
- package/assets/scaffold/core/scripts/token-usage-report.sh +254 -0
- package/assets/scaffold/core/scripts/worktree.sh +136 -0
- package/dist/commands/agents.js +28 -12
- package/dist/commands/api-keys.js +100 -20
- package/dist/commands/core.d.ts +90 -0
- package/dist/commands/core.js +279 -0
- package/dist/commands/files-browse.d.ts +21 -0
- package/dist/commands/files-browse.js +145 -24
- package/dist/commands/files.js +33 -7
- package/dist/commands/members.js +16 -5
- package/dist/commands/pack-install.d.ts +14 -0
- package/dist/commands/pack-install.js +51 -2
- package/dist/commands/pkg-install.js +43 -0
- package/dist/commands/run.js +8 -0
- package/dist/commands/secrets.js +125 -65
- package/dist/main.js +6 -0
- package/dist/utils/api-key-command-gate.d.ts +45 -0
- package/dist/utils/api-key-command-gate.js +51 -0
- package/dist/utils/hq-roots.d.ts +91 -0
- package/dist/utils/hq-roots.js +212 -0
- package/dist/utils/resolve-vault-credential.d.ts +63 -3
- package/dist/utils/resolve-vault-credential.js +152 -6
- package/dist/utils/run-bundled-script.d.ts +66 -0
- package/dist/utils/run-bundled-script.js +80 -0
- package/dist/utils/vault-api.d.ts +21 -0
- package/dist/utils/vault-api.js +74 -3
- package/package.json +7 -1
- package/.claude/policies/hq-cli-interactive-reads-use-sts-vend.md +0 -49
- package/.github/workflows/ci.yml +0 -46
- package/.github/workflows/publish.yml +0 -36
- package/.github/workflows/scripts/smoke-test-pkg.sh +0 -97
- package/e2e/cli.test.ts +0 -128
- package/eslint.config.js +0 -37
- package/pnpm-workspace.yaml +0 -4
- package/scripts/chmod-bins.mjs +0 -49
- package/scripts/generate-dsn.mjs +0 -26
- package/scripts/generate-scan-packages-table.mjs +0 -113
- package/scripts/smoke-sources-signals.sh +0 -103
- package/src/bin/hq-auth-refresh.ts +0 -43
- package/src/cli-version.ts +0 -13
- package/src/commands/__fixtures__/make-tar.ts +0 -126
- package/src/commands/_patterns.ts +0 -10
- package/src/commands/add.ts +0 -75
- package/src/commands/agents.test.ts +0 -527
- package/src/commands/agents.ts +0 -923
- package/src/commands/api-keys.test.ts +0 -291
- package/src/commands/api-keys.ts +0 -382
- package/src/commands/artifact-verify.test.ts +0 -177
- package/src/commands/auth.test.ts +0 -82
- package/src/commands/auth.ts +0 -213
- package/src/commands/billing.test.ts +0 -158
- package/src/commands/billing.ts +0 -146
- package/src/commands/channels.test.ts +0 -74
- package/src/commands/channels.ts +0 -91
- package/src/commands/cloud-demote.test.ts +0 -401
- package/src/commands/cloud-demote.ts +0 -278
- package/src/commands/cloud-provision.test.ts +0 -1117
- package/src/commands/cloud-provision.ts +0 -942
- package/src/commands/cloud.pull-all.test.ts +0 -711
- package/src/commands/cloud.pull-per-company.test.ts +0 -188
- package/src/commands/cloud.push-all.test.ts +0 -485
- package/src/commands/cloud.scope-excluded-warning.test.ts +0 -22
- package/src/commands/cloud.selectors.test.ts +0 -208
- package/src/commands/cloud.status.test.ts +0 -160
- package/src/commands/cloud.test.ts +0 -41
- package/src/commands/cloud.ts +0 -2130
- package/src/commands/company.test.ts +0 -202
- package/src/commands/company.ts +0 -148
- package/src/commands/creators.test.ts +0 -60
- package/src/commands/creators.ts +0 -117
- package/src/commands/crm.test.ts +0 -179
- package/src/commands/crm.ts +0 -236
- package/src/commands/db-migrate.ts +0 -55
- package/src/commands/db-provision.ts +0 -114
- package/src/commands/db-sql.ts +0 -124
- package/src/commands/db-status.ts +0 -108
- package/src/commands/db.ts +0 -26
- package/src/commands/dm.test.ts +0 -748
- package/src/commands/dm.ts +0 -1226
- package/src/commands/feedback.test.ts +0 -413
- package/src/commands/feedback.ts +0 -169
- package/src/commands/files-browse.test.ts +0 -1249
- package/src/commands/files-browse.ts +0 -1506
- package/src/commands/files-delete.test.ts +0 -484
- package/src/commands/files-recovery.test.ts +0 -370
- package/src/commands/files.test.ts +0 -722
- package/src/commands/files.ts +0 -1446
- package/src/commands/group-grants.test.ts +0 -330
- package/src/commands/group-grants.ts +0 -455
- package/src/commands/groups.test.ts +0 -44
- package/src/commands/groups.ts +0 -368
- package/src/commands/integrations.test.ts +0 -633
- package/src/commands/integrations.ts +0 -507
- package/src/commands/list.ts +0 -85
- package/src/commands/login.ts +0 -52
- package/src/commands/logout.ts +0 -30
- package/src/commands/marketplace-install.test.ts +0 -543
- package/src/commands/marketplace-security.test.ts +0 -646
- package/src/commands/mcp-registration.test.ts +0 -2787
- package/src/commands/mcp-registration.ts +0 -2612
- package/src/commands/mcp-status.test.ts +0 -483
- package/src/commands/mcp-status.ts +0 -575
- package/src/commands/mcp-status.us011.test.ts +0 -243
- package/src/commands/meetings.test.ts +0 -522
- package/src/commands/meetings.ts +0 -789
- package/src/commands/members.test.ts +0 -1474
- package/src/commands/members.ts +0 -1181
- package/src/commands/onboard-identity-guard.test.ts +0 -99
- package/src/commands/onboard-identity-guard.ts +0 -103
- package/src/commands/onboard-join.test.ts +0 -96
- package/src/commands/onboard-join.ts +0 -101
- package/src/commands/onboard-warning.test.ts +0 -26
- package/src/commands/onboard-warning.ts +0 -12
- package/src/commands/onboard.ts +0 -267
- package/src/commands/outposts-heartbeat.test.ts +0 -299
- package/src/commands/outposts-heartbeat.ts +0 -310
- package/src/commands/outposts-replica-sync.test.ts +0 -272
- package/src/commands/outposts-self-deploy.test.ts +0 -243
- package/src/commands/outposts.test.ts +0 -1039
- package/src/commands/outposts.ts +0 -1935
- package/src/commands/pack-install-secret-authorization.test.ts +0 -115
- package/src/commands/pack-install.test.ts +0 -1469
- package/src/commands/pack-install.ts +0 -2247
- package/src/commands/pack-update-cache.test.ts +0 -149
- package/src/commands/packs.test.ts +0 -88
- package/src/commands/packs.ts +0 -622
- package/src/commands/people.test.ts +0 -807
- package/src/commands/people.ts +0 -422
- package/src/commands/pkg-install.dispatch.test.ts +0 -71
- package/src/commands/pkg-install.ts +0 -215
- package/src/commands/pkg-list.test.ts +0 -79
- package/src/commands/pkg-list.ts +0 -13
- package/src/commands/pkg-remove.ts +0 -71
- package/src/commands/pkg-update.ts +0 -189
- package/src/commands/publish.test.ts +0 -650
- package/src/commands/publish.ts +0 -580
- package/src/commands/reindex.test.ts +0 -259
- package/src/commands/reindex.ts +0 -274
- package/src/commands/rescue.test.ts +0 -39
- package/src/commands/rescue.ts +0 -210
- package/src/commands/run.env-local.test.ts +0 -88
- package/src/commands/run.test.ts +0 -45
- package/src/commands/run.ts +0 -184
- package/src/commands/safe-extract.test.ts +0 -459
- package/src/commands/safe-extract.ts +0 -444
- package/src/commands/secrets-scope.test.ts +0 -56
- package/src/commands/secrets-scope.ts +0 -32
- package/src/commands/secrets.parse-destination.test.ts +0 -38
- package/src/commands/secrets.test.ts +0 -2037
- package/src/commands/secrets.ts +0 -2240
- package/src/commands/signals.ts +0 -351
- package/src/commands/skill.test.ts +0 -770
- package/src/commands/skill.ts +0 -796
- package/src/commands/sources.ts +0 -362
- package/src/commands/sync-mode.test.ts +0 -366
- package/src/commands/sync-mode.ts +0 -387
- package/src/commands/sync-narrow.test.ts +0 -633
- package/src/commands/sync-narrow.ts +0 -555
- package/src/commands/sync.ts +0 -165
- package/src/commands/team-sync.ts +0 -628
- package/src/commands/update.ts +0 -71
- package/src/commands/whoami.ts +0 -83
- package/src/commands/workers.test.ts +0 -158
- package/src/commands/workers.ts +0 -301
- package/src/index.test.ts +0 -32
- package/src/index.ts +0 -20
- package/src/lib/db/control-plane.test.ts +0 -59
- package/src/lib/db/control-plane.ts +0 -113
- package/src/lib/db/local.test.ts +0 -81
- package/src/lib/db/local.ts +0 -148
- package/src/lib/db/migrate.test.ts +0 -133
- package/src/lib/db/migrate.ts +0 -137
- package/src/lib/db/paths.test.ts +0 -112
- package/src/lib/db/paths.ts +0 -128
- package/src/lib/db/remote-engine.test.ts +0 -44
- package/src/lib/db/remote-engine.ts +0 -148
- package/src/lib/db/remote-sql.test.ts +0 -32
- package/src/lib/db/remote-sql.ts +0 -62
- package/src/lib/db/sql.test.ts +0 -106
- package/src/lib/db/sql.ts +0 -192
- package/src/lib/hq-cloud-dep.smoke.test.ts +0 -75
- package/src/lib/local-tree-diff.test.ts +0 -301
- package/src/lib/local-tree-diff.ts +0 -362
- package/src/lib/narrow-hint-banner.test.ts +0 -235
- package/src/lib/narrow-hint-banner.ts +0 -212
- package/src/lib/plan-limit-nag.test.ts +0 -317
- package/src/lib/plan-limit-nag.ts +0 -264
- package/src/main.ts +0 -371
- package/src/node-preflight.test.ts +0 -60
- package/src/node-preflight.ts +0 -67
- package/src/outpost/session-heartbeat-bounds.test.ts +0 -195
- package/src/outpost/session-heartbeat-guard.test.ts +0 -105
- package/src/outpost/session-heartbeat-publisher.test.ts +0 -178
- package/src/outpost/session-heartbeat-publisher.ts +0 -186
- package/src/outpost/session-heartbeat-retain-guard.test.ts +0 -126
- package/src/outpost/session-heartbeat.test.ts +0 -459
- package/src/outpost/session-heartbeat.ts +0 -877
- package/src/packaging.test.ts +0 -109
- package/src/run/__fixtures__/discover-schemas/example.env.schema +0 -4
- package/src/run/discover-schemas.test.ts +0 -153
- package/src/run/discover-schemas.ts +0 -79
- package/src/run/hq-plugin.test.ts +0 -371
- package/src/run/hq-plugin.ts +0 -277
- package/src/run/varlock-shape.test.ts +0 -57
- package/src/schemas/hq-package.schema.json +0 -155
- package/src/sentry-before-send.test.ts +0 -359
- package/src/sentry-before-send.ts +0 -221
- package/src/sentry-epipe.test.ts +0 -37
- package/src/sentry-release.test.ts +0 -54
- package/src/sentry.test.ts +0 -24
- package/src/sentry.ts +0 -54
- package/src/strategies/link.ts +0 -62
- package/src/strategies/merge.ts +0 -142
- package/src/types.ts +0 -146
- package/src/utils/__fixtures__/scan-packages.generated-block.sh +0 -23
- package/src/utils/auth-error.test.ts +0 -40
- package/src/utils/auth-error.ts +0 -42
- package/src/utils/billing-gate.test.ts +0 -95
- package/src/utils/billing-gate.ts +0 -228
- package/src/utils/breadcrumb-buffer.ts +0 -18
- package/src/utils/cli-telemetry.test.ts +0 -153
- package/src/utils/cli-telemetry.ts +0 -61
- package/src/utils/cognito-session.machine.test.ts +0 -109
- package/src/utils/cognito-session.refresh.test.ts +0 -84
- package/src/utils/cognito-session.test.ts +0 -328
- package/src/utils/cognito-session.ts +0 -448
- package/src/utils/company-selection-error.test.ts +0 -42
- package/src/utils/company-selection-error.ts +0 -45
- package/src/utils/contribution-table.ts +0 -83
- package/src/utils/environmental-error.test.ts +0 -45
- package/src/utils/environmental-error.ts +0 -39
- package/src/utils/epipe.test.ts +0 -28
- package/src/utils/epipe.ts +0 -29
- package/src/utils/expected-cli-error.test.ts +0 -28
- package/src/utils/expected-cli-error.ts +0 -39
- package/src/utils/feedback-diagnostics.test.ts +0 -183
- package/src/utils/feedback-diagnostics.ts +0 -123
- package/src/utils/feedback-screenshots.test.ts +0 -134
- package/src/utils/feedback-screenshots.ts +0 -124
- package/src/utils/feedback-versions.test.ts +0 -98
- package/src/utils/feedback-versions.ts +0 -68
- package/src/utils/git.ts +0 -74
- package/src/utils/integrity.ts +0 -59
- package/src/utils/intercepted-process-exit.test.ts +0 -37
- package/src/utils/intercepted-process-exit.ts +0 -36
- package/src/utils/login-provider.test.ts +0 -42
- package/src/utils/login-provider.ts +0 -30
- package/src/utils/manifest.test.ts +0 -167
- package/src/utils/manifest.ts +0 -131
- package/src/utils/pack-contributions.test.ts +0 -603
- package/src/utils/pack-contributions.ts +0 -450
- package/src/utils/people.ts +0 -215
- package/src/utils/registry-client.ts +0 -204
- package/src/utils/registry.ts +0 -90
- package/src/utils/resolve-vault-credential.test.ts +0 -69
- package/src/utils/resolve-vault-credential.ts +0 -60
- package/src/utils/sandbox-runner-client.test.ts +0 -279
- package/src/utils/sandbox-runner-client.ts +0 -260
- package/src/utils/secrets-cache.ts +0 -183
- package/src/utils/sentry-identity.ts +0 -45
- package/src/utils/settle-with-timeout.test.ts +0 -21
- package/src/utils/settle-with-timeout.ts +0 -22
- package/src/utils/user-yaml-error.test.ts +0 -24
- package/src/utils/user-yaml-error.ts +0 -30
- package/src/utils/vault-api.test.ts +0 -536
- package/src/utils/vault-api.ts +0 -382
- package/src/utils/version-check.test.ts +0 -176
- package/src/utils/version-check.ts +0 -155
- package/src/utils/version-gate.test.ts +0 -1024
- package/src/utils/version-gate.ts +0 -702
- package/test/commands/db-tenant-isolation.test.ts +0 -94
- package/test/commands/db.test.ts +0 -85
- package/test/commands/signals.test.ts +0 -207
- package/test/commands/sources.test.ts +0 -231
- package/test/e2e/smoke-install-mcp.sh +0 -113
- package/test/fixtures/hq-pack-smoke-mcp/mcp/smoke-http.json +0 -1
- package/test/fixtures/hq-pack-smoke-mcp/package.yaml +0 -11
- package/test/fixtures/signals/action_item/sample.md +0 -16
- package/test/fixtures/signals/summary/sample.md +0 -12
- package/test/fixtures/sources/meetings/sample.md +0 -25
- package/test/helpers/cli-runner.ts +0 -150
- package/test/helpers/s3-list-mock.ts +0 -79
- package/test/helpers/vault-service-mock.ts +0 -295
- package/test/sources-signals/smoke.test.ts +0 -228
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -11
- package/vitest.e2e.config.ts +0 -7
package/dist/utils/vault-api.js
CHANGED
|
@@ -62,8 +62,65 @@ async function peekPlanLimitStatus(response) {
|
|
|
62
62
|
return response;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Map Cognito JWT paths onto parallel Bearer `hqk_` routes under `/v1/keys/…`.
|
|
67
|
+
* Returns null when no keyed route exists (caller must fail closed).
|
|
68
|
+
*
|
|
69
|
+
* The table mirrors hq-pro's gateway routes, NOT its path shapes: a rewrite is
|
|
70
|
+
* listed only where an `hqk_`-authorized route actually exists. Two surfaces
|
|
71
|
+
* are therefore unmapped ON PURPOSE, and adding a rewrite for them would turn
|
|
72
|
+
* an explicit fail-closed error into a 404/401 that reads like a login problem:
|
|
73
|
+
*
|
|
74
|
+
* - the unversioned file ACL + share surfaces (`/files/{companyUid}/acl…`,
|
|
75
|
+
* `/files/{companyUid}/share-session`) — hq-pro serves these under JWT
|
|
76
|
+
* only. `/v1/keys/files/…` exists but covers the VERSIONED family
|
|
77
|
+
* (`list`, `versions`, `versions-list`, `grants`, `tombstones`, `presign`,
|
|
78
|
+
* `delete`, `restore`), which is a different set of handlers.
|
|
79
|
+
* - the notify surface (`/v1/notify/dm`, `/v1/notify/thread`) behind
|
|
80
|
+
* `hq agents message|thread` — there is no `/v1/keys/notify…` route.
|
|
81
|
+
*
|
|
82
|
+
* Both are additionally gated at the command layer so they fail before any
|
|
83
|
+
* network call; this stays the backstop for a new call site that forgets to.
|
|
84
|
+
*/
|
|
85
|
+
export function rewritePathForApiKey(path) {
|
|
86
|
+
if (path.startsWith("/v1/keys/") || path === "/v1/keys/secrets/fetch") {
|
|
87
|
+
return path;
|
|
88
|
+
}
|
|
89
|
+
const rewrites = [
|
|
90
|
+
[/^\/v1\/files(\/|$)/, "/v1/keys/files$1"],
|
|
91
|
+
[/^\/v1\/agents(\/|$)/, "/v1/keys/agents$1"],
|
|
92
|
+
[/^\/v1\/search(\/|$)/, "/v1/keys/search$1"],
|
|
93
|
+
[/^\/v1\/listings(\/|$)/, "/v1/keys/listings$1"],
|
|
94
|
+
[/^\/v1\/fleet(\/|$)/, "/v1/keys/fleet$1"],
|
|
95
|
+
[/^\/v1\/outposts(\/|$)/, "/v1/keys/outposts$1"],
|
|
96
|
+
[/^\/v1\/integrations(\/|$)/, "/v1/keys/integrations$1"],
|
|
97
|
+
[/^\/v1\/work-mesh(\/|$)/, "/v1/keys/work-mesh$1"],
|
|
98
|
+
[/^\/v1\/memberships(\/|$)/, "/v1/keys/memberships$1"],
|
|
99
|
+
[/^\/v1\/companies(\/|$)/, "/v1/keys/companies$1"],
|
|
100
|
+
[/^\/membership(\/|$)/, "/v1/keys/membership$1"],
|
|
101
|
+
[/^\/company-settings(\/|$)/, "/v1/keys/company-settings$1"],
|
|
102
|
+
[/^\/sts(\/|$)/, "/v1/keys/sts$1"],
|
|
103
|
+
// Secrets Cognito routes → keyed family (list/set/get/delete/acl).
|
|
104
|
+
[/^\/secrets(\/|$)/, "/v1/keys/secrets$1"],
|
|
105
|
+
];
|
|
106
|
+
for (const [pattern, replacement] of rewrites) {
|
|
107
|
+
if (pattern.test(path))
|
|
108
|
+
return path.replace(pattern, replacement);
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
65
112
|
export async function vaultApiFetch(opts) {
|
|
66
|
-
|
|
113
|
+
let path = opts.path;
|
|
114
|
+
if (opts.token.startsWith("hqk_")) {
|
|
115
|
+
const rewritten = rewritePathForApiKey(path);
|
|
116
|
+
if (rewritten === null) {
|
|
117
|
+
throw Object.assign(new Error(`HQ_API_KEY cannot call '${path}' — hq-pro has no Bearer hqk_ route ` +
|
|
118
|
+
`for this surface. Use a Cognito session (unset HQ_API_KEY), or a ` +
|
|
119
|
+
`keyed route under /v1/keys/… when available.`), { expected: true });
|
|
120
|
+
}
|
|
121
|
+
path = rewritten;
|
|
122
|
+
}
|
|
123
|
+
const url = new URL(path, opts.baseUrl ?? DEFAULT_VAULT_API_URL);
|
|
67
124
|
if (opts.query) {
|
|
68
125
|
for (const [k, v] of Object.entries(opts.query)) {
|
|
69
126
|
url.searchParams.set(k, v);
|
|
@@ -73,7 +130,7 @@ export async function vaultApiFetch(opts) {
|
|
|
73
130
|
const safeUrl = url.search ? `${url.origin}${url.pathname}?<redacted>` : `${url.origin}${url.pathname}`;
|
|
74
131
|
Sentry.addBreadcrumb({
|
|
75
132
|
category: "http",
|
|
76
|
-
message: `${method} ${
|
|
133
|
+
message: `${method} ${path}`,
|
|
77
134
|
level: "info",
|
|
78
135
|
data: { url: safeUrl, method },
|
|
79
136
|
});
|
|
@@ -89,7 +146,7 @@ export async function vaultApiFetch(opts) {
|
|
|
89
146
|
if (!response.ok) {
|
|
90
147
|
Sentry.addBreadcrumb({
|
|
91
148
|
category: "http",
|
|
92
|
-
message: `${method} ${
|
|
149
|
+
message: `${method} ${path} → ${response.status}`,
|
|
93
150
|
level: "warning",
|
|
94
151
|
data: { url: safeUrl, status: response.status },
|
|
95
152
|
});
|
|
@@ -267,6 +324,20 @@ async function resolveCompanyFromMemberships(token) {
|
|
|
267
324
|
uids.map((u) => ` --company ${u}`).join('\n'));
|
|
268
325
|
}
|
|
269
326
|
export async function getCompanyUid(token, companySlug) {
|
|
327
|
+
// Vault API keys are company-bound. Entity slug resolution has no keyed
|
|
328
|
+
// route, so under hqk_ we accept an explicit cmp_ uid (or HQ_COMPANY_UID)
|
|
329
|
+
// and otherwise fall through to keyed GET /v1/keys/membership/me.
|
|
330
|
+
if (token.startsWith("hqk_")) {
|
|
331
|
+
const ref = companySlug ?? process.env.HQ_COMPANY_UID?.trim();
|
|
332
|
+
if (ref) {
|
|
333
|
+
if (!looksLikeCompanyUid(ref)) {
|
|
334
|
+
throw Object.assign(new Error(`HQ_API_KEY is set; --company must be a company uid (cmp_…) — ` +
|
|
335
|
+
`resolving a slug needs a Cognito session. Got '${ref}'.`), { expected: true });
|
|
336
|
+
}
|
|
337
|
+
return ref;
|
|
338
|
+
}
|
|
339
|
+
return resolveCompanyFromMemberships(token);
|
|
340
|
+
}
|
|
270
341
|
if (companySlug) {
|
|
271
342
|
return resolveCompanyUid(token, companySlug);
|
|
272
343
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indigoai-us/hq-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.78.0",
|
|
4
4
|
"description": "HQ by Indigo management CLI — modules and cloud sync",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"hq": "dist/index.js",
|
|
8
8
|
"hq-auth-refresh": "dist/bin/hq-auth-refresh.js"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"!dist/**/*.map",
|
|
13
|
+
"assets/scaffold",
|
|
14
|
+
"CHANGELOG.md"
|
|
15
|
+
],
|
|
10
16
|
"scripts": {
|
|
11
17
|
"build": "node scripts/generate-dsn.mjs && tsc && node scripts/chmod-bins.mjs",
|
|
12
18
|
"prepublishOnly": "npm run build",
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: hq-cli-interactive-reads-use-sts-vend
|
|
3
|
-
title: Interactive vault reads vend via /sts/vend, never the legacy POST /vend
|
|
4
|
-
scope: repo
|
|
5
|
-
trigger: any hq-cli command that vends vault credentials to read/list company objects (files browse, files cat, files get/search, or any new interactive read surface)
|
|
6
|
-
enforcement: hard
|
|
7
|
-
public: false
|
|
8
|
-
version: 1
|
|
9
|
-
created: 2026-05-29
|
|
10
|
-
updated: 2026-05-29
|
|
11
|
-
source: back-pressure-failure
|
|
12
|
-
applies_to: [aws]
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Rule
|
|
16
|
-
|
|
17
|
-
Interactive vault reads in hq-cli MUST vend through the multi-tenant STS
|
|
18
|
-
routes — `VaultClient.sts.vend({ companyUid })` (`POST /sts/vend`, company) or
|
|
19
|
-
`VaultClient.sts.vendSelf({ personUid })` (`POST /sts/vend-self`, personal).
|
|
20
|
-
NEVER vend through the legacy `VaultClient.vend(...)` (`POST /vend`).
|
|
21
|
-
|
|
22
|
-
The legacy `POST /vend` (hq-pro `VaultVendFunction` → `vend.handler`) builds
|
|
23
|
-
its IAM policy against a static `process.env.BUCKET_ARN`, but the hq-pro infra
|
|
24
|
-
(`infra/vault-service.ts`) deliberately does NOT set `BUCKET_ARN` — production
|
|
25
|
-
is multi-tenant with one bucket per company. At runtime `BUCKET_ARN` is
|
|
26
|
-
`undefined`, so the session policy contains `"Resource":[null,"undefined/…"]`
|
|
27
|
-
and STS rejects it with `MalformedPolicyDocument: Syntax error at position
|
|
28
|
-
(-1,-1)` → the client sees a 500 "Failed to generate credentials". Only
|
|
29
|
-
`/sts/vend{,-self,-child}` resolve the per-entity bucket (`entity.bucketArn`)
|
|
30
|
-
and apply role/ACL scoping server-side (owner/admin → full access; member/
|
|
31
|
-
guest → per-prefix). `policy-builder.ts` even documents that `POST /vend` "has
|
|
32
|
-
no production callers" — treat it as dead.
|
|
33
|
-
|
|
34
|
-
Related namespace rule: company vault bucket keys are **company-relative**
|
|
35
|
-
(`knowledge/foo.md`, NOT `companies/<slug>/knowledge/foo.md`). Translate the
|
|
36
|
-
CLI's anchored `companies/<slug>/…` form to the bucket-relative key at the S3
|
|
37
|
-
boundary (`toBucketRelative` / `toCompanyAnchored` in `files-browse.ts`), and
|
|
38
|
-
normalize ACL grant paths with `grantPathToPrefix` before `startsWith`
|
|
39
|
-
classification. Listing/getting with the anchored prefix returns nothing.
|
|
40
|
-
|
|
41
|
-
## Rationale
|
|
42
|
-
|
|
43
|
-
`hq files browse`/`cat` (US-009) were wired to `POST /vend`, which 500'd on
|
|
44
|
-
every multi-tenant call. The root cause was an undefined `BUCKET_ARN` env on
|
|
45
|
-
the vend Lambda, not a stale deploy — redeploying clean source did not fix it.
|
|
46
|
-
The working fix routed both commands through `/sts/vend` + `/sts/vend-self`
|
|
47
|
-
(client-only, hq-cloud 5.43.0 / hq-cli 5.29.0) and fixed the company-relative
|
|
48
|
-
namespace translation. Captured so future interactive-read surfaces reach for
|
|
49
|
-
the STS routes from the start and don't resurrect the dead `POST /vend`.
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
on:
|
|
3
|
-
pull_request:
|
|
4
|
-
branches: [main]
|
|
5
|
-
push:
|
|
6
|
-
branches: [main]
|
|
7
|
-
|
|
8
|
-
concurrency:
|
|
9
|
-
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
-
cancel-in-progress: true
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
build:
|
|
14
|
-
name: build (node ${{ matrix.node-version }})
|
|
15
|
-
strategy:
|
|
16
|
-
fail-fast: false
|
|
17
|
-
matrix:
|
|
18
|
-
# 20 is the declared engines floor (package.json engines.node >=20),
|
|
19
|
-
# 22 is the current dev/publish baseline.
|
|
20
|
-
node-version: ["20", "22"]
|
|
21
|
-
uses: indigoai-us/.github/.github/workflows/_node-ci.yml@main
|
|
22
|
-
with:
|
|
23
|
-
package-manager: pnpm
|
|
24
|
-
pnpm-version: "10"
|
|
25
|
-
node-version: ${{ matrix.node-version }}
|
|
26
|
-
run-build: true
|
|
27
|
-
run-lint: true
|
|
28
|
-
run-coverage: true
|
|
29
|
-
secrets: inherit
|
|
30
|
-
|
|
31
|
-
e2e:
|
|
32
|
-
name: e2e (node 22)
|
|
33
|
-
runs-on: ubuntu-latest
|
|
34
|
-
timeout-minutes: 10
|
|
35
|
-
steps:
|
|
36
|
-
- uses: actions/checkout@v4
|
|
37
|
-
- uses: pnpm/action-setup@v4
|
|
38
|
-
with:
|
|
39
|
-
version: "10"
|
|
40
|
-
- uses: actions/setup-node@v4
|
|
41
|
-
with:
|
|
42
|
-
node-version: "22"
|
|
43
|
-
cache: pnpm
|
|
44
|
-
- run: pnpm install --frozen-lockfile
|
|
45
|
-
- run: pnpm build
|
|
46
|
-
- run: pnpm test:e2e
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
tags: ["v*"]
|
|
5
|
-
# Manual dry-run: validate the build/pack/smoke pipeline without publishing.
|
|
6
|
-
workflow_dispatch:
|
|
7
|
-
inputs:
|
|
8
|
-
dry_run:
|
|
9
|
-
description: "Dry-run (validate build/pack/smoke; npm publish --dry-run, no Sentry upload)"
|
|
10
|
-
type: boolean
|
|
11
|
-
default: true
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
publish:
|
|
15
|
-
permissions:
|
|
16
|
-
contents: read
|
|
17
|
-
id-token: write
|
|
18
|
-
uses: indigoai-us/.github/.github/workflows/_npm-publish.yml@main
|
|
19
|
-
with:
|
|
20
|
-
package-manager: pnpm
|
|
21
|
-
pnpm-version: "10"
|
|
22
|
-
node-version: "24"
|
|
23
|
-
build-command: "pnpm run build"
|
|
24
|
-
dsn-env-name: "HQ_CLI_PUBLISH_SENTRY_DSN"
|
|
25
|
-
sentry-inject-dir: "dist/"
|
|
26
|
-
smoke-test-arg: "hq"
|
|
27
|
-
sentry-release-prefix: "hq-cli"
|
|
28
|
-
sentry-upload-paths: "dist/ node_modules/@indigoai-us/hq-cloud/dist/"
|
|
29
|
-
sentry-org: "indigo-d0"
|
|
30
|
-
sentry-project: "hq-cli"
|
|
31
|
-
# Prerelease versions (e.g. 5.x.y-rc.0) ship to the rc dist-tag, not latest.
|
|
32
|
-
prerelease-dist-tag: "rc"
|
|
33
|
-
dry-run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
|
|
34
|
-
secrets:
|
|
35
|
-
sentry-dsn: ${{ secrets.HQ_CLI_PUBLISH_SENTRY_DSN }}
|
|
36
|
-
sentry-auth-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# smoke-test-pkg.sh — pre-publish cross-package import smoke test (Bug A guard).
|
|
3
|
-
#
|
|
4
|
-
# Single-package adaptation of the same script used in the legacy hq monorepo.
|
|
5
|
-
# The monorepo version operated on `packages/$PKG/package.json`; this version
|
|
6
|
-
# reads `./package.json` because each extracted repo is a single package at
|
|
7
|
-
# its root.
|
|
8
|
-
#
|
|
9
|
-
# Install the package in an isolated tmpdir — using a freshly-packed tarball
|
|
10
|
-
# when the package.json version is new, or fetching the existing name@version
|
|
11
|
-
# from npm when it is already published — then boot the binary with
|
|
12
|
-
# `--version`. The boot exercises the full module-load graph and the
|
|
13
|
-
# transitive `@indigoai-us/*` resolution path a customer's `npm install`
|
|
14
|
-
# would take. If the boot fails the script exits non-zero and the workflow
|
|
15
|
-
# aborts before any further publish steps run.
|
|
16
|
-
#
|
|
17
|
-
# Why we don't skip when the consumer's version is already on npm:
|
|
18
|
-
# @indigoai-us/hq-cli depends on @indigoai-us/hq-cloud via a caret range
|
|
19
|
-
# (^5.1.0). A producer bump (published from indigoai-us/hq-cloud) re-resolves
|
|
20
|
-
# this consumer's transitive deps on the next fresh install, so an already-
|
|
21
|
-
# published consumer is NOT actually "locked." If the new producer drops or
|
|
22
|
-
# renames a symbol the published consumer imports, `hq --version` crashes
|
|
23
|
-
# on every fresh install starting the moment the producer publishes.
|
|
24
|
-
#
|
|
25
|
-
# Usage:
|
|
26
|
-
# smoke-test-pkg.sh <bin-name>
|
|
27
|
-
# Example:
|
|
28
|
-
# smoke-test-pkg.sh hq
|
|
29
|
-
|
|
30
|
-
set -uo pipefail
|
|
31
|
-
|
|
32
|
-
BIN=${1:?usage: smoke-test-pkg.sh <bin-name>}
|
|
33
|
-
|
|
34
|
-
PKG_JSON="package.json"
|
|
35
|
-
if [ ! -f "$PKG_JSON" ]; then
|
|
36
|
-
echo "::error::smoke-test-pkg.sh: $PKG_JSON not found (cwd: $(pwd))"
|
|
37
|
-
exit 2
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
NAME=$(jq -r .name "$PKG_JSON")
|
|
41
|
-
VER=$(jq -r .version "$PKG_JSON")
|
|
42
|
-
|
|
43
|
-
# Pick the install target. Already on npm → install by name@version so the
|
|
44
|
-
# smoke matches what a customer would actually receive. Not yet on npm →
|
|
45
|
-
# pack the local repo; the next publish step will push that exact byte-for-
|
|
46
|
-
# byte content. Either way, `npm install` happens OUTSIDE this repo so
|
|
47
|
-
# transitive @indigoai-us/* deps resolve from the registry.
|
|
48
|
-
INSTALL_SOURCE=""
|
|
49
|
-
if npm view "$NAME@$VER" version >/dev/null 2>&1; then
|
|
50
|
-
INSTALL_TARGET="$NAME@$VER"
|
|
51
|
-
INSTALL_SOURCE="npm registry (consumer version already published)"
|
|
52
|
-
else
|
|
53
|
-
TARBALL_RELATIVE=$(npm pack --silent --pack-destination /tmp)
|
|
54
|
-
if [ -z "$TARBALL_RELATIVE" ]; then
|
|
55
|
-
echo "::error::npm pack produced no tarball for $NAME"
|
|
56
|
-
exit 1
|
|
57
|
-
fi
|
|
58
|
-
INSTALL_TARGET="/tmp/$TARBALL_RELATIVE"
|
|
59
|
-
if [ ! -f "$INSTALL_TARGET" ]; then
|
|
60
|
-
echo "::error::expected tarball at $INSTALL_TARGET not found"
|
|
61
|
-
exit 1
|
|
62
|
-
fi
|
|
63
|
-
INSTALL_SOURCE="packed tarball ($TARBALL_RELATIVE)"
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
echo "::group::smoke test: $NAME@$VER via $INSTALL_SOURCE"
|
|
67
|
-
|
|
68
|
-
SMOKE=$(mktemp -d)
|
|
69
|
-
pushd "$SMOKE" >/dev/null
|
|
70
|
-
|
|
71
|
-
printf '%s' '{"name":"smoke","version":"0.0.0","private":true}' > package.json
|
|
72
|
-
|
|
73
|
-
if ! npm install --no-audit --no-fund --no-package-lock "$INSTALL_TARGET" >/tmp/smoke-install.log 2>&1; then
|
|
74
|
-
echo "::error::pre-publish smoke install FAILED for $NAME@$VER:"
|
|
75
|
-
tail -50 /tmp/smoke-install.log
|
|
76
|
-
popd >/dev/null
|
|
77
|
-
echo "::endgroup::"
|
|
78
|
-
exit 1
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
set +e
|
|
82
|
-
OUT=$("./node_modules/.bin/$BIN" --version 2>&1)
|
|
83
|
-
CODE=$?
|
|
84
|
-
set -e
|
|
85
|
-
|
|
86
|
-
popd >/dev/null
|
|
87
|
-
|
|
88
|
-
if [ "$CODE" -ne 0 ]; then
|
|
89
|
-
echo "::error::pre-publish smoke FAILED for $NAME@$VER (exit $CODE):"
|
|
90
|
-
echo "::error::$OUT"
|
|
91
|
-
echo "::error::Likely cause: a cross-package symbol was changed (added, removed, renamed) in another @indigoai-us/* package without keeping this consumer's import in sync. Bump this consumer (or revert the producer change) and re-tag, OR set the repo/workflow variable WORKFLOW_ALLOW_BROKEN_PUBLISH=1 to override (audited)."
|
|
92
|
-
echo "::endgroup::"
|
|
93
|
-
exit 1
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
echo "✓ smoke ok: $NAME@$VER → $BIN --version → $OUT (via $INSTALL_SOURCE)"
|
|
97
|
-
echo "::endgroup::"
|
package/e2e/cli.test.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { spawn } from "node:child_process";
|
|
5
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
6
|
-
import { version } from "../package.json";
|
|
7
|
-
|
|
8
|
-
const cliEntry = path.resolve("dist/index.js");
|
|
9
|
-
const tempDirs: string[] = [];
|
|
10
|
-
|
|
11
|
-
interface CliResult {
|
|
12
|
-
code: number | null;
|
|
13
|
-
stdout: string;
|
|
14
|
-
stderr: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function runHq(args: string[], options: { cwd?: string; env?: NodeJS.ProcessEnv } = {}) {
|
|
18
|
-
return new Promise<CliResult>((resolve, reject) => {
|
|
19
|
-
const child = spawn(process.execPath, [cliEntry, ...args], {
|
|
20
|
-
cwd: options.cwd,
|
|
21
|
-
env: {
|
|
22
|
-
...process.env,
|
|
23
|
-
HQ_NO_UPDATE_CHECK: "1",
|
|
24
|
-
...options.env,
|
|
25
|
-
},
|
|
26
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
let stdout = "";
|
|
30
|
-
let stderr = "";
|
|
31
|
-
child.stdout.setEncoding("utf8");
|
|
32
|
-
child.stderr.setEncoding("utf8");
|
|
33
|
-
child.stdout.on("data", (chunk) => {
|
|
34
|
-
stdout += chunk;
|
|
35
|
-
});
|
|
36
|
-
child.stderr.on("data", (chunk) => {
|
|
37
|
-
stderr += chunk;
|
|
38
|
-
});
|
|
39
|
-
child.on("error", reject);
|
|
40
|
-
child.on("close", (code) => resolve({ code, stdout, stderr }));
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Spawn the built CLI with its stdout read-end closed immediately, so the
|
|
45
|
-
// child's first write to stdout hits EPIPE — the `hq … | head` / `source <(hq
|
|
46
|
-
// …)` scenario behind HQ-6B. Returns the child's own exit code + stderr.
|
|
47
|
-
function runHqWithClosedStdout(args: string[]) {
|
|
48
|
-
return new Promise<{ code: number | null; stderr: string }>(
|
|
49
|
-
(resolve, reject) => {
|
|
50
|
-
const child = spawn(process.execPath, [cliEntry, ...args], {
|
|
51
|
-
env: { ...process.env, HQ_NO_UPDATE_CHECK: "1" },
|
|
52
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
53
|
-
});
|
|
54
|
-
let stderr = "";
|
|
55
|
-
child.stderr.setEncoding("utf8");
|
|
56
|
-
child.stderr.on("data", (chunk) => {
|
|
57
|
-
stderr += chunk;
|
|
58
|
-
});
|
|
59
|
-
// Close the read end up front (and again on any byte that slips through)
|
|
60
|
-
// so subsequent writes by the child fail with EPIPE.
|
|
61
|
-
child.stdout.on("data", () => child.stdout.destroy());
|
|
62
|
-
child.stdout.destroy();
|
|
63
|
-
child.on("error", reject);
|
|
64
|
-
child.on("close", (code) => resolve({ code, stderr }));
|
|
65
|
-
},
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function makeTempDir(prefix: string) {
|
|
70
|
-
const dir = await mkdtemp(path.join(tmpdir(), prefix));
|
|
71
|
-
tempDirs.push(dir);
|
|
72
|
-
return dir;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
afterEach(async () => {
|
|
76
|
-
await Promise.all(tempDirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })));
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe("built hq CLI", () => {
|
|
80
|
-
it("prints help from the built entrypoint", async () => {
|
|
81
|
-
const result = await runHq(["--help"]);
|
|
82
|
-
|
|
83
|
-
expect(result.code).toBe(0);
|
|
84
|
-
expect(result.stderr).toBe("");
|
|
85
|
-
expect(result.stdout).toContain("Usage: hq [options] [command]");
|
|
86
|
-
expect(result.stdout).toContain("HQ management CLI");
|
|
87
|
-
expect(result.stdout).toContain("whoami");
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("exits cleanly when the downstream reader closes the pipe (HQ-6B)", async () => {
|
|
91
|
-
// Regression for HQ-6B: a closed stdout reader must NOT crash the CLI with
|
|
92
|
-
// a fatal `write EPIPE`. The process should exit 0 with no EPIPE traceback.
|
|
93
|
-
const { code, stderr } = await runHqWithClosedStdout(["--help"]);
|
|
94
|
-
|
|
95
|
-
expect(code).toBe(0);
|
|
96
|
-
expect(stderr).not.toMatch(/EPIPE/);
|
|
97
|
-
expect(stderr).not.toMatch(/Error:/);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("prints the package version from the built entrypoint", async () => {
|
|
101
|
-
const result = await runHq(["--version"]);
|
|
102
|
-
|
|
103
|
-
expect(result.code).toBe(0);
|
|
104
|
-
expect(result.stderr).toBe("");
|
|
105
|
-
expect(result.stdout.trim()).toBe(version);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("reports logged-out state without network or credentials", async () => {
|
|
109
|
-
const home = await makeTempDir("hq-cli-e2e-home-");
|
|
110
|
-
const cwd = await makeTempDir("hq-cli-e2e-cwd-");
|
|
111
|
-
|
|
112
|
-
const result = await runHq(["whoami"], {
|
|
113
|
-
cwd,
|
|
114
|
-
env: {
|
|
115
|
-
HOME: home,
|
|
116
|
-
USERPROFILE: home,
|
|
117
|
-
XDG_CONFIG_HOME: path.join(home, ".config"),
|
|
118
|
-
XDG_CACHE_HOME: path.join(home, ".cache"),
|
|
119
|
-
HQ_MACHINE_IDENTITY: undefined,
|
|
120
|
-
HQ_MACHINE_CREDS: undefined,
|
|
121
|
-
},
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
expect(result.code).toBe(0);
|
|
125
|
-
expect(result.stderr).toBe("");
|
|
126
|
-
expect(result.stdout.trim()).toBe("Not logged in. Run 'hq login' to authenticate.");
|
|
127
|
-
});
|
|
128
|
-
});
|
package/eslint.config.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import js from "@eslint/js";
|
|
2
|
-
import tseslint from "typescript-eslint";
|
|
3
|
-
|
|
4
|
-
const sourceFiles = ["src/**/*.ts"];
|
|
5
|
-
const recommended = tseslint
|
|
6
|
-
.config(js.configs.recommended, ...tseslint.configs.recommended)
|
|
7
|
-
.map((config) => ({
|
|
8
|
-
...config,
|
|
9
|
-
files: sourceFiles,
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
export default [
|
|
13
|
-
{
|
|
14
|
-
ignores: ["dist/**", "generated/**", "node_modules/**"],
|
|
15
|
-
},
|
|
16
|
-
...recommended,
|
|
17
|
-
{
|
|
18
|
-
files: sourceFiles,
|
|
19
|
-
rules: {
|
|
20
|
-
"no-undef": "off",
|
|
21
|
-
"no-useless-assignment": "warn",
|
|
22
|
-
"no-useless-escape": "warn",
|
|
23
|
-
"prefer-const": "warn",
|
|
24
|
-
"preserve-caught-error": "off",
|
|
25
|
-
"@typescript-eslint/no-explicit-any": "warn",
|
|
26
|
-
"@typescript-eslint/no-require-imports": "warn",
|
|
27
|
-
"@typescript-eslint/no-unused-vars": [
|
|
28
|
-
"warn",
|
|
29
|
-
{
|
|
30
|
-
argsIgnorePattern: "^_",
|
|
31
|
-
caughtErrorsIgnorePattern: "^_",
|
|
32
|
-
varsIgnorePattern: "^_",
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
];
|
package/pnpm-workspace.yaml
DELETED
package/scripts/chmod-bins.mjs
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Make every declared `bin` executable after `tsc` emits it.
|
|
4
|
-
*
|
|
5
|
-
* WHY: the build is plain `tsc`, and TypeScript does NOT set the executable
|
|
6
|
-
* bit on its output — `dist/index.js` lands as 0644 despite carrying a
|
|
7
|
-
* `#!/usr/bin/env node` shebang. Most `npm install` paths re-chmod bin targets
|
|
8
|
-
* to 0755 while linking, but not all do: a root global install on a fresh
|
|
9
|
-
* Amazon Linux outpost (`npm install -g @indigoai-us/hq-cli`) has been observed
|
|
10
|
-
* to leave the linked target at 0644, so `/usr/bin/hq` resolves to a
|
|
11
|
-
* non-executable file and EVERY `hq …` invocation on the box dies with
|
|
12
|
-
* "Permission denied" — the outpost never becomes CLI-ready.
|
|
13
|
-
*
|
|
14
|
-
* Fixing it here means the published tarball ships its bins already 0755, so
|
|
15
|
-
* the runnable bit no longer depends on the installer re-chmod'ing. Runs from
|
|
16
|
-
* `build` (local + CI) and `prepublishOnly` (guarantees a fresh publish is
|
|
17
|
-
* always executable, whatever state the publisher's dist was in).
|
|
18
|
-
*
|
|
19
|
-
* Cross-platform: uses fs.chmod (no `chmod` shell dependency); a no-op on
|
|
20
|
-
* Windows where the mode bits are ignored anyway.
|
|
21
|
-
*/
|
|
22
|
-
import { chmodSync, existsSync, readFileSync } from "node:fs";
|
|
23
|
-
import { dirname, resolve } from "node:path";
|
|
24
|
-
import { fileURLToPath } from "node:url";
|
|
25
|
-
|
|
26
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
27
|
-
const pkgPath = resolve(here, "..", "package.json");
|
|
28
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
29
|
-
|
|
30
|
-
const bins =
|
|
31
|
-
typeof pkg.bin === "string"
|
|
32
|
-
? { [pkg.name]: pkg.bin }
|
|
33
|
-
: (pkg.bin ?? {});
|
|
34
|
-
|
|
35
|
-
let touched = 0;
|
|
36
|
-
for (const [name, relPath] of Object.entries(bins)) {
|
|
37
|
-
const target = resolve(here, "..", relPath);
|
|
38
|
-
if (!existsSync(target)) {
|
|
39
|
-
// Build not run yet / stale bin map — surface it loudly so a publish that
|
|
40
|
-
// would ship a missing bin fails fast instead of silently.
|
|
41
|
-
console.error(`chmod-bins: declared bin "${name}" not found at ${relPath}`);
|
|
42
|
-
process.exitCode = 1;
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
chmodSync(target, 0o755);
|
|
46
|
-
touched += 1;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
console.log(`chmod-bins: made ${touched} bin(s) executable (0755)`);
|
package/scripts/generate-dsn.mjs
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from "fs";
|
|
2
|
-
import { join, dirname } from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
|
|
5
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
|
|
7
|
-
const isGitHubActions = process.env.GITHUB_ACTIONS === "true";
|
|
8
|
-
const isPublishJob = process.env.GITHUB_JOB === "publish";
|
|
9
|
-
const dsn = process.env.HQ_CLI_PUBLISH_SENTRY_DSN ?? "";
|
|
10
|
-
|
|
11
|
-
if (isGitHubActions && isPublishJob && !dsn) {
|
|
12
|
-
process.stderr.write(
|
|
13
|
-
"[generate-dsn] FATAL: GITHUB_ACTIONS=true, GITHUB_JOB=publish, " +
|
|
14
|
-
"but HQ_CLI_PUBLISH_SENTRY_DSN is not set. " +
|
|
15
|
-
"Add the repo secret HQ_CLI_PUBLISH_SENTRY_DSN before publishing.\n",
|
|
16
|
-
);
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const outPath = join(__dirname, "../src/sentry-dsn.generated.ts");
|
|
21
|
-
const content = `export const BUNDLED_DSN = "${dsn}";\n`;
|
|
22
|
-
|
|
23
|
-
writeFileSync(outPath, content, "utf8");
|
|
24
|
-
process.stdout.write(
|
|
25
|
-
`[generate-dsn] Wrote BUNDLED_DSN="${dsn ? "[DSN set]" : ""}" to ${outPath}\n`,
|
|
26
|
-
);
|