nodejs service OFFICIAL v1.0.1

BSB Registry Core

service-bsb-registry

Event-driven plugin registry core for multi-language BSB plugin storage and discovery

registry plugin marketplace discovery publishing events storage

BSB Registry Core

Event-driven plugin storage and business logic for the BSB plugin registry. This plugin has no HTTP server -- it exposes all operations as BSB returnable events. The companion service-bsb-registry-ui plugin provides the HTTP/web layer.

Configuration

service-bsb-registry:
  database:
    type: file                   # 'file' or 'postgres'
    path: ./.temp/data           # file storage directory (type: file)
  auth:
    requireAuth: true            # require bearer token for write operations
Option Type Default Description
database.type 'file' or 'postgres' 'file' Storage backend
database.path string ./.temp/data Directory for file-based storage
auth.requireAuth boolean true Require authentication for publish/delete

Events

All operations are exposed as returnable events. The UI/API plugin (or any other BSB plugin) calls these via the generated BsbRegistryClient.

Plugin Operations

Event Input Output Description
registry.plugin.publish PublishRequest PublishResponse Publish a new plugin version
registry.plugin.get { org, name, version? } RegistryEntry Get plugin details (latest if no version)
registry.plugin.list ListQuery ListResults List plugins with filtering and pagination
registry.plugin.search SearchQuery SearchResults Full-text search across names, tags, descriptions
registry.plugin.delete { org, name, version? } { success, deleted } Delete a plugin or specific version
registry.plugin.versions { org, name, majorMinor? } VersionList Get all versions of a plugin

Stats and Auth

Event Input Output Description
registry.stats.get {} RegistryStats Total plugins, counts by language/category
registry.auth.login { username, password } { success, token?, message? } Login (not yet implemented -- use tokens)
registry.auth.verify { token } { valid, userId?, permissions? } Verify a bearer token

Publish Request Schema

The publish request is the primary write operation. The body is validated by the UI/API plugin at the HTTP boundary and passed as a structured object through events.

{
  "org": "mycompany",
  "name": "service-my-plugin",
  "version": "1.0.0",
  "language": "nodejs",
  "metadata": {
    "displayName": "My Plugin",
    "description": "Short description of the plugin",
    "category": "service",
    "tags": ["example", "demo"],
    "author": "Author Name",
    "license": "MIT",
    "homepage": "https://example.com",
    "repository": "https://github.com/org/repo"
  },
  "eventSchema": {
    "pluginName": "service-my-plugin",
    "version": "1.0.0",
    "events": {
      "my-plugin.do-something": {
        "type": "returnable",
        "category": "onReturnableEvents",
        "description": "Does something",
        "inputSchema": { "type": "object", "properties": {} },
        "outputSchema": { "type": "object", "properties": {} }
      }
    },
    "dependencies": []
  },
  "configSchema": {
    "type": "object",
    "properties": {
      "port": { "type": "number", "default": 3000, "description": "Server port" }
    },
    "required": ["port"]
  },
  "documentation": [
    "# My Plugin\n\nThis is the main readme content...",
    "# API Reference\n\nDetailed API documentation..."
  ],
  "dependencies": [
    { "id": "bettercorp/service-other", "version": "^1.0.0" }
  ],
  "package": {
    "nodejs": "@mycompany/my-plugin"
  },
  "runtime": {
    "nodejs": ">=18.0.0"
  },
  "visibility": "public"
}

Field Reference

Field Required Type Description
org yes string Organization name (use _ for unaffiliated)
name yes string Plugin name
version yes string Semver version (e.g. 1.0.0)
language yes enum nodejs, csharp, go, java, python
metadata yes object Display info (displayName, description, category, tags, etc.)
eventSchema yes object EventSchemaExport object from build
configSchema no object JSON Schema for plugin configuration (must have type: "object")
documentation yes string[] Array of markdown strings (min 1, max 20). Title extracted from first # heading
dependencies no array Plugin dependencies [{ id, version }]
package no object Language-specific package names (npm, NuGet, etc.)
runtime no object Runtime version requirements
visibility no enum public (default) or private

Version Immutability

Published versions are immutable. Attempting to publish the same org/name/version will return an error. Publish a new version instead.

Storage

File Storage (Default)

Stores plugin data as JSON files in the configured directory. Suitable for development and single-instance deployments.

PostgreSQL (Production)

For multi-instance or high-availability deployments. Set database.type: postgres and provide the connection URL. Migrations run automatically on first start.

Authentication

Authentication is enforced at the HTTP layer (by service-bsb-registry-ui). The core plugin trusts event callers -- if you are calling events directly from another BSB plugin, no token is needed.

API tokens are stored in a JSON file:

{
  "tokens": [
    {
      "name": "ci-deploy",
      "token": "bsb_abc123...",
      "createdAt": "2026-02-13T00:00:00Z",
      "permissions": ["read", "write"]
    }
  ]
}

Permissions:

  • read -- list, search, get plugin details
  • write -- publish and delete plugins
  • admin -- all operations

See Also

Registry File DB

File-based storage backend for the BSB Registry. Stores all data as JSON files in a configurable directory. This is the default storage backend -- suitable for development, single-instance deployments, and small registries.

Configuration

service-bsb-registry:
  database:
    type: file
    path: ./.temp/data

The path is the root directory. All subdirectories and files are created automatically on first startup.

Directory Layout

<path>/
  plugins/
    <org>/
      <name>/
        <version>.json          # RegistryEntry for each published version
  orgs/
    <orgId>.json                # Organization metadata + members
  users.json                    # User[] array
  tokens.json                   # AuthToken[] array

File Schemas

Plugin Version -- plugins/<org>/<name>/<version>.json

One file per published version. Created on publish, never modified (versions are immutable).

{
  "id": "mycompany/service-demo",
  "org": "mycompany",
  "name": "service-demo",
  "displayName": "Demo Service",
  "description": "Example service plugin",
  "version": "1.0.0",
  "majorMinor": "1.0",
  "language": "nodejs",
  "category": "service",
  "tags": ["demo", "example"],
  "visibility": "public",
  "eventSchema": {
    "demo.do-something": {
      "type": "returnable",
      "category": "onReturnableEvents",
      "description": "Does something",
      "inputSchema": { "type": "object", "properties": {} },
      "outputSchema": { "type": "object", "properties": {} }
    }
  },
  "configSchema": {
    "type": "object",
    "properties": {
      "port": { "type": "number", "default": 3000, "description": "Server port" }
    },
    "required": ["port"]
  },
  "documentation": [
    "# Demo Service\n\nMain documentation content..."
  ],
  "dependencies": [],
  "package": {
    "nodejs": "@mycompany/service-demo"
  },
  "runtime": {
    "nodejs": ">=18.0.0"
  },
  "author": {
    "name": "Author Name",
    "email": "author@example.com"
  },
  "license": "MIT",
  "homepage": "https://example.com",
  "repository": "https://github.com/mycompany/service-demo",
  "eventCount": 1,
  "emitEventCount": 0,
  "onEventCount": 0,
  "returnableEventCount": 1,
  "broadcastEventCount": 0,
  "publishedBy": "user-uuid-here",
  "publishedAt": "2026-02-17T00:00:00.000Z",
  "updatedAt": "2026-02-17T00:00:00.000Z",
  "downloads": 0
}

Field Reference

Field Type Required Description
id string yes Full ID (org/name)
org string yes Organization name
name string yes Plugin name
displayName string yes Human-readable name
description string yes Short description (max 1000 chars)
version string yes Semver (1.0.0)
majorMinor string yes Major.minor only (1.0)
language enum yes nodejs, csharp, go, java, python
category enum yes service, observable, events, config
tags string[] yes Searchable keywords
visibility enum yes public or private
eventSchema object yes Events map (Record<eventName, EventExportEntry>)
configSchema object no JSON Schema for plugin config (type: "object")
documentation string[] no Array of markdown strings
dependencies array no [{ id: "org/name", version: "^1.0.0" }]
package object no Language-specific package names
runtime object no Runtime version requirements
author string or object no Author name or { name, email?, url? }
license string no License identifier
homepage string no Documentation URL
repository string no Source repository URL
eventCount int yes Total event count
emitEventCount int yes Fire-and-forget emit events
onEventCount int yes Fire-and-forget on events
returnableEventCount int yes Returnable events
broadcastEventCount int yes Broadcast events
publishedBy string yes User ID or "system"
publishedAt ISO datetime yes First publish timestamp
updatedAt ISO datetime yes Last update timestamp
downloads int no Download count (default 0)

Organization -- orgs/<orgId>.json

One file per organization. Created when an organization is first set up.

{
  "id": "mycompany",
  "name": "mycompany",
  "displayName": "My Company",
  "pluginCount": 0,
  "visibility": "public",
  "members": [
    {
      "userId": "user-uuid-here",
      "permission": "write"
    }
  ]
}
Field Type Required Description
id string yes Organization ID
name string yes Organization name (same as ID)
displayName string yes Human-readable display name
pluginCount int yes Stored count (live count computed on read)
visibility enum yes public or private
members array no [{ userId, permission }]

Member permissions: read or write.

Users -- users.json

Single file containing all registered users as a JSON array.

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Admin User",
    "email": "admin@example.com",
    "active": true,
    "permissions": ["read", "write", "create-org"],
    "createdAt": "2026-02-17T00:00:00.000Z",
    "updatedAt": "2026-02-17T00:00:00.000Z"
  }
]
Field Type Required Description
id UUID yes User ID
name string yes Display name
email string yes Email address
active boolean yes Account active flag
permissions string[] yes User-level permissions: read, write, create-org
createdAt ISO datetime yes Account creation time
updatedAt ISO datetime yes Last update time

Tokens -- tokens.json

Single file containing all API tokens as a JSON array.

[
  {
    "token": "bsb_abc123...",
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "name": "CI deploy",
    "permissions": ["read", "write"],
    "createdAt": "2026-02-17T00:00:00.000Z",
    "expiresAt": null
  }
]
Field Type Required Description
token string yes Bearer token string
userId UUID yes Owner user ID
name string yes Token label (e.g. "CI deploy", "laptop")
permissions string[] no Token-scoped permissions (inherits from user if omitted)
createdAt ISO datetime yes Token creation time
expiresAt ISO datetime no Optional expiration (null = never expires)

Bootstrapping

On first startup, the file DB creates the directory structure and empty users.json / tokens.json files automatically. No manual setup is needed.

To seed initial data, create the files manually before starting the service:

  1. Create users.json with at least one admin user
  2. Create tokens.json with a token tied to that user
  3. Start the service -- it will use the existing files

Generate a token string:

node -e "console.log('bsb_' + require('crypto').randomBytes(32).toString('hex'))"

Limitations

  • Single-writer only -- no concurrent process safety
  • All queries scan files on disk (no indexing)
  • Not suitable for large registries (1000+ plugins)
  • No automatic backups -- back up the data directory yourself

For production or multi-instance deployments, use PostgreSQL (database.type: postgres).

See Also

Installation

Use as a dependency (client reference)
bsb client install service-bsb-registry
Deploy as a service
bsb plugin install service-bsb-registry
Node.js (npm)
npm install @bsb/registry

Configuration

Configuration options for this plugin:

Tree view shows nested config fields and object branches.

database database object
type database.type "file" | "postgres" default: "file"
path database.path string default: "./.temp/data"
auth auth object
requireAuth auth.requireAuth boolean default: true

Events

Events available to clients of this plugin:

Emit and Return

Call these events and receive a response.

registry.plugin.publish returnable

Publish a new plugin or version

Input
org string Organization name
name string Plugin name
version string Semantic version
language "nodejs" | "csharp" | "go" | "java" | "python" Programming language
metadata object Plugin metadata
eventSchema unknown EventSchemaExport object (parsed at HTTP boundary, transported as object)
capabilities unknown optional Plugin capabilities object (parsed at HTTP boundary, optional top-level override)
configSchema unknown optional Configuration JSON Schema object (parsed at HTTP boundary)
typeDefinitions object optional Language-specific type definitions
documentation string[] Array of markdown documentation files (at least 1 required)
dependencies object[] optional Plugin dependencies
package object optional Language-specific package information
runtime object optional Runtime version requirements
visibility "public" | "private" optional Visibility level (default: public)
publishedBy string optional User ID of the publisher (set by HTTP layer)
Returns
success boolean Operation success status
pluginId string Full plugin ID (org/name)
version string Published version
message string optional Success or error message
registry.plugin.get returnable

Get plugin details by org/name

Input
org string Organization name
name string Plugin name
version string optional Version (defaults to latest)
Returns
id string Full ID: org/plugin-name
org string Organization or user name
name string Plugin name
displayName string Human-readable name
description string Short description
version string Semantic version (1.0.0)
majorMinor string Major.minor only (1.0)
language "nodejs" | "csharp" | "go" | "java" | "python" Programming language
package object optional Language-specific package information
category "service" | "observable" | "events" | "config" Plugin category
tags string[] Searchable keywords
author unknown optional Author - either a string or { name, email?, url? }
license string optional License identifier
homepage uri optional Documentation URL
repository uri optional Source repository URL
visibility "public" | "private" Visibility level
eventSchema unknown Events map (Record<eventName, EventExportEntry>)
capabilities unknown optional Plugin capabilities object
configSchema unknown optional Configuration JSON Schema object
typeDefinitions object optional Language-specific type definitions
documentation string[] optional Array of markdown documentation files (at least 1 required)
dependencies object[] optional Plugins this plugin depends on
permissions object[] optional Per-package user permissions
eventCount int32 Total event count
emitEventCount int32 Fire-and-forget emit events
onEventCount int32 Fire-and-forget on events
returnableEventCount int32 Returnable events
broadcastEventCount int32 Broadcast events
publishedBy string User ID who published
publishedAt datetime First publish timestamp
updatedAt datetime Last update timestamp
downloads int32 optional Download count
runtime object optional Runtime version requirements
registry.plugin.list returnable

List plugins with filtering

Input
org string optional Filter by organization
language "nodejs" | "csharp" | "go" | "java" | "python" optional Filter by language
category "service" | "observable" | "events" | "config" optional Filter by category
limit int32 optional Results per page (default: 50)
offset int32 optional Pagination offset (default: 0)
Returns
results object[] Plugin list
total int32 Total count
page int32 Current page number
registry.plugin.search returnable

Search plugins by query

Input
query string Search query string
language "nodejs" | "csharp" | "go" | "java" | "python" optional Filter by language
category "service" | "observable" | "events" | "config" optional Filter by category
limit int32 optional Results per page (default: 20)
offset int32 optional Pagination offset (default: 0)
Returns
results object[] Matching plugins
total int32 Total result count
query string Search query used
registry.plugin.delete returnable

Delete a plugin or specific version

Input
org string Organization name
name string Plugin name
version string optional Version (or all if not provided)
Returns
success boolean Success status
deleted int32 Number of versions deleted
registry.plugin.versions returnable

Get all versions of a plugin

Input
org string Organization name
name string Plugin name
majorMinor string optional Filter by major.minor
Returns
versions object[] All available versions
latest string Latest version
latestForMajorMinor string JSON map of major.minor to latest patch
registry.stats.get returnable

Get registry statistics

Returns
totalPlugins int32 Total plugin count
byLanguage string JSON map of language to count
byCategory string JSON map of category to count
totalDownloads int32 Total downloads across all plugins
registry.auth.login returnable

Authenticate user and get token

Input
username string Username
password string Encrypted password
Returns
success boolean Login success
token string optional Auth token
expiresAt datetime optional Expiration
message string optional Error message
registry.auth.verify returnable

Verify authentication token

Input
token string Token to verify
Returns
valid boolean Token validity
userId string optional User ID
permissions string[] optional

Available Versions

v1.0.1

Dependencies

No dependencies

Metadata