@bitmacro/relay-agent 0.1.4 → 0.1.5
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.
- package/README.md +14 -5
- package/dist/bin/relay-agent.mjs +34 -1
- package/dist/bin/relay-agent.mjs.map +1 -1
- package/dist/index.mjs +34 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
`relay-agent` is a REST API agent that runs on your relay server and translates HTTP requests into strfry CLI commands. It is part of the [BitMacro Relay Manager](https://bitmacro.io) ecosystem.
|
|
10
10
|
|
|
11
|
+
| Project | Description | License |
|
|
12
|
+
|---------|-------------|---------|
|
|
13
|
+
| **relay-agent** | This repo — REST API for strfry | MIT |
|
|
14
|
+
| [relay-api](https://github.com/bitmacro/relay-api) | Central hub (Supabase, proxy) | Private |
|
|
15
|
+
| [relay-panel](https://github.com/bitmacro/relay-panel) | Frontend | BSL 1.1 |
|
|
16
|
+
|
|
11
17
|
---
|
|
12
18
|
|
|
13
19
|
## Quick Start
|
|
@@ -137,7 +143,7 @@ Authorization: Bearer <your-token>
|
|
|
137
143
|
| `STRFRY_CONFIG` | — | Path to strfry config file (for explicit db path) |
|
|
138
144
|
| `WHITELIST_PATH` | `/etc/strfry/whitelist.txt` | Path to whitelist file |
|
|
139
145
|
| `PORT` | `7800` | HTTP server port |
|
|
140
|
-
| `ALLOWED_ORIGINS` | — | Comma-separated extra CORS origins (defaults include `
|
|
146
|
+
| `ALLOWED_ORIGINS` | — | Comma-separated extra CORS origins (defaults include `relay-panel.bitmacro.cloud`, `relay-panel.bitmacro.pro`, `http://localhost:3000`) |
|
|
141
147
|
|
|
142
148
|
---
|
|
143
149
|
|
|
@@ -152,16 +158,19 @@ Authorization: Bearer <your-token>
|
|
|
152
158
|
## Architecture
|
|
153
159
|
|
|
154
160
|
```
|
|
155
|
-
|
|
161
|
+
relay-panel
|
|
162
|
+
│ HTTP + JWT
|
|
163
|
+
▼
|
|
164
|
+
relay-api (Vercel)
|
|
156
165
|
│ HTTP REST + Bearer JWT
|
|
157
166
|
▼
|
|
158
|
-
relay-agent
|
|
167
|
+
relay-agent (this repo)
|
|
159
168
|
│ child_process spawn()
|
|
160
169
|
▼
|
|
161
170
|
strfry (local C++ process / LMDB)
|
|
162
171
|
```
|
|
163
172
|
|
|
164
|
-
The relay-agent is **stateless** — it has no database. State lives in Supabase, managed by
|
|
173
|
+
The relay-agent is **stateless** — it has no database. State lives in Supabase, managed by relay-api. The relay-agent only translates HTTP calls into strfry CLI commands.
|
|
165
174
|
|
|
166
175
|
---
|
|
167
176
|
|
|
@@ -202,7 +211,7 @@ The relay-agent is **stateless** — it has no database. State lives in Supabase
|
|
|
202
211
|
## Security
|
|
203
212
|
|
|
204
213
|
- **Run on a private network.** The relay-agent should run on the operator's server and **never be exposed directly to the internet**.
|
|
205
|
-
- Access is controlled by the
|
|
214
|
+
- Access is controlled by the relay-api, which proxies requests with a shared Bearer token.
|
|
206
215
|
- Use a strong, random token in production. Rotate it if compromised.
|
|
207
216
|
|
|
208
217
|
---
|
package/dist/bin/relay-agent.mjs
CHANGED
|
@@ -2986,6 +2986,25 @@ async function readWhitelist() {
|
|
|
2986
2986
|
const content = await readFile(WHITELIST_PATH, "utf-8");
|
|
2987
2987
|
return content.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
2988
2988
|
}
|
|
2989
|
+
var PUBKEY_HEX_REGEX = /^[0-9a-f]{64}$/;
|
|
2990
|
+
function isValidPubkey(s) {
|
|
2991
|
+
return PUBKEY_HEX_REGEX.test(s.toLowerCase());
|
|
2992
|
+
}
|
|
2993
|
+
async function getPolicyEntries() {
|
|
2994
|
+
const lines = await readWhitelist();
|
|
2995
|
+
const entries = [];
|
|
2996
|
+
for (const line of lines) {
|
|
2997
|
+
if (line.startsWith("#") || !line) continue;
|
|
2998
|
+
if (line.startsWith("!")) {
|
|
2999
|
+
const pubkey2 = line.slice(1).toLowerCase();
|
|
3000
|
+
if (isValidPubkey(pubkey2)) entries.push({ pubkey: pubkey2, status: "blocked" });
|
|
3001
|
+
continue;
|
|
3002
|
+
}
|
|
3003
|
+
const pubkey = line.toLowerCase();
|
|
3004
|
+
if (isValidPubkey(pubkey)) entries.push({ pubkey, status: "allowed" });
|
|
3005
|
+
}
|
|
3006
|
+
return entries;
|
|
3007
|
+
}
|
|
2989
3008
|
async function writeWhitelist(lines) {
|
|
2990
3009
|
const dir = dirname(WHITELIST_PATH);
|
|
2991
3010
|
if (!existsSync(dir)) {
|
|
@@ -3084,6 +3103,14 @@ statsRoutes.get("/stats", async (c) => {
|
|
|
3084
3103
|
// src/routes/policy.ts
|
|
3085
3104
|
var PUBKEY_REGEX = /^[0-9a-f]{64}$/;
|
|
3086
3105
|
var policyRoutes = new Hono2();
|
|
3106
|
+
policyRoutes.get("/policy", async (c) => {
|
|
3107
|
+
try {
|
|
3108
|
+
const entries = await getPolicyEntries();
|
|
3109
|
+
return c.json({ entries });
|
|
3110
|
+
} catch {
|
|
3111
|
+
return c.json({ error: "relay unavailable" }, 503);
|
|
3112
|
+
}
|
|
3113
|
+
});
|
|
3087
3114
|
policyRoutes.post("/policy/block", async (c) => {
|
|
3088
3115
|
try {
|
|
3089
3116
|
const body = await c.req.json();
|
|
@@ -3137,12 +3164,18 @@ usersRoutes.get("/users", async (c) => {
|
|
|
3137
3164
|
|
|
3138
3165
|
// src/index.ts
|
|
3139
3166
|
var DEFAULT_ORIGINS = [
|
|
3140
|
-
"https://
|
|
3167
|
+
"https://relay-panel.bitmacro.cloud",
|
|
3168
|
+
"https://relay-panel.bitmacro.pro",
|
|
3141
3169
|
"http://localhost:3000"
|
|
3142
3170
|
];
|
|
3143
3171
|
var EXTRA_ORIGINS = (process.env.ALLOWED_ORIGINS ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
3144
3172
|
var ALLOWED_ORIGINS = [...DEFAULT_ORIGINS, ...EXTRA_ORIGINS];
|
|
3145
3173
|
var app = new Hono2();
|
|
3174
|
+
app.use("*", async (c, next) => {
|
|
3175
|
+
const start = Date.now();
|
|
3176
|
+
await next();
|
|
3177
|
+
console.log(`[relay-agent] ${c.req.method} ${c.req.path} ${c.res.status} ${Date.now() - start}ms`);
|
|
3178
|
+
});
|
|
3146
3179
|
app.use("*", cors({ origin: ALLOWED_ORIGINS }));
|
|
3147
3180
|
app.use("*", async (c, next) => {
|
|
3148
3181
|
if (c.req.path === "/health") return next();
|