mediaDrop/config.schema.json
Nicolas 8eb0470474
All checks were successful
Publier l'image Docker / test (push) Successful in 22s
Publier l'image Docker / publish (push) Successful in 10s
Notifications par webhook (upload finalisé / échec)
Nouvelle clé `webhooks` : liste de points de terminaison POST notifiés à
chaque upload finalisé (`upload`, direct comme fragmenté) et à chaque
requête `/upload*` terminée en 4xx/5xx (`error`).

Chaque entrée : `url` (http/https), `events` (défaut : les deux),
`headers` (auth du récepteur), `secret` (signature HMAC-SHA256 dans
`X-MediaDrop-Signature`), `timeoutMs` (défaut 5 s, max 30 s).

Corps JSON structuré + champs `text`/`content` portant un résumé lisible,
pour fonctionner tel quel avec Slack / Discord / ntfy ou un récepteur
custom. Livraison en parallèle, sans bloquer la réponse d'upload ; une
nouvelle tentative sur erreur réseau / 429 / 5xx ; échecs journalisés en
`warn` ; l'arrêt du serveur attend les envois en cours. Sans webhook
configuré, le notifieur est une non-opération.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 19:29:44 +02:00

138 lines
4.8 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://mediadrop.local/config.schema.json",
"title": "Configuration mediaDrop",
"type": "object",
"additionalProperties": false,
"required": ["publicUrl", "targets", "session", "oidc"],
"properties": {
"$schema": { "type": "string" },
"port": { "type": "integer", "minimum": 1, "maximum": 65535, "default": 3000 },
"host": { "type": "string", "default": "0.0.0.0" },
"publicUrl": {
"type": "string",
"format": "uri",
"description": "URL externe de base, ex. https://media.exemple.fr (sert à redirect_uri / post-logout)."
},
"targets": {
"type": "array",
"minItems": 1,
"description": "Dossiers nommés dans lesquels déposer. Le premier est la cible par défaut.",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["name", "dir"],
"properties": {
"name": {
"type": "string",
"pattern": "^[A-Za-z0-9._-]+$",
"description": "Identifiant transmis par le client (?target=...)."
},
"label": { "type": "string", "description": "Libellé affiché (défaut : name)." },
"dir": { "type": "string", "description": "Chemin du dossier de destination." },
"allowDirectories": {
"type": "boolean",
"default": false,
"description": "Autoriser le dépôt de dossiers (arborescence recréée sous dir)."
}
}
}
},
"maxFileSizeMb": { "type": "integer", "minimum": 1, "default": 512 },
"logLevel": {
"enum": ["fatal", "error", "warn", "info", "debug", "trace", "silent"],
"default": "info"
},
"chunkPoolSize": {
"type": "integer",
"minimum": 1,
"maximum": 256,
"default": 30,
"description": "Nombre max de requêtes de morceaux en vol, réparti par le navigateur entre les fichiers fragmentés actifs (1 fichier => tout le pool, N fichiers => une part chacun). Efficace surtout en HTTP/2."
},
"webhooks": {
"type": "array",
"description": "Points de terminaison POST notifiés à chaque upload finalisé et/ou chaque échec d'upload.",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["url"],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "URL HTTP(S) appelée en POST (corps JSON)."
},
"events": {
"type": "array",
"items": { "enum": ["upload", "error"] },
"uniqueItems": true,
"default": ["upload", "error"],
"description": "Événements souscrits. Défaut : les deux."
},
"headers": {
"type": "object",
"additionalProperties": { "type": "string" },
"description": "En-têtes ajoutés à chaque requête (auth du récepteur, etc.)."
},
"secret": {
"type": "string",
"description": "Si présent : en-tête X-MediaDrop-Signature = sha256=HMAC-SHA256(corps brut)."
},
"timeoutMs": {
"type": "integer",
"minimum": 1,
"maximum": 30000,
"default": 5000,
"description": "Délai d'attente par tentative."
}
}
}
},
"allowedMimeTypes": {
"description": "\"all\", ou liste de types exacts et/ou jokers de préfixe (\"video/*\", \"*/*\", \"*\"). Absent => liste média par défaut.",
"oneOf": [
{ "const": "all" },
{
"type": "array",
"minItems": 1,
"items": { "type": "string", "pattern": "^(\\*|\\*/\\*|[^/*\\s]+/(\\*|[^/*\\s]+))$" }
}
]
},
"session": {
"type": "object",
"additionalProperties": false,
"required": ["key"],
"properties": {
"key": {
"type": "string",
"description": "32 octets encodés en base64. Générer avec : openssl rand -base64 32"
},
"maxAgeHours": { "type": "number", "exclusiveMinimum": 0, "default": 12 }
}
},
"oidc": {
"type": "object",
"additionalProperties": false,
"required": ["issuer", "clientId", "clientSecret"],
"properties": {
"issuer": {
"type": "string",
"format": "uri",
"description": "Issuer OIDC (le serveur lit <issuer>/.well-known/openid-configuration)."
},
"clientId": { "type": "string" },
"clientSecret": {
"type": "string",
"description": "Secret du client confidentiel déclaré côté fournisseur."
},
"scopes": {
"type": "array",
"items": { "type": "string" },
"default": ["openid", "profile", "email"]
}
}
}
}
}