feat: Add context-aware-blocker kit#239
Conversation
- Implemented true black and Lamatic Red design system in tailwind.config.js - Refactored dashboard.html into a full-screen premium web app layout - Built commitCard.js generator with precise 3-column flexbox grid alignment - Scaled Material Symbols icons for high-contrast mobile feel
|
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:
WalkthroughChangesA context-aware blocker kit is added with a Lamatic classification flow, authenticated Next.js evaluation endpoints, a persisted blocking-rule dashboard, and a Chrome MV3 extension that scrapes page context, evaluates active rules, and displays blocking or strict-lock overlays. Context-Aware Blocker
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Biome (2.5.3)kits/context-aware-blocker/apps/src/app/globals.cssFile contains syntax errors that prevent linting: Line 22: Tailwind-specific syntax is disabled. 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 |
… cache bouncer - Engineered a 4-step evaluation waterfall (Time -> Static -> Cache -> AI) to protect API quotas. - Implemented an in-memory Promise Cache Bouncer (5-min TTL) to intercept redundant API calls during the 5-second polling loop. - Added a safeSendMessage wrapper and a contextAlive kill-switch to prevent 'context invalidated' crashes when reloading the extension. - Built a Next.js terminal bridge in route.ts for verbose, real-time tracking of engine decisions. - Added physical DOM overlay injection with auto-close countdown and programmatic tab removal.
- Implemented /api/evaluate endpoint to securely proxy Lamatic SDK calls - Added rule-aware in-memory caching (rulesHash) in extension background - Integrated AI natural language rules extraction into AI payload - Added robust fail-open error handling for API outages - Whitelisted localhost dashboard to prevent redundant AI blocks - Upgraded terminal logging for full visibility of cache states, timings, and payloads
:robot_face: AgentKit Structural ValidationNew Contributions Detected
Check Results
|
There was a problem hiding this comment.
Actionable comments posted: 38
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@kits/context-aware-blocker/agent.md`:
- Line 56: Update the “Privacy First” disclosure in agent.md to accurately list
that the extension transmits the URL, page title, H1 text, meta description,
static rules, and AI rules, and explicitly state that the API logs these fields;
remove the inaccurate claim that only the title and URL are sent or that no data
is transmitted.
In `@kits/context-aware-blocker/apps/extension/background.js`:
- Around line 43-70: Update isCommitCurrentlyActive so overnight time windows
evaluate the previous calendar day for times after midnight, allowing Monday
10:00 PM–2:00 AM to remain active early Tuesday when Monday is selected.
Preserve same-day checks for standard windows and the pre-midnight portion of
overnight windows, including correct Sunday-to-Saturday day wrapping.
- Around line 322-367: Update the evaluation flow around the fetch and decision
enforcement to invalidate superseded requests per tab when navigation or active
rules change. Track a per-tab AbortController or generation token, apply a
request timeout, and before caching the result or sending
BLOCK_PAGE/HIDE_AI_EVALUATING verify that the evaluation is still current and
the tab URL and rulesHash match; ignore aborted or stale responses.
- Around line 336-350: The response handling around the AI evaluation cache must
not cache failure responses as PASS. Validate response.ok after the fetch,
reject any result containing an error before deriving or caching decision, and
only call aiEvaluationCache.set for successful classifications; preserve normal
PASS/other decision caching when the response is valid.
- Around line 115-118: Replace the substring checks in the payload URL handling
with URL parsing and exact origin or hostname-and-port validation for the local
dashboard. Only instantly allow requests whose actual host and port are
localhost:3000 or 127.0.0.1:3000; query parameters, paths, and other URL content
must not qualify.
In `@kits/context-aware-blocker/apps/extension/content.js`:
- Around line 77-89: Remove the five-second setInterval polling block around
contextAlive and scrapePageContext. Retain schedule-boundary handling through
chrome.alarms and add or reuse a debounced MutationObserver to trigger
scrapePageContext only for relevant DOM changes, while preserving the overlay
and contextAlive safeguards.
- Around line 145-146: Replace the innerHTML assignment in the subtitle
construction with safe DOM node creation: render the untrusted commitName via
textContent, and create separate strong, br, and countdown elements for the
intended formatting and message. Preserve the existing text and countdown
styling while ensuring persisted commitName content cannot inject markup or
event handlers.
- Around line 291-303: Update syncStorage so it always sends both
synchronization messages, including when localStorage keys are absent. In the
cab_commits flow, use an empty array when the key is missing; in the
lama_lock_settings flow, send the established cleared lock-state value when
absent, while preserving parsed values when present.
In `@kits/context-aware-blocker/apps/extension/strict.html`:
- Line 2: Update the root html element in strict.html to declare the lock page’s
language using the appropriate lang attribute.
In `@kits/context-aware-blocker/apps/package.json`:
- Line 12: Replace the "lamatic" dependency’s "latest" range with the specific
reviewed Lamatic SDK version approved for this project, using an exact pinned
version to keep clean installs reproducible.
In `@kits/context-aware-blocker/apps/src/app/api/evaluate/route.ts`:
- Around line 37-40: Secure both public POST handlers: in
kits/context-aware-blocker/apps/src/app/api/evaluate/route.ts lines 37-40,
update POST to authenticate the extension, validate a strict schema with bounded
field lengths, and enforce rate limiting before triggering evaluations; in
kits/context-aware-blocker/apps/src/app/api/log/route.ts lines 14-16, apply the
same authentication and rate-limiting protections plus strict schema and
payload-size limits before accepting terminal logs.
- Around line 42-48: Remove or development-gate the raw page-context console
logs around evaluate route lines 42-48, including URL, title, headings,
metadata, and rules. In evaluate route lines 97-99, stop logging the complete
Lamatic response and retain only safe, non-sensitive diagnostics. In log route
lines 19-29, restrict the logging bridge to development mode and sanitize every
logged field; update the relevant evaluate route logging and log route handler
symbols accordingly.
- Around line 56-60: The configuration logging around the API key must not
expose any portion of the secret. Update the LAMATIC_API_KEY log in the route’s
configuration-check block to report only whether apiKey is set, while preserving
the existing missing/unconfigured status behavior.
- Around line 88-95: Bound the Lamatic flow execution in the route containing
the executeFlow call by exporting the framework’s maxDuration setting and
wrapping the await in a server-side timeout that returns the established
fallback when the limit is reached. Do not claim or implement request
cancellation, since the SDK cannot abort the underlying request; preserve the
normal executeFlow result when it completes in time.
In `@kits/context-aware-blocker/apps/src/app/globals.css`:
- Around line 3-13: Centralize the kit’s visual tokens in globals.css by
defining shared surface, muted, accent, border, and foreground CSS variables and
exposing them through the existing theme. Update AIPopupModal.tsx,
ActiveTimePane.tsx, BlockedContentPane.tsx, CommitSettingsModal.tsx, and
DaySelector.tsx to replace their hardcoded modal, editor, tab, overlay, control,
and day-state colors with those shared variables; apply the changes at the
listed ranges in each file and preserve the existing visual states.
In `@kits/context-aware-blocker/apps/src/app/layout.tsx`:
- Around line 40-42: Remove the Material Symbols stylesheet from
kits/context-aware-blocker/apps/src/app/layout.tsx at lines 40-42, and replace
the indicated icons with lucide-react components: use close and sparkle in
AIPopupModal.tsx lines 33-40; add, clock, and close in ActiveTimePane.tsx lines
139-185; add, globe, check, sparkle, and close in BlockedContentPane.tsx lines
191-263; and chevron and close in CommitSettingsModal.tsx lines 92-114. Preserve
the existing icon actions, sizing, and styling while using Lucide imports.
In `@kits/context-aware-blocker/apps/src/app/page.tsx`:
- Around line 152-189: Define semantic Lamatic palette CSS variables in the app
styling and replace raw color literals across page.tsx ranges 152-189 and
249-306, CommitCard.tsx 44-115, ConfirmationModal.tsx 64-103, and
UpcomingBlocksCard.tsx 12-22. Use the variables for surfaces, text, borders,
icons, dividers, focus states, and primary actions; update ConfirmationModal’s
API to accept semantic variants rather than raw color props.
- Around line 61-84: Update saveLockSettings to validate newTimestamp before
persisting: require it to be finite and strictly later than Date.now(), show an
appropriate alert and return for invalid or expired values, and keep the modal
open. Preserve the existing strict-mode check that prevents reducing an already
saved deadline.
- Around line 249-306: The lock form in page.tsx should use react-hook-form with
a zod schema instead of manually managed date/time state, and validate the
requested lock date/time itself before submission while preserving the existing
form behavior. Add react-hook-form, zod, and `@hookform/resolvers` to
kits/context-aware-blocker/apps/package.json dependencies.
In `@kits/context-aware-blocker/apps/src/components/features/ActiveTimePane.tsx`:
- Around line 33-46: Update the activeDays initialization and synchronization in
ActiveTimePane to preserve an intentionally empty array; use the commit’s
activeDays whenever it is defined, and only fall back to the Monday–Friday
defaults when the value is absent. Remove the length-based fallback from the
activeDays state and the commits synchronization effect.
- Around line 143-184: Update all icon classes using the leading !text-[...]
utility in ActiveTimePane.tsx (lines 143-184) and BlockedContentPane.tsx (lines
192-263) to the trailing text-[...]! Tailwind v4 form; no other class or
behavior changes are needed.
In `@kits/context-aware-blocker/apps/src/components/features/AIPopupModal.tsx`:
- Around line 7-11: Implement the AI configuration UI in AIPopupModal instead of
leaving it as placeholder content. Add controls for overriding the default
system prompt and configuring the LLM strictness threshold, connect them to the
modal’s existing state and save/cancel behavior, and remove the “Popup holder
active” placeholder and related TODO.
- Around line 21-45: Implement accessible dialog behavior in AIPopupModal.tsx
lines 21-45 and CommitSettingsModal.tsx lines 82-114: add dialog semantics with
role="dialog", aria-modal, and an accessible label, move initial focus into each
modal, trap focus while open, close on Escape, and restore focus to the opener
when closed. Apply the same behavior to both modal components, using their
existing onClose and opener context.
In `@kits/context-aware-blocker/apps/src/components/features/CommitCard.tsx`:
- Around line 55-113: Standardize all affected icons on lucide-react: update
CommitCard.tsx (lines 55-113) to replace Material Symbols strings with Lucide
components while preserving handlers and styling, update page.tsx (lines
173-178) to use a Lucide lock icon, update UpcomingBlocksCard.tsx (lines 13-22)
to use the appropriate Lucide security icon, and add lucide-react to
apps/package.json (lines 11-27).
In
`@kits/context-aware-blocker/apps/src/components/features/CommitSettingsModal.tsx`:
- Around line 117-147: Update CommitSettingsModal to own a shared draft
containing both time and blocked-content edits, and pass that draft plus setters
or update callbacks to ActiveTimePane and BlockedContentPane. Replace each
pane’s independent persistence-and-close behavior with a modal-level Save
handler that persists the combined draft once, then invokes onClose; ensure
saving either pane preserves edits made in the other.
- Around line 36-44: Update the modal-opening effect in CommitSettingsModal to
reset the title when commit is absent, rather than only setting it when commit
exists. Preserve loading commit.title for existing commits, and use the
appropriate empty-title value for new commits so stale state cannot be
submitted.
In `@kits/context-aware-blocker/apps/src/components/ui/Button.tsx`:
- Around line 1-3: Replace the placeholder Button component with the shared
shadcn/ui Button contract: forward its ref, accept and pass through native
button props and handlers, support the expected variants, and preserve the
standard button behavior and styling API. Update the Button symbol itself rather
than introducing a separate component.
In `@kits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsx`:
- Around line 63-105: The clickable ConfirmationModal markup in
kits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsx lines
63-105 must be migrated to the shadcn/ui Dialog component, preserving title,
message, children, cancel, and confirm behavior while providing focus trapping,
Escape handling, dialog semantics, and focus restoration. In
kits/context-aware-blocker/apps/src/components/features/CommitCard.tsx lines
47-115, replace the clickable card and action span elements with
keyboard-operable buttons and preserve their actions. In
kits/context-aware-blocker/apps/src/app/page.tsx lines 173-178, replace the
clickable lock span with a labeled button that preserves the lock action.
In `@kits/context-aware-blocker/apps/src/components/ui/DaySelector.tsx`:
- Around line 45-69: Update the Repeat button in DaySelector to include the
disabled attribute, and enhance each day button generated by DAYS.map with a
full aria-label identifying the day and aria-pressed reflecting isSelected.
Preserve the existing selection and styling behavior.
In `@kits/context-aware-blocker/apps/src/components/ui/Modal.tsx`:
- Around line 1-3: Replace the placeholder Modal component with the shadcn/ui
Dialog-based implementation, using the project’s established Dialog primitives
and preserving the exported Modal API where applicable; otherwise remove Modal
until a usable implementation is available.
In `@kits/context-aware-blocker/apps/src/components/ui/UpcomingBlocksCard.tsx`:
- Around line 4-6: Replace the static mock schedule in UpcomingBlocksCard with
data from the Zustand store, calculating the nearest upcoming time window across
all active commits and displaying its actual title and timing. Wire the card’s
action button to the appropriate store behavior, or render it as non-interactive
content if no action exists; remove the fabricated fixed values.
In `@kits/context-aware-blocker/apps/src/hooks/useCommitStore.ts`:
- Around line 90-101: Update loadCommits to validate the persisted value is a
BlockCommit[] with all required BlockCommit fields before hydrating the store.
Use defaultCommits when saved data is null or malformed, set isLoaded as before,
and initialize storage with the fallback whenever validation fails.
In `@kits/context-aware-blocker/apps/src/lib/storage.ts`:
- Around line 31-35: Make Chrome storage failures observable and reconcile
optimistic state: in kits/context-aware-blocker/apps/src/lib/storage.ts lines
31-35, update the retrieval callback to reject when chrome.runtime.lastError is
present; in lines 62-66, perform the same lastError check and reject failed
writes; in kits/context-aware-blocker/apps/src/hooks/useCommitStore.ts lines
104-126, catch write failures for save, add, and delete actions and roll back
the optimistic state or reload the persisted state safely.
In `@kits/context-aware-blocker/apps/src/lib/utils.ts`:
- Around line 22-42: Replace the client-controlled localStorage and Date.now()
authority in isStrictLockActive with an extension/server-owned lock state that
is cryptographically signed and validated using a trusted timestamp. Ensure
missing, modified, expired, or invalid state keeps strict lock enforcement
active rather than returning false, while preserving the SSR guard and boolean
API.
In `@kits/context-aware-blocker/prompts/app-blocker_llmnode-1_system_0.md`:
- Line 1: Update the system prompt to explicitly label the URL, title, heading,
and description values as untrusted webpage evidence, delimit them from the
governing instructions, and state that any directives embedded in those fields
must never be followed. Preserve the existing BLOCK/PASS-only response
requirements and active-rule evaluation behavior.
In `@kits/context-aware-blocker/README.md`:
- Around line 41-42: Align the documented failure policy with the current
fail-open runtime behavior: update the fail-closed section in
kits/context-aware-blocker/README.md at lines 41-42 to state that API or AI
evaluation failures return or retain PASS, and update
kits/context-aware-blocker/agent.md at line 55 with the same policy and
rationale. No runtime change is required.
- Line 66: Update the README setup instructions to replace FLOW_ID with the
exact required environment variable CONTENT_CLASSIFICATION_FLOW_ID, including
wherever the variable is referenced in the configuration steps.
- Line 132: Update the Next.js version from 16 to 15 in both the frontend
dependency declaration in apps/package.json and the Tech Stack table in the
README, keeping the two references aligned with the kit toolchain.
🪄 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: b155de25-6ef4-4054-aaca-e5d016a89a1f
⛔ Files ignored due to path filters (7)
kits/context-aware-blocker/apps/package-lock.jsonis excluded by!**/package-lock.jsonkits/context-aware-blocker/apps/public/file.svgis excluded by!**/*.svgkits/context-aware-blocker/apps/public/globe.svgis excluded by!**/*.svgkits/context-aware-blocker/apps/public/next.svgis excluded by!**/*.svgkits/context-aware-blocker/apps/public/vercel.svgis excluded by!**/*.svgkits/context-aware-blocker/apps/public/window.svgis excluded by!**/*.svgkits/context-aware-blocker/apps/src/app/favicon.icois excluded by!**/*.ico
📒 Files selected for processing (42)
kits/context-aware-blocker/.env.examplekits/context-aware-blocker/.gitignorekits/context-aware-blocker/README.mdkits/context-aware-blocker/agent.mdkits/context-aware-blocker/apps/.env.examplekits/context-aware-blocker/apps/.gitignorekits/context-aware-blocker/apps/AGENTS.mdkits/context-aware-blocker/apps/CLAUDE.mdkits/context-aware-blocker/apps/README.mdkits/context-aware-blocker/apps/eslint.config.mjskits/context-aware-blocker/apps/extension/background.jskits/context-aware-blocker/apps/extension/content.jskits/context-aware-blocker/apps/extension/manifest.jsonkits/context-aware-blocker/apps/extension/strict.htmlkits/context-aware-blocker/apps/next.config.tskits/context-aware-blocker/apps/package.jsonkits/context-aware-blocker/apps/postcss.config.mjskits/context-aware-blocker/apps/src/app/api/evaluate/route.tskits/context-aware-blocker/apps/src/app/api/log/route.tskits/context-aware-blocker/apps/src/app/globals.csskits/context-aware-blocker/apps/src/app/layout.tsxkits/context-aware-blocker/apps/src/app/page.tsxkits/context-aware-blocker/apps/src/components/features/AIPopupModal.tsxkits/context-aware-blocker/apps/src/components/features/ActiveTimePane.tsxkits/context-aware-blocker/apps/src/components/features/BlockedContentPane.tsxkits/context-aware-blocker/apps/src/components/features/CommitCard.tsxkits/context-aware-blocker/apps/src/components/features/CommitSettingsModal.tsxkits/context-aware-blocker/apps/src/components/ui/Button.tsxkits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsxkits/context-aware-blocker/apps/src/components/ui/DaySelector.tsxkits/context-aware-blocker/apps/src/components/ui/Modal.tsxkits/context-aware-blocker/apps/src/components/ui/UpcomingBlocksCard.tsxkits/context-aware-blocker/apps/src/hooks/useCommitStore.tskits/context-aware-blocker/apps/src/lib/storage.tskits/context-aware-blocker/apps/src/lib/utils.tskits/context-aware-blocker/apps/src/types/store.tskits/context-aware-blocker/apps/tsconfig.jsonkits/context-aware-blocker/constitutions/default.mdkits/context-aware-blocker/flows/content-classification.tskits/context-aware-blocker/lamatic.config.tskits/context-aware-blocker/model-configs/app-blocker_llmnode-1_generative-model-name.tskits/context-aware-blocker/prompts/app-blocker_llmnode-1_system_0.md
| export function isStrictLockActive(): boolean { | ||
| // NOTE: Next.js SSR guard. localStorage is not available on the server. | ||
| if (typeof window === 'undefined') return false; | ||
|
|
||
| const saved = localStorage.getItem("lama_lock_settings"); | ||
| if (saved) { | ||
| try { | ||
| const parsed = JSON.parse(saved); | ||
| if (parsed.date && parsed.time) { | ||
| const lockTimestamp = new Date(`${parsed.date}T${parsed.time}`).getTime(); | ||
| // FIXME: This relies on the client's local system clock. A dedicated user could | ||
| // bypass this by rolling back their OS clock. Future improvement should use an NTP server. | ||
| if (Date.now() < lockTimestamp) { | ||
| return true; | ||
| } | ||
| } | ||
| } catch (e) { | ||
| // Fail silently if JSON parsing fails to prevent UI crashing. | ||
| } | ||
| } | ||
| return false; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
Mission compromised: strict-lock authority is user-controlled.
Deleting or editing lama_lock_settings makes this return false; changing the OS clock also bypasses it. Enforce the lock in an extension/server-owned authority, ideally with signed state and a trusted timestamp—not NTP alone.
Would you like me to draft that design or open an issue for the FIXME?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker/apps/src/lib/utils.ts` around lines 22 - 42,
Replace the client-controlled localStorage and Date.now() authority in
isStrictLockActive with an extension/server-owned lock state that is
cryptographically signed and validated using a trusted timestamp. Ensure
missing, modified, expired, or invalid state keeps strict lock enforcement
active rather than returning false, while preserving the SSR guard and boolean
API.
- Fix overnight time window evaluation (check previous day after midnight) - Replace localhost substring bypass with exact URL origin matching - Add AbortController + eval tokens to prevent stale AI responses - Validate response.ok before caching AI decisions - Replace setInterval DOM polling with debounced MutationObserver - Fix innerHTML XSS vector with safe DOM node construction - Sync empty storage state (send empty array when key absent) - Add maxDuration + Promise.race timeout to evaluate route - Redact PII and API key from production logs - Add schema validation to evaluate and log endpoints - Validate lock timestamp is finite and in the future - Add storage write rollback on failure in Zustand store - Handle chrome.runtime.lastError in storage adapter - Add untrusted input warning to LLM system prompt - Update privacy disclosure and fail-open policy in docs - Pin Next.js to 15.0.0, swap Geist fonts for Inter - Add lang=en to strict.html
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kits/context-aware-blocker/apps/src/app/page.tsx (1)
178-183: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winMission accessibility: provide keyboard access.
Agent, this
spanacts as a button but lacks keyboard interactivity and semantic meaning. Users relying on keyboard navigation cannot activate the lock modal. Your mission is to convert this into a semantic<button>element.🛠️ Proposed semantic fix
- <span - className="material-symbols-outlined text-gray-400 text-[20px] cursor-pointer hover:text-white transition-colors" - onClick={() => setIsLockModalOpen(true)} - > - lock - </span> + <button + className="text-gray-400 cursor-pointer hover:text-white transition-colors" + onClick={() => setIsLockModalOpen(true)} + aria-label="Open Lock Settings" + > + <Lock className="w-5 h-5" /> + </button>(Note: assumes
Lockis imported fromlucide-reactas requested in the directive below)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/context-aware-blocker/apps/src/app/page.tsx` around lines 178 - 183, Replace the lock span in the page component with a semantic button that preserves the existing styling and setIsLockModalOpen(true) click behavior, allowing keyboard users to activate the lock modal; use the requested Lock icon if the surrounding implementation already imports it.
♻️ Duplicate comments (2)
kits/context-aware-blocker/apps/src/app/page.tsx (2)
178-183: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winMission directive: swap the compromised assets.
Agent, you are still relying on the Google Material Symbols font for the lock icon here. As per coding guidelines, kit Next.js apps must use
lucide-reactfor all icons.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/context-aware-blocker/apps/src/app/page.tsx` around lines 178 - 183, Replace the Google Material Symbols lock span in the page component with the appropriate lucide-react lock icon, importing it from lucide-react. Preserve the existing styling, click behavior that opens the lock modal, and visual size.Source: Coding guidelines
161-217: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftMission architecture: standardize the camouflage.
Agent, the UI still relies heavily on raw hex values (e.g.,
#0a0a0a,#151515,#e83a3a), leaving our styling vulnerable to inconsistencies and preventing centralized theme updates. As per coding guidelines, kit Next.js apps must use CSS variables for styling.
kits/context-aware-blocker/apps/src/app/page.tsx#L161-L217: extract these background and text hex literals into semantic CSS variables.kits/context-aware-blocker/apps/src/app/page.tsx#L243-L315: extract the modal's input background, text, and border hex literals into semantic CSS variables.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/context-aware-blocker/apps/src/app/page.tsx` around lines 161 - 217, Replace raw hex colors in the main page UI around kits/context-aware-blocker/apps/src/app/page.tsx lines 161-217 with semantic CSS variables, including background, text, and control colors; also update modal input background, text, and border colors around lines 243-315 to use semantic variables. Define or reuse the variables through the app’s existing styling system rather than introducing duplicated literals, preserving the current appearance.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@kits/context-aware-blocker/apps/extension/background.js`:
- Around line 61-64: Update the active-day checks in isCommitCurrentlyActive to
safely handle commits whose activeDays is undefined, matching the existing guard
behavior near the start of the function. Ensure both current-day and
previous-day checks return false rather than throwing when activeDays is absent,
while preserving normal includes behavior when the array exists.
In `@kits/context-aware-blocker/apps/extension/content.js`:
- Around line 305-310: Isolate the JSON parsing and synchronization for commits
and lock settings into separate error-handled blocks so corrupted `localCommits`
cannot prevent `SYNC_LOCK_SETTINGS` from being sent, and vice versa. Update the
surrounding synchronization flow in `content.js` and remove the outer try-catch
that currently wraps both operations.
In `@kits/context-aware-blocker/apps/src/app/api/evaluate/route.ts`:
- Around line 43-45: Protect both API routes with the project’s existing
extension authentication and rate-limiting mechanisms before processing
requests: add these checks at the start of the evaluate handler around the
payload validation and at the start of the log handler before accepting log
data. Update kits/context-aware-blocker/apps/src/app/api/evaluate/route.ts lines
43-45 and kits/context-aware-blocker/apps/src/app/api/log/route.ts lines 18-19;
reject unauthenticated or rate-limited requests without invoking evaluation or
persisting logs.
- Around line 96-106: Update the Promise.race in the route handler around
lamaticClient.executeFlow to retain the timeout handle and clear it whenever the
flow resolves or rejects, including timeout handling. Ensure the timer is always
cleaned up after the race settles without changing the existing 8-second timeout
behavior.
In `@kits/context-aware-blocker/apps/src/components/ui/UpcomingBlocksCard.tsx`:
- Around line 14-16: Replace the non-interactive button in UpcomingBlocksCard
with a semantically appropriate non-interactive element such as a div,
preserving its existing styling, layout, and activeCount text.
---
Outside diff comments:
In `@kits/context-aware-blocker/apps/src/app/page.tsx`:
- Around line 178-183: Replace the lock span in the page component with a
semantic button that preserves the existing styling and setIsLockModalOpen(true)
click behavior, allowing keyboard users to activate the lock modal; use the
requested Lock icon if the surrounding implementation already imports it.
---
Duplicate comments:
In `@kits/context-aware-blocker/apps/src/app/page.tsx`:
- Around line 178-183: Replace the Google Material Symbols lock span in the page
component with the appropriate lucide-react lock icon, importing it from
lucide-react. Preserve the existing styling, click behavior that opens the lock
modal, and visual size.
- Around line 161-217: Replace raw hex colors in the main page UI around
kits/context-aware-blocker/apps/src/app/page.tsx lines 161-217 with semantic CSS
variables, including background, text, and control colors; also update modal
input background, text, and border colors around lines 243-315 to use semantic
variables. Define or reuse the variables through the app’s existing styling
system rather than introducing duplicated literals, preserving the current
appearance.
🪄 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: 389b1fbf-1bef-4ea1-a6ee-dc51142fc23b
⛔ Files ignored due to path filters (1)
kits/context-aware-blocker/apps/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (16)
kits/context-aware-blocker/README.mdkits/context-aware-blocker/agent.mdkits/context-aware-blocker/apps/extension/background.jskits/context-aware-blocker/apps/extension/content.jskits/context-aware-blocker/apps/extension/strict.htmlkits/context-aware-blocker/apps/package.jsonkits/context-aware-blocker/apps/src/app/api/evaluate/route.tskits/context-aware-blocker/apps/src/app/api/log/route.tskits/context-aware-blocker/apps/src/app/globals.csskits/context-aware-blocker/apps/src/app/layout.tsxkits/context-aware-blocker/apps/src/app/page.tsxkits/context-aware-blocker/apps/src/components/ui/UpcomingBlocksCard.tsxkits/context-aware-blocker/apps/src/hooks/useCommitStore.tskits/context-aware-blocker/apps/src/lib/storage.tskits/context-aware-blocker/apps/tsconfig.jsonkits/context-aware-blocker/prompts/app-blocker_llmnode-1_system_0.md
…sync, timeout cleanup, semantic HTML, Lucide lock icon
|
Just a gentle ping , PR #239 (Context-Aware Blocker Kit) is ready for review.
Only left the 3 bigger architectural changes (react-hook-form, CSS variables, full API auth) intentionally to avoid scope creep, as mentioned earlier. Would really appreciate a human review whenever you have time. Thanks! |
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
Studio Runtime Validation (Phase 2)✅ Studio validation passed. The kit loaded successfully in Lamatic Studio. This PR is ready for final review and merge. |
|
@akshatvirmani @amanintech @d-pamneja Studio validation just passed ✅ and all CI checks are green. PR #239 (Context-Aware Blocker Kit) is ready for final review. If there are any changes needed, please let me know — I'm happy to fix them quickly. Otherwise, would appreciate if you can merge it whenever possible. Thanks a lot! |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
|
@Maajith9127 LGTM! But there are some comments left, please resolve them before we merge |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
…ct-hook-form, clock defense
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
There was a problem hiding this comment.
Actionable comments posted: 19
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@kits/context-aware-blocker-backup-cpu-spike/apps/eslint.config.mjs`:
- Around line 1-18: Remove the entire context-aware-blocker-backup-cpu-spike
tree from the change, including its eslintConfig and all contained files; retain
the hardened kits/context-aware-blocker implementation as the sole shipped
version.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/extension/background.js`:
- Around line 99-105: Update the whitelist check in the STEP 0 block to parse
payload.url with URL and allow only an exact localhost or 127.0.0.1 hostname on
port 3000; remove the substring includes checks so embedded or deceptive URL
text cannot bypass blocking, while preserving the existing early return for the
valid dashboard origin.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/extension/content.js`:
- Around line 117-118: Replace the innerHTML interpolation in the subtitle
construction with a safe DOM-building approach: create text nodes for the static
message and commitName, and create the countdown element separately with its
fixed text and styling. Preserve the existing visual structure and ensure
commitName is never parsed as HTML.
- Around line 170-227: Update showAiEvaluatingOverlay to avoid accumulating
duplicate spinner stylesheet elements across evaluation cycles, and ensure
hideAiEvaluatingOverlay removes the stylesheet when the overlay is removed. Use
a stable identifier or existing overlay lifecycle to locate and clean up the
style while preserving the current spinner appearance.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/package.json`:
- Around line 11-17: Update the dependencies map in package.json to replace the
floating lamatic "latest" specifier with an explicit pinned SDK version. Leave
the other dependency versions unchanged.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/app/api/evaluate/route.ts`:
- Around line 46-55: Remove the partial secret disclosure from the configuration
logging in the evaluate handler: update the LAMATIC_API_KEY status message to
report only whether apiKey is set, without slicing or printing any characters.
Do not alter the other configuration checks or flow ID handling; the additional
authentication, rate limiting, and request validation concerns are outside this
requested change.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/src/app/page.tsx`:
- Around line 58-63: Centralize dashboard theming by replacing all literal hex
colors with the established semantic CSS variables: update page.tsx ranges 58-63
for spinner and page colors, 83-88 for Add-button colors, 107-108 for
empty-state text, and 124-131 to pass semantic color variables or remove color
props; update AIPopupModal.tsx 13-29 for modal and icon colors, CommitCard.tsx
26-92 for state and surface colors, ConfirmationModal.tsx 21-70 for default and
inline action colors, and UpcomingBlocksCard.tsx 3-10 for card and action
colors. Ensure all styling in these components uses CSS variables without
introducing new literal colors.
- Around line 52-56: Update handleAddCommit to create and persist the new
commitment in commits using the generated commit-${Date.now()} ID before calling
openModal("time", newId). Ensure the created record is available to
CommitSettingsModal and its ActiveTimePane/BlockedContentPane consumers so edits
attach to an existing commitment.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/AIPopupModal.tsx`:
- Around line 10-23: The modal overlays allow background interaction and lack
accessible keyboard behavior. In AIPopupModal.tsx at lines 10-23 and
ConfirmationModal.tsx at lines 42-74, add a labelled role="dialog" with
aria-modal, dismiss on Escape, contain keyboard focus within the active dialog,
and restore focus to the opener when closing; apply the same interaction
semantics to both dialogs.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/CommitCard.tsx`:
- Around line 29-31: Update the clickable card and its time/content controls in
CommitCard to use semantic button elements instead of div/span elements, making
each action focusable and keyboard-activatable. Preserve the existing styling
and onClick behavior, including event propagation or stopping propagation where
currently required.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/CommitSettingsModal.tsx`:
- Around line 73-129: Replace the hardcoded Tailwind hex colors with the shared
CSS variables in CommitSettingsModal.tsx lines 73-129: update bg-[`#0f0f0f`],
bg-[`#151515`], border-[`#e83a3a`], and text-[`#94a3b8`] to their corresponding
variable-based utilities. Apply the same migration in DaySelector.tsx lines
53-54 for bg-[`#e83a3a`], bg-[`#151515`], and text-[`#94a3b8`], preserving the
existing styling semantics.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/Button.tsx`:
- Around line 1-3: Remove the unused Button declaration from
kits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/Button.tsx:1-3
and the unused Modal declaration from
kits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/Modal.tsx:1-3.
If either component is required, add the specified props—Button with
children/onClick/className and Modal with isOpen/onClose/children—before
retaining it.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/DaySelector.tsx`:
- Around line 44-60: Add an accessible aria-label to each button rendered in the
DAYS.map callback, using the full day name from the day object so duplicate
single-letter labels such as Tuesday and Thursday are distinguishable to screen
readers. Preserve the existing visual labels and selection behavior in
toggleDay.
In
`@kits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/UpcomingBlocksCard.tsx`:
- Around line 1-13: The UpcomingBlocksCard component currently hardcodes a
fictional “Deep Work” block and an inert button; connect it to the real
commitments/schedule state. Derive and display the next upcoming block, wire the
button to the existing action for that block, and render non-interactive
empty-state content when no upcoming commitment exists.
In `@kits/context-aware-blocker-backup-cpu-spike/lamatic.config.ts`:
- Around line 1-19: The entire kits/context-aware-blocker-backup-cpu-spike/
directory is an unintended duplicate and must be removed, including the anchor
lamatic.config.ts and all listed sibling files:
apps/src/components/features/ActiveTimePane.tsx,
apps/src/components/features/BlockedContentPane.tsx,
apps/src/hooks/useCommitStore.ts, apps/src/lib/storage.ts,
apps/src/types/store.ts, flows/content-classification.ts, and
model-configs/app-blocker_llmnode-1_generative-model-name.ts; no rebranding is
needed.
In `@kits/context-aware-blocker-backup-cpu-spike/README.md`:
- Around line 41-42: Correct the supplied evaluate route so missing
configuration, unrecognized flow output, and execution errors all resolve to
BLOCK rather than PASS, preserving fail-closed behavior. In
kits/context-aware-blocker-backup-cpu-spike/README.md lines 41-42, retain the
documented claim after the endpoint is corrected; update
kits/context-aware-blocker-backup-cpu-spike/agent.md lines 55-57 to match the
endpoint’s BLOCK fallbacks.
In `@kits/context-aware-blocker/apps/extension/background.js`:
- Around line 1-6: Remove the hardcoded default from CAB_API_SECRET and replace
the shared-secret authentication with server-side extension-origin validation
using the extension identity (sender.id or the chrome-extension:// origin).
Update the background authentication flow and corresponding API validation so
requests are accepted only from the intended extension, without relying on a
secret embedded in public source.
In `@kits/context-aware-blocker/apps/src/lib/api-middleware.ts`:
- Around line 25-27: Update authenticateRequest so a missing CAB_SECRET fails
closed in production by returning a 503 response instead of null. Preserve the
bypass only when the runtime explicitly indicates local development, and keep
normal authentication behavior unchanged when the secret is configured.
In `@kits/context-aware-blocker/apps/src/lib/utils.ts`:
- Around line 40-60: Remove the ineffective clock-bypass defense based on
parsed.lockSetAt, expectedDuration, and actualElapsed in the lock validation
logic, since it reuses the same Date.now() value and cannot independently
activate. Retain the primary lockTimestamp expiry check unchanged, and do not
present the removed arithmetic as a security defense; implementing genuine
protection requires an external or monotonic time source beyond this
self-contained logic.
🪄 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 Plus
Run ID: dc2b12e0-0b41-4a53-9ee5-01a01b1a2f8a
⛔ Files ignored due to path filters (8)
kits/context-aware-blocker-backup-cpu-spike/apps/package-lock.jsonis excluded by!**/package-lock.jsonkits/context-aware-blocker-backup-cpu-spike/apps/public/file.svgis excluded by!**/*.svgkits/context-aware-blocker-backup-cpu-spike/apps/public/globe.svgis excluded by!**/*.svgkits/context-aware-blocker-backup-cpu-spike/apps/public/next.svgis excluded by!**/*.svgkits/context-aware-blocker-backup-cpu-spike/apps/public/vercel.svgis excluded by!**/*.svgkits/context-aware-blocker-backup-cpu-spike/apps/public/window.svgis excluded by!**/*.svgkits/context-aware-blocker-backup-cpu-spike/apps/src/app/favicon.icois excluded by!**/*.icokits/context-aware-blocker/apps/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (47)
kits/context-aware-blocker-backup-cpu-spike/.gitignorekits/context-aware-blocker-backup-cpu-spike/README.mdkits/context-aware-blocker-backup-cpu-spike/agent.mdkits/context-aware-blocker-backup-cpu-spike/apps/.env.examplekits/context-aware-blocker-backup-cpu-spike/apps/.gitignorekits/context-aware-blocker-backup-cpu-spike/apps/eslint.config.mjskits/context-aware-blocker-backup-cpu-spike/apps/extension/background.jskits/context-aware-blocker-backup-cpu-spike/apps/extension/content.jskits/context-aware-blocker-backup-cpu-spike/apps/extension/manifest.jsonkits/context-aware-blocker-backup-cpu-spike/apps/next.config.tskits/context-aware-blocker-backup-cpu-spike/apps/package.jsonkits/context-aware-blocker-backup-cpu-spike/apps/postcss.config.mjskits/context-aware-blocker-backup-cpu-spike/apps/src/app/api/evaluate/route.tskits/context-aware-blocker-backup-cpu-spike/apps/src/app/api/log/route.tskits/context-aware-blocker-backup-cpu-spike/apps/src/app/globals.csskits/context-aware-blocker-backup-cpu-spike/apps/src/app/layout.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/app/page.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/AIPopupModal.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/ActiveTimePane.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/BlockedContentPane.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/CommitCard.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/CommitSettingsModal.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/Button.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/ConfirmationModal.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/DaySelector.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/Modal.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/components/ui/UpcomingBlocksCard.tsxkits/context-aware-blocker-backup-cpu-spike/apps/src/hooks/useCommitStore.tskits/context-aware-blocker-backup-cpu-spike/apps/src/lib/storage.tskits/context-aware-blocker-backup-cpu-spike/apps/src/lib/utils.tskits/context-aware-blocker-backup-cpu-spike/apps/src/types/store.tskits/context-aware-blocker-backup-cpu-spike/apps/tsconfig.jsonkits/context-aware-blocker-backup-cpu-spike/constitutions/default.mdkits/context-aware-blocker-backup-cpu-spike/flows/content-classification.tskits/context-aware-blocker-backup-cpu-spike/lamatic.config.tskits/context-aware-blocker-backup-cpu-spike/model-configs/app-blocker_llmnode-1_generative-model-name.tskits/context-aware-blocker-backup-cpu-spike/prompts/app-blocker_llmnode-1_system_0.mdkits/context-aware-blocker/apps/.env.examplekits/context-aware-blocker/apps/extension/background.jskits/context-aware-blocker/apps/package.jsonkits/context-aware-blocker/apps/src/app/api/evaluate/route.tskits/context-aware-blocker/apps/src/app/api/log/route.tskits/context-aware-blocker/apps/src/app/globals.csskits/context-aware-blocker/apps/src/app/page.tsxkits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsxkits/context-aware-blocker/apps/src/lib/api-middleware.tskits/context-aware-blocker/apps/src/lib/utils.ts
| import { defineConfig, globalIgnores } from "eslint/config"; | ||
| import nextVitals from "eslint-config-next/core-web-vitals"; | ||
| import nextTs from "eslint-config-next/typescript"; | ||
|
|
||
| const eslintConfig = defineConfig([ | ||
| ...nextVitals, | ||
| ...nextTs, | ||
| // Override default ignores of eslint-config-next. | ||
| globalIgnores([ | ||
| // Default ignores of eslint-config-next: | ||
| ".next/**", | ||
| "out/**", | ||
| "build/**", | ||
| "next-env.d.ts", | ||
| ]), | ||
| ]); | ||
|
|
||
| export default eslintConfig; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Agent, this entire context-aware-blocker-backup-cpu-spike/ tree looks like a self-destructing artifact that forgot to self-destruct.
Your mission, should you choose to accept it: this file — and every file under kits/context-aware-blocker-backup-cpu-spike/ — is a byte-for-byte-ish duplicate of the real kit kits/context-aware-blocker/. The directory name (backup-cpu-spike) betrays it as a debugging/backup snapshot.
More dangerous: this copy is the pre-hardening version. The shipped kit's apps/src/app/api/evaluate/route.ts and .../api/log/route.ts run authenticateRequest, rateLimit, and zod schema validation, and gate verbose logging behind NODE_ENV. The versions in this backup tree have none of that — so merging reintroduces unauthenticated, unvalidated, verbose-logging API routes into the repo.
Recommend deleting the whole context-aware-blocker-backup-cpu-spike/ directory from this PR. If it must stay, every security regression called out below has to be re-applied here too. This message will not self-destruct.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/eslint.config.mjs` around
lines 1 - 18, Remove the entire context-aware-blocker-backup-cpu-spike tree from
the change, including its eslintConfig and all contained files; retain the
hardened kits/context-aware-blocker implementation as the sole shipped version.
| // ======================================================== | ||
| // STEP 0: WHITELIST (Never block our own dashboard) | ||
| // ======================================================== | ||
| if (payload.url.includes("localhost:3000") || payload.url.includes("127.0.0.1:3000")) { | ||
| console.log(`✅ STATUS: PASS (Whitelisted LamaBlock Dashboard)`); | ||
| return; // Instantly allow | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Whitelist check trusts a substring — a crafted URL slips past the checkpoint.
payload.url.includes("localhost:3000") matches any URL merely containing that string, e.g. https://localhost:3000.evil.com or https://evil.com/?redir=localhost:3000. Those get instantly allowed, defeating the blocker. Parse the URL and compare the host/port precisely (as the evaluation path already does with new URL(...).hostname).
🕶️ Suggested tightening
- if (payload.url.includes("localhost:3000") || payload.url.includes("127.0.0.1:3000")) {
+ try {
+ const { hostname, port } = new URL(payload.url);
+ const isDashboard = (hostname === "localhost" || hostname === "127.0.0.1") && port === "3000";
+ if (isDashboard) {
console.log(`✅ STATUS: PASS (Whitelisted LamaBlock Dashboard)`);
return;
- }
+ }
+ } catch { /* not a parseable URL; fall through to evaluation */ }📝 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.
| // ======================================================== | |
| // STEP 0: WHITELIST (Never block our own dashboard) | |
| // ======================================================== | |
| if (payload.url.includes("localhost:3000") || payload.url.includes("127.0.0.1:3000")) { | |
| console.log(`✅ STATUS: PASS (Whitelisted LamaBlock Dashboard)`); | |
| return; // Instantly allow | |
| } | |
| // ======================================================== | |
| // STEP 0: WHITELIST (Never block our own dashboard) | |
| // ======================================================== | |
| try { | |
| const { hostname, port } = new URL(payload.url); | |
| const isDashboard = (hostname === "localhost" || hostname === "127.0.0.1") && port === "3000"; | |
| if (isDashboard) { | |
| console.log(`✅ STATUS: PASS (Whitelisted LamaBlock Dashboard)`); | |
| return; // Instantly allow | |
| } | |
| } catch { /* not a parseable URL; fall through to evaluation */ } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/extension/background.js`
around lines 99 - 105, Update the whitelist check in the STEP 0 block to parse
payload.url with URL and allow only an exact localhost or 127.0.0.1 hostname on
port 3000; remove the substring includes checks so embedded or deceptive URL
text cannot bypass blocking, while preserving the existing early return for the
valid dashboard origin.
| const subtitle = document.createElement('p'); | ||
| subtitle.innerHTML = `This page is blocked by your "<strong>${commitName}</strong>" commit.<br><br><span id="lamablock-countdown" style="color: #ef4444; font-weight: bold;">Closing tab in 3s...</span>`; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Interrogate commitName before it goes on the record.
subtitle.innerHTML interpolates commitName directly into markup. It's user-controlled data (the commit title) rendered without escaping — flagged as CWE-79 by both ast-grep and OpenGrep. Today it's self-XSS at worst, but it's a landmine for any future flow that imports/syncs titles from less-trusted sources, and this content script has chrome.runtime.sendMessage access.
🛡️ Proposed fix
const subtitle = document.createElement('p');
- subtitle.innerHTML = `This page is blocked by your "<strong>${commitName}</strong>" commit.<br><br><span id="lamablock-countdown" style="color: `#ef4444`; font-weight: bold;">Closing tab in 3s...</span>`;
+ const strongName = document.createElement('strong');
+ strongName.textContent = commitName;
+ subtitle.append('This page is blocked by your "', strongName, '" commit.', document.createElement('br'), document.createElement('br'));
+ const countdownSpan = document.createElement('span');
+ countdownSpan.id = 'lamablock-countdown';
+ countdownSpan.style.cssText = 'color: `#ef4444`; font-weight: bold;';
+ countdownSpan.textContent = 'Closing tab in 3s...';
+ subtitle.appendChild(countdownSpan);📝 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 subtitle = document.createElement('p'); | |
| subtitle.innerHTML = `This page is blocked by your "<strong>${commitName}</strong>" commit.<br><br><span id="lamablock-countdown" style="color: #ef4444; font-weight: bold;">Closing tab in 3s...</span>`; | |
| const subtitle = document.createElement('p'); | |
| const strongName = document.createElement('strong'); | |
| strongName.textContent = commitName; | |
| subtitle.append('This page is blocked by your "', strongName, '" commit.', document.createElement('br'), document.createElement('br')); | |
| const countdownSpan = document.createElement('span'); | |
| countdownSpan.id = 'lamablock-countdown'; | |
| countdownSpan.style.cssText = 'color: `#ef4444`; font-weight: bold;'; | |
| countdownSpan.textContent = 'Closing tab in 3s...'; | |
| subtitle.appendChild(countdownSpan); |
🧰 Tools
🪛 ast-grep (0.44.1)
[warning] 117-117: Avoid assigning untrusted data to innerHTML/outerHTML or document.write
Context: subtitle.innerHTML = This page is blocked by your "<strong>${commitName}</strong>" commit.<br><br><span id="lamablock-countdown" style="color: #ef4444; font-weight: bold;">Closing tab in 3s...</span>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').
(inner-outer-html)
🪛 OpenGrep (1.25.0)
[WARNING] 118-118: Setting innerHTML with dynamic content can lead to XSS. Use textContent or createElement with proper escaping instead.
(coderabbit.xss.innerhtml-assignment)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/extension/content.js` around
lines 117 - 118, Replace the innerHTML interpolation in the subtitle
construction with a safe DOM-building approach: create text nodes for the static
message and commitName, and create the countdown element separately with its
fixed text and styling. Preserve the existing visual structure and ensure
commitName is never parsed as HTML.
| function showAiEvaluatingOverlay() { | ||
| if (document.getElementById('lamablock-ai-overlay')) return; | ||
|
|
||
| const overlay = document.createElement('div'); | ||
| overlay.id = 'lamablock-ai-overlay'; | ||
| overlay.style.cssText = ` | ||
| position: fixed; | ||
| top: 20px; | ||
| right: 20px; | ||
| background-color: rgba(26, 26, 26, 0.9); | ||
| backdrop-filter: blur(8px); | ||
| -webkit-backdrop-filter: blur(8px); | ||
| z-index: 2147483646; /* Just below the main block overlay */ | ||
| display: flex; | ||
| flex-direction: row; | ||
| align-items: center; | ||
| padding: 12px 20px; | ||
| border-radius: 9999px; | ||
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5); | ||
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | ||
| color: white; | ||
| pointer-events: none; /* User can click through the overlay */ | ||
| transition: opacity 0.3s ease; | ||
| `; | ||
|
|
||
| // Loader animation style | ||
| const style = document.createElement('style'); | ||
| style.innerHTML = ` | ||
| @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } | ||
| .lamablock-spinner { | ||
| border: 3px solid rgba(255, 255, 255, 0.1); | ||
| border-left-color: #ef4444; /* Match brand red */ | ||
| border-radius: 50%; | ||
| width: 20px; | ||
| height: 20px; | ||
| animation: spin 1s linear infinite; | ||
| margin-right: 12px; | ||
| } | ||
| `; | ||
| document.head.appendChild(style); | ||
|
|
||
| const spinner = document.createElement('div'); | ||
| spinner.className = 'lamablock-spinner'; | ||
|
|
||
| const title = document.createElement('span'); | ||
| title.innerText = 'AI is evaluating...'; | ||
| title.style.cssText = ` | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| margin: 0; | ||
| color: #ffffff; | ||
| `; | ||
|
|
||
| overlay.appendChild(spinner); | ||
| overlay.appendChild(title); | ||
|
|
||
| document.documentElement.appendChild(overlay); | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Agent, this style tag never self-destructs — head just keeps piling up.
showAiEvaluatingOverlay() guards against duplicate overlay <div>s (line 171) but unconditionally injects a fresh <style> element into document.head on every call (196-209), and hideAiEvaluatingOverlay() never removes it. Every AI-evaluation cycle on a long-lived tab leaks another duplicate stylesheet into the DOM.
🧹 Proposed fix
- // Loader animation style
- const style = document.createElement('style');
- style.innerHTML = `
- `@keyframes` spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
- .lamablock-spinner {
- border: 3px solid rgba(255, 255, 255, 0.1);
- border-left-color: `#ef4444`; /* Match brand red */
- border-radius: 50%;
- width: 20px;
- height: 20px;
- animation: spin 1s linear infinite;
- margin-right: 12px;
- }
- `;
- document.head.appendChild(style);
+ // Loader animation style (inject once, reuse thereafter)
+ if (!document.getElementById('lamablock-spinner-style')) {
+ const style = document.createElement('style');
+ style.id = 'lamablock-spinner-style';
+ style.innerHTML = `
+ `@keyframes` spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
+ .lamablock-spinner {
+ border: 3px solid rgba(255, 255, 255, 0.1);
+ border-left-color: `#ef4444`; /* Match brand red */
+ border-radius: 50%;
+ width: 20px;
+ height: 20px;
+ animation: spin 1s linear infinite;
+ margin-right: 12px;
+ }
+ `;
+ document.head.appendChild(style);
+ }📝 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.
| function showAiEvaluatingOverlay() { | |
| if (document.getElementById('lamablock-ai-overlay')) return; | |
| const overlay = document.createElement('div'); | |
| overlay.id = 'lamablock-ai-overlay'; | |
| overlay.style.cssText = ` | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| background-color: rgba(26, 26, 26, 0.9); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| z-index: 2147483646; /* Just below the main block overlay */ | |
| display: flex; | |
| flex-direction: row; | |
| align-items: center; | |
| padding: 12px 20px; | |
| border-radius: 9999px; | |
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5); | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| color: white; | |
| pointer-events: none; /* User can click through the overlay */ | |
| transition: opacity 0.3s ease; | |
| `; | |
| // Loader animation style | |
| const style = document.createElement('style'); | |
| style.innerHTML = ` | |
| @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } | |
| .lamablock-spinner { | |
| border: 3px solid rgba(255, 255, 255, 0.1); | |
| border-left-color: #ef4444; /* Match brand red */ | |
| border-radius: 50%; | |
| width: 20px; | |
| height: 20px; | |
| animation: spin 1s linear infinite; | |
| margin-right: 12px; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| const spinner = document.createElement('div'); | |
| spinner.className = 'lamablock-spinner'; | |
| const title = document.createElement('span'); | |
| title.innerText = 'AI is evaluating...'; | |
| title.style.cssText = ` | |
| font-size: 14px; | |
| font-weight: 500; | |
| margin: 0; | |
| color: #ffffff; | |
| `; | |
| overlay.appendChild(spinner); | |
| overlay.appendChild(title); | |
| document.documentElement.appendChild(overlay); | |
| } | |
| function showAiEvaluatingOverlay() { | |
| if (document.getElementById('lamablock-ai-overlay')) return; | |
| const overlay = document.createElement('div'); | |
| overlay.id = 'lamablock-ai-overlay'; | |
| overlay.style.cssText = ` | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| background-color: rgba(26, 26, 26, 0.9); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| z-index: 2147483646; /* Just below the main block overlay */ | |
| display: flex; | |
| flex-direction: row; | |
| align-items: center; | |
| padding: 12px 20px; | |
| border-radius: 9999px; | |
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5); | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| color: white; | |
| pointer-events: none; /* User can click through the overlay */ | |
| transition: opacity 0.3s ease; | |
| `; | |
| // Loader animation style (inject once, reuse thereafter) | |
| if (!document.getElementById('lamablock-spinner-style')) { | |
| const style = document.createElement('style'); | |
| style.id = 'lamablock-spinner-style'; | |
| style.innerHTML = ` | |
| `@keyframes` spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } | |
| .lamablock-spinner { | |
| border: 3px solid rgba(255, 255, 255, 0.1); | |
| border-left-color: `#ef4444`; /* Match brand red */ | |
| border-radius: 50%; | |
| width: 20px; | |
| height: 20px; | |
| animation: spin 1s linear infinite; | |
| margin-right: 12px; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| } | |
| const spinner = document.createElement('div'); | |
| spinner.className = 'lamablock-spinner'; | |
| const title = document.createElement('span'); | |
| title.innerText = 'AI is evaluating...'; | |
| title.style.cssText = ` | |
| font-size: 14px; | |
| font-weight: 500; | |
| margin: 0; | |
| color: `#ffffff`; | |
| `; | |
| overlay.appendChild(spinner); | |
| overlay.appendChild(title); | |
| document.documentElement.appendChild(overlay); | |
| } |
🧰 Tools
🪛 ast-grep (0.44.1)
[warning] 196-207: Avoid assigning untrusted data to innerHTML/outerHTML or document.write
Context: style.innerHTML = @Keyframesspin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .lamablock-spinner { border: 3px solid rgba(255, 255, 255, 0.1); border-left-color:#ef4444; /* Match brand red */ border-radius: 50%; width: 20px; height: 20px; animation: spin 1s linear infinite; margin-right: 12px; }
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').
(inner-outer-html)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/extension/content.js` around
lines 170 - 227, Update showAiEvaluatingOverlay to avoid accumulating duplicate
spinner stylesheet elements across evaluation cycles, and ensure
hideAiEvaluatingOverlay removes the stylesheet when the overlay is removed. Use
a stable identifier or existing overlay lifecycle to locate and clean up the
style while preserving the current spinner appearance.
| "dependencies": { | ||
| "lamatic": "latest", | ||
| "next": "16.2.10", | ||
| "react": "19.2.4", | ||
| "react-dom": "19.2.4", | ||
| "zustand": "^5.0.14" | ||
| }, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
lamatic npm package latest version
💡 Result:
To determine the latest version of the Lamatic packages from the npm registry, you can use the npm view command with the dist-tags.latest field. For the core SDK package (lamatic), run: npm view lamatic dist-tags.latest For the command-line interface package (@lamatic/cli), run: npm view @lamatic/cli dist-tags.latest These commands will output the version string currently tagged as latest in the npm registry, which is the version installed by default when you run npm install [package-name]. Note that Lamatic provides multiple packages, such as the SDK [1][2] and the @lamatic/cli tool [3][4], which are managed and versioned independently.
Citations:
- 1: https://lamatic.ai/docs/api-integration/sdk
- 2: https://get.lamatic.ai/
- 3: https://lamatic.ai/docs/cli
- 4: https://product.lamatic.ai/changelog/lamatic-cli-and-real-time-cost-in-logs
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locate package files mentioning lamatic or matching kits/*/apps/package.json"
git ls-files 'kits/*/apps/package.json' kits 2>/dev/null | head -100
echo
echo "Find lamatic dependencies"
rg -n '"lamatic"|package.json' -S kits 2>/dev/null | head -200
echo
echo "Inspect target package"
if [ -f kits/context-aware-blocker-backup-cpu-spike/apps/package.json ]; then
cat -n kits/context-aware-blocker-backup-cpu-spike/apps/package.json
fi
echo
echo "Inspect any kit-level root package references if present"
fd -a 'package.json$' kits/context-aware-blocker-backup-cpu-spike -x sh -c 'echo "--- $1"; cat -n "$1"' sh {} \; 2>/dev/null | sed -n '1,200p'Repository: Lamatic/AgentKit
Length of output: 5518
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Tracked files under target kit:"
git ls-files 'kits/context-aware-blocker-backup-cpu-spike/*' 2>/dev/null
echo
echo "Search target kit for package.json and lamatic:"
rg -n '"package.json"|"lamatic"|\blamatic\b' kits/context-aware-blocker-backup-cpu-spike 2>/dev/null || true
echo
echo "Search for backup-cpu-spike label anywhere:"
rg -n "context-aware-blocker-backup-cpu-spike|backup-cpu-spike|context-aware-blocker" . 2>/dev/null | head -100Repository: Lamatic/AgentKit
Length of output: 7302
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Target apps/package.json dependency section:"
sed -n '1,35p' kits/context-aware-blocker-backup-cpu-spike/apps/package.json | cat -n
echo
echo "Lockfile lamatic entry:"
sed -n '4668,4682p' kits/context-aware-blocker-backup-cpu-spike/apps/package-lock.json | cat -n
echo
echo "Shipped kit target section:"
sed -n '1,35p' kits/context-aware-blocker/apps/package.json | cat -n
echo
echo "Shipped lockfile lamatic entry:"
sed -n '4668,4682p' kits/context-aware-blocker/apps/package-lock.json | cat -n 2>/dev/null || trueRepository: Lamatic/AgentKit
Length of output: 3525
Pin the Lamatic SDK version.
"lamatic": "latest" makes clean installs non-reproducible and can introduce breaking API changes into this kit. Pin it to an explicit version in the dependency map.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker-backup-cpu-spike/apps/package.json` around lines
11 - 17, Update the dependencies map in package.json to replace the floating
lamatic "latest" specifier with an explicit pinned SDK version. Leave the other
dependency versions unchanged.
| export default { | ||
| name: "Context-Aware Blocker", | ||
| description: "A production-grade AI content blocker for productivity. Features a Next.js backend for secure Lamatic API communication and a Chrome Extension frontend for real-time contextual blocking.", | ||
| version: '1.0.0', | ||
| type: 'kit' as const, | ||
| author: { name: "Abdul Maajith", email: "maajith9127@gmail.com" }, | ||
| tags: ["agentic", "productivity", "content-blocking", "chrome-extension", "nextjs"], | ||
| steps: [ | ||
| { | ||
| id: "content-classification", | ||
| type: "mandatory" as const, | ||
| envKey: "CONTENT_CLASSIFICATION_FLOW_ID" | ||
| } | ||
| ], | ||
| links: { | ||
| github: "https://github.com/Lamatic/AgentKit/tree/main/kits/context-aware-blocker", | ||
| deploy: "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FLamatic%2FAgentKit%2Ftree%2Fmain%2Fkits%2Fcontext-aware-blocker%2Fapps&env=LAMATIC_API_KEY,LAMATIC_PROJECT_ID,LAMATIC_API_URL,CONTENT_CLASSIFICATION_FLOW_ID" | ||
| }, | ||
| }; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Mission briefing: the entire kits/context-aware-blocker-backup-cpu-spike/ directory is a stray duplicate and should self-destruct before this PR merges.
Every file in this tree is a byte-for-byte (or near-identical) copy of the real kit at kits/context-aware-blocker/. The clincher is in lamatic.config.ts: its own links.github and links.deploy still point at kits/context-aware-blocker, not at itself — a real, independently-maintained second kit would never self-reference the other one. The directory name ("backup-cpu-spike") strongly suggests this was a debugging/rollback snapshot that got committed by mistake instead of being cleaned up. Shipping it duplicates maintenance burden, confuses kits/* discovery/tooling that globs by kit name, and risks the community deploying a stale, unpatched copy (this tree still contains apps/extension/background.js, apps/extension/content.js, and API routes that aren't part of the hardened "Additional reviewed files" layer applied to the primary kit).
kits/context-aware-blocker-backup-cpu-spike/lamatic.config.ts: delete the file/directory, or if intentionally kept, rename/rebrand it with its ownname,links.github, andlinks.deploydistinct fromkits/context-aware-blocker.kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/ActiveTimePane.tsx: remove as part of directory cleanup.kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/BlockedContentPane.tsx: remove as part of directory cleanup.kits/context-aware-blocker-backup-cpu-spike/apps/src/hooks/useCommitStore.ts: remove as part of directory cleanup.kits/context-aware-blocker-backup-cpu-spike/apps/src/lib/storage.ts: remove as part of directory cleanup.kits/context-aware-blocker-backup-cpu-spike/apps/src/types/store.ts: remove as part of directory cleanup.kits/context-aware-blocker-backup-cpu-spike/flows/content-classification.ts: remove as part of directory cleanup.kits/context-aware-blocker-backup-cpu-spike/model-configs/app-blocker_llmnode-1_generative-model-name.ts: remove as part of directory cleanup.
🕵️ Suggested cleanup
git rm -r kits/context-aware-blocker-backup-cpu-spike📍 Affects 8 files
kits/context-aware-blocker-backup-cpu-spike/lamatic.config.ts#L1-L19(this comment)kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/ActiveTimePane.tsx#L1-L165kits/context-aware-blocker-backup-cpu-spike/apps/src/components/features/BlockedContentPane.tsx#L1-L249kits/context-aware-blocker-backup-cpu-spike/apps/src/hooks/useCommitStore.ts#L1-L93kits/context-aware-blocker-backup-cpu-spike/apps/src/lib/storage.ts#L1-L45kits/context-aware-blocker-backup-cpu-spike/apps/src/types/store.ts#L1-L22kits/context-aware-blocker-backup-cpu-spike/flows/content-classification.ts#L1-L131kits/context-aware-blocker-backup-cpu-spike/model-configs/app-blocker_llmnode-1_generative-model-name.ts#L1-L15
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker-backup-cpu-spike/lamatic.config.ts` around lines 1
- 19, The entire kits/context-aware-blocker-backup-cpu-spike/ directory is an
unintended duplicate and must be removed, including the anchor lamatic.config.ts
and all listed sibling files: apps/src/components/features/ActiveTimePane.tsx,
apps/src/components/features/BlockedContentPane.tsx,
apps/src/hooks/useCommitStore.ts, apps/src/lib/storage.ts,
apps/src/types/store.ts, flows/content-classification.ts, and
model-configs/app-blocker_llmnode-1_generative-model-name.ts; no rebranding is
needed.
| // ** PRODUCTION LEVEL: Shared API Secret for Localhost Authentication ** // | ||
| // This secret must match the CAB_API_SECRET in the Next.js .env.local file. | ||
| // Since this extension only communicates with localhost:3000, hardcoding here | ||
| // is acceptable — it prevents other local network actors from hitting the API. | ||
| const CAB_API_SECRET = "cab-local-dev-secret-change-me"; | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
Your mission, should you choose to accept it: make this secret actually secret.
CAB_API_SECRET is hardcoded to the exact default value shipped in .env.example, which is public in this open-source repo. Anyone reading the repo (not just "local network actors") already knows this value, so the auth check only protects installs where the user manually edits both .env.local and this JS constant to a custom value — an easy step to miss since this file isn't rebuilt from env vars.
Consider documenting the required manual rotation more prominently, or replacing the shared-secret model with an origin check (validate sender.id / Origin: chrome-extension://<id> server-side) that doesn't depend on a string baked into public source.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kits/context-aware-blocker/apps/extension/background.js` around lines 1 - 6,
Remove the hardcoded default from CAB_API_SECRET and replace the shared-secret
authentication with server-side extension-origin validation using the extension
identity (sender.id or the chrome-extension:// origin). Update the background
authentication flow and corresponding API validation so requests are accepted
only from the intended extension, without relying on a secret embedded in public
source.
…th, fix clock defense
|
All 19 of the latest CodeRabbit comments have been addressed (the backup directory was accidentally staged and has been removed, and the 3 security/logic bugs in the main kit are fixed). The PR is fully green and ready to merge!" please check if any changes needed and let me know |
|
/validate |
|
📡 Running Studio validation — results will appear here shortly. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kits/context-aware-blocker/apps/src/app/page.tsx (1)
258-271: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftMission: the Lamatic palette still hasn't defected to CSS variables.
Both
ConfirmationModalusages still pass raw hex (#e83a3a,#94a3b8) instead of theme tokens/CSS variables, as flagged previously for this component tree.As per coding guidelines,
kits/*/apps/**/*.{ts,tsx,css}requires kit Next.js apps to "use CSS variables for styling."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/context-aware-blocker/apps/src/app/page.tsx` around lines 258 - 271, Update both ConfirmationModal usages in page.tsx, including the delete and lock settings modals, to replace the raw confirmColor and cancelColor hex values with the appropriate existing CSS theme variables or palette tokens. Preserve the current modal behavior and color roles.Source: Coding guidelines
♻️ Duplicate comments (2)
kits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsx (1)
63-106: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftMission: this modal still can't be operated by keyboard alone.
The overlay has no
role="dialog"/aria-modal, no Escape-to-close handler, and no focus trap or focus restoration — the accessibility gap flagged previously is still live here. Note per the kit's dependency-minimalism guidance, a full shadcn Dialog isn't strictly required if this app doesn't already depend on shadcn/ui — a native fix (e.g. wrap in a<dialog>element, or addrole="dialog",aria-modal="true", an Escapekeydownlistener, and focus trap/restore logic) would satisfy the same goal with less footprint.Based on learnings, "keep dependencies minimal... do not require adding
shadcn/uisolely to replace a native control... when that kit/app does not already depend on or useshadcn/ui."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsx` around lines 63 - 106, Update ConfirmationModal to provide keyboard-accessible modal behavior without adding shadcn/ui or other dependencies: expose the modal as a dialog with aria-modal, close it on Escape, trap focus within the modal while open, and restore focus to the previously focused element when it closes. Keep the existing cancel, confirm, title, message, and children behavior intact.Source: Learnings
kits/context-aware-blocker/apps/src/lib/utils.ts (1)
22-44: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy liftMission still compromised: strict-lock authority remains fully client-controlled.
Good save on removing the dead "clock bypass" arithmetic — that critical dead-code issue is resolved. However, the underlying architecture gap flagged previously is unchanged:
isStrictLockActivestill trustslocalStorageandDate.now()exclusively. Deletinglama_lock_settingsor rolling the OS clock forward still returnsfalseand lets the user bypass the lock. This needs an extension/server-owned authority with a trusted timestamp to be a real commitment device.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kits/context-aware-blocker/apps/src/lib/utils.ts` around lines 22 - 44, The strict-lock decision in isStrictLockActive must no longer rely exclusively on client-controlled localStorage or Date.now(). Add an extension/server-owned authority that provides the lock state and trusted timestamp, and use that authoritative result for enforcement; retain localStorage only as non-authoritative fallback or configuration as appropriate. Ensure deleting lama_lock_settings or changing the OS clock cannot deactivate an active lock.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@kits/context-aware-blocker/apps/src/app/page.tsx`:
- Around line 298-304: Update the time picker render logic around field.value
and field.onChange so the displayed fallback "12:00" is written to the form
field when the value is empty, preferably via mount/synchronization logic rather
than only changing the display value. Preserve existing user selections and
ensure saving without interacting with the selects submits 12:00 instead of
triggering the required-time validation.
In `@kits/context-aware-blocker/apps/src/lib/api-middleware.ts`:
- Around line 37-46: Restrict extension authentication to the provisioned
extension identity: in kits/context-aware-blocker/apps/src/lib/api-middleware.ts
lines 37-46, replace the chrome-extension prefix bypass with an equality check
against the configured authorized extension origin. Update
kits/context-aware-blocker/apps/.env.example lines 11-14 to document and provide
the exact extension-origin configuration contract instead of the unused
shared-secret instructions, and revise
kits/context-aware-blocker/apps/extension/background.js lines 1-2 to reflect the
pinned extension identity.
---
Outside diff comments:
In `@kits/context-aware-blocker/apps/src/app/page.tsx`:
- Around line 258-271: Update both ConfirmationModal usages in page.tsx,
including the delete and lock settings modals, to replace the raw confirmColor
and cancelColor hex values with the appropriate existing CSS theme variables or
palette tokens. Preserve the current modal behavior and color roles.
---
Duplicate comments:
In `@kits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsx`:
- Around line 63-106: Update ConfirmationModal to provide keyboard-accessible
modal behavior without adding shadcn/ui or other dependencies: expose the modal
as a dialog with aria-modal, close it on Escape, trap focus within the modal
while open, and restore focus to the previously focused element when it closes.
Keep the existing cancel, confirm, title, message, and children behavior intact.
In `@kits/context-aware-blocker/apps/src/lib/utils.ts`:
- Around line 22-44: The strict-lock decision in isStrictLockActive must no
longer rely exclusively on client-controlled localStorage or Date.now(). Add an
extension/server-owned authority that provides the lock state and trusted
timestamp, and use that authoritative result for enforcement; retain
localStorage only as non-authoritative fallback or configuration as appropriate.
Ensure deleting lama_lock_settings or changing the OS clock cannot deactivate an
active lock.
🪄 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 Plus
Run ID: cec9c023-9257-4cff-88bc-32bd0b8fc5e4
⛔ Files ignored due to path filters (1)
kits/context-aware-blocker/apps/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
kits/context-aware-blocker/apps/.env.examplekits/context-aware-blocker/apps/extension/background.jskits/context-aware-blocker/apps/package.jsonkits/context-aware-blocker/apps/src/app/api/evaluate/route.tskits/context-aware-blocker/apps/src/app/api/log/route.tskits/context-aware-blocker/apps/src/app/globals.csskits/context-aware-blocker/apps/src/app/page.tsxkits/context-aware-blocker/apps/src/components/ui/ConfirmationModal.tsxkits/context-aware-blocker/apps/src/lib/api-middleware.tskits/context-aware-blocker/apps/src/lib/utils.ts
|
@akshatvirmani @amanintech @d-pamneja Thanks for the review! I have fully resolved the final round of CodeRabbit comments: Cleaned up the duplicate backup folder: The kits/context-aware-blocker-backup-cpu-spike directory was accidentally staged during a previous debug session and has now been completely deleted. Could you let me know if there's anything else you'd like me to change, or is this good to merge? Thanks again! |
What is the Context-Aware Blocker?
Traditional website blockers are dumb—they just block URLs. The Context-Aware Blocker Kit is a smart, AI-driven productivity tool that understands what you are trying to do, and selectively blocks distracting content based on the actual context of the page, not just the domain name.
It consists of two main parts working together:
A Next.js Dashboard (for setting your goals and schedules)
A Chrome Extension (for enforcing those rules in real-time)
💡 The Use Case & Example
Imagine you are a developer setting a "Deep Work" commitment on a Tuesday afternoon.
You tell the dashboard: "Block all entertainment and social media, but allow coding tutorials and documentation."
Scenario A: You go to youtube.com/watch?v=funny-cat-video.
The Chrome extension scrapes the page title and metadata.
It sends this context to our Lamatic AI Evaluation Flow.
The AI realizes this is entertainment.
Result: The extension throws up a physical block screen. 🛑
Scenario B: You go to youtube.com/watch?v=nextjs-tutorial.
The extension scrapes the context.
The Lamatic AI evaluates it against your "Deep Work" rule and realizes this is educational coding content.
Result: The AI returns PASS, and you are allowed to watch the video! ✅
🏗️ How it was built
To achieve this, this PR introduces a complete production-grade architecture:
Next.js Dashboard (apps/): A sleek, dark-themed React application styled with Tailwind CSS. It features reusable CommitCard components, a unified sliding settings modal (mimicking native iOS/Android behavior), and interactive panes for managing active times and AI rules.
Chrome MV3 Extension (apps/extension/): A background service worker and content script that safely scrapes DOM context (H1s, titles, meta tags) and communicates with the Next.js API.
Lamatic AI Flow (flows/content-classification.ts): A custom trigger node and LLM node that take the scraped context, evaluate it against a strict system prompt and constitution, and definitively return a PASS or BLOCK verdict.
Strict Lock Mode: A tamper-proof mechanism (backed by storage.ts) that prevents users from deleting their own block settings while a commitment is active.
(Note: All critical security, XSS, memory-leak, and logic bugs flagged in the review process have been fixed. Some architectural suggestions like react-hook-form were intentionally skipped to keep this PR focused and minimal).
/api/evaluatevalidates and authenticates requests, rate-limits callers, invokes Lamatic classification, enforces timeouts, sanitizes results toBLOCK/PASS, and fails open on errors./api/logauthenticates and rate-limits structured development logging.chrome://extensions.BLOCKorPASSresponse based on the active focus rules.