Handle KAI token config and route normalization#16
Handle KAI token config and route normalization#16ahmadnathanfirdaus wants to merge 1 commit intocomuline:mainfrom
Conversation
📝 WalkthroughWalkthroughThis PR introduces dynamic bearer token configuration by adding a KAI_BEARER_TOKEN environment variable to replace hard-coded tokens, updates documentation with setup instructions for this token in dev and production workflows, and refactors the schedule synchronization logic to normalize station names and improve error handling. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/sync/schedule.ts (1)
211-214: Wrong table reference in WHERE clause.The update targets
stationTablebut the WHERE clause referencesscheduleTable.id. This condition will never match the intended station row.Proposed fix
await db .update(stationTable) .set(payload) - .where(eq(scheduleTable.id, id)) + .where(eq(stationTable.id, id))
🤖 Fix all issues with AI agents
In @.dev.example.vars:
- Line 10: Replace the real JWT value assigned to KAI_BEARER_TOKEN in the
.dev.example.vars file with a clear placeholder (e.g., "your-bearer-token-here"
or "<KAI_BEARER_TOKEN>") so the example contains no secrets; update the
KAI_BEARER_TOKEN entry only (preserve surrounding formatting) and add a brief
comment if desired indicating it is a placeholder. After changing the example,
ensure any real token shown here is revoked/rotated in the credential store and
confirm the repo history is purged or rotate credentials if the token was
committed publicly.
In `@src/sync/headers.ts`:
- Around line 1-8: The module currently builds KAI_HEADERS using
KAI_BEARER_TOKEN which can be "undefined"; update the module to validate
process.env.KAI_BEARER_TOKEN at import time and fail fast if missing (e.g.,
throw a clear Error like "Missing KAI_BEARER_TOKEN env var") before exporting
KAI_HEADERS so Authorization is never "Bearer undefined"; reference the
KAI_BEARER_TOKEN constant and the KAI_HEADERS export when adding this check.
In `@src/sync/schedule.ts`:
- Around line 51-64: The regexes in normalizeStationKey use double-escaped
sequences (e.g. /VIA\\s*MRI/g and /\\s+/g) which match a backslash + 's' instead
of whitespace; update those regex literals to use single backslashes (e.g.
/VIA\s*MRI/g and /\s+/g) so \s behaves as the whitespace metacharacter, leaving
other patterns like /VIAMRI/g and /[^A-Z0-9]/g unchanged.
🧹 Nitpick comments (1)
README.md (1)
90-92: Add language specifier to fenced code block.Per markdownlint (MD040), fenced code blocks should have a language specified.
Proposed fix
-``` +```bash COMULINE_ENV=production</details> </blockquote></details> </blockquote></details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
| # KRL stuff | ||
| KRL_ENDPOINT_BASE_URL="https://api-partner.krl.co.id/krl-webs/v1" No newline at end of file | ||
| KRL_ENDPOINT_BASE_URL="https://api-partner.krl.co.id/krl-webs/v1" | ||
| KAI_BEARER_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzIiwianRpIjoiYmE0Yzc4MzE4ODNjYTI0N2YzMTBkMTJhYzc3ZjE5ZTdjMTVkNjgxOTk2ODM0MDc0MGM3MzliYmRjNGQ3YTI5MzczYzMyNWM2NDFiZjgxYzciLCJpYXQiOjE3NTQ0NTkxMjYsIm5iZiI6MTc1NDQ1OTEyNiwiZXhwIjoxNzg1OTk1MTI2LCJzdWIiOiI1Iiwic2NvcGVzIjpbXX0.zPA0IDAN3NycMKa6DaOdRmkcFz1oUTX1dkxEp3MLBlhibTQI0L0WB9mY-pUlQW5vQj8ktOdo-rRvrjxiXaHFqLQM6ebONbqTg8V0AjBXwrkBjLZDCE4dop9iZyDXcG2b9XTLCgPgpOBbduW_Dy0-bIkJOOIgIzl9mEEUVQf3T6G_zA796SGJ6rtLqfBK-sMnhOV4eZSqQIXIrxPyCJ8SA893p-29PFxfQfcbXW_6cYBFhDzyiilhJ6xQd6znN2eWOL4MPAxYeS2ZGnaZ7ijUN91MAyPnV0dQU7loVtS1jt2HlM5oMSsE2Zoz6FP31GvG6f7o_MWogEp0ZMOus50bVly3II8Rjjc4IGgswbw0h-RS0Ipo3f2QmXp4GfhRNUoTyqq-7oiCIDPUJcdg39lSIy9Fz7-ECNfbjEiH60V3GyftuiFGrayMoE7XeWaC9wQZo3fLHhI1aPgbXXsP-rqWLFf2km4zdG5Y5CYpUNb_Z11VOU6aaFCdRtoC6e7VcxHxLwCBT22wluNpbfFtEQSYDQE1JlegijvFmnRHTM88n-zp7sWhuCWVX6oE0ULdy51SR4iOqpYOA4B1ZymmYrQz1kBxSA_52lnTBlU9gfWkUiFX8GLSh7wQ8a4dVMYoJj6t1VCJt9-d30jn4S3tXsim_3wpp71RE9SSazV35j8o7do" |
There was a problem hiding this comment.
Critical: Remove real JWT token from example file.
This example file contains what appears to be a real, valid JWT token. Example files are committed to version control and should only contain placeholder values like "your-bearer-token-here" or "<KAI_BEARER_TOKEN>". Real tokens risk exposure even after rotation if the repository history is public.
Proposed fix
-KAI_BEARER_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzIiwianRpIjoiYmE0Yzc4MzE4ODNjYTI0N2YzMTBkMTJhYzc3ZjE5ZTdjMTVkNjgxOTk2ODM0MDc0MGM3MzliYmRjNGQ3YTI5MzczYzMyNWM2NDFiZjgxYzciLCJpYXQiOjE3NTQ0NTkxMjYsIm5iZiI6MTc1NDQ1OTEyNiwiZXhwIjoxNzg1OTk1MTI2LCJzdWIiOiI1Iiwic2NvcGVzIjpbXX0.zPA0IDAN3NycMKa6DaOdRmkcFz1oUTX1dkxEp3MLBlhibTQI0L0WB9mY-pUlQW5vQj8ktOdo-rRvrjxiXaHFqLQM6ebONbqTg8V0AjBXwrkBjLZDCE4dop9iZyDXcG2b9XTLCgPgpOBbduW_Dy0-bIkJOOIgIzl9mEEUVQf3T6G_zA796SGJ6rtLqfBK-sMnhOV4eZSqQIXIrxPyCJ8SA893p-29PFxfQfcbXW_6cYBFhDzyiilhJ6xQd6znN2eWOL4MPAxYeS2ZGnaZ7ijUN91MAyPnV0dQU7loVtS1jt2HlM5oMSsE2Zoz6FP31GvG6f7o_MWogEp0ZMOus50bVly3II8Rjjc4IGgswbw0h-RS0Ipo3f2QmXp4GfhRNUoTyqq-7oiCIDPUJcdg39lSIy9Fz7-ECNfbjEiH60V3GyftuiFGrayMoE7XeWaC9wQZo3fLHhI1aPgbXXsP-rqWLFf2km4zdG5Y5CYpUNb_Z11VOU6aaFCdRtoC6e7VcxHxLwCBT22wluNpbfFtEQSYDQE1JlegijvFmnRHTM88n-zp7sWhuCWVX6oE0ULdy51SR4iOqpYOA4B1ZymmYrQz1kBxSA_52lnTBlU9gfWkUiFX8GLSh7wQ8a4dVMYoJj6t1VCJt9-d30jn4S3tXsim_3wpp71RE9SSazV35j8o7do"
+KAI_BEARER_TOKEN="<your-kai-bearer-token>"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| KAI_BEARER_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzIiwianRpIjoiYmE0Yzc4MzE4ODNjYTI0N2YzMTBkMTJhYzc3ZjE5ZTdjMTVkNjgxOTk2ODM0MDc0MGM3MzliYmRjNGQ3YTI5MzczYzMyNWM2NDFiZjgxYzciLCJpYXQiOjE3NTQ0NTkxMjYsIm5iZiI6MTc1NDQ1OTEyNiwiZXhwIjoxNzg1OTk1MTI2LCJzdWIiOiI1Iiwic2NvcGVzIjpbXX0.zPA0IDAN3NycMKa6DaOdRmkcFz1oUTX1dkxEp3MLBlhibTQI0L0WB9mY-pUlQW5vQj8ktOdo-rRvrjxiXaHFqLQM6ebONbqTg8V0AjBXwrkBjLZDCE4dop9iZyDXcG2b9XTLCgPgpOBbduW_Dy0-bIkJOOIgIzl9mEEUVQf3T6G_zA796SGJ6rtLqfBK-sMnhOV4eZSqQIXIrxPyCJ8SA893p-29PFxfQfcbXW_6cYBFhDzyiilhJ6xQd6znN2eWOL4MPAxYeS2ZGnaZ7ijUN91MAyPnV0dQU7loVtS1jt2HlM5oMSsE2Zoz6FP31GvG6f7o_MWogEp0ZMOus50bVly3II8Rjjc4IGgswbw0h-RS0Ipo3f2QmXp4GfhRNUoTyqq-7oiCIDPUJcdg39lSIy9Fz7-ECNfbjEiH60V3GyftuiFGrayMoE7XeWaC9wQZo3fLHhI1aPgbXXsP-rqWLFf2km4zdG5Y5CYpUNb_Z11VOU6aaFCdRtoC6e7VcxHxLwCBT22wluNpbfFtEQSYDQE1JlegijvFmnRHTM88n-zp7sWhuCWVX6oE0ULdy51SR4iOqpYOA4B1ZymmYrQz1kBxSA_52lnTBlU9gfWkUiFX8GLSh7wQ8a4dVMYoJj6t1VCJt9-d30jn4S3tXsim_3wpp71RE9SSazV35j8o7do" | |
| KAI_BEARER_TOKEN="<your-kai-bearer-token>" |
🤖 Prompt for AI Agents
In @.dev.example.vars at line 10, Replace the real JWT value assigned to
KAI_BEARER_TOKEN in the .dev.example.vars file with a clear placeholder (e.g.,
"your-bearer-token-here" or "<KAI_BEARER_TOKEN>") so the example contains no
secrets; update the KAI_BEARER_TOKEN entry only (preserve surrounding
formatting) and add a brief comment if desired indicating it is a placeholder.
After changing the example, ensure any real token shown here is revoked/rotated
in the credential store and confirm the repo history is purged or rotate
credentials if the token was committed publicly.
| const KAI_BEARER_TOKEN = process.env.KAI_BEARER_TOKEN?.trim() | ||
|
|
||
| export const KAI_HEADERS = { | ||
| "User-Agent": | ||
| "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:132.0) Gecko/20100101 Firefox/132.0", | ||
| Accept: "application/json, text/javascript, */*; q=0.01", | ||
| "Accept-Language": "en-US,en;q=0.5", | ||
| Authorization: | ||
| "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzIiwianRpIjoiMDYzNWIyOGMzYzg3YTY3ZTRjYWE4YTI0MjYxZGYwYzIxNjYzODA4NWM2NWU4ZjhiYzQ4OGNlM2JiZThmYWNmODU4YzY0YmI0MjgyM2EwOTUiLCJpYXQiOjE3MjI2MTc1MTQsIm5iZiI6MTcyMjYxNzUxNCwiZXhwIjoxNzU0MTUzNTE0LCJzdWIiOiI1Iiwic2NvcGVzIjpbXX0.Jz_sedcMtaZJ4dj0eWVc4_pr_wUQ3s1-UgpopFGhEmJt_iGzj6BdnOEEhcDDdIz-gydQL5ek0S_36v5h6P_X3OQyII3JmHp1SEDJMwrcy4FCY63-jGnhPBb4sprqUFruDRFSEIs1cNQ-3rv3qRDzJtGYc_bAkl2MfgZj85bvt2DDwBWPraZuCCkwz2fJvox-6qz6P7iK9YdQq8AjJfuNdl7t_1hMHixmtDG0KooVnfBV7PoChxvcWvs8FOmtYRdqD7RSEIoOXym2kcwqK-rmbWf9VuPQCN5gjLPimL4t2TbifBg5RWNIAAuHLcYzea48i3okbhkqGGlYTk3iVMU6Hf_Jruns1WJr3A961bd4rny62lNXyGPgNLRJJKedCs5lmtUTr4gZRec4Pz_MqDzlEYC3QzRAOZv0Ergp8-W1Vrv5gYyYNr-YQNdZ01mc7JH72N2dpU9G00K5kYxlcXDNVh8520-R-MrxYbmiFGVlNF2BzEH8qq6Ko9m0jT0NiKEOjetwegrbNdNq_oN4KmHvw2sHkGWY06rUeciYJMhBF1JZuRjj3JTwBUBVXcYZMFtwUAoikVByzKuaZZeTo1AtCiSjejSHNdpLxyKk_SFUzog5MOkUN1ktAhFnBFoz6SlWAJBJIS-lHYsdFLSug2YNiaNllkOUsDbYkiDtmPc9XWc", | ||
| Authorization: `Bearer ${KAI_BEARER_TOKEN}`, |
There was a problem hiding this comment.
Handle missing KAI_BEARER_TOKEN environment variable.
If KAI_BEARER_TOKEN is not set, the Authorization header will be "Bearer undefined", causing silent authentication failures. Consider adding validation or a fallback.
Proposed fix: fail fast if token is missing
-const KAI_BEARER_TOKEN = process.env.KAI_BEARER_TOKEN?.trim()
+const KAI_BEARER_TOKEN = process.env.KAI_BEARER_TOKEN?.trim()
+
+if (!KAI_BEARER_TOKEN) {
+ throw new Error("KAI_BEARER_TOKEN environment variable is required")
+}
export const KAI_HEADERS = {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const KAI_BEARER_TOKEN = process.env.KAI_BEARER_TOKEN?.trim() | |
| export const KAI_HEADERS = { | |
| "User-Agent": | |
| "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:132.0) Gecko/20100101 Firefox/132.0", | |
| Accept: "application/json, text/javascript, */*; q=0.01", | |
| "Accept-Language": "en-US,en;q=0.5", | |
| Authorization: | |
| "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzIiwianRpIjoiMDYzNWIyOGMzYzg3YTY3ZTRjYWE4YTI0MjYxZGYwYzIxNjYzODA4NWM2NWU4ZjhiYzQ4OGNlM2JiZThmYWNmODU4YzY0YmI0MjgyM2EwOTUiLCJpYXQiOjE3MjI2MTc1MTQsIm5iZiI6MTcyMjYxNzUxNCwiZXhwIjoxNzU0MTUzNTE0LCJzdWIiOiI1Iiwic2NvcGVzIjpbXX0.Jz_sedcMtaZJ4dj0eWVc4_pr_wUQ3s1-UgpopFGhEmJt_iGzj6BdnOEEhcDDdIz-gydQL5ek0S_36v5h6P_X3OQyII3JmHp1SEDJMwrcy4FCY63-jGnhPBb4sprqUFruDRFSEIs1cNQ-3rv3qRDzJtGYc_bAkl2MfgZj85bvt2DDwBWPraZuCCkwz2fJvox-6qz6P7iK9YdQq8AjJfuNdl7t_1hMHixmtDG0KooVnfBV7PoChxvcWvs8FOmtYRdqD7RSEIoOXym2kcwqK-rmbWf9VuPQCN5gjLPimL4t2TbifBg5RWNIAAuHLcYzea48i3okbhkqGGlYTk3iVMU6Hf_Jruns1WJr3A961bd4rny62lNXyGPgNLRJJKedCs5lmtUTr4gZRec4Pz_MqDzlEYC3QzRAOZv0Ergp8-W1Vrv5gYyYNr-YQNdZ01mc7JH72N2dpU9G00K5kYxlcXDNVh8520-R-MrxYbmiFGVlNF2BzEH8qq6Ko9m0jT0NiKEOjetwegrbNdNq_oN4KmHvw2sHkGWY06rUeciYJMhBF1JZuRjj3JTwBUBVXcYZMFtwUAoikVByzKuaZZeTo1AtCiSjejSHNdpLxyKk_SFUzog5MOkUN1ktAhFnBFoz6SlWAJBJIS-lHYsdFLSug2YNiaNllkOUsDbYkiDtmPc9XWc", | |
| Authorization: `Bearer ${KAI_BEARER_TOKEN}`, | |
| const KAI_BEARER_TOKEN = process.env.KAI_BEARER_TOKEN?.trim() | |
| if (!KAI_BEARER_TOKEN) { | |
| throw new Error("KAI_BEARER_TOKEN environment variable is required") | |
| } | |
| export const KAI_HEADERS = { | |
| "User-Agent": | |
| "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:132.0) Gecko/20100101 Firefox/132.0", | |
| Accept: "application/json, text/javascript, */*; q=0.01", | |
| "Accept-Language": "en-US,en;q=0.5", | |
| Authorization: `Bearer ${KAI_BEARER_TOKEN}`, |
🤖 Prompt for AI Agents
In `@src/sync/headers.ts` around lines 1 - 8, The module currently builds
KAI_HEADERS using KAI_BEARER_TOKEN which can be "undefined"; update the module
to validate process.env.KAI_BEARER_TOKEN at import time and fail fast if missing
(e.g., throw a clear Error like "Missing KAI_BEARER_TOKEN env var") before
exporting KAI_HEADERS so Authorization is never "Bearer undefined"; reference
the KAI_BEARER_TOKEN constant and the KAI_HEADERS export when adding this check.
| const normalizeStationKey = (name: string) => { | ||
| let normalized = name | ||
| .toUpperCase() | ||
| .replace(/VIA\\s*MRI/g, "") | ||
| .replace(/VIAMRI/g, "") | ||
| .replace(/\\s+/g, "") | ||
| .replace(/[^A-Z0-9]/g, "") | ||
|
|
||
| if (normalized === "TANJUNGPRIUK") { | ||
| normalized = "TANJUNGPRIOK" | ||
| } | ||
|
|
||
| return normalized | ||
| } |
There was a problem hiding this comment.
Regex escape sequences are incorrect.
In JavaScript regex literals, \\s matches a literal backslash followed by 's', not whitespace. Use single backslashes for regex metacharacters.
Proposed fix
const normalizeStationKey = (name: string) => {
let normalized = name
.toUpperCase()
- .replace(/VIA\\s*MRI/g, "")
- .replace(/VIAMRI/g, "")
- .replace(/\\s+/g, "")
- .replace(/[^A-Z0-9]/g, "")
+ .replace(/VIA\s*MRI/g, "")
+ .replace(/VIAMRI/g, "")
+ .replace(/\s+/g, "")
+ .replace(/[^A-Z0-9]/g, "")
if (normalized === "TANJUNGPRIUK") {
normalized = "TANJUNGPRIOK"
}
return normalized
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const normalizeStationKey = (name: string) => { | |
| let normalized = name | |
| .toUpperCase() | |
| .replace(/VIA\\s*MRI/g, "") | |
| .replace(/VIAMRI/g, "") | |
| .replace(/\\s+/g, "") | |
| .replace(/[^A-Z0-9]/g, "") | |
| if (normalized === "TANJUNGPRIUK") { | |
| normalized = "TANJUNGPRIOK" | |
| } | |
| return normalized | |
| } | |
| const normalizeStationKey = (name: string) => { | |
| let normalized = name | |
| .toUpperCase() | |
| .replace(/VIA\s*MRI/g, "") | |
| .replace(/VIAMRI/g, "") | |
| .replace(/\s+/g, "") | |
| .replace(/[^A-Z0-9]/g, "") | |
| if (normalized === "TANJUNGPRIUK") { | |
| normalized = "TANJUNGPRIOK" | |
| } | |
| return normalized | |
| } |
🤖 Prompt for AI Agents
In `@src/sync/schedule.ts` around lines 51 - 64, The regexes in
normalizeStationKey use double-escaped sequences (e.g. /VIA\\s*MRI/g and
/\\s+/g) which match a backslash + 's' instead of whitespace; update those regex
literals to use single backslashes (e.g. /VIA\s*MRI/g and /\s+/g) so \s behaves
as the whitespace metacharacter, leaving other patterns like /VIAMRI/g and
/[^A-Z0-9]/g unchanged.
Summary by CodeRabbit
Documentation
Configuration
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.