166 Commits

Author SHA1 Message Date
Andrey Antukh
d56c452288 🎉 Add telemetry anonymous event collection
When the :telemetry flag is ON and :audit-log is OFF, frontend and
backend events are stored anonymously in the audit_log table and
shipped in compressed batches by the existing telemetry task.

Stored rows strip props and ip-addr but preserve the profile-id, since
Penpot profile UUIDs are already anonymous random identifiers with no
PII attached. Timestamps are truncated to day precision to avoid leaking
exact event timing. Only a safe subset of context fields is preserved:

- Backend events: initiator, version, client-version, client-user-agent
- Frontend events: browser, os, locale, screen metrics and event-origin

Backend (app.loggers.audit):
- Store backend telemetry events with source='telemetry', the safe
  context subset described above, and timestamps truncated to day
  precision via ct/truncate.

Frontend RPC (app.rpc.commands.audit):
- Add filter-safe-context to retain only the allowed frontend context
  fields.
- Add xf:map-telemetry-event-row transducer that anonymises frontend
  events before inserting them.
- push-audit-events now accepts events when telemetry is active.

Telemetry task (app.tasks.telemetry):
- gc-telemetry-events: enforces a 100,000-row safety cap by dropping
  the oldest rows first.
- collect-and-send-audit-events: loop that fetches up to 10,000 rows
  per iteration, encodes and sends each page, deletes it on success,
  and stops immediately on failure leaving remaining rows for retry.
- send-event-batch: POSTs a fressian+zstd batch (base64-encoded via
  blob/encode-str) to the telemetry endpoint, including instance-id
  and profile-id per event.
- delete-sent-events: deletes successfully shipped rows by id.

Blob utilities (app.util.blob):
- Add blob/encode-str and blob/decode-str: convenience wrappers that
  combine blob encoding with base64 for JSON-safe string transport.

Database:
- Add index on audit_log (source, created_at ASC) to support efficient
  queries for telemetry batch collection.

Tests (backend-tests.tasks-telemetry-test):
- 21 tests, 94 assertions covering all code paths: disabled/enabled
  telemetry, no-events no-op, happy-path batch send and delete, failure
  retention, payload anonymity, context stripping, timestamp day
  precision, batch encoding round-trip, multi-page iteration, GC cap
  enforcement.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-05-08 09:19:39 +00:00
Andrey Antukh
279231240d
🐛 Harden outbound HTTP requests against SSRF and restrict assets handlers (#9390)
* ⬆️ Update root deps

* 🐛 Harden outbound HTTP requests against SSRF and restrict unauthenticated asset access

- Add app.util.ssrf URL/host validator that resolves hostnames and blocks
  loopback, link-local, site-local, cloud metadata, and operator-supplied CIDRs
- Add app.media.sanitize image EOF truncator that strips trailing data after
  PNG IEND, JPEG EOI, GIF trailer, and WebP RIFF markers
- Disable HTTP client auto-redirect; add req-with-redirects! helper that
  revalidates every redirect hop against the SSRF blocklist
- Wire SSRF validation and EOF sanitization into media/download-image
- Validate webhook URLs and OIDC profile picture URLs against SSRF
- Restrict /assets/by-id to require authentication for non-public buckets
  (profile) while keeping public access for file-media-object,
  file-object-thumbnail, team-font-variant, and file-data-fragment
- Add config knobs: ssrf-protection-enabled, ssrf-allowed-hosts,
  ssrf-extra-blocked-cidrs

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-05-08 09:18:22 +02:00
Andrey Antukh
0ab126748f
💄 Add format rule for code comments (#8211)
* 💄 Add format rule for code comments

* ⬆️ Update linter and formatter on devenv
2026-01-27 15:07:18 +01:00
Andrey Antukh
9aa387a473 🐛 Fix incorrect string truncation with abbreviate template filter 2025-12-12 13:50:46 +01:00
Andrey Antukh
fcbe9d92dc 🐛 Fix unexpected exception on rendering feedback email
Looks like a bug on selmer library
2025-11-27 16:09:15 +01:00
Andrey Antukh
e9d177eae3 Make the binfile export process more resilent to errors
The current binfile export process uses a streaming technique. The
major problem with the streaming approach is the case when an error
happens on the middle of generation, because we have no way to
notify the user about the error (because the response is already
is sent and contents are streaming directly to the user
client/browser).

This commit replaces the streaming with temporal files and SSE
encoded response for emit the export progress events; once the
exportation is finished, a temporal uri to the exported artifact
is emited to the user via "end" event and the frontend code
will automatically trigger the download.

Using the SSE approach removes possible transport timeouts on export
large files by sending progress data over the open connection.

This commit also removes obsolete code related to old binfile
formats.
2025-11-19 17:28:55 +01:00
Andrey Antukh
28cf67e7ff
🎉 Add management RPC API (#7700)
* 🎉 Add management RPC API

And refactor internal http auth flow

* 📎 Adjust final url namings

* 📚 Update changelog
2025-11-10 17:10:59 +01:00
Andrey Antukh
c1058c7fdb ♻️ Add minor refactor for internal concurrency model
Replace general usage of virtual threads with platform threads
and use virtual threads for lightweight procs such that websocket
connections. This decision is made mainly because virtual threads
does not appear on thread dumps in an easy way so debugging issues
becomes very difficult.

The threads requirement of penpot for serving http requests
is not very big so having so this decision does not really affects
the resource usage.
2025-09-26 14:35:06 +02:00
Andrey Antukh
283eb0419c ♻️ Refactor time related namespaces
Mainly removes the custom app.util.time namespace
from frontend and backend and normalize all to use
the app.common.time namespace
2025-08-01 11:20:01 +02:00
Andrey Antukh
37cec8891f 🎉 Add inplace binfile import support 2025-07-30 12:23:40 +02:00
Andrey Antukh
cf274099c4 Improve events/sse internal API
For make code cleaner and more evident for a quick view
2025-05-18 17:30:41 +02:00
Andrey Antukh
88fb5e7ab5 ♻️ Update integrant to latest version
This upgrade also includes complete elimination of use spec
from the backend codebase, completing the long running migration
to fully use malli for validation and decoding.
2024-11-13 19:09:19 +01:00
Andrey Antukh
607e0c5c1d Move team invitations and access requests to a separate namespace
This commit also comes with:

- a fix for incorrect conflict handling on team access request creation
- a fix for incorrect handling of file-data when it is offloaded
- replace some inneficient queries with effcient ones
- remove redundant validation on creation of request-access
2024-11-13 14:16:18 +01:00
Andrey Antukh
cc6e071f48 ♻️ Remove all usage of graalvm js runtime
And replace it with a commandline call to nodejs
for execute a custom svgo based command line script.
2024-10-22 23:30:56 +02:00
Andrey Antukh
51ecbf15a9 ⬆️ Update yetti and http server dependency 2024-10-22 20:23:38 +02:00
alonso.torres
03040ed40b 🐛 Fix problem when dismissing shared library update 2024-09-06 11:02:02 +02:00
Andrey Antukh
cacee40d11 🎉 Add proper schema encoding/decoding mechanism
this allows almost all api operations to success usin application/json
encoding with the exception of the update-file, which we need to
approach a bit differently;

the reason update-file is different, is because the operations vector
is right now defined without the context of shape type, so we are just
unable to properly parse the value to correct type using the schema
decoding mechanism
2024-08-21 11:27:36 +02:00
Andrey Antukh
025034cb71 Merge remote-tracking branch 'origin/staging' into develop 2024-07-25 11:23:42 +02:00
Andrey Antukh
343f3feed3 Improve ip-addr parsing 2024-07-24 21:07:11 +02:00
Andrey Antukh
9174bb140b ♻️ Refactor configuration validation
Replace spec with schema
2024-07-10 15:16:28 +02:00
Andrey Antukh
d2bedec59c Unify naming of schema registering functions 2024-07-04 12:30:28 +02:00
Andrey Antukh
3363793d64 🐛 Fix json encoding truncation issue 2024-06-19 07:59:28 +02:00
Andrey Antukh
7e803eeca8 Add minor improvements for fdata logging 2024-03-22 12:58:50 +01:00
Andrey Antukh
ba55d657a4 Prevent adding object map to not loaded pointer-map containers 2024-02-14 17:34:50 +01:00
Andrey Antukh
43b8ccb52e Improve error handling on websocket code 2024-02-09 12:01:09 +01:00
Andrey Antukh
cdf312fdd9 Add better progress reporting
For components migration and for binfile import process
2024-01-30 16:27:16 +01:00
Andrey Antukh
8d0afd8c96 🐛 Add migration for fix invalid shadows 2024-01-25 16:03:30 +01:00
Andrey Antukh
6ad6e6f856 🐛 Fix objects-map and pointer-map issues on file crud 2024-01-25 16:03:29 +01:00
Andrey Antukh
92643b29c1 Improve internal cache api 2024-01-25 15:59:45 +01:00
Andrey Antukh
0ebf9564b2 Add internal helper for team duplication 2024-01-02 12:01:07 +01:00
Andrey Antukh
ecee15af5b Improve logging on websocket related code (backend) 2023-12-26 14:14:20 +01:00
Andrey Antukh
76a6f077a6 🐛 Fix incorrect feature handling on absorb-library! fn
Used in shared flag assignation and library deletion
2023-12-13 11:56:20 +01:00
Andrey Antukh
87615ce221 💄 Fix format issues on backend module 2023-11-29 12:55:58 +01:00
Andrey Antukh
bb5a4c0fa5 Update yetti and adapt for ring-2.0 2023-11-27 14:25:12 +01:00
Andrey Antukh
00afb841ac Add svg optimization on components migration process 2023-11-07 12:48:31 +01:00
Andrey Antukh
6f93b41920 🎉 Add features assignation for teams 2023-11-07 12:48:31 +01:00
Andrey Antukh
405aa66357 🎉 Add new shape & rect data structures
Also optimizes some functions for faster shape and rect props
access (there is still a lot of work ahead optimizing the rest of
the functions)

Also normalizes shape creation and validation for ensuring
correct setup of all the mandatory properties.
2023-07-11 17:27:35 +02:00
Andrey Antukh
1d4bd34dfc Move fressian to common module 2023-05-26 08:04:01 +02:00
Andrey Antukh
63f4ef97fb 🐛 Fix pointermap issue on file export 2023-05-17 16:05:31 +02:00
Andrey Antukh
5ca3d01ea1 🎉 Add malli based validation and coersion subsystem 2023-05-17 16:05:29 +02:00
Andrey Antukh
4e7f32aa88 Improve retry mechanism and macros 2023-05-17 15:47:21 +02:00
Andrés Moya
8a42a53522 Notify library updates when really needed 2023-05-17 14:12:49 +02:00
Andrey Antukh
2818666a1a 📎 Fix minnor cosmetic issue on instant and duration pretty printing 2023-03-16 22:33:35 +01:00
Andrey Antukh
c9ec5234d3 ♻️ Refactor local in-memory cache api 2023-03-14 12:30:27 +01:00
Andrey Antukh
2cddc49463 Remove several reflection calls 2023-03-14 12:30:27 +01:00
Andrey Antukh
aafbf6bc15 ♻️ Refactor cocurrency model on backend
Mainly the followin changes:

- Pass majority of code to the old and plain synchronous style
  and start using virtual threads for the RPC (and partially some
  HTTP server middlewares).
- Make some improvements on how CLIMIT is handled, simplifying code
- Improve considerably performance reducing the reflection and
  unnecesary funcion calls on the whole stack-trace of an RPC call.
- Improve efficiency reducing considerably the total threads number.
2023-03-14 12:30:27 +01:00
Andrey Antukh
2e717882f1 ♻️ Refactor websockets impl to use virtual threads
Removing the use of core.async code and implement code using
plain old and familiar synchronous code
2023-03-14 12:30:27 +01:00
Andrey Antukh
1325e46192 Improve internal state validation on db module 2023-02-02 14:20:13 +01:00
Andrey Antukh
bb055a3c84 ♻️ Refactor logging subsystem and error reporting 2023-02-02 13:38:04 +01:00
Andrey Antukh
db689d151e ♻️ Refactor profile and session handling
- makes the profile access more efficient (replace in-app joins to a
  simple select query on profile table
- add partial support for access-tokens (still missing some RPC methods)
- move router definitions to specific modules and simplify the main http
  module definitions to simple includes
- simplifiy authentication code related to access-tokens and sessions
- normalize db parameters with proper namespaced props
- more work on convert all modules initialization to use proper specs
  with fully-qualified keyword config props
2023-01-18 10:51:58 +01:00