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
8 changes: 8 additions & 0 deletions app/gateway/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ export interface GatewayDeps {
export function createGateway(deps: GatewayDeps): Hono {
const app = new Hono();

// The gateway has no UI; people who open its URL in a browser should see that it's running, not a 404.
app.get("/", (c) =>
c.text(
"software-factory gateway is running.\n\n" +
"It has no web UI. GitHub sends webhooks to POST /webhooks/github, and the factory replies on issues and pull requests.\n" +
"Health checks: GET /health and GET /ready. Setup and usage: docs/quickstart.md in your software-factory repository.\n",
),
);
app.get("/health", (c) => c.json({ status: "ok" }));
app.get("/ready", (c) => c.json({ status: "ready" }));

Expand Down
4 changes: 4 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ Setup is complete when:
- applying `factory:triage` produces an App-authored status comment and a
useful outcome.

software-factory has no web UI. You use it through labels and comments in
GitHub. Opening the `factory-gateway` URL in a browser shows only a short
message that the gateway is running.

## Next steps

- [Configuration](configuration.md) — change settings, follow or cancel runs,
Expand Down
3 changes: 3 additions & 0 deletions docs/runbooks/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ and apply it. The form asks for no values.

Continue when both services have deployed and the gateway is live.

The gateway has no web UI. Opening its URL in a browser shows a short
message that it is running; that is expected, not a failed deploy.

## Phase 8: Configure GitHub

Ask for the public gateway URL. It is not a secret. Run:
Expand Down
10 changes: 10 additions & 0 deletions tests/gateway.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ describe("gateway", () => {
expect(await ready.json()).toEqual({ status: "ready" });
});

it("tells a browser at / that the headless gateway is running, without revealing its secret", async () => {
const res = await app.request("/");
expect(res.status).toBe(200);
const text = await res.text();
expect(text).toContain("software-factory gateway is running");
expect(text).toContain("no web UI");
expect(text).not.toContain(SECRET);
expect(startTask).not.toHaveBeenCalled();
});

it("rejects a bad signature before parsing the body", async () => {
const parse = vi.spyOn(JSON, "parse");
const res = await app.fetch(webhook("{not json", { signature: sign("{not json", "wrong") }));
Expand Down
Loading