Admin

tickets

  • mmo.admin
  • agent skill
  • mmoframework-skill://mmo.admin/mmo-release-bugs/references/tickets.md
# A ticket, and the script that writes them ## The description ```markdown **Constat** : what happens, where, with what account, since when; the report's numbers (checklist n°36), what was replayed and how (HTTP 200, `/user/scopes.json` then says `admin: true`). **Retour Flo** : confirmé <- the reporter's answer, when the report has one **Attendu** : what "fixed" means, testable (403 for any non admin account, role unchanged, attempt logged). **Prompt suggéré :** ```claude <HEAD> <the bug's own paragraph> <FOOT> ``` ``` The prompt block's language is the agent's (```` ```claude ````, ```` ```chatgpt ````, ```` ```ai ```` for any: mmo.client's `KanbanPrompts` reads them); `api/boards/{board}/prompts.json?agent=claude` lists them. ## The head and the foot (my.oviepro, in French as its report was) ```text HEAD = Contexte : application my.oviepro (`~/dev/src/my.oviepro`, oviepro 4.1.0, branche develop), servie en local sur http://localhost/my.oviepro/ ; les bibliothèques MMO sont dans `~/dev/src/MMO/master/libs` (mmo.core, mmo.client, mmo.admin, mmo.oauth, mmo.edms, mmo.pdf...). Bug relevé en recette de la release sur dev.oviepro.com. FOOT = Reproduis d'abord le problème en local (skill `mmo-agent-login` pour te connecter, avec un compte sans droit d'administration quand c'est pertinent), corrige-le à sa cause plutôt qu'en surface, puis vérifie à l'écran ou par l'API. Si la cause est dans une bibliothèque MMO, corrige-la dans la bibliothèque et dis-le. Ne commite pas : résume ce que tu as changé (fichiers, raison, comment vérifier) dans la discussion du ticket. ``` A ticket found while fixing others says so in its head: "Problème découvert pendant la correction des tickets de recette du 05/10/2026" and its constat names the ticket that found it ("Trouvé par l'agent du ticket #62"). ## The bug's paragraph - What happens, with the route, file or class it happens in: `PUT /data/main/roles.json` (route `PUT|data/{repository}/{collection}` of `libs/core/src/controllers/RepositoryController.php`). - Where to look, when you know: `src/views/parts/temoins-tiers.jhs`, the `typeTemoin` property of `src/entities/Accident.php`. - What to do, and its limits: "rends le type obligatoire dès qu'un témoin est saisi (validation de l'entité et de l'étape)", "propose un script de reprise, sans le lancer", "n'applique rien en base sans validation". - What to prove: "ajoute un test qui rejoue l'attaque", "vérifie aussi POST/DELETE et les écritures en lot", "liste dans ton compte rendu chaque page vérifiée". - A decision that is not the agent's is asked for, not taken: "explique ... et si l'échec du mail doit vraiment empêcher le changement de statut". ## The generator ```python #builds the {board} board's backlog from "{report}" import json, urllib.request API = 'http://localhost/my.oviepro/api/boards/{board}' HEAD = ('Contexte : ...\n\n') FOOT = ('\n\nReproduis d\'abord le problème en local ... dans la discussion du ticket.') board = json.load(urllib.request.urlopen(API + '.json'))['data'] data = board['data'] first = 1 + max([int(t['id']) for t in data.get('tickets', []) if str(t['id']).isdigit()] or [0]) tickets = [] def T(title, category, labels, constat, prompt, attendu=None, retour=None): d = '**Constat** : ' + constat if retour: d += '\n\n**Retour Flo** : ' + retour if attendu: d += '\n\n**Attendu** : ' + attendu d += '\n\n**Prompt suggéré :**\n\n```claude\n' + HEAD + prompt + FOOT + '\n```\n' tickets.append({'id': str(first + len(tickets)), 'title': title, 'status': 'backlog', 'labels': labels, 'category': category, 'description': d, 'parent': None, 'constraint': None}) T('Escalade de privilèges : un compte non admin se donne admin: true par PUT /data/main/roles.json', 'securite', ['bloquant', 'securite', 'confirme-flo'], 'un compte sans droit d\'administration modifie son propre rôle ...', 'Un compte sans droit d\'administration peut modifier son propre rôle par `PUT /data/main/roles.json` ...', attendu='403 pour tout compte non admin, rôle inchangé, tentative tracée.', retour='confirmé') # ... one T() per bug data['tickets'] = data.get('tickets', []) + tickets #labels and categories the tickets use must exist on the board: add the missing ones to data['labels'] / data['categories'] req = urllib.request.Request(API + '.json', method='PUT', headers={'Content-Type': 'application/json'}, data=json.dumps({'version': board['version'], 'data': data}).encode()) print(json.load(urllib.request.urlopen(req))['data']['version'], len(tickets), 'tickets') ``` A label is `{"id": "bloquant", "label": "bloquant", "color": "red"}` (`icon` optional, a Font Awesome name that exists: check it); a category the same; a status `{"id": "todo", "label": "À faire", "type": "backlog"}`, its type one of `backlog`, `active`, `done`.