mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-10-02 04:43:58 +00:00
A new spec at /openfleet and /docs/openfleet replacing the AgentSwarm placeholder. A fleet is every agent session one human answers for; a swarm is the members one spawner starts inside it for one task. One record per session (claimed by the first session that writes its member.start, derived when inherited), one append-only ledger per fleet per host with eight events, five sysop verbs, fifteen rules, and what Claude Code and moshcode would each add. Written from job 172ffd83, which had to reconstruct its own parentage by hand. openswarm keeps its slug (it is the peer-to-peer media family) and gains a one-line pointer. /agent-swarm redirects permanently to /openfleet; the registry entry, home band, catch-all route and scroll hook for the placeholder are replaced or removed. Contract test covers the redirect. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RZV4zJ2pDZLNN3kE5jFCmV
85 lines
3.6 KiB
TypeScript
85 lines
3.6 KiB
TypeScript
// logicsrc.com serves the marketing app, but `logicsrc login` talks to /cli/*,
|
|
// which lives in apps/pwa. These rewrites are what let both live on the apex.
|
|
//
|
|
// The ordering assertion is the important one: CommandBoard owns a catch-all
|
|
// `/api/:path*`, so anything of the credentials app's that lives under /api has
|
|
// to be matched first or CLI auth silently goes to the wrong service.
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { buildRedirects, buildRewrites, commandboardRewrites, credentialsRewrites } from "../next.config";
|
|
|
|
const CRED = "https://creds.example";
|
|
const CB = "https://commandboard.example";
|
|
|
|
const sources = (rules: { source: string }[]) => rules.map((r) => r.source);
|
|
|
|
describe("apex rewrites", () => {
|
|
it("proxies the whole CLI login flow to the credentials app", () => {
|
|
expect(sources(credentialsRewrites(CRED))).toEqual([
|
|
"/cli/:path*",
|
|
"/api/me",
|
|
"/api/credshare/:path*",
|
|
"/auth/:path*",
|
|
]);
|
|
});
|
|
|
|
it("sends /cli to the credentials app, not the marketing app", () => {
|
|
const rule = credentialsRewrites(CRED).find((r) => r.source === "/cli/:path*");
|
|
expect(rule?.destination).toBe(`${CRED}/cli/:path*`);
|
|
});
|
|
|
|
it("includes /auth, because the CLI browser flow redirects there to sign in", () => {
|
|
// /cli/authorize and /cli/device are behind requireAuth. Without /auth
|
|
// proxied, an unauthenticated visitor lands on a 404 mid-login.
|
|
expect(sources(credentialsRewrites(CRED))).toContain("/auth/:path*");
|
|
});
|
|
|
|
it("matches credentials paths BEFORE CommandBoard's /api catch-all", () => {
|
|
const all = buildRewrites(CRED, CB);
|
|
const list = "afterFiles" in all ? all.afterFiles : [];
|
|
const idx = (s: string) => sources(list).indexOf(s);
|
|
|
|
expect(idx("/api/me")).toBeGreaterThanOrEqual(0);
|
|
expect(idx("/api/:path*")).toBeGreaterThanOrEqual(0);
|
|
// The catch-all would otherwise swallow /api/me and /api/credshare/*.
|
|
expect(idx("/api/me")).toBeLessThan(idx("/api/:path*"));
|
|
expect(idx("/api/credshare/:path*")).toBeLessThan(idx("/api/:path*"));
|
|
});
|
|
|
|
it("keeps the existing CommandBoard rules intact", () => {
|
|
expect(sources(commandboardRewrites(CB))).toEqual(["/health", "/api/:path*"]);
|
|
});
|
|
|
|
it("trims a trailing slash so destinations never double up", () => {
|
|
const [first] = credentialsRewrites("https://creds.example/".replace(/\/$/, ""));
|
|
expect(first.destination).toBe("https://creds.example/cli/:path*");
|
|
});
|
|
|
|
it("sends the retired AgentSwarm placeholder path to the OpenFleet spec, permanently", () => {
|
|
// /agent-swarm was in the sitemap and in links for months; the spec it
|
|
// promised is OpenFleet. A 308 keeps every old link and the crawl equity.
|
|
const rule = buildRedirects().find((r) => r.source === "/agent-swarm");
|
|
expect(rule).toEqual({ source: "/agent-swarm", destination: "/openfleet", permanent: true });
|
|
});
|
|
|
|
it("degrades to whichever services are configured", () => {
|
|
// Neither set: unchanged behaviour, no rewrites at all.
|
|
expect(buildRewrites(undefined, undefined)).toEqual([]);
|
|
|
|
// CommandBoard only — exactly what shipped before this change.
|
|
const cbOnly = buildRewrites(undefined, CB);
|
|
expect("afterFiles" in cbOnly ? sources(cbOnly.afterFiles) : []).toEqual([
|
|
"/health",
|
|
"/api/:path*",
|
|
]);
|
|
|
|
// Credentials only, e.g. before CommandBoard is wired up.
|
|
const credOnly = buildRewrites(CRED, undefined);
|
|
expect("afterFiles" in credOnly ? sources(credOnly.afterFiles) : []).toEqual([
|
|
"/cli/:path*",
|
|
"/api/me",
|
|
"/api/credshare/:path*",
|
|
"/auth/:path*",
|
|
]);
|
|
});
|
|
});
|