Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
40618dd
feat(PLATENG-800): Replace @lifeomic/alpha with @jupiterone/platform-…
tokio-on-jupiter Jan 23, 2026
ad5d7a0
feat: Create standalone canary release workflow for public repo
tokio-on-jupiter Jan 23, 2026
d82c3d9
refactor: Address Copilot review feedback
tokio-on-jupiter Jan 23, 2026
7bef637
security: Add authorization checks and environment protection
tokio-on-jupiter Jan 23, 2026
0c31352
refactor: Use jq direct file read instead of cat pipe
tokio-on-jupiter Jan 23, 2026
51bebd5
fix: Update platform-sdk-fetch to released version and fix compression
tokio-on-jupiter Jan 23, 2026
af21390
fix: Remove GitHub packages registry override from canary workflow
tokio-on-jupiter Jan 23, 2026
48619c7
fix: Resolve TypeScript errors with bunyan logger method spreads
tokio-on-jupiter Jan 23, 2026
b7442be
fix: resolve TypeScript build errors from platform-sdk-fetch types
tokio-on-jupiter Jan 23, 2026
b5e27f4
test: update tests to remove axios dependency
tokio-on-jupiter Jan 23, 2026
d60c2d1
fix(canary): resolve backtick escaping issue in comment script
tokio-on-jupiter Jan 23, 2026
fb443fc
fix(canary): compact JSON output to avoid multiline string issues
tokio-on-jupiter Jan 23, 2026
1a7aeae
fix: Use platform-sdk-fetch canary with rawBody support
tokio-on-jupiter Jan 26, 2026
f0af857
chore: trigger new canary release for rawBody fix
tokio-on-jupiter Jan 26, 2026
e814783
fix: Default compressUploads to true to match Alpha behavior
tokio-on-jupiter Jan 26, 2026
3a8c1a3
chore: Update platform-sdk-fetch to 6.0.5-canary-490-1.0
tokio-on-jupiter Jan 26, 2026
a905dab
fix: Address Copilot review comments
tokio-on-jupiter Jan 26, 2026
4bc1694
chore: Update package-lock.json for new canary version
tokio-on-jupiter Jan 26, 2026
8972ea7
chore: Update platform-sdk-fetch to released version 6.0.5
tokio-on-jupiter Jan 27, 2026
73a0dda
Address Copilot review feedback
tokio-on-jupiter Jan 27, 2026
9fc2a04
Update packages/integration-sdk-testing/src/logger.ts
tokio-on-jupiter Jan 27, 2026
11264b4
Fix npm install by overriding platform-sdk-logging version
tokio-on-jupiter Jan 27, 2026
e4af020
Fix npm auth in CI workflow
tokio-on-jupiter Jan 27, 2026
bfcf5a8
Fix test mocks to return proper RequestClientResponse objects
tokio-on-jupiter Jan 27, 2026
1502eda
Fix remaining test mock type issues
tokio-on-jupiter Jan 27, 2026
642fe86
fix: pin transitive dependencies and update tests for compression def…
tokio-on-jupiter Jan 27, 2026
bc290c0
fix(canary): use run_id for unique canary version and commit before p…
tokio-on-jupiter Jan 28, 2026
a9bc0fa
fix: address PR review comments
tokio-on-jupiter Feb 3, 2026
80eb827
fix: address mscottford review feedback
tokio-on-jupiter Feb 3, 2026
dabba5a
feat: add createMockApiClient utility to integration-sdk-testing
tokio-on-jupiter Feb 3, 2026
9352b6b
fix: address PR review comments (items 1-6)
tokio-on-jupiter Feb 3, 2026
5ba653b
fix: remove all as any violations from PR diff
tokio-on-jupiter Feb 3, 2026
36c3e56
fix: replace err: any with unknown in cleanRequestError
tokio-on-jupiter Feb 3, 2026
5e020e4
fix: add skipLibCheck to tsconfig.json files for CI build compatibility
tokio-on-jupiter Feb 3, 2026
47cae91
fix: use isRequestClientError type guard in cleanRequestError
tokio-on-jupiter Feb 3, 2026
3792b7b
fix: warn instead of throw for deprecated alphaOptions/proxyUrl
tokio-on-jupiter Feb 3, 2026
654b394
fix: use process.emitWarning instead of console.warn
tokio-on-jupiter Feb 4, 2026
6a2b879
fix: upgrade fast-xml-parser to 5.3.4 for CVE-2026-25128
tokio-on-jupiter Feb 5, 2026
e02282b
refactor: add mockApiClient subpath export to avoid polly conflict
tokio-on-jupiter Feb 5, 2026
93d2f56
Update package.json
tokio-on-jupiter Feb 6, 2026
07a2892
refactor: migrate from Lerna to NX build system
tokio-on-jupiter Feb 6, 2026
4831886
fix: retain lerna.json for canary workflow compatibility
tokio-on-jupiter Feb 6, 2026
cfc3954
chore: remove unnecessary npm overrides
tokio-on-jupiter Feb 6, 2026
b4cfd98
feat(runtime): add JupiterOneApiClient scaffold with constructor and …
tokio-on-jupiter Feb 16, 2026
924ef34
feat(runtime): add post/get methods with response mapping and rawBody…
tokio-on-jupiter Feb 16, 2026
23dc4e1
test(runtime): add gzip rawBody tests for JupiterOneApiClient
tokio-on-jupiter Feb 16, 2026
4614506
refactor(runtime): replace platform-sdk-fetch with JupiterOneApiClient
tokio-on-jupiter Feb 16, 2026
7e5148a
chore(runtime): remove platform-sdk-fetch dependency
tokio-on-jupiter Feb 16, 2026
f11f976
fix(runtime): remove unnecessary await on sync getAuthorizationHeaders
tokio-on-jupiter Feb 16, 2026
d41679a
fix(testing): remove stale ts-expect-error directive in logger
tokio-on-jupiter Feb 16, 2026
d0792f1
fix(cli): replace platform-sdk-fetch type imports with runtime ApiClient
tokio-on-jupiter Feb 16, 2026
3084c95
fix(build): add http-client to runtime tsconfig references and fix bu…
tokio-on-jupiter Feb 16, 2026
de71780
fix(cli): remove stale platform-sdk-fetch reference from test comment
tokio-on-jupiter Feb 16, 2026
aa95cc1
fix(deps): bump axios 1.13.4 → 1.13.5 (CVE-2026-25639)
tokio-on-jupiter Feb 16, 2026
e5c68af
refactor(runtime): address PR review feedback
tokio-on-jupiter Feb 23, 2026
2f9e32c
pinned nx to 22.5.3
tokio-on-jupiter Mar 3, 2026
0eef9df
fix(deps): regenerate lockfile for nx 22.5.3 with npm 10
tokio-on-jupiter Mar 3, 2026
d2adc8e
fix(deps): pin minimatch to 10.2.4 (CVE-2026-27903, CVE-2026-27904)
tokio-on-jupiter Mar 3, 2026
24dafad
fix(deps): align @sinclair/typebox to 0.32.30 across workspace
tokio-on-jupiter Mar 3, 2026
0291c7d
chore: format files to pass prettier check
tokio-on-jupiter Mar 3, 2026
2b8ebe0
fix(runtime): address PR review — restore retryOptions/proxyUrl, refa…
tokio-on-jupiter Mar 3, 2026
1a5eb80
fix(ci): replace lerna with nx release in canary workflow
tokio-on-jupiter Mar 3, 2026
aa25d72
fix(runtime): remove all as-any casts and eslint-disable overrides fr…
tokio-on-jupiter Mar 4, 2026
2d8cded
fix(runtime): remove unnecessary async from TestableApiClient overrid…
tokio-on-jupiter Mar 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Install dependencies
run: npm ci --include=optional
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}

- name: Run tests
run: npm run test:ci
Expand All @@ -59,7 +59,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 20.x
cache: npm
registry-url: https://registry.npmjs.org

Expand All @@ -83,5 +83,6 @@ jobs:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
run: |
echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > .npmrc
npm ci
npm exec -c "lerna publish from-package --no-verify-access --yes"
npm ci --include=optional
npx nx run-many -t build:dist
npx nx release publish
121 changes: 81 additions & 40 deletions .github/workflows/canary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ jobs:
node-version: '20'
registry-url: 'https://registry.npmjs.org'

- name: Configure npm authentication
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" >> .npmrc

- name: Install dependencies
run: npm ci --include=optional

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be using --ignore-scripts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — will add --ignore-scripts to the npm install step.

env:
Expand All @@ -106,72 +110,109 @@ jobs:
git config --global user.email "automation@jupiterone.com"
git config --global user.name "Automation"

- name: Get changed packages
- name: Detect affected packages
id: changed
run: |
# Get list of packages changed since main (compact JSON for single-line output)
CHANGED=$(npx lerna changed --json 2>/dev/null | jq -c '.' || echo "[]")
echo "Changed packages: $CHANGED"

# Output as single line (no heredoc needed for compact JSON)
echo "packages=$CHANGED" >> $GITHUB_OUTPUT
AFFECTED=$(npx nx show projects --affected --base=origin/main --json 2>/dev/null || echo "[]")
echo "Affected packages: $AFFECTED"
echo "packages=$AFFECTED" >> $GITHUB_OUTPUT

# Check if there are any changed packages
if [ "$CHANGED" = "[]" ]; then
if [ "$AFFECTED" = "[]" ] || [ -z "$AFFECTED" ]; then
echo "has_changes=false" >> $GITHUB_OUTPUT
else
echo "has_changes=true" >> $GITHUB_OUTPUT
fi

- name: Build packages
if: steps.changed.outputs.has_changes == 'true'
run: npm run build:dist

- name: Publish canary versions
id: publish
- name: Bump canary versions
if: steps.changed.outputs.has_changes == 'true'
run: |
PRERELEASE_ID="canary-${{ github.event.issue.number }}-${{ github.run_attempt }}"
node <<'SCRIPT'
const fs = require('fs');
const path = require('path');

const preid = process.env.PRERELEASE_ID;
const packagesDir = 'packages';
const dirs = fs.readdirSync(packagesDir).filter(d =>
fs.existsSync(path.join(packagesDir, d, 'package.json'))
);

// Load all packages
const packages = new Map();
for (const dir of dirs) {
const pkgPath = path.join(packagesDir, dir, 'package.json');
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
packages.set(pkg.name, { dir, pkg, pkgPath });
}

# Version bump with canary prerelease
npx lerna version prerelease --preid "$PRERELEASE_ID" --no-git-tag-version --no-push --yes
// Bump non-private packages to canary version
const bumped = new Map();
for (const [name, entry] of packages) {
if (entry.pkg.private) {
console.log(`Skipping private: ${name}`);
continue;
}
const canaryVersion = `${entry.pkg.version}-${preid}.0`;
entry.pkg.version = canaryVersion;
bumped.set(name, canaryVersion);
console.log(`${name} -> ${canaryVersion}`);
}

# Commit version changes locally to satisfy lerna publish
# These changes won't be pushed back to the PR
# Only stage lerna-modified files (package.json, lerna.json, package-lock.json)
git add lerna.json package-lock.json packages/*/package.json
git commit -m "chore: canary version bump [skip ci]" --no-verify
// Update internal cross-references
for (const [, entry] of packages) {
let changed = false;
for (const depType of ['dependencies', 'devDependencies', 'peerDependencies']) {
if (!entry.pkg[depType]) continue;
for (const depName of Object.keys(entry.pkg[depType])) {
if (bumped.has(depName)) {
entry.pkg[depType][depName] = bumped.get(depName);
changed = true;
}
}
}
if (changed || bumped.has(entry.pkg.name)) {
fs.writeFileSync(entry.pkgPath, JSON.stringify(entry.pkg, null, 2) + '\n');
}
}
SCRIPT
env:
PRERELEASE_ID: canary-${{ github.event.issue.number }}-${{ github.run_id }}

# Publish with canary tag
npx lerna publish from-package --dist-tag canary --yes 2>&1 | tee publish-output.txt
- name: Build packages
if: steps.changed.outputs.has_changes == 'true'
run: npx nx run-many -t build:dist

# Extract published versions
PUBLISHED=$(grep -E "Successfully published" publish-output.txt || echo "")
echo "published<<EOF" >> $GITHUB_OUTPUT
echo "$PUBLISHED" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Publish canary versions
id: publish
if: steps.changed.outputs.has_changes == 'true'
run: npx nx release publish --tag canary
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
GH_TOKEN: ${{ secrets.AUTO_GITHUB_PAT_TOKEN }}
NPM_CONFIG_REGISTRY: https://registry.npmjs.org

- name: Comment with published versions
if: steps.changed.outputs.has_changes == 'true'
uses: actions/github-script@v7
with:
script: |
const packages = JSON.parse('${{ steps.changed.outputs.packages }}');
const fs = require('fs');
const path = require('path');

// Build versions list and install commands from package.json files
// Read all non-private package versions
let versionsList = [];
let installCommands = [];

for (const pkg of packages) {
const pkgPath = pkg.location.startsWith(process.env.GITHUB_WORKSPACE)
? pkg.location
: `${process.env.GITHUB_WORKSPACE}/${pkg.location}`;
const pkgJson = require(`${pkgPath}/package.json`);
versionsList.push(`- \`${pkg.name}@${pkgJson.version}\``);
installCommands.push(`npm install ${pkg.name}@${pkgJson.version}`);
const packagesDir = path.join(process.env.GITHUB_WORKSPACE, 'packages');
const dirs = fs.readdirSync(packagesDir);

for (const dir of dirs) {
const pkgPath = path.join(packagesDir, dir, 'package.json');
if (fs.existsSync(pkgPath)) {
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
if (!pkg.private && pkg.version.includes('canary')) {
versionsList.push(`- \`${pkg.name}@${pkg.version}\``);
installCommands.push(`npm install ${pkg.name}@${pkg.version}`);
}
}
}

const versionsText = versionsList.join('\n');
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ yarn-error.log
*.bak.*

tsconfig.tsbuildinfo
*.tsbuildinfo

# NX
.nx/
2 changes: 0 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1037,7 +1037,6 @@ Skipped step "Fetch Issues". Beta feature, please contact support to enable.
### Changed

- The following packages have been upgraded:

- `@pollyjs/adapter-node-http`
- `@pollyjs/core`
- `@pollyjs/persister-fs`
Expand Down Expand Up @@ -1274,7 +1273,6 @@ RETURN account, repo, user
```

- Updated jest matchers in the following way:

- added optional `_type` argument to `.toMatchGraphObjectSchema` matcher
- added optional `_type` and `_class` arguments to
`.toMatchDirectRelationshipSchema` matcher
Expand Down
1 change: 0 additions & 1 deletion docs/integrations/development_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ in this SDK project.
You'll need:

- Node.js

- It's recommended to use a Node version manager. Both
[fnm](https://github.com/Schniz/fnm) and
[nvm](https://github.com/nvm-sh/nvm) are great choices.
Expand Down
167 changes: 167 additions & 0 deletions docs/plans/2026-02-06-platform-sdk-public-publishing-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Platform SDK Public Publishing Design

**Date:** 2026-02-06 **Status:** Approved for implementation **Authors:** Toks
Fawibe, Ryan McAfee (security analysis) **Context:** PLATENG-800 — PR #1188 adds
`@jupiterone/platform-sdk-fetch` (private) as a dependency of `@jupiterone/sdk`
(public). External consumers cannot install private transitive deps.

---

## Problem

`@jupiterone/sdk` is public on npm. PR #1188 replaces `@lifeomic/alpha` with
`@jupiterone/platform-sdk-fetch`, which has
`publishConfig.access: "restricted"`. Five of its transitive `@jupiterone/*`
dependencies are also restricted. External consumers cannot `npm install` the
SDK after this change merges.

## Decision

Make 17 platform-sdk packages public with MPL-2.0 license. This was chosen over:

- **Vendoring the RequestClient** (~400 lines) — Viable but creates maintenance
burden and divergence from upstream.
- **Using `undici` directly** — Requires rewriting ~460 lines + tests.
Unnecessary complexity.
- **Bundling with tsdown/tsup** — 8-15 days effort, fragile DTS inlining,
massive bundle from unused AWS SDK clients. Not recommended.
- **Native `fetch`** — Experimental on Node 18-20 (SDK's target range). Not
viable until engine constraint is raised to >=21.

## Security Assessment

Ryan McAfee performed a full assessment of all 21 platform-sdk packages.
Independent verification audit confirmed his findings across 107+ source files.

### Classification

| Tier | Count | Packages |
| ------------------------ | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Safe to publish | 14 | config-reader, errors, fetch, graphql, koa, logging, message-codec, service, service-plugin-errors, service-plugin-health, service-types, sqs-consumer, test-tools, framework |
| Safe after minor cleanup | 3 | aws, headers, iam |
| Keep restricted | 2 | elasticsearch, observability |
| Keep private | 2 | benchmark, examples |

### Findings Summary

- Zero HIGH or CRITICAL issues across all 17 packages
- All hardcoded credentials found are verified LocalStack mocks (`test`/`test`)
- All URLs in source/tests are generic placeholders (`example.com`, `localhost`)
- Common LOW finding: `development@jupiterone.com` team email in `package.json`
author fields (standard npm convention)
- Common INFORMATIONAL: GitHub usernames and Jira ticket prefixes in CHANGELOGs

## Implementation Plan

### Execution Order

Packages must be published bottom-up (dependencies before dependents):

```
Layer 1 (no @jupiterone deps):
config-reader, errors, service-types, test-tools, headers*, iam*

Layer 1.5:
aws* (depends on config-reader)

Layer 2 (depends on Layer 1):
logging (-> errors)

Layer 3 (depends on Layer 2):
fetch (-> logging, errors, aws)
message-codec (-> logging, errors)
koa (-> logging, errors)
graphql (-> errors)
service-plugin-errors (-> errors)
service-plugin-health (-> errors)
sqs-consumer (-> logging)
service (-> logging, errors)

Layer 4 (depends on Layer 3):
framework (-> config-reader, errors, iam, logging)

* = caution packages requiring minor code fixes
```

Since platform-sdk uses NX with independent versioning in a single monorepo, all
changes go in one PR and publish together.

### Changes

**All 17 packages** — `package.json`:

```diff
- "license": "UNLICENSED",
+ "license": "MPL-2.0",

"publishConfig": {
- "access": "restricted"
+ "access": "public"
}
```

**`platform-sdk-aws`** — `src/config.ts:44`:

```diff
- (awsProfile === 'jupiterone-dev' ? 'us-east-1' : undefined)
+ (process.env.AWS_DEFAULT_REGION || undefined)
```

**`platform-sdk-headers`** — `src/index.ts:120-121`:

```diff
- // The JupiterOne-Forwards-acirciapo header is set by our CF distribution and gateways
- // based on how many additional forwards there are between the CF distribution and the lambda:
+ // The JupiterOne-Forwards-acirciapo header is set by the CDN distribution and gateways
+ // based on how many additional forwards there are between the CDN distribution and the handler:
```

**`platform-sdk-iam`** — No code change. The `lifeomic-*` header names are a
runtime contract across all consumers. Renaming would be a breaking change. Not
a security vulnerability.

**Root** — Add `LICENSE` file with MPL-2.0 text. Update root `package.json`
license to `MPL-2.0`.

### PR Strategy

Single PR to `platform-sdk` repo:

- Title: `chore: publish 17 packages as public with MPL-2.0 license`
- 17 `package.json` updates
- 2 code fixes (aws, headers)
- Root LICENSE file + root package.json license field

### Validation

**Before merge:**

1. CI passes (all existing tests)
2. Verify `platform-sdk-aws` config change doesn't break tests
3. `npm pack` dry-run on a few packages to inspect tarball contents

**After platform-sdk publishes:** 4. Verify public access from unauthenticated
environment:

```
npm view @jupiterone/platform-sdk-fetch
npm view @jupiterone/platform-sdk-errors
npm view @jupiterone/platform-sdk-logging
```

5. Trigger new SDK canary on PR #1188, deploy to dev, check NR logs
6. External consumer simulation:
`npm install @jupiterone/integration-sdk-runtime@canary` in a clean directory
without `.npmrc` auth

### Rollback

npm allows deprecating or unpublishing within 72 hours. Security audit confirmed
no sensitive data, so rollback is unlikely to be needed.

### Timeline

1. Create platform-sdk PR — ~1 hour
2. Review & merge — same day
3. Publish completes — automated via CI
4. Validate SDK canary — ~30 minutes
Loading