Skip to content
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ jobs:
TWILIO_FROM_NUMBER: ${{ secrets.TWILIO_FROM_NUMBER }}
TWILIO_VERIFY_SERVICE_SID: ${{ secrets.TWILIO_VERIFY_SERVICE_SID }}
TURNSTILE_SECRET_KEY: ${{ secrets.TURNSTILE_SECRET_KEY }}
TURNSTILE_SITE_KEY: ${{ vars.TURNSTILE_SITE_KEY }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"type": "module",
"scripts": {
"lint": "node --check tool-registry/worker.js && node --check workers/permit-poller/worker.js && node --check workers/permit-poller/catalog.js && node --check workers/permit-poller/adapters.js && node --check workers/permit-poller/service.js && node --check lib/registry.js && node --check lib/queries.js && node --check lib/mcp-server.js && node --check lib/resources.js && node --check scripts/live-acceptance.mjs && node --check scripts/permit-poller-live-check.mjs && node --check scripts/deploy-permit-poller.mjs",
"lint": "node --check tool-registry/worker.js && node --check workers/permit-poller/worker.js && node --check workers/permit-poller/public-site.js && node --check workers/permit-poller/catalog.js && node --check workers/permit-poller/adapters.js && node --check workers/permit-poller/service.js && node --check lib/registry.js && node --check lib/queries.js && node --check lib/mcp-server.js && node --check lib/resources.js && node --check scripts/live-acceptance.mjs && node --check scripts/permit-poller-live-check.mjs && node --check scripts/deploy-permit-poller.mjs",
"test": "node --test tests/registry.test.mjs",
"test:workers": "vitest run --config vitest.config.mjs",
"test:permit-poller": "node --test tests/permit-poller.test.mjs && vitest run --config vitest.permit-poller.config.mjs",
Expand Down
4 changes: 4 additions & 0 deletions scripts/deploy-permit-poller.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const missingSecrets = secretNames.filter((name) => !process.env[name]);
if (missingSecrets.length) {
throw new Error(`Missing required deployment secrets: ${missingSecrets.join(", ")}`);
}
if (!process.env.TURNSTILE_SITE_KEY) {
throw new Error("Missing required deployment variable: TURNSTILE_SITE_KEY");
}

const wrangler = (...args) =>
execFileSync("npx", ["wrangler", ...args], {
Expand Down Expand Up @@ -91,6 +94,7 @@ for (const queueName of queueNames) {

const config = JSON.parse(readFileSync(sourceConfigPath, "utf8"));
config.d1_databases[0].database_id = databaseId;
config.vars.TURNSTILE_SITE_KEY = process.env.TURNSTILE_SITE_KEY;
writeFileSync(deployConfigPath, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });

try {
Expand Down
15 changes: 15 additions & 0 deletions tests/permit-poller.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,18 @@ test("HTTP catalog is no-store and rejects unapproved browser origins", async ()
}), env);
assert.equal(bad.status, 403);
});

test("public signup and compliance pages are served by the alerts Worker", async () => {
const env = { ALLOWED_ORIGINS: "https://alerts.trailgenic.com", TURNSTILE_SITE_KEY: "0x_test" };
const signup = await handleHttp(new Request("https://alerts.trailgenic.com/"), env);
assert.equal(signup.status, 200);
const signupBody = await signup.text();
assert.match(signupBody, /TrailGenic Permit Alert SMS messages/);
assert.match(signupBody, /0x_test/);

for (const path of ["/privacy", "/terms", "/help"]) {
const response = await handleHttp(new Request(`https://alerts.trailgenic.com${path}`), env);
assert.equal(response.status, 200);
assert.equal(response.headers.get("Content-Type"), "text/html; charset=utf-8");
}
});
63 changes: 63 additions & 0 deletions workers/permit-poller/public-site.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions workers/permit-poller/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
verifyTrackerPhone,
validateTrackerInput
} from "./service.js";
import { publicPage } from "./public-site.js";

const JSON_TYPE = "application/json; charset=utf-8";

Expand Down Expand Up @@ -80,6 +81,20 @@ const handleHttp = async (request, env) => {
return new Response(null, { status: 204, headers: corsHeaders(request, env) });
}

if (request.method === "GET") {
const page = publicPage(url.pathname, env);
if (page) {
return new Response(page, {
headers: {
"Content-Type": "text/html; charset=utf-8",
"Cache-Control": "no-store",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin-when-cross-origin"
}
});
}
}

if (request.method === "GET" && url.pathname === "/health") {
try {
const health = await healthSnapshot(env);
Expand Down
2 changes: 1 addition & 1 deletion workers/permit-poller/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
]
},
"vars": {
"ALLOWED_ORIGINS": "https://trailgenic.com,https://www.trailgenic.com",
"ALLOWED_ORIGINS": "https://trailgenic.com,https://www.trailgenic.com,https://alerts.trailgenic.com",
"REQUIRE_TURNSTILE": "true"
}
}