@supaku/agentfactory-nextjs 0.4.7 → 0.4.8
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/middleware/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AA0GlD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,CAAC,EAAE,gBAAgB;0BAO3C,WAAW,KAAG,YAAY,GAAG,SAAS;;;;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/middleware/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AA0GlD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,CAAC,EAAE,gBAAgB;0BAO3C,WAAW,KAAG,YAAY,GAAG,SAAS;;;;EAgHpE"}
|
|
@@ -103,9 +103,32 @@ export function createAgentFactoryMiddleware(userConfig) {
|
|
|
103
103
|
function middleware(request) {
|
|
104
104
|
const { pathname } = request.nextUrl;
|
|
105
105
|
const clientIP = getClientIP(request.headers);
|
|
106
|
-
// ===
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
// === PROTECTED INTERNAL APIS (checked first — no rate limiting) ===
|
|
107
|
+
// Must come before public routes because '/' in publicRoutes would
|
|
108
|
+
// match all pathnames via startsWith, rate-limiting authenticated workers.
|
|
109
|
+
if (protectedRoutes.some(route => pathname.startsWith(route))) {
|
|
110
|
+
const workerApiKey = process.env.WORKER_API_KEY;
|
|
111
|
+
// In development without key, allow access
|
|
112
|
+
if (!workerApiKey && process.env.NODE_ENV !== 'production') {
|
|
113
|
+
return NextResponse.next();
|
|
114
|
+
}
|
|
115
|
+
if (!workerApiKey) {
|
|
116
|
+
console.error('WORKER_API_KEY not configured - blocking protected API access');
|
|
117
|
+
return new NextResponse(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }), { status: 401, headers: { 'Content-Type': 'application/json' } });
|
|
118
|
+
}
|
|
119
|
+
const authHeader = request.headers.get('authorization');
|
|
120
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
121
|
+
return new NextResponse(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }), { status: 401, headers: { 'Content-Type': 'application/json' } });
|
|
122
|
+
}
|
|
123
|
+
const token = authHeader.slice(7);
|
|
124
|
+
if (!timingSafeEqual(token, workerApiKey)) {
|
|
125
|
+
return new NextResponse(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }), { status: 401, headers: { 'Content-Type': 'application/json' } });
|
|
126
|
+
}
|
|
127
|
+
return NextResponse.next();
|
|
128
|
+
}
|
|
129
|
+
// === WEBHOOK ROUTE ===
|
|
130
|
+
if (pathname === webhookRoute) {
|
|
131
|
+
const result = checkRateLimit('webhook', clientIP);
|
|
109
132
|
if (!result.allowed) {
|
|
110
133
|
return new NextResponse(JSON.stringify({ error: 'Too many requests' }), {
|
|
111
134
|
status: 429,
|
|
@@ -115,20 +138,19 @@ export function createAgentFactoryMiddleware(userConfig) {
|
|
|
115
138
|
},
|
|
116
139
|
});
|
|
117
140
|
}
|
|
118
|
-
|
|
119
|
-
const rateLimitHeaders = buildRateLimitHeaders(result);
|
|
120
|
-
for (const [key, value] of Object.entries(rateLimitHeaders)) {
|
|
121
|
-
response.headers.set(key, value);
|
|
122
|
-
}
|
|
123
|
-
return response;
|
|
141
|
+
return NextResponse.next();
|
|
124
142
|
}
|
|
125
143
|
// === SESSION DETAIL PAGES ===
|
|
126
144
|
if (sessionPages.some(route => pathname.startsWith(route))) {
|
|
127
145
|
return NextResponse.next();
|
|
128
146
|
}
|
|
129
|
-
// ===
|
|
130
|
-
if (pathname ===
|
|
131
|
-
|
|
147
|
+
// === PASSTHROUGH ROUTES ===
|
|
148
|
+
if (passthroughRoutes.some(route => pathname === route || pathname.startsWith(route))) {
|
|
149
|
+
return NextResponse.next();
|
|
150
|
+
}
|
|
151
|
+
// === PUBLIC ROUTES (rate limited) ===
|
|
152
|
+
if (publicRoutes.some(route => pathname === route || pathname.startsWith(route))) {
|
|
153
|
+
const result = checkRateLimit('public', clientIP);
|
|
132
154
|
if (!result.allowed) {
|
|
133
155
|
return new NextResponse(JSON.stringify({ error: 'Too many requests' }), {
|
|
134
156
|
status: 429,
|
|
@@ -138,32 +160,12 @@ export function createAgentFactoryMiddleware(userConfig) {
|
|
|
138
160
|
},
|
|
139
161
|
});
|
|
140
162
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const workerApiKey = process.env.WORKER_API_KEY;
|
|
146
|
-
// In development without key, allow access
|
|
147
|
-
if (!workerApiKey && process.env.NODE_ENV !== 'production') {
|
|
148
|
-
return NextResponse.next();
|
|
149
|
-
}
|
|
150
|
-
if (!workerApiKey) {
|
|
151
|
-
console.error('WORKER_API_KEY not configured - blocking protected API access');
|
|
152
|
-
return new NextResponse(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }), { status: 401, headers: { 'Content-Type': 'application/json' } });
|
|
153
|
-
}
|
|
154
|
-
const authHeader = request.headers.get('authorization');
|
|
155
|
-
if (!authHeader?.startsWith('Bearer ')) {
|
|
156
|
-
return new NextResponse(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }), { status: 401, headers: { 'Content-Type': 'application/json' } });
|
|
157
|
-
}
|
|
158
|
-
const token = authHeader.slice(7);
|
|
159
|
-
if (!timingSafeEqual(token, workerApiKey)) {
|
|
160
|
-
return new NextResponse(JSON.stringify({ error: 'Unauthorized', message: 'Invalid or missing API key' }), { status: 401, headers: { 'Content-Type': 'application/json' } });
|
|
163
|
+
const response = NextResponse.next();
|
|
164
|
+
const rateLimitHeaders = buildRateLimitHeaders(result);
|
|
165
|
+
for (const [key, value] of Object.entries(rateLimitHeaders)) {
|
|
166
|
+
response.headers.set(key, value);
|
|
161
167
|
}
|
|
162
|
-
return
|
|
163
|
-
}
|
|
164
|
-
// === PASSTHROUGH ROUTES ===
|
|
165
|
-
if (passthroughRoutes.some(route => pathname === route || pathname.startsWith(route))) {
|
|
166
|
-
return NextResponse.next();
|
|
168
|
+
return response;
|
|
167
169
|
}
|
|
168
170
|
// === ALL OTHER ROUTES ===
|
|
169
171
|
return NextResponse.next();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supaku/agentfactory-nextjs",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Next.js API route handlers for AgentFactory — webhook processor, worker/session management, public stats",
|
|
6
6
|
"author": "Supaku (https://supaku.com)",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"LICENSE"
|
|
49
49
|
],
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@supaku/agentfactory": "0.4.
|
|
52
|
-
"@supaku/agentfactory
|
|
53
|
-
"@supaku/agentfactory-
|
|
51
|
+
"@supaku/agentfactory-server": "0.4.8",
|
|
52
|
+
"@supaku/agentfactory": "0.4.8",
|
|
53
|
+
"@supaku/agentfactory-linear": "0.4.8"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"next": ">=14.0.0"
|