ugly-app 0.1.782 → 0.1.784
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.
- package/dist/cli/auth/cloudflareOauth.d.ts +17 -9
- package/dist/cli/auth/cloudflareOauth.d.ts.map +1 -1
- package/dist/cli/auth/cloudflareOauth.js +66 -36
- package/dist/cli/auth/cloudflareOauth.js.map +1 -1
- package/dist/cli/auth/credentials.d.ts +16 -0
- package/dist/cli/auth/credentials.d.ts.map +1 -1
- package/dist/cli/auth/credentials.js +63 -0
- package/dist/cli/auth/credentials.js.map +1 -1
- package/dist/cli/feedbackResolve.d.ts +20 -7
- package/dist/cli/feedbackResolve.d.ts.map +1 -1
- package/dist/cli/feedbackResolve.js +62 -24
- package/dist/cli/feedbackResolve.js.map +1 -1
- package/dist/cli/index.js +74 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/serverLogQueryApi.d.ts +21 -1
- package/dist/cli/serverLogQueryApi.d.ts.map +1 -1
- package/dist/cli/serverLogQueryApi.js +102 -6
- package/dist/cli/serverLogQueryApi.js.map +1 -1
- package/dist/cli/telemetryAuth.d.ts.map +1 -1
- package/dist/cli/telemetryAuth.js +11 -4
- package/dist/cli/telemetryAuth.js.map +1 -1
- package/dist/cli/version.d.ts +1 -1
- package/dist/cli/version.js +1 -1
- package/dist/native/server/binaries/installer.js +29 -3
- package/dist/native/server/binaries/installer.js.map +1 -1
- package/dist/server/App.d.ts.map +1 -1
- package/dist/server/App.js +15 -1
- package/dist/server/App.js.map +1 -1
- package/dist/server/TelemetryStore.d.ts +17 -0
- package/dist/server/TelemetryStore.d.ts.map +1 -1
- package/dist/server/TelemetryStore.js +33 -0
- package/dist/server/TelemetryStore.js.map +1 -1
- package/dist/server/adapter/workers/createWorkersApp.d.ts.map +1 -1
- package/dist/server/adapter/workers/createWorkersApp.js +17 -1
- package/dist/server/adapter/workers/createWorkersApp.js.map +1 -1
- package/dist/server/adminAllowlist.d.ts +11 -0
- package/dist/server/adminAllowlist.d.ts.map +1 -0
- package/dist/server/adminAllowlist.js +22 -0
- package/dist/server/adminAllowlist.js.map +1 -0
- package/dist/server/feedbackNotify.d.ts +3 -0
- package/dist/server/feedbackNotify.d.ts.map +1 -0
- package/dist/server/feedbackNotify.js +38 -0
- package/dist/server/feedbackNotify.js.map +1 -0
- package/dist/server/feedbackResolveTemplate.d.ts +15 -0
- package/dist/server/feedbackResolveTemplate.d.ts.map +1 -0
- package/dist/server/feedbackResolveTemplate.js +26 -0
- package/dist/server/feedbackResolveTemplate.js.map +1 -0
- package/dist/server/userEmailLookup.d.ts +5 -0
- package/dist/server/userEmailLookup.d.ts.map +1 -0
- package/dist/server/userEmailLookup.js +35 -0
- package/dist/server/userEmailLookup.js.map +1 -0
- package/dist/shared/FrameworkRequests.d.ts +16 -0
- package/dist/shared/FrameworkRequests.d.ts.map +1 -1
- package/dist/shared/FrameworkRequests.js +17 -0
- package/dist/shared/FrameworkRequests.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/auth/cloudflareOauth.ts +62 -34
- package/src/cli/auth/credentials.ts +59 -0
- package/src/cli/feedbackResolve.test.ts +44 -27
- package/src/cli/feedbackResolve.ts +79 -25
- package/src/cli/index.ts +115 -20
- package/src/cli/serverLogQueryApi.ts +142 -9
- package/src/cli/telemetryAuth.ts +13 -4
- package/src/cli/version.ts +1 -1
- package/src/native/server/binaries/installer.ts +30 -3
- package/src/server/App.ts +22 -1
- package/src/server/TelemetryStore.test.ts +33 -0
- package/src/server/TelemetryStore.ts +49 -0
- package/src/server/adapter/workers/createWorkersApp.ts +24 -1
- package/src/server/adminAllowlist.test.ts +29 -0
- package/src/server/adminAllowlist.ts +20 -0
- package/src/server/feedbackNotify.test.ts +61 -0
- package/src/server/feedbackNotify.ts +40 -0
- package/src/server/feedbackResolveTemplate.test.ts +38 -0
- package/src/server/feedbackResolveTemplate.ts +34 -0
- package/src/server/userEmailLookup.test.ts +35 -0
- package/src/server/userEmailLookup.ts +35 -0
- package/src/shared/FrameworkRequests.ts +18 -0
|
@@ -38,19 +38,27 @@ export declare function refreshCloudflareToken(refreshToken: string): Promise<{
|
|
|
38
38
|
expiresAt: number;
|
|
39
39
|
} | undefined>;
|
|
40
40
|
/**
|
|
41
|
-
* Return a fresh Cloudflare access token, refreshing
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* Return a fresh Cloudflare access token, refreshing when within REFRESH_SKEW_MS
|
|
42
|
+
* of expiry. The refresh runs inside the cross-process credentials lock and
|
|
43
|
+
* re-reads inside it, so concurrent callers don't double-consume the single-use
|
|
44
|
+
* refresh token. Returns `undefined` when not signed in or the refresh failed.
|
|
44
45
|
*/
|
|
45
46
|
export declare function getFreshCloudflareCredentials(): Promise<CloudflareCredentials | undefined>;
|
|
46
47
|
/**
|
|
47
48
|
* FORCE a token refresh (ignoring the local `expiresAt`) and persist the result.
|
|
48
49
|
* For callers that hit a real 401 despite a locally-"valid" token — the cached
|
|
49
|
-
* `expiresAt` can lie (revoked token, or a mis-computed expiry).
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* (
|
|
50
|
+
* `expiresAt` can lie (revoked token, or a mis-computed expiry).
|
|
51
|
+
*
|
|
52
|
+
* Runs inside the cross-process credentials lock. Pass `staleToken` — the access
|
|
53
|
+
* token that just 401'd — so that if another process already rotated the token
|
|
54
|
+
* out from under us (the on-disk access token no longer matches), we return the
|
|
55
|
+
* fresh token WITHOUT consuming the single-use refresh token a second time. This
|
|
56
|
+
* is the dedupe that collapses concurrent 401 storms into a single refresh and
|
|
57
|
+
* stops the refresh chain from being breach-invalidated.
|
|
58
|
+
*
|
|
59
|
+
* Persisting the rotated refresh token is mandatory (Cloudflare rotates them
|
|
60
|
+
* single-use). Returns `undefined` if there's no session or the refresh token is
|
|
61
|
+
* dead (caller must prompt re-login).
|
|
54
62
|
*/
|
|
55
|
-
export declare function forceRefreshCloudflareCredentials(): Promise<CloudflareCredentials | undefined>;
|
|
63
|
+
export declare function forceRefreshCloudflareCredentials(staleToken?: string): Promise<CloudflareCredentials | undefined>;
|
|
56
64
|
//# sourceMappingURL=cloudflareOauth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflareOauth.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/cloudflareOauth.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,qBAAqB,
|
|
1
|
+
{"version":3,"file":"cloudflareOauth.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/cloudflareOauth.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,qBAAqB,EAI3B,MAAM,kBAAkB,CAAC;AA0E1B,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAYD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAkEhC;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAsBxF;AASD;;;;;GAKG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAuBhG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iCAAiC,CACrD,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAiB5C"}
|
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { openInBrowser } from './browser.js';
|
|
3
3
|
import { startCallbackServer } from './callbackServer.js';
|
|
4
4
|
import { generateCodeChallenge, generateCodeVerifier, generateState } from './pkce.js';
|
|
5
|
-
import { getCloudflareCredentials, setCloudflareCredentials, } from './credentials.js';
|
|
5
|
+
import { getCloudflareCredentials, setCloudflareCredentials, withCredentialsLock, } from './credentials.js';
|
|
6
6
|
import { parseOrLog, parseOrThrow } from '../../shared/parseWithZod.js';
|
|
7
7
|
/**
|
|
8
8
|
* Cloudflare OAuth configuration.
|
|
@@ -171,54 +171,84 @@ export async function refreshCloudflareToken(refreshToken) {
|
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
174
|
+
* How far before local `expiresAt` we proactively refresh. Bumped from 60s to
|
|
175
|
+
* 5 min so a token doesn't expire mid-operation (a multi-step publish can outlive
|
|
176
|
+
* a 60s window). The real durability comes from the single-flight lock below.
|
|
177
|
+
*/
|
|
178
|
+
const REFRESH_SKEW_MS = 300_000;
|
|
179
|
+
/**
|
|
180
|
+
* Return a fresh Cloudflare access token, refreshing when within REFRESH_SKEW_MS
|
|
181
|
+
* of expiry. The refresh runs inside the cross-process credentials lock and
|
|
182
|
+
* re-reads inside it, so concurrent callers don't double-consume the single-use
|
|
183
|
+
* refresh token. Returns `undefined` when not signed in or the refresh failed.
|
|
177
184
|
*/
|
|
178
185
|
export async function getFreshCloudflareCredentials() {
|
|
179
186
|
const creds = await getCloudflareCredentials();
|
|
180
187
|
if (!creds)
|
|
181
188
|
return undefined;
|
|
182
|
-
if (creds.expiresAt > Date.now() +
|
|
189
|
+
if (creds.expiresAt > Date.now() + REFRESH_SKEW_MS)
|
|
183
190
|
return creds;
|
|
184
191
|
if (!creds.refreshToken)
|
|
185
192
|
return undefined;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
return withCredentialsLock(async () => {
|
|
194
|
+
// Re-read INSIDE the lock — another process/waiter may have just refreshed,
|
|
195
|
+
// in which case we reuse its token instead of consuming the rotated one.
|
|
196
|
+
const cur = await getCloudflareCredentials();
|
|
197
|
+
if (!cur)
|
|
198
|
+
return undefined;
|
|
199
|
+
if (cur.expiresAt > Date.now() + REFRESH_SKEW_MS)
|
|
200
|
+
return cur;
|
|
201
|
+
if (!cur.refreshToken)
|
|
202
|
+
return undefined;
|
|
203
|
+
const refreshed = await refreshCloudflareToken(cur.refreshToken);
|
|
204
|
+
if (!refreshed)
|
|
205
|
+
return undefined;
|
|
206
|
+
const next = {
|
|
207
|
+
...cur,
|
|
208
|
+
accessToken: refreshed.accessToken,
|
|
209
|
+
refreshToken: refreshed.refreshToken,
|
|
210
|
+
expiresAt: refreshed.expiresAt,
|
|
211
|
+
};
|
|
212
|
+
await setCloudflareCredentials(next);
|
|
213
|
+
return next;
|
|
214
|
+
});
|
|
197
215
|
}
|
|
198
216
|
/**
|
|
199
217
|
* FORCE a token refresh (ignoring the local `expiresAt`) and persist the result.
|
|
200
218
|
* For callers that hit a real 401 despite a locally-"valid" token — the cached
|
|
201
|
-
* `expiresAt` can lie (revoked token, or a mis-computed expiry).
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* (
|
|
219
|
+
* `expiresAt` can lie (revoked token, or a mis-computed expiry).
|
|
220
|
+
*
|
|
221
|
+
* Runs inside the cross-process credentials lock. Pass `staleToken` — the access
|
|
222
|
+
* token that just 401'd — so that if another process already rotated the token
|
|
223
|
+
* out from under us (the on-disk access token no longer matches), we return the
|
|
224
|
+
* fresh token WITHOUT consuming the single-use refresh token a second time. This
|
|
225
|
+
* is the dedupe that collapses concurrent 401 storms into a single refresh and
|
|
226
|
+
* stops the refresh chain from being breach-invalidated.
|
|
227
|
+
*
|
|
228
|
+
* Persisting the rotated refresh token is mandatory (Cloudflare rotates them
|
|
229
|
+
* single-use). Returns `undefined` if there's no session or the refresh token is
|
|
230
|
+
* dead (caller must prompt re-login).
|
|
206
231
|
*/
|
|
207
|
-
export async function forceRefreshCloudflareCredentials() {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
export async function forceRefreshCloudflareCredentials(staleToken) {
|
|
233
|
+
return withCredentialsLock(async () => {
|
|
234
|
+
const creds = await getCloudflareCredentials();
|
|
235
|
+
if (!creds?.refreshToken)
|
|
236
|
+
return undefined;
|
|
237
|
+
// Someone else already rotated it — reuse instead of double-consuming.
|
|
238
|
+
if (staleToken && creds.accessToken !== staleToken)
|
|
239
|
+
return creds;
|
|
240
|
+
const refreshed = await refreshCloudflareToken(creds.refreshToken);
|
|
241
|
+
if (!refreshed)
|
|
242
|
+
return undefined;
|
|
243
|
+
const next = {
|
|
244
|
+
...creds,
|
|
245
|
+
accessToken: refreshed.accessToken,
|
|
246
|
+
refreshToken: refreshed.refreshToken,
|
|
247
|
+
expiresAt: refreshed.expiresAt,
|
|
248
|
+
};
|
|
249
|
+
await setCloudflareCredentials(next);
|
|
250
|
+
return next;
|
|
251
|
+
});
|
|
222
252
|
}
|
|
223
253
|
const cfUserResponseSchema = z
|
|
224
254
|
.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflareOauth.js","sourceRoot":"","sources":["../../../src/cli/auth/cloudflareOauth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvF,OAAO,EAEL,wBAAwB,EACxB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"cloudflareOauth.js","sourceRoot":"","sources":["../../../src/cli/auth/cloudflareOauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,6 +44,22 @@ export declare function readCredentials(): Promise<Credentials>;
|
|
|
44
44
|
* leaves a half-written file.
|
|
45
45
|
*/
|
|
46
46
|
export declare function writeCredentials(creds: Credentials): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Serialize a read→(refresh)→write critical section on the credentials file
|
|
49
|
+
* across processes. Cloudflare rotates the OAuth refresh token single-use, so two
|
|
50
|
+
* processes (e.g. `ugly-app errors` + the ugly-studio publish sidecar, or two
|
|
51
|
+
* concurrent CLIs) that both refresh with the same refresh token cause Cloudflare
|
|
52
|
+
* to breach-invalidate the whole chain — leaving a dead access token with a
|
|
53
|
+
* still-future `expiresAt`. Holding this lock across the whole refresh lets the
|
|
54
|
+
* second waiter re-read the freshly-rotated token instead of double-consuming it.
|
|
55
|
+
*
|
|
56
|
+
* Implementation: an atomic `O_CREAT|O_EXCL` create of a sibling `.lock` file
|
|
57
|
+
* (works cross-process on local filesystems — this is a single-machine dev tool).
|
|
58
|
+
* A crashed holder can't wedge login forever: a lock older than STALE_MS is broken.
|
|
59
|
+
* The callback MUST use the lock-free `readCredentials`/`writeCredentials` (never
|
|
60
|
+
* re-enter this lock).
|
|
61
|
+
*/
|
|
62
|
+
export declare function withCredentialsLock<T>(fn: () => Promise<T>): Promise<T>;
|
|
47
63
|
export declare function getCloudflareCredentials(): Promise<CloudflareCredentials | undefined>;
|
|
48
64
|
export declare function setCloudflareCredentials(cf: CloudflareCredentials): Promise<void>;
|
|
49
65
|
export declare function getNeonCredentials(): Promise<NeonCredentials | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/credentials.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAU5D;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAOxE;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAG3F;AAED,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvF;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAG/E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7E;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlF;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9C"}
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/cli/auth/credentials.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAU5D;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAOxE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA0C7E;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAG3F;AAED,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvF;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAG/E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7E;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlF;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9C"}
|
|
@@ -43,6 +43,69 @@ export async function writeCredentials(creds) {
|
|
|
43
43
|
await fs.writeFile(tmp, JSON.stringify(creds, null, 2), { mode: 0o600 });
|
|
44
44
|
await fs.rename(tmp, file);
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Serialize a read→(refresh)→write critical section on the credentials file
|
|
48
|
+
* across processes. Cloudflare rotates the OAuth refresh token single-use, so two
|
|
49
|
+
* processes (e.g. `ugly-app errors` + the ugly-studio publish sidecar, or two
|
|
50
|
+
* concurrent CLIs) that both refresh with the same refresh token cause Cloudflare
|
|
51
|
+
* to breach-invalidate the whole chain — leaving a dead access token with a
|
|
52
|
+
* still-future `expiresAt`. Holding this lock across the whole refresh lets the
|
|
53
|
+
* second waiter re-read the freshly-rotated token instead of double-consuming it.
|
|
54
|
+
*
|
|
55
|
+
* Implementation: an atomic `O_CREAT|O_EXCL` create of a sibling `.lock` file
|
|
56
|
+
* (works cross-process on local filesystems — this is a single-machine dev tool).
|
|
57
|
+
* A crashed holder can't wedge login forever: a lock older than STALE_MS is broken.
|
|
58
|
+
* The callback MUST use the lock-free `readCredentials`/`writeCredentials` (never
|
|
59
|
+
* re-enter this lock).
|
|
60
|
+
*/
|
|
61
|
+
export async function withCredentialsLock(fn) {
|
|
62
|
+
const lock = `${credentialsPath()}.lock`;
|
|
63
|
+
const dir = path.dirname(lock);
|
|
64
|
+
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
65
|
+
const STALE_MS = 15_000;
|
|
66
|
+
const MAX_WAIT_MS = 10_000;
|
|
67
|
+
const started = Date.now();
|
|
68
|
+
// eslint-disable-next-line no-constant-condition
|
|
69
|
+
while (true) {
|
|
70
|
+
try {
|
|
71
|
+
const fh = await fs.open(lock, 'wx', 0o600);
|
|
72
|
+
try {
|
|
73
|
+
await fh.writeFile(`${process.pid} ${Date.now()}`);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await fh.close();
|
|
77
|
+
}
|
|
78
|
+
break; // acquired
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
if (err.code !== 'EEXIST')
|
|
82
|
+
throw err;
|
|
83
|
+
// Break a stale lock left by a crashed holder.
|
|
84
|
+
try {
|
|
85
|
+
const st = await fs.stat(lock);
|
|
86
|
+
if (Date.now() - st.mtimeMs > STALE_MS) {
|
|
87
|
+
await fs.rm(lock, { force: true });
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// lock vanished between open and stat — retry immediately
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (Date.now() - started > MAX_WAIT_MS) {
|
|
96
|
+
// Give up waiting rather than hang login forever; proceed best-effort.
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
await new Promise((r) => setTimeout(r, 50 + Math.floor((Date.now() - started) / 20)));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
return await fn();
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
await fs.rm(lock, { force: true }).catch(() => { });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
46
109
|
export async function getCloudflareCredentials() {
|
|
47
110
|
const creds = await readCredentials();
|
|
48
111
|
return creds.cloudflare;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/cli/auth/credentials.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/cli/auth/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,15 +8,28 @@ export interface FeedbackResolveItem {
|
|
|
8
8
|
status: 'resolved' | 'declined';
|
|
9
9
|
resolution: string;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/** Where + how to reach the deployed app's `feedbackReportResolve` request. */
|
|
12
|
+
export interface ResolveContext {
|
|
13
|
+
/** Deployed app base URL, e.g. https://code.ugly.bot */
|
|
14
|
+
appUrl: string;
|
|
15
|
+
/** Owner bearer token (ugly.bot user token) — verified by the Worker and gated
|
|
16
|
+
* by resolvedIsAdmin (MAINTAIN_BOT_USER_ID or the ADMIN_USER_IDS allowlist). */
|
|
17
|
+
token: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the deployed app URL (from publish state) + the owner token needed to
|
|
21
|
+
* authorize `feedbackReportResolve`. Throws with actionable guidance if either
|
|
22
|
+
* is missing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveProdResolveContext(): ResolveContext;
|
|
25
|
+
export declare function resolveFeedback(opts: FeedbackResolveOptions, ctx: ResolveContext): Promise<void>;
|
|
12
26
|
/**
|
|
13
|
-
* Resolve many feedback items over
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* leave items at `status: new` for a duplicate-process next cycle).
|
|
27
|
+
* Resolve many feedback items over one auth context. Process each item even if
|
|
28
|
+
* earlier ones fail — partial failure is surfaced via the returned `failures`
|
|
29
|
+
* array AND a non-zero exit at the CLI layer, never silently swallowed (the
|
|
30
|
+
* bot-swarm cycle invariant is to fail loud, not leave items at `status: new`).
|
|
18
31
|
*/
|
|
19
|
-
export declare function resolveFeedbackBatch(items: FeedbackResolveItem[], onItem?: (item: FeedbackResolveItem, result: {
|
|
32
|
+
export declare function resolveFeedbackBatch(items: FeedbackResolveItem[], ctx: ResolveContext, onItem?: (item: FeedbackResolveItem, result: {
|
|
20
33
|
ok: true;
|
|
21
34
|
} | {
|
|
22
35
|
ok: false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedbackResolve.d.ts","sourceRoot":"","sources":["../../src/cli/feedbackResolve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feedbackResolve.d.ts","sourceRoot":"","sources":["../../src/cli/feedbackResolve.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf;qFACiF;IACjF,KAAK,EAAE,MAAM,CAAC;CACf;AAaD;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,cAAc,CAU1D;AAgCD,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,EAC5B,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,mBAAmB,EAAE,EAC5B,GAAG,EAAE,cAAc,EACnB,MAAM,CAAC,EAAE,CACP,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAChD,IAAI,GACR,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAe3E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,EAAE,CA8BpE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAWzD"}
|
|
@@ -1,43 +1,79 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { resolveProdAuth } from './prodDb.js';
|
|
5
|
+
/** Read the signed-in owner's ugly.bot token from `~/.ugly-bot/auth.json`. */
|
|
6
|
+
function readOwnerToken() {
|
|
7
|
+
const file = path.join(os.homedir(), '.ugly-bot', 'auth.json');
|
|
8
|
+
try {
|
|
9
|
+
const data = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
10
|
+
return typeof data.token === 'string' ? data.token : '';
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the deployed app URL (from publish state) + the owner token needed to
|
|
18
|
+
* authorize `feedbackReportResolve`. Throws with actionable guidance if either
|
|
19
|
+
* is missing.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveProdResolveContext() {
|
|
22
|
+
const auth = resolveProdAuth();
|
|
23
|
+
const appUrl = auth.wsUrl.replace(/^ws/, 'http').replace(/\/ws$/, '');
|
|
24
|
+
const token = readOwnerToken();
|
|
25
|
+
if (!token) {
|
|
26
|
+
throw new Error('Not signed in to ugly.bot — run `ugly-app login`. feedback:resolve needs your owner token to authorize the resolve on the deployed app.');
|
|
27
|
+
}
|
|
28
|
+
return { appUrl, token };
|
|
29
|
+
}
|
|
2
30
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* that 400s ("Missing op"), so resolves silently failed for every child app.
|
|
31
|
+
* Resolve a single feedback report by calling the deployed app's admin
|
|
32
|
+
* `feedbackReportResolve` request. The Worker updates the `feedback_report` D1
|
|
33
|
+
* row (status + resolution + resolved_at) AND emails the reporter from the app's
|
|
34
|
+
* own domain — email must run in Worker context, so (unlike the old raw D1
|
|
35
|
+
* UPDATE) the resolve goes through the app rather than the Cloudflare D1 API.
|
|
9
36
|
*/
|
|
10
|
-
async function resolveOne(item) {
|
|
11
|
-
const
|
|
12
|
-
|
|
37
|
+
async function resolveOne(item, ctx) {
|
|
38
|
+
const res = await fetch(`${ctx.appUrl}/api/feedbackReportResolve`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
Authorization: `Bearer ${ctx.token}`,
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify({
|
|
45
|
+
input: { id: item.id, status: item.status, resolution: item.resolution },
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
if (!res.ok) {
|
|
49
|
+
const body = await res.text().catch(() => '');
|
|
50
|
+
throw new Error(`resolve request failed (${res.status})${body ? ` — ${body.slice(0, 200)}` : ''}`);
|
|
51
|
+
}
|
|
52
|
+
const data = (await res.json().catch(() => ({})));
|
|
53
|
+
if (!data.ok) {
|
|
13
54
|
throw new Error(`no feedback_report row with id "${item.id}"`);
|
|
14
55
|
}
|
|
15
56
|
}
|
|
16
|
-
export async function resolveFeedback(opts) {
|
|
57
|
+
export async function resolveFeedback(opts, ctx) {
|
|
17
58
|
try {
|
|
18
|
-
await resolveOne({
|
|
19
|
-
id: opts.feedbackId,
|
|
20
|
-
status: opts.status,
|
|
21
|
-
resolution: opts.resolution,
|
|
22
|
-
});
|
|
59
|
+
await resolveOne({ id: opts.feedbackId, status: opts.status, resolution: opts.resolution }, ctx);
|
|
23
60
|
}
|
|
24
61
|
catch (e) {
|
|
25
62
|
throw new Error(`Failed to resolve feedback: ${e.message}`);
|
|
26
63
|
}
|
|
27
64
|
}
|
|
28
65
|
/**
|
|
29
|
-
* Resolve many feedback items over
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* leave items at `status: new` for a duplicate-process next cycle).
|
|
66
|
+
* Resolve many feedback items over one auth context. Process each item even if
|
|
67
|
+
* earlier ones fail — partial failure is surfaced via the returned `failures`
|
|
68
|
+
* array AND a non-zero exit at the CLI layer, never silently swallowed (the
|
|
69
|
+
* bot-swarm cycle invariant is to fail loud, not leave items at `status: new`).
|
|
34
70
|
*/
|
|
35
|
-
export async function resolveFeedbackBatch(items, onItem) {
|
|
71
|
+
export async function resolveFeedbackBatch(items, ctx, onItem) {
|
|
36
72
|
const failures = [];
|
|
37
73
|
let successes = 0;
|
|
38
74
|
for (const item of items) {
|
|
39
75
|
try {
|
|
40
|
-
await resolveOne(item);
|
|
76
|
+
await resolveOne(item, ctx);
|
|
41
77
|
successes++;
|
|
42
78
|
onItem?.(item, { ok: true });
|
|
43
79
|
}
|
|
@@ -89,7 +125,9 @@ export async function readStdinToString() {
|
|
|
89
125
|
return new Promise((resolve, reject) => {
|
|
90
126
|
let buf = '';
|
|
91
127
|
process.stdin.setEncoding('utf-8');
|
|
92
|
-
process.stdin.on('data', (chunk) => {
|
|
128
|
+
process.stdin.on('data', (chunk) => {
|
|
129
|
+
buf += chunk;
|
|
130
|
+
});
|
|
93
131
|
process.stdin.on('end', () => resolve(buf));
|
|
94
132
|
process.stdin.on('error', reject);
|
|
95
133
|
process.stdin.resume();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedbackResolve.js","sourceRoot":"","sources":["../../src/cli/feedbackResolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"feedbackResolve.js","sourceRoot":"","sources":["../../src/cli/feedbackResolve.ts"],"names":[],"mappings":"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"}
|