Skip to content

feat: content localisation - #796

Open
123FLO321 wants to merge 36 commits into
rajnandan1:mainfrom
123FLO321:feature/content-localisation
Open

feat: content localisation#796
123FLO321 wants to merge 36 commits into
rajnandan1:mainfrom
123FLO321:feature/content-localisation

Conversation

@123FLO321

@123FLO321 123FLO321 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Adds a option for all user visible texts to enter texts in all (in internationalization configured) languages.

Example:
image

Summary by CodeRabbit

  • New Features
    • Added multilingual content support for monitors, incidents, comments, and maintenance records.
    • Added translation editing controls for names, titles, descriptions, and comments.
    • Added localized content display across public status, incident, maintenance, and monitor pages.
    • Added monitor translation support to API requests, responses, and documentation.
  • Bug Fixes
    • Preserved existing translations when unrelated records are updated.
    • Added validation, fallback behavior, and safe handling for invalid or incomplete translations.
  • Tests
    • Expanded automated coverage for translations, UI components, browser behavior, and utility functions.
  • Documentation
    • Added testing commands and browser setup guidance.

123FLO321 and others added 30 commits July 13, 2026 20:51
…superpowers

Shell scripts checked out with CRLF on Windows (core.autocrlf=true) broke
the Docker entrypoint at container start. Force LF for all text files at
the git layer, matching the existing .editorconfig and Prettier settings.
Add a workflow-level concurrency group keyed by workflow + ref with
cancel-in-progress, so pushing a new commit cancels the still-running
test job for the previous commit on that branch/PR.
… them

Five manage-monitor cards (MonitorTypeCard, UptimeSettingsCard,
StatusHistoryDaysCard, MonitorSharingOptionsCard, DangerZoneCard) spread
the page's monitor state into storeMonitorData payloads without a
translations key, so it arrived as undefined. CreateUpdateMonitor
serialized that unconditionally to null, silently wiping authored
monitor translations whenever one of those cards was saved.

Add resolveTranslationsForUpdate (src/lib/server/content-i18n.ts), a
pure keep-on-undefined resolver matching the pattern already used by
UpdateIncident/UpdateMaintenance: an omitted translations key preserves
whatever is stored, while an explicit object or null always replaces
it. Wire it into CreateUpdateMonitor's update branch and the standalone
UpdateMonitor controller, fetching the existing raw value only when the
incoming payload actually omits translations. The create path keeps its
prior undefined-to-null semantics.

Also retype the local MonitorInput interface's translations field to
unknown (was inherited string | null from MonitorRecordInsert), matching
IncidentInput/CreateMaintenanceInput, since real callers pass objects,
serialized strings, undefined, or null - never just string | null.
MonitorRecord/MonitorRecordInsert, which describe actual DB rows, are
unchanged.
cancelEditComment() and cancelAddComment() reset commentText but left
commentTranslations holding the last-edited values, relying on the next
startEditComment/startAddComment call to reset it first. Clear it in
both cancel paths too, so the safety invariant holds locally rather than
depending on every future entry path.
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds localized content translations for monitors, incidents, comments, and maintenances across storage, APIs, management forms, and rendered pages. It also adds Vitest browser/server testing, CI execution, database migration support, and repository configuration updates.

Changes

Content translations

Layer / File(s) Summary
Translation contracts and resolution
src/lib/types/*, src/lib/content-i18n.ts, src/lib/stores/i18n.ts, src/lib/client/manage-locales.ts
Defines translation shapes, validation, serialization, locale resolution, and locale discovery.
Schema, records, and repositories
migrations/*, src/lib/server/types/*, src/lib/server/db/repositories/*
Adds nullable translation columns and propagates translation data through database records and query results.
Controllers and API mutation paths
src/lib/server/controllers/*, src/routes/(api)/*, src/routes/(manage)/manage/api/*
Validates and persists translation payloads while preserving omitted existing values.
Translation editing controls
src/lib/components/manage/*, src/routes/(manage)/manage/app/*
Adds locale-aware translation dialogs and integrates translation state into monitor, incident, and maintenance forms.
Localized content rendering
src/lib/components/*, src/routes/(kener)/*, src/lib/server/api-server/*, static/api-references/*
Renders translated titles, descriptions, comments, monitor names, and exposes monitor translation fields in API schemas.
Translation validation tests
src/lib/content-i18n.test.ts, src/lib/server/content-i18n.test.ts, src/lib/stores/i18n.test.ts
Covers parsing, fallback, validation, serialization, update semantics, and locale-specific resolution.

Test infrastructure and repository configuration

Layer / File(s) Summary
Vitest projects and commands
vite.config.ts, vitest-setup-client.ts, package.json
Configures Node and Playwright browser projects, UTC test scripts, browser dependencies, and SvelteKit mocks.
Continuous test execution
.github/workflows/test.yml
Runs type checks and tests in GitHub Actions with Node and Playwright setup.
Component and server test coverage
src/lib/components/*.test.ts, src/lib/server/tool.test.ts
Adds CopyButton, StatusBarCalendar, and server utility test coverage.
Repository defaults and developer guidance
.gitattributes, .gitignore, CLAUDE.md
Updates line-ending rules, ignored paths, and documented test commands.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Manager
  participant ManageAPI
  participant Controller
  participant Database
  participant PublicPage

  Manager->>ManageAPI: submit translated content
  ManageAPI->>Controller: forward translation payload
  Controller->>Database: validate and store serialized translations
  Database-->>PublicPage: return translation fields
  PublicPage->>PublicPage: resolve active-locale content with fallback
Loading

Possibly related PRs

  • rajnandan1/kener#789 — Adds overlapping Vitest projects, CI workflow, package scripts, browser setup, and test changes.

Suggested reviewers: rajnandan1, rajnandan1

Poem

I’m a rabbit with locales to share,
Translating carrots with careful care.
Tests hop through browsers, servers, and light,
CI checks every line just right.
LF paths keep the burrow neat—
Multilingual code is a tasty treat!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding content localization support across translations, APIs, UI, and tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds localized user-visible content across status-page entities. The main changes are:

  • Adds translation storage for monitors, incidents, comments, and maintenance records.
  • Adds server-side validation, serialization, and update handling.
  • Adds translation editors to management forms.
  • Resolves localized content on public pages and monitor bars.
  • Adds server and browser test infrastructure.

Confidence Score: 4/5

Translated-only descriptions can disappear on public maintenance and monitor pages.

  • Empty base descriptions suppress valid localized descriptions.
  • Detail-page metadata remains in the base language.
  • Translation persistence and fallback handling otherwise appear consistent.

src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte and src/routes/(kener)/monitors/[monitor_tag]/+page.svelte

Important Files Changed

Filename Overview
src/lib/server/content-i18n.ts Adds validation, serialization, and preserve-on-undefined update behavior.
src/lib/content-i18n.ts Adds tolerant parsing and locale-aware field resolution.
src/lib/components/manage/TranslationsButton.svelte Adds a reusable editor for translated entity fields.
src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte Localizes visible content, but translated-only descriptions can remain hidden and metadata stays untranslated.
src/routes/(kener)/monitors/[monitor_tag]/+page.svelte Localizes visible content, but translated-only descriptions can remain hidden and metadata stays untranslated.
src/routes/(kener)/incidents/[incident_id]/+page.svelte Localizes visible incident content while retaining base-language page metadata.
migrations/20260716120000_add_content_translations.ts Adds guarded nullable translation columns through Knex.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Management translation editor] --> B[Validation and serialization]
  B --> C[(Translation JSON columns)]
  C --> D[Query and parsing]
  D --> E[Locale resolver]
  E --> F[Incident pages]
  E --> G[Maintenance pages]
  E --> H[Monitor pages]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart LR
  A[Management translation editor] --> B[Validation and serialization]
  B --> C[(Translation JSON columns)]
  C --> D[Query and parsing]
  D --> E[Locale resolver]
  E --> F[Incident pages]
  E --> G[Maintenance pages]
  E --> H[Monitor pages]
Loading

Reviews (1): Last reviewed commit: "fix(monitors): look up preserved transla..." | Re-trigger Greptile

<div class="prose prose-sm dark:prose-invert max-w-none min-w-0 overflow-x-auto p-4 wrap-break-word">
<SveltePurify html={mdToHTML(data.maintenance.description)} />
<SveltePurify
html={mdToHTML($lt(data.maintenance.translations, "description", data.maintenance.description))}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Translated Description Remains Hidden

When the optional base description is empty but the current locale has a description, the surrounding block still tests data.maintenance.description and skips this localized output. Visitors therefore see no description despite a valid translation being stored.

Context Used: CLAUDE.md (source)

let descriptionExpanded = $state(false);
let showInlineEvents = $derived(data.eventDisplaySettings?.showInlineEvents === true);
const monitorName = $derived($lt(data.monitorTranslations, "name", data.monitorName));
const monitorDescription = $derived($lt(data.monitorTranslations, "description", data.monitorDescription ?? ""));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Translated Description Remains Hidden

monitorDescription can resolve to translated text when the optional base description is empty, but the template still renders the section only when data.monitorDescription is truthy. A translated-only description is therefore omitted from the public monitor page.

Context Used: CLAUDE.md (source)

<h1>
<Item.Title class="text-3xl wrap-break-word">{data.incident.title}</Item.Title>
<Item.Title class="text-3xl wrap-break-word"
>{$lt(data.incident.translations, "title", data.incident.title)}</Item.Title

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Localized Content Has Base Metadata

The visible title and comments now use $lt, but the page title and social metadata still use the base incident title and first comment. For a non-default locale, browser tabs, search descriptions, and shared-link previews disagree with the rendered page.

Context Used: CLAUDE.md (source)

<h1>
<Item.Title class="text-3xl wrap-break-word">{data.maintenance.title}</Item.Title>
<Item.Title class="text-3xl wrap-break-word"
>{$lt(data.maintenance.translations, "title", data.maintenance.title)}</Item.Title

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Localized Content Has Base Metadata

The heading and description now resolve translations, while <svelte:head> still uses the base title and description. Visitors using another locale receive default-language browser and social-preview metadata for otherwise localized content.

Context Used: CLAUDE.md (source)

Comment on lines +20 to +21
const monitorName = $derived($lt(data.monitorTranslations, "name", data.monitorName));
const monitorDescription = $derived($lt(data.monitorTranslations, "description", data.monitorDescription ?? ""));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Localized Content Has Base Metadata

These derived values localize the visible monitor content, but <svelte:head> still reads data.monitorName and data.monitorDescription. Browser titles and shared-link previews therefore remain in the default language.

Context Used: CLAUDE.md (source)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/routes/(kener)/incidents/[incident_id]/+page.svelte (1)

22-28: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use translated strings for SEO and page metadata.

The <title> and <meta> tags currently render the raw, untranslated fallback strings (e.g., data.incident.title or data.maintenance.title). To ensure that browser tab titles and social media previews match the localized page language currently in view, apply the $lt translation helper to these properties.

  • src/routes/(kener)/incidents/[incident_id]/+page.svelte#L22-L28: Update <title> and <meta> properties (og:title, description, og:description) to use the $lt helper for evaluating translations on data.incident.title and data.comments[0].comment.
  • src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte#L67-L73: Update <title> and <meta> properties (og:title, description, og:description) to use the $lt helper for evaluating translations on data.maintenance.title and data.maintenance.description.
💡 Proposed fixes

For src/routes/(kener)/incidents/[incident_id]/+page.svelte:

-  <title>{data.incident.title + " - " + data.siteName}</title>
-  <meta property="og:title" content={data.incident.title + " - " + data.siteName} />
+  <title>{$lt(data.incident.translations, "title", data.incident.title) + " - " + data.siteName}</title>
+  <meta property="og:title" content={$lt(data.incident.translations, "title", data.incident.title) + " - " + data.siteName} />
   <meta property="og:type" content="article" />
   <meta name="twitter:card" content="summary_large_image" />
   {`#if` data.comments.length > 0}
-    <meta name="description" content={data.comments[0].comment} />
-    <meta property="og:description" content={data.comments[0].comment} />
+    <meta name="description" content={$lt(data.comments[0].translations, "comment", data.comments[0].comment)} />
+    <meta property="og:description" content={$lt(data.comments[0].translations, "comment", data.comments[0].comment)} />
   {/if}

For src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte:

-  <title>{data.maintenance.title + " - " + data.siteName}</title>
-  <meta property="og:title" content={data.maintenance.title + " - " + data.siteName} />
+  <title>{$lt(data.maintenance.translations, "title", data.maintenance.title) + " - " + data.siteName}</title>
+  <meta property="og:title" content={$lt(data.maintenance.translations, "title", data.maintenance.title) + " - " + data.siteName} />
   <meta property="og:type" content="article" />
   <meta name="twitter:card" content="summary_large_image" />
   {`#if` data.maintenance.description}
-    <meta name="description" content={data.maintenance.description} />
-    <meta property="og:description" content={data.maintenance.description} />
+    <meta name="description" content={$lt(data.maintenance.translations, "description", data.maintenance.description)} />
+    <meta property="og:description" content={$lt(data.maintenance.translations, "description", data.maintenance.description)} />
   {/if}
🤖 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 `@src/routes/`(kener)/incidents/[incident_id]/+page.svelte around lines 22 -
28, Update the incident metadata in
src/routes/(kener)/incidents/[incident_id]/+page.svelte at lines 22-28 to
evaluate data.incident.title and data.comments[0].comment through the $lt
translation helper for the title, og:title, description, and og:description.
Apply the same change in
src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte at lines 67-73,
using $lt for data.maintenance.title and data.maintenance.description in the
corresponding metadata properties.
src/routes/(api)/api/v4/monitors/+server.ts (1)

118-144: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Authenticate both monitor mutation endpoints with VerifyAPIKey.

The new translation writes are handled without the route-level Bearer-token authentication required for API endpoints.

  • src/routes/(api)/api/v4/monitors/+server.ts#L118-L144: authenticate before validating or inserting the monitor.
  • src/routes/(api)/api/v4/monitors/[monitor_tag]/+server.ts#L144-L159: authenticate before applying the monitor update.

As per coding guidelines, src/routes/(api)/**/*.ts must use API authentication via VerifyAPIKey() imported from $lib/server/controllers/apiController.

🤖 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 `@src/routes/`(api)/api/v4/monitors/+server.ts around lines 118 - 144,
Authenticate both monitor mutation handlers with VerifyAPIKey from
$lib/server/controllers/apiController before validation or database changes.
Update src/routes/(api)/api/v4/monitors/+server.ts lines 118-144 and
src/routes/(api)/api/v4/monitors/[monitor_tag]/+server.ts lines 144-159;
preserve the existing request handling after successful authentication.

Source: Coding guidelines

src/lib/server/controllers/monitorsController.ts (1)

283-303: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not retain the source monitor’s translated name.

The clone receives newName, but source.translations may still contain the source "name" in every locale. Public localized views will therefore show the old monitor name. Remove translated name entries or require translated names for the clone; translated descriptions can still be copied.

🤖 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 `@src/lib/server/controllers/monitorsController.ts` around lines 283 - 303,
Update the monitor clone construction in the controller’s db.insertMonitor call
so source.translations does not retain localized “name” entries when using
newNameTrimmed. Remove or replace translated name values while preserving
translated descriptions and other translation data.
🤖 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 @.github/workflows/test.yml:
- Line 21: Update the workflow’s actions/checkout, actions/setup-node, and
actions/cache uses entries to reference audited immutable commit SHAs instead of
mutable version tags, while retaining the corresponding action version in an
inline comment for readability.

In `@CLAUDE.md`:
- Line 25: Update the component test setup note in CLAUDE.md to include a
Linux-specific dependency installation step using `npx playwright install
--with-deps chromium`, while retaining the existing one-time Chromium
installation guidance for other environments.

In `@src/lib/client/manage-locales.ts`:
- Around line 15-23: Update the locale-discovery request before response.json()
in the manage-locales flow to validate response.ok and reject failed HTTP
responses, including 401, 403, and 500 statuses, instead of falling back to the
English-only configuration. Preserve the existing parsing and locale handling
for successful responses.

In `@static/api-references/v4.json`:
- Around line 1860-1871: Update the Incident, IncidentComment, and Maintenance
schema definitions in v4.json to include translations and is_global wherever
those API payloads and request models support them, including
CreateIncidentRequest and UpdateMaintenanceRequest. Reuse the existing Monitor
translations definition and the established is_global type, while preserving
strict additionalProperties validation.

---

Outside diff comments:
In `@src/lib/server/controllers/monitorsController.ts`:
- Around line 283-303: Update the monitor clone construction in the controller’s
db.insertMonitor call so source.translations does not retain localized “name”
entries when using newNameTrimmed. Remove or replace translated name values
while preserving translated descriptions and other translation data.

In `@src/routes/`(api)/api/v4/monitors/+server.ts:
- Around line 118-144: Authenticate both monitor mutation handlers with
VerifyAPIKey from $lib/server/controllers/apiController before validation or
database changes. Update src/routes/(api)/api/v4/monitors/+server.ts lines
118-144 and src/routes/(api)/api/v4/monitors/[monitor_tag]/+server.ts lines
144-159; preserve the existing request handling after successful authentication.

In `@src/routes/`(kener)/incidents/[incident_id]/+page.svelte:
- Around line 22-28: Update the incident metadata in
src/routes/(kener)/incidents/[incident_id]/+page.svelte at lines 22-28 to
evaluate data.incident.title and data.comments[0].comment through the $lt
translation helper for the title, og:title, description, and og:description.
Apply the same change in
src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte at lines 67-73,
using $lt for data.maintenance.title and data.maintenance.description in the
corresponding metadata properties.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f9fad65b-2f99-4ba2-ba3d-397128ebb0c9

📥 Commits

Reviewing files that changed from the base of the PR and between e5b745e and ab35a29.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (49)
  • .gitattributes
  • .github/workflows/test.yml
  • .gitignore
  • CLAUDE.md
  • migrations/20260716120000_add_content_translations.ts
  • package.json
  • src/lib/client/manage-locales.ts
  • src/lib/components/CopyButton.svelte.test.ts
  • src/lib/components/IncidentItem.svelte
  • src/lib/components/MaintenanceItem.svelte
  • src/lib/components/MonitorBar.svelte
  • src/lib/components/StatusBarCalendar.svelte.test.ts
  • src/lib/components/manage/TranslationsButton.svelte
  • src/lib/content-i18n.test.ts
  • src/lib/content-i18n.ts
  • src/lib/server/api-server/monitor-bar/get.ts
  • src/lib/server/api-server/monitor-bar/shared.ts
  • src/lib/server/content-i18n.test.ts
  • src/lib/server/content-i18n.ts
  • src/lib/server/controllers/incidentController.ts
  • src/lib/server/controllers/maintenanceController.ts
  • src/lib/server/controllers/monitorsController.ts
  • src/lib/server/db/repositories/incidents.ts
  • src/lib/server/db/repositories/maintenances.ts
  • src/lib/server/db/repositories/monitors.ts
  • src/lib/server/tool.test.ts
  • src/lib/server/types/db.ts
  • src/lib/stores/i18n.test.ts
  • src/lib/stores/i18n.ts
  • src/lib/types/api.ts
  • src/lib/types/common.ts
  • src/routes/(api)/api/v4/incidents/[incident_id]/+server.ts
  • src/routes/(api)/api/v4/incidents/[incident_id]/comments/+server.ts
  • src/routes/(api)/api/v4/incidents/[incident_id]/comments/[comment_id]/+server.ts
  • src/routes/(api)/api/v4/monitors/+server.ts
  • src/routes/(api)/api/v4/monitors/[monitor_tag]/+server.ts
  • src/routes/(kener)/incidents/[incident_id]/+page.svelte
  • src/routes/(kener)/maintenances/[maintenance_id]/+page.server.ts
  • src/routes/(kener)/maintenances/[maintenance_id]/+page.svelte
  • src/routes/(kener)/monitors/[monitor_tag]/+page.server.ts
  • src/routes/(kener)/monitors/[monitor_tag]/+page.svelte
  • src/routes/(manage)/manage/api/+server.ts
  • src/routes/(manage)/manage/app/incidents/[incident_id]/+page.svelte
  • src/routes/(manage)/manage/app/maintenances/[id]/+page.svelte
  • src/routes/(manage)/manage/app/monitors/[tag]/+page.svelte
  • src/routes/(manage)/manage/app/monitors/[tag]/components/GeneralSettingsCard.svelte
  • static/api-references/v4.json
  • vite.config.ts
  • vitest-setup-client.ts

contents: read
steps:
- name: Checkout
uses: actions/checkout@v4.2.2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- .github/workflows/test.yml ---\n'
nl -ba .github/workflows/test.yml | sed -n '1,120p'

printf '\n--- search for pinning policy / workflow comments ---\n'
rg -n --hidden -S "pinning|action-pinning|checkout@|setup-node@|actions/cache@" .github/workflows .github README.md . | sed -n '1,200p'

Repository: rajnandan1/kener

Length of output: 245


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- .github/workflows/test.yml ---'
nl -ba .github/workflows/test.yml | sed -n '1,120p'

printf '\n%s\n' '--- search for pinning policy / workflow comments ---'
rg -n --hidden -S "pinning|action-pinning|checkout@|setup-node@|actions/cache@" .github/workflows .github README.md . | sed -n '1,200p'

Repository: rajnandan1/kener

Length of output: 229


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- .github/workflows/test.yml ---'
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/test.yml')
for i, line in enumerate(p.read_text().splitlines(), 1):
    if i <= 120:
        print(f"{i:4d}: {line}")
PY

printf '\n%s\n' '--- search for pinning policy / workflow references ---'
python3 - <<'PY'
from pathlib import Path
import re
targets = [Path('.github/workflows/test.yml'), Path('.github')]
for path in targets:
    if path.is_file():
        text = path.read_text(errors='ignore')
        for pat in ['checkout@', 'setup-node@', 'actions/cache@', 'pinning', 'action-pinning']:
            if pat in text:
                print(f"{path}: contains {pat}")
    else:
        for p in path.rglob('*'):
            if p.is_file() and p.suffix in {'.yml', '.yaml', '.md', '.txt'}:
                try:
                    text = p.read_text(errors='ignore')
                except Exception:
                    continue
                if any(pat in text for pat in ['pinning', 'action-pinning', 'checkout@', 'setup-node@', 'actions/cache@']):
                    print(p)
PY

Repository: rajnandan1/kener

Length of output: 2067


Pin the workflow actions to commit SHAs. actions/checkout, actions/setup-node, and actions/cache are still referenced by mutable tags, so they can change without a repo diff. Pin each to an audited SHA and keep the version in a comment.

Also applies to: 26-26, 39-39

🧰 Tools
🪛 zizmor (1.26.1)

[error] 21-21: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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 @.github/workflows/test.yml at line 21, Update the workflow’s
actions/checkout, actions/setup-node, and actions/cache uses entries to
reference audited immutable commit SHAs instead of mutable version tags, while
retaining the corresponding action version in an inline comment for readability.

Source: Linters/SAST tools

Comment thread CLAUDE.md
npm run test:watch # Watch mode
```

Component tests need a one-time `npx playwright install chromium`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## FILES\n'
git ls-files CLAUDE.md package.json .github/workflows/test.yml .claude/skills/documentation-writer/SKILL.md

for f in CLAUDE.md package.json .github/workflows/test.yml .claude/skills/documentation-writer/SKILL.md; do
  if [ -f "$f" ]; then
    printf '\n## %s (%s lines)\n' "$f" "$(wc -l < "$f")"
  fi
done

printf '\n## CLAUDE.md excerpt\n'
sed -n '1,80p' CLAUDE.md

printf '\n## package.json excerpt\n'
sed -n '1,240p' package.json

printf '\n## test workflow excerpt\n'
sed -n '1,240p' .github/workflows/test.yml

if [ -f .claude/skills/documentation-writer/SKILL.md ]; then
  printf '\n## documentation skill excerpt\n'
  sed -n '1,220p' .claude/skills/documentation-writer/SKILL.md
fi

Repository: rajnandan1/kener

Length of output: 14842


🌐 Web query:

Playwright install --with-deps chromium Linux system dependencies official docs

💡 Result:

To install the Chromium browser along with its required Linux system dependencies using Playwright, you can use the following command: npx playwright install --with-deps chromium [1][2] This command performs two actions: it downloads the Chromium browser binary and automatically installs the necessary operating system-level packages required to run it on your Linux environment [1][2]. Key points regarding this process: - Usage: This command is particularly useful in Continuous Integration (CI) environments where you need to ensure the environment is correctly configured to run browser automation [1][3]. - Targeted Installation: You can install dependencies for a specific browser (like chromium) as shown above, or you can run npx playwright install-deps to install system dependencies for all browsers supported by your current Playwright version [1][2]. - Proxy Configuration: If your Linux environment requires a proxy, you must run the command as a root user (e.g., using sudo). If not run as root, Playwright's attempt to elevate privileges may prevent it from correctly passing environment variables like HTTPS_PROXY to the system's package manager [1][4]. - Underlying Mechanism: Playwright uses internal tooling to identify missing shared libraries (via ldd) and maps them to the appropriate package names for your specific Linux distribution, ensuring the browser can launch successfully [5]. For official information regarding supported operating systems and further details on browser management, refer to the official Playwright documentation on browsers [1][6].

Citations:


Document the Linux Playwright dependency step npx playwright install chromium still misses the Linux system packages needed to run component tests on clean machines; CI already uses npx playwright install --with-deps chromium. Add a Linux-specific note here.

🤖 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 `@CLAUDE.md` at line 25, Update the component test setup note in CLAUDE.md to
include a Linux-specific dependency installation step using `npx playwright
install --with-deps chromium`, while retaining the existing one-time Chromium
installation guidance for other environments.

Comment on lines +15 to +23
const response = await fetch(clientResolver(resolve, "/manage/api"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "getAllSiteData" }),
});
const result = await response.json();
const names = new Map(availableLocalesList.map((l) => [l.code, l.name]));
const defaultLocale: string = result?.i18n?.defaultLocale || "en";
const enabled: { code: string; name?: string; selected?: boolean }[] = result?.i18n?.locales || [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Reject failed locale-discovery responses.

A 401/403/500 response is currently treated as a valid English-only configuration, silently hiding translation controls. Check response.ok before parsing.

Proposed fix
   const response = await fetch(clientResolver(resolve, "/manage/api"), {
     method: "POST",
     headers: { "Content-Type": "application/json" },
     body: JSON.stringify({ action: "getAllSiteData" }),
   });
+  if (!response.ok) {
+    throw new Error(`Failed to fetch translatable locales (${response.status})`);
+  }
   const result = await response.json();
📝 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.

Suggested change
const response = await fetch(clientResolver(resolve, "/manage/api"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "getAllSiteData" }),
});
const result = await response.json();
const names = new Map(availableLocalesList.map((l) => [l.code, l.name]));
const defaultLocale: string = result?.i18n?.defaultLocale || "en";
const enabled: { code: string; name?: string; selected?: boolean }[] = result?.i18n?.locales || [];
const response = await fetch(clientResolver(resolve, "/manage/api"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "getAllSiteData" }),
});
if (!response.ok) {
throw new Error(`Failed to fetch translatable locales (${response.status})`);
}
const result = await response.json();
const names = new Map(availableLocalesList.map((l) => [l.code, l.name]));
const defaultLocale: string = result?.i18n?.defaultLocale || "en";
const enabled: { code: string; name?: string; selected?: boolean }[] = result?.i18n?.locales || [];
🤖 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 `@src/lib/client/manage-locales.ts` around lines 15 - 23, Update the
locale-discovery request before response.json() in the manage-locales flow to
validate response.ok and reject failed HTTP responses, including 401, 403, and
500 statuses, instead of falling back to the English-only configuration.
Preserve the existing parsing and locale handling for successful responses.

Comment on lines +1860 to +1871
"translations": {
"oneOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"description": "Per-locale content translations, keyed by locale code, e.g. {\"de\": {\"name\": \"...\"}}"
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Add translations and is_global to Incident, IncidentComment, and Maintenance schemas.

While translations has been correctly added to the Monitor request and response schemas, it is missing from the Incident, IncidentComment, and Maintenance schemas (e.g., CreateIncidentRequest, UpdateMaintenanceRequest).

Additionally, the is_global field has been added to incident and maintenance API payloads in this PR but is missing from their respective request schemas here. Since these request schemas enforce "additionalProperties": false, omitting these properties will cause strict API validators and generated SDKs to reject requests containing them.

🤖 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 `@static/api-references/v4.json` around lines 1860 - 1871, Update the Incident,
IncidentComment, and Maintenance schema definitions in v4.json to include
translations and is_global wherever those API payloads and request models
support them, including CreateIncidentRequest and UpdateMaintenanceRequest.
Reuse the existing Monitor translations definition and the established is_global
type, while preserving strict additionalProperties validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant