diff --git a/.gitignore b/.gitignore index 3831f06..a9f26a3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ dist/ !.env.example .DS_Store + +# local, per-developer agent preferences: never versioned +.claude/*.local.md diff --git a/apps/blog/src/content/posts/en/what-is-iam-introduction-to-ferriskey.mdx b/apps/blog/src/content/posts/en/what-is-iam-introduction-to-ferriskey.mdx index 23a2190..c9a3678 100644 --- a/apps/blog/src/content/posts/en/what-is-iam-introduction-to-ferriskey.mdx +++ b/apps/blog/src/content/posts/en/what-is-iam-introduction-to-ferriskey.mdx @@ -1,6 +1,6 @@ --- title: "Who are you, and what are you doing here?" -description: "IAM (Identity & Access Management) underpins the security of almost every modern application. But what is it really, what does it do, and why is it so hard to get right? We break it all down — and introduce FerrisKey." +description: "IAM (Identity & Access Management) underpins the security of almost every modern application. But what is it really, what does it do, and why is it so hard to get right? We take it apart, and introduce FerrisKey." short_description: "Understand IAM from scratch, and discover FerrisKey." date: 2026-03-19 tags: [iam, identity, access-management, ferriskey, rust, open-source] @@ -16,7 +16,7 @@ A deceptively simple question. But behind it lies an entire discipline, one that ## The problem, put simply -Picture a large company. Hundreds of employees. Dozens of applications — accounting, HR, CRM, dev tooling, production servers. Every morning, people log in. Every evening, they log out. In between, they access data, trigger processes, read documents. +Picture a large company. Hundreds of employees. Dozens of applications: accounting, HR, CRM, dev tooling, production servers. Every morning, people log in. Every evening, they log out. In between, they access data, trigger processes, read documents. Now, a few simple questions: @@ -43,7 +43,7 @@ It knows who exists. Every human user, every application, every machine service ::: :::card{label="Authentication" icon="lucide:key-round"} -It verifies you are who you claim to be — password, TOTP, hardware key, magic link. When you "Sign in with Google", Google is the IAM. +It verifies you are who you claim to be, with a password, a TOTP code, a hardware key, or a magic link. When you "Sign in with Google", Google is the IAM. ::: :::card{label="Authorization" icon="lucide:shield-check"} @@ -51,7 +51,7 @@ Once your identity is confirmed, it decides what you're allowed to do. Read? Wri ::: :::card{label="Standard protocols" icon="lucide:globe"} -A good IAM speaks OAuth2 and OpenID Connect (OIDC) — the universal languages of the web. Apps can delegate authentication without ever touching passwords. +A good IAM speaks OAuth2 and OpenID Connect, the two languages the whole web already understands. Apps can delegate authentication without ever touching passwords. ::: :::card{label="Audit" icon="lucide:scroll-text"} @@ -73,7 +73,7 @@ IAM sounds simple. It's just a `users` table with a `password_hash`, right? Managing identities seriously means dealing with dozens of problems that stack up fast: secret rotation, token revocation, session expiration, service accounts, multi-tenancy, MFA strategies, webhooks, tamper-proof audit logs… -And all of this has to hold under load. An IAM is a **mandatory chokepoint** — every authenticated request goes through it. If it's slow or goes down, your entire infrastructure stops. +And all of this has to hold under load. An IAM is a mandatory chokepoint: every authenticated request goes through it. If it slows down or falls over, everything behind it stops. ::: That's why large enterprises pay fortunes for solutions like Okta, Auth0, or Azure AD. On the open source side, Keycloak has been around for a long time and does the job, but it carries significant configuration complexity and a JVM footprint that doesn't suit everyone. @@ -87,10 +87,10 @@ FerrisKey doesn't claim to be the definitive solution. It's an alternative, with FerrisKey is an open source IAM system, built in **Rust**, with a hexagonal architecture. :::callout{variant="info" title="Why Rust?"} -Performance and reliability are non-negotiable for a component this critical. Rust delivers C-level speed without the pitfalls — no garbage collector, no data races, no memory surprises. For a service handling millions of authentications, that's exactly what you want. +Performance and reliability are non-negotiable for a component this critical. Rust gives you C-level speed without the traps: no garbage collector, no data races, no memory surprises. For a service handling millions of authentications, that's exactly what you want. ::: -The hexagonal architecture ensures that business logic stays pure and decoupled from infrastructure. The database can change, the HTTP framework can evolve — the domain core stays stable and testable. +The hexagonal architecture ensures that business logic stays pure and decoupled from infrastructure. The database can change and the HTTP framework can evolve while the domain core stays stable and testable. What a decoded OIDC ID token looks like when FerrisKey issues it: @@ -112,23 +112,23 @@ In practice, FerrisKey gives you: ::::card-group{cols=2} :::card{label="Realms" icon="lucide:layers"} -Fully isolated spaces. Each organization, project, or environment gets its own realm — its own users, roles, and clients. No cross-contamination possible. +Fully isolated spaces. Each organization, project, or environment gets its own realm, with its own users, roles, and clients. Nothing crosses over. ::: :::card{label="OAuth2 & OIDC" icon="lucide:lock-keyhole"} The web's standards, implemented correctly, so your apps can delegate authentication without friction. ::: -:::card{label="Trident — MFA" icon="lucide:shield"} +:::card{label="Trident, for MFA" icon="lucide:shield"} FerrisKey's MFA module: TOTP, WebAuthn (hardware keys, passkeys), magic links, and recovery codes. ::: -:::card{label="SeaWatch — Audit" icon="lucide:eye"} +:::card{label="SeaWatch, for audit" icon="lucide:eye"} A complete audit system, queryable from the console, tracing every security event across your realms. ::: :::card{label="Webhooks" icon="lucide:webhook"} -Connect FerrisKey to your existing systems and react to lifecycle events — user creation, access revocation, and more. +Connect FerrisKey to your existing systems and react to lifecycle events: a user created, an access revoked, and the rest. ::: :::card{label="Cloud-native" icon="lucide:cloud"} @@ -136,7 +136,7 @@ An official Helm chart, Kubernetes Operator, and Docker Compose support for fric ::: :::: -:::callout{variant="success" title="Apache 2.0 — fully open"} +:::callout{variant="success" title="Apache 2.0, fully open"} No paywall. No "enterprise" tier hiding critical features behind a contact form. The code is open, the community is here. ::: @@ -146,7 +146,7 @@ No paywall. No "enterprise" tier hiding critical features behind a contact form. ::::card-group{cols=3} :::card{label="SaaS teams" icon="lucide:rocket"} -Building a platform and want robust auth without starting from scratch — or paying per monthly active user. +Building a platform and want solid auth without starting from scratch, or paying per monthly active user. ::: :::card{label="Platform engineers" icon="lucide:server"} diff --git a/apps/blog/src/content/posts/en/why-rust-for-an-iam.mdx b/apps/blog/src/content/posts/en/why-rust-for-an-iam.mdx index c7cd210..4a9c5f1 100644 --- a/apps/blog/src/content/posts/en/why-rust-for-an-iam.mdx +++ b/apps/blog/src/content/posts/en/why-rust-for-an-iam.mdx @@ -72,7 +72,7 @@ For the SREs who get paged when it isn't: no garbage collector means no GC pause ## What determinism buys us next -Memory safety gets the headlines, but it's not the only property this design gives us for free. Ownership and the absence of a garbage collector also make the runtime deterministic: no GC pause, no JIT warm-up curve, no allocator quietly deciding to compact the heap under load. Feed the same input to the same binary twice and it takes the same path both times, with the same timing characteristics. That's not just a safety property, it's a performance one too: the same determinism that rules out data races is what keeps tail latency boring under load. +Memory safety gets the headlines, but it's not the only property this design gives us for free. Ownership and the absence of a garbage collector also make the runtime deterministic: no GC pause, no JIT warm-up curve, no allocator quietly deciding to compact the heap under load. Feed the same input to the same binary twice and it takes the same path both times, with the same timing characteristics. That determinism buys you more than safety. The same property that rules out data races is what keeps tail latency boring under load. That determinism is also a foundation, not just an outcome, and it points at two things we want FerrisKey to grow into. diff --git a/apps/blog/src/content/posts/fr/what-is-iam-introduction-to-ferriskey.mdx b/apps/blog/src/content/posts/fr/what-is-iam-introduction-to-ferriskey.mdx index 77103da..bff45f5 100644 --- a/apps/blog/src/content/posts/fr/what-is-iam-introduction-to-ferriskey.mdx +++ b/apps/blog/src/content/posts/fr/what-is-iam-introduction-to-ferriskey.mdx @@ -1,6 +1,6 @@ --- title: "Qui es-tu, et qu'est-ce que tu fais là ?" -description: "L'IAM (Identity & Access Management) est au cœur de la sécurité de presque toutes les applications modernes. Mais qu'est-ce que c'est vraiment, à quoi ça sert, et pourquoi c'est si difficile à bien faire ? On démêle tout — et on vous présente FerrisKey." +description: "L'IAM (Identity & Access Management) est au cœur de la sécurité de presque toutes les applications modernes. Mais qu'est-ce que c'est vraiment, à quoi ça sert, et pourquoi c'est si difficile à bien faire ? On démêle tout, et on vous présente FerrisKey." short_description: "Comprendre l'IAM de zéro, et découvrir FerrisKey." date: 2026-03-19 tags: [iam, identity, access-management, ferriskey, rust, open-source] @@ -16,7 +16,7 @@ Une question trompeusement simple. Mais derrière elle se cache toute une discip ## Le problème, en clair -Imaginez une grande entreprise. Des centaines d'employés. Des dizaines d'applications — comptabilité, RH, CRM, outils de dev, serveurs de production. Chaque matin, les gens se connectent. Chaque soir, ils se déconnectent. Entre-temps, ils accèdent à des données, déclenchent des processus, lisent des documents. +Imaginez une grande entreprise. Des centaines d'employés. Des dizaines d'applications : comptabilité, RH, CRM, outils de dev, serveurs de production. Chaque matin, les gens se connectent. Chaque soir, ils se déconnectent. Entre-temps, ils accèdent à des données, déclenchent des processus, lisent des documents. Quelques questions simples : @@ -43,7 +43,7 @@ Il sait qui existe. Chaque utilisateur humain, chaque application, chaque servic ::: :::card{label="Authentification" icon="lucide:key-round"} -Il vérifie que vous êtes bien qui vous prétendez être — mot de passe, TOTP, clé matérielle, magic link. Quand vous faites « Se connecter avec Google », Google est l'IAM. +Il vérifie que vous êtes bien qui vous prétendez être, par mot de passe, TOTP, clé matérielle ou magic link. Quand vous faites « Se connecter avec Google », Google est l'IAM. ::: :::card{label="Autorisation" icon="lucide:shield-check"} @@ -51,7 +51,7 @@ Une fois votre identité confirmée, il décide ce que vous avez le droit de fai ::: :::card{label="Protocoles standards" icon="lucide:globe"} -Un bon IAM parle OAuth2 et OpenID Connect (OIDC) — les langages universels du web. Les applications peuvent déléguer l'authentification sans jamais toucher aux mots de passe. +Un bon IAM parle OAuth2 et OpenID Connect, les deux langages que tout le web comprend déjà. Les applications peuvent déléguer l'authentification sans jamais toucher aux mots de passe. ::: :::card{label="Audit" icon="lucide:scroll-text"} @@ -73,7 +73,7 @@ L'IAM paraît simple. C'est juste une table `users` avec un `password_hash`, non Gérer des identités sérieusement, c'est faire face à des dizaines de problèmes qui s'accumulent vite : rotation des secrets, révocation de tokens, expiration de sessions, comptes de service, multi-tenancy, stratégies MFA, webhooks, journaux d'audit infalsifiables… -Et tout ça doit tenir sous charge. Un IAM est un **point de passage obligatoire** — chaque requête authentifiée le traverse. S'il est lent ou tombe, toute votre infrastructure s'arrête. +Et tout ça doit tenir sous charge. Un IAM est un point de passage obligatoire : chaque requête authentifiée le traverse. S'il ralentit ou tombe, tout ce qu'il y a derrière s'arrête. ::: C'est pourquoi les grandes entreprises paient des fortunes pour des solutions comme Okta, Auth0 ou Azure AD. Côté open source, Keycloak existe depuis longtemps et fait le travail, mais il embarque une complexité de configuration significative et une empreinte JVM qui ne convient pas à tout le monde. @@ -87,10 +87,10 @@ FerrisKey ne prétend pas être la solution définitive. C'est une alternative, FerrisKey est un système IAM open source, construit en **Rust**, avec une architecture hexagonale. :::callout{variant="info" title="Pourquoi Rust ?"} -La performance et la fiabilité ne sont pas négociables pour un composant aussi critique. Rust offre une vitesse comparable au C sans les pièges — pas de garbage collector, pas de data races, pas de surprises mémoire. Pour un service qui gère des millions d'authentifications, c'est exactement ce qu'il faut. +La performance et la fiabilité ne sont pas négociables pour un composant aussi critique. Rust offre une vitesse comparable au C sans les pièges : pas de garbage collector, pas de data races, pas de surprises mémoire. Pour un service qui gère des millions d'authentifications, c'est exactement ce qu'il faut. ::: -L'architecture hexagonale garantit que la logique métier reste pure et découplée de l'infrastructure. La base de données peut changer, le framework HTTP peut évoluer — le cœur du domaine reste stable et testable. +L'architecture hexagonale garantit que la logique métier reste pure et découplée de l'infrastructure. La base de données peut changer et le framework HTTP évoluer, le cœur du domaine reste stable et testable. Voici à quoi ressemble un ID token OIDC décodé émis par FerrisKey : @@ -112,23 +112,23 @@ En pratique, FerrisKey vous offre : ::::card-group{cols=2} :::card{label="Realms" icon="lucide:layers"} -Des espaces totalement isolés. Chaque organisation, projet ou environnement dispose de son propre realm — ses propres utilisateurs, rôles et clients. Zéro contamination croisée possible. +Des espaces totalement isolés. Chaque organisation, projet ou environnement dispose de son propre realm, avec ses utilisateurs, ses rôles et ses clients. Rien ne traverse. ::: :::card{label="OAuth2 & OIDC" icon="lucide:lock-keyhole"} Les standards du web, implémentés correctement, pour que vos applications puissent déléguer l'authentification sans friction. ::: -:::card{label="Trident — MFA" icon="lucide:shield"} +:::card{label="Trident, pour le MFA" icon="lucide:shield"} Le module MFA de FerrisKey : TOTP, WebAuthn (clés matérielles, passkeys), magic links et codes de récupération. ::: -:::card{label="SeaWatch — Audit" icon="lucide:eye"} +:::card{label="SeaWatch, pour l'audit" icon="lucide:eye"} Un système d'audit complet, interrogeable depuis la console, traçant chaque événement de sécurité dans vos realms. ::: :::card{label="Webhooks" icon="lucide:webhook"} -Connectez FerrisKey à vos systèmes existants et réagissez aux événements du cycle de vie — création d'utilisateur, révocation d'accès, et plus encore. +Connectez FerrisKey à vos systèmes existants et réagissez aux événements du cycle de vie : création d'utilisateur, révocation d'accès, et le reste. ::: :::card{label="Cloud-native" icon="lucide:cloud"} @@ -136,7 +136,7 @@ Un chart Helm officiel, un Kubernetes Operator et le support Docker Compose pour ::: :::: -:::callout{variant="success" title="Apache 2.0 — entièrement ouvert"} +:::callout{variant="success" title="Apache 2.0, entièrement ouvert"} Pas de paywall. Pas de tier « enterprise » qui cache des fonctionnalités critiques derrière un formulaire de contact. Le code est ouvert, la communauté est là. ::: @@ -146,7 +146,7 @@ Pas de paywall. Pas de tier « enterprise » qui cache des fonctionnalités crit ::::card-group{cols=3} :::card{label="Équipes SaaS" icon="lucide:rocket"} -Vous construisez une plateforme et voulez une auth robuste sans repartir de zéro — ni payer au nombre d'utilisateurs actifs mensuels. +Vous construisez une plateforme et voulez une auth solide sans repartir de zéro, ni payer au nombre d'utilisateurs actifs mensuels. ::: :::card{label="Ingénieurs plateforme" icon="lucide:server"} diff --git a/apps/blog/src/content/posts/fr/why-rust-for-an-iam.mdx b/apps/blog/src/content/posts/fr/why-rust-for-an-iam.mdx index 838b00c..8f37294 100644 --- a/apps/blog/src/content/posts/fr/why-rust-for-an-iam.mdx +++ b/apps/blog/src/content/posts/fr/why-rust-for-an-iam.mdx @@ -72,7 +72,7 @@ Pour les SRE qui sont réveillés quand ce n'est pas le cas : pas de garbage col ## Ce que le déterminisme nous permet ensuite -La sécurité mémoire fait les gros titres, mais ce n'est pas la seule propriété que ce design nous offre gratuitement. L'ownership et l'absence de garbage collector rendent aussi le runtime déterministe : pas de pause GC, pas de courbe de chauffe JIT, pas d'allocateur qui décide discrètement de compacter le heap sous charge. Donnez la même entrée au même binaire deux fois, il emprunte le même chemin les deux fois, avec les mêmes caractéristiques de timing. Ce n'est pas qu'une propriété de sécurité, c'est aussi une propriété de performance : le même déterminisme qui exclut les data races est ce qui garde la latence de queue prévisible sous charge. +La sécurité mémoire fait les gros titres, mais ce n'est pas la seule propriété que ce design nous offre gratuitement. L'ownership et l'absence de garbage collector rendent aussi le runtime déterministe : pas de pause GC, pas de courbe de chauffe JIT, pas d'allocateur qui décide discrètement de compacter le heap sous charge. Donnez la même entrée au même binaire deux fois, il emprunte le même chemin les deux fois, avec les mêmes caractéristiques de timing. Ce déterminisme rapporte plus que de la sûreté. La même propriété qui exclut les data races est celle qui garde la latence de queue prévisible sous charge. Ce déterminisme est aussi une fondation, pas juste un résultat, et il pointe vers deux choses qu'on veut voir grandir chez FerrisKey. diff --git a/apps/blog/src/layouts/base.astro b/apps/blog/src/layouts/base.astro index a518c01..deb410c 100644 --- a/apps/blog/src/layouts/base.astro +++ b/apps/blog/src/layouts/base.astro @@ -16,7 +16,7 @@ interface Props { const { title, description = 'Explainer Blog', thumbnail, locale = 'en', locales = ['en'], localeSwitchUrls = {} } = Astro.props const t = useTranslations(locale) const thumbnailPath = thumbnail ?? `${Astro.url.pathname.replace(/\/$/, '')}/thumbnail.png` -// og:image/twitter:image must be absolute — Discord and most link-preview bots won't resolve a relative path. +// og:image/twitter:image must be absolute: Discord and most link-preview bots won't resolve a relative path. const thumbnailUrl = Astro.site ? new URL(thumbnailPath, Astro.site).toString() : thumbnailPath const appUrlOverrides = { @@ -41,7 +41,7 @@ const appUrlOverrides = { - {title} — Blog + {title} | Blog