Package Exports
- @karimov-labs/backstage-plugin-devxp-backend
- @karimov-labs/backstage-plugin-devxp-backend/src/index.ts
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@karimov-labs/backstage-plugin-devxp-backend) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@karimov-labs/backstage-plugin-devxp-backend
Backstage backend plugin that powers the Developer Intelligence dashboard. It stores masked developer identity mappings, exposes REST endpoints for hashing/unmasking, and accepts bulk CSV uploads — all backed by the Backstage-managed database (SQLite or PostgreSQL).
This plugin is the backend counterpart to @karimov-labs/backstage-plugin-devxp.
Built for use with the DevXP developer analytics platform.
Features
- Persists
masked_name ↔ real_namepairs in the Backstage database using Knex migrations - SHA-256 hashing algorithm compatible with dev-xp-analyzer:
SHA-256(salt + realName), truncated to 16 hex characters - REST API for hashing, unmasking, bulk CSV upload, and listing/deleting mappings
- Reads salt and API credentials from
app-config.yaml(never exposes them to the frontend) - Runs unauthenticated (access policy:
allow: 'unauthenticated') so the frontend can reach it without an extra auth token
Requirements
| Dependency | Version |
|---|---|
| Backstage | >= 1.30 |
| Node.js | >= 18 |
Installation
1. Install the package
# yarn (Backstage default)
yarn workspace backend add @karimov-labs/backstage-plugin-devxp-backend
# npm
npm install @karimov-labs/backstage-plugin-devxp-backend2. Register the plugin
Edit packages/backend/src/index.ts:
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// ... other plugins
backend.add(import('@karimov-labs/backstage-plugin-devxp-backend'));
backend.start();3. Configure app-config.yaml
devxp:
# Salt used for SHA-256 hashing — must match the salt used in dev-xp-analyzer
salt: ${DEVXP_SALT}
# Whether developer names are masked in the analytics tool
masked: true
# dev-xp-analyzer API credentials (optional)
apiToken: ${DEVXP_API_TOKEN}
apiEndpoint: ${DEVXP_API_ENDPOINT}
projectId: ${DEVXP_PROJECT_ID}Set the corresponding environment variables before starting Backstage:
export DEVXP_SALT="your-secret-salt"
export DEVXP_API_TOKEN="your-api-token" # optional
export DEVXP_API_ENDPOINT="https://..." # optional
export DEVXP_PROJECT_ID="your-project-id" # optionalSecurity note:
saltandapiTokenare read only on the backend and are never serialised into any response.
4. Database
The plugin uses the standard Backstage database service. It automatically creates the devxp_developer_mappings table on startup — no manual migration is needed.
devxp_developer_mappings
├── id INTEGER PRIMARY KEY AUTOINCREMENT
├── masked_name TEXT UNIQUE NOT NULL
├── real_name TEXT NOT NULL
└── created_at DATETIME DEFAULT CURRENT_TIMESTAMPWorks with both SQLite (development) and PostgreSQL (production).
REST API
All endpoints are mounted at /api/devxp/.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check — returns { status: 'ok' } |
GET |
/config |
Non-sensitive configuration status (booleans — never exposes secret values) |
GET |
/mappings |
List all stored masked_name ↔ real_name pairs |
POST |
/mappings/upload |
Upload CSV text; hashes each line and upserts mappings |
POST |
/mappings/delete |
Delete a single mapping by maskedName |
POST |
/unmask |
Look up a real name from a masked name |
POST |
/hash |
Compute the masked hash for a given real name |
Example: upload CSV
curl -X POST http://localhost:7007/api/devxp/mappings/upload \
-H 'Content-Type: application/json' \
-d '{"csvContent": "Alice Smith\nBob Jones\nCarol White"}'Example: unmask
curl -X POST http://localhost:7007/api/devxp/mappings/unmask \
-H 'Content-Type: application/json' \
-d '{"maskedName": "a3f2c1d4e5b67890"}'
# → { "maskedName": "a3f2c1d4e5b67890", "realName": "Alice Smith" }Example: hash
curl -X POST http://localhost:7007/api/devxp/hash \
-H 'Content-Type: application/json' \
-d '{"realName": "Alice Smith"}'
# → { "realName": "Alice Smith", "maskedName": "a3f2c1d4e5b67890" }Hashing algorithm
import { createHash } from 'crypto';
function hashUsername(salt: string, username: string): string {
return createHash('sha256')
.update(salt + username)
.digest('hex')
.substring(0, 16);
}This matches the algorithm used in dev-xp-analyzer. Make sure the same salt value is configured in both systems.
License
Apache-2.0