Skip to content

feat: add Cloudflare Worker check-in console - #7

Open
zhikanyeye wants to merge 16 commits into
Jasonliu-0:mainfrom
zhikanyeye:main
Open

feat: add Cloudflare Worker check-in console#7
zhikanyeye wants to merge 16 commits into
Jasonliu-0:mainfrom
zhikanyeye:main

Conversation

@zhikanyeye

@zhikanyeye zhikanyeye commented Jul 22, 2026

Copy link
Copy Markdown

Co-authored-by: monkeycode-ai monkeycode-ai@chaitin.com

Summary by CodeRabbit

  • New Features
    • Added a Cloudflare Worker “Check Console” with login, encrypted account storage (D1), run history, success summaries, and per-account enable/disable controls.
    • Added runner-based execution that fetches enabled accounts and reports aggregated results back to the console.
  • Documentation
    • Rewrote README for the Worker + D1 architecture; added WORKER_DEPLOYMENT.md and FIRST_RUN.md.
    • Updated the environment examples and setup guides for the new Worker URL + runner token flow.
  • Improvements
    • Improved check-in result normalization and handling of “already checked in” across response variants.
  • Chores
    • Added local dev vars template and worker project scaffolding; updated .gitignore and refreshed license header.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The project now uses a Cloudflare Worker with D1-backed encrypted account storage, authenticated dashboard APIs, a static management console, and Python Runner integration for fetching configurations and reporting check-in results.

Changes

Worker platform and check-in integration

Layer / File(s) Summary
Worker foundation and persistence
worker/package.json, worker/wrangler.toml, worker/schema.sql, worker/.dev.vars.example, .gitignore, package.json
Adds Wrangler configuration, local development settings, deployment scripts, and D1 tables for accounts, runs, results, and sessions.
Worker API and request routing
worker/src/index.js
Adds health, login, dashboard, and Runner endpoints with session or Runner-token authorization, encrypted account handling, static asset serving, and run-result persistence.
Dashboard console
worker/public/index.html
Adds login, account management, run history, summary statistics, and enable/disable controls backed by Worker APIs.
Runner configuration and reporting
checkin.py, cf_bypass.py, .env.example, .github/workflows/checkin.yml
Normalizes check-in responses, loads enabled accounts from the Worker, reports execution results with account identifiers, and passes Worker credentials through Actions.
Deployment and project documentation
README.md, WORKER_DEPLOYMENT.md, FIRST_RUN.md, config_generator.html, LICENSE
Documents Worker deployment, D1 setup, environment bindings, Runner connection, APIs, local execution, compatibility behavior, first-run validation, and updated branding.

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

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard
  participant Worker
  participant D1
  participant Runner
  Dashboard->>Worker: Login and request dashboard data
  Worker->>D1: Store session hash and query records
  Runner->>Worker: Fetch enabled account configuration
  Worker->>D1: Read encrypted account records
  Worker-->>Runner: Return decrypted configuration
  Runner->>Worker: Report check-in results
  Worker->>D1: Store run and per-account results
Loading

Suggested reviewers: jasonliu-0

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 clearly summarizes the main change: adding a Cloudflare Worker-based check-in console.
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.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>

@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: 8

Caution

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

⚠️ Outside diff range comments (2)
checkin.py (1)

637-652: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve Worker account_id during account parsing.

load_config_from_worker() receives account_id, but parse_accounts() drops it while rebuilding each account object. Consequently these fields are always None; the Worker falls back to matching by name (worker/src/index.js, Lines 78–105), which can associate results with the wrong account when names repeat.

Proposed fix
                     account = {
                         'url': item['url'],
                         'session': item['session'],
-                        'name': item.get('name', '')
+                        'name': item.get('name', ''),
+                        'account_id': item.get('account_id'),
                     }
🤖 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 `@checkin.py` around lines 637 - 652, Update parse_accounts() to retain and
propagate the account_id received from load_config_from_worker() when rebuilding
each account object, so downstream success and failure results use the original
identifier instead of None or name-based matching.
worker/wrangler.toml (1)

1-12: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add the D1 binding for env.Check. worker/wrangler.toml still has no [[d1_databases]] entry, but worker/src/index.js uses env.Check for login, runner, and dashboard queries. Wire the newapi-checkin database here so those routes can run.

🤖 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 `@worker/wrangler.toml` around lines 1 - 12, Add a [[d1_databases]]
configuration for the newapi-checkin database in wrangler.toml, binding it as
Check to match the env.Check references in the login, runner, and dashboard
routes in src/index.js. Use the database’s existing D1 identifier and preserve
the current assets and vars configuration.
🧹 Nitpick comments (3)
README.md (1)

145-154: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the dashboard read endpoints.

The table omits GET /api/dashboard/accounts and GET /api/dashboard/runs/:id, although the Worker exposes both. Add them so the documented API contract is complete.

🤖 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 `@README.md` around lines 145 - 154, Update the README API table to document
the missing dashboard read endpoints: GET /api/dashboard/accounts for listing
accounts and GET /api/dashboard/runs/:id for retrieving a run by ID. Include
their Dashboard Token authentication requirement and concise usage descriptions,
while preserving the existing endpoint entries.
worker/src/index.js (1)

33-49: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Redundant key (re)derivation on every encrypt/decrypt call.

Both encrypt and decrypt re-hash env.DATA_ENCRYPTION_KEY and re-import the AES-GCM key on every call. This is called once per account inside the loop at for (const row of rows.results) accounts.push({ ...JSON.parse(await decrypt(row.secret, env)), name: row.name, account_id: row.id }); — for N accounts that's N redundant digest+import cycles for the same static key. Derive the key once per request (or memoize it) and pass it into encrypt/decrypt.

🤖 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 `@worker/src/index.js` around lines 33 - 49, Refactor encrypt and decrypt to
accept a previously derived AES-GCM CryptoKey instead of hashing
env.DATA_ENCRYPTION_KEY and importing the key on every call. Derive or memoize
the key once per request before processing rows, then pass it into each
encrypt/decrypt invocation while preserving the existing encryption and
decryption behavior.
worker/schema.sql (1)

39-43: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Sessions table has no expiry-cleanup path.

sessions rows are inserted on every login (worker/src/index.js login handler) but nothing ever deletes expired rows — there's no logout endpoint or scheduled cleanup. Given expected low login volume for a personal dashboard, this is likely a slow, low-impact growth; consider periodically deleting rows where expires_at <= now() (e.g., opportunistically inside requireSession, or via a Cron Trigger) if this ever sees heavier use.

🤖 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 `@worker/schema.sql` around lines 39 - 43, Implement an expiry-cleanup path for
sessions by deleting rows whose expires_at is at or before the current time,
preferably opportunistically in requireSession or through an existing scheduled
worker mechanism. Ensure cleanup runs periodically without disrupting
valid-session checks and preserves the sessions table schema and login behavior.
🤖 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 `@checkin.py`:
- Around line 556-558: Update the missing-account error handling near
accounts_str to mention all supported configuration sources:
CHECKIN_WORKER_URL/CHECKIN_RUNNER_TOKEN, CONFIG_URL/CONFIG_AUTH, and
NEWAPI_ACCOUNTS, so users of fallback configurations receive actionable
guidance.

In `@README.md`:
- Line 26: Update the GitHub Actions edge label in the README diagram from
encrypted-account wording to “获取启用账号配置”, and clarify nearby documentation that
encryption applies to storage at rest while the Worker returns decrypted account
JSON to the Runner.

In `@WORKER_DEPLOYMENT.md`:
- Around line 58-61: Make the documented D1 database name configurable in all
initialization commands: update WORKER_DEPLOYMENT.md lines 58-61 and 320-323,
plus README.md lines 53-59, to use a database-name placeholder or clearly
instruct readers to substitute their chosen name for both remote and local
commands.

In `@worker/public/index.html`:
- Line 17: Validate runner-supplied count fields as finite non-negative integers
in the report handler around the dashboard persistence logic, rejecting or
sanitizing invalid values before storage. In dashboard() within
worker/public/index.html, escape or numeric-coerce latest.success_count,
latest.fail_count, latest.total, and each history run’s success_count,
fail_count, and total before interpolating them into innerHTML; preserve the
existing displayed counts and success-rate behavior for valid values.

In `@worker/schema.sql`:
- Around line 1-13: The accounts schema at worker/schema.sql lines 1-13 must
enforce unique account names by adding a UNIQUE constraint to accounts.name. In
the account-creation flow around the insertion handler at worker/src/index.js
lines 128-135, check for an existing account with the same name before inserting
and return a 409 or validation error to the dashboard when found; otherwise
preserve the existing insert behavior.

In `@worker/src/index.js`:
- Around line 20-22: Replace the plain secret comparisons in requireRunner and
the login check with timing-safe comparisons: hash both the supplied and
configured tokens/passwords using the existing sha256 helper, then compare the
resulting digests without direct string comparison. Preserve the current
authentication outcomes, including rejection of missing or invalid credentials.
- Around line 68-76: Implement rate limiting for the `/api/auth/login` branch
before validating the password, tracking failed attempts by client IP (or an
equivalent persistent identifier) in the existing D1/KV storage. Apply
exponential backoff or a lockout window, increment and persist failures for
invalid passwords, and clear the tracking record after successful authentication
while preserving the existing session creation flow.
- Around line 146-159: Update the catch block in the default export’s fetch
method to log the caught error server-side with console.error, then return a
generic internal-error message instead of exposing error.message to clients.

---

Outside diff comments:
In `@checkin.py`:
- Around line 637-652: Update parse_accounts() to retain and propagate the
account_id received from load_config_from_worker() when rebuilding each account
object, so downstream success and failure results use the original identifier
instead of None or name-based matching.

In `@worker/wrangler.toml`:
- Around line 1-12: Add a [[d1_databases]] configuration for the newapi-checkin
database in wrangler.toml, binding it as Check to match the env.Check references
in the login, runner, and dashboard routes in src/index.js. Use the database’s
existing D1 identifier and preserve the current assets and vars configuration.

---

Nitpick comments:
In `@README.md`:
- Around line 145-154: Update the README API table to document the missing
dashboard read endpoints: GET /api/dashboard/accounts for listing accounts and
GET /api/dashboard/runs/:id for retrieving a run by ID. Include their Dashboard
Token authentication requirement and concise usage descriptions, while
preserving the existing endpoint entries.

In `@worker/schema.sql`:
- Around line 39-43: Implement an expiry-cleanup path for sessions by deleting
rows whose expires_at is at or before the current time, preferably
opportunistically in requireSession or through an existing scheduled worker
mechanism. Ensure cleanup runs periodically without disrupting valid-session
checks and preserves the sessions table schema and login behavior.

In `@worker/src/index.js`:
- Around line 33-49: Refactor encrypt and decrypt to accept a previously derived
AES-GCM CryptoKey instead of hashing env.DATA_ENCRYPTION_KEY and importing the
key on every call. Derive or memoize the key once per request before processing
rows, then pass it into each encrypt/decrypt invocation while preserving the
existing encryption and decryption behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef0fee84-1a7e-4095-8135-647b3050c13b

📥 Commits

Reviewing files that changed from the base of the PR and between 9ab62be and 605f64f.

📒 Files selected for processing (15)
  • .env.example
  • .github/workflows/checkin.yml
  • .gitignore
  • LICENSE
  • README.md
  • WORKER_DEPLOYMENT.md
  • checkin.py
  • config_generator.html
  • index.html
  • worker/.dev.vars.example
  • worker/package.json
  • worker/public/index.html
  • worker/schema.sql
  • worker/src/index.js
  • worker/wrangler.toml

Comment thread checkin.py
Comment on lines 556 to +558
if not accounts_str:
print('[错误] 未配置账号信息')
print('请设置 CONFIG_URL(云端配置)或 NEWAPI_ACCOUNTS(本地配置)环境变量')
print('请设置 CHECKIN_WORKER_URL 和 CHECKIN_RUNNER_TOKEN 环境变量')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Mention the supported fallback configuration sources.

CONFIG_URL/CONFIG_AUTH and NEWAPI_ACCOUNTS remain valid fallbacks, but this error tells users to configure only Worker variables. List all supported sources so compatibility users receive an actionable error.

🤖 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 `@checkin.py` around lines 556 - 558, Update the missing-account error handling
near accounts_str to mention all supported configuration sources:
CHECKIN_WORKER_URL/CHECKIN_RUNNER_TOKEN, CONFIG_URL/CONFIG_AUTH, and
NEWAPI_ACCOUNTS, so users of fallback configurations receive actionable
guidance.

Comment thread README.md Outdated
Comment thread WORKER_DEPLOYMENT.md Outdated
Comment thread worker/public/index.html Outdated
Comment thread worker/schema.sql
Comment on lines +1 to +13
CREATE TABLE IF NOT EXISTS accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
url TEXT NOT NULL,
secret TEXT NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1,
failure_count INTEGER NOT NULL DEFAULT 0,
last_status TEXT,
last_message TEXT,
last_checkin_at TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);

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 | 🟡 Minor | ⚡ Quick win

Duplicate account names can misattribute check-in results.

Nothing enforces uniqueness on accounts.name, and /api/runner/report's fallback lookup (SELECT id, failure_count FROM accounts WHERE name = ? at worker/src/index.js line 95) will silently pick an arbitrary match via .first() if two accounts share a name, corrupting failure_count/last_status updates and run-result attribution for the wrong account.

  • worker/schema.sql#L1-L13: add UNIQUE on the name column of accounts.
  • worker/src/index.js#L128-L135: check for an existing account with the same name before inserting and return a 409/validation error to the dashboard instead of allowing silent duplicates.
📍 Affects 2 files
  • worker/schema.sql#L1-L13 (this comment)
  • worker/src/index.js#L128-L135
🤖 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 `@worker/schema.sql` around lines 1 - 13, The accounts schema at
worker/schema.sql lines 1-13 must enforce unique account names by adding a
UNIQUE constraint to accounts.name. In the account-creation flow around the
insertion handler at worker/src/index.js lines 128-135, check for an existing
account with the same name before inserting and return a 409 or validation error
to the dashboard when found; otherwise preserve the existing insert behavior.

Comment thread worker/src/index.js
Comment on lines +20 to +22
async function requireRunner(request, env) {
return tokenFrom(request) && tokenFrom(request) === env.RUNNER_TOKEN;
}

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 | 🟡 Minor | ⚡ Quick win

Non-constant-time secret comparisons.

Both async function requireRunner(request, env) {
return tokenFrom(request) && tokenFrom(request) === env.RUNNER_TOKEN;
} and the login check body.password !== env.DASHBOARD_PASSWORD use plain string comparison, which leaks timing information proportional to matched prefix length. sha256 is already available in this file — hash both sides (or use a constant-time byte comparison) before comparing.

🔒 Timing-safe comparison
 async function requireRunner(request, env) {
-  return tokenFrom(request) && tokenFrom(request) === env.RUNNER_TOKEN;
+  const token = tokenFrom(request);
+  if (!token || !env.RUNNER_TOKEN) return false;
+  return (await sha256(token)) === (await sha256(env.RUNNER_TOKEN));
 }

Also applies to: 68-76

🤖 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 `@worker/src/index.js` around lines 20 - 22, Replace the plain secret
comparisons in requireRunner and the login check with timing-safe comparisons:
hash both the supplied and configured tokens/passwords using the existing sha256
helper, then compare the resulting digests without direct string comparison.
Preserve the current authentication outcomes, including rejection of missing or
invalid credentials.

Comment thread worker/src/index.js
Comment on lines +68 to +76
if (method === 'POST' && path === '/api/auth/login') {
const body = await text(request);
if (!body?.password || body.password !== env.DASHBOARD_PASSWORD) return json({ error: '访问口令错误' }, 401, env);
const token = crypto.randomUUID();
const expires = new Date(Date.now() + Number(env.SESSION_TTL_SECONDS || 86400) * 1000).toISOString();
await env.Check.prepare('INSERT INTO sessions (token_hash, expires_at, created_at) VALUES (?, ?, ?)')
.bind(await sha256(token), expires, now()).run();
return json({ token, expires_at: expires }, 200, env);
}

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 | 🏗️ Heavy lift

No rate limiting/lockout on /api/auth/login.

The password check has no throttling, so an attacker can brute-force DASHBOARD_PASSWORD with unlimited attempts against a public endpoint. Consider tracking failed attempts (e.g., per-IP or globally in D1/KV) with exponential backoff or a hard lockout window.

🤖 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 `@worker/src/index.js` around lines 68 - 76, Implement rate limiting for the
`/api/auth/login` branch before validating the password, tracking failed
attempts by client IP (or an equivalent persistent identifier) in the existing
D1/KV storage. Apply exponential backoff or a lockout window, increment and
persist failures for invalid passwords, and clear the tracking record after
successful authentication while preserving the existing session creation flow.

Comment thread worker/src/index.js
Comment on lines +146 to +159
export default {
async fetch(request, env) {
try {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/')) return await handler(request, env);
if (env.ASSETS) {
const assetUrl = new URL(request.url);
if (assetUrl.pathname === '/' || assetUrl.pathname === '/dashboard.html') assetUrl.pathname = '/index.html';
return env.ASSETS.fetch(new Request(assetUrl, request));
}
return json({ error: '静态资源绑定未配置' }, 500, env);
} catch (error) {
return json({ error: error.message || 'Internal error' }, 500, env);
}

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 | 🟡 Minor | ⚡ Quick win

Raw internal error messages returned to clients.

} catch (error) {
return json({ error: error.message || 'Internal error' }, 500, env);
} exposes internal exception text (D1 errors, decrypt failures, etc.) directly in the API response. Log the error server-side (e.g., console.error) and return a generic message to callers.

🛡️ Sanitize error response
     } catch (error) {
-      return json({ error: error.message || 'Internal error' }, 500, env);
+      console.error('Worker error:', error);
+      return json({ error: 'Internal error' }, 500, env);
     }
📝 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
export default {
async fetch(request, env) {
try {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/')) return await handler(request, env);
if (env.ASSETS) {
const assetUrl = new URL(request.url);
if (assetUrl.pathname === '/' || assetUrl.pathname === '/dashboard.html') assetUrl.pathname = '/index.html';
return env.ASSETS.fetch(new Request(assetUrl, request));
}
return json({ error: '静态资源绑定未配置' }, 500, env);
} catch (error) {
return json({ error: error.message || 'Internal error' }, 500, env);
}
export default {
async fetch(request, env) {
try {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/')) return await handler(request, env);
if (env.ASSETS) {
const assetUrl = new URL(request.url);
if (assetUrl.pathname === '/' || assetUrl.pathname === '/dashboard.html') assetUrl.pathname = '/index.html';
return env.ASSETS.fetch(new Request(assetUrl, request));
}
return json({ error: '静态资源绑定未配置' }, 500, env);
} catch (error) {
console.error('Worker error:', error);
return json({ error: 'Internal error' }, 500, env);
}
🤖 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 `@worker/src/index.js` around lines 146 - 159, Update the catch block in the
default export’s fetch method to log the caught error server-side with
console.error, then return a generic internal-error message instead of exposing
error.message to clients.

@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: 3

🧹 Nitpick comments (1)
worker/public/index.html (1)

247-264: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Session token stored in localStorage is readable by any injected script.

Static analysis flags storing data.token via localStorage.setItem (used later by api() for the Authorization header) as persistent, JS-readable storage (CWE-312). Given the query APIs already withhold session/ciphertext per the form note at line 396, actual exposure is limited to account-management actions, but consider sessionStorage (tab-scoped, cleared on close) as a low-cost improvement, or a Worker-set httpOnly cookie for stronger protection if Worker-side changes are acceptable.

🤖 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 `@worker/public/index.html` around lines 247 - 264, Replace the persistent
localStorage usage for the session token with tab-scoped sessionStorage,
updating the token read/write/remove logic used by api(), login, and
clearSession() consistently. Preserve the existing Authorization header behavior
and session-expiration handling; do not leave token access dependent on
localStorage.

Source: Linters/SAST tools

🤖 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 `@README.md`:
- Line 89: Update the repository reference in the README deployment instructions
so it points to the deployer’s fork or their own copied repository rather than
the upstream zhikanyeye/Newapi-checkin repository. Preserve the existing table
formatting and surrounding deployment guidance.
- Around line 159-160: Update the dashboard account API table in README.md to
document the account deletion endpoint alongside the existing POST and PATCH
entries, including its HTTP method, route, authentication requirement, and
delete-account description.

In `@worker/public/index.html`:
- Around line 231-238: Update formatTime so all timezone-less timestamp strings
use one consistent timezone interpretation, regardless of whether they contain a
space or an ISO-style “T” separator. Preserve explicit timezone offsets and
Z-suffixed values, and keep the existing invalid-date fallback and zh-CN
formatting behavior.

---

Nitpick comments:
In `@worker/public/index.html`:
- Around line 247-264: Replace the persistent localStorage usage for the session
token with tab-scoped sessionStorage, updating the token read/write/remove logic
used by api(), login, and clearSession() consistently. Preserve the existing
Authorization header behavior and session-expiration handling; do not leave
token access dependent on localStorage.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1b3f0070-33d8-4f25-9a97-38bb98b8daaf

📥 Commits

Reviewing files that changed from the base of the PR and between 605f64f and d2efb50.

📒 Files selected for processing (8)
  • .env.example
  • README.md
  • WORKER_DEPLOYMENT.md
  • config_generator.html
  • index.html
  • worker/.dev.vars.example
  • worker/public/index.html
  • worker/src/index.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • worker/.dev.vars.example
  • WORKER_DEPLOYMENT.md
  • worker/src/index.js

Comment thread README.md
- 其他非 JSON 内容
| 设置 | 值 |
|------|----|
| Repository | `zhikanyeye/Newapi-checkin` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the deployer’s fork instead of the upstream repository.

Line 89 directs users to connect Workers Builds to zhikanyeye/Newapi-checkin, so fork deployments will build upstream rather than the user’s copy.

Proposed fix
-| Repository | `zhikanyeye/Newapi-checkin` |
+| Repository | 选择你自己的 Fork 仓库(例如 `<your-account>/Newapi-checkin`) |
📝 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
| Repository | `zhikanyeye/Newapi-checkin` |
| Repository | 选择你自己的 Fork 仓库(例如 `<your-account>/Newapi-checkin` |
🤖 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 `@README.md` at line 89, Update the repository reference in the README
deployment instructions so it points to the deployer’s fork or their own copied
repository rather than the upstream zhikanyeye/Newapi-checkin repository.
Preserve the existing table formatting and surrounding deployment guidance.

Comment thread README.md Outdated
Comment on lines +159 to +160
| `POST` | `/api/dashboard/accounts` | Dashboard Token | 添加加密账号 |
| `PATCH` | `/api/dashboard/accounts/:id` | Dashboard Token | 启用或停用账号 |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Document the delete-account endpoint.

The overview describes account add/delete/enablement support, but lists only POST and PATCH. Add the dashboard deletion route so operators can discover it.

Proposed fix
 | `POST` | `/api/dashboard/accounts` | Dashboard Token | 添加加密账号 |
 | `PATCH` | `/api/dashboard/accounts/:id` | Dashboard Token | 启用或停用账号 |
+| `DELETE` | `/api/dashboard/accounts/:id` | Dashboard Token | 删除账号 |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| `POST` | `/api/dashboard/accounts` | Dashboard Token | 添加加密账号 |
| `PATCH` | `/api/dashboard/accounts/:id` | Dashboard Token | 启用或停用账号 |
| `POST` | `/api/dashboard/accounts` | Dashboard Token | 添加加密账号 |
| `PATCH` | `/api/dashboard/accounts/:id` | Dashboard Token | 启用或停用账号 |
| `DELETE` | `/api/dashboard/accounts/:id` | Dashboard Token | 删除账号 |
🤖 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 `@README.md` around lines 159 - 160, Update the dashboard account API table in
README.md to document the account deletion endpoint alongside the existing POST
and PATCH entries, including its HTTP method, route, authentication requirement,
and delete-account description.

Comment thread worker/public/index.html
Comment on lines +231 to +238
function formatTime(value) {
if (!value) return '尚未运行';
const date = new Date(value.includes('T') ? value : value.replace(' ', 'T') + '+08:00');
if (Number.isNaN(date.getTime())) return value;
return new Intl.DateTimeFormat('zh-CN', {
month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false,
}).format(date);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how timestamps are generated/stored in the Worker to confirm timezone assumptions.
rg -n "execution_time|last_checkin_at|CURRENT_TIMESTAMP|toISOString|new Date\(\)" worker/src/index.js worker/schema.sql

Repository: Jasonliu-0/Newapi-checkin

Length of output: 1081


Hardcoded +08:00 makes timestamp parsing inconsistent. formatTime treats strings without T as UTC+8 but leaves ISO strings without a zone to the browser’s local timezone. Since Worker timestamps are stored as toISOString() values and some fields can also come from body.execution_time, this can shift displayed times and render the same moment differently depending on string shape.

🤖 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 `@worker/public/index.html` around lines 231 - 238, Update formatTime so all
timezone-less timestamp strings use one consistent timezone interpretation,
regardless of whether they contain a space or an ISO-style “T” separator.
Preserve explicit timezone offsets and Z-suffixed values, and keep the existing
invalid-date fallback and zh-CN formatting behavior.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>

@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: 1

🤖 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 `@worker/src/index.js`:
- Around line 155-177: Make the account update flow around the enabled update
and session handling atomic: validate the URL, decrypt/encrypt the session, and
prepare all requested field values before executing any database write. Replace
the separate UPDATE statements with one UPDATE or atomic D1 batch so invalid
session requests cannot persist the enabled change, while preserving updates for
enabled-only and session-only requests.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d8b8afd-2f1d-4e55-a62c-9745c3aa6eac

📥 Commits

Reviewing files that changed from the base of the PR and between d2efb50 and 621560e.

📒 Files selected for processing (9)
  • FIRST_RUN.md
  • README.md
  • WORKER_DEPLOYMENT.md
  • checkin.py
  • config_generator.html
  • index.html
  • package.json
  • worker/public/index.html
  • worker/src/index.js
💤 Files with no reviewable changes (1)
  • index.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • worker/public/index.html

Comment thread worker/src/index.js Outdated
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Unify API payload normalization so null/nested data and "already checked in" responses are not treated as failures; pass new-api-user in CF Playwright requests.
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>

@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: 1

Caution

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

⚠️ Outside diff range comments (2)
worker/src/index.js (1)

159-160: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Preserve zero-valued check-in metrics.

|| null converts valid 0 values for quota_awarded and checkin_count into NULL, losing reported results. Use nullish coalescing instead.

Proposed fix
- .bind(run.meta.last_row_id, account?.id || null, result.name || '未知账号', result.success ? 1 : 0, result.message || '', result.quota_awarded || null, result.checkin_count || null, result.session_expired ? 1 : 0, createdAt).run();
+ .bind(run.meta.last_row_id, account?.id || null, result.name || '未知账号', result.success ? 1 : 0, result.message || '', result.quota_awarded ?? null, result.checkin_count ?? null, result.session_expired ? 1 : 0, createdAt).run();
🤖 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 `@worker/src/index.js` around lines 159 - 160, Update the parameter bindings in
the run-results INSERT within the current worker flow to use nullish fallback
for quota_awarded and checkin_count, preserving valid zero values while still
converting null or undefined values to NULL. Leave the other field mappings
unchanged.
checkin.py (1)

563-572: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Retain Worker account_id through account parsing.

The Worker returns account_id, but the JSON is subsequently passed through parse_accounts, which drops that field. Reports therefore use the Worker’s name fallback; duplicate account names can update another account’s failure/status history. Preserve account_id in parsed JSON accounts.

Proposed fix
             if 'cf_clearance' in item:
                 account['cf_clearance'] = item['cf_clearance']
+            if 'account_id' in item:
+                account['account_id'] = item['account_id']
             accounts.append(account)
🤖 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 `@checkin.py` around lines 563 - 572, Preserve each Worker-provided account_id
through the account parsing flow after the response handling in the account
configuration fetch. Update parse_accounts and its parsed-account serialization
so account_id remains available alongside the existing account fields, allowing
report updates to target the correct account instead of falling back to names.
🤖 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 `@checkin.py`:
- Around line 147-185: Update the response normalization in NewAPICheckin to
derive success_flag and message from the nested candidates built from data,
matching the existing date/quota extraction order. Ensure nested payload fields
such as data.success and data.message are honored before falling back to the
outer response, while preserving already_checked_in handling and the existing
success/message defaults.

---

Outside diff comments:
In `@checkin.py`:
- Around line 563-572: Preserve each Worker-provided account_id through the
account parsing flow after the response handling in the account configuration
fetch. Update parse_accounts and its parsed-account serialization so account_id
remains available alongside the existing account fields, allowing report updates
to target the correct account instead of falling back to names.

In `@worker/src/index.js`:
- Around line 159-160: Update the parameter bindings in the run-results INSERT
within the current worker flow to use nullish fallback for quota_awarded and
checkin_count, preserving valid zero values while still converting null or
undefined values to NULL. Leave the other field mappings unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89260676-41b1-491d-b558-412d56da1d1e

📥 Commits

Reviewing files that changed from the base of the PR and between 621560e and a13206e.

📒 Files selected for processing (3)
  • cf_bypass.py
  • checkin.py
  • worker/src/index.js

Comment thread checkin.py
Guard env.Check access, return clear D1_BINDING_MISSING errors, and document wrangler.toml [[d1_databases]] so auto-deploy does not drop the Check binding.
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>

@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: 2

Caution

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

⚠️ Outside diff range comments (1)
worker/src/index.js (1)

159-164: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

A single undecryptable account secret aborts the entire runner config fetch.

decrypt(row.secret, env) runs unguarded inside the loop. If any one enabled account's secret fails to decrypt (corrupted data, key rotation, etc.), the exception propagates out of the handler, and the Runner gets a 500 for all accounts instead of just the broken one — turning one bad row into a full outage of the scheduled check-in run.

🛠️ Proposed fix
       const accounts = [];
-      for (const row of rows.results) accounts.push({ ...JSON.parse(await decrypt(row.secret, env)), name: row.name, account_id: row.id });
+      for (const row of rows.results) {
+        try {
+          accounts.push({ ...JSON.parse(await decrypt(row.secret, env)), name: row.name, account_id: row.id });
+        } catch (err) {
+          console.error(`Failed to decrypt account ${row.id}:`, err);
+        }
+      }
       return json({ accounts }, 200, env);
🤖 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 `@worker/src/index.js` around lines 159 - 164, Update the account-building loop
in the GET /api/runner/config handler to handle decryption failures per row:
catch errors from decrypt and skip only the affected account, while continuing
to include successfully decrypted accounts and return the normal JSON response.
🧹 Nitpick comments (1)
checkin.py (1)

86-118: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the unused session ID extractor.

_extract_user_id_from_session is only defined; no caller uses it, while the constructor keeps any passed-in user_id directly. Drop the method if session-derived IDs are no longer needed.

🤖 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 `@checkin.py` around lines 86 - 118, Remove the unused
_extract_user_id_from_session method and its implementation, leaving the
constructor’s existing handling of the provided user_id unchanged.
🤖 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 `@worker/src/index.js`:
- Around line 9-18: Update worker/src/index.js at lines 9-18 so missingDbError
accepts env and passes it to json with status 503, then update its three call
sites at lines 146, 158, and 187 to pass env. Also update the result-format
error response at lines 165-184 to call json with the existing env argument and
status 400.
- Line 150: Update the SESSION_TTL_SECONDS expiration calculation so invalid or
non-finite numeric values, including truthy strings such as “abc”, fall back to
86400 seconds before constructing the Date. Preserve valid configured TTL values
and ensure the resulting expires calculation cannot produce an invalid date.

---

Outside diff comments:
In `@worker/src/index.js`:
- Around line 159-164: Update the account-building loop in the GET
/api/runner/config handler to handle decryption failures per row: catch errors
from decrypt and skip only the affected account, while continuing to include
successfully decrypted accounts and return the normal JSON response.

---

Nitpick comments:
In `@checkin.py`:
- Around line 86-118: Remove the unused _extract_user_id_from_session method and
its implementation, leaving the constructor’s existing handling of the provided
user_id unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0457ec00-5478-44b4-b0aa-7e1913bd13d0

📥 Commits

Reviewing files that changed from the base of the PR and between a13206e and 8099abb.

📒 Files selected for processing (8)
  • .github/workflows/checkin.yml
  • FIRST_RUN.md
  • README.md
  • WORKER_DEPLOYMENT.md
  • checkin.py
  • worker/public/index.html
  • worker/src/index.js
  • worker/wrangler.toml
🚧 Files skipped from review as they are similar to previous changes (6)
  • FIRST_RUN.md
  • worker/wrangler.toml
  • .github/workflows/checkin.yml
  • worker/public/index.html
  • README.md
  • WORKER_DEPLOYMENT.md

Comment thread worker/src/index.js
Comment on lines +9 to +18
function getDb(env) {
return env?.Check || env?.DB || env?.D1 || env?.CHECK || null;
}

function missingDbError() {
return json({
error: 'D1 未绑定:自动部署后绑定可能被清空。请在 Worker Settings → Bindings 添加 D1,变量名必须为 Check;或在 worker/wrangler.toml 的 [[d1_databases]] 填入 database_id 后重新部署。',
code: 'D1_BINDING_MISSING',
}, 503);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Inconsistent env argument to json() across error responses. Both sites omit the third env argument that every other response in the file passes, which is inconsistent and, if json() ever keys any header (e.g. CORS) off env, would silently degrade those specific error paths — notably the D1_BINDING_MISSING path this PR is meant to make reliable.

  • worker/src/index.js#L9-L18: change missingDbError() to missingDbError(env) and pass env through to json(..., 503, env); update the three call sites (Lines 146, 158, 187) to missingDbError(env).
  • worker/src/index.js#L165-L184: change Line 167 to return json({ error: '结果格式错误' }, 400, env);.
📍 Affects 1 file
  • worker/src/index.js#L9-L18 (this comment)
  • worker/src/index.js#L165-L184
🤖 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 `@worker/src/index.js` around lines 9 - 18, Update worker/src/index.js at lines
9-18 so missingDbError accepts env and passes it to json with status 503, then
update its three call sites at lines 146, 158, and 187 to pass env. Also update
the result-format error response at lines 165-184 to call json with the existing
env argument and status 400.

Comment thread worker/src/index.js
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Enable Cloudflare auto-provisioned D1 bindings without repository database IDs, polish the README and guides, and keep local .monkeycode content out of Git.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Add a short shareable Markdown post for community promotion and link it from the docs index.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Remove unused community share draft and clean related documentation links.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Scope cookies to target hosts, make D1 reports atomic, enforce secure account origins, revoke dashboard sessions on logout, and add regression coverage.

Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
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.

2 participants