feat(node): full dashboard auth and API parity#385
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 15 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (62)
📝 WalkthroughWalkthroughThis PR adds Rust N-API support for job replay and inspection, and expands the Node dashboard with session/CSRF auth, optional OAuth login, ops and settings endpoints, override and middleware controls, webhook delivery replay, and proxy/interception metrics. It also rewires server dispatch, queue behavior, worker startup, CLI integrations, and tests around those surfaces. ChangesDashboard auth, inspection, and admin surface
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
sdks/node/src/proxies/proxy-session.ts (1)
71-76: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRecord verification failures in session reconstruction metrics.
ProxySession.reconstructbypassesProxies.reconstruct, so signature/expiry/purpose failures fromverifyRefare not counted while the direct path records them.📊 Proposed fix
this.ensureOpen(); const handler = this.proxies.handlerFor(ref.handler); - this.proxies.verifyRef(ref, expectedPurpose); + try { + this.proxies.verifyRef(ref, expectedPurpose); + } catch (error) { + proxyMetrics.recordChecksumFailure(ref.handler); + throw error; + } if (this.reconstructed.has(ref.signature)) {🤖 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 `@sdks/node/src/proxies/proxy-session.ts` around lines 71 - 76, ProxySession.reconstruct currently calls this.proxies.verifyRef directly, so signature/expiry/purpose failures are not recorded in the session reconstruction metrics like they are through Proxies.reconstruct. Update ProxySession.reconstruct to route verification through the same metrics-tracking path, or explicitly record verification failures around verifyRef using the existing reconstruction metrics helpers. Keep the behavior for successful reconstruction and the reconstructed cache intact.
🧹 Nitpick comments (6)
sdks/node/src/dashboard/auth/oauth/config.ts (1)
73-75: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAvoid the flagged trailing-slash regex.
CodeQL flags Line 74; replacing it with deterministic trimming keeps behavior and avoids a blocking static-analysis finding.
Proposed fix
export function callbackUrl(config: OAuthConfig, slot: string): string { - return `${config.redirectBaseUrl.replace(/\/+$/, "")}/api/auth/oauth/callback/${slot}`; + let base = config.redirectBaseUrl; + while (base.endsWith("/")) { + base = base.slice(0, -1); + } + return `${base}/api/auth/oauth/callback/${slot}`; }🤖 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 `@sdks/node/src/dashboard/auth/oauth/config.ts` around lines 73 - 75, The callbackUrl helper currently uses a trailing-slash regex on config.redirectBaseUrl, which is triggering the static-analysis finding. Update callbackUrl to trim trailing slashes deterministically without regex while preserving the same URL construction, and keep the change localized to the callbackUrl function in the OAuth config module.Source: Linters/SAST tools
sdks/node/src/dashboard/auth/oauth/stateStore.ts (1)
100-108: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winRevalidate persisted
next_urlbefore returning it.
OAuthFlow.startsanitizesnextUrl, but the persisted KV row is trusted on callback; keep the store invariant safe even if a row is malformed or written by another path.Proposed fix
+import { isSafeRedirect } from "../../urlSafety"; + return { state: stateToken, nonce: row.nonce, codeVerifier: row.code_verifier, slot: row.slot, - nextUrl: typeof row.next_url === "string" ? row.next_url : "/", + nextUrl: typeof row.next_url === "string" && isSafeRedirect(row.next_url) ? row.next_url : "/", createdAt: row.created_at ?? 0, expiresAt: row.expires_at, };🤖 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 `@sdks/node/src/dashboard/auth/oauth/stateStore.ts` around lines 100 - 108, The OAuth callback path in stateStore is trusting persisted next_url data too directly. In the state retrieval logic that returns the row fields (including nextUrl), revalidate the stored value with the same sanitization/invariant checks used by OAuthFlow.start before exposing it, and fall back to "/" for any malformed or unsafe value. Keep the fix localized to the stateStore read path so the returned object always preserves the expected nextUrl invariant even if the KV row was tampered with or written elsewhere.sdks/node/src/cli/commands/dashboard.ts (1)
14-34: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winConsider warning when
--insecure-cookiesis used.Silently dropping the
Securecookie attribute is easy to misuse in a non-dev environment (e.g., a copy-pasted CLI invocation). A one-line stderr warning would reduce accidental misconfiguration risk.♻️ Proposed addition
const server = serveDashboard(queue, { port, host, auth: options.token ? { token: options.token } : undefined, secureCookies: options.insecureCookies ? false : undefined, }); + if (options.insecureCookies) { + process.stderr.write("warning: --insecure-cookies disables the Secure cookie attribute; use only for plain-HTTP dev\n"); + }🤖 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 `@sdks/node/src/cli/commands/dashboard.ts` around lines 14 - 34, The dashboard CLI currently enables --insecure-cookies without any user-facing warning, which can be easy to misuse. Update registerDashboard in dashboard.ts so that when options.insecureCookies is set, it emits a one-line warning to stderr before calling serveDashboard, using the existing action handler and the insecureCookies flag as the trigger. Keep the warning concise and explicit that the Secure cookie attribute is being disabled.sdks/node/test/dashboard/sessionAuth.test.ts (1)
1-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShared dashboard-test bootstrap duplicated across five test files.
The
beforeAllstatic-asset build guard, temp-dbbeforeEach, and server teardown here are duplicated nearly verbatim acrossinspectRoutes.test.ts,opsSettings.test.ts,overridesMiddleware.test.ts,server.test.ts, andwebhookDeliveries.test.ts. Consider extracting a sharedstartDashboardTestServer()/ensureDashboardBuilt()helper (similar in spirit toseedAdminAndSession) into a shared test-utils module to reduce copy-paste drift as the dashboard test surface keeps growing.🤖 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 `@sdks/node/test/dashboard/sessionAuth.test.ts` around lines 1 - 44, The dashboard test setup is duplicated across multiple test files, including the static build guard, temporary queue/database initialization, server startup, and teardown logic. Extract this shared bootstrap into a reusable test helper such as ensureDashboardBuilt() and startDashboardTestServer() in the dashboard testing utilities module, then update sessionAuth.test.ts and the related dashboard tests to use it instead of repeating the same beforeAll/beforeEach/afterEach logic.sdks/node/src/worker.ts (1)
76-87: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winPer-invocation settings read for middleware disables could add hot-path latency.
middlewareFor()performs a synchronous KV read (getSetting) on every task invocation (line 154) and again on every outcome dispatch (line 198) — two storage round-trips per job purely to check disable toggles. This is an explicit "live toggle" tradeoff per the comment, but for high-throughput queues this doubles the storage reads per job. Consider a short-TTL in-memory cache (invalidated onsetDisabled/clearFor, or simply refreshed every N seconds) to bound this cost while still picking up toggles promptly.Also applies to: 198-198
🤖 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 `@sdks/node/src/worker.ts` around lines 76 - 87, The live per-invocation middleware disable lookup in MiddlewareDisableStore is causing extra synchronous KV reads in middlewareFor(), which is used on both task handling and outcome dispatch. Update MiddlewareDisableStore/getFor usage to add a short-TTL in-memory cache or periodic refresh so repeated calls within the TTL reuse cached disables, and make sure setDisabled and clearFor invalidate the cache so toggle changes still propagate promptly.sdks/node/src/proxies/metrics.ts (1)
4-12: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
durationssliding window usespush+shift(), which is O(n) per sample once at capacity.Once
durations.lengthreachesMAX_SAMPLES(1000), every subsequentrecordReconstruction()call does ashift()that re-indexes the remaining ~1000 elements. Under sustained proxy-reconstruction throughput this becomes a repeated O(n) cost on a metrics hot path. A fixed-size ring buffer (array + write index moduloMAX_SAMPLES) would make this O(1) per sample.♻️ Sketch of a ring-buffer alternative
interface HandlerMetrics { reconstructions: number; errors: number; cleanupErrors: number; checksumFailures: number; totalDurationMs: number; maxDurationMs: number; - durations: number[]; + durations: number[]; // fixed-length ring buffer + durationsWriteIndex: number; + durationsFilled: number; }recordReconstruction(handlerName: string, durationMs: number): void { const entry = this.handler(handlerName); entry.reconstructions += 1; entry.totalDurationMs += durationMs; entry.maxDurationMs = Math.max(entry.maxDurationMs, durationMs); - entry.durations.push(durationMs); - if (entry.durations.length > MAX_SAMPLES) { - entry.durations.shift(); - } + entry.durations[entry.durationsWriteIndex] = durationMs; + entry.durationsWriteIndex = (entry.durationsWriteIndex + 1) % MAX_SAMPLES; + entry.durationsFilled = Math.min(entry.durationsFilled + 1, MAX_SAMPLES); }Also applies to: 50-59
🤖 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 `@sdks/node/src/proxies/metrics.ts` around lines 4 - 12, The `durations` storage in `HandlerMetrics` and `recordReconstruction()` uses `push()` plus `shift()`, which becomes O(n) once `MAX_SAMPLES` is reached. Replace this with a fixed-size ring buffer approach in `metrics.ts` so samples are written at a rotating index modulo `MAX_SAMPLES`, keeping `recordReconstruction()` O(1) while preserving the existing metrics 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 `@crates/taskito-node/src/queue/admin.rs`:
- Around line 75-109: `replay_job` in `AdminQueue` is doing synchronous storage
work on the Node.js main thread, unlike the other queue admin methods that use
`spawn_blocking`. Update `replay_job` to be async and move the
read/enqueue/record_replay sequence into a blocking task so SQLite I/O does not
block the event loop, while keeping the same replay behavior and error mapping
via `to_napi_err`.
In `@crates/taskito-node/src/queue/inspect.rs`:
- Around line 168-198: The job_dag traversal is adding the same relationship
twice, so JsJobDag.edges contains duplicates. In job_dag, keep a HashSet of seen
JsDagEdge pairs (or normalized from/to keys) while walking dependencies and
dependents, and only push a JsDagEdge into edges the first time it is
encountered. Use the existing job_dag, JsDagEdge, get_dependencies, and
get_dependents flow to locate and update the edge collection logic.
In `@sdks/node/src/dashboard/auth/oauth/config.ts`:
- Around line 196-220: parseOidcSlots and parseOidcSlot currently validate
distinct slot names that can still map to the same environment prefix, so
foo-bar and foo_bar may silently share credentials. Update the OIDC slot
validation in parseOidcSlot to reject any slot whose normalized prefix collides
with another slot’s TASKITO_DASHBOARD_OAUTH_OIDC_* prefix, and add a
duplicate-prefix check in parseOidcSlots before calling parseOidcSlot so each
provider gets a unique env namespace.
In `@sdks/node/src/dashboard/auth/oauth/idToken.ts`:
- Around line 162-165: The expiry check in the id token validation flow
currently only rejects numeric expired values, so tokens with a missing or
non-numeric exp can slip through. Update the validation in the idToken.ts logic
around the claims.exp check to require a valid numeric exp before accepting the
token, and throw IdentityFetchError for any token where exp is absent or not a
number. Keep the fix localized to the existing expiry validation path so the
rest of the id_token claim checks remain unchanged.
- Around line 151-158: The audience check in idToken validation is too
permissive for multi-audience tokens. Update the logic in the idToken claims
validation path to require that when claims.aud is an array with more than one
entry, claims.azp must be present and equal options.clientId; keep the existing
single-string aud handling intact. Use the existing claims, options.clientId,
and audienceOk check in idToken.ts to locate and extend the validation before
the token is accepted.
In `@sdks/node/src/dashboard/auth/oauth/providers.ts`:
- Around line 134-153: Validate the OIDC discovery endpoints before using them
in the OAuth provider flow: in getDiscovery() and getJwks() (and the related
token exchange path in the same provider class), reject authorization_endpoint,
token_endpoint, and jwks_uri values that use plain http:// unless they point to
a local host. Add a shared endpoint validation helper or equivalent check near
these methods, and call it immediately after fetching the DiscoveryDocument and
before any request uses those URLs.
In `@sdks/node/src/dashboard/auth/store.ts`:
- Around line 240-250: The createUser flow in store.ts is not atomic because it
loads the users map, awaits hashPassword, and then saves a stale snapshot,
allowing concurrent requests to overwrite each other. Update createUser() to
re-check or lock the auth:users state after the await before writing, or
otherwise make the read-modify-write sequence atomic; if multiple dashboard
processes may share the KV store, use a KV compare-and-swap/transaction or
distributed lock around the loadUsers/saveUsers path and the username existence
check.
- Around line 265-272: The deleteUser() method in the auth store only removes
the user record and leaves any existing auth:session:* entries valid, so update
this flow to also revoke that user’s active sessions when a username is deleted.
Use the existing deleteUser() logic and the session persistence helpers in the
same store to locate and remove all sessions associated with the deleted
username before returning success. Ensure the cleanup happens only after the
user exists and is removed, and keep the boolean return behavior unchanged.
In `@sdks/node/src/dashboard/handlers/settings.ts`:
- Around line 64-65: The setting value validation currently uses value.length,
which counts UTF-16 code units instead of bytes, so multibyte strings can bypass
the intended storage cap. Update the check in the settings handler that throws
BadRequestError to measure the encoded byte size of the value before comparing
against MAX_VALUE_LENGTH, and keep the error message aligned with the byte-based
limit.
In `@sdks/node/src/dashboard/index.ts`:
- Around line 55-58: The dashboard server setup currently forwards secureCookies
in createDashboardServer even when running over plain node:http, which can cause
login cookies to be marked Secure and then dropped by browsers. Update
serveDashboard() so it does not default or forward secureCookies for the
standalone HTTP server; only pass it through when the caller explicitly provides
a value, and leave the dashboard server to infer the correct behavior from the
transport.
- Around line 50-54: The admin bootstrap in dashboard startup is currently
fire-and-forget, which can let setup traffic race before the env-provisioned
admin is created. Update the startup flow around bootstrapAdminFromEnv(queue) so
it is awaited or otherwise fully settled before the server begins listening and
accepting /api/auth/setup requests, while preserving the existing non-auth path
behavior in the dashboard index startup logic.
In `@sdks/node/src/dashboard/server.ts`:
- Around line 220-225: The matchSlot helper currently calls decodeURIComponent
directly on the sliced path, which can throw on malformed OAuth slot encodings
and turn an invalid unauthenticated URL into a server error. Update matchSlot to
safely handle decode failures by catching the decodeURIComponent exception and
returning undefined, keeping the existing prefix/slot validation intact so bad
public OAuth paths fall through as a normal non-match instead of throwing.
- Around line 435-437: The /readiness handler in server.ts always returns 200
even when readiness(queue) reports degraded; update the endpoint logic in the
request handler to inspect the readiness status and return a non-2xx response
for degraded states so Kubernetes/load balancers stop routing traffic to an
unready instance. Keep the change localized around the readiness(queue) call and
sendJson(res, ...) behavior, preserving the existing readiness payload while
adjusting the HTTP status based on the status value.
In `@sdks/node/src/webhooks/deliveryLog.ts`:
- Around line 82-84: The pagination logic in deliveryLog’s row slicing currently
passes raw `filters.offset` and `filters.limit` values into `Array.slice`, which
can produce negative-index behavior. Normalize the inputs in the
`fromRow`/pagination path by clamping `offset` and `limit` to non-negative
values before slicing, so `rows.slice(...)` always returns the expected page for
dashboard/API callers.
In `@sdks/node/src/webhooks/manager.ts`:
- Around line 118-120: The webhook delivery history is split because
deliveries() reads from DeliveryLog while WebhooksManager.test() still sends via
Deliverer without persisting anything, so dashboard test deliveries never appear
in the audit surface. Update WebhooksManager.test() to record test deliveries in
the same persisted log path used by deliveries()/DeliveryLog, and make sure any
success/failure metadata is captured consistently with normal deliveries so test
runs are included in delivery history.
- Around line 175-177: The detached promise chain in Manager’s webhook dispatch
can produce unhandled rejections when deliver() or deliveryLog.record() fails.
Update the async fire-and-forget path in the deliverer/deliveryLog.record flow
to catch and handle those failures explicitly, using the existing webhook
dispatch logic in Manager so unexpected errors are routed through the emitter’s
rejection handling instead of escaping.
In `@sdks/node/src/worker.ts`:
- Around line 154-165: `middlewareFor(invocation.taskName)` is evaluated before
the cleanup-owning try/finally in `worker.ts`, so a throw there can skip poller
cancellation and `scope.teardown()`. Move the `middlewareFor()` lookup into the
`try` path inside the worker invocation flow, and initialize `chain` to a safe
default so the `catch`/cleanup logic still has a defined value. Keep the fix
centered around `middlewareFor`, `runWithResolver`, and the existing `finally`
cleanup that clears `poller` and tears down `scope`.
---
Outside diff comments:
In `@sdks/node/src/proxies/proxy-session.ts`:
- Around line 71-76: ProxySession.reconstruct currently calls
this.proxies.verifyRef directly, so signature/expiry/purpose failures are not
recorded in the session reconstruction metrics like they are through
Proxies.reconstruct. Update ProxySession.reconstruct to route verification
through the same metrics-tracking path, or explicitly record verification
failures around verifyRef using the existing reconstruction metrics helpers.
Keep the behavior for successful reconstruction and the reconstructed cache
intact.
---
Nitpick comments:
In `@sdks/node/src/cli/commands/dashboard.ts`:
- Around line 14-34: The dashboard CLI currently enables --insecure-cookies
without any user-facing warning, which can be easy to misuse. Update
registerDashboard in dashboard.ts so that when options.insecureCookies is set,
it emits a one-line warning to stderr before calling serveDashboard, using the
existing action handler and the insecureCookies flag as the trigger. Keep the
warning concise and explicit that the Secure cookie attribute is being disabled.
In `@sdks/node/src/dashboard/auth/oauth/config.ts`:
- Around line 73-75: The callbackUrl helper currently uses a trailing-slash
regex on config.redirectBaseUrl, which is triggering the static-analysis
finding. Update callbackUrl to trim trailing slashes deterministically without
regex while preserving the same URL construction, and keep the change localized
to the callbackUrl function in the OAuth config module.
In `@sdks/node/src/dashboard/auth/oauth/stateStore.ts`:
- Around line 100-108: The OAuth callback path in stateStore is trusting
persisted next_url data too directly. In the state retrieval logic that returns
the row fields (including nextUrl), revalidate the stored value with the same
sanitization/invariant checks used by OAuthFlow.start before exposing it, and
fall back to "/" for any malformed or unsafe value. Keep the fix localized to
the stateStore read path so the returned object always preserves the expected
nextUrl invariant even if the KV row was tampered with or written elsewhere.
In `@sdks/node/src/proxies/metrics.ts`:
- Around line 4-12: The `durations` storage in `HandlerMetrics` and
`recordReconstruction()` uses `push()` plus `shift()`, which becomes O(n) once
`MAX_SAMPLES` is reached. Replace this with a fixed-size ring buffer approach in
`metrics.ts` so samples are written at a rotating index modulo `MAX_SAMPLES`,
keeping `recordReconstruction()` O(1) while preserving the existing metrics
behavior.
In `@sdks/node/src/worker.ts`:
- Around line 76-87: The live per-invocation middleware disable lookup in
MiddlewareDisableStore is causing extra synchronous KV reads in middlewareFor(),
which is used on both task handling and outcome dispatch. Update
MiddlewareDisableStore/getFor usage to add a short-TTL in-memory cache or
periodic refresh so repeated calls within the TTL reuse cached disables, and
make sure setDisabled and clearFor invalidate the cache so toggle changes still
propagate promptly.
In `@sdks/node/test/dashboard/sessionAuth.test.ts`:
- Around line 1-44: The dashboard test setup is duplicated across multiple test
files, including the static build guard, temporary queue/database
initialization, server startup, and teardown logic. Extract this shared
bootstrap into a reusable test helper such as ensureDashboardBuilt() and
startDashboardTestServer() in the dashboard testing utilities module, then
update sessionAuth.test.ts and the related dashboard tests to use it instead of
repeating the same beforeAll/beforeEach/afterEach 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 90a99deb-67ac-4775-9a9f-8c419f61512a
📒 Files selected for processing (62)
crates/taskito-node/src/convert/mod.rscrates/taskito-node/src/convert/ops.rscrates/taskito-node/src/queue/admin.rscrates/taskito-node/src/queue/inspect.rssdks/node/src/cli/commands/dashboard.tssdks/node/src/contrib/express.tssdks/node/src/contrib/fastify.tssdks/node/src/dashboard/api.tssdks/node/src/dashboard/auth/context.tssdks/node/src/dashboard/auth/handlers.tssdks/node/src/dashboard/auth/index.tssdks/node/src/dashboard/auth/oauth/config.tssdks/node/src/dashboard/auth/oauth/flow.tssdks/node/src/dashboard/auth/oauth/idToken.tssdks/node/src/dashboard/auth/oauth/identity.tssdks/node/src/dashboard/auth/oauth/index.tssdks/node/src/dashboard/auth/oauth/pkce.tssdks/node/src/dashboard/auth/oauth/providers.tssdks/node/src/dashboard/auth/oauth/stateStore.tssdks/node/src/dashboard/auth/store.tssdks/node/src/dashboard/auth/tokenAuth.tssdks/node/src/dashboard/errors.tssdks/node/src/dashboard/handlers/contract.tssdks/node/src/dashboard/handlers/core.tssdks/node/src/dashboard/handlers/index.tssdks/node/src/dashboard/handlers/metrics.tssdks/node/src/dashboard/handlers/middleware.tssdks/node/src/dashboard/handlers/ops.tssdks/node/src/dashboard/handlers/overrides.tssdks/node/src/dashboard/handlers/settings.tssdks/node/src/dashboard/index.tssdks/node/src/dashboard/policy.tssdks/node/src/dashboard/routes.tssdks/node/src/dashboard/server.tssdks/node/src/dashboard/stores/index.tssdks/node/src/dashboard/stores/middlewareDisables.tssdks/node/src/dashboard/stores/overrides.tssdks/node/src/dashboard/testing.tssdks/node/src/dashboard/urlSafety.tssdks/node/src/index.tssdks/node/src/interception.tssdks/node/src/middleware.tssdks/node/src/native.tssdks/node/src/proxies/index.tssdks/node/src/proxies/metrics.tssdks/node/src/proxies/proxies.tssdks/node/src/proxies/proxy-session.tssdks/node/src/queue.tssdks/node/src/types.tssdks/node/src/webhooks/deliveryLog.tssdks/node/src/webhooks/manager.tssdks/node/src/worker.tssdks/node/test/dashboard/inspectRoutes.test.tssdks/node/test/dashboard/oauth.test.tssdks/node/test/dashboard/oauthEndpoints.test.tssdks/node/test/dashboard/opsSettings.test.tssdks/node/test/dashboard/overridesMiddleware.test.tssdks/node/test/dashboard/server.test.tssdks/node/test/dashboard/sessionAuth.test.tssdks/node/test/dashboard/webhookDeliveries.test.tssdks/node/test/integrations/express.test.tssdks/node/test/integrations/fastify.test.ts
💤 Files with no reviewable changes (1)
- sdks/node/src/dashboard/api.ts
First-run setup, password login with PBKDF2 sessions, CSRF double-submit, and admin/viewer roles, persisted via new Queue settings-KV accessors under the cross-SDK auth key layout. Shared-token mode stays as a legacy option.
Adds /api/settings CRUD (protected namespaces hidden), /health + /readiness + Prometheus /metrics with optional bearer gate, the KEDA scaler payload, heartbeat-aggregated /api/resources, job errors/logs routes, and dead-letter purge.
Delivery history moves from an in-memory ring to the settings KV under the cross-SDK row layout, surviving restarts. Adds delivery detail, delivery replay, and rotate-secret endpoints.
Operators tune rate limits, concurrency, retries, and pause state from the dashboard; overrides persist in the settings KV under the cross-SDK key layout and apply at worker startup. Per-task middleware disables are re-read each invocation, so toggles take effect without a restart.
Group files into auth/, handlers/, and stores/ with index barrels, split route policy out of the route table, replace error helper functions with a typed exception hierarchy (DashboardError subclasses + store-level ValidationError), and drop the unused api.ts module.
New napi bindings (queryTaskLogs, listCircuitBreakers, replayJob, getReplayHistory, jobDag) surfaced as Queue methods and dashboard routes, closing the remaining read-API gaps.
Google, GitHub, and generic OIDC providers with PKCE S256, full id_token validation on node:crypto, a single-use KV-backed state store, domain/org allowlists, and admin-email role mapping — configured via the cross-SDK TASKITO_DASHBOARD_OAUTH_* env vars. No new runtime dependencies.
Per-handler proxy reconstruction metrics and enqueue-interception counters, surfaced as queue accessors plus /api/proxy-stats and /api/interception-stats.
Hash before the load-check-save so concurrent creates can't clobber each other across the PBKDF2 await, and revoke live sessions when a user is deleted.
f475897 to
84d2e7b
Compare
Summary
Changes
Session auth
--token/--insecure-cookiesflags, Express/Fastify mount optionsOAuth
New endpoints
Native additions (crates/taskito-node)
Persistence
Refactor
Behavior change
Session auth is now the default. With zero users, the API returns 503
setup_requiredand the SPA shows the setup flow. The legacy shared-token mode (auth: {token}) is unchanged for existing deployments.Test plan
Summary by CodeRabbit