|
1 | 1 | import test from "node:test"; |
2 | 2 | import assert from "node:assert/strict"; |
3 | | -import { buildBroadcastCommand, buildCarePackageWhisperPayload, buildMapChatPayload, buildShutdownBroadcastCommand, publishCarePackageWhisper, publishMapChat, validateBroadcastMessage, validateLocalizedTexts, validatePublishLabel } from "../src/rmq.js"; |
| 3 | +import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; |
| 4 | +import { tmpdir } from "node:os"; |
| 5 | +import { join, resolve } from "node:path"; |
| 6 | +import { buildBroadcastCommand, buildCarePackageWhisperPayload, buildMapChatPayload, buildShutdownBroadcastCommand, commandAuthToken, publishCarePackageWhisper, publishMapChat, validateBroadcastMessage, validateLocalizedTexts, validatePublishLabel } from "../src/rmq.js"; |
4 | 7 |
|
5 | 8 | test("builds verified ServiceBroadcast generic command payload", () => { |
6 | 9 | const command = buildBroadcastCommand({ message: "Server event starts soon", durationSec: 45, title: "Event" }); |
@@ -107,6 +110,66 @@ test("validates RabbitMQ publish labels before eval construction", () => { |
107 | 110 | assert.throws(() => validatePublishLabel("bad\"), halt(). %")); |
108 | 111 | }); |
109 | 112 |
|
| 113 | +test("command auth token generates and reuses a local secret file", () => { |
| 114 | + const repoRoot = mkdtempSync(join(tmpdir(), "arrakis-rmq-token-")); |
| 115 | + const previous = process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 116 | + delete process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 117 | + try { |
| 118 | + const tokenFile = resolve(repoRoot, "runtime/secrets/command-auth-token.txt"); |
| 119 | + const token = commandAuthToken(repoRoot); |
| 120 | + assert.match(token, /^[A-Za-z0-9_-]{40,}$/); |
| 121 | + assert.equal(existsSync(tokenFile), true); |
| 122 | + assert.equal(readFileSync(tokenFile, "utf8").trim(), token); |
| 123 | + assert.equal(statSync(tokenFile).mode & 0o777, 0o600); |
| 124 | + assert.equal(commandAuthToken(repoRoot), token); |
| 125 | + } finally { |
| 126 | + if (previous === undefined) { |
| 127 | + delete process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 128 | + } else { |
| 129 | + process.env.DUNE_COMMAND_AUTH_TOKEN = previous; |
| 130 | + } |
| 131 | + rmSync(repoRoot, { recursive: true, force: true }); |
| 132 | + } |
| 133 | +}); |
| 134 | + |
| 135 | +test("command auth token honors explicit environment override", () => { |
| 136 | + const repoRoot = mkdtempSync(join(tmpdir(), "arrakis-rmq-token-env-")); |
| 137 | + const previous = process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 138 | + process.env.DUNE_COMMAND_AUTH_TOKEN = "explicit-token"; |
| 139 | + try { |
| 140 | + const tokenFile = resolve(repoRoot, "runtime/secrets/command-auth-token.txt"); |
| 141 | + assert.equal(commandAuthToken(repoRoot), "explicit-token"); |
| 142 | + assert.equal(existsSync(tokenFile), false); |
| 143 | + } finally { |
| 144 | + if (previous === undefined) { |
| 145 | + delete process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 146 | + } else { |
| 147 | + process.env.DUNE_COMMAND_AUTH_TOKEN = previous; |
| 148 | + } |
| 149 | + rmSync(repoRoot, { recursive: true, force: true }); |
| 150 | + } |
| 151 | +}); |
| 152 | + |
| 153 | +test("command auth token reuses an existing local secret file", () => { |
| 154 | + const repoRoot = mkdtempSync(join(tmpdir(), "arrakis-rmq-token-existing-")); |
| 155 | + const previous = process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 156 | + delete process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 157 | + try { |
| 158 | + const tokenFile = resolve(repoRoot, "runtime/secrets/command-auth-token.txt"); |
| 159 | + mkdirSync(resolve(repoRoot, "runtime/secrets"), { recursive: true }); |
| 160 | + writeFileSync(tokenFile, "existing-local-token\n", { mode: 0o600 }); |
| 161 | + assert.equal(commandAuthToken(repoRoot), "existing-local-token"); |
| 162 | + assert.equal(readFileSync(tokenFile, "utf8"), "existing-local-token\n"); |
| 163 | + } finally { |
| 164 | + if (previous === undefined) { |
| 165 | + delete process.env.DUNE_COMMAND_AUTH_TOKEN; |
| 166 | + } else { |
| 167 | + process.env.DUNE_COMMAND_AUTH_TOKEN = previous; |
| 168 | + } |
| 169 | + rmSync(repoRoot, { recursive: true, force: true }); |
| 170 | + } |
| 171 | +}); |
| 172 | + |
110 | 173 | test("publishes map chat to chat.map routing key", async () => { |
111 | 174 | const originalSpawn = globalThis.__testSpawn; |
112 | 175 | try { |
|
0 commit comments