npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@scoutflo/integration-sdk

v1.0.34

Published

TypeScript SDK for third-party integrations with auth lifecycle management.

Readme

Scoutflo Integration SDK

This project is a TypeScript SDK for managing third-party integrations and their authentication lifecycles, supporting multiple providers and authentication strategies.

Project Structure

  • src/index.ts: SDK entry point, exposes the createSDK function.
  • src/connection-manager.ts: Core logic for managing and resolving connections.
  • src/providers/: Provider-specific logic (e.g., sentry.provider.ts).
  • src/storage/: Storage interface and implementations:
    • mongodb.storage.ts: MongoDB storage provider
    • redis.storage.ts: Redis storage provider
    • storage.interface.ts: Storage provider interface
  • src/strategies/: Authentication strategies:
    • api-key.strategy.ts: API Key auth
    • basic.strategy.ts: Basic Auth
    • mapped-credentials.strategy.ts: provider-mapped static credential auth
    • oauth.strategy.ts: reusable OAuth app lifecycle core for provider adapters
  • src/providers/atlassian-oauth.adapter.ts: Atlassian adapter over the shared OAuth core
  • src/providers/atlassian-oauth.helpers.ts: Atlassian-specific helper functions for state, scope, cache-key, runtime, and sibling-token handling
  • src/types/: Shared types and enums
  • usage/my-service.ts: Example usage of the SDK in a service
  • package.json: Project metadata, scripts, and dependencies
  • tsconfig.json: TypeScript compiler configuration

Setup and Installation

  1. Clone or create the project directory:

    git clone <repo-url>
    cd scoutflo-integration-sdk
  2. Install dependencies:

    npm install

    This will install TypeScript, Zod, and the example database drivers (MongoDB, Redis, Mongoose).

Usage

  1. Ensure your MongoDB and/or Redis instances are running if you are using the provided storage implementations.

  2. Build the project:

    npm run build

    This will compile the TypeScript files into JavaScript in the dist directory.

  3. Use the SDK in your service: See usage/my-service.ts for an example. A minimal example:

    import { Model } from "mongoose";
    import { createSDK } from "../src";
    import { MongoDBStorage } from "../src/storage/mongodb.storage";
    import { Integration } from "../src/types";
    
    const model = new Model<Integration>();
    const storage = new MongoDBStorage(model);
    const sdk = createSDK(storage);
    
    // Create or resolve connections using sdk.createConnection and sdk.resolveConnection

Atlassian Jira/Confluence lifecycle

The SDK now includes adapter-backed lifecycle support for Atlassian Jira, JSM, and Confluence.

Current architecture:

  1. OAuthStrategy owns shared OAuth mechanics such as install URL shell assembly, code exchange, refresh exchange, cache lookup, lock handling, and token invalidation.
  2. AtlassianProvider remains the public Atlassian facade and still owns the resolved runtime contract.
  3. AtlassianOAuthAdapter owns Atlassian-specific callback and refresh orchestration.
  4. atlassian-oauth.helpers.ts owns smaller Atlassian-specific helpers for scope lookup, state shaping, cache-key compatibility, runtime shaping, and sibling refresh-token synchronization.

What is supported:

  1. install URL generation for Atlassian OAuth 3LO through the shared OAuth core
  2. callback handling that returns a single selected-product integration payload
  3. sibling Atlassian integration scope-union support when extending an existing site install
  4. install context recovery through encoded OAuth state for sibling integration installs
  5. Redis-backed short-lived access-token caching with TTL
  6. refresh-token based access-token renewal with sibling Atlassian refresh-token synchronization
  7. normalized Jira/JSM/Confluence resolved runtime output for caller services

Minimal shape:

import Redis from "ioredis";
import { createSDK } from "../src";
import { MongoDBStorage } from "../src/storage/mongodb.storage";
import { RedisStorage } from "../src/storage/redis.storage";

const persistentStorage = new MongoDBStorage(model);
const cacheStorage = new RedisStorage(new Redis(process.env.REDIS_URL));

const sdk = createSDK(persistentStorage, {
  cacheStorage,
  atlassian: {
    clientId: process.env.ATLASSIAN_CLIENT_ID!,
    clientSecret: process.env.ATLASSIAN_CLIENT_SECRET!,
    redirectUri: process.env.ATLASSIAN_REDIRECT_URI!,
    identityResolver: async (userId) => {
      return {
        account_id: "account-id",
        created_by: userId,
      };
    },
  },
});

const install = await sdk.buildInstallUrl({ user_id: "user-123", account_id: "acct-123", provider: "jira" as const });
const callback = await sdk.handleInstallCallback({ code: "oauth-code", state: install.state, provider: "jira" as const });

await sdk.createConnection(callback.integration);

const jiraRuntime = await sdk.resolveConnection("jira-integration-id");

Atlassian install behavior in the current V1 flow:

  • scope union lookup runs only for Atlassian sibling providers (jira, confluence, jsm)
  • sibling scope lookup is account-scoped via account_id
  • refresh-token rotation is synchronized across Atlassian sibling integrations for the same Scoutflo account_id
  • non-Atlassian integrations do not trigger Atlassian scope lookup
  • Redis token cache key format is integration:{provider}:{integration_id}:app_user:{account_id}:access_token
  • Redis refresh lock key format is integration:{provider}:{integration_id}:app_user:{account_id}:refresh_lock
  • resolveConnection() still returns the Atlassian-specific runtime shape from AtlassianProvider

IMPORTANT V1 NOTE:

  • callback now fails fast when Atlassian returns multiple accessible resources.
  • SDK throws atlassian_site_selection_required and does not silently choose accessible-resources[0].
  • product warning: Atlassian multi-site selection UX/API is still pending and must be implemented before broader rollout.
  • backlog item (mandatory): add explicit site-selection contract and persistence rules for multi-site callbacks.

OAuth callback-state security deferral (explicit):

  • accepted risk: callback state is used for context recovery, but it is not yet a signed, replay-protected integrity boundary.
  • do not treat as secure CSRF-grade state yet.
  • why deferred: V1 prioritized lifecycle migration and blast-radius control across SDK, Gateway, and Voyager.
  • owner: Platform Integrations (SDK + Gateway joint ownership)
  • target version/date: SDK 2.0.0 by April 30, 2026
  • mandatory V2 work: signed + replay-resistant state integrity, deterministic reject semantics, and negative tests for tampered/replayed/mismatched callback state.

Important notes:

  1. handleInstallCallback(...) returns the selected Atlassian integration payload but does not persist it automatically.
  2. cacheStorage is required when Atlassian lifecycle support is enabled.
  3. access tokens are cached in Redis per integration, while refresh tokens remain in persistent integration storage.
  4. when a site already has sibling Atlassian integrations, the SDK can extend requested scopes and synchronize rotated refresh tokens across those sibling Atlassian integrations.

Versioning Rule (Documented Policy)

Current decision:

  • keep current semver line for this controlled rollout (no immediate major bump required right now).

Before wider/shared adoption:

  • either bump major to 2.0.0, or
  • make the interface fully backward-compatible and document that compatibility explicitly.

Do not widen adoption without one of the two conditions above being completed.

Rollout Checks Before Preprod/Prod

Run and capture evidence for all three paths before promoting:

  1. Slack install/callback path:
    • npm run test:slack-lifecycle
  2. Slack token refresh path:
    • npm run trace:slack-requested-flow
  3. Atlassian install/callback happy path (current assumptions):
    • npm run test:atlassian-lifecycle

Customization

  • Storage: Implement the IStorageProvider interface in src/storage/storage.interface.ts to connect to your actual data store (e.g., a specific MongoDB database, a different Redis configuration, or another technology).
  • Providers: Add new provider logic in src/providers/ and update the ConnectionManager to support them.
  • Authentication Strategies: Add or modify strategies in src/strategies/ for different authentication methods.
  • Types: Extend or modify types in src/types/ as needed for your integrations.

Scripts

  • npm run build: Compile TypeScript to JavaScript in dist/
  • npm publish: Publish the package (private)

Dependencies

  • typescript, zod, ioredis, mongodb, mongoose, redis

For more details, see the code in the respective directories and the example in usage/my-service.ts.