openfused 0.3.13 → 0.3.14

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
@@ -181,7 +181,7 @@ Pull peer context, pull their outbox for your mail, push your outbox. Two transp
181
181
 
182
182
  ```bash
183
183
  # LAN — rsync over SSH (uses your ~/.ssh/config for host aliases)
184
- openfuse peer add ssh://alice.local:/home/agent/context --name wisp
184
+ openfuse peer add ssh://your-server:/home/agent/store --name wisp
185
185
 
186
186
  # WAN — HTTP against the OpenFused daemon
187
187
  openfuse peer add https://wisp.openfused.dev --name wisp
@@ -193,7 +193,7 @@ openfuse sync
193
193
  openfuse watch
194
194
 
195
195
  # Watch + reverse SSH tunnel (NAT traversal)
196
- openfuse watch --tunnel alice.local
196
+ openfuse watch --tunnel your-server
197
197
  ```
198
198
 
199
199
  Sync does three things:
@@ -276,7 +276,7 @@ Public mode endpoints:
276
276
  openfuse watch -d ./store # sync every 60s
277
277
  openfuse watch -d ./store --sync-interval 30 # sync every 30s
278
278
  openfuse watch -d ./store --sync-interval 0 # local watch only
279
- openfuse watch -d ./store --tunnel alice.local # + reverse SSH tunnel
279
+ openfuse watch -d ./store --tunnel your-server # + reverse SSH tunnel
280
280
  ```
281
281
 
282
282
  ## Reachability
package/dist/sync.js CHANGED
@@ -203,15 +203,33 @@ async function syncHttp(store, peer, baseUrl, peerDir) {
203
203
  for (const msg of messages) {
204
204
  const ts = (msg.timestamp || new Date().toISOString()).replace(/[:.]/g, "-");
205
205
  const from = msg.from || "unknown";
206
- // SECURITY: sanitize remote-controlled values before constructing local filenames.
207
- // Without this, a malicious "from" like "../../.keys/x" could write outside inbox/.
208
206
  const safeFrom = from.replace(/[^a-zA-Z0-9\-_]/g, "");
209
207
  const safeTs = ts.replace(/[^a-zA-Z0-9\-_]/g, "");
210
208
  const fname = `${safeTs}_from-${safeFrom}_to-${myName}.json`;
209
+ const outboxFile = msg._outboxFile; // filename on sender's outbox
211
210
  const dest = join(inboxDir, fname);
212
211
  if (!existsSync(dest)) {
213
- await writeFile(dest, JSON.stringify(msg, null, 2));
212
+ // Strip the _outboxFile metadata before saving
213
+ const { _outboxFile, ...cleanMsg } = msg;
214
+ await writeFile(dest, JSON.stringify(cleanMsg, null, 2));
214
215
  pulled.push(`outbox→${fname}`);
216
+ // ACK: tell sender to move this message to .sent/
217
+ if (outboxFile) {
218
+ try {
219
+ const ackTs = new Date().toISOString();
220
+ const ackChallenge = `ACK:${myName}:${outboxFile}:${ackTs}`;
221
+ const ackSig = await signChallenge(store.root, ackChallenge);
222
+ await fetch(`${baseUrl}/outbox/${myName}/${outboxFile}`, {
223
+ method: "DELETE",
224
+ headers: {
225
+ "X-OpenFuse-PublicKey": ackSig.publicKey,
226
+ "X-OpenFuse-Signature": ackSig.signature,
227
+ "X-OpenFuse-Timestamp": ackTs,
228
+ },
229
+ });
230
+ }
231
+ catch { } // best-effort ACK
232
+ }
215
233
  }
216
234
  }
217
235
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openfused",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "The file protocol for AI agent context. Encrypted, signed, peer-to-peer.",
5
5
  "license": "MIT",
6
6
  "type": "module",