@sanlam-fintech-digital/mfe-platform-cli
v0.2.7
Published
Bootstrapping and orchestration CLI for the Sanlam Fintech Digital platform
Readme
Sanlam Platform CLI
A bootstrapping and orchestration CLI for the Sanlam Fintech Digital platform.
Overview
@sanlam-fintech-digital/mfe-platform-cli initializes new developer machines by:
- Configuring
.npmrcwith scoped, private npm registries - Authenticating registries using OAuth device flow (Azure DevOps, GitHub)
- Automatically generating Personal Access Tokens for Azure DevOps (one per organization)
- Providing pass-through access to internal CLI tools (future capability)
Installation
Global Install
npm install -g @sanlam-fintech-digital/mfe-platform-cliOne-off Execution
npx @sanlam-fintech-digital/mfe-platform-cli init --config <source>Usage
Initialize Your Machine
The init command sets up your local npm registry configuration with automatic OAuth authentication:
# From remote URL
sft-mfe-platform init --config https://example.com/registry-config.json
# From local file
sft-mfe-platform init --config ./registry-config.json
# Dry-run to preview changes
sft-mfe-platform init --config ./registry-config.json --dry-runThis will:
- Load registry configuration from URL or file
- Store the config source for later updates
- Authenticate via OAuth (GitHub device flow, Azure DevOps PKCE)
- Backup your existing
.npmrcfile (just before modifying) - Update
.npmrcwith registry URLs and authenticated tokens
Update Registry Configuration
After initial setup, update your registry configuration:
# Uses the stored config source and auth options from init
sft-mfe-platform update
# Or specify a different source
sft-mfe-platform update --config https://example.com/registry-config.json
# Override stored auth options if needed
sft-mfe-platform update --config-client-id <new-client-id>Note: The update command automatically reuses the config source URL and authentication options (if any) from your initial init command. You only need to provide --config-auth-* options if you want to override the stored authentication settings.
NuGet Feed Support
The CLI supports configuring NuGet feeds alongside npm registries using a unified configuration.
Configuration Example
{
"authGroups": [
{
"provider": "azure-devops",
"clientId": "your-client-id",
"tenantId": "your-tenant-id",
"registries": [
{
"scope": "@myorg",
"url": "https://pkgs.dev.azure.com/myorg/_packaging/feed/npm/registry/",
"feedType": "npm"
},
{
"scope": "MyOrgNuGet",
"url": "https://pkgs.dev.azure.com/myorg/_packaging/feed/nuget/v3/index.json",
"feedType": "nuget"
}
]
}
]
}Feed Types
- npm (default): npm registries configured in
~/.npmrc - nuget: NuGet feeds configured in platform-specific nuget.config:
- Windows:
%AppData%\NuGet\NuGet.Config - macOS/Linux:
~/.config/NuGet/NuGet.Config
- Windows:
Authentication
Azure DevOps: Same PAT works for both npm and NuGet feeds (vso.packaging scope)
GitHub: OAuth device flow token works for both npm and NuGet feeds (read:packages scope)
Backward Compatibility
Existing configurations work unchanged. The feedType field is optional and defaults to "npm".
Authenticated Config URL
If the config URL requires authentication, use these options:
## Device flow (when using /devicecode)
sft-mfe-platform init \
--config https://example.com/registry-config.json \
--config-auth-endpoint https://login.microsoft.com/<tenantId>/oauth2/v2.0/devicecode \
--config-token-endpoint https://login.microsoft.com/<tenantId>/oauth2/v2.0/token \
--config-client-id <client-id> \
--config-token-kind access \
--config-auth-scope <scope>
## PKCE (when using /authorize)
sft-mfe-platform init \
--config https://example.com/registry-config.json \
--config-auth-endpoint https://login.microsoft.com/<tenantId>/oauth2/v2.0/authorize \
--config-token-endpoint https://login.microsoft.com/<tenantId>/oauth2/v2.0/token \
--config-client-id <client-id> \
--config-token-kind access \
--config-auth-scope <scope>Authentication options are automatically stored: When you provide
--config-auth-*options duringinit, they are saved to~/.sft-mfe-platform/config-source.jsonand automatically reused by theupdatecommand. You don't need to provide them again unless you want to override them.If
--config-token-endpointis omitted, it is derived from the auth endpoint when possible (e.g., replacing/devicecodeor/authorizewith/token, GitHub/device/code→/oauth/access_token). The default token kind isaccessfor all providers, unless overridden. If--config-auth-endpointpoints to GitHub, the default scope isrepo read:packagesunless overridden. If--config-auth-endpointpoints to Entra ID (login.microsoftonline.com), the default scope is499b84ac-1321-427f-aa17-267ca6975798/.defaultunless overridden. Use--config-token-kind idto send the ID token as the bearer token instead of the access token.
Configuration Format
The registry configuration file (JSON) defines authentication groups and optional public registries:
{
"authGroups": [
{
"provider": "github",
"clientId": "Iv1.1234567890abcdef",
"registries": [
{
"scope": "@github-project",
"url": "https://npm.pkg.github.com"
}
]
},
{
"provider": "azure-devops",
"clientId": "your-azure-client-id",
"tenantId": "your-azure-tenant-id",
"registries": [
{
"scope": "@some-scope",
"url": "https://pkgs.dev.azure.com/my-org/_packaging/my-feed/npm/registry/"
},
{
"scope": "@other-scope",
"url": "https://pkgs.dev.azure.com/my-org/_packaging/other-feed/npm/registry/"
}
]
}
],
"registries": [
{
"scope": "@public-scope",
"url": "https://registry.npmjs.org"
}
]
}Configuration Structure
authGroups (optional)
Array of authentication groups, each with:
- provider: Registry provider type (
"azure-devops"or"github") - clientId: OAuth client ID for the provider
- tenantId: Azure AD tenant ID (required for
azure-devopsprovider only) - registries: Array of registries sharing this authentication
- scope: npm scope (e.g.,
@your-org) - url: Registry URL (Azure DevOps Artifacts or GitHub Packages)
- scope: npm scope (e.g.,
Important Limitations:
- GitHub: Only one GitHub auth group is allowed per configuration (GitHub uses a single
_authTokenfornpm.pkg.github.com) - Azure DevOps: Multiple auth groups supported; one PAT generated per organization
registries (optional)
Array of public registries that do not require authentication:
- scope: npm scope
- url: Registry URL
Authentication
Authentication is handled automatically during init using OAuth 2.0 (GitHub device flow, Azure DevOps PKCE):
GitHub Authentication
- User runs
sft-mfe-platform init - CLI displays a device code and verification URL
- User signs in and enters the device code
- CLI receives access token and stores in
.npmrc - All GitHub registries in the auth group use the same token
Permissions: Read-only access to GitHub Packages (read:packages)
Limitation: Only one GitHub auth group is allowed per configuration because GitHub uses a single authentication token for npm.pkg.github.com. All GitHub package registries must be grouped together.
Azure DevOps Authentication
- User runs
sft-mfe-platform init - CLI opens or prints a browser URL for PKCE login
- User signs in via Entra ID and the browser redirects to the registered
redirectUri - CLI exchanges the authorization code for an access token
- CLI generates a Personal Access Token (PAT) for each organization
- PAT is stored in
.npmrcfor each registry
Details:
- Uses Entra ID (Azure AD) OAuth 2.0 Authorization Code with PKCE
- One PAT is generated per Azure DevOps organization
- PAT display name format:
mfe-platform-cli-{organization}-{timestamp}(visible in Azure DevOps token management) - PAT expires after 1 year; re-run
sft-mfe-platform initto refresh - Permissions: Read-only access to package feeds (
vso.packaging)
Dynamic Port & Relay Support
By default, the CLI listens on port 53682 for the PKCE callback (http://localhost:53682/callback).
To support environments where fixed ports are problematic or to use a public relay service:
CLI Option: Use
--config-redirect-uri <url>sft-mfe-platform init --config ... --config-redirect-uri https://relay.example.com/callbackConfiguration: Add
redirectUrito your Azure DevOps auth group in the config JSON.
How it works:
- If a custom redirect URI is provided (non-localhost), the CLI finds a random available local port.
- It sends the port in the
stateparameter as a JSON string (e.g.{"id":"...","port":12345}). - The relay service is expected to parse this JSON state to extract the port and redirect the callback to
http://localhost:<port>/callback.
License
ISC
