# auth.md — benenoc.com

Compagnon lisible de la découverte OAuth (RFC 9728 / RFC 8414) pour les agents autonomes.
Source de vérité structurée : `/.well-known/oauth-protected-resource`, puis le bloc `agent_auth`
dans `/.well-known/oauth-authorization-server`. Humains : voir `/#contact`.

## Audience

Ce document s'adresse aux agents autonomes. `benenoc.com` est un portfolio public en lecture seule :
l'accès agent se fait en mode `anonymous`, sans inscription, sans identifiant et sans OAuth interactif.
La découverte ne crée aucun compte, n'envoie aucun courriel et n'émet aucun jeton : ne sondez aucun
`POST` d'enregistrement, il n'en existe pas.

## Étape 1 — Découverte (deux sauts)

1a. Métadonnées de ressource protégée (PRM) :

```http
GET https://benenoc.com/.well-known/oauth-protected-resource
```

```json
{
  "resource": "https://benenoc.com/",
  "authorization_servers": ["https://benenoc.com"],
  "scopes_supported": [],
  "bearer_methods_supported": ["header"]
}
```

`resource` est l'URL canonique de l'API. `authorization_servers` désigne le serveur
d'autorisation. `scopes_supported` est vide : aucun scope n'est défini. `bearer_methods_supported`
vaut `["header"]` (`Authorization: Bearer …`), de façon nominale : aucun jeton n'est émis.

1b. Métadonnées du serveur d'autorisation (avec le bloc `agent_auth`) :

```http
GET https://benenoc.com/.well-known/oauth-authorization-server
```

`issuer` vaut `https://benenoc.com` et correspond à l'URL annoncée dans `authorization_servers`
de la PRM. Le bloc `agent_auth` contient `skill` (`https://benenoc.com/auth.md`, ce fichier),
`register_uri`, `claim_uri` et `identity_types_supported: ["anonymous"]`.

Aucune route protégée n'existe, donc aucun `401` avec en-tête `WWW-Authenticate: Bearer
resource_metadata="…oauth-protected-resource"` n'est émis. Si une route protégée apparaît un jour,
son `401` portera cet en-tête vers la PRM ci-dessus.

## Étape 2 — Choisir une méthode

Seule méthode prise en charge : `anonymous` (valeur de `identity_types_supported`).

- `identity_assertion` (ID-JAG, `urn:ietf:params:oauth:token-type:id-jag`) : non pris en charge —
  aucun fournisseur d'identité de confiance n'est configuré, aucune assertion n'est vérifiée.
- `service_auth` / courriel vérifié (`verified_email`) : non pris en charge — aucun compte
  utilisateur n'existe sur ce service.
- `anonymous` : pris en charge — `anonymous.credential_types_supported` est vide : aucun
  identifiant n'est requis ni émis.

N'annoncez que ce qui est accepté : ce service n'accepte que `anonymous`.

## Étape 3 — Enregistrement (register_uri)

`register_uri` = `https://benenoc.com/#contact`. Il n'y a pas d'enregistrement programmatique
ni de point de terminaison `POST /agent/identity` : l'unique point d'engagement avec un humain
est la section contact.

Pour contacter le propriétaire (action médiée par un humain), suivre la compétence
`https://benenoc.com/.well-known/agent-skills/contact-site-owner/SKILL.md` :
`POST https://benenoc.com/api/contact` en JSON (`name`, `email`, `subject`, `message`).
En production, un jeton Cloudflare Turnstile (`cf-turnstile-response`) est requis : un agent sans
capacité captcha prépare la charge utile et fait compléter l'envoi par un humain.
Limites : 5 requêtes/minute/IP (429 au-delà), corps ≤ 20 000 octets. Détails : `/openapi.json`.

## Étape 4 — Revendication (claim_uri)

`claim_uri` = `https://benenoc.com/#contact`. Il n'y a pas de cérémonie de revendication
automatisée : aucun compte à rattacher, aucun `user_code`, aucun `identity_assertion` émis.
Toute mise en relation passe par un message au propriétaire (voir étape 3).

## Étape 5 — Utiliser l'accès (sans identifiant)

Contenu public en lecture seule, sans jeton :

- Pages et sections : `https://benenoc.com/` (négociation `Accept: text/markdown` supportée)
- Catalogue d'API (RFC 9727) : `https://benenoc.com/.well-known/api-catalog`
- Catalogue de capacités (ARD) : `https://benenoc.com/.well-known/ai-catalog.json`
- Index des skills : `https://benenoc.com/.well-known/agent-skills/index.json`
- Spécification OpenAPI du contact : `https://benenoc.com/openapi.json`
- Serveur MCP (lecture seule) : carte à `https://benenoc.com/.well-known/mcp/server-card.json`,
  point de terminaison `https://benenoc.com/mcp`

## Erreurs

- Aucune route n'exige d'authentification : pas de `401`, pas de `WWW-Authenticate` en pratique.
- `POST /api/contact` : `400` (validation ou captcha invalide), `413` (> 20 000 octets),
  `415` (Content-Type non supporté), `429` (rate limiting, avec `Retry-After`), `500` (serveur).
  Formats documentés dans `https://benenoc.com/openapi.json`.

## Révocation

Aucun identifiant n'étant émis, il n'y a rien à révoquer : pas de `revocation_uri`,
pas de `events_supported`, pas de point de terminaison de révocation. En cas de besoin
(supprimer un message envoyé, signaler un abus), écrire au propriétaire via `/#contact`.

## Web Bot Auth (identité du site émetteur)

Quand ce site envoie lui-même des requêtes automatisées (vérification Turnstile,
envoi Resend), il s'identifie par signatures de messages HTTP (RFC 9421, groupe
de travail IETF WebBotAuth) : en-têtes `Signature-Agent` (`"https://benenoc.com"`),
`Signature-Input` (tag `web-bot-auth`, composants `"@authority"` et `"signature-agent"`,
`keyid` = thumbprint ci-dessous) et `Signature` (Ed25519).

Répertoire de clés : `https://benenoc.com/.well-known/http-message-signatures-directory`
(Content-Type `application/http-message-signatures-directory+json`, réponse elle-même
signée, tag `http-message-signatures-directory`). Clé active (`kid`, thumbprint JWK) :
`Ge0nw40Q0aLLc4zO20hbxSF9BNtK03f4Ds1LwSkB-N8`.
