diff --git a/.github/workflows/cloudflare-pages.yaml b/.github/workflows/cloudflare-pages.yaml index cda116c1..93872b98 100644 --- a/.github/workflows/cloudflare-pages.yaml +++ b/.github/workflows/cloudflare-pages.yaml @@ -1,9 +1,8 @@ name: Deploy to Cloudflare Pages on: - push: - branches: - - main + # we don't deploy on push to the main branch to + # keep the site from being open to the public pull_request: branches: - main @@ -12,17 +11,18 @@ on: permissions: contents: read deployments: write + statuses: write jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '20' cache: 'yarn' @@ -33,12 +33,48 @@ jobs: - name: Build docs run: yarn build-docs:ci - - name: Typecheck functions - run: yarn typecheck - - name: Deploy to Cloudflare Pages + id: deploy uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: e1c79c7a03d49b6cb456873259a2280f - command: pages deploy build/docs --project-name=admin-docs + wranglerVersion: '4' + command: pages deploy build/docs --project-name=docs + + - name: Create deployment and status + uses: actions/github-script@v8 + with: + script: | + const isPR = context.eventName === 'pull_request'; + const sha = isPR ? context.payload.pull_request.head.sha : context.sha; + const environment = isPR ? 'preview' : 'production'; + const deploymentUrl = '${{ steps.deploy.outputs.deployment-url }}'; + + // GitHub deployment (shows in PR UI) + const deployment = await github.rest.repos.createDeployment({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: sha, + environment, + auto_merge: false, + required_contexts: [] + }); + await github.rest.repos.createDeploymentStatus({ + owner: context.repo.owner, + repo: context.repo.repo, + deployment_id: deployment.data.id, + state: 'success', + environment_url: deploymentUrl, + description: 'Deployed to Cloudflare Pages' + }); + + await github.rest.repos.createCommitStatus({ + owner: context.repo.owner, + repo: context.repo.repo, + sha, + state: 'success', + target_url: deploymentUrl, + context: 'deploy/cloudflare-pages', + description: 'Deployed to Cloudflare Pages' + }); diff --git a/functions/_middleware.ts b/functions/_middleware.ts deleted file mode 100644 index 8ad28199..00000000 --- a/functions/_middleware.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Env } from './lib/config'; -import { getSession, isExpired, createSessionCookie } from './lib/session'; -import { initiateLogin, refreshSession } from './lib/auth'; -import { renderErrorPage } from './lib/error-page'; - -export const onRequest: PagesFunction = async (context) => { - try { - const url = new URL(context.request.url); - - // Skip auth routes - let them be handled by auth/[[path]].ts - if (url.pathname.startsWith('/auth/')) { - return context.next(); - } - - const session = await getSession(context.request, context.env); - - if (!session) { - return initiateLogin(context.request, context.env); - } - - if (isExpired(session)) { - const refreshed = await refreshSession(session, context.env); - if (!refreshed) { - return initiateLogin(context.request, context.env); - } - // Set refreshed session cookie and continue - const response = await context.next(); - response.headers.append( - 'Set-Cookie', - await createSessionCookie(refreshed, context.env) - ); - return response; - } - - return context.next(); - } catch (error) { - console.error('Authentication middleware error:', error); - return renderErrorPage( - 'Authentication Error', - 'We encountered a problem verifying your identity. Please try again or contact support if the issue persists.', - 503 - ); - } -}; diff --git a/functions/auth/[[path]].ts b/functions/auth/[[path]].ts deleted file mode 100644 index 8b5530c6..00000000 --- a/functions/auth/[[path]].ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Env } from '../lib/config'; -import { handleCallback, handleLogout } from '../lib/auth'; -import { renderErrorPage } from '../lib/error-page'; - -export const onRequest: PagesFunction = async (context) => { - try { - const url = new URL(context.request.url); - const path = url.pathname; - - if (path === '/auth/callback') { - return handleCallback(context.request, context.env); - } - - if (path === '/auth/logout') { - return handleLogout(context.request, context.env); - } - - // Unknown auth route - return renderErrorPage('Not Found', 'The requested page could not be found.', 404); - } catch (error) { - console.error('Auth route error:', error); - return renderErrorPage( - 'Authentication Error', - 'We encountered a problem processing your request. Please try again.', - 500 - ); - } -}; diff --git a/functions/lib/auth.ts b/functions/lib/auth.ts deleted file mode 100644 index 18d32e44..00000000 --- a/functions/lib/auth.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { Env, Session, TokenResponse } from './config'; -import { validateIdToken } from './cognito'; -import { - createSessionCookie, - createAuthStateCookies, - clearAuthStateCookies, - getStateCookie, - getCodeVerifierCookie, - getReturnToCookie, - clearSessionCookie, -} from './session'; -import { renderErrorPage } from './error-page'; - -function generateRandomString(length: number): string { - const array = new Uint8Array(length); - crypto.getRandomValues(array); - return Array.from(array, (b) => b.toString(16).padStart(2, '0')).join(''); -} - -async function generateCodeChallenge(verifier: string): Promise { - const encoder = new TextEncoder(); - const data = encoder.encode(verifier); - const digest = await crypto.subtle.digest('SHA-256', data); - return btoa(String.fromCharCode(...new Uint8Array(digest))) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); -} - -function getAuthorizeUrl(env: Env): string { - return `https://${env.COGNITO_DOMAIN}/oauth2/authorize`; -} - -function getTokenUrl(env: Env): string { - return `https://${env.COGNITO_DOMAIN}/oauth2/token`; -} - -function getLogoutUrl(env: Env): string { - return `https://${env.COGNITO_DOMAIN}/logout`; -} - -function getCallbackUrl(request: Request): string { - const url = new URL(request.url); - return `${url.origin}/auth/callback`; -} - -export async function initiateLogin( - request: Request, - env: Env -): Promise { - const url = new URL(request.url); - const returnTo = url.pathname + url.search; - const callbackUrl = getCallbackUrl(request); - - const state = generateRandomString(32); - const codeVerifier = generateRandomString(64); - const codeChallenge = await generateCodeChallenge(codeVerifier); - - const authorizeParams = new URLSearchParams({ - response_type: 'code', - client_id: env.COGNITO_CLIENT_ID, - redirect_uri: callbackUrl, - scope: 'openid email profile', - state: state, - code_challenge: codeChallenge, - code_challenge_method: 'S256', - }); - - const authorizeUrl = `${getAuthorizeUrl(env)}?${authorizeParams.toString()}`; - const stateCookies = createAuthStateCookies(state, codeVerifier, returnTo); - - console.log('InitiateLogin debug:', { - callbackUrl, - returnTo, - statePrefix: state.substring(0, 16) + '...', - numCookies: stateCookies.length, - }); - - return new Response(null, { - status: 302, - headers: [ - ['Location', authorizeUrl], - ...stateCookies.map((cookie): [string, string] => ['Set-Cookie', cookie]), - ], - }); -} - -export async function handleCallback( - request: Request, - env: Env -): Promise { - const url = new URL(request.url); - const code = url.searchParams.get('code'); - const state = url.searchParams.get('state'); - const error = url.searchParams.get('error'); - const errorDescription = url.searchParams.get('error_description'); - - if (error) { - console.error('OAuth error:', error, errorDescription); - return renderErrorPage( - 'Authentication Failed', - errorDescription || 'The identity provider returned an error. Please try again.', - 400 - ); - } - - if (!code || !state) { - return renderErrorPage( - 'Invalid Request', - 'The authentication response was incomplete. Please try logging in again.', - 400 - ); - } - - const savedState = getStateCookie(request); - const codeVerifier = getCodeVerifierCookie(request); - const returnTo = getReturnToCookie(request); - - // Debug logging - const cookieHeader = request.headers.get('Cookie'); - console.log('Callback debug:', { - hasCodeParam: !!code, - hasStateParam: !!state, - stateParam: state?.substring(0, 16) + '...', - savedState: savedState ? savedState.substring(0, 16) + '...' : null, - statesMatch: savedState === state, - hasCodeVerifier: !!codeVerifier, - hasReturnTo: !!returnTo, - hasCookieHeader: !!cookieHeader, - cookieHeaderLength: cookieHeader?.length, - }); - - if (!savedState || savedState !== state) { - return renderErrorPage( - 'Session Expired', - `Your login session has expired or is invalid. Debug: savedState=${savedState ? 'present' : 'missing'}, match=${savedState === state}`, - 400 - ); - } - - if (!codeVerifier) { - return renderErrorPage( - 'Session Expired', - 'Your login session has expired. Please try logging in again.', - 400 - ); - } - - try { - const callbackUrl = getCallbackUrl(request); - const tokens = await exchangeCodeForTokens(code, codeVerifier, callbackUrl, env); - const userInfo = await validateIdToken(tokens.id_token, env); - - const session: Session = { - refreshToken: tokens.refresh_token, - expiresAt: Date.now() + tokens.expires_in * 1000, - userInfo, - }; - - const sessionCookie = await createSessionCookie(session, env); - const clearAuthCookies = clearAuthStateCookies(); - const redirectTo = returnTo ? decodeURIComponent(returnTo) : '/'; - - return new Response(null, { - status: 302, - headers: [ - ['Location', redirectTo], - ['Set-Cookie', sessionCookie], - ...clearAuthCookies.map((cookie): [string, string] => ['Set-Cookie', cookie]), - ], - }); - } catch (err) { - console.error('Token exchange error:', err); - return renderErrorPage( - 'Authentication Failed', - 'We could not complete your sign-in. Please try again or contact support if the issue persists.', - 500 - ); - } -} - -async function exchangeCodeForTokens( - code: string, - codeVerifier: string, - callbackUrl: string, - env: Env -): Promise { - const tokenParams = new URLSearchParams({ - grant_type: 'authorization_code', - client_id: env.COGNITO_CLIENT_ID, - client_secret: env.COGNITO_CLIENT_SECRET, - code: code, - redirect_uri: callbackUrl, - code_verifier: codeVerifier, - }); - - const response = await fetch(getTokenUrl(env), { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: tokenParams.toString(), - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`Token exchange failed: ${response.status} - ${errorText}`); - } - - return response.json(); -} - -export async function refreshSession( - session: Session, - env: Env -): Promise { - try { - const tokenParams = new URLSearchParams({ - grant_type: 'refresh_token', - client_id: env.COGNITO_CLIENT_ID, - client_secret: env.COGNITO_CLIENT_SECRET, - refresh_token: session.refreshToken, - }); - - const response = await fetch(getTokenUrl(env), { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: tokenParams.toString(), - }); - - if (!response.ok) { - console.error('Token refresh failed:', await response.text()); - return null; - } - - const tokens: TokenResponse = await response.json(); - const userInfo = await validateIdToken(tokens.id_token, env); - - return { - refreshToken: tokens.refresh_token || session.refreshToken, - expiresAt: Date.now() + tokens.expires_in * 1000, - userInfo, - }; - } catch (err) { - console.error('Token refresh error:', err); - return null; - } -} - -export function handleLogout(request: Request, env: Env): Response { - const url = new URL(request.url); - const returnTo = url.searchParams.get('return_to') || '/'; - - // Build Cognito logout URL - const logoutParams = new URLSearchParams({ - client_id: env.COGNITO_CLIENT_ID, - logout_uri: new URL(returnTo, url.origin).toString(), - }); - - const logoutUrl = `${getLogoutUrl(env)}?${logoutParams.toString()}`; - - return new Response(null, { - status: 302, - headers: [ - ['Location', logoutUrl], - ['Set-Cookie', clearSessionCookie()], - ], - }); -} diff --git a/functions/lib/cognito.ts b/functions/lib/cognito.ts deleted file mode 100644 index 7fbaa6af..00000000 --- a/functions/lib/cognito.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { Env, JWK, JWKS, UserInfo } from './config'; - -let jwksCache: { keys: Map; fetchedAt: number } | null = null; -const JWKS_CACHE_TTL = 3600000; // 1 hour - -function getJwksUrl(env: Env): string { - return `https://cognito-idp.${env.COGNITO_REGION}.amazonaws.com/${env.COGNITO_USER_POOL_ID}/.well-known/jwks.json`; -} - -function getIssuer(env: Env): string { - return `https://cognito-idp.${env.COGNITO_REGION}.amazonaws.com/${env.COGNITO_USER_POOL_ID}`; -} - -async function fetchJwks(env: Env): Promise> { - if (jwksCache && Date.now() - jwksCache.fetchedAt < JWKS_CACHE_TTL) { - return jwksCache.keys; - } - - const response = await fetch(getJwksUrl(env)); - if (!response.ok) { - throw new Error(`Failed to fetch JWKS: ${response.status}`); - } - - const jwks: JWKS = await response.json(); - const keysMap = new Map(); - for (const key of jwks.keys) { - keysMap.set(key.kid, key); - } - - jwksCache = { keys: keysMap, fetchedAt: Date.now() }; - return keysMap; -} - -async function getPublicKey(kid: string, env: Env): Promise { - const keys = await fetchJwks(env); - const jwk = keys.get(kid); - - if (!jwk) { - // Key not found, try refreshing cache - jwksCache = null; - const refreshedKeys = await fetchJwks(env); - const refreshedJwk = refreshedKeys.get(kid); - if (!refreshedJwk) { - throw new Error(`Key ${kid} not found in JWKS`); - } - return importPublicKey(refreshedJwk); - } - - return importPublicKey(jwk); -} - -async function importPublicKey(jwk: JWK): Promise { - return crypto.subtle.importKey( - 'jwk', - { - kty: jwk.kty, - n: jwk.n, - e: jwk.e, - alg: jwk.alg, - use: jwk.use, - }, - { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, - false, - ['verify'] - ); -} - -function base64UrlDecode(str: string): Uint8Array { - const base64 = str.replace(/-/g, '+').replace(/_/g, '/'); - const padding = '='.repeat((4 - (base64.length % 4)) % 4); - const decoded = atob(base64 + padding); - return Uint8Array.from(decoded, (c) => c.charCodeAt(0)); -} - -interface JwtHeader { - alg: string; - kid: string; -} - -interface JwtPayload { - sub: string; - iss: string; - aud?: string; - client_id?: string; - token_use: string; - exp: number; - iat: number; - email?: string; - name?: string; - [key: string]: unknown; -} - -export async function validateIdToken( - idToken: string, - env: Env -): Promise { - const parts = idToken.split('.'); - if (parts.length !== 3) { - throw new Error('Invalid JWT format'); - } - - const [headerB64, payloadB64, signatureB64] = parts; - const header: JwtHeader = JSON.parse( - new TextDecoder().decode(base64UrlDecode(headerB64)) - ); - const payload: JwtPayload = JSON.parse( - new TextDecoder().decode(base64UrlDecode(payloadB64)) - ); - - // Validate claims - const expectedIssuer = getIssuer(env); - if (payload.iss !== expectedIssuer) { - throw new Error(`Invalid issuer: expected ${expectedIssuer}, got ${payload.iss}`); - } - - // ID tokens use 'aud', access tokens use 'client_id' - const audience = payload.aud || payload.client_id; - if (audience !== env.COGNITO_CLIENT_ID) { - throw new Error(`Invalid audience: expected ${env.COGNITO_CLIENT_ID}, got ${audience}`); - } - - if (payload.token_use !== 'id') { - throw new Error(`Invalid token_use: expected 'id', got ${payload.token_use}`); - } - - if (payload.exp * 1000 < Date.now()) { - throw new Error('Token has expired'); - } - - // Verify signature - const publicKey = await getPublicKey(header.kid, env); - const signatureData = base64UrlDecode(signatureB64); - const dataToVerify = new TextEncoder().encode(`${headerB64}.${payloadB64}`); - - const isValid = await crypto.subtle.verify( - 'RSASSA-PKCS1-v1_5', - publicKey, - signatureData, - dataToVerify - ); - - if (!isValid) { - throw new Error('Invalid token signature'); - } - - return { - sub: payload.sub, - email: payload.email, - name: payload.name, - ...extractCustomClaims(payload), - }; -} - -function extractCustomClaims(payload: JwtPayload): Record { - const standardClaims = [ - 'sub', 'iss', 'aud', 'client_id', 'token_use', 'exp', 'iat', - 'auth_time', 'nonce', 'acr', 'amr', 'azp', 'at_hash', - 'email', 'email_verified', 'name', 'given_name', 'family_name', - 'middle_name', 'nickname', 'preferred_username', 'profile', - 'picture', 'website', 'gender', 'birthdate', 'zoneinfo', - 'locale', 'phone_number', 'phone_number_verified', 'address', - 'updated_at', 'cognito:username', 'cognito:groups', - ]; - - const customClaims: Record = {}; - for (const [key, value] of Object.entries(payload)) { - if (!standardClaims.includes(key)) { - customClaims[key] = value; - } - } - return customClaims; -} diff --git a/functions/lib/config.ts b/functions/lib/config.ts deleted file mode 100644 index 587b5b24..00000000 --- a/functions/lib/config.ts +++ /dev/null @@ -1,42 +0,0 @@ -export interface Env { - COGNITO_DOMAIN: string; - COGNITO_CLIENT_ID: string; - COGNITO_CLIENT_SECRET: string; - COGNITO_REGION: string; - COGNITO_USER_POOL_ID: string; - SESSION_SECRET: string; -} - -export interface Session { - refreshToken: string; - expiresAt: number; - userInfo: UserInfo; -} - -export interface UserInfo { - sub: string; - email?: string; - name?: string; - [key: string]: unknown; -} - -export interface TokenResponse { - access_token: string; - id_token: string; - refresh_token: string; - expires_in: number; - token_type: string; -} - -export interface JWK { - kid: string; - kty: string; - alg: string; - use: string; - n: string; - e: string; -} - -export interface JWKS { - keys: JWK[]; -} diff --git a/functions/lib/error-page.ts b/functions/lib/error-page.ts deleted file mode 100644 index ce303439..00000000 --- a/functions/lib/error-page.ts +++ /dev/null @@ -1,110 +0,0 @@ -export function renderErrorPage( - title: string, - message: string, - statusCode: number = 500 -): Response { - const html = ` - - - - - ${escapeHtml(title)} - Kobiton Docs - - - -
-
${statusCode}
-

${escapeHtml(title)}

-

${escapeHtml(message)}

- -
- -`; - - return new Response(html, { - status: statusCode, - headers: { - 'Content-Type': 'text/html; charset=utf-8', - 'Cache-Control': 'no-store', - }, - }); -} - -function escapeHtml(str: string): string { - return str - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} diff --git a/functions/lib/session.ts b/functions/lib/session.ts deleted file mode 100644 index ec22a991..00000000 --- a/functions/lib/session.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { Env, Session } from './config'; - -const COOKIE_NAME = '__session'; -const ENCODER = new TextEncoder(); -const DECODER = new TextDecoder(); - -async function deriveKey(secret: string): Promise { - const keyMaterial = await crypto.subtle.importKey( - 'raw', - ENCODER.encode(secret), - 'PBKDF2', - false, - ['deriveKey'] - ); - - return crypto.subtle.deriveKey( - { - name: 'PBKDF2', - salt: ENCODER.encode('cognito-session-salt'), - iterations: 100000, - hash: 'SHA-256', - }, - keyMaterial, - { name: 'AES-GCM', length: 256 }, - false, - ['encrypt', 'decrypt'] - ); -} - -async function encrypt(data: string, secret: string): Promise { - const key = await deriveKey(secret); - const iv = crypto.getRandomValues(new Uint8Array(12)); - const encrypted = await crypto.subtle.encrypt( - { name: 'AES-GCM', iv }, - key, - ENCODER.encode(data) - ); - - const combined = new Uint8Array(iv.length + encrypted.byteLength); - combined.set(iv, 0); - combined.set(new Uint8Array(encrypted), iv.length); - - return btoa(String.fromCharCode(...combined)); -} - -async function decrypt(encryptedData: string, secret: string): Promise { - const key = await deriveKey(secret); - const combined = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0)); - const iv = combined.slice(0, 12); - const data = combined.slice(12); - - const decrypted = await crypto.subtle.decrypt( - { name: 'AES-GCM', iv }, - key, - data - ); - - return DECODER.decode(decrypted); -} - -export async function getSession( - request: Request, - env: Env -): Promise { - const cookieHeader = request.headers.get('Cookie'); - if (!cookieHeader) return null; - - const cookies = parseCookies(cookieHeader); - const sessionCookie = cookies[COOKIE_NAME]; - if (!sessionCookie) return null; - - try { - const decrypted = await decrypt(sessionCookie, env.SESSION_SECRET); - return JSON.parse(decrypted) as Session; - } catch { - return null; - } -} - -export async function createSessionCookie( - session: Session, - env: Env -): Promise { - const sessionJson = JSON.stringify(session); - const encrypted = await encrypt(sessionJson, env.SESSION_SECRET); - const maxAge = Math.floor((session.expiresAt - Date.now()) / 1000); - const cookie = `${COOKIE_NAME}=${encrypted}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAge}`; - - console.log('Session cookie debug:', { - jsonSize: sessionJson.length, - encryptedSize: encrypted.length, - cookieSize: cookie.length, - maxAge, - }); - - if (cookie.length > 4096) { - console.warn('WARNING: Cookie exceeds 4KB limit, may be rejected by browser'); - } - - return cookie; -} - -export function clearSessionCookie(): string { - return `${COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0`; -} - -export function isExpired(session: Session): boolean { - return Date.now() >= session.expiresAt - 60000; // 1 minute buffer -} - -function parseCookies(cookieHeader: string): Record { - const cookies: Record = {}; - for (const cookie of cookieHeader.split(';')) { - const [name, ...rest] = cookie.trim().split('='); - if (name && rest.length > 0) { - cookies[name] = rest.join('='); - } - } - return cookies; -} - -export function getStateCookie(request: Request): string | null { - const cookieHeader = request.headers.get('Cookie'); - if (!cookieHeader) return null; - const cookies = parseCookies(cookieHeader); - return cookies['__auth_state'] || null; -} - -export function getCodeVerifierCookie(request: Request): string | null { - const cookieHeader = request.headers.get('Cookie'); - if (!cookieHeader) return null; - const cookies = parseCookies(cookieHeader); - return cookies['__code_verifier'] || null; -} - -export function getReturnToCookie(request: Request): string | null { - const cookieHeader = request.headers.get('Cookie'); - if (!cookieHeader) return null; - const cookies = parseCookies(cookieHeader); - return cookies['__return_to'] || null; -} - -export function createAuthStateCookies( - state: string, - codeVerifier: string, - returnTo: string -): string[] { - const maxAge = 600; // 10 minutes - return [ - `__auth_state=${state}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAge}`, - `__code_verifier=${codeVerifier}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAge}`, - `__return_to=${encodeURIComponent(returnTo)}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAge}`, - ]; -} - -export function clearAuthStateCookies(): string[] { - return [ - '__auth_state=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0', - '__code_verifier=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0', - '__return_to=; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=0', - ]; -} diff --git a/package.json b/package.json index 095f6f59..58d77b33 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "devDependencies": { "@antora/cli": "^3.1.2", "@antora/site-generator": "^3.1.2", - "@cloudflare/workers-types": "^4.20241127.0", "@sntke/antora-mermaid-extension": "^0.0.3", "http-server": "^14.1.1", "postcss": "^8.4.25", @@ -50,7 +49,6 @@ "postcss-cli": "^10.1.0", "postcss-import": "^15.1.0", "python-shell": "^5.0.0", - "typescript": "^5.6.3", "wrangler": "^3.91.0" } } diff --git a/tsconfig.functions.json b/tsconfig.functions.json deleted file mode 100644 index 947def08..00000000 --- a/tsconfig.functions.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "lib": ["ES2022"], - "types": ["@cloudflare/workers-types/2023-07-01"], - "strict": true, - "skipLibCheck": true, - "noEmit": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true - }, - "include": ["functions/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/wrangler.toml b/wrangler.toml index 2895c242..7638f746 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,13 +1,2 @@ -name = "admin-docs" +name = "docs" pages_build_output_dir = "build/docs" -fail_open = false - -[vars] -COGNITO_DOMAIN = "us-east-1vpo9m10ko.auth.us-east-1.amazoncognito.com" -COGNITO_CLIENT_ID = "7ileid37iqu389msn6rvrsu437" -COGNITO_REGION = "us-east-1" -COGNITO_USER_POOL_ID = "us-east-1_vPO9m10ko" - -# Secrets (set in Cloudflare dashboard or via wrangler): -# - COGNITO_CLIENT_SECRET -# - SESSION_SECRET (generate with: openssl rand -hex 32) diff --git a/yarn.lock b/yarn.lock index d3417847..5ed8467a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -297,11 +297,6 @@ resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250718.0.tgz#93abadbd1c036088f8e87d911bdd8b598def28ab" integrity sha512-dY16RXKffmugnc67LTbyjdDHZn5NoTF1yHEf2fN4+OaOnoGSp3N1x77QubTDwqZ9zECWxgQfDLjddcH8dWeFhg== -"@cloudflare/workers-types@^4.20241127.0": - version "4.20260130.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20260130.0.tgz#05ecd9112d738f267d93f1f0d0e5786cf1528872" - integrity sha512-eVJZjA4o0ANE/RX5g6mBs5MKRQxcSJYDPsFj8SPul7FDSFv682UzwXK3i0CSdIy/rtDNrMRmwJZ8KxANg2bY8A== - "@cspotcode/source-map-support@0.8.1": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -3535,11 +3530,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@^5.6.3: - version "5.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" - integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== - ufo@^1.5.4: version "1.6.3" resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.3.tgz#799666e4e88c122a9659805e30b9dc071c3aed4f"