Feat: Support Triage [agentkit-challenge]#80
Feat: Support Triage [agentkit-challenge]#80VITianYash42 wants to merge 20 commits intoLamatic:mainfrom
Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 29 minutes and 31 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (6)
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughMission: Established an "AI Support Triage Engine" Next.js kit — adds frontend UI, backend Lamatic API route, project config (TS, ESLint, Tailwind), documentation, and environment templates for running AI-driven ticket triage. Changes
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (4)
kits/automation/support-triage/README.md (1)
16-17: Update placeholder Flow ID.The Flow ID shows
your-flow-idas a placeholder. Consider either removing this line (since users will set it via environment variables) or noting this is obtained from Lamatic Studio after flow creation.kits/automation/support-triage/app/layout.tsx (1)
15-18: Update boilerplate metadata.The metadata still contains default "Create Next App" values. Update to reflect the actual kit purpose.
✏️ Suggested metadata
export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "AI Support Triage Engine", + description: "Automated customer support ticket categorization, sentiment analysis, and draft response generation", };kits/automation/support-triage/app/globals.css (1)
22-26: Use the configured font variable instead of hardcoded Arial.The
@theme inlineblock defines--font-sans: var(--font-geist-sans), but the body styles hardcodeArial, Helvetica, sans-serif. Use the Tailwind font variable for consistency with the configured Geist fonts.✏️ Proposed fix
body { background: var(--background); color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + font-family: var(--font-sans), Arial, Helvetica, sans-serif; }kits/automation/support-triage/config.json (1)
19-22: Populate public URLs in config for discoverability.Given this PR already provides a live preview and walkthrough, leaving
demoUrl,deployUrl, anddocumentationUrlempty misses useful kit metadata.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: dfad26f1-5b68-4704-bd09-a8fec7c77d22
⛔ Files ignored due to path filters (7)
kits/automation/support-triage/app/favicon.icois excluded by!**/*.icokits/automation/support-triage/package-lock.jsonis excluded by!**/package-lock.jsonkits/automation/support-triage/public/file.svgis excluded by!**/*.svgkits/automation/support-triage/public/globe.svgis excluded by!**/*.svgkits/automation/support-triage/public/next.svgis excluded by!**/*.svgkits/automation/support-triage/public/vercel.svgis excluded by!**/*.svgkits/automation/support-triage/public/window.svgis excluded by!**/*.svg
📒 Files selected for processing (12)
kits/automation/support-triage/.gitignorekits/automation/support-triage/README.mdkits/automation/support-triage/app/globals.csskits/automation/support-triage/app/layout.tsxkits/automation/support-triage/app/page.tsxkits/automation/support-triage/app/utils.tskits/automation/support-triage/config.jsonkits/automation/support-triage/eslint.config.mjskits/automation/support-triage/next.config.tskits/automation/support-triage/package.jsonkits/automation/support-triage/postcss.config.mjskits/automation/support-triage/tsconfig.json
| export const lamaticClient = new Lamatic({ | ||
| endpoint:process.env.NEXT_PUBLIC_LAMATIC_PROJECT_ENDPOINT as string, | ||
| projectId: process.env.NEXT_PUBLIC_LAMATIC_PROJECT_ID as string, | ||
| apiKey: process.env.NEXT_PUBLIC_LAMATIC_PROJECT_API_KEY as string, | ||
| }) |
There was a problem hiding this comment.
Security: API key exposed to the browser via NEXT_PUBLIC_ prefix.
Environment variables prefixed with NEXT_PUBLIC_ are bundled into the client-side JavaScript and visible to anyone inspecting the page. The NEXT_PUBLIC_LAMATIC_PROJECT_API_KEY will be exposed in the browser, allowing unauthorized use of your API credentials.
Move API calls to a server-side API route (app/api/triage/route.ts) and use non-prefixed environment variables.
🔒 Recommended approach: Create a server-side API route
Create app/api/triage/route.ts:
import { Lamatic } from 'lamatic';
import { NextRequest, NextResponse } from 'next/server';
const lamaticClient = new Lamatic({
endpoint: process.env.LAMATIC_PROJECT_ENDPOINT!,
projectId: process.env.LAMATIC_PROJECT_ID!,
apiKey: process.env.LAMATIC_PROJECT_API_KEY!,
});
export async function POST(request: NextRequest) {
const { ticket_text } = await request.json();
const response = await lamaticClient.executeFlow(
process.env.LAMATIC_FLOW_ID!,
{ ticket_text }
);
return NextResponse.json(response);
}There was a problem hiding this comment.
please use server side JWT encryptions
There was a problem hiding this comment.
@amanintech, understood! Here's the mission plan to implement server-side JWT authentication to lock down the /api/triage route while keeping all credentials out of the browser.
Mission: Server-side JWT Encryption for /api/triage
- Add
josefor Edge-compatible JWT signing/verification - Add
JWT_SECRETto.env.example - Create
/api/tokenroute to issue short-lived JWTs server-side - Protect
/api/triageroute with JWT verification - Remove
utils.ts(the leaked client) - Update
page.tsxto fetch a token before calling/api/triage
Here's the overall security flow after these changes:
sequenceDiagram
participant Browser
participant TokenServer as /api/token (Server)
participant TriageServer as /api/triage (Server)
participant Lamatic
Browser->>+TokenServer: POST (no credentials)
TokenServer-->>-Browser: { token: "<signed JWT, 2min TTL>" }
Browser->>+TriageServer: POST Authorization: Bearer <token>
TriageServer->>+TriageServer: jwtVerify(token, JWT_SECRET)
TriageServer->>+Lamatic: executeFlow(flowId, { ticket_text })
Lamatic-->>-TriageServer: triage result
TriageServer-->>-Browser: { category, sentiment, urgency, draft }
Key security properties of this approach:
- 🔒
LAMATIC_PROJECT_API_KEY,LAMATIC_PROJECT_ID, andJWT_SECRETnever leave the server - ⏱️ JWTs are short-lived (2 min), limiting replay attack windows
- 🚫
/api/triagerejects any request without a valid, unexpired JWT - ✅ No
NEXT_PUBLIC_prefixes needed anywhere
✏️ Learnings added
Learnt from: amanintech
Repo: Lamatic/AgentKit PR: 80
File: kits/automation/support-triage/app/utils.ts:0-0
Timestamp: 2026-03-27T19:13:29.605Z
Learning: In `kits/automation/support-triage`, the maintainer (amanintech) requires server-side JWT authentication for API routes. Use the `jose` library with an `HS256` short-lived JWT (2-minute TTL) issued by `/api/token` and verified in `/api/triage`. The JWT_SECRET must be a non-NEXT_PUBLIC_ env var. All Lamatic credentials (LAMATIC_PROJECT_ENDPOINT, LAMATIC_PROJECT_ID, LAMATIC_PROJECT_API_KEY, LAMATIC_FLOW_ID) must also be non-NEXT_PUBLIC_ and server-only.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: CR
Repo: Lamatic/AgentKit PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-23T17:08:51.738Z
Learning: Applies to kits/**/lib/lamatic-client.ts : Use the `lib/lamatic-client.ts` pattern to initialize the Lamatic SDK with `LAMATIC_API_URL`, `LAMATIC_PROJECT_ID`, and `LAMATIC_API_KEY`
Learnt from: CR
Repo: Lamatic/AgentKit PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-23T17:08:51.738Z
Learning: Applies to kits/**/actions/**/*.ts : Kit server action files (e.g., `actions/orchestrate.ts`) must call Lamatic flows via the SDK and read flow IDs from environment variables
Failed to handle agent chat message. Please try again.
There was a problem hiding this comment.
Actionable comments posted: 4
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 431fe6de-06eb-4766-89f8-5b0d5cd6b042
📒 Files selected for processing (7)
kits/automation/support-triage/.env.examplekits/automation/support-triage/.gitignorekits/automation/support-triage/app/api/triage/route.jskits/automation/support-triage/app/globals.csskits/automation/support-triage/app/layout.tsxkits/automation/support-triage/app/page.tsxkits/automation/support-triage/config.json
✅ Files skipped from review due to trivial changes (2)
- kits/automation/support-triage/.gitignore
- kits/automation/support-triage/config.json
🚧 Files skipped from review as they are similar to previous changes (1)
- kits/automation/support-triage/app/layout.tsx
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ca9f0c9f-ba30-4ca1-ab93-fda9e0b4cbb1
📒 Files selected for processing (1)
kits/automation/support-triage/app/page.tsx
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
kits/automation/support-triage/app/api/triage/route.ts (2)
12-12:⚠️ Potential issue | 🟠 MajorAgent, your perimeter is unguarded—hostile payloads may breach.
The API currently trusts client input without validation. A missing, non-string, or empty
ticket_textwill pass through to the Lamatic provider, causing unnecessary calls and ambiguous failures. This intel was previously transmitted—awaiting implementation.🛡️ Proposed validation block
- const { ticket_text } = await request.json(); + const body = await request.json(); + const ticket_text = + typeof body?.ticket_text === "string" ? body.ticket_text.trim() : ""; + + if (!ticket_text) { + return NextResponse.json( + { error: "ticket_text must be a non-empty string." }, + { status: 400 } + ); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@kits/automation/support-triage/app/api/triage/route.ts` at line 12, Validate the incoming ticket_text immediately after parsing request.json(): ensure ticket_text exists, is a string, and is not empty/whitespace; if validation fails return a 400/Bad Request response with a clear error message instead of calling the Lamatic provider. Update the code around the const { ticket_text } = await request.json(); extraction (the request.json() parsing and any subsequent call to the Lamatic provider) to perform these checks and short-circuit on invalid input.
19-20:⚠️ Potential issue | 🟠 MajorAgent, mission control is receiving false positives.
The
executeFlowresponse may include{ status: "error", message: ... }, which this route currently returns as HTTP 200. The frontend inpage.tsx(lines 26-39) checks fordata.errorand rate-limit patterns, but a Lamatic error response won't trigger those guards—it'll slip through as "success."Other kits in this repo check
response?.status === "error"and handle accordingly. This intel was previously transmitted—awaiting alignment with established protocol.🔧 Proposed response handling
const response = await lamaticClient.executeFlow(flowId, { ticket_text }); - return NextResponse.json(response); + if (response?.status === "error") { + return NextResponse.json( + { error: response?.message || "Lamatic flow execution failed." }, + { status: 502 } + ); + } + + return NextResponse.json(response?.result ?? response);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@kits/automation/support-triage/app/api/triage/route.ts` around lines 19 - 20, The route currently returns lamaticClient.executeFlow(flowId, { ticket_text }) directly as HTTP 200 even when the response is an error object; update the handler in route.ts to inspect the returned value from lamaticClient.executeFlow (e.g., check response?.status === "error" or presence of response.message) and return an appropriate non-200 response (use NextResponse.json with a 4xx/5xx status or NextResponse.error) when an error status is present, otherwise return the successful payload via NextResponse.json; reference lamaticClient.executeFlow, flowId, ticket_text, and NextResponse.json when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Around line 4-8: The Lamatic client is being constructed at module load using
non-null assertions (Lamatic and lamaticClient built from
process.env.LAMATIC_PROJECT_ENDPOINT!, LAMATIC_PROJECT_ID!,
LAMATIC_PROJECT_API_KEY!), which will crash the module with a cryptic error if
any env var is missing; change this to either validate env vars up-front with
clear diagnostic messages or lazily create the client at request time via a
factory like getLamaticClient() that checks
process.env.LAMATIC_PROJECT_ENDPOINT/ID/API_KEY and throws or returns a
controlled error; update any callers (e.g., where flowId is checked) to call the
factory and handle/report the explicit error instead of relying on non-null
assertions at import time.
- Line 21: The catch currently types the caught value as any; change it to
unknown (catch(error: unknown)) and explicitly narrow before using it: check if
error is an instance of Error to access error.message/stack, otherwise coerce to
string (e.g., String(error)) before logging/returning. Update the error handling
inside the same route handler in route.ts (the catch(error: any) block) to
perform this narrowing so TypeScript safety is preserved.
---
Duplicate comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Line 12: Validate the incoming ticket_text immediately after parsing
request.json(): ensure ticket_text exists, is a string, and is not
empty/whitespace; if validation fails return a 400/Bad Request response with a
clear error message instead of calling the Lamatic provider. Update the code
around the const { ticket_text } = await request.json(); extraction (the
request.json() parsing and any subsequent call to the Lamatic provider) to
perform these checks and short-circuit on invalid input.
- Around line 19-20: The route currently returns
lamaticClient.executeFlow(flowId, { ticket_text }) directly as HTTP 200 even
when the response is an error object; update the handler in route.ts to inspect
the returned value from lamaticClient.executeFlow (e.g., check response?.status
=== "error" or presence of response.message) and return an appropriate non-200
response (use NextResponse.json with a 4xx/5xx status or NextResponse.error)
when an error status is present, otherwise return the successful payload via
NextResponse.json; reference lamaticClient.executeFlow, flowId, ticket_text, and
NextResponse.json when making this change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: ad30a0ae-20a4-4a81-979e-a620388e7fe7
📒 Files selected for processing (1)
kits/automation/support-triage/app/api/triage/route.ts
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
kits/automation/support-triage/app/api/triage/route.ts (2)
22-23:⚠️ Potential issue | 🟠 MajorMission gap: Lamatic error payloads can still leak through as HTTP 200.
Line 23 returns raw
executeFlowoutput. If Lamatic returns{ status: "error", ... }, clients will treat it as success. Map this to a non-2xx status.🛠️ Proposed response handling
const response = await lamaticClient.executeFlow(flowId, { ticket_text }); - return NextResponse.json(response); + if (response?.status === "error") { + return NextResponse.json( + { error: response?.message || "Lamatic flow execution failed." }, + { status: 502 } + ); + } + + return NextResponse.json(response?.result ?? response);#!/bin/bash set -euo pipefail echo "== Locate executeFlow call sites and surrounding handling ==" rg -nP --type=ts --type=js -C3 '\bexecuteFlow\s*\(' echo echo "== Locate Lamatic error-shape checks ==" rg -nP --type=ts --type=js -C3 'response\?\.(status|result)|status\s*===\s*["'"'"']error["'"'"']'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@kits/automation/support-triage/app/api/triage/route.ts` around lines 22 - 23, The route currently returns lamaticClient.executeFlow output directly (call at lamaticClient.executeFlow(flowId, { ticket_text }) and return via NextResponse.json), which can leak Lamatic error payloads as HTTP 200; update the handler to inspect the returned object (e.g., check response?.status === 'error' or response?.result?.status === 'error') and map error cases to a non-2xx HTTP response (use NextResponse.json(response, { status: 400/500 }) with an appropriate status code and message), otherwise return the successful payload as before — modify the code around the executeFlow call and the NextResponse.json return to perform this conditional branching.
20-20:⚠️ Potential issue | 🟠 MajorMission gap: validate
ticket_textbefore calling Lamatic.Line 20 trusts request JSON shape. Reject missing/non-string/empty
ticket_textwith HTTP 400 before Line 22 to avoid ambiguous provider failures and wasted calls.✅ Proposed validation
- const { ticket_text } = await request.json(); + const body = await request.json(); + const ticket_text = + typeof body?.ticket_text === "string" ? body.ticket_text.trim() : ""; + + if (!ticket_text) { + return NextResponse.json( + { error: "ticket_text must be a non-empty string." }, + { status: 400 } + ); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@kits/automation/support-triage/app/api/triage/route.ts` at line 20, Request JSON is currently trusted when extracting const { ticket_text } = await request.json(); — add validation immediately after parsing (before any call to Lamatic) to reject missing, non-string, or empty/whitespace-only ticket_text with an HTTP 400 Response; specifically, check typeof ticket_text === 'string' and ticket_text.trim().length > 0 and return early with a 400 and clear error message if validation fails so downstream calls to Lamatic (the provider invocation) are never made with bad input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Around line 9-16: The code reads process.env.LAMATIC_FLOW_ID into flowId but
the kit's metadata exposes NEXT_PUBLIC_LAMATIC_FLOW_ID; update the kit
configuration so the environment variable used by this route is LAMATIC_FLOW_ID
(server-only) instead of NEXT_PUBLIC_LAMATIC_FLOW_ID, and ensure config.json no
longer declares a NEXT_PUBLIC_ variant; keep the route reference to
process.env.LAMATIC_FLOW_ID (flowId) and remove any public export to prevent
leaking server-only Lamatic credentials.
- Around line 4-23: The POST route is unprotected and uses a public env key; add
HS256 JWT verification at the start of the POST handler (before parsing the body
and calling lamaticClient.executeFlow) using the `jose` library and the
server-only `JWT_SECRET` env var to reject requests with invalid/missing bearer
tokens, then proceed only on successful verification; update your config.json
entry from "envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID" to "envKey":
"LAMATIC_FLOW_ID" to keep the flow ID server-only; additionally, validate
`ticket_text` (non-empty string) before calling `Lamatic.executeFlow` and
inspect the Lamatic response (treat response.status >= 400 as an error and map
it to a proper NextResponse with an error status/message) so you never return
raw error payloads directly.
---
Duplicate comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Around line 22-23: The route currently returns lamaticClient.executeFlow
output directly (call at lamaticClient.executeFlow(flowId, { ticket_text }) and
return via NextResponse.json), which can leak Lamatic error payloads as HTTP
200; update the handler to inspect the returned object (e.g., check
response?.status === 'error' or response?.result?.status === 'error') and map
error cases to a non-2xx HTTP response (use NextResponse.json(response, {
status: 400/500 }) with an appropriate status code and message), otherwise
return the successful payload as before — modify the code around the executeFlow
call and the NextResponse.json return to perform this conditional branching.
- Line 20: Request JSON is currently trusted when extracting const { ticket_text
} = await request.json(); — add validation immediately after parsing (before any
call to Lamatic) to reject missing, non-string, or empty/whitespace-only
ticket_text with an HTTP 400 Response; specifically, check typeof ticket_text
=== 'string' and ticket_text.trim().length > 0 and return early with a 400 and
clear error message if validation fails so downstream calls to Lamatic (the
provider invocation) are never made with bad input.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4e042d77-24b9-428f-b62e-6babbf20a514
📒 Files selected for processing (1)
kits/automation/support-triage/app/api/triage/route.ts
| export async function POST(request: NextRequest) { | ||
| try { | ||
| const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT; | ||
| const projectId = process.env.LAMATIC_PROJECT_ID; | ||
| const apiKey = process.env.LAMATIC_PROJECT_API_KEY; | ||
| const flowId = process.env.LAMATIC_FLOW_ID; | ||
|
|
||
| // Fails fast and safely if env vars are missing | ||
| if (!endpoint || !projectId || !apiKey || !flowId) { | ||
| return NextResponse.json( | ||
| { error: "Missing required Lamatic environment variables on the server." }, | ||
| { status: 500 } | ||
| ); | ||
| } | ||
|
|
||
| const lamaticClient = new Lamatic({ endpoint, projectId, apiKey }); | ||
| const { ticket_text } = await request.json(); | ||
|
|
||
| const response = await lamaticClient.executeFlow(flowId, { ticket_text }); | ||
| return NextResponse.json(response); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Verify /api/token route exists =="
fd -i 'route\.ts$' kits/automation/support-triage/app/api/token
echo
echo "== Verify JWT issuance/verification usage in support-triage API routes =="
rg -nP --type=ts -C2 'SignJWT|jwtVerify|HS256|JWT_SECRET|authorization' kits/automation/support-triage/app/apiRepository: Lamatic/AgentKit
Length of output: 245
🏁 Script executed:
# Search entire support-triage codebase for JWT/token references
find kits/automation/support-triage -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name ".env*" -o -name "*.json" \) | head -20Repository: Lamatic/AgentKit
Length of output: 475
🏁 Script executed:
# Look for jose library usage or JWT references across entire triage kit
rg -i 'jose|jwtverify|signjwt|jwt_secret|authorization.*bearer' kits/automation/support-triage --type=ts --type=tsx --type=json -lRepository: Lamatic/AgentKit
Length of output: 87
🏁 Script executed:
# Check the actual triage route file to see complete implementation including error handling
cat kits/automation/support-triage/app/api/triage/route.tsRepository: Lamatic/AgentKit
Length of output: 1186
🏁 Script executed:
# Check config.json and .env files for environment variable naming
find kits/automation/support-triage -name "config.json" -o -name ".env*" | xargs cat 2>/dev/nullRepository: Lamatic/AgentKit
Length of output: 1237
This mission cannot be accepted in its current state: /api/triage is executing privileged Lamatic flows without authentication.
Your route processes API requests on line 4 without verifying bearer tokens. This exposes the Lamatic flow to unauthorized abuse and quota exhaustion. Additionally, your config.json declares NEXT_PUBLIC_LAMATIC_FLOW_ID, but per architectural requirements, all Lamatic credentials must remain server-only non-NEXT_PUBLIC_ environment variables—your code correctly reads LAMATIC_FLOW_ID, creating a configuration inconsistency that will confuse developers.
Critical blockers:
-
Missing JWT authentication. Gate the route with HS256 JWT verification before line 20 body processing. Use the
joselibrary with tokens issued by an/api/tokenendpoint (currently missing). The JWT_SECRET environment variable must also be server-only. -
config.json environment key violation. Correct
"envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID"to"envKey": "LAMATIC_FLOW_ID"to align with.env.exampleand maintain server-side credential isolation.
🔐 JWT verification patch (before line 20)
import { Lamatic } from 'lamatic';
+import { jwtVerify } from 'jose';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
try {
+ const authHeader = request.headers.get("authorization");
+ if (!authHeader?.startsWith("Bearer ")) {
+ return NextResponse.json({ error: "Missing bearer token." }, { status: 401 });
+ }
+
+ const jwtSecret = process.env.JWT_SECRET;
+ if (!jwtSecret) {
+ return NextResponse.json({ error: "Missing JWT_SECRET on server." }, { status: 500 });
+ }
+
+ try {
+ const token = authHeader.slice("Bearer ".length);
+ await jwtVerify(token, new TextEncoder().encode(jwtSecret), {
+ algorithms: ["HS256"],
+ });
+ } catch {
+ return NextResponse.json({ error: "Invalid or expired token." }, { status: 401 });
+ }
+
const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT;Outstanding issues from prior review:
- Validate
ticket_textinput before passing toexecuteFlow - Map Lamatic response status errors (e.g.,
response.status >= 400) before returning raw response
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@kits/automation/support-triage/app/api/triage/route.ts` around lines 4 - 23,
The POST route is unprotected and uses a public env key; add HS256 JWT
verification at the start of the POST handler (before parsing the body and
calling lamaticClient.executeFlow) using the `jose` library and the server-only
`JWT_SECRET` env var to reject requests with invalid/missing bearer tokens, then
proceed only on successful verification; update your config.json entry from
"envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID" to "envKey": "LAMATIC_FLOW_ID" to keep
the flow ID server-only; additionally, validate `ticket_text` (non-empty string)
before calling `Lamatic.executeFlow` and inspect the Lamatic response (treat
response.status >= 400 as an error and map it to a proper NextResponse with an
error status/message) so you never return raw error payloads directly.
|
@vrijraj The CI checks are now passing. I have implemented secure server-side API routes for the Lamatic client to address the CodeRabbit security flag, and added the required flow schema files to satisfy the validation pipeline. Ready for your review. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@vrijraj The structural validation for the flow schema is passing locally, but the GitHub Action is failing at the final step (HTTP 403) when trying to post the validation summary comment and apply the passing label. This appears to be a GitHub Token permissions restriction for workflows triggered from a forked repository. My codebase is ready for review whenever you have a moment. |
There was a problem hiding this comment.
Could you add a live demo link to this file? would allow us to view the functionality better, and allow users to see the kit before forking it. otherwise, LGTM. Thanks! Will check once that is fixed and github action will be handled
There was a problem hiding this comment.
@d-pamneja I already have added the live demo link to the README! You can also test the deployment here: https://agent-kit-ten.vercel.app/
Thanks for the review. Let me know if you need anything else to unblock the merge.
There was a problem hiding this comment.
@d-pamneja Sorry for that! I had hardcoded the text colors for a dark theme and missed the light mode toggle. I've updated the Tailwind classes to properly support both light and dark system preferences. The Vercel deployment has been automatically updated with the fix.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|

What This Kit Does
Automates customer support by taking inbound tickets and instantly generating a category, sentiment analysis, urgency level, and a draft email response. This saves time, reduces manual routing work, and improves response clarity.
Video Walkthrough: (https://drive.google.com/file/d/192fqT63JLxS9tOcBvN-nEK8ll36xbKhs/view?usp=sharing)
Providers & Prerequisites
(Note: Requires a 60-second cooldown between requests to prevent 429 Rate Limit errors. The Next.js UI explicitly catches and handles this exception.)
(Note 2: The Lamatic Studio UI currently lacks the 'Export' button on the flow menu as documented in CONTRIBUTING.md, so raw JSON flow files are intentionally omitted.)
How to Run Locally
cd kits/automation/support-triagenpm installcp .env.example .env.localand fill in valuesnpm run devLive Preview
https://agent-kit-git-feat-suppo-3f22fd-yash-singhals-projects-d43367ba.vercel.app/
Lamatic Flow
Flow ID:
c5e67b16-fa77-454d-80d4-77b40adbda38Flow file check: