@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 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 `https://admin.bitmacro.io`, `http://localhost:3000`) |
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
- bitmacro-api (Vercel)
161
+ relay-panel
162
+ │ HTTP + JWT
163
+
164
+ relay-api (Vercel)
156
165
  │ HTTP REST + Bearer JWT
157
166
 
158
- relay-agent this package
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 bitmacro-api. The relay-agent only translates HTTP calls into strfry CLI commands.
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 bitmacro-api, which proxies requests with a shared Bearer token.
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
  ---
@@ -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://admin.bitmacro.io",
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();