Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ DB_PASSWORD=postgres

FPH_ENABLED=true
CSP_ENABLED=true
CSP_NONCE_ENABLED=true

SESSION_DRIVER=database
SESSION_LIFETIME=120
Expand Down
4 changes: 4 additions & 0 deletions app/Security/Presets/MyCspPreset.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public function configure(Policy $policy): void

$policy->add(Directive::SCRIPT_ELEM, $scriptSources);

$policy->addNonce(Directive::SCRIPT);

$policy->addNonce(Directive::SCRIPT_ELEM);

$styleSources = array_filter([
Keyword::SELF,
$cdnHost ?: null,
Expand Down
31 changes: 31 additions & 0 deletions app/Security/Replacers/CspHeaderReplacer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\Security\Replacers;

use Spatie\ResponseCache\Replacers\Replacer;
use Symfony\Component\HttpFoundation\Response;

class CspHeaderReplacer implements Replacer
{
/** @var list<string> */
protected array $headers = [
'Content-Security-Policy',
'Content-Security-Policy-Report-Only',
];

public function prepareResponseToCache(Response $response): void
{
foreach ($this->headers as $header) {
$response->headers->remove($header);
}
}

public function replaceInCachedResponse(Response $response): void
{
foreach ($this->headers as $header) {
$response->headers->remove($header);
}
}
}
4 changes: 2 additions & 2 deletions app/Seo/SchemaGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ private function breadcrumbList(string $url): ?array
}

/**
* Title of the page being rendered, stripped of the " – codebar Solutions AG"
* suffix that belongs in <title> but not in a breadcrumb.
* Title of the page being rendered, reduced to the part before the first
* separator: a breadcrumb carries the label, not the full title.
*/
private function currentPageName(): ?string
{
Expand Down
2 changes: 1 addition & 1 deletion config/csp.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@
* and cannot add inline nonces.
* Note that this will make your CSP policy less secure.
*/
'nonce_enabled' => env('CSP_NONCE_ENABLED', false),
'nonce_enabled' => env('CSP_NONCE_ENABLED', true),
];
2 changes: 1 addition & 1 deletion config/health.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
/*
* Notifications will only get sent if this option is set to `true`.
*/
'enabled' => true,
'enabled' => (bool) env('HEALTH_NOTIFICATION_EMAIL'),

'notifications' => [
CheckFailedNotification::class => ['mail'],
Expand Down
2 changes: 2 additions & 0 deletions config/responsecache.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use App\Security\Replacers\CspHeaderReplacer;
use Spatie\ResponseCache\CacheProfiles\CacheAllSuccessfulGetRequests;
use Spatie\ResponseCache\Hasher\DefaultHasher;
use Spatie\ResponseCache\Replacers\CsrfTokenReplacer;
Expand Down Expand Up @@ -123,5 +124,6 @@
*/
'replacers' => [
CsrfTokenReplacer::class,
CspHeaderReplacer::class,
],
];
4 changes: 2 additions & 2 deletions database/files/pages/about-us.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: about-us.index
robots: index,follow
image: images/pages/about-us.index.svg
title:
de_CH: 'Team – die Menschen hinter codebar Solutions AG'
en_CH: 'Team – the People Behind codebar Solutions AG'
de_CH: 'Team – die Menschen hinter codebar'
en_CH: 'Team – the People Behind codebar'
description:
de_CH: 'Klein aus Überzeugung: kurze Wege, direkte Ansprechpersonen – und Ausbildung als Teil unserer Kultur. Lerne die Menschen hinter codebar kennen.'
en_CH: 'Small by conviction: short paths, direct contacts – and training as part of our culture. Meet the people behind codebar.'
4 changes: 2 additions & 2 deletions database/files/pages/ai.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: ai.index
robots: index,follow
image: images/pages/ai.index.svg
title:
de_CH: 'Lokale KI auf eigener Infrastruktur | codebar Solutions AG'
en_CH: 'Local AI on Our Own Infrastructure | codebar Solutions AG'
de_CH: 'Lokale KI auf eigener Infrastruktur'
en_CH: 'Local AI on Our Own Infrastructure'
description:
de_CH: 'Transparenz statt Buzzwords: Wir zeigen offen, wie wir KI in der eigenen Arbeit einsetzen – mit lokalen Open-Source-Modellen und echten Nutzungszahlen.'
en_CH: 'Transparency over buzzwords: an open look at how we use AI in our own work – with local open-source models and real usage figures.'
4 changes: 2 additions & 2 deletions database/files/pages/ai.llm.analytics.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: ai.llm.analytics.index
robots: index,follow
image: images/pages/ai.llm.analytics.index.svg
title:
de_CH: 'LLM-Nutzungsstatistik – codebar Solutions AG'
en_CH: 'LLM Usage Analytics – codebar Solutions AG'
de_CH: 'LLM-Nutzungsstatistik'
en_CH: 'LLM Usage Analytics'
description:
de_CH: 'Token-Verbrauch und Anfragen unserer lokal betriebenen Modelle – transparent aufgeschlüsselt pro Monat und Modell.'
en_CH: 'Token consumption and requests of our locally run models – transparently broken down per month and model.'
4 changes: 2 additions & 2 deletions database/files/pages/ai.llm.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: ai.llm.index
robots: index,follow
image: images/pages/ai.llm.index.svg
title:
de_CH: 'Unsere lokalen LLMs im Einsatz – codebar Solutions AG'
en_CH: 'Our Local LLMs in Action – codebar Solutions AG'
de_CH: 'Unsere lokalen LLMs im Einsatz'
en_CH: 'Our Local LLMs in Action'
description:
de_CH: 'Diese lokalen Open-Source-Modelle betreiben wir aktuell – auf eigener Hardware im hauseigenen Bürokeller. Modelle, Infrastruktur und Nutzung.'
en_CH: 'The local open-source models we currently run – on our own hardware, in our own office basement. Models, infrastructure and usage.'
4 changes: 2 additions & 2 deletions database/files/pages/co-working.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: co-working.index
robots: index,follow
image: images/pages/co-working.index.svg
title:
de_CH: 'Co-Working bei codebar Solutions AG'
en_CH: 'Co-Working at codebar Solutions AG'
de_CH: 'Co-Working bei codebar'
en_CH: 'Co-Working at codebar'
description:
de_CH: 'Ein professioneller Arbeitsplatz in Oberwil — ruhig, gut ausgestattet und Teil eines Tech-Teams.'
en_CH: 'A professional workspace in Oberwil — quiet, well-equipped, and embedded in a tech team.'
4 changes: 2 additions & 2 deletions database/files/pages/contact.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: contact.index
robots: index,follow
image: images/pages/contact.index.svg
title:
de_CH: "Kontakt – lass uns sprechen | codebar Solutions AG"
en_CH: "Contact – Let's Talk | codebar Solutions AG"
de_CH: "Kontakt – lass uns sprechen"
en_CH: "Contact – Let's Talk"
description:
de_CH: 'Erzähl uns von deiner Idee oder deinem Projekt – wir hören zu. Telefon, E-Mail und unsere zwei Standorte in der Region Basel.'
en_CH: "Tell us about your idea or your project – we'll listen. Phone, email and our two locations in the Basel region."
4 changes: 2 additions & 2 deletions database/files/pages/jobs.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: jobs.index
robots: index,follow
image: images/pages/jobs.index.svg
title:
de_CH: 'Stellen – arbeiten bei codebar Solutions AG'
en_CH: 'Jobs – Working at codebar Solutions AG'
de_CH: 'Stellen – arbeiten bei codebar'
en_CH: 'Jobs – Working at codebar'
description:
de_CH: 'Klein aus Überzeugung: Verantwortung ab Tag eins, offene Technologien und Praktika mitten im Projektalltag. So arbeitest du bei codebar.'
en_CH: 'Small by conviction: responsibility from day one, open technologies and internships inside real projects. This is what working at codebar is like.'
4 changes: 2 additions & 2 deletions database/files/pages/legal.imprint.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: legal.imprint.index
robots: index,follow
image: images/pages/legal.imprint.index.svg
title:
de_CH: 'Impressum – codebar Solutions AG'
en_CH: 'Imprint – codebar Solutions AG'
de_CH: 'Impressum'
en_CH: 'Imprint'
description:
de_CH: 'Rechtliche Angaben zur codebar Solutions AG: Rechtsform, UID-Nummer, Handelsregistereintrag, Zeichnungsberechtigte sowie Kontaktdaten und Haftungsausschluss.'
en_CH: 'Legal details of codebar Solutions AG: legal form, UID number, commercial register entry, authorised representatives, contact details and disclaimer.'
4 changes: 2 additions & 2 deletions database/files/pages/legal.privacy.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: legal.privacy.index
robots: index,follow
image: images/pages/legal.privacy.index.svg
title:
de_CH: 'Datenschutz – codebar Solutions AG'
en_CH: 'Privacy – codebar Solutions AG'
de_CH: 'Datenschutz'
en_CH: 'Privacy'
description:
de_CH: 'Wie wir Personendaten auf codebar.ch bearbeiten: welche Daten anfallen, wofür wir sie nutzen, wie lange wir sie aufbewahren – und welche Rechte du hast.'
en_CH: 'How we process personal data on codebar.ch: what we collect, why, how long we keep it – and the rights you have.'
4 changes: 2 additions & 2 deletions database/files/pages/legal.terms.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: legal.terms.index
robots: index,follow
image: images/pages/legal.terms.index.svg
title:
de_CH: 'AGB – codebar Solutions AG'
en_CH: 'Terms & Conditions – codebar Solutions AG'
de_CH: 'AGB'
en_CH: 'Terms & Conditions'
description:
de_CH: 'Die Allgemeinen Geschäftsbedingungen der codebar Solutions AG: Angebote, Projektabwicklung, Nutzungsrechte, Haftung und Support.'
en_CH: 'The general terms and conditions of codebar Solutions AG: offers, project delivery, rights of use, liability and support.'
4 changes: 2 additions & 2 deletions database/files/pages/media.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: media.index
robots: index,follow
image: images/pages/media.index.svg
title:
de_CH: 'Medien & Markenassets – codebar Solutions AG'
en_CH: 'Media & Brand Assets – codebar Solutions AG'
de_CH: 'Medien & Markenassets'
en_CH: 'Media & Brand Assets'
description:
de_CH: 'Offizielle codebar-Logos für Presse und Partner – farbig, invertiert, schwarz-weiss, als PNG und SVG.'
en_CH: 'Official codebar logos for press and partners – colour, inverted, black and white, as PNG and SVG.'
4 changes: 2 additions & 2 deletions database/files/pages/network.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: network.index
robots: index,follow
image: images/pages/network.index.svg
title:
de_CH: 'Netzwerk – Partner & Community | codebar Solutions AG'
en_CH: 'Network – Partners & Community | codebar Solutions AG'
de_CH: 'Netzwerk – Partner & Community'
en_CH: 'Network – Partners & Community'
description:
de_CH: 'Mit wem wir arbeiten: Projekt-, Software- und Infrastrukturpartner, unser Engagement in der Community – und die Labels, die dahinterstehen.'
en_CH: 'Who we work with: project, software and infrastructure partners, our community engagement – and the labels behind it.'
4 changes: 2 additions & 2 deletions database/files/pages/network.request.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: network.request.index
robots: noindex,nofollow
image: images/pages/network.request.index.svg
title:
de_CH: 'Netzwerk-Profil aktualisieren – codebar Solutions AG'
en_CH: 'Update network profile – codebar Solutions AG'
de_CH: 'Netzwerk-Profil aktualisieren'
en_CH: 'Update network profile'
description:
de_CH: 'Persönlichen Link anfordern, um das eigene Profil im codebar Netzwerk zu aktualisieren.'
en_CH: 'Request a personal link to update your codebar network profile.'
4 changes: 2 additions & 2 deletions database/files/pages/news.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: news.index
robots: index,follow
image: images/pages/news.index.svg
title:
de_CH: 'Neuigkeiten & Insights – codebar Solutions AG'
en_CH: 'News & Insights – codebar Solutions AG'
de_CH: 'Neuigkeiten & Insights'
en_CH: 'News & Insights'
description:
de_CH: 'Aktuelle News, Fachbeiträge und Trends rund um Softwareentwicklung, offene Technologien und digitale Innovation von codebar.'
en_CH: 'Latest news and expert insights on software development, open technologies and digital innovation from codebar.'
4 changes: 2 additions & 2 deletions database/files/pages/open-source.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: open-source.index
robots: index,follow
image: images/pages/open-source.index.svg
title:
de_CH: 'Open-Source-Beiträge – codebar Solutions AG'
en_CH: 'Open Source Contributions – codebar Solutions AG'
de_CH: 'Open-Source-Beiträge'
en_CH: 'Open Source Contributions'
description:
de_CH: 'Unsere Beiträge an die Open-Source-Community – Packages, Tools und Libraries, entwickelt und gepflegt von codebar.'
en_CH: 'Our contributions to the open source community – packages, tools and libraries developed and maintained by codebar.'
4 changes: 2 additions & 2 deletions database/files/pages/products.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: products.index
robots: index,follow
image: images/pages/products.index.svg
title:
de_CH: 'Nutzerzentrierte Softwarelösungen – codebar Solutions AG'
en_CH: 'User-Centric Software Solutions – codebar Solutions AG'
de_CH: 'Nutzerzentrierte Softwarelösungen'
en_CH: 'User-Centric Software Solutions'
description:
de_CH: 'Nutzerzentrierte Softwarelösungen mit echtem Mehrwert – entwickelt mit offenen Technologien und Standards.'
en_CH: 'Our software solutions are built around the needs of users, delivering real value through open technologies and standards.'
4 changes: 2 additions & 2 deletions database/files/pages/services.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: services.index
robots: index,follow
image: images/pages/services.index.svg
title:
de_CH: 'Konzeption, Software, DMS & ERP | codebar Solutions AG'
en_CH: 'Concept, Software, DMS & ERP | codebar Solutions AG'
de_CH: 'Konzeption, Software, DMS & ERP'
en_CH: 'Concept, Software, DMS & ERP'
description:
de_CH: 'Vier Bereiche, ein Weg: von der ersten Idee bis zum laufenden Betrieb – Konzeption, Softwareentwicklung, Dokumentenmanagement und ERP.'
en_CH: 'Four areas, one path: from the first idea to day-to-day operations – concept design, software development, document management and ERP.'
4 changes: 2 additions & 2 deletions database/files/pages/start.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: start.index
robots: index,follow
image: images/pages/start.index.svg
title:
de_CH: 'Innovative Ideen zum Leben erwecken – codebar Solutions AG'
en_CH: 'Bringing Innovative Ideas to Life – codebar Solutions AG'
de_CH: 'Innovative Ideen zum Leben erwecken'
en_CH: 'Bringing Innovative Ideas to Life'
description:
de_CH: 'Wir hören zu, verstehen dein Problem und begleiten dich von der ersten Idee bis zur Software im täglichen Einsatz. Ein kleines Team aus der Region Basel.'
en_CH: 'We listen, understand your problem and stay with you from the first idea to software in daily use. A small team based in the Basel region.'
4 changes: 2 additions & 2 deletions database/files/pages/technologies.index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ key: technologies.index
robots: index,follow
image: images/pages/technologies.index.svg
title:
de_CH: 'Offene Technologien & Standards – codebar Solutions AG'
en_CH: 'Open Technologies & Standards – codebar Solutions AG'
de_CH: 'Offene Technologien & Standards'
en_CH: 'Open Technologies & Standards'
description:
de_CH: 'Die offenen Technologien und Standards, auf denen unsere Software basiert – bewährt, transparent und herstellerunabhängig.'
en_CH: 'The open technologies and standards we build our software on – proven, transparent and vendor-independent.'
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public function up(): void
$table->string('url')->nullable();
$table->json('tags')->nullable();
$table->timestamps();

$table->index(['published', 'order']);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public function up(): void
$table->string('url')->nullable();
$table->json('tags')->nullable();
$table->timestamps();

$table->index(['published', 'order']);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public function up(): void
$table->string('image');
$table->json('icons')->nullable();
$table->timestamps();

$table->index(['published', 'sort']);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public function up(): void
$table->json('tags')->nullable();
$table->string('link')->nullable();
$table->timestamps();

$table->index(['published', 'order']);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ public function up(): void
$table->string('website')->nullable();
$table->unsignedSmallInteger('since_year')->nullable();
$table->unsignedSmallInteger('until_year')->nullable();
$table->string('page_slug')->nullable();
$table->string('page_slug')->nullable()->unique();
$table->boolean('published')->default(true);
$table->unsignedInteger('sort')->default(0);
$table->timestamps();

$table->index(['published', 'status', 'sort']);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function up(): void
$table->string('avatar_disk')->nullable();
$table->string('avatar_path')->nullable();
$table->string('avatar_url')->nullable();
$table->string('email')->nullable()->index();
$table->string('email')->nullable()->unique();
$table->string('public_email')->nullable();
$table->string('linkedin')->nullable();
$table->string('phone')->nullable();
Expand Down
9 changes: 2 additions & 7 deletions database/migrations/2026_07_28_150010_create_news_table.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@ public function up(): void
{
Schema::create('news', function (Blueprint $table) {
$table->id();
// Cross-language anchor: the de_CH and en_CH markdown files of one article share it.
$table->string('key')->unique();
$table->json('slug');
$table->json('title');
$table->json('teaser');
$table->json('content')->nullable();
$table->string('hero_image')->nullable();
// The square the index shows next to a list row. Its own file rather than a crop
// of the hero: the hero carries the title, and a square crop cuts the words.
$table->string('thumb_image')->nullable();
$table->json('hero_caption')->nullable();
$table->json('hero_alt')->nullable();
Expand All @@ -36,12 +33,10 @@ public function up(): void
$table->unsignedSmallInteger('reading_minutes')->nullable();
$table->json('tags')->nullable();
$table->timestamps();

$table->index(['published', 'published_at']);
});

// A JSON column cannot carry a plain unique constraint — index the extracted
// per-locale value instead, so each language keeps its own unique slug.
// PostgreSQL only: `->>` here takes a bare key, which is not valid MySQL.
// The whole application targets pgsql (see config/database.php).
foreach (['de_CH', 'en_CH'] as $locale) {
$index = 'news_slug_'.strtolower(str_replace('_', '', $locale)).'_unique';
DB::statement("CREATE UNIQUE INDEX {$index} ON news (( slug->>'{$locale}' ))");
Expand Down
Loading