{"_id":"@agent-society/bls","name":"@agent-society/bls","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@agent-society/bls","version":"1.0.0","description":"Standalone Business Logic Server for ILP-gated Nostr event storage","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup","dev":"tsup --watch"},"keywords":["nostr","ilp","interledger","bls"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ALLiDoizCode/agent-society.git","directory":"packages/bls"},"author":{"name":"ALLiDoizCode"},"publishConfig":{"access":"public"},"dependencies":{"@hono/node-server":"^1.14.0","@toon-format/toon":"^1.0.0","better-sqlite3":"^11.0.0","hono":"^4.0.0","nostr-tools":"^2.20.0"},"devDependencies":{"@types/better-sqlite3":"^7.6.0"},"gitHead":"2b72f950e6f07d3caa9892200c85ff178121dca0","_id":"@agent-society/bls@1.0.0","bugs":{"url":"https://github.com/ALLiDoizCode/agent-society/issues"},"homepage":"https://github.com/ALLiDoizCode/agent-society#readme","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-ahe0no+9xnWQAbDngvdf3F+QCMfSxaK8WBDMfxCBJrXugbav2HrJoYuLP4sFu/WiqKpX2UbQ4qv6iSK7qGooCg==","shasum":"88a46c163b48f818b367a2be6f053a433786ecee","tarball":"https://registry.npmjs.org/@agent-society/bls/-/bls-1.0.0.tgz","fileCount":10,"unpackedSize":135830,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCOAjGzi6bpTj92d2mZXQetk4LnJHItBGB6ZrQn01/rUwIhAJpKYKqWk7BuEHgXIBa3AJ6OVk1/cjN/b9Yet0i+72OM"}]},"_npmUser":{"name":"di3twater","email":"dev.jonathan.green@gmail.com"},"directories":{},"maintainers":[{"name":"di3twater","email":"dev.jonathan.green@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bls_1.0.0_1770828903567_0.94597374581432"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-11T16:55:03.420Z","1.0.0":"2026-02-11T16:55:03.767Z","modified":"2026-02-11T16:55:04.030Z"},"maintainers":[{"name":"di3twater","email":"dev.jonathan.green@gmail.com"}],"description":"Standalone Business Logic Server for ILP-gated Nostr event storage","homepage":"https://github.com/ALLiDoizCode/agent-society#readme","keywords":["nostr","ilp","interledger","bls"],"repository":{"type":"git","url":"git+https://github.com/ALLiDoizCode/agent-society.git","directory":"packages/bls"},"author":{"name":"ALLiDoizCode"},"bugs":{"url":"https://github.com/ALLiDoizCode/agent-society/issues"},"license":"MIT","readme":"# @agent-society/bls\n\nStandalone Business Logic Server (BLS) for ILP-gated Nostr event storage.\n\n## Quick Start\n\n```bash\ndocker pull di3twater/agent-society-bls:latest\n```\n\n```bash\ndocker run -d \\\n  -e NODE_ID=my-node \\\n  -e NOSTR_SECRET_KEY=<64-char-hex-secret-key> \\\n  -e ILP_ADDRESS=g.agent-society.my-node \\\n  -p 3100:3100 \\\n  -v bls-data:/data \\\n  di3twater/agent-society-bls\n```\n\n## Docker Hub\n\nPublished at [`di3twater/agent-society-bls`](https://hub.docker.com/r/di3twater/agent-society-bls).\n\n### Available Tags\n\n| Tag | Description |\n|-----|-------------|\n| `latest` | Most recent build from `main` branch |\n| `X.Y.Z` | Semantic version (from `bls-vX.Y.Z` git tags) |\n| `sha-<short>` | Git commit SHA for traceability |\n\n## Docker Compose\n\nAn example `docker-compose.yml` is provided in [`packages/bls/examples/`](examples/).\n\n### Quickstart\n\n```bash\ncd packages/bls/examples\ncp .env.example .env\n# Edit .env with your values (NOSTR_SECRET_KEY is required)\ndocker compose up\n```\n\n### Integrating into an Existing Compose File\n\nTo add the BLS to your own `docker-compose.yml`:\n\n1. Copy the `bls` service definition from [`examples/docker-compose.yml`](examples/docker-compose.yml)\n2. Add the `bls-data` volume to your top-level `volumes:` section\n3. Set the required environment variables (`NODE_ID`, `NOSTR_SECRET_KEY`, `ILP_ADDRESS`)\n4. Connect the BLS to the same Docker network as your ILP connector\n\nYour connector can reach the BLS at `http://bls:3100/handle-payment` when both services share a network.\n\n## Kubernetes\n\nExample Kubernetes manifests are provided in [`packages/bls/examples/k8s/`](examples/k8s/).\n\n### Quickstart\n\n1. Edit `secret.yaml` with a real `NOSTR_SECRET_KEY` (generate one with `openssl rand -hex 32`)\n2. Edit `configmap.yaml` with your desired `NODE_ID` and `ILP_ADDRESS`\n3. Apply all manifests:\n\n```bash\nkubectl apply -f packages/bls/examples/k8s/\n```\n\nOr use Kustomize:\n\n```bash\nkubectl apply -k packages/bls/examples/k8s/\n```\n\n### Customizing with Kustomize Overlays\n\nThe manifests include a `kustomization.yaml` base. Create overlay directories for different environments:\n\n```\noverlays/\n  production/\n    kustomization.yaml   # references the base, patches as needed\n```\n\nExample overlay `kustomization.yaml`:\n\n```yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nresources:\n  - ../../packages/bls/examples/k8s\npatches:\n  - target:\n      kind: Deployment\n      name: bls\n    patch: |\n      - op: replace\n        path: /spec/template/spec/containers/0/resources/limits/memory\n        value: 512Mi\n```\n\n### What's Included\n\n| Manifest | Purpose |\n|----------|---------|\n| `deployment.yaml` | BLS Deployment with resource limits, probes, and volume mount |\n| `service.yaml` | ClusterIP Service exposing port 3100 |\n| `configmap.yaml` | Non-secret configuration (NODE_ID, ILP_ADDRESS, etc.) |\n| `secret.yaml` | Template for secrets (NOSTR_SECRET_KEY) |\n| `pvc.yaml` | PersistentVolumeClaim for SQLite event storage |\n| `kustomization.yaml` | Kustomize base for easy customization |\n\n## Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `NODE_ID` | Yes | — | Unique node identifier |\n| `NOSTR_SECRET_KEY` | Yes | — | 64-character hex Nostr secret key |\n| `ILP_ADDRESS` | Yes | — | Node's ILP address (e.g., `g.agent-society.node1`) |\n| `BLS_PORT` | No | `3100` | HTTP port to listen on (1–65535) |\n| `BLS_BASE_PRICE_PER_BYTE` | No | `10` | Base price per byte for event storage |\n| `OWNER_PUBKEY` | No | — | 64-char hex pubkey for self-write payment bypass |\n| `DATA_DIR` | No | `/data` | Directory for SQLite database storage |\n| `BLS_KIND_OVERRIDES` | No | — | JSON object mapping event kinds to prices |\n\n### Pricing Variable Aliases\n\nThe pricing variables support multiple naming conventions for backwards compatibility:\n\n- **`BLS_BASE_PRICE_PER_BYTE`** (canonical) — takes precedence\n- `RELAY_BASE_PRICE_PER_BYTE` — fallback\n- `BASE_PRICE_PER_BYTE` — final fallback (unprefixed)\n\n- **`BLS_KIND_OVERRIDES`** (canonical) — takes precedence\n- `RELAY_KIND_OVERRIDES` — fallback\n- `KIND_OVERRIDES` — final fallback (unprefixed)\n\n### Configuration Details\n\n**NODE_ID** — A unique string identifying this node. Used in health check responses and logging.\n\n**NOSTR_SECRET_KEY** — A 64-character lowercase hex string representing your Nostr private key. The corresponding public key is derived automatically and displayed in logs and health responses. The secret key is never logged.\n\n**ILP_ADDRESS** — Must start with `g.` and contain only alphanumeric characters, dots, and hyphens. Example: `g.agent-society.node1`.\n\n**BLS_PORT** — Integer between 1 and 65535. The container exposes this port for HTTP traffic.\n\n**OWNER_PUBKEY** — When set, events signed by this pubkey bypass payment requirements. Must be a valid 64-character hex Nostr public key.\n\n**DATA_DIR** — Directory where the SQLite database (`events.db`) is stored. Mount a Docker volume here for persistence.\n\n**BLS_KIND_OVERRIDES** — JSON object mapping Nostr event kinds to custom prices. Keys are event kind numbers, values are price strings.\n\n```bash\n# Example: kind 0 (metadata) free, kind 30023 (long-form) costs 100 per byte\nBLS_KIND_OVERRIDES='{\"0\":\"0\",\"30023\":\"100\"}'\n```\n\n## Endpoints\n\n### GET /health\n\nHealth check endpoint for container orchestration.\n\n**Response (200 OK):**\n```json\n{\n  \"status\": \"healthy\",\n  \"nodeId\": \"my-node\",\n  \"pubkey\": \"6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3\",\n  \"ilpAddress\": \"g.agent-society.my-node\",\n  \"timestamp\": 1234567890\n}\n```\n\n### POST /handle-payment\n\nVerify an ILP payment and process event storage.\n\n**Request Body:**\n```json\n{\n  \"amount\": \"1000\",\n  \"destination\": \"g.agent-society.my-node\",\n  \"data\": \"<base64-encoded TOON event>\"\n}\n```\n\n**Success Response (200 OK):**\n```json\n{\n  \"accept\": true,\n  \"fulfillment\": \"<base64, SHA-256 of event ID>\",\n  \"metadata\": {\n    \"eventId\": \"<nostr-event-id>\",\n    \"storedAt\": 1234567890\n  }\n}\n```\n\n**Rejection Response (400/500):**\n```json\n{\n  \"accept\": false,\n  \"code\": \"F06\",\n  \"message\": \"Insufficient payment\",\n  \"metadata\": {\n    \"required\": \"1000\",\n    \"received\": \"500\"\n  }\n}\n```\n\n### ILP Error Codes\n\n| Code | Name | Description |\n|------|------|-------------|\n| `F00` | BAD_REQUEST | Malformed request or invalid TOON data |\n| `F06` | INSUFFICIENT_AMOUNT | Payment amount below required price |\n| `T00` | INTERNAL_ERROR | Server-side error during processing |\n","readmeFilename":"README.md","_rev":"1-f2fb940e2dd0a54f8c2eebcdf2082b4b"}