Commit Graph

73301 Commits

Author SHA1 Message Date
Patrik Oldsberg e4804abb44 Add DialogApi.open() and deprecate show/showModal
The existing show() and showModal() methods render dialog chrome (a
Material UI Dialog) as part of the implementation. This causes focus
trap conflicts when the caller's content uses components from a
different design library (e.g. Backstage UI).

The new open() method renders the caller's content as-is, without any
dialog chrome. The caller provides the full dialog component including
overlay, backdrop, and surface, making the API design-library-agnostic.

The deprecated show/showModal are re-implemented on top of open() with
a MUI Dialog wrapper for backward compatibility, and emit console
warnings when used.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-12 11:14:02 +02:00
Andre Wanlin a52a2236d4 Merge pull request #33808 from meleu/patch-3
Update TechDocs CLI repo link, as the old repo was archived in 2021
2026-04-11 15:18:43 -05:00
Patrik Oldsberg 0ecb8225cb Merge pull request #33839 from jonkoops/deprecate-proxy-bootstrap
refactor(cli-common): deprecate `bootstrapEnvProxyAgents()` in favor of Node.js built-in proxy support
2026-04-11 12:05:55 +02:00
Fredrik Adelöw 6a34f8a26f Merge pull request #33841 from backstage/dependabot/npm_and_yarn/basic-ftp-5.2.2 2026-04-11 08:31:36 +02:00
Suhrid Marwah f7cddd3f20 fix(notifications): handle limit=0 in getNotifications query
Replace falsy guards with explicit undefined checks so that a
limit or offset of 0 is not silently discarded.

Signed-off-by: Suhrid Marwah <suhridmarwah07@gmail.com>
2026-04-11 04:32:24 +05:30
dependabot[bot] dcfc229155 chore(deps): bump basic-ftp from 5.2.0 to 5.2.2
Bumps [basic-ftp](https://github.com/patrickjuchli/basic-ftp) from 5.2.0 to 5.2.2.
- [Release notes](https://github.com/patrickjuchli/basic-ftp/releases)
- [Changelog](https://github.com/patrickjuchli/basic-ftp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/patrickjuchli/basic-ftp/compare/v5.2.0...v5.2.2)

---
updated-dependencies:
- dependency-name: basic-ftp
  dependency-version: 5.2.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-10 21:32:39 +00:00
Aramis Sennyey 2b4f97adf7 docs: frontend plugin golden path (#33541)
* docs: frontend plugin golden path guide

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* add changeset

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* Apply suggestion from @aramissennyeydd

Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix template

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix template test

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* print stderr on failure

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* try writing directly

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* maybe this?

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* address feedback

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix: avoid destructuring FetchApi and fix template issues

- Use fetchApi.fetch() instead of destructuring to preserve this binding
- Add discoveryApi and fetchApi to useAsync dependency array
- Use react-use/esm/useAsync to match repo conventions
- Replace waitFor + getAllByText with findByText in error test
- Update HTTP client doc to match template changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix: address docs review feedback

- Use stronger guidance tone in scaffolding guide intro
- Slim down file tree to show folder structure only
- Mention that plugin path depends on chosen plugin ID
- Link to installation docs for non-discovery case
- Quote page:todo YAML key to avoid parse errors
- Remove "new" from "new frontend system" in template README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix: improve error handling in e2e plugin creation

- Narrow error to non-null object before using in operator
- Also write error.stdout since tools like Jest report to stdout
- Avoid variable shadowing with outer scope stdout/stderr

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* revert: keep destructured fetch from FetchApi

Destructuring fetch from FetchApi is fine — revert to original
pattern while keeping the dependency array and other fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* feat: use @backstage/ui components in frontend plugin template

Replace core-components layout and table with @backstage/ui equivalents:
- Use HeaderPage and Container instead of Page, Header, Content, ContentHeader
- Use BUI Table with useTable and CellText instead of core-components Table
- Add @backstage/ui to template package.json dependencies
- Update poking-around docs to reflect BUI component usage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix: add example data when backend request fails

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* better logging setup

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* address feedback

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* better config driven example

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* debug logs

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* fix build failure related to unknown version

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* revert e2e run changes

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>

* skip the discovery api for now

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* remove another ref

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>

---------

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-10 14:00:55 -04:00
Patrik Oldsberg 5b6061ac77 Address review feedback: zod import path and legacy route ref
Use explicit zod/v4 import path in tests, and remove unnecessary
convertLegacyRouteRef wrapper in catalog-graph README.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 16:54:06 +02:00
Jon Koops 46ff47034c refactor(cli-common): deprecate bootstrapEnvProxyAgents() in favor of Node.js built-in proxy support
Node.js 22.21.0+ and 24.5.0+ support proxy configuration natively
via NODE_USE_ENV_PROXY=1 and --use-env-proxy, making the legacy
global-agent and undici proxy workarounds unnecessary.

Rather than removing the function immediately, deprecate it with
context-aware runtime warnings that guide users based on their
current configuration:

- Users with GLOBAL_AGENT_* vars are told to switch to standard
  HTTP_PROXY/HTTPS_PROXY and set NODE_USE_ENV_PROXY=1.
- Users with HTTP_PROXY/HTTPS_PROXY but no NODE_USE_ENV_PROXY are
  told to set it.
- Users who have already opted in to Node.js built-in proxy see no
  warning, and the legacy bootstrap is skipped entirely.

See #33444

Signed-off-by: Jon Koops <jonkoops@gmail.com>
2026-04-10 16:53:33 +02:00
Fredrik Adelöw 05b1de4321 Merge pull request #33680 from rolandfuszenecker-seon/feat/aws-rds-iam-auth
feat(backend-defaults): add AWS RDS IAM authentication support for PostgreSQL
2026-04-10 16:47:13 +02:00
Patrik Oldsberg 461d4fc48b Clean up parse output and schema enumerability
Skip assigning undefined keys for absent optional fields in parse,
matching the previous zod-object behavior. Make the schema getter
non-enumerable so JSON.stringify on the portable schema only
serializes parse and _fields.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 15:09:02 +02:00
Patrik Oldsberg 27f6fb30e7 Update SearchResultListItemBlueprint snapshot
The inline snapshot was stale after the PortableSchema internal
representation changed to use lazy schema and _fields structure.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 14:42:40 +02:00
Patrik Oldsberg fe8473b5f1 Fix review feedback: override warnings and search docs
Add explicit deprecation warnings in override and makeWithOverrides when
config.schema is used, since the merged result now passes through
configSchema. Update search declarative-integration docs to use
SearchResultListItemBlueprint instead of the removed extension creator.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 13:58:38 +02:00
Fredrik Adelöw 907bd33833 Revert locationKey change; keep allowedLocationTypes validation on updateLocation
Reverts the location_entity_ref-as-locationKey change: the full mutation on
startup would compare existing rows (locationKey = url:target) against the
new values and trigger a remove+add cycle for every location. The type:target
locationKey is kept as-is to preserve the existing startup contract.

Keeps the allowedLocationTypes validation added to DefaultLocationService.updateLocation.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-10 13:57:47 +02:00
Fredrik Adelöw 068f4739ac Use stable location_entity_ref as locationKey; validate allowedLocationTypes
Use location_entity_ref as the locationKey in all applyMutation calls
instead of type:target. This prevents the catalog from treating a type/target
update as a remove+re-add cycle (which would temporarily prune the entity
and its descendants). The location_entity_ref never changes after creation,
so the catalog can safely upsert the entity in-place on updateLocation.

Also add allowedLocationTypes validation to updateLocation in
DefaultLocationService, matching the existing check in createLocation.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-10 13:44:14 +02:00
Patrik Oldsberg 27bc970c91 Fix review feedback: override warning, input guard, required tests
Pass merged config schemas via configSchema instead of config.schema in
the override method to avoid false deprecation warnings. Add type guard
for non-object inputs in parse. Add tests for defaulted field required
semantics (already correct) and invalid input types.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 13:16:25 +02:00
aarish mansur b871d4e335 chore: add changeset
Signed-off-by: aarish mansur <aarishmansur@gmail.com>
2026-04-10 16:28:42 +05:30
Patrik Oldsberg 8330f1319a frontend-plugin-api: restore @ignore on internal utility types
Route createExtension overloads through CreateExtensionOptions so that
ResolvedExtensionInputs, VerifyExtensionFactoryOutput, VerifyExtensionAttachTo,
and RequiredExtensionIds can remain @ignore without ae-forgotten-export warnings.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 12:52:59 +02:00
aarish mansur 2143a0ee85 feat(api-docs): use catalog presentation for API titles
Signed-off-by: aarish mansur <aarishmansur@gmail.com>
2026-04-10 16:10:28 +05:30
Patrik Oldsberg effa7bf459 Fix missing changesets and tsc errors from CI
Add changesets for plugin-app and plugin-catalog-graph. Fix cross-style
merge test to use direct schema values with configSchema instead of
factory functions.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 12:26:25 +02:00
Fredrik Adelöw 18d6f00afb Mark CatalogService updateLocation addition as BREAKING PRODUCERS in changeset
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-10 12:08:28 +02:00
Patrik Oldsberg a2a6c3b72e Add migration docs and changeset for new configSchema option
Add 1.50 migration section documenting the config.schema to configSchema
migration with examples for createExtension, createExtensionBlueprint,
and makeWithOverrides. Add a separate changeset for the new feature and
update the existing breaking changeset to reference the migration docs.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 11:51:22 +02:00
Patrik Oldsberg 540a03171c Add missing changeset and test coverage for PR review gaps
Add changeset for catalog-react blueprint migration. Add tests for
cross-style config merge (configSchema + deprecated config.schema),
deprecation warning emission, and empty configSchema edge case.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 11:28:38 +02:00
Patrik Oldsberg 2d89e198bd frontend-plugin-api: remove deprecated createSchemaFromZod
The helper is no longer used internally and has been replaced by
the `configSchema` option with direct Standard Schema values.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 11:18:03 +02:00
Patrik Oldsberg 1e6d2e91ad frontend-plugin-api: thorough error message tests for portable schema
Cover zod v3, zod v4, mixed, and merged schema error messages
with exact string assertions to document the error format produced
for missing fields, type mismatches, nested paths, and multi-field
errors.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 11:13:27 +02:00
Patrik Oldsberg 3218028048 docs: update extension config schema examples to new configSchema format
Switch all documentation examples from the deprecated
`config: { schema: { field: z => z.type() } }` pattern to the new
`configSchema: { field: z.type() }` format using zod v4 imports.
Also update catalog-graph README to use current blueprint APIs.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 10:58:21 +02:00
Fredrik Adelöw e3fd1d0f8e Mark entityRef addition as breaking for Location producers in changeset
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-10 10:52:20 +02:00
Fredrik Adelöw f0d82ac4b0 Merge pull request #33834 from backstage/freben/exit
exit prerelease mode
2026-04-10 10:44:50 +02:00
Patrik Oldsberg 1ef7954725 Migrate catalog-react and app blueprints to configSchema
Move EntityCardBlueprint and EntityContentBlueprint to the new
`configSchema` option using zod v3, and AppLanguageApi to zod v4.
Fix config schema merge in `makeWithOverrides` when mixing
`configSchema` and deprecated `config.schema` sources.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 10:39:50 +02:00
Fredrik Adelöw de2eb783a0 exit prerelease mode
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
2026-04-10 10:33:51 +02:00
Patrik Oldsberg 8bb8560557 frontend-plugin-api: always warn on deprecated config.schema with call site
Instead of a one-time warning, emit a deprecation warning every time
an extension is created using the deprecated `config.schema` option,
including the call site location to help track down each usage.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 10:19:51 +02:00
Patrik Oldsberg 426d1b389f frontend-plugin-api: clean up comments in createPortableSchema
Replace box-style section comments with TSDoc comments to match
the style used throughout the rest of the repository.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 10:17:35 +02:00
Patrik Oldsberg 1f80e1a5a4 frontend-plugin-api: per-field config schema with lazy JSON Schema
Replace the monolithic `createSchemaFromZod` approach with per-field
schema resolution via `createConfigSchema`. Each field is resolved
individually and eagerly validated for JSON Schema conversion support,
but the actual JSON Schema generation is deferred until first access.

`PortableSchema.schema` is now a lazy callable — it can still be
accessed as a property (backward compat, deprecated) or called as a
method returning `{ schema: JsonObject }` for the new API.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 10:13:19 +02:00
Jack Palmer 28a362f2f7 Remove unused type parameter from ExtensionPointFactoryMiddleware
The generic is no longer needed since the interface is opaque. Type
inference is handled by createExtensionPointFactoryMiddleware instead.

Signed-off-by: Jack Palmer <jackpalmer@spotify.com>
2026-04-10 09:03:12 +01:00
Patrik Oldsberg 7ff3429bda Merge pull request #33831 from drodil/get_notifications_action
feat(notifications): action to get users notifications
2026-04-10 09:42:16 +02:00
Patrik Oldsberg 0d398f3271 frontend-plugin-api: remove ConfigFieldSchema and fix API report warnings
Remove the `ConfigFieldSchema` and `ConfigSchemaRecord` types that are
no longer needed now that `configSchema` and `config.schema` each accept
only one form. The deprecated overloads now constrain directly to the
factory signature `(zImpl: typeof z) => z.ZodType`.

Also fix pre-existing API report warnings by promoting
`ResolvedExtensionInputs`, `RequiredExtensionIds`,
`VerifyExtensionFactoryOutput`, and `VerifyExtensionAttachTo` to
`@public` and exporting them from both entry points.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 09:21:40 +02:00
Hellgren Heikki 4c1fd438b3 feat(notifications): action to get users notifications
useful for mcp for example to get the daily what is going on
status.

Signed-off-by: Hellgren Heikki <heikki.hellgren@op.fi>
2026-04-10 10:19:46 +03:00
Patrik Oldsberg 4c7905d22c frontend-plugin-api: add configSchema option and deprecate config.schema
Introduce a new top-level `configSchema` option for `createExtension`,
`createExtensionBlueprint`, `override`, and `makeWithOverrides` that
accepts Standard Schema values directly. The old `config.schema` form
is deprecated via function/method overloads so that the entire call
site gets editor strikethrough when matched.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-10 08:54:43 +02:00
Fredrik Adelöw a25a9b8573 Merge pull request #33826 from backstage/dependabot/npm_and_yarn/axios-1.15.0 2026-04-09 21:28:03 +02:00
dependabot[bot] 9b09aba3ed chore(deps-dev): bump axios from 1.14.0 to 1.15.0
Bumps [axios](https://github.com/axios/axios) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.15.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-09 18:32:42 +00:00
Patrik Oldsberg aebba3f485 Merge pull request #33426 from backstage/rugvip/rename-create-app-templates
create-app: rename template directories
2026-04-09 20:25:58 +02:00
Patrik Oldsberg 70336a127c Merge pull request #33664 from backstage/scaffolder-actions-single-table
scaffolder: migrate actions page to @backstage/ui components
2026-04-09 20:25:49 +02:00
Patrik Oldsberg 787200224e frontend-plugin-api: use @standard-schema/spec dependency instead of inlining
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-09 18:45:20 +02:00
Fredrik Adelöw a328fd358f Add conflict check on updateLocation and authorization tests
Prevent updating a location to a {type, target} already used by another
location, matching the invariant enforced by createLocation. Also adds
ALLOW/DENY tests for updateLocation in AuthorizedLocationService.

Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
2026-04-09 17:21:06 +02:00
Fredrik Adelöw 5b61c2f339 Merge pull request #33822 from backstage/freben/refactor-postgres-retry-loop
refactor(backend-defaults): clean up database creation retry loop
2026-04-09 17:11:30 +02:00
Jack Palmer e782afcb3b Address PR review comments
- Make ExtensionPointFactoryMiddleware an opaque type via new
  @internal/backend package using OpaqueType from @internal/opaque
- Use options object for createExtensionPointFactoryMiddleware
- Make middleware function async (returns Promise<T>)
- Remove extensionPointFactoryMiddleware from createBackend, keep only
  on createSpecializedBackend
- Export defaultServiceFactories from @backstage/backend-defaults

Signed-off-by: Jack Palmer <jackpalmer@spotify.com>
2026-04-09 15:59:44 +01:00
Erik Miller 49cab31527 fix: use database clock and separate migrations table for slack module
Address reviewer feedback:
- Use a dedicated migrations table to avoid conflicts with the parent plugin
- Use database-native now() instead of JS Date for timestamp columns
- Use database-level interval arithmetic for cleanup retention cutoff

Signed-off-by: Erik Miller <erik.miller@gusto.com>
2026-04-09 07:59:41 -07:00
Patrik Oldsberg 23a35d1b91 frontend-plugin-api: widen config schema constraint to accept Standard Schema
Widens the TConfigSchema generic constraint in createExtension,
createExtensionBlueprint, and their override/makeWithOverrides methods
to accept both the existing zod factory form and direct Standard Schema
instances via the new ConfigFieldSchema union type.

Existing consumers are unaffected — the factory form continues to
infer concrete types through z.infer<ReturnType<...>>. Direct Standard
Schema values are accepted but infer as any in the current iteration.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-09 16:36:00 +02:00
Patrik Oldsberg 6541cbfc58 Remove stray package.json from create-app templates
These empty `{}` files were accidentally committed during the template
directory rename and override the properly templated package.json
generated from package.json.hbs, causing E2E tests to fail.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-09 15:52:20 +02:00
Patrik Oldsberg 7fc1a406d2 Increase E2E timeouts for default-app template
The new frontend system app takes longer to compile and render on
Windows CI runners. Switch from port-based to URL-based server
readiness detection and increase expect timeout to 30s to avoid
flaky failures on slow runners.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
2026-04-09 15:52:20 +02:00