jamdesk 1.1.203 → 1.1.205
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/__tests__/integration/fix-scan-integration.test.js.map +1 -1
- package/dist/__tests__/integration/init.integration.test.js.map +1 -1
- package/dist/__tests__/integration/prepublish.integration.test.js.map +1 -1
- package/dist/__tests__/integration/validate.integration.test.js.map +1 -1
- package/dist/__tests__/unit/banner-art-sync.test.js.map +1 -1
- package/dist/__tests__/unit/deploy-templates.test.js.map +1 -1
- package/dist/__tests__/unit/deploy.test.js +106 -0
- package/dist/__tests__/unit/deploy.test.js.map +1 -1
- package/dist/__tests__/unit/deprecated-components-sync.test.js.map +1 -1
- package/dist/__tests__/unit/deps-sync.test.js.map +1 -1
- package/dist/__tests__/unit/dev-spinner-ownership.test.js.map +1 -1
- package/dist/__tests__/unit/docs-config.test.js.map +1 -1
- package/dist/__tests__/unit/fix-engine-sync.test.js.map +1 -1
- package/dist/__tests__/unit/frontmatter-sync.test.js.map +1 -1
- package/dist/__tests__/unit/heading-extractor-sync.test.js.map +1 -1
- package/dist/__tests__/unit/inert-config-keys-sync.test.js.map +1 -1
- package/dist/__tests__/unit/init.test.js.map +1 -1
- package/dist/__tests__/unit/install-banner-gating.test.js.map +1 -1
- package/dist/__tests__/unit/jwt-auth-config-drift.test.d.ts +22 -0
- package/dist/__tests__/unit/jwt-auth-config-drift.test.d.ts.map +1 -0
- package/dist/__tests__/unit/jwt-auth-config-drift.test.js +193 -0
- package/dist/__tests__/unit/jwt-auth-config-drift.test.js.map +1 -0
- package/dist/__tests__/unit/openapi-schema-patch-sync.test.js.map +1 -1
- package/dist/__tests__/unit/openapi-schema-runtime-patch.test.js +1 -1
- package/dist/__tests__/unit/openapi.test.js.map +1 -1
- package/dist/__tests__/unit/package-config.test.js.map +1 -1
- package/dist/__tests__/unit/project-favicon.test.js.map +1 -1
- package/dist/__tests__/unit/prompt-vendoring.test.js.map +1 -1
- package/dist/__tests__/unit/risky-expression-scanner-sync.test.js.map +1 -1
- package/dist/__tests__/unit/seo-ai-schema.test.js.map +1 -1
- package/dist/__tests__/unit/snippet-scanner-sync.test.js.map +1 -1
- package/dist/__tests__/unit/spec-generation-notice.test.js.map +1 -1
- package/dist/__tests__/unit/templates-consistency.test.js.map +1 -1
- package/dist/__tests__/unit/validate-inert-config-keys.test.js.map +1 -1
- package/dist/__tests__/unit/validate-jwt-auth.test.d.ts +2 -0
- package/dist/__tests__/unit/validate-jwt-auth.test.d.ts.map +1 -0
- package/dist/__tests__/unit/validate-jwt-auth.test.js +77 -0
- package/dist/__tests__/unit/validate-jwt-auth.test.js.map +1 -0
- package/dist/__tests__/unit/validate-password-warning.test.js.map +1 -1
- package/dist/__tests__/unit/vendored-sync.test.js +11 -0
- package/dist/__tests__/unit/vendored-sync.test.js.map +1 -1
- package/dist/commands/broken-links.js.map +1 -1
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/deploy/cloudflare.js.map +1 -1
- package/dist/commands/deploy.js +16 -0
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/deps.d.ts +4 -4
- package/dist/lib/deps.d.ts.map +1 -1
- package/dist/lib/deps.js +15 -10
- package/dist/lib/deps.js.map +1 -1
- package/dist/lib/docs-config.d.ts +1 -0
- package/dist/lib/docs-config.d.ts.map +1 -1
- package/dist/lib/docs-config.js +49 -0
- package/dist/lib/docs-config.js.map +1 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/find-project-dir.js.map +1 -1
- package/dist/lib/first-run-banner.js.map +1 -1
- package/dist/lib/mdx-validator.js.map +1 -1
- package/dist/lib/missing-description-scan.js.map +1 -1
- package/dist/utils/update-checker.js.map +1 -1
- package/package.json +9 -8
- package/vendored/app/(jd-system)/jd-inactive/BrandedInactive.tsx +1 -7
- package/vendored/app/(jd-system)/jd-inactive/page.tsx +2 -4
- package/vendored/app/(unlock)/jd/auth/callback/CallbackClient.tsx +33 -0
- package/vendored/app/(unlock)/jd/auth/callback/page.tsx +15 -0
- package/vendored/app/(unlock)/jd/unlock/page.tsx +29 -7
- package/vendored/app/api/jd/auth/callback/route.ts +103 -0
- package/vendored/app/api/jd/auth/logout/route.ts +38 -0
- package/vendored/app/api/jd/auth/me/route.ts +52 -0
- package/vendored/app/api/jd/unlock/route.ts +26 -2
- package/vendored/app/api/markdown-export/[project]/[...slug]/route.ts +65 -22
- package/vendored/app/api/raw-content/[...slug]/route.ts +21 -1
- package/vendored/app/layout.tsx +7 -0
- package/vendored/components/AIActionsMenu.tsx +19 -2
- package/vendored/components/mdx/OpenApiEndpoint.tsx +4 -0
- package/vendored/components/navigation/Header.tsx +5 -0
- package/vendored/components/navigation/LogoutButton.tsx +41 -0
- package/vendored/lib/auth-resolver.ts +125 -50
- package/vendored/lib/cached-redis.ts +28 -3
- package/vendored/lib/docs-types.ts +17 -1
- package/vendored/lib/glob-match.ts +54 -0
- package/vendored/lib/jwt-auth-config.ts +37 -0
- package/vendored/lib/jwt-session.ts +98 -0
- package/vendored/lib/language-utils.ts +14 -2
- package/vendored/lib/layout-helpers.tsx +4 -0
- package/vendored/lib/mdx-inline-components.ts +1 -1
- package/vendored/lib/middleware-helpers.ts +27 -6
- package/vendored/lib/nav-group-filter.ts +81 -0
- package/vendored/lib/public-paths-resolver.ts +164 -7
- package/vendored/lib/r2-public-storage-guard.ts +26 -4
- package/vendored/lib/redis.ts +20 -2
- package/vendored/lib/render-doc-page.tsx +76 -34
- package/vendored/lib/root-page-slug.ts +110 -0
- package/vendored/lib/same-origin.ts +38 -0
- package/vendored/lib/sanitize-from.ts +31 -1
- package/vendored/lib/session-hint.ts +11 -0
- package/vendored/lib/snippet-compiler-isr.ts +1 -1
- package/vendored/lib/snippet-loader-isr.ts +1 -1
- package/vendored/lib/validate-config.ts +14 -0
- package/vendored/lib/viewer-navigation.ts +45 -0
- package/vendored/lib/visibility.ts +65 -0
- package/vendored/schema/docs-schema.json +25 -0
- package/vendored/shared/auth-cookie.ts +98 -5
- package/vendored/workspace-package-lock.json +474 -183
|
@@ -15,15 +15,23 @@
|
|
|
15
15
|
* which is not available in Edge runtime. This module reimplements a
|
|
16
16
|
* minimal constant-time compare over Uint8Array outputs from Web Crypto.
|
|
17
17
|
*
|
|
18
|
-
* Cookie wire format:
|
|
18
|
+
* Cookie wire format (v1, password-gated sites — unchanged, byte-for-byte):
|
|
19
19
|
* base64url(`v1.${version}.${expiresAt}.${base64url(HMAC_SHA256(`v1|${slug}|${host}|${version}|${expiresAt}`, secret))}`)
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* Cookie wire format (v2, JWT-gated sites — carries signed groups + playground
|
|
22
|
+
* inputs, raw dotted string with NO outer base64 wrap to reclaim cookie budget):
|
|
23
|
+
* `v2.${version}.${expiresAt}.${extrasB64}.${sigB64}`
|
|
24
|
+
* where sigB64 = base64url(HMAC_SHA256(`v2|${slug}|${host}|${version}|${expiresAt}|${extrasB64}`, secret))
|
|
25
|
+
*
|
|
26
|
+
* The "v1"/"v2" prefix on both the HMAC input and the body makes it safe to
|
|
27
|
+
* rotate the payload format without silently accepting a cookie signed under
|
|
28
|
+
* a different binding. verifyAuthCookie() branches on the RAW `v2.` prefix
|
|
29
|
+
* before attempting the v1 base64 decode, so both formats verify correctly
|
|
30
|
+
* from the same function.
|
|
24
31
|
*/
|
|
25
32
|
|
|
26
33
|
const FORMAT_VERSION = 'v1';
|
|
34
|
+
const FORMAT_VERSION_V2 = 'v2';
|
|
27
35
|
|
|
28
36
|
export interface AuthCookiePayload {
|
|
29
37
|
slug: string;
|
|
@@ -38,9 +46,19 @@ export interface VerifyExpectation {
|
|
|
38
46
|
version: number;
|
|
39
47
|
}
|
|
40
48
|
|
|
49
|
+
/** Signed extras carried by v2 cookies: JWT-sourced groups + playground inputs. */
|
|
50
|
+
export interface SessionExtras {
|
|
51
|
+
/** User groups from the JWT payload. */
|
|
52
|
+
g?: string[];
|
|
53
|
+
/** apiPlaygroundInputs from the JWT payload (size-capped by the callback route). */
|
|
54
|
+
api?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
export interface VerifyResult {
|
|
42
58
|
valid: boolean;
|
|
43
59
|
expiresAt?: number;
|
|
60
|
+
formatVersion?: 'v1' | 'v2';
|
|
61
|
+
extras?: SessionExtras;
|
|
44
62
|
}
|
|
45
63
|
|
|
46
64
|
function base64url(bytes: Uint8Array): string {
|
|
@@ -102,6 +120,20 @@ function buildSignInput(
|
|
|
102
120
|
return `${FORMAT_VERSION}|${slug}|${host}|${version}|${expiresAt}`;
|
|
103
121
|
}
|
|
104
122
|
|
|
123
|
+
function utf8ToBase64url(s: string): string {
|
|
124
|
+
return base64url(new TextEncoder().encode(s));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function buildSignInputV2(
|
|
128
|
+
slug: string,
|
|
129
|
+
host: string,
|
|
130
|
+
version: number,
|
|
131
|
+
expiresAt: number,
|
|
132
|
+
extrasB64: string
|
|
133
|
+
): string {
|
|
134
|
+
return `${FORMAT_VERSION_V2}|${slug}|${host}|${version}|${expiresAt}|${extrasB64}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
105
137
|
/**
|
|
106
138
|
* Sign a cookie payload. Returns the full cookie value string to put in Set-Cookie.
|
|
107
139
|
*/
|
|
@@ -119,15 +151,44 @@ export async function signAuthCookie(
|
|
|
119
151
|
return base64url(new TextEncoder().encode(body));
|
|
120
152
|
}
|
|
121
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Sign a v2 cookie payload carrying signed extras (groups + playground inputs).
|
|
156
|
+
*
|
|
157
|
+
* Wire format: the raw string `v2.${version}.${expiresAt}.${extrasB64}.${sigB64}`
|
|
158
|
+
* — NO outer base64 wrap (every segment is already cookie-safe base64url or
|
|
159
|
+
* digits; v1's whole-body wrap costs ~25% of the ~4KB cookie budget, and v2
|
|
160
|
+
* carries groups in the cookie, so the headroom is load-bearing).
|
|
161
|
+
* extrasB64 = base64url(utf8(JSON.stringify(extras))). The extras segment is
|
|
162
|
+
* inside the HMAC, so groups/playground data can't be forged.
|
|
163
|
+
*/
|
|
164
|
+
export async function signAuthCookieV2(
|
|
165
|
+
payload: AuthCookiePayload,
|
|
166
|
+
extras: SessionExtras,
|
|
167
|
+
secret: string
|
|
168
|
+
): Promise<string> {
|
|
169
|
+
const extrasB64 = utf8ToBase64url(JSON.stringify(extras));
|
|
170
|
+
const sig = await hmac(
|
|
171
|
+
secret,
|
|
172
|
+
buildSignInputV2(payload.slug, payload.host, payload.version, payload.expiresAt, extrasB64)
|
|
173
|
+
);
|
|
174
|
+
return `${FORMAT_VERSION_V2}.${payload.version}.${payload.expiresAt}.${extrasB64}.${base64url(sig)}`;
|
|
175
|
+
}
|
|
176
|
+
|
|
122
177
|
/**
|
|
123
178
|
* Verify a cookie value against the expected slug, host, and version.
|
|
124
179
|
* Returns { valid: false } on any failure (including malformed input).
|
|
180
|
+
* Handles both the legacy v1 (whole-body base64-wrapped) format and the v2
|
|
181
|
+
* (raw dotted, unwrapped) format — identified by the raw `v2.` prefix, which
|
|
182
|
+
* is checked before the v1 base64 decode since v2 is never base64-wrapped.
|
|
125
183
|
*/
|
|
126
184
|
export async function verifyAuthCookie(
|
|
127
185
|
cookie: string,
|
|
128
186
|
expected: VerifyExpectation,
|
|
129
187
|
secret: string
|
|
130
188
|
): Promise<VerifyResult> {
|
|
189
|
+
if (cookie.startsWith(`${FORMAT_VERSION_V2}.`)) {
|
|
190
|
+
return verifyV2(cookie, expected, secret);
|
|
191
|
+
}
|
|
131
192
|
try {
|
|
132
193
|
if (!cookie) return { valid: false };
|
|
133
194
|
const bodyBytes = fromBase64url(cookie);
|
|
@@ -156,8 +217,40 @@ export async function verifyAuthCookie(
|
|
|
156
217
|
const actualSig = fromBase64url(sigB64);
|
|
157
218
|
if (!constantTimeEqual(expectedSig, actualSig)) return { valid: false };
|
|
158
219
|
|
|
159
|
-
return { valid: true, expiresAt };
|
|
220
|
+
return { valid: true, expiresAt, formatVersion: 'v1' };
|
|
160
221
|
} catch {
|
|
161
222
|
return { valid: false };
|
|
162
223
|
}
|
|
163
224
|
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Verify a v2 (raw dotted, unwrapped) cookie. Split out of verifyAuthCookie
|
|
228
|
+
* so the v1 path stays byte-for-byte unchanged for existing password sites.
|
|
229
|
+
*/
|
|
230
|
+
async function verifyV2(
|
|
231
|
+
cookie: string,
|
|
232
|
+
expected: VerifyExpectation,
|
|
233
|
+
secret: string
|
|
234
|
+
): Promise<VerifyResult> {
|
|
235
|
+
const parts = cookie.split('.');
|
|
236
|
+
if (parts.length !== 5) return { valid: false };
|
|
237
|
+
const [, versionStr, expiresAtStr, extrasB64, sigB64] = parts;
|
|
238
|
+
const version = Number(versionStr);
|
|
239
|
+
const expiresAt = Number(expiresAtStr);
|
|
240
|
+
if (!Number.isSafeInteger(version) || !Number.isSafeInteger(expiresAt)) {
|
|
241
|
+
return { valid: false };
|
|
242
|
+
}
|
|
243
|
+
if (version !== expected.version) return { valid: false };
|
|
244
|
+
if (expiresAt <= Date.now()) return { valid: false };
|
|
245
|
+
try {
|
|
246
|
+
const expectedSig = await hmac(
|
|
247
|
+
secret,
|
|
248
|
+
buildSignInputV2(expected.slug, expected.host, version, expiresAt, extrasB64)
|
|
249
|
+
);
|
|
250
|
+
if (!constantTimeEqual(expectedSig, fromBase64url(sigB64))) return { valid: false };
|
|
251
|
+
const extras = JSON.parse(new TextDecoder().decode(fromBase64url(extrasB64))) as SessionExtras;
|
|
252
|
+
return { valid: true, expiresAt, formatVersion: 'v2', extras };
|
|
253
|
+
} catch {
|
|
254
|
+
return { valid: false }; // malformed base64 / JSON — same catch discipline as v1
|
|
255
|
+
}
|
|
256
|
+
}
|