oceanbus 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +170 -171
  3. package/bin/oceanbus.js +28 -28
  4. package/dist/config/defaults.d.ts.map +1 -1
  5. package/dist/config/defaults.js +3 -6
  6. package/dist/config/defaults.js.map +1 -1
  7. package/dist/config/loader.d.ts.map +1 -1
  8. package/dist/config/loader.js +0 -3
  9. package/dist/config/loader.js.map +1 -1
  10. package/dist/crypto/ed25519.d.ts +6 -0
  11. package/dist/crypto/ed25519.d.ts.map +1 -1
  12. package/dist/crypto/ed25519.js +46 -18
  13. package/dist/crypto/ed25519.js.map +1 -1
  14. package/dist/crypto/index.d.ts +1 -1
  15. package/dist/crypto/index.d.ts.map +1 -1
  16. package/dist/crypto/index.js +3 -1
  17. package/dist/crypto/index.js.map +1 -1
  18. package/dist/index.d.ts +12 -10
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +24 -31
  21. package/dist/index.js.map +1 -1
  22. package/dist/l1/base-client.d.ts.map +1 -1
  23. package/dist/l1/base-client.js +8 -2
  24. package/dist/l1/base-client.js.map +1 -1
  25. package/dist/l1/dispatcher.d.ts +2 -0
  26. package/dist/l1/dispatcher.d.ts.map +1 -1
  27. package/dist/l1/dispatcher.js +12 -0
  28. package/dist/l1/dispatcher.js.map +1 -1
  29. package/dist/l1/index.d.ts +1 -0
  30. package/dist/l1/index.d.ts.map +1 -1
  31. package/dist/l1/index.js.map +1 -1
  32. package/dist/l1/yellow-pages.d.ts +38 -8
  33. package/dist/l1/yellow-pages.d.ts.map +1 -1
  34. package/dist/l1/yellow-pages.js +138 -38
  35. package/dist/l1/yellow-pages.js.map +1 -1
  36. package/dist/quota/manager.d.ts.map +1 -1
  37. package/dist/quota/manager.js +1 -1
  38. package/dist/quota/manager.js.map +1 -1
  39. package/dist/types/config.d.ts +0 -6
  40. package/dist/types/config.d.ts.map +1 -1
  41. package/dist/types/l1.d.ts +17 -7
  42. package/dist/types/l1.d.ts.map +1 -1
  43. package/dist/types/l1.js +12 -0
  44. package/dist/types/l1.js.map +1 -1
  45. package/package.json +52 -52
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 OceanBus
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OceanBus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,171 +1,170 @@
1
- # OceanBus SDK
2
-
3
- AI Agent 通信与信任基础设施 Node.js SDK。
4
-
5
- ## 安装
6
-
7
- ```bash
8
- npm install oceanbus
9
- ```
10
-
11
- ## 快速开始
12
-
13
- ```javascript
14
- const { createOceanBus } = require('oceanbus');
15
-
16
- async function main() {
17
- // 创建实例(自动加载本地持久化身份)
18
- const ob = await createOceanBus();
19
-
20
- // 首次使用需要注册
21
- await ob.register();
22
-
23
- // 获取你的收件地址
24
- const myOpenid = await ob.getOpenId();
25
-
26
- // 发送消息
27
- await ob.send(targetOpenid, 'Hello OceanBus!');
28
-
29
- // 监听收件
30
- const stop = ob.startListening((msg) => {
31
- console.log(`[${msg.seq_id}] ${msg.from_openid}: ${msg.content}`);
32
- });
33
-
34
- // 退出时清理
35
- await ob.destroy();
36
- }
37
- ```
38
-
39
- ## 配置
40
-
41
- OceanBus 支持四层配置覆盖(高优先级覆盖低优先级):
42
-
43
- 1. 编译默认值
44
- 2. `~/.oceanbus/config.yaml`
45
- 3. 环境变量(`OCEANBUS_*`)
46
- 4. 构造函数参数
47
-
48
- ```javascript
49
- const ob = await createOceanBus({
50
- baseUrl: 'https://prod.example.com/api/l0', // 切换生产服
51
- http: { timeout: 15000 },
52
- quota: { dailyLimit: 500 },
53
- });
54
- ```
55
-
56
- | 环境变量 | 说明 |
57
- |----------|------|
58
- | `OCEANBUS_BASE_URL` | L0 API 地址 |
59
- | `OCEANBUS_DAILY_LIMIT` | 每日消息配额上限 |
60
- | `OCEANBUS_TIMEOUT` | HTTP 超时(毫秒) |
61
- | `OCEANBUS_POLL_INTERVAL` | 轮询间隔(毫秒) |
62
- | `OCEANBUS_API_KEY` | API Key |
63
- | `OCEANBUS_AGENT_ID` | Agent ID |
64
-
65
- ## CLI
66
-
67
- ```bash
68
- oceanbus register # 注册新 Agent
69
- oceanbus whoami # 查看当前身份
70
- oceanbus openid # 获取当前 OpenID
71
- oceanbus send <openid> # 发送消息(支持管道输入)
72
- oceanbus listen # 监听收件
73
- oceanbus block <openid> # 屏蔽发送者
74
- oceanbus keygen # 生成 Ed25519 密钥对
75
- oceanbus key new # 创建新 API Key
76
- oceanbus key revoke <key_id> # 吊销 API Key
77
- ```
78
-
79
- ## API 概览
80
-
81
- ### 身份与密钥
82
-
83
- ```javascript
84
- await ob.register(); // 注册新 Agent
85
- await ob.whoami(); // 查看身份和 OpenID
86
- await ob.getOpenId(); // 获取当前 OpenID
87
- await ob.createApiKey(); // 创建新 API Key
88
- await ob.revokeApiKey('key_id'); // 吊销 API Key
89
- ```
90
-
91
- ### 消息收发
92
-
93
- ```javascript
94
- await ob.send(openid, 'Hello'); // 发送消息
95
- await ob.sendJson(openid, { action: 'test' }); // 发送 JSON
96
- await ob.sync(sinceSeq, limit); // 手动同步消息
97
-
98
- const stop = ob.startListening((msg) => { // 自动监听
99
- console.log(msg.content);
100
- });
101
- ```
102
-
103
- ### 黑名单与反查
104
-
105
- ```javascript
106
- await ob.blockSender(fromOpenid); // 屏蔽
107
- await ob.unblockSender(fromOpenid); // 解除屏蔽
108
- ob.isBlocked(fromOpenid); // 检查是否已屏蔽
109
- await ob.reverseLookup(openid); // 反查 OpenID 真实 ID
110
- ```
111
-
112
- ### 密码学(Ed25519)
113
-
114
- ```javascript
115
- const kp = await ob.crypto.generateKeypair();
116
- const sig = await ob.crypto.sign(kp, { action: 'pay', amount: 100 });
117
- const valid = await ob.crypto.verify(kp.publicKey, { action: 'pay', amount: 100 }, sig);
118
- const canon = ob.crypto.canonicalize({ z: 1, a: 2 }); // {"a":2,"z":1}
119
- ```
120
-
121
- ### 拦截器
122
-
123
- ```javascript
124
- ob.interceptors.register({
125
- name: 'fraud-detector',
126
- priority: 100,
127
- evaluate: async (msg, ctx) => {
128
- if (msg.content.includes('钓鱼')) {
129
- return { action: 'block', reason: 'phishing detected' };
130
- }
131
- return { action: 'pass' };
132
- },
133
- });
134
- ```
135
-
136
- ### 配额
137
-
138
- ```javascript
139
- const usage = ob.quota.getDailyUsage();
140
- // { used: 10, limit: 100, remaining: 90 }
141
- ```
142
-
143
- ## 测试
144
-
145
- ```bash
146
- npm test # 全部测试(单元 + 端到端)
147
- npm run test:unit # 仅单元测试(Jest,86 个用例)
148
- npm run test:e2e # 仅端到端测试(32 个用例)
149
- ```
150
-
151
- ## 服务器迁移
152
-
153
- 切换服务器只需修改 `baseUrl`:
154
-
155
- ```javascript
156
- const ob = await createOceanBus({
157
- baseUrl: 'https://prod.oceanbus.com/api/l0'
158
- });
159
- ```
160
-
161
- 或通过环境变量:
162
-
163
- ```bash
164
- export OCEANBUS_BASE_URL=https://prod.oceanbus.com/api/l0
165
- ```
166
-
167
- L0 API 接口规范不变的前提下,SDK 代码无需任何改动。
168
-
169
- ## License
170
-
171
- MIT
1
+ # OceanBus
2
+
3
+ **AI Agent Communication & Trust Infrastructure** — Your agents need to talk. Zero deployment.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/oceanbus)](https://www.npmjs.com/package/oceanbus)
6
+ [![weekly downloads](https://img.shields.io/npm/dw/oceanbus)](https://www.npmjs.com/package/oceanbus)
7
+ [![license](https://img.shields.io/npm/l/oceanbus)](https://www.npmjs.com/package/oceanbus)
8
+
9
+ ---
10
+
11
+ You built an AI Agent. It works perfectly on localhost. But how does **another developer's Agent** — running on a different continent — discover your Agent and send it a message?
12
+
13
+ Without OceanBus: buy a domain, configure DNS, provision SSL certificates, set up a load balancer, open firewall ports, write a WebSocket reconnect loop, build authentication middleware.
14
+
15
+ **With OceanBus: `ob.register()`.** You get a permanent global address. Messages arrive in a callback. The network handles the rest — end-to-end encrypted, no server required.
16
+
17
+ Now say that other Agent wants to buy something from yours. How does your Agent know the buyer isn't a scammer? OceanBus gives you **reputation queries**, **Ed25519-signed messages** that can't be forged, and a **Yellow Pages** that tells you who's been operating for 300 days with trusted labels — versus someone who registered 30 minutes ago. Your Agent makes the decision. OceanBus provides the evidence.
18
+
19
+ ---
20
+
21
+ ### 🏮 See It In Action
22
+
23
+ **[Ocean Chat](https://clawhub.ai/skills/ocean-chat)** — the official OceanBus lighthouse demo on ClawHub. Two AI agents negotiate a meetup location in 3 rounds, via OceanBus P2P messaging. Zero deployment.
24
+
25
+ ```bash
26
+ clawhub install ocean-chat
27
+ ```
28
+
29
+ Install the skill, register your agent, add a friend, and watch two agents coordinate a meeting place — all through the OceanBus network. You deployed nothing.
30
+
31
+ [Ocean Chat on ClawHub](https://clawhub.ai/skills/ocean-chat)
32
+
33
+ ---
34
+
35
+ ## 30-Second Quickstart
36
+
37
+ ```bash
38
+ npm install oceanbus
39
+ ```
40
+
41
+ ```javascript
42
+ const { createOceanBus } = require('oceanbus');
43
+
44
+ async function main() {
45
+ // Zero config — auto-connects to the OceanBus network
46
+ const ob = await createOceanBus();
47
+
48
+ // One call → you now exist on the global network.
49
+ // You get a permanent Agent ID + API key.
50
+ await ob.register();
51
+
52
+ // This is your global address. Share it like an email address.
53
+ // Any agent, anywhere, can send messages to this address.
54
+ const myOpenid = await ob.getOpenId();
55
+ console.log('Your address:', myOpenid);
56
+
57
+ // Messages arrive here. No webhooks. No polling code.
58
+ // Just a callback. End-to-end encrypted.
59
+ ob.startListening((msg) => {
60
+ console.log(`[${msg.from_openid}] ${msg.content}`);
61
+ });
62
+
63
+ // Send to any agent by their OpenID.
64
+ // The platform cannot read your messages — XChaCha20-Poly1305 blind transport.
65
+ await ob.send('target-openid-here', 'Hello from my agent!');
66
+
67
+ // Clean shutdown
68
+ // await ob.destroy();
69
+ }
70
+
71
+ main();
72
+ ```
73
+
74
+ ---
75
+
76
+ ## What's Inside
77
+
78
+ Organized by what you need — not by module structure.
79
+
80
+ | You want to... | Use this | Details |
81
+ |---------------|----------|---------|
82
+ | **Get a global identity** | `ob.register()` → `ob.getOpenId()` | Permanent address on the OceanBus network. No domain needed. |
83
+ | **Send messages** | `ob.send(openid, text)` | 2000-char limit. End-to-end encrypted (XChaCha20-Poly1305). |
84
+ | **Receive messages** | `ob.startListening(callback)` | Auto-polling. Messages arrive in your callback. |
85
+ | **Find services** | `ob.l1.yellowPages.discover({ tags })` | Discover agents by tag. "Which agents do food delivery?" |
86
+ | **Check reputation** | `ob.l1.reputation.queryReputation([openid])` | Tag distribution, marker profiles, communication topology. You decide who to trust. |
87
+ | **Sign & verify** | `ob.crypto.sign()` / `ob.crypto.verify()` | Ed25519 signatures. Messages cannot be forged or repudiated. |
88
+ | **Block harassers** | `ob.blockSender(openid)` | UUID-level blocking. Changing OpenID doesn't escape the block. |
89
+ | **Custom security** | `ob.interceptors.register(...)` | Plug in your own fraud detector. Priority-ordered pipeline. |
90
+
91
+ ---
92
+
93
+ ## CLI
94
+
95
+ Debug, prototype, and vibe-code from the terminal.
96
+
97
+ ```bash
98
+ npm install -g oceanbus
99
+
100
+ oceanbus register # Register a new Agent
101
+ oceanbus whoami # Show current identity
102
+ oceanbus openid # Print your OpenID
103
+ oceanbus send <openid> # Send a message (supports stdin pipe)
104
+ oceanbus listen # Listen for incoming messages
105
+ oceanbus block <openid> # Block a sender
106
+ oceanbus keygen # Generate an Ed25519 key pair
107
+ oceanbus key new # Create a new API key
108
+ oceanbus key revoke <key_id> # Revoke an API key
109
+ ```
110
+
111
+ Pipe mode:
112
+ ```bash
113
+ echo "Hello world" | oceanbus send ob_xxxxx
114
+ oceanbus listen | jq '.content' # JSON stream on stdout
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Configuration
120
+
121
+ Four-layer override (higher wins):
122
+
123
+ 1. Built-in defaults
124
+ 2. `~/.oceanbus/config.yaml`
125
+ 3. Environment variables (`OCEANBUS_*`)
126
+ 4. Constructor options
127
+
128
+ ```javascript
129
+ const ob = await createOceanBus({
130
+ baseUrl: 'https://prod.example.com/api/l0', // switch servers
131
+ http: { timeout: 15000 },
132
+ });
133
+ ```
134
+
135
+ | Environment variable | Purpose |
136
+ |---------------------|---------|
137
+ | `OCEANBUS_BASE_URL` | L0 API endpoint |
138
+ | `OCEANBUS_API_KEY` | Your API key |
139
+ | `OCEANBUS_AGENT_ID` | Your Agent ID |
140
+ | `OCEANBUS_TIMEOUT` | HTTP timeout (ms) |
141
+ | `OCEANBUS_POLL_INTERVAL` | Poll interval (ms) |
142
+
143
+ ---
144
+
145
+ ## When You Need OceanBus
146
+
147
+ - Your Agent needs to communicate with **other people's Agents** — not just your own
148
+ - You're building a P2P marketplace, booking system, or any multi-Agent service
149
+ - You need trust infrastructure (reputation, signatures, anti-fraud) without building it
150
+ - You want your `localhost:3000` to be reachable by the world without deploying a server
151
+
152
+ ## When You Don't
153
+
154
+ - Your Agent runs alone, on one machine, forever
155
+ - You already have a service mesh or message queue that works
156
+ - You're building an internal pipeline where trust isn't a concern
157
+
158
+ ---
159
+
160
+ ## License
161
+
162
+ MIT
163
+
164
+ ---
165
+
166
+ ## Links
167
+
168
+ - [Ocean Chat — Lighthouse Demo](https://clawhub.ai/skills/ocean-chat) — Two agents negotiate a meetup via OceanBus in 5 minutes
169
+ - [OceanBus Docs](../../../../OceanBusDocs/) — Full API spec, L1 design, growth strategy
170
+ - [OceanBus Constitution](../../../../OCEANBUS-CONSTITUTION.md) — Design principles
package/bin/oceanbus.js CHANGED
@@ -1,28 +1,28 @@
1
- #!/usr/bin/env node
2
- // OceanBus CLI entry point
3
- // After tsc compiles, this file requires dist/cli/index.js
4
-
5
- const path = require('path');
6
- const fs = require('fs');
7
-
8
- // Determine the source root: bin/ lives next to dist/
9
- const distRoot = path.join(__dirname, '..', 'dist');
10
- const cliEntry = path.join(distRoot, 'cli', 'index.js');
11
-
12
- if (fs.existsSync(cliEntry)) {
13
- const { runCli } = require(cliEntry);
14
- runCli();
15
- } else {
16
- // Development mode: try ts-node or fallback
17
- try {
18
- require('ts-node').register({
19
- project: path.join(__dirname, '..', 'tsconfig.json'),
20
- });
21
- const { runCli } = require(path.join(__dirname, '..', 'src', 'cli', 'index'));
22
- runCli();
23
- } catch (tsErr) {
24
- console.error('OceanBus CLI is not built. Run `npx tsc` first.');
25
- console.error('Or install ts-node: npm install -g ts-node');
26
- process.exit(1);
27
- }
28
- }
1
+ #!/usr/bin/env node
2
+ // OceanBus CLI entry point
3
+ // After tsc compiles, this file requires dist/cli/index.js
4
+
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+
8
+ // Determine the source root: bin/ lives next to dist/
9
+ const distRoot = path.join(__dirname, '..', 'dist');
10
+ const cliEntry = path.join(distRoot, 'cli', 'index.js');
11
+
12
+ if (fs.existsSync(cliEntry)) {
13
+ const { runCli } = require(cliEntry);
14
+ runCli();
15
+ } else {
16
+ // Development mode: try ts-node or fallback
17
+ try {
18
+ require('ts-node').register({
19
+ project: path.join(__dirname, '..', 'tsconfig.json'),
20
+ });
21
+ const { runCli } = require(path.join(__dirname, '..', 'src', 'cli', 'index'));
22
+ runCli();
23
+ } catch (tsErr) {
24
+ console.error('OceanBus CLI is not built. Run `npx tsc` first.');
25
+ console.error('Or install ts-node: npm install -g ts-node');
26
+ process.exit(1);
27
+ }
28
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,eAAO,MAAM,QAAQ,EAAE,cAyCtB,CAAC"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,eAAO,MAAM,QAAQ,EAAE,cAsCtB,CAAC"}
@@ -22,7 +22,9 @@ exports.DEFAULTS = {
22
22
  cursorPersistence: true,
23
23
  },
24
24
  l1: {
25
- ypOpenids: [],
25
+ ypOpenids: [
26
+ 'YwvQeEb8X9b394wKxetJ06EV9w5IIglMlucJmbb_gwLbBg_dB50NyB7SYdxBAIObSjdPNprkooxZ3icV',
27
+ ],
26
28
  trustedCAs: [],
27
29
  requestTimeoutMs: 30000,
28
30
  requestPollIntervalMs: 1000,
@@ -31,10 +33,5 @@ exports.DEFAULTS = {
31
33
  interceptor: {
32
34
  enabled: false,
33
35
  },
34
- quota: {
35
- enforceLocal: true,
36
- dailyLimit: 100,
37
- dailyLimitWarnThreshold: 0.8,
38
- },
39
36
  };
40
37
  //# sourceMappingURL=defaults.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";;;AAEa,QAAA,QAAQ,GAAmB;IACtC,OAAO,EAAE,mCAAmC;IAE5C,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS,EAAE,sDAAsD;KAC5E;IAED,IAAI,EAAE;QACJ,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,GAAG;YACnB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,CAAC;SACd;KACF;IAED,OAAO,EAAE;QACP,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,GAAG;QACpB,iBAAiB,EAAE,IAAI;KACxB;IAED,EAAE,EAAE;QACF,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE;QACd,gBAAgB,EAAE,KAAK;QACvB,qBAAqB,EAAE,IAAI;QAC3B,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,uCAAuC;KAC5E;IAED,WAAW,EAAE;QACX,OAAO,EAAE,KAAK;KACf;IAED,KAAK,EAAE;QACL,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,GAAG;QACf,uBAAuB,EAAE,GAAG;KAC7B;CACF,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";;;AAEa,QAAA,QAAQ,GAAmB;IACtC,OAAO,EAAE,mCAAmC;IAE5C,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS,EAAE,sDAAsD;KAC5E;IAED,IAAI,EAAE;QACJ,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,GAAG;YACnB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,CAAC;SACd;KACF;IAED,OAAO,EAAE;QACP,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,GAAG;QACpB,iBAAiB,EAAE,IAAI;KACxB;IAED,EAAE,EAAE;QACF,SAAS,EAAE;YACT,kFAAkF;SACnF;QACD,UAAU,EAAE,EAAE;QACd,gBAAgB,EAAE,KAAK;QACvB,qBAAqB,EAAE,IAAI;QAC3B,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,uCAAuC;KAC5E;IAED,WAAW,EAAE;QACX,OAAO,EAAE,KAAK;KACf;CAEF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA0DrE,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,aAAa,GAAG,cAAc,CAcxE;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAwDrE,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,aAAa,GAAG,cAAc,CAcxE;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
@@ -60,9 +60,6 @@ function envConfig() {
60
60
  if (process.env.OCEANBUS_API_KEY) {
61
61
  result.identity = { agent_id: process.env.OCEANBUS_AGENT_ID || '', api_key: process.env.OCEANBUS_API_KEY };
62
62
  }
63
- const dailyLimit = safeInt(process.env.OCEANBUS_DAILY_LIMIT);
64
- if (dailyLimit !== undefined)
65
- result.quota = { dailyLimit };
66
63
  return result;
67
64
  }
68
65
  function merge(base, ...overrides) {
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,14 @@ import type { Ed25519KeyPair } from '../types/crypto';
2
2
  export declare function generateKeypair(): Promise<Ed25519KeyPair>;
3
3
  export declare function sign(secretKey: Uint8Array, payload: Record<string, unknown>): Promise<string>;
4
4
  export declare function verify(publicKey: Uint8Array, payload: Record<string, unknown>, signature: string): Promise<boolean>;
5
+ export declare function keypairToBase64url(keypair: Ed25519KeyPair): {
6
+ publicKey: string;
7
+ secretKey: string;
8
+ };
9
+ export declare function base64urlToKeypair(publicKeyStr: string, secretKeyStr: string): Ed25519KeyPair;
5
10
  export declare function bufferToHex(buf: Uint8Array): string;
6
11
  export declare function hexToBuffer(hex: string): Uint8Array;
12
+ /** @deprecated Use keypairToBase64url instead. */
7
13
  export declare function keypairToHex(keypair: Ed25519KeyPair): {
8
14
  publicKey: string;
9
15
  secretKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../../src/crypto/ed25519.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtD,wBAAsB,eAAe,IAAI,OAAO,CAAC,cAAc,CAAC,CAI/D;AAED,wBAAsB,IAAI,CACxB,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,MAAM,CAC1B,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAInD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAOnD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAK9F;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,cAAc,CAKvF"}
1
+ {"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../../src/crypto/ed25519.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,wBAAsB,eAAe,IAAI,OAAO,CAAC,cAAc,CAAC,CAI/D;AAED,wBAAsB,IAAI,CACxB,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,MAAM,CAC1B,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAclB;AAcD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAKpG;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,cAAc,CAK7F;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAInD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAOnD;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAG9F;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,cAAc,CAevF"}
@@ -36,14 +36,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.generateKeypair = generateKeypair;
37
37
  exports.sign = sign;
38
38
  exports.verify = verify;
39
+ exports.keypairToBase64url = keypairToBase64url;
40
+ exports.base64urlToKeypair = base64urlToKeypair;
39
41
  exports.bufferToHex = bufferToHex;
40
42
  exports.hexToBuffer = hexToBuffer;
41
43
  exports.keypairToHex = keypairToHex;
42
44
  exports.hexToKeypair = hexToKeypair;
43
45
  const ed = __importStar(require("@noble/ed25519"));
44
46
  const canonical_json_1 = require("./canonical-json");
45
- // Ensure ed25519 has access to crypto (Node 19+ global, or polyfill)
46
- // @noble/ed25519 uses globally available crypto.subtle
47
47
  async function generateKeypair() {
48
48
  const secretKey = ed.utils.randomPrivateKey();
49
49
  const publicKey = await ed.getPublicKeyAsync(secretKey);
@@ -53,25 +53,43 @@ async function sign(secretKey, payload) {
53
53
  const message = (0, canonical_json_1.canonicalize)(payload);
54
54
  const msgBytes = new TextEncoder().encode(message);
55
55
  const sigBytes = await ed.signAsync(msgBytes, secretKey);
56
- return `ed25519:${bufferToHex(sigBytes)}`;
56
+ return `ed25519:${bufferToBase64url(sigBytes)}`;
57
57
  }
58
58
  async function verify(publicKey, payload, signature) {
59
59
  try {
60
60
  const message = (0, canonical_json_1.canonicalize)(payload);
61
61
  const msgBytes = new TextEncoder().encode(message);
62
- let sigBytes;
63
- if (signature.startsWith('ed25519:')) {
64
- sigBytes = hexToBuffer(signature.slice(8));
65
- }
66
- else {
67
- sigBytes = hexToBuffer(signature);
68
- }
62
+ const raw = signature.startsWith('ed25519:')
63
+ ? signature.slice(8)
64
+ : signature;
65
+ const sigBytes = base64urlToBuffer(raw);
69
66
  return await ed.verifyAsync(sigBytes, msgBytes, publicKey);
70
67
  }
71
68
  catch {
72
69
  return false;
73
70
  }
74
71
  }
72
+ // ── base64url encoding (matches backend wire format) ──
73
+ function bufferToBase64url(buf) {
74
+ return Buffer.from(buf).toString('base64url');
75
+ }
76
+ function base64urlToBuffer(s) {
77
+ return Buffer.from(s, 'base64url');
78
+ }
79
+ // ── key serialization (ed25519:<base64url>) ──
80
+ function keypairToBase64url(keypair) {
81
+ return {
82
+ publicKey: `ed25519:${bufferToBase64url(keypair.publicKey)}`,
83
+ secretKey: `ed25519:${bufferToBase64url(keypair.secretKey)}`,
84
+ };
85
+ }
86
+ function base64urlToKeypair(publicKeyStr, secretKeyStr) {
87
+ return {
88
+ publicKey: base64urlToBuffer(publicKeyStr.replace('ed25519:', '')),
89
+ secretKey: base64urlToBuffer(secretKeyStr.replace('ed25519:', '')),
90
+ };
91
+ }
92
+ // ── legacy hex helpers (kept for backward compat) ──
75
93
  function bufferToHex(buf) {
76
94
  return Array.from(buf)
77
95
  .map((b) => b.toString(16).padStart(2, '0'))
@@ -86,16 +104,26 @@ function hexToBuffer(hex) {
86
104
  }
87
105
  return bytes;
88
106
  }
107
+ /** @deprecated Use keypairToBase64url instead. */
89
108
  function keypairToHex(keypair) {
90
- return {
91
- publicKey: `ed25519:${bufferToHex(keypair.publicKey)}`,
92
- secretKey: `ed25519:${bufferToHex(keypair.secretKey)}`,
93
- };
109
+ console.warn('[oceanbus] keypairToHex is deprecated — use keypairToBase64url instead');
110
+ return keypairToBase64url(keypair);
94
111
  }
95
112
  function hexToKeypair(publicKeyHex, secretKeyHex) {
96
- return {
97
- publicKey: hexToBuffer(publicKeyHex.replace('ed25519:', '')),
98
- secretKey: hexToBuffer(secretKeyHex.replace('ed25519:', '')),
99
- };
113
+ const pubStr = publicKeyHex.startsWith('ed25519:') ? publicKeyHex.slice(8) : publicKeyHex;
114
+ const secStr = secretKeyHex.startsWith('ed25519:') ? secretKeyHex.slice(8) : secretKeyHex;
115
+ // Try base64url first (current format), fall back to hex (legacy)
116
+ try {
117
+ return {
118
+ publicKey: base64urlToBuffer(pubStr),
119
+ secretKey: base64urlToBuffer(secStr),
120
+ };
121
+ }
122
+ catch {
123
+ return {
124
+ publicKey: hexToBuffer(pubStr),
125
+ secretKey: hexToBuffer(secStr),
126
+ };
127
+ }
100
128
  }
101
129
  //# sourceMappingURL=ed25519.js.map