chore: remove dead routes/components + fix redact/env cleanup
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
const secretPatterns = [
|
const secretPatterns: { pattern: RegExp; replacement: string }[] = [
|
||||||
/ghs_[A-Za-z0-9_]+/g,
|
{ pattern: /ghs_[A-Za-z0-9_]+/g, replacement: '[redacted]' },
|
||||||
/github_pat_[A-Za-z0-9_]+/g,
|
{ pattern: /github_pat_[A-Za-z0-9_]+/g, replacement: '[redacted]' },
|
||||||
/sk-[A-Za-z0-9_-]+/g,
|
{ pattern: /sk-[A-Za-z0-9_-]+/g, replacement: '[redacted]' },
|
||||||
/(client_secret|auth_secret|api_key|token|password)=([^ \n\r]+)/gi,
|
{
|
||||||
|
pattern: /(client_secret|auth_secret|api_key|token|password)=([^ \n\r]+)/gi,
|
||||||
|
replacement: '$1=[redacted]',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const createRedactor = (values: string[]) => {
|
export const createRedactor = (values: string[]) => {
|
||||||
@@ -12,8 +15,8 @@ export const createRedactor = (values: string[]) => {
|
|||||||
for (const secret of secrets) {
|
for (const secret of secrets) {
|
||||||
output = output.split(secret).join('[redacted]');
|
output = output.split(secret).join('[redacted]');
|
||||||
}
|
}
|
||||||
for (const pattern of secretPatterns) {
|
for (const { pattern, replacement } of secretPatterns) {
|
||||||
output = output.replace(pattern, '$1=[redacted]');
|
output = output.replace(pattern, replacement);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
|
import { createRedactor } from '../../src/redact';
|
||||||
|
|
||||||
|
describe('createRedactor', () => {
|
||||||
|
test('redacts group-less token patterns without emitting a literal $1', () => {
|
||||||
|
const redact = createRedactor([]);
|
||||||
|
const output = redact('token ghs_ABC123 and sk-xyz789 here');
|
||||||
|
|
||||||
|
expect(output).toContain('[redacted]');
|
||||||
|
expect(output).not.toContain('$1');
|
||||||
|
expect(output).not.toContain('ghs_ABC123');
|
||||||
|
expect(output).not.toContain('sk-xyz789');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('redacts github_pat_ tokens to [redacted]', () => {
|
||||||
|
const redact = createRedactor([]);
|
||||||
|
const output = redact('github_pat_ABCDEF123456');
|
||||||
|
|
||||||
|
expect(output).toBe('[redacted]');
|
||||||
|
expect(output).not.toContain('$1');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('keeps the key= prefix for key=value secrets', () => {
|
||||||
|
const redact = createRedactor([]);
|
||||||
|
|
||||||
|
expect(redact('api_key=secret')).toBe('api_key=[redacted]');
|
||||||
|
expect(redact('password=hunter2')).toBe('password=[redacted]');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('redacts caller-supplied secret values verbatim', () => {
|
||||||
|
const redact = createRedactor(['super-secret-value']);
|
||||||
|
|
||||||
|
expect(redact('the value is super-secret-value')).toBe(
|
||||||
|
'the value is [redacted]',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
const AgentsRedirectPage = () => {
|
|
||||||
redirect('/threads?source=user_request');
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AgentsRedirectPage;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
const AiSettingsPage = () => redirect('/settings/ai-providers');
|
|
||||||
|
|
||||||
export default AiSettingsPage;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
const UpdatesRedirectPage = () => {
|
|
||||||
redirect('/threads?source=upstream_update');
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UpdatesRedirectPage;
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import type { Metadata } from 'next';
|
|
||||||
import { redirect } from 'next/navigation';
|
|
||||||
import { isAuthenticatedNextjs } from '@convex-dev/auth/nextjs/server';
|
|
||||||
|
|
||||||
export const generateMetadata = (): Metadata => {
|
|
||||||
return {
|
|
||||||
title: 'Profile',
|
|
||||||
robots: {
|
|
||||||
index: false,
|
|
||||||
follow: false,
|
|
||||||
googleBot: {
|
|
||||||
index: false,
|
|
||||||
follow: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const ProfileLayout = async ({
|
|
||||||
children,
|
|
||||||
}: Readonly<{ children: React.ReactNode }>) => {
|
|
||||||
if (!(await isAuthenticatedNextjs())) redirect('/sign-in');
|
|
||||||
return <>{children}</>;
|
|
||||||
};
|
|
||||||
export default ProfileLayout;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
const Profile = () => {
|
|
||||||
redirect('/settings/profile');
|
|
||||||
};
|
|
||||||
export default Profile;
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
const techStack = [
|
|
||||||
{
|
|
||||||
category: 'Frontend',
|
|
||||||
technologies: [
|
|
||||||
{ name: 'Next.js 16', description: 'React framework with App Router' },
|
|
||||||
{ name: 'Expo 54', description: 'React Native framework' },
|
|
||||||
{ name: 'React 19', description: 'Latest React with Server Components' },
|
|
||||||
{
|
|
||||||
name: 'Tailwind CSS v4',
|
|
||||||
description: 'Utility-first CSS framework',
|
|
||||||
},
|
|
||||||
{ name: 'shadcn/ui', description: 'Beautiful component library' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Backend',
|
|
||||||
technologies: [
|
|
||||||
{ name: 'Convex', description: 'Self-hosted reactive backend' },
|
|
||||||
{
|
|
||||||
name: '@convex-dev/auth',
|
|
||||||
description: 'Multi-provider authentication',
|
|
||||||
},
|
|
||||||
{ name: 'UseSend', description: 'Self-hosted email service' },
|
|
||||||
{ name: 'File Storage', description: 'Built-in file uploads' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Developer Tools',
|
|
||||||
technologies: [
|
|
||||||
{ name: 'Turborepo', description: 'High-performance build system' },
|
|
||||||
{ name: 'TypeScript', description: 'Type-safe development' },
|
|
||||||
{ name: 'Bun', description: 'Fast package manager and runtime' },
|
|
||||||
{ name: 'ESLint + Prettier', description: 'Code quality tools' },
|
|
||||||
{ name: 'Docker', description: 'Containerized deployment' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const TechStack = () => (
|
|
||||||
<section id='tech-stack' className='border-border/40 bg-muted/30 border-t'>
|
|
||||||
<div className='container mx-auto px-4 py-24'>
|
|
||||||
<div className='mx-auto max-w-6xl'>
|
|
||||||
<div className='mb-16 text-center'>
|
|
||||||
<h2 className='mb-4 text-3xl font-bold tracking-tight sm:text-4xl md:text-5xl'>
|
|
||||||
Modern Tech Stack
|
|
||||||
</h2>
|
|
||||||
<p className='text-muted-foreground mx-auto max-w-2xl text-lg'>
|
|
||||||
Built with the latest and greatest tools for maximum productivity
|
|
||||||
and performance.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='grid gap-12 md:grid-cols-3'>
|
|
||||||
{techStack.map((stack) => (
|
|
||||||
<div key={stack.category}>
|
|
||||||
<h3 className='mb-6 text-xl font-semibold'>{stack.category}</h3>
|
|
||||||
<ul className='space-y-4'>
|
|
||||||
{stack.technologies.map((tech) => (
|
|
||||||
<li key={tech.name}>
|
|
||||||
<div className='text-foreground font-medium'>
|
|
||||||
{tech.name}
|
|
||||||
</div>
|
|
||||||
<div className='text-muted-foreground text-sm'>
|
|
||||||
{tech.description}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
@@ -33,7 +33,6 @@ const runtimeLabels: Record<RuntimeName, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type AgentSettings = {
|
type AgentSettings = {
|
||||||
_id?: Id<'spoonAgentSettings'>;
|
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
runtime?: RuntimeName | 'openai_direct';
|
runtime?: RuntimeName | 'openai_direct';
|
||||||
defaultBaseBranch?: string;
|
defaultBaseBranch?: string;
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ const runtimeLabels: Record<RuntimeName, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type AgentSettings = {
|
type AgentSettings = {
|
||||||
_id?: Id<'spoonAgentSettings'>;
|
|
||||||
defaultBaseBranch?: string;
|
defaultBaseBranch?: string;
|
||||||
runtime?: RuntimeName | 'openai_direct';
|
runtime?: RuntimeName | 'openai_direct';
|
||||||
agentModel: string;
|
agentModel: string;
|
||||||
|
|||||||
@@ -8,12 +8,9 @@ const isAuthRoute = createRouteMatcher(['/sign-in', '/forgot-password']);
|
|||||||
const isProtectedRoute = createRouteMatcher([
|
const isProtectedRoute = createRouteMatcher([
|
||||||
'/dashboard(.*)',
|
'/dashboard(.*)',
|
||||||
'/spoons(.*)',
|
'/spoons(.*)',
|
||||||
'/updates(.*)',
|
|
||||||
'/agents(.*)',
|
|
||||||
'/threads(.*)',
|
'/threads(.*)',
|
||||||
'/github(.*)',
|
'/github(.*)',
|
||||||
'/settings(.*)',
|
'/settings(.*)',
|
||||||
'/profile(.*)',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default convexAuthNextjsMiddleware(
|
export default convexAuthNextjsMiddleware(
|
||||||
|
|||||||
Reference in New Issue
Block a user