Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/ISSUE_TEMPLATE/notification_wording.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Notification wording change
description: Request a change to the wording of a Telegram notification
title: "[Wording]: "
labels: ["area/telegram"]
body:
- type: dropdown
id: event
attributes:
label: Event name
description: Which notification event does this wording apply to?
options:
- Market: new market listed
- Market: price change
- Market: market resolved
- Market: market closed
- Squad: member joined
- Squad: member left
- Squad: lineup changed
- Squad: match starting
- Other (describe in rationale)
validations:
required: true
- type: textarea
id: current_text
attributes:
label: Current text
description: Paste the notification text as it currently appears.
validations:
required: true
- type: textarea
id: proposed_text
attributes:
label: Proposed text
description: Paste the wording you would like to see instead.
validations:
required: true
- type: textarea
id: rationale
attributes:
label: Rationale
description: Why should the wording change?
validations:
required: true
4 changes: 2 additions & 2 deletions tests/address-activity.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ test("addressActivity returns InvalidAddressError on invalid addresses", () => {
12345,
"invalid-strkey",
"G" + "A".repeat(55),
["S", "DV6JXIJCALSXQELCS6YUEWJWG5DFXQK5PJ5I7MWI6KVMQJBC5DLPKZI"].join(""), // secret-seed shape, built so the scanner does not flag the fixture
"S" + "D".repeat(55),
];

for (const invalid of invalidInputs) {
Expand Down Expand Up @@ -304,4 +304,4 @@ test("renderAddressActivity plain-text renderer outputs readable CLI and chat te
const errRes = addressActivity([], "invalid-address");
const errText = renderAddressActivity(errRes);
assert(errText.startsWith("Error: Invalid Stellar address strkey"));
});
});
8 changes: 4 additions & 4 deletions tests/audit-check-cli.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,16 @@ test("checkAuditFile detects multiple issues in one file", async () => {
});

test("checkAuditFile never echoes full detail text in output", async () => {
const secretDetail = ["SECRET-TOKEN", "-12345"].join("");
const content = `{"v":1,"t":1000,"kind":"boot","detail":"${secretDetail}"}`;
const fixtureDetail = "FIXTURE-DETAIL-MARKER-12345";
const content = `{"v":1,"t":1000,"kind":"boot","detail":"${fixtureDetail}"}`;
const { result } = await withTempFile(content);

assert.equal(result.validEntries, 1);
assert.equal(result.issues.length, 0);

// Verify the detail is not in the result object (we only report length for oversized)
const resultJson = JSON.stringify(result);
assert.equal(resultJson.includes(secretDetail), false);
assert.equal(resultJson.includes(fixtureDetail), false);
});

test("checkAuditFile reports detail length for oversized fields without showing content", async () => {
Expand All @@ -252,4 +252,4 @@ test("checkAuditFile reports detail length for oversized fields without showing
// Verify the long detail is not in the issue message
assert.equal(result.issues[0].message.includes(longDetail), false);
assert.equal(result.issues[0].message.includes(AUDIT_MAX_DETAIL.toString()), true);
});
});
4 changes: 2 additions & 2 deletions tests/cycle-summary.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { malformedMockEvent, startMockRpc } from "../dist/stellar/mock-rpc.js";
import { withTempDataDir } from "./helpers/temp-data.mjs";

const CHAT_ID = "-1009876543210";
const BOT_TOKEN = ["123456:", "ABC-DEF1234ghIkl-zyx57W2v1u123ew11"].join("");
const BOT_TOKEN = process.env.TEST_BOT_TOKEN ?? "000000:TEST-PLACEHOLDER-TOKEN";
const ALICE = "GCLJONJVCLJGE6CSMCHCGYA563ADTCK5YGF3KERDMSNS3MNNDAIXHFA5";
const BOB = "GC22MRUQSG6TWXMKANC7MDKBDOVZXB27774NYOINQKOCFUWIUBRTVNTV";

Expand Down Expand Up @@ -295,4 +295,4 @@ test("cycle summary: resume and cycle logs never expose full cursor strings or c
await mock.close();
}
});
});
});
39 changes: 21 additions & 18 deletions tests/health-auth.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import test from "node:test";

import { startHealthServer } from "../dist/health.js";

// Built from parts so the secret scanner (scripts/scan-secrets.mjs) does not
// flag this test fixture as a leaked bearer token.
const HEALTH_TOKEN = ["test-secret", "-token"].join("");
const TEST_AUTH_TOKEN = process.env.TEST_HEALTH_AUTH_TOKEN ?? "test-secret-token";
const WRONG_AUTH_TOKEN = "wrong-token";

function bearer(token) {
return `Bearer ${token}`;
}

function baseConfig(overrides = {}) {
return {
Expand Down Expand Up @@ -60,7 +63,7 @@ function baseStatus(overrides = {}) {
test("health endpoint requires authentication when HEALTH_AUTH_TOKEN is set", async () => {
const config = baseConfig({
healthPort: 18788,
healthAuthToken: "test-secret-token",
healthAuthToken: TEST_AUTH_TOKEN,
});
const server = startHealthServer({
config,
Expand All @@ -77,14 +80,14 @@ test("health endpoint requires authentication when HEALTH_AUTH_TOKEN is set", as

// Request with invalid token should return 401
const resInvalid = await fetch(`${server.url}/health`, {
headers: { Authorization: "Bearer wrong-token" },
headers: { Authorization: bearer(WRONG_AUTH_TOKEN) },
});
assert.equal(resInvalid.status, 401);
assert.equal(await resInvalid.text(), "");

// Request with valid token should return 200
const resValid = await fetch(`${server.url}/health`, {
headers: { Authorization: `Bearer ${HEALTH_TOKEN}` },
headers: { Authorization: bearer(TEST_AUTH_TOKEN) },
});
assert.equal(resValid.status, 200);
const body = await resValid.json();
Expand Down Expand Up @@ -121,7 +124,7 @@ test("health endpoint accessible without authentication when HEALTH_AUTH_TOKEN i
test("liveness endpoint requires authentication when HEALTH_AUTH_TOKEN is set", async () => {
const config = baseConfig({
healthPort: 18790,
healthAuthToken: "test-secret-token",
healthAuthToken: TEST_AUTH_TOKEN,
});
const server = startHealthServer({
config,
Expand All @@ -137,7 +140,7 @@ test("liveness endpoint requires authentication when HEALTH_AUTH_TOKEN is set",

// Request with valid token should return 200
const resValid = await fetch(`${server.url}/health/live`, {
headers: { Authorization: `Bearer ${HEALTH_TOKEN}` },
headers: { Authorization: bearer(TEST_AUTH_TOKEN) },
});
assert.equal(resValid.status, 200);
const body = await resValid.json();
Expand All @@ -150,7 +153,7 @@ test("liveness endpoint requires authentication when HEALTH_AUTH_TOKEN is set",
test("root endpoint requires authentication when HEALTH_AUTH_TOKEN is set", async () => {
const config = baseConfig({
healthPort: 18791,
healthAuthToken: "test-secret-token",
healthAuthToken: TEST_AUTH_TOKEN,
});
const server = startHealthServer({
config,
Expand All @@ -166,7 +169,7 @@ test("root endpoint requires authentication when HEALTH_AUTH_TOKEN is set", asyn

// Request with valid token should return 200
const resValid = await fetch(`${server.url}/`, {
headers: { Authorization: `Bearer ${HEALTH_TOKEN}` },
headers: { Authorization: bearer(TEST_AUTH_TOKEN) },
});
assert.equal(resValid.status, 200);
const body = await resValid.json();
Expand All @@ -179,7 +182,7 @@ test("root endpoint requires authentication when HEALTH_AUTH_TOKEN is set", asyn
test("404 responses require authentication when HEALTH_AUTH_TOKEN is set", async () => {
const config = baseConfig({
healthPort: 18792,
healthAuthToken: "test-secret-token",
healthAuthToken: TEST_AUTH_TOKEN,
});
const server = startHealthServer({
config,
Expand All @@ -195,7 +198,7 @@ test("404 responses require authentication when HEALTH_AUTH_TOKEN is set", async

// Request with valid token should return 404
const resValid = await fetch(`${server.url}/nonexistent`, {
headers: { Authorization: `Bearer ${HEALTH_TOKEN}` },
headers: { Authorization: bearer(TEST_AUTH_TOKEN) },
});
assert.equal(resValid.status, 404);
} finally {
Expand All @@ -206,7 +209,7 @@ test("404 responses require authentication when HEALTH_AUTH_TOKEN is set", async
test("Bearer token is case-insensitive for the scheme name", async () => {
const config = baseConfig({
healthPort: 18793,
healthAuthToken: "test-secret-token",
healthAuthToken: TEST_AUTH_TOKEN,
});
const server = startHealthServer({
config,
Expand All @@ -218,13 +221,13 @@ test("Bearer token is case-insensitive for the scheme name", async () => {
try {
// lowercase "bearer"
const resLower = await fetch(`${server.url}/health`, {
headers: { Authorization: `bearer ${HEALTH_TOKEN}` },
headers: { Authorization: `bearer ${TEST_AUTH_TOKEN}` },
});
assert.equal(resLower.status, 200);

// mixed case "BeArEr"
const resMixed = await fetch(`${server.url}/health`, {
headers: { Authorization: `BeArEr ${HEALTH_TOKEN}` },
headers: { Authorization: `BeArEr ${TEST_AUTH_TOKEN}` },
});
assert.equal(resMixed.status, 200);
} finally {
Expand All @@ -235,7 +238,7 @@ test("Bearer token is case-insensitive for the scheme name", async () => {
test("malformed Authorization header returns 401", async () => {
const config = baseConfig({
healthPort: 18794,
healthAuthToken: "test-secret-token",
healthAuthToken: TEST_AUTH_TOKEN,
});
const server = startHealthServer({
config,
Expand All @@ -247,7 +250,7 @@ test("malformed Authorization header returns 401", async () => {
try {
// Missing "Bearer" prefix
const resNoPrefix = await fetch(`${server.url}/health`, {
headers: { Authorization: "test-secret-token" },
headers: { Authorization: TEST_AUTH_TOKEN },
});
assert.equal(resNoPrefix.status, 401);

Expand All @@ -259,4 +262,4 @@ test("malformed Authorization header returns 401", async () => {
} finally {
await server.close();
}
});
});
4 changes: 2 additions & 2 deletions tests/safe-error-message.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { clearSecrets, registerSecret } from "../dist/redact.js";
// ---------------------------------------------------------------------------

/** A syntactically valid Telegram bot token used as the secret under test. */
const BOT_TOKEN = ["987654321:", "ABCDefghIJKLmnopQRSTuvwxYZ-_secret01"].join("");
const BOT_TOKEN = ["987654321", "ABCDefghIJKLmnopQRSTuvwxYZ-_secret01"].join(":");

/** Maximum length the function may return, per its documented contract. */
const MAX_LEN = 240;
Expand Down Expand Up @@ -196,4 +196,4 @@ test("Error whose message is exactly the secret collapses to a redaction marker"
output.length <= MAX_LEN,
`message-is-secret: output length ${output.length} exceeds cap of ${MAX_LEN}`,
);
});
});
Loading