mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-11 17:32:22 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55f8ffb4da | ||
|
|
e3256601cc |
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { wrapSendBody } from "../src/commands/send.js";
|
||||
import { resolveQueueHostDestination } from "../src/commands/queue.js";
|
||||
|
||||
describe("wrapSendBody — pre-release CLI/daemon Item 2 (email-style envelope)", () => {
|
||||
it("renders From / To / body / reply hint with both session names", () => {
|
||||
@@ -23,6 +24,26 @@ describe("wrapSendBody — pre-release CLI/daemon Item 2 (email-style envelope)"
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["human@kernel@host-origin", "human-reviewer@host@host-origin", "alex@external@host-origin"])(
|
||||
"a forwarded person %s gets a queue hint retaining the origin host",
|
||||
(sender) => {
|
||||
const body = "Original body\nkept verbatim.";
|
||||
expect(resolveQueueHostDestination(sender)).toEqual({ ok: true, destination: sender.slice(0, sender.lastIndexOf("@")), hostId: "host-origin" });
|
||||
const out = wrapSendBody(sender, "driver@receiver", body);
|
||||
expect(out).toContain("From: " + sender + "\nTo: driver@receiver\n");
|
||||
expect(out.split("\n---\n")[1]).toBe(body);
|
||||
expect(out.split("\n").at(-1)).toBe("↩ Reply if needed: rig queue create --destination " + sender + ' --human-intent update --summary "<one line>" --evidence-ref "<path>" --body "..." --verify');
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps host-qualified look-alike seats and malformed human triples on the ordinary hint", () => {
|
||||
for (const sender of ["humanity@kernel@host-origin", "human@real-rig@host-origin", "dev-human@host@host-origin",
|
||||
"human@kernel@", "human@kernel@host-origin@extra"]) {
|
||||
expect(wrapSendBody(sender, "driver@receiver", "hi").split("\n").at(-1))
|
||||
.toBe("↩ Reply: rig send " + sender + ' "..."');
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps similarly named real seats on the ordinary reply route", () => {
|
||||
for (const sender of ["human@my-rig", "humanity@kernel", "dev-human@host", "dev-human@rig@origin-host"]) {
|
||||
expect(wrapSendBody(sender, "driver@rig", "hi").split("\n").at(-1))
|
||||
|
||||
@@ -35,6 +35,25 @@ describe("wrapPaneEnvelope — slice 23 envelope renderer (daemon-side)", () =>
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["human@kernel@host-origin", "human-reviewer@host@host-origin", "alex@external@host-origin"])(
|
||||
"a forwarded person %s gets a queue hint retaining the origin host",
|
||||
(sender) => {
|
||||
const body = "Original body\nkept verbatim.";
|
||||
const out = wrapPaneEnvelope(sender, "driver@receiver", body);
|
||||
expect(out).toContain("From: " + sender + "\nTo: driver@receiver\n");
|
||||
expect(out.split("\n---\n")[1]).toBe(body);
|
||||
expect(out.split("\n").at(-1)).toBe("↩ Reply if needed: rig queue create --destination " + sender + ' --human-intent update --summary "<one line>" --evidence-ref "<path>" --body "..." --verify');
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps host-qualified look-alike seats and malformed human triples on the ordinary hint", () => {
|
||||
for (const sender of ["humanity@kernel@host-origin", "human@real-rig@host-origin", "dev-human@host@host-origin",
|
||||
"human@kernel@", "human@kernel@host-origin@extra"]) {
|
||||
expect(wrapPaneEnvelope(sender, "driver@receiver", "hi").split("\n").at(-1))
|
||||
.toBe("↩ Reply: rig send " + sender + ' "..."');
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps similarly named real seats on the ordinary reply route", () => {
|
||||
for (const sender of ["human@my-rig", "humanity@kernel", "dev-human@host", "dev-human@rig@origin-host"]) {
|
||||
expect(wrapPaneEnvelope(sender, "driver@rig", "hi").split("\n").at(-1))
|
||||
|
||||
@@ -15,6 +15,8 @@ import { Hono } from "hono";
|
||||
import type Database from "better-sqlite3";
|
||||
import { createDb } from "../src/db/connection.js";
|
||||
import { migrate } from "../src/db/migrate.js";
|
||||
import { ALL_MIGRATIONS } from "../src/db/all-migrations.js";
|
||||
import { OutboxHandler } from "../src/domain/outbox-handler.js";
|
||||
import { coreSchema } from "../src/db/migrations/001_core_schema.js";
|
||||
import { eventsSchema } from "../src/db/migrations/003_events.js";
|
||||
import { queueItemsSchema } from "../src/db/migrations/024_queue_items.js";
|
||||
@@ -51,8 +53,9 @@ function makeApp(opts: {
|
||||
bus: EventBus;
|
||||
fetchImpl?: typeof fetch;
|
||||
registry?: HostRegistry;
|
||||
repo?: QueueRepository;
|
||||
}): Hono {
|
||||
const queueRepo = new QueueRepository(opts.db, opts.bus, { validateRig: () => true });
|
||||
const queueRepo = opts.repo ?? new QueueRepository(opts.db, opts.bus, { validateRig: () => true });
|
||||
const app = new Hono();
|
||||
app.use("*", async (c, next) => {
|
||||
const set = c.set.bind(c) as (k: string, v: unknown) => void;
|
||||
@@ -152,6 +155,45 @@ describe("MH-3 C1 — cross-host queue create (route)", () => {
|
||||
// stamp the RECEIVER's host onto a bare member@rig — sender-identity FORGERY on
|
||||
// exactly the cross-host path this slice exists to make honest (replies would
|
||||
// route to the wrong host). The not-bare guard then protects it at the remote.
|
||||
it("a forwarded human create reaches the receiver with an origin-qualified queue reply hint", async () => {
|
||||
const receiverDb = createDb(); migrate(receiverDb, ALL_MIGRATIONS);
|
||||
const receiverBus = new EventBus(receiverDb);
|
||||
const receiverRepo = new QueueRepository(receiverDb, receiverBus, { validateRig: () => true });
|
||||
const sends: Array<{ session: string; text: string }> = [];
|
||||
receiverRepo.attachTransport({ async send(session, text) { sends.push({ session, text }); return { ok: true, verified: true }; } });
|
||||
receiverRepo.attachOutbox(new OutboxHandler(receiverDb));
|
||||
const receiver = makeApp({ db: receiverDb, bus: receiverBus, repo: receiverRepo });
|
||||
const forwarded: Record<string, unknown>[] = [];
|
||||
setSelfHostId("host-origin");
|
||||
try {
|
||||
const app = makeApp({ db, bus, fetchImpl: (async (url: string | URL | Request, init?: RequestInit) => {
|
||||
forwarded.push(JSON.parse(String(init?.body)) as Record<string, unknown>);
|
||||
setSelfHostId("host-receiver");
|
||||
try { return await receiver.request(String(url), init); }
|
||||
finally { setSelfHostId("host-origin"); }
|
||||
}) as typeof fetch });
|
||||
const body = "Please check the result.\nKeep my words.";
|
||||
const response = await post(app, { ...BASE, sourceSession: "human@kernel", body, hostId: "vps-b" });
|
||||
expect(response.status).toBe(201);
|
||||
expect(forwarded).toHaveLength(1);
|
||||
expect(forwarded[0]).toMatchObject({ sourceSession: "human@kernel@host-origin", body });
|
||||
expect(forwarded[0]).not.toHaveProperty("hostId");
|
||||
expect(rowCount(db)).toBe(0);
|
||||
const item = await response.json() as { qitemId: string };
|
||||
expect(receiverRepo.getById(item.qitemId)).toMatchObject({ sourceSession: "human@kernel@host-origin", body });
|
||||
await vi.waitFor(() => expect(sends).toHaveLength(1));
|
||||
expect(sends[0]!.session).toBe("dev@rig-b");
|
||||
expect(sends[0]!.text).toContain("From: human@kernel@host-origin\nTo: dev@rig-b");
|
||||
expect(sends[0]!.text).toContain("Queue handoff: " + item.qitemId + " - check your queue.");
|
||||
expect(sends[0]!.text).not.toContain("human@kernel@host-receiver");
|
||||
expect(sends[0]!.text.split("\n").at(-1)).toBe('↩ Reply if needed: rig queue create --destination human@kernel@host-origin --human-intent update --summary "<one line>" --evidence-ref "<path>" --body "..." --verify');
|
||||
} finally {
|
||||
setSelfHostId(null);
|
||||
await new Promise<void>(resolve => setImmediate(resolve));
|
||||
receiverDb.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("cross-host create STAMPS the ORIGIN self-id onto sourceSession at FORWARD (never the receiver)", async () => {
|
||||
setSelfHostId("host-origin");
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user