Add Hydra service + migrate (todo §3); pin oryd/hydra:v26.2.0, OAuth2 issuer + login/consent URLs → our app routes
This commit is contained in:
46
src/hydra.test.ts
Normal file
46
src/hydra.test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
// Guards the Ory Hydra config (§3): image pinned to an exact version (AGENTS.md),
|
||||
// migrations run before the server (hydra-migrate → hydra), the DSN targets the hydra
|
||||
// database, the server listens on the public/admin ports, and the issuer +
|
||||
// login/consent/logout URLs point at our app. Real boot is verified by running the
|
||||
// stack; this catches edits.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
const read = (p: string) => readFileSync(new URL(`../${p}`, import.meta.url), "utf8");
|
||||
const compose = read("compose.yml");
|
||||
const hydraYml = read("ory/hydra/hydra.yml");
|
||||
|
||||
test("compose pins both hydra services to one exact version", () => {
|
||||
const tags = [...compose.matchAll(/image:\s*oryd\/hydra:(\S+)/g)].map((m) => m[1]);
|
||||
assert.equal(tags.length, 2, "hydra + hydra-migrate both present");
|
||||
assert.equal(tags[0], tags[1], "both pinned to the same version");
|
||||
const tag = tags[0]!;
|
||||
assert.match(tag, /^v\d+\.\d+\.\d+$/, `${tag} is an exact vMAJOR.MINOR.PATCH`);
|
||||
assert.doesNotMatch(tag, /latest|[\^~*]/, `${tag} is exact, not floating`);
|
||||
});
|
||||
|
||||
test("hydra migrations run once before the server starts", () => {
|
||||
assert.ok((compose.match(/migrate sql -e --yes/g) ?? []).length >= 2,
|
||||
"hydra-migrate runs SQL migrations (alongside kratos)");
|
||||
assert.ok((compose.match(/condition:\s*service_completed_successfully/g) ?? []).length >= 3,
|
||||
"hydra waits for hydra-migrate (alongside kratos's + keto's gates)");
|
||||
});
|
||||
|
||||
test("hydra DSN targets the per-service hydra database", () => {
|
||||
const dsns = [...compose.matchAll(/DSN:\s*(\S+)/g)].map((m) => m[1]).filter((d) => /\/hydra\b/.test(d!));
|
||||
assert.ok(dsns.length >= 2, "both hydra services point DSN at the hydra DB");
|
||||
for (const dsn of dsns) assert.match(dsn!, /@postgres:5432\/hydra\b/, `${dsn} hits the hydra DB`);
|
||||
});
|
||||
|
||||
test("hydra serves OAuth2 on the public + admin ports", () => {
|
||||
assert.match(hydraYml, /public:\s*\n\s*port:\s*4444/, "public API on 4444");
|
||||
assert.match(hydraYml, /admin:\s*\n\s*port:\s*4445/, "admin API on 4445");
|
||||
});
|
||||
|
||||
test("hydra issuer + login/consent/logout URLs point at our app", () => {
|
||||
assert.match(hydraYml, /issuer:\s*http:\/\/127\.0\.0\.1:4444\//, "issuer is the public OAuth2 URL");
|
||||
assert.match(hydraYml, /login:\s*http:\/\/127\.0\.0\.1:3000\/oauth2\/login\b/, "login challenge → our /oauth2/login");
|
||||
assert.match(hydraYml, /consent:\s*http:\/\/127\.0\.0\.1:3000\/oauth2\/consent\b/, "consent challenge → our /oauth2/consent");
|
||||
assert.match(hydraYml, /logout:\s*http:\/\/127\.0\.0\.1:3000\/oauth2\/logout\b/, "logout → our /oauth2/logout");
|
||||
});
|
||||
Reference in New Issue
Block a user