Use when building or reviewing a back-office / admin portal — CRUD routes under /api/admin, role and capability gating, audit logging, deciding what should be editable, bootstrapping the first superadmin, or filling an admin dashboard with data. Covers logAdminAction as a mandatory path, capability-based UI, why API keys must never be editable from an interface, and never inventing a number to fill a chart.
Scanned 10/1/2026
npx -y skills add Giovannyengamba/Otopcy-Softstart --skill otopcy-admin --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Otopcy Admin?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/giovannyengamba-otopcy-admin)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: otopcy-admin
description: Use when building or reviewing a back-office / admin portal — CRUD routes under /api/admin, role and capability gating, audit logging, deciding what should be editable, bootstrapping the first superadmin, or filling an admin dashboard with data. Covers logAdminAction as a mandatory path, capability-based UI, why API keys must never be editable from an interface, and never inventing a number to fill a chart.
---
# Administration — Otopcy SoftStart
Par Giovanny Engamba (giovannyengamba.com) · Otopcy (otopcy.com).
Le back-office est la surface où une seule personne peut, en un clic,
changer les prix, lire les données de tous les clients ou supprimer une
commande payée.
## Trois exigences avant toute esthétique
1. Dire **qui a fait quoi, quand**.
2. Refuser côté **serveur** — masquer un bouton n'est pas un contrôle.
3. Montrer les **vraies** données, ou rien.
## Journal d'audit — sans exception
```ts
await logAdminAction(prisma, {
actorId: auth.user.id,
action: 'product.price_change', // objet.verbe, stable
targetType: 'Product', targetId: id,
metadata: { avant: 30000, apres: 35000 }, // l'avant ET l'après
});
```
Non modifiable : aucune route ne supprime ni n'édite une ligne d'audit.
Écris le test qui vérifie que toute route `/api/admin/*` qui écrit l'appelle.
## Capacités plutôt que rôles
L'interface demande « a-t-il le droit de supprimer un devis ? », pas
« est-il ADMIN ? ». Une table de capacités par rôle, servie par
`/api/admin/me`. Le jour où tu ajoutes un « éditeur », tu changes une
table, pas trente composants. **Le serveur revérifie toujours.**
| Action | Rôle minimum |
|---|---|
| Lire, créer, modifier | ADMIN |
| **Supprimer** | SUPERADMIN (irréversible) |
| Changer un rôle | SUPERADMIN (sinon un admin se promeut) |
| Annuler un retrait | SUPERADMIN (c'est de l'argent) |
On refuse de rétrograder le **dernier** SUPERADMIN.
Premier administrateur : un script en ligne de commande qui promeut un
compte **existant**. Jamais un bouton dans l'interface.
## Éditable, ou pas
| Éditable | Jamais |
|---|---|
| Contenu, prix, textes, statuts | **Les clés d'API** |
| Réglages du site | Un montant de commande déjà payée |
| Rôles et statuts de comptes | Les lignes d'audit, le résultat d'un webhook |
### Les clés d'API ne se gèrent pas depuis l'interface
C'est la fonctionnalité que les agents proposent le plus spontanément, et
une des pires. Trois raisons : une clé affichable est lisible par
quiconque obtient une session ou une capture ; une clé en base est une
surface de chiffrement et de rotation de plus ; **une clé modifiable par
hameçonnage détourne les paiements sans que rien ne semble cassé.**
Les clés vivent dans les variables d'environnement de l'hébergeur.
Corollaire : un montant déjà payé ne se modifie pas — on crée un
remboursement ou un avoir, sinon la piste comptable est détruite.
## Ne jamais inventer un chiffre
```tsx
<EtatVide titre="Aucune donnée d'audience"
detail="La mesure n'est pas encore branchée." /> // ✅
<Graphique donnees={[120, 145, 132, 178]} /> // ❌
```
Le coût n'est pas esthétique : une décision sera prise dessus.
## Le motif, sept étapes toujours dans cet ordre
`runtime = 'nodejs'` → contexte de requête → `verifyCsrf` → `requireAdmin`
→ valider le corps → lire l'**avant** → écrire → `logAdminAction` avec
avant/après → répondre.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!