Skip to content

Système de Visibilité Starlight - Schéma et Configuration

Système de Visibilité Starlight - Schéma et Configuration

Documentation technique

Objet : Implémentation du champ visibility pour contrôler l’accès public/privé aux documents Starlight
Type : Documentation Technique (DAT)
Couche : Couche 02 (Présentation - Astro)
Emplacement : apps/web/src/content.config.ts + apps/web/src/middleware.ts
Statut : DOC (Proposé)

1. Vue d’ensemble (DOC)

1.1. Description

Ce système permet de marquer les documents Starlight comme public ou private via un champ personnalisé dans le frontmatter. Le middleware Astro lit cette métadonnée pour déterminer si une authentification est requise.

1.2. Objectif

  • Permettre un contrôle granulaire de l’accès aux documents
  • Garder tous les documents privés par défaut (secure by default)
  • Rendre certains documents publics facilement (ex: overview, guides généraux)
  • Intégration transparente avec Starlight et le middleware existant

2. Configuration et Schéma (CODE)

2.1. Extension Schéma Starlight1/2

Modifier apps/web/src/content.config.ts pour étendre le schéma docs :

2.1. Extension Schéma Starlight2/2

import { defineCollection } from 'astro:content';
import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders';
import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
schema: ({ image }) =>
z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
heroImage: z.optional(image()),
}),
});
const docs = defineCollection({
loader: docsLoader(),
schema: docsSchema({
extend: z.object({
// Champ de visibilité : public ou private (par défaut)
visibility: z.enum(['public', 'private']).default('private'),
}),
}),
});
export const collections = {
blog,
docs,
i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }),
};

2.2. Exemple Frontmatter1/2

---
title: "Guide de Démarrage"
description: "Guide pour les nouveaux développeurs"
visibility: "public" # Ce document est accessible sans authentification
---
Contenu du guide...

2.2. Exemple Frontmatter2/2

---
title: "Architecture Interne"
description: "Documentation technique sensible"
visibility: "private" # Ce document nécessite une authentification (valeur par défaut)
---
Contenu technique sensible...

2.3. Modification Middleware

Le middleware existant (apps/web/src/middleware.ts) doit être mis à jour pour lire le champ visibility :

// Dans la fonction onRequest, après avoir déterminé docId
let isPrivate = true;
try {
// Attempt to read entry frontmatter schema
const entry = await getEntry('docs', docId);
if (entry && entry.data) {
const data = entry.data as { visibility?: 'public' | 'private' };
// Si visibility est explicitement 'public', document public
if (data.visibility === 'public') {
isPrivate = false;
}
}
} catch (_e) {
// En cas d'erreur, considérer comme privé (secure by default)
isPrivate = true;
}
// Override pour overview (public par défaut)
if (docId === 'overview') {
isPrivate = false;
}

3. Architecture et Flux1/2

3. Architecture et Flux2/2

Utilisateur → Requête /docs/private-doc
│
▼
[Middleware Astro]
│
▼
[Déterminer docId depuis pathname]
│
▼
[getEntry('docs', docId)]
│
▼
[Lire entry.data.visibility]
│
┌─────────────┴─────────────┐
│ │
▼ ▼
visibility === 'public' visibility === 'private'
│ │
│ ▼
│ [Vérifier auth_session]
│ │
│ ┌───────┴───────┐
│ │ │
│ ▼ ▼
│ [Session valide] [Session invalide]
│ │ │
│ ▼ ▼
│ [Accès autorisé] [Redirect /login]
│ │
└───────────────────────────┘
│
▼
[Accès autorisé]

4. Contrats d’Entrée/Sortie (SPEC)

4.1. Frontmatter Schema

Champ Type Valeurs Défaut Description
visibility enum 'public' | 'private' 'private' Contrôle l’accès au document

4.2. Middleware Logic

Condition Action
visibility === 'public' Accès autorisé sans authentification
visibility === 'private' Vérification auth_session requise
docId === 'overview' Accès autorisé (override public)
Erreur lecture entry Accès refusé (secure by default)

4.3. TypeScript Types

// Généré automatiquement par Astro
interface DocsEntry {
id: string;
slug: string;
body: string;
collection: 'docs';
data: {
title: string;
description: string;
visibility: 'public' | 'private'; // Nouveau champ
// ... autres champs Starlight
};
}

5. Sécurité

  1. Secure by Default : Valeur par défaut 'private' pour éviter les fuites accidentelles
  2. Validation Zod : Schéma strict empêche les valeurs invalides
  3. Override explicite : Seul overview est explicitement public dans le middleware
  4. Gestion d’erreurs : En cas d’erreur de lecture, document considéré privé
  5. TypeScript : Typage automatique prévient les erreurs de développement

6. Migration des Documents Existants

6.1. Stratégie

  • Documents privés : Aucune modification (valeur par défaut 'private')
  • Documents publics : Ajouter explicitement visibility: 'public'
  • Overview : Déjà public via override middleware

6.2. Script de Migration (Optionnel)

Terminal window
# Pour marquer tous les docs d'un répertoire comme publics
find src/content/docs/docs/L1_Contenu -name "*.md" -exec sed -i '2a visibility: "public"' {} \;

6.3. Documents Candidats pour Public

  • overview : Déjà public
  • Guides Getting Started généraux : Potentiellement publics
  • Documentation API publique : Potentiellement publique
  • Architecture interne : Toujours privé
  • Spécifications techniques : Toujours privé

7. Tests Attendus (TEST)

7.1. Tests Schéma

  • Document sans champ visibility → défaut 'private'
  • Document avec visibility: 'public' → accessible sans auth
  • Document avec visibility: 'private' → nécessite auth
  • Valeur invalide → erreur de validation Zod

7.2. Tests Middleware

  • Accès document public sans cookie → 200 OK
  • Accès document privé sans cookie → 302 /login
  • Accès document privé avec cookie valide → 200 OK
  • Accès document privé avec cookie invalide → 302 /login

7.3. Tests Starlight

  • Sidebar affiche tous les documents (publics et privés)
  • Navigation fonctionne correctement
  • Recherche Pagefind indexe correctement
  • TypeScript typecheck réussi

8. Documentation Utilisateur

8.1. Pour les Éditeurs de Documentation

---
title: "Mon Document"
description: "Description"
visibility: "public" # ou "private" (par défaut)
---
Contenu...

8.2. Règles de Visibilité

  • Par défaut : Toujours private (plus sécurisé)
  • Public : Uniquement pour documents non sensibles
  • Overview : Public automatiquement via middleware
  • Audit : Vérifier régulièrement les documents publics

9. Historique des Modifications

Date Version Description Auteur
2026-09-27 1.0 Création initiale DAT Système Visibilité Team (Agent)
Switch to normal mode

Contents