@wipcomputer/wip-ldm-os 0.4.85-alpha.7 → 0.4.85-alpha.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ldm-os",
3
- "version": "0.4.85-alpha.7",
3
+ "version": "0.4.85-alpha.8",
4
4
  "type": "module",
5
5
  "description": "LDM OS: identity, memory, and sovereignty infrastructure for AI agents",
6
6
  "engines": {
@@ -29,6 +29,7 @@
29
29
  "test:bin-manifest": "node scripts/test-bin-manifest.mjs",
30
30
  "test:crc-agentid-tenant-boundary": "node scripts/test-crc-agentid-tenant-boundary.mjs",
31
31
  "test:crc-pair-login-flow": "node scripts/test-crc-pair-login-flow.mjs",
32
+ "test:crc-pair-status-poll-token": "node scripts/test-crc-pair-status-poll-token.mjs",
32
33
  "test:crc-e2ee-session-route": "node scripts/test-crc-e2ee-session-route.mjs",
33
34
  "fmt": "npx prettier --write 'src/**/*.{ts,mjs}' 'lib/**/*.mjs' 'bin/**/*.js'",
34
35
  "fmt:check": "npx prettier --check 'src/**/*.{ts,mjs}' 'lib/**/*.mjs' 'bin/**/*.js'"
@@ -0,0 +1,73 @@
1
+ import { readFileSync } from "node:fs";
2
+
3
+ const server = readFileSync("src/hosted-mcp/server.mjs", "utf8");
4
+
5
+ function assertContains(needle, label) {
6
+ if (!server.includes(needle)) {
7
+ throw new Error(`${label} missing expected text: ${needle}`);
8
+ }
9
+ }
10
+
11
+ function assertNotContains(needle, label) {
12
+ if (server.includes(needle)) {
13
+ throw new Error(`${label} still contains forbidden text: ${needle}`);
14
+ }
15
+ }
16
+
17
+ assertContains("function generateCodexPairPollToken()", "pair poll token generator");
18
+ assertContains('return "ppt_" + randomBytes(32).toString("base64url");', "pair poll token entropy");
19
+ assertContains("function getBearerToken(req)", "bearer token helper");
20
+ assertContains("const pollToken = generateCodexPairPollToken();", "pair-init mints poll token");
21
+ assertContains("poll_token: pollToken,", "pair state stores poll token");
22
+ assertContains("poll_token_used: false,", "pair state tracks token consumption");
23
+ assertContains("pair_poll_token: pollToken,", "pair-init returns poll token to daemon");
24
+ assertContains('json(res, 401, { error: "pair_poll_token_expired" });', "expired token rejected");
25
+ assertContains('json(res, 401, { error: "invalid_pair_poll_token" });', "missing or wrong token rejected");
26
+ assertContains("if (!pollToken || pollToken !== p.poll_token || p.poll_token_used)", "pair-status validates token");
27
+ assertContains("p.poll_token_used = true;", "completed credential response consumes token");
28
+
29
+ function pairStatusModel(pair, bearer, now) {
30
+ if (now > pair.expires) return { code: 401, body: { error: "pair_poll_token_expired" } };
31
+ if (!bearer || bearer !== pair.poll_token || pair.poll_token_used) {
32
+ return { code: 401, body: { error: "invalid_pair_poll_token" } };
33
+ }
34
+ if (pair.status === "completed") {
35
+ pair.poll_token_used = true;
36
+ return { code: 200, body: { status: "completed", api_key: pair.apiKey, handle: pair.handle } };
37
+ }
38
+ return { code: 200, body: { status: pair.status } };
39
+ }
40
+
41
+ const pair = {
42
+ status: "pending",
43
+ expires: 10_000,
44
+ poll_token: "ppt_good",
45
+ poll_token_used: false,
46
+ apiKey: "ck_secret",
47
+ handle: "Parker",
48
+ };
49
+
50
+ if (pairStatusModel({ ...pair }, null, 1).code !== 401) {
51
+ throw new Error("missing poll token should fail");
52
+ }
53
+ if (pairStatusModel({ ...pair }, "ppt_wrong", 1).code !== 401) {
54
+ throw new Error("wrong poll token should fail");
55
+ }
56
+ if (pairStatusModel({ ...pair }, "ppt_good", 20_000).code !== 401) {
57
+ throw new Error("expired poll token should fail");
58
+ }
59
+ if (pairStatusModel({ ...pair }, "ppt_good", 1).body.status !== "pending") {
60
+ throw new Error("correct poll token should return pending before completion");
61
+ }
62
+
63
+ const completedPair = { ...pair, status: "completed" };
64
+ const completed = pairStatusModel(completedPair, "ppt_good", 1);
65
+ if (completed.code !== 200 || completed.body.api_key !== "ck_secret") {
66
+ throw new Error("correct poll token should return completed credential once");
67
+ }
68
+ const replay = pairStatusModel(completedPair, "ppt_good", 1);
69
+ if (replay.code !== 401) {
70
+ throw new Error("reused completed poll token should fail");
71
+ }
72
+
73
+ console.log("crc pair-status poll token checks passed");
@@ -2599,7 +2599,7 @@ const httpServer = createServer(async (req, res) => {
2599
2599
 
2600
2600
  const CODEX_PAIR_EXPIRY_MS = 5 * 60 * 1000;
2601
2601
  const CODEX_PAIR_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
2602
- const codexPairings = {}; // pairing_id -> { code, status, expires, daemon_info, apiKey?, agentId?, handle?, daemon_public_key?, crypto_versions? }
2602
+ const codexPairings = {}; // pairing_id -> { code, status, expires, poll_token, poll_token_used?, daemon_info, apiKey?, agentId?, handle?, daemon_public_key?, crypto_versions? }
2603
2603
  const codexPairingByCode = {}; // code -> pairing_id (only while pending)
2604
2604
  const codexDaemons = new Map(); // agentId -> ws
2605
2605
  const codexWebClients = new Map(); // `${agentId}:${threadId}` -> Set<ws>
@@ -2689,16 +2689,30 @@ function generateCodexPairingCode() {
2689
2689
  throw new Error("Could not generate unique codex-relay pairing code");
2690
2690
  }
2691
2691
 
2692
+ function generateCodexPairPollToken() {
2693
+ return "ppt_" + randomBytes(32).toString("base64url");
2694
+ }
2695
+
2696
+ function getBearerToken(req) {
2697
+ const auth = req.headers["authorization"];
2698
+ if (typeof auth !== "string" || !auth.startsWith("Bearer ")) return null;
2699
+ const token = auth.slice(7).trim();
2700
+ return token || null;
2701
+ }
2702
+
2692
2703
  async function handleCodexPairInit(req, res) {
2693
2704
  let body = {};
2694
2705
  try { body = (await readBody(req)) || {}; } catch {}
2695
2706
  const code = generateCodexPairingCode();
2696
2707
  const pairingId = randomUUID();
2708
+ const pollToken = generateCodexPairPollToken();
2697
2709
  const expires = Date.now() + CODEX_PAIR_EXPIRY_MS;
2698
2710
  codexPairings[pairingId] = {
2699
2711
  code,
2700
2712
  status: "pending",
2701
2713
  expires,
2714
+ poll_token: pollToken,
2715
+ poll_token_used: false,
2702
2716
  daemon_info: {
2703
2717
  hostname: typeof body.hostname === "string" ? body.hostname.slice(0, 64) : null,
2704
2718
  platform: typeof body.platform === "string" ? body.platform.slice(0, 32) : null,
@@ -2721,6 +2735,7 @@ async function handleCodexPairInit(req, res) {
2721
2735
  json(res, 200, {
2722
2736
  code,
2723
2737
  pairing_id: pairingId,
2738
+ pair_poll_token: pollToken,
2724
2739
  web_url: ISSUER_URL + "/login?next=" + encodeURIComponent("/pair/" + code),
2725
2740
  expires_at: new Date(expires).toISOString(),
2726
2741
  });
@@ -2729,11 +2744,19 @@ async function handleCodexPairInit(req, res) {
2729
2744
  function handleCodexPairStatus(req, res, pairingId) {
2730
2745
  const p = codexPairings[pairingId];
2731
2746
  if (!p) { json(res, 404, { error: "pairing not found" }); return; }
2732
- if (p.status === "pending" && Date.now() > p.expires) {
2747
+ if (Date.now() > p.expires) {
2733
2748
  p.status = "expired";
2734
2749
  if (codexPairingByCode[p.code] === pairingId) delete codexPairingByCode[p.code];
2750
+ json(res, 401, { error: "pair_poll_token_expired" });
2751
+ return;
2752
+ }
2753
+ const pollToken = getBearerToken(req);
2754
+ if (!pollToken || pollToken !== p.poll_token || p.poll_token_used) {
2755
+ json(res, 401, { error: "invalid_pair_poll_token" });
2756
+ return;
2735
2757
  }
2736
2758
  if (p.status === "completed") {
2759
+ p.poll_token_used = true;
2737
2760
  json(res, 200, { status: "completed", api_key: p.apiKey, handle: p.handle || p.agentId });
2738
2761
  } else {
2739
2762
  json(res, 200, { status: p.status });