Commit Graph

7071 Commits

Author SHA1 Message Date
Atul Tameshwari
b1def9316e refactor: remove command palette & sidebar components and related files from web/app/ce 2026-06-16 10:26:30 +05:30
Rahulcheryala
3e6f7ab9d0 fix: import structure for hooks 2026-06-15 18:14:40 +05:30
Rahulcheryala
2c98862acf fix: React doctor comments 2026-06-15 18:06:56 +05:30
Rahulcheryala
717eae9a0f fix: coderabbit comments 2026-06-15 18:05:38 +05:30
Rahulcheryala
1ca66f7f1d refactor: delete hook (use-issue-embed) from web/app/ce 2026-06-15 17:38:58 +05:30
Rahulcheryala
d920416e8f refactor: migrate hooks (use-workspace-issue-properties) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
e3aa81f7cd refactor: migrate hooks (use-issue-properties) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
34ddd1674a refactor: migrate hooks (use-debounced-duplicate-issues) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
bf55317d0f refactor: migrate hooks (use-bulk-operations) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
6c571d0841 refactor: migrate hooks (use-extended-editor-config) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
f74ee5aa63 refactor: migrate hooks (use-work-items-filters-config) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
d977d6d0d4 refactor: migrate hooks (use-extended-editor-extensions, use-pages-pane-extensions) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
a189d7be8d refactor: migrate hooks (use-additional-favorite-item-details) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
ec34e95e7b refactor: migrate hooks (use-additional-editor-mention) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
b2795efa77 refactor: migrate hooks (use-filters-operator-configs) from web/app/ce to web/app/core 2026-06-15 17:38:58 +05:30
Rahulcheryala
57972d4519 refactor: migrate hooks (use-editor-flagging) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
f7056d1ef4 refactor: migrate hooks (use-page-flag) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
db2c39eff6 refactor: migrate hooks (app-rail, indexes) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
41a0d0ece6 refactor: migrate hooks (use-page, use-page-store) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
3b809cd306 refactor: migrate hooks (use-timeline-chart) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
40c94e726b refactor: migrate hooks (use-notification-preview) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
5e09a7abc6 refactor: migrate hooks (use-file-size) from web/app/ce to web/app/core 2026-06-15 17:38:57 +05:30
Rahulcheryala
efecb7b75d refactor: resolve coderabbit comments 2026-06-15 17:30:58 +05:30
Rahulcheryala
b82f376a49 fix: resolve coderabbit comments 2026-06-15 17:12:44 +05:30
Rahulcheryala
315ccee369 resolved lint errors 2026-06-15 17:12:44 +05:30
Rahulcheryala
76bdd9515f refactor: migrate constants (plans) from apps/web to @core/components 2026-06-15 17:12:44 +05:30
Rahulcheryala
9503c7211a refactor: migrate constants (editor) from apps/web to @plane/constants 2026-06-15 17:12:44 +05:30
Rahulcheryala
bba0ca9613 refactor: migrate constants (sidebar, favorites) from apps/web to @plane/constants 2026-06-15 17:12:44 +05:30
Rahulcheryala
dbca2b2b62 refactor: migrate constants (ai, calenda, gaant) from apps/web to @plane/constants 2026-06-15 17:12:44 +05:30
Rahulcheryala
1221954ed5 refactor: migrate constants (fetch-keys) from apps/web to @plane/constants 2026-06-15 17:12:44 +05:30
Nikita Mitasov
f2feca61e8 feat(api): add workspace_slug to webhook delivery payload (#9232) 2026-06-15 13:16:41 +05:30
sriram veeraghanta
498f857be4 fix: resolve esbuild advisory and bump turbo to 2.9.18 (#9236)
Resolves the sole open Dependabot alert (GHSA-gv7w-rqvm-qjhr, high):
esbuild <0.28.1 lacks binary-integrity verification in its Deno install
path, enabling RCE via NPM_CONFIG_REGISTRY. The pnpm `overrides` entry
pinned the entire tree to esbuild 0.25.0; bump it to 0.28.1, which fixes
all transitive paths (vite, vitest, tsx, vite-node, esbuild-register).

Also bump turbo 2.9.14 -> 2.9.18 in the workspace catalog and the four
pinned production Dockerfiles (web, live, admin, space).

Verified: `pnpm audit` clean, admin react-router/vite build succeeds,
@plane/codemods vitest suite 33/33 passing.
2026-06-15 13:15:40 +05:30
sriram veeraghanta
fd16d033fc fix(api): reject API key auth for deactivated user accounts (#9225)
The custom API key authentication only verified that the APIToken row was
active and unexpired; it never checked the owning user's is_active flag.
DRF's IsAuthenticated only checks user.is_authenticated (always True for a
real User), so a user whose account was deactivated could keep using a
previously issued API key indefinitely.

Add user__is_active=True to the validate_api_token() lookup so a token tied
to a disabled account is treated as invalid (a generic AuthenticationFailed,
avoiding account-state disclosure). Applied to both the external API
middleware (plane/api) and the identical, currently unused copy in
plane/app to prevent the gap from being reintroduced.

Adds unit coverage on validate_api_token and an end-to-end contract test
proving GET /api/v1/users/me/ is denied once the account is deactivated.
2026-06-10 11:36:45 +05:30
sriram veeraghanta
2f7941a17c fix(api): sanitize XLSX export cells to prevent formula injection (#9224)
User-controlled values (work item titles, labels, etc.) were written
raw into openpyxl worksheet cells, so values beginning with = were
stored as live formula cells in exported XLSX files. Apply the same
formula-trigger sanitization already used for CSV exports to XLSX
cell values and header rows in both export formatters, and sanitize
CSV header rows in the porters formatter for parity.
2026-06-10 11:32:13 +05:30
Rahul Cheryala
373f149fdb [GIT-238] refactor: migrate types from apps/web to @plane/types (#9203)
* refactor: migrate types from apps/web to @plane/types

* [WEB-238] resolved lint errors

* [WEB-238] Resolved coderabbit comments
2026-06-09 18:06:08 +05:30
sriram veeraghanta
a1535319e6 chore: integrate react-doctor scanning (#9223)
Add react-doctor for React lint/a11y/perf/architecture diagnostics:
- Add react-doctor devDependency and "doctor" npm script
- Add .claude/skills/react-doctor skill for local triage workflow
- Add GitHub Actions workflow to scan PRs and track health score
2026-06-09 02:02:54 +05:30
sriram veeraghanta
0bbfe95cc7 fix: bump react-router and vitest to resolve Dependabot advisories (#9215)
* fix: bump react-router and vitest to resolve Dependabot advisories

Resolves 6 open Dependabot alerts (all npm, manifest pnpm-lock.yaml):

- react-router 7.12.0 -> 7.15.0 (fixes GHSA-8x6r-g9mw-2r78 [high],
  GHSA-49rj-9fvp-4h2h [high], GHSA-8646-j5j9-6r62 [high],
  GHSA-2j2x-hqr9-3h42 [medium], GHSA-f22v-gfqf-p8f3 [medium])
- vitest 4.0.x -> 4.1.x (fixes GHSA-5xrq-8626-4rwp [critical])

Aligned lockstep siblings to avoid peer-dependency mismatches:
@react-router/dev|node|serve -> 7.15.0, @vitest/coverage-v8 -> ^4.1.0.

Edited catalog entries in pnpm-workspace.yaml and regenerated
pnpm-lock.yaml; verified with pnpm install --frozen-lockfile.

* fix: raise vitest catalog floor to ^4.1.8 to match security advisory

The critical advisory GHSA-5xrq-8626-4rwp is patched in vitest 4.1.8, but
the catalog specifiers were ^4.1.0, which permits resolving to vulnerable
4.1.0-4.1.7. Align the floor with the documented patched version for vitest
and @vitest/coverage-v8 so a future lockfile refresh cannot reintroduce a
vulnerable Vitest stack. Resolved version is unchanged (4.1.8).
2026-06-05 00:51:33 +05:30
sriram veeraghanta
9a30a07cf5 fix(api): enforce workspace membership on GenericAssetEndpoint (#9212)
The public REST API GenericAssetEndpoint (/api/v1/workspaces/<slug>/assets/)
declared no permission class, inheriting only IsAuthenticated. Since
APIKeyAuthentication does not bind a token to a workspace and the workspace is
read straight from the URL slug, any valid Personal Access Token could read
(GET), create (POST), and modify (PATCH) assets in a workspace the caller is
not a member of — a cross-workspace IDOR, the public-API sibling of the
CVE-2026-46558 dashboard asset fix.

Add permission_classes = [WorkspaceUserPermission] so every method requires
active workspace membership, matching the dashboard fix semantics. Also add
contract regression tests covering cross-workspace GET/POST/PATCH (now 403)
and a positive control confirming members retain access.

Also ignore the local /security/ advisory notes folder.
2026-06-04 18:49:39 +05:30
Karthikeyan Ganesh
b6e47ccdae fix: dropdown shadow on the work item more options (#9154)
* fix: UI border and shadow on the dropdown menu usability

* fix: shadow-md and border strong
2026-06-03 17:28:19 +05:30
Durgesh Shekhawat
4280c4d1b1 fix: handle error message for special characters in Identifier of Project (#9059) 2026-06-03 17:26:18 +05:30
sriram veeraghanta
b1c78fe4c8 fix(api): rate-limit magic-code verify, bound per-token attempts (GHSA-9pvm-fcf6-9234) (#9130)
* fix(api): rate-limit magic-code verification and bound per-token attempts

The magic-link sign-in / sign-up endpoints accept a 6-digit numeric code
(900k-value space, 600s TTL) but never increment a failure counter on a
wrong-code verify and extend django.views.View rather than DRF APIView,
so DRF's AuthenticationThrottle never runs against them. The space-side
generate endpoint also lacked throttle_classes. Combined, this allowed
an unauthenticated attacker who knew a victim's email to brute-force
the code within the TTL window and log in as the victim.

- Add MAX_VERIFY_ATTEMPTS=5 in MagicCodeProvider.set_user_data: failed
  comparisons now persist verify_attempts in Redis under the remaining
  TTL and, on hitting the limit, delete the key and raise
  EMAIL_CODE_ATTEMPT_EXHAUSTED. This is the load-bearing fix - it caps
  total attempts per issued token regardless of request rate.
- Add authentication_throttle_allows() so plain Django Views can apply
  AuthenticationThrottle without converting to APIView (would change
  CSRF + request-parsing semantics for the redirect-flow endpoints).
- Apply the throttle to MagicSignIn/UpEndpoint and the space variants;
  add throttle_classes to MagicGenerateSpaceEndpoint to match its app
  sibling.

Refs GHSA-9pvm-fcf6-9234.

* fix(api): make verify-attempt increment atomic, expose throttle rate via env

Address PR review feedback:

- Replace the JSON read-modify-write of verify_attempts with a Lua
  EVAL script that INCRs a dedicated counter key and EXPIREs it only
  on the first increment. The previous round-trip was racy: parallel
  wrong-code requests could read the same value and both write the
  same incremented count, letting an attacker exceed MAX_VERIFY_ATTEMPTS
  under concurrency. Counter is now reset on each new token issuance
  and cleared on successful verify / exhaustion.
- Make AuthenticationThrottle.rate configurable via the
  AUTHENTICATION_RATE_LIMIT env var (default 10/minute, down from 30
  to tighten the budget on unauth auth-adjacent endpoints). Document
  it in deployments/aio and deployments/cli variables.env.

* test(api): cover magic-code attempt cap, counter reset, and auth throttle

Add the contract tests called out in the PR test plan:

- TestMagicSignInVerifyAttempts:
  - test_exhausted_after_max_wrong_attempts: after MAX_VERIFY_ATTEMPTS
    wrong codes the next verify redirects with EMAIL_CODE_ATTEMPT_
    EXHAUSTED_SIGN_IN and both Redis keys are deleted; a follow-up
    verify reports EXPIRED.
  - test_counter_increments_on_each_wrong_attempt: the dedicated
    verify_attempts counter advances by exactly one per wrong POST,
    matching the atomic Lua INCR.
  - test_counter_resets_on_token_regeneration: regenerating the
    magic-link clears the counter so the user isn't pre-locked-out by
    a prior session's wrong attempts.
- TestMagicSignUpVerifyAttempts.test_signup_exhausted_after_max_wrong_attempts:
  the sign-up endpoint returns EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP on
  the exhausting attempt.
- TestAuthenticationThrottle: exercises authentication_throttle_allows
  on the plain-View redirect-flow endpoints by patching the rate down
  and asserting RATE_LIMIT_EXCEEDED is appended to the redirect URL
  once the per-IP budget is exceeded, for both magic-sign-in and
  magic-sign-up.

Each new class clears Django cache (DRF throttle storage) and the
per-email Redis keys around every test so runs are independent.

* fix(api): clamp remaining_ttl to >=1 for verify-attempt counter EXPIRE

ri.ttl() returns 0 when the token has less than one second remaining
(Redis floors to whole seconds). The previous clamp only caught
None and < 0, so a sub-second TTL would pass through and the Lua
script's EXPIRE counter 0 would immediately delete the key — letting
an attacker bypass MAX_VERIFY_ATTEMPTS during the final second of the
token's life. Switch the comparison to <= 0.

Narrow real-world impact (sub-second window, throttle still bounds
the rate) but the cap should hold regardless of timing.
2026-06-01 18:44:57 +05:30
sriram veeraghanta
7ec8d4990f fix: bump npm deps to resolve Dependabot advisories (#9191)
* fix: bump npm deps to resolve Dependabot advisories

Resolve 8 open Dependabot alerts (all npm, in pnpm-lock.yaml) by bumping
the affected packages in pnpm-workspace.yaml and regenerating the lockfile:

- axios 1.15.2 -> 1.16.0 (catalog): CVE-2026-44494/44492/44490/44489
- tmp -> 0.2.6 (override): CVE-2026-44705 path traversal
- ws 8.x -> 8.20.1 (catalog + scoped override): CVE-2026-45736
- qs 6.14.2 -> 6.15.2 (override): CVE-2026-8723 DoS
- brace-expansion 5.0.5 -> 5.0.6 (override): CVE-2026-45149 DoS

brace-expansion and qs were pinned to their vulnerable versions in the
overrides block, so the pins had to be bumped directly. ws is scoped to
the 8.x major (ws@7.5.10 is below the vulnerable >=8.0.0 floor). All bumps
are semver-compatible patch/minor upgrades; no source changes required.

* fix: use named axios `create` import after 1.16.0 bump

axios 1.16.0 newly exposes `create` as a named export, so oxlint's
import/no-named-as-default-member rule now flags `axios.create(...)`.
That added one warning to @plane/services (7 > its --max-warnings=6
baseline) and to apps/web and apps/live, failing check:lint — surfaced
on this PR because the lockfile change busts Turbo's lint cache.

Switch the three `axios.create(...)` call sites to a named `{ create }`
import. `create` is a real value+type export in axios 1.16.0 (verified
via tsc). isCancel/CancelToken are left as `axios.*`: CancelToken is
only a type export (cannot be a value import under verbatimModuleSyntax)
and both were already counted within the existing baselines.

Verified locally: full `pnpm check:lint` (16/16) and `check:types`
(15/15) pass.
2026-06-01 18:37:35 +05:30
sriram veeraghanta
e388cb9125 fix: declare @tailwindcss/postcss in admin/space/web for Docker builds (#9189)
The web/admin/space Docker image builds fail at the Vite/PostCSS step with
"Cannot find module '@tailwindcss/postcss'". These apps load the shared
@plane/tailwind-config/postcss.config.js, which references the @tailwindcss/postcss
plugin by name, but the plugin was only declared as a dependency of
packages/tailwind-config.

The Docker build installs via turbo prune + 'pnpm fetch' + 'pnpm install --offline',
which lays out node_modules so PostCSS resolves the plugin relative to the app
directory (apps/<app>), where it is not reachable. A plain 'pnpm install' resolves
it from tailwind-config's context instead, which is why local builds passed and
masked the issue.

Declare @tailwindcss/postcss as a direct devDependency of the three apps that run
Vite/PostCSS so it is symlinked into each app's node_modules and resolves under the
isolated linker regardless of install flow.

Verified by reproducing the exact Docker flow (prune -> fetch -> --frozen-lockfile
offline install -> build) for admin, space and web: all install in sync and build
successfully with full Tailwind CSS output.
2026-06-01 16:44:16 +05:30
Rahul Cheryala
bd0d164e0b fix(GIT-235): add styles to onboarding tour close button for contrast (#9188) 2026-06-01 16:43:45 +05:30
sriram veeraghanta
011328c793 [GIT-213] fix: return HTTP response from dispatch() exception handler (#9179)
* fix(api): return HTTP response from dispatch() exception handler

BaseAPIView.dispatch() and BaseViewSet.dispatch() built the proper
error Response via handle_exception() but returned the raw exception
object instead, causing Django to raise
"TypeError: 'Exception' object is not a valid HTTP response".

Fix all six occurrences across the api, app, license and space view
bases, and add a regression test covering every affected base class.

Fixes #9157

* chore(api): add copyright header to tests/unit/views/__init__.py

The empty package init file was missing the AGPL copyright header,
failing the Copy Right Check CI (addlicense -check on all tracked
.py files).
2026-06-01 15:03:22 +05:30
sriram veeraghanta
3f57fefdb4 chore: move all dependencies into pnpm catalog (#9153)
Centralize every external dependency version in the pnpm catalog
(pnpm-workspace.yaml) and reference them via `catalog:` across all
apps and packages. Packages that previously used differing versions
were unified to the highest (notably @react-pdf/renderer ^3.4.5 ->
^4.3.0 in apps/web).
2026-05-31 15:56:12 +05:30
sriram veeraghanta
04622ce118 fix: harden webhook/link/OAuth-avatar SSRF (advisory clusters A/B/C/E) (#9163)
* fix(api): harden webhook & link-unfurl SSRF (advisory clusters A/B/C)

Resolves three overlapping SSRF advisory clusters around webhook delivery
and work-item link unfurling:

- Cluster A (private-IP validation + PATCH bypass): the webhook PATCH
  handler passed context={request: request} (the request object as the
  dict key) so the loopback/disallowed-domain guard silently no-op'd —
  now context={"request": request}. Hardened IP classification
  (is_blocked_ip) to also block multicast, unspecified, CGNAT
  (100.64.0.0/10), and IPv4 embedded in IPv6 transition addresses
  (IPv4-mapped, NAT64, 6to4, Teredo), robust across Python versions.

- Cluster B (DNS-rebinding TOCTOU): validators resolved DNS, then
  requests resolved it again at connect time. New pinned-IP client
  (plane/utils/url_security.py) resolves+validates once and connects to
  the validated IP literal so urllib3 performs no second lookup, while
  preserving Host header, TLS SNI and certificate verification against
  the real hostname.

- Cluster C (redirect SSRF): webhook delivery never follows redirects;
  the link crawler follows them manually, re-resolving + re-validating +
  re-pinning every hop.

Also: pin requests==2.33.0 in base.txt (imported directly; the pinning
adapter needs the >=2.32 get_connection_with_tls_context hook), and log
webhook URL-validation rejections to WebhookLog instead of swallowing
them.

Tests: new test_url_security.py (pinning, rebinding, redirect
re-validation, IP edge cases, TLS SNI) + updated link-task tests.
Full unit suite: 178 passed.

* fix(api): block OAuth avatar SSRF + add per-advisory SSRF regression tests

Verified every SSRF-class advisory against the current code. The webhook /
link / favicon reports — including the published CVE-2026-30242 and
CVE-2026-39843 and the newer "still bypassable" reports (DNS rebinding
GHSA-3856/-fgcv/-9292/-whh3/-4mjx/-6p39/-fv24/-8wvv, IP-classification gaps
GHSA-75fg, redirect GHSA-6v37/-jw6g/-mq87) — are resolved by the pinned-IP
client + hardened classifier in this branch.

The one SSRF family still unresolved was the OAuth avatar path:
download_and_upload_avatar() fetched the provider-supplied avatar_url with a
raw requests.get (no IP validation, default redirect following), so an
attacker-controlled avatar could reach internal addresses and be exfiltrated
via the static-asset endpoint (GHSA-cv9p-325g-wmv5, and the avatar hop of the
Gitea SSRF GHSA-hx79-5pj5-qh42). It now uses pinned_fetch_following_redirects,
which validates + pins every hop and blocks internal targets.

Adds test_ssrf_advisories.py: a per-advisory regression map covering webhook
IP validation, the PATCH context-key guard, webhook DNS rebinding, webhook
redirect, favicon redirect + rebinding, and OAuth avatar SSRF.

docker compose test: 199 unit tests pass.

* fix(api): address PR review feedback on the SSRF pinned client

- url_security: preserve URL-embedded credentials (user:pass@host) as Basic
  Auth instead of silently dropping them when rewriting to the IP literal
  (Copilot); bracket IPv6-literal hostnames in the Host header (Copilot);
  add stream=True support that keeps the session open until the response is
  closed, and release intermediate redirect hops.
- ip_address / work_item_link_task: treat UnicodeError (IDNA failures) from
  getaddrinfo as a resolution failure, not an uncaught exception (CodeRabbit).
- authentication/adapter/base: stream the avatar download so the size cap
  actually bounds memory, upload the size-bounded buffer (not response.content),
  and always close the response (CodeRabbit, major).
- tests: cover auth preservation, IPv6 Host bracketing, IDNA handling, and
  streamed session lifetime; drop an unused import.

docker compose test: 204 unit tests pass.
2026-05-31 00:12:23 +05:30
sriram veeraghanta
248f5d66e6 refactor(api): source API_KEY_RATE_LIMIT from settings, drop service token throttle (#9161)
- Define API_KEY_RATE_LIMIT in plane/settings/common.py and read it via
  django.conf.settings in ApiKeyRateThrottle instead of os.environ.
- Remove ServiceTokenRateThrottle and the service-token branch in
  BaseAPIView.get_throttles; all API key requests now go through
  ApiKeyRateThrottle.
2026-05-29 00:13:41 +05:30
KanteshMurade
f14451a5de fix(web): add Safari fallback for requestIdleCallback (#9137)
* fix(web): add Safari fallback for requestIdleCallback

* fix(web): use globalThis in idle-task fallbacks

Switch idle-task fallback paths from window.* to globalThis.* so the
fallback no longer crashes in environments where window is undefined.
Also thread IdleRequestOptions through requestIdleFallback so the
caller's timeout hint is honored when falling back.

Addresses CodeRabbit review feedback on #9137.

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
2026-05-28 23:56:46 +05:30
Manish Gupta
095b1aa360 [WEB-7447] feat: migrate CE telemetry from OTLP traces to OTLP metrics (#9156)
* [WEB-7447] feat: migrate CE telemetry from OTLP traces to OTLP metrics

Replace span-based tracing (tracer.py) with OTLP observable gauges,
mirroring the approach already used in plane-ee. Key changes:

- Add otlp_endpoints.py — shared gRPC/HTTP endpoint helpers
- Add telemetry_metrics.py — push_instance_metrics task using
  MeterProvider + observable gauges (service name: plane-ce-api)
- User count excludes bots (is_bot=False)
- Page count excludes bot-owned private pages only
- Domain derived from WEB_URL env var
- Celery beat entry replaced with timedelta schedule +
  configurable METRICS_PUSH_INTERVAL_MINUTES (default 360 min)
- Add explicit opentelemetry-exporter-otlp-proto-grpc dep
- Delete tracer.py and telemetry.py (no longer needed)

Co-authored-by: Plane AI <noreply@plane.so>

* fix: address review comments on CE telemetry metrics

- harden grpc_endpoint_from_url for scheme-less OTLP_ENDPOINT values
  (e.g. "telemetry.plane.so:4317") by prepending "//" before urlparse
- fix WEB_URL domain extraction for scheme-less values with same approach
- replace N+1 workspace count queries (6×N) with 6 batched annotate(Count)
  aggregation queries — reduces DB load significantly at WORKSPACE_METRICS_LIMIT
- add deterministic ordering (order_by created_at) to workspace slice
- harden METRICS_PUSH_INTERVAL_MINUTES env parsing with try/except guard
  and positive-value validation to avoid crash on malformed input

Co-authored-by: Plane AI <noreply@plane.so>

* fix: cap METRICS_PUSH_INTERVAL_MINUTES to prevent timedelta overflow

Add upper-bound check (10_000_000 minutes) and catch OverflowError alongside
ValueError so an arbitrarily large env value cannot crash worker startup via
timedelta(minutes=...) OverflowError.

Co-authored-by: Plane AI <noreply@plane.so>

---------

Co-authored-by: Plane AI <noreply@plane.so>
2026-05-28 18:34:27 +05:30