Skip to content
Back to skills

Otopcy Admin

ASecurity

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.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 1, 2026
databasesnodenodejsapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add Giovannyengamba/Otopcy-Softstart --skill otopcy-admin --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Otopcy Admin?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Otopcy Admin
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/giovannyengamba-otopcy-admin/badge)](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.

Download with Pro
SKILL.md
---
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.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…