Skip to content

Commit fcd1c2b

Browse files
committed
Replace local OAuth with the shared oauth-core package
xAI login and refresh go through @corbits/xai-provider. Callback copy is injected from branding so auth does not import it.
1 parent b07f606 commit fcd1c2b

49 files changed

Lines changed: 931 additions & 1741 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bun.lock

Lines changed: 8 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
},
8282
"dependencies": {
8383
"@corbits/codex-provider": "github:corbitsdev/corbits-codex-provider",
84+
"@corbits/oauth-core": "github:corbitsdev/corbits-oauth-core",
8485
"@corbits/openai-responses": "github:corbitsdev/corbits-openai-responses",
8586
"@corbits/xai-provider": "github:corbitsdev/corbits-xai-provider",
8687
"@intx/agent": "workspace:*",

src/auth/callback-page.test.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import { describe, expect, test } from "bun:test";
22

33
import {
4-
PRODUCT_GITHUB_LABEL,
5-
PRODUCT_GITHUB_URL,
6-
PRODUCT_SITE_LABEL,
7-
PRODUCT_SITE_URL,
8-
} from "../branding.js";
9-
import { callbackPageHtml, humanizeIdentifier } from "./callback-page.js";
10-
import { authorizationDoneHtml } from "./oauth/callback-server.js";
4+
authorizationDoneHtml,
5+
callbackPageHtml,
6+
humanizeIdentifier,
7+
type CallbackPageCopy,
8+
} from "./callback-page.js";
9+
10+
const copy: CallbackPageCopy = {
11+
productName: "Fixture Product",
12+
siteUrl: "https://fixture.example",
13+
siteLabel: "fixture.example",
14+
githubUrl: "https://github.com/fixture",
15+
githubLabel: "github.com/fixture",
16+
};
1117

1218
describe("humanizeIdentifier", () => {
1319
test("machine identifiers lose their separators and lead with a capital", () => {
@@ -24,59 +30,57 @@ describe("humanizeIdentifier", () => {
2430

2531
describe("callbackPageHtml", () => {
2632
test("success names the server that connected", () => {
27-
const html = callbackPageHtml({ subject: "linear" });
33+
const html = callbackPageHtml({ subject: "linear" }, copy);
2834
expect(html).toContain("Linear connected successfully");
2935
expect(html).not.toContain("access_denied");
3036
});
3137

3238
test("provider authorization waits for native setup before claiming connection", () => {
33-
const html = authorizationDoneHtml("Codex");
39+
const html = authorizationDoneHtml("Codex", copy);
3440
expect(html).toContain("Codex authorization received");
3541
expect(html).toContain("finish setup");
3642
expect(html).not.toContain("connected successfully");
3743
});
3844

3945
test("failure names the server and the humanized reason", () => {
40-
const html = callbackPageHtml({
41-
subject: "granola",
42-
error: "access_denied",
43-
});
46+
const html = callbackPageHtml(
47+
{
48+
subject: "granola",
49+
error: "access_denied",
50+
},
51+
copy,
52+
);
4453
expect(html).toContain("Granola failed to connect");
4554
expect(html).toContain("Access denied.");
4655
expect(html).not.toContain("access_denied");
4756
});
4857

4958
test("an unnamed authorization still renders both outcomes", () => {
50-
expect(callbackPageHtml()).toContain("Authorization complete");
51-
expect(callbackPageHtml({ error: "server_error" })).toContain(
59+
expect(callbackPageHtml({}, copy)).toContain("Authorization complete");
60+
expect(callbackPageHtml({ error: "server_error" }, copy)).toContain(
5261
"Authorization did not complete",
5362
);
5463
});
5564

5665
test("the subject is escaped rather than pasted into markup", () => {
57-
expect(callbackPageHtml({ subject: "<script>x</script>" })).not.toContain(
58-
"<script>x",
59-
);
66+
expect(
67+
callbackPageHtml({ subject: "<script>x</script>" }, copy),
68+
).not.toContain("<script>x");
6069
});
6170

62-
test("the footer links to the product site and the GitHub org", () => {
63-
const html = callbackPageHtml({ subject: "linear" });
71+
test("the footer links to the injected site and GitHub copy", () => {
72+
const html = callbackPageHtml({ subject: "linear" }, copy);
6473
const link = (url: string, label: string) =>
6574
`<a href="${url}" target="_blank" rel="noopener noreferrer">${label}</a>`;
66-
expect(html).toContain(link(PRODUCT_SITE_URL, PRODUCT_SITE_LABEL));
67-
expect(html).toContain(link(PRODUCT_GITHUB_URL, PRODUCT_GITHUB_LABEL));
68-
});
69-
70-
test("each footer label names the destination its URL actually points at", () => {
71-
expect(PRODUCT_SITE_URL).toContain(PRODUCT_SITE_LABEL);
72-
expect(PRODUCT_GITHUB_URL).toContain(PRODUCT_GITHUB_LABEL);
75+
expect(html).toContain(link(copy.siteUrl, copy.siteLabel));
76+
expect(html).toContain(link(copy.githubUrl, copy.githubLabel));
7377
});
7478

7579
// An allowlist rather than a shape match: an unexpected origin fails loudly
7680
// instead of passing because it happened to be wrapped in an anchor tag.
7781
const allowedOrigins = new Set([
78-
PRODUCT_SITE_URL,
79-
PRODUCT_GITHUB_URL,
82+
copy.siteUrl,
83+
copy.githubUrl,
8084
// The SVG namespace the wordmark declares; a URI, never fetched.
8185
"http://www.w3.org/2000/svg",
8286
]);
@@ -97,7 +101,7 @@ describe("callbackPageHtml", () => {
97101
["failure", { subject: "linear", error: "access_denied" }],
98102
] as const) {
99103
test(`the ${outcome} page names no off-machine origin beyond the footer links`, () => {
100-
const html = callbackPageHtml(page);
104+
const html = callbackPageHtml(page, copy);
101105
expect(offMachineOrigins(html)).toEqual([]);
102106
expect(html).not.toMatch(
103107
/\b(?:fetch|XMLHttpRequest|WebSocket|EventSource|sendBeacon|importScripts)\s*\(/,

0 commit comments

Comments
 (0)