ugly-app 0.1.734 → 0.1.735

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- export declare const CLI_VERSION = "0.1.734";
1
+ export declare const CLI_VERSION = "0.1.735";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.734";
2
+ export const CLI_VERSION = "0.1.735";
3
3
  //# sourceMappingURL=version.js.map
@@ -26,6 +26,17 @@ export declare function startUglyBotAuthorize(opts?: {
26
26
  scopes?: string[];
27
27
  aiCapCents?: number;
28
28
  }): void;
29
+ /**
30
+ * A dev/preview origin that ugly.bot's `/oauth/silent` redirect mode will reject
31
+ * with 400 "Invalid origin": plain-http (localhost dev servers) or a
32
+ * `*.trycloudflare.com` quick-tunnel (Ugly Studio's Preview panel publishes the
33
+ * dev server there so mobile can reach it). The apex silent-SSO top-level
34
+ * redirect must be skipped for these, or the app strands on ugly.bot's blank 400.
35
+ */
36
+ export declare function isDevPreviewOrigin(loc: {
37
+ protocol: string;
38
+ hostname: string;
39
+ }): boolean;
29
40
  /**
30
41
  * Silent SSO for apex-domain apps (ugly.chat, ugly.press, …) that don't share
31
42
  * ugly.bot's `auth_token` cookie. Adopts an existing ugly.bot session with NO
@@ -1 +1 @@
1
- {"version":3,"file":"startLogin.d.ts","sourceRoot":"","sources":["../../../src/client/auth/startLogin.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,iBAAsB,GAAG,IAAI,CAmCpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,IAAI,CAUN;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAc1C;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,IAAI,IAAI,CAMzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAO1C"}
1
+ {"version":3,"file":"startLogin.d.ts","sourceRoot":"","sources":["../../../src/client/auth/startLogin.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,iBAAsB,GAAG,IAAI,CAmCpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,IAAI,CAUN;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAUvF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAuB1C;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,IAAI,IAAI,CAMzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAO1C"}
@@ -78,6 +78,22 @@ export function startUglyBotAuthorize(opts = {}) {
78
78
  window.location.assign(`${UGLY_BOT_URL}/oauth?${params.toString()}`);
79
79
  }
80
80
  const SILENT_SSO_TRIED_KEY = 'uglySilentSsoTried';
81
+ /**
82
+ * A dev/preview origin that ugly.bot's `/oauth/silent` redirect mode will reject
83
+ * with 400 "Invalid origin": plain-http (localhost dev servers) or a
84
+ * `*.trycloudflare.com` quick-tunnel (Ugly Studio's Preview panel publishes the
85
+ * dev server there so mobile can reach it). The apex silent-SSO top-level
86
+ * redirect must be skipped for these, or the app strands on ugly.bot's blank 400.
87
+ */
88
+ export function isDevPreviewOrigin(loc) {
89
+ const host = loc.hostname;
90
+ return (loc.protocol !== 'https:' ||
91
+ host === 'localhost' ||
92
+ host === '127.0.0.1' ||
93
+ host === '[::1]' ||
94
+ host === '::1' ||
95
+ host.endsWith('.trycloudflare.com'));
96
+ }
81
97
  /**
82
98
  * Silent SSO for apex-domain apps (ugly.chat, ugly.press, …) that don't share
83
99
  * ugly.bot's `auth_token` cookie. Adopts an existing ugly.bot session with NO
@@ -98,6 +114,16 @@ const SILENT_SSO_TRIED_KEY = 'uglySilentSsoTried';
98
114
  export function attemptSilentSso() {
99
115
  if (typeof window === 'undefined')
100
116
  return false;
117
+ // Dev/preview origins — plain-http localhost or a *.trycloudflare.com preview
118
+ // tunnel (Ugly Studio's Preview panel exposes the dev server there for mobile)
119
+ // — are never allow-listed by ugly.bot's `/oauth/silent` redirect mode. It
120
+ // returns 400 "Invalid origin" (an open-redirect guard), and since this is a
121
+ // top-level `location.replace`, the app is STRANDED on that blank error page —
122
+ // "nothing shows up in the preview". Skip the redirect for those origins and
123
+ // render normally (logged-out); the hidden-iframe `silentAuthSync` still adopts
124
+ // a session without navigating away.
125
+ if (isDevPreviewOrigin(window.location))
126
+ return false;
101
127
  try {
102
128
  if (sessionStorage.getItem(SILENT_SSO_TRIED_KEY))
103
129
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"startLogin.js","sourceRoot":"","sources":["../../../src/client/auth/startLogin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"startLogin.js","sourceRoot":"","sources":["../../../src/client/auth/startLogin.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-app",
3
- "version": "0.1.734",
3
+ "version": "0.1.735",
4
4
  "type": "module",
5
5
  "comment:files": "Allowlist what ships to npm. dist = runtime; src = sourcemap targets (dist/*.js.map reference ../../src/); templates = CLI scaffold. Everything else at repo root (.pgdata local Postgres, coverage, assets/icons sources, test/, test-results/) is excluded by omission. The !negations strip the scaffold's installed deps + cruft (templates/node_modules is 200MB+ and must never ship). package.json/README/LICENSE ship automatically.",
6
6
  "files": [
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.734";
2
+ export const CLI_VERSION = "0.1.735";
@@ -30,3 +30,59 @@ describe('startUglyBotAuthorize', () => {
30
30
  expect(url).not.toContain('ai_cap=');
31
31
  });
32
32
  });
33
+
34
+ describe('isDevPreviewOrigin', () => {
35
+ it('flags plain-http, localhost, loopback, and trycloudflare preview origins', async () => {
36
+ const { isDevPreviewOrigin } = await import('./startLogin');
37
+ expect(isDevPreviewOrigin({ protocol: 'http:', hostname: 'localhost' })).toBe(true);
38
+ expect(isDevPreviewOrigin({ protocol: 'http:', hostname: '127.0.0.1' })).toBe(true);
39
+ expect(isDevPreviewOrigin({ protocol: 'https:', hostname: '127.0.0.1' })).toBe(true);
40
+ expect(isDevPreviewOrigin({ protocol: 'https:', hostname: 'abc-def-ghi.trycloudflare.com' })).toBe(true);
41
+ expect(isDevPreviewOrigin({ protocol: 'http:', hostname: 'ugly.press' })).toBe(true); // plain http
42
+ });
43
+ it('does NOT flag real https apex/subdomain production origins', async () => {
44
+ const { isDevPreviewOrigin } = await import('./startLogin');
45
+ expect(isDevPreviewOrigin({ protocol: 'https:', hostname: 'ugly.press' })).toBe(false);
46
+ expect(isDevPreviewOrigin({ protocol: 'https:', hostname: 'ugly.chat' })).toBe(false);
47
+ expect(isDevPreviewOrigin({ protocol: 'https:', hostname: 'code.ugly.bot' })).toBe(false);
48
+ });
49
+ });
50
+
51
+ describe('attemptSilentSso — dev/preview guard', () => {
52
+ function stubLoc(protocol: string, hostname: string): ReturnType<typeof vi.fn> {
53
+ const replace = vi.fn();
54
+ vi.stubGlobal('window', {
55
+ location: { protocol, hostname, origin: `${protocol}//${hostname}`, pathname: '/', search: '', hash: '', replace },
56
+ __UGLY_BOT_URL__: 'https://ugly.bot',
57
+ } as unknown as Window & typeof globalThis);
58
+ vi.stubGlobal('sessionStorage', {
59
+ _m: new Map<string, string>(),
60
+ getItem(k: string) { return this._m.get(k) ?? null; },
61
+ setItem(k: string, v: string) { this._m.set(k, v); },
62
+ removeItem(k: string) { this._m.delete(k); },
63
+ } as unknown as Storage);
64
+ return replace;
65
+ }
66
+
67
+ it('does NOT redirect (renders normally) on a localhost preview origin', async () => {
68
+ const replace = stubLoc('http:', 'localhost');
69
+ const { attemptSilentSso } = await import('./startLogin');
70
+ expect(attemptSilentSso()).toBe(false);
71
+ expect(replace).not.toHaveBeenCalled();
72
+ });
73
+
74
+ it('does NOT redirect on a trycloudflare preview tunnel origin', async () => {
75
+ const replace = stubLoc('https:', 'gamma-delta-epsilon.trycloudflare.com');
76
+ const { attemptSilentSso } = await import('./startLogin');
77
+ expect(attemptSilentSso()).toBe(false);
78
+ expect(replace).not.toHaveBeenCalled();
79
+ });
80
+
81
+ it('DOES redirect to /oauth/silent on a real https apex production origin', async () => {
82
+ const replace = stubLoc('https:', 'ugly.press');
83
+ const { attemptSilentSso } = await import('./startLogin');
84
+ expect(attemptSilentSso()).toBe(true);
85
+ const url = replace.mock.calls[0]?.[0] as string;
86
+ expect(url).toContain('https://ugly.bot/oauth/silent?origin=https%3A%2F%2Fugly.press');
87
+ });
88
+ });
@@ -90,6 +90,25 @@ export function startUglyBotAuthorize(
90
90
 
91
91
  const SILENT_SSO_TRIED_KEY = 'uglySilentSsoTried';
92
92
 
93
+ /**
94
+ * A dev/preview origin that ugly.bot's `/oauth/silent` redirect mode will reject
95
+ * with 400 "Invalid origin": plain-http (localhost dev servers) or a
96
+ * `*.trycloudflare.com` quick-tunnel (Ugly Studio's Preview panel publishes the
97
+ * dev server there so mobile can reach it). The apex silent-SSO top-level
98
+ * redirect must be skipped for these, or the app strands on ugly.bot's blank 400.
99
+ */
100
+ export function isDevPreviewOrigin(loc: { protocol: string; hostname: string }): boolean {
101
+ const host = loc.hostname;
102
+ return (
103
+ loc.protocol !== 'https:' ||
104
+ host === 'localhost' ||
105
+ host === '127.0.0.1' ||
106
+ host === '[::1]' ||
107
+ host === '::1' ||
108
+ host.endsWith('.trycloudflare.com')
109
+ );
110
+ }
111
+
93
112
  /**
94
113
  * Silent SSO for apex-domain apps (ugly.chat, ugly.press, …) that don't share
95
114
  * ugly.bot's `auth_token` cookie. Adopts an existing ugly.bot session with NO
@@ -109,6 +128,15 @@ const SILENT_SSO_TRIED_KEY = 'uglySilentSsoTried';
109
128
  */
110
129
  export function attemptSilentSso(): boolean {
111
130
  if (typeof window === 'undefined') return false;
131
+ // Dev/preview origins — plain-http localhost or a *.trycloudflare.com preview
132
+ // tunnel (Ugly Studio's Preview panel exposes the dev server there for mobile)
133
+ // — are never allow-listed by ugly.bot's `/oauth/silent` redirect mode. It
134
+ // returns 400 "Invalid origin" (an open-redirect guard), and since this is a
135
+ // top-level `location.replace`, the app is STRANDED on that blank error page —
136
+ // "nothing shows up in the preview". Skip the redirect for those origins and
137
+ // render normally (logged-out); the hidden-iframe `silentAuthSync` still adopts
138
+ // a session without navigating away.
139
+ if (isDevPreviewOrigin(window.location)) return false;
112
140
  try {
113
141
  if (sessionStorage.getItem(SILENT_SSO_TRIED_KEY)) return false;
114
142
  sessionStorage.setItem(SILENT_SSO_TRIED_KEY, '1');