- list_slots + update_slots for composant/piece slots
- list/add/update/remove machine links (component, piece, product)
- get_machine_structure with full hierarchy
- clone_machine with all links and custom fields
- 52 MCP tests pass total
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 5 tools each: list, get, create, update, delete
- Piece: includes typePiece, constructeurs, prix (string)
- Composant: includes typeComposant, constructeurs, prix (string)
- Machine: includes site (required), constructeurs
- 40 MCP tests pass total
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 5 tools each: list, get, create, update, delete
- McpToolHelper extracted to AbstractApiTestCase for reuse
- DashboardStatsToolTest simplified to use base helpers
- 22 MCP tests pass
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- McpStdioAuthSubscriber for console transport auth via env vars
- DashboardStatsTool as PoC (validates MCP protocol flow)
- McpToolHelper trait for shared pagination/error utilities
- Key learning: #[McpTool] must be on CLASS, not method for __invoke
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SkeletonStructureService was deleting all skeleton requirements and
recreating them on every ModelType update. Combined with position-based
matching in sync strategies, any reordering or insertion caused all
existing slots to be orphaned and recreated empty, losing selections.
- SkeletonStructureService: update requirements in-place by matching
on typeId instead of delete-all/recreate-all
- ComposantSyncStrategy & PieceSyncStrategy: two-pass smart matching
algorithm (exact typeId+position first, then typeId-only fallback)
to preserve selectedPiece/selectedComposant/selectedProduct on
reorder/insertion
- Frontend: check patch result.success before updating local state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add selectedPieceId support to ComposantPieceSlotController
- Create ComposantProductSlotController and ComposantSubcomponentSlotController
- Add updateCustomFields() to SkeletonStructureService for managing CustomField entities
- Fix position/orderIndex fallback to array index in all 3 sync strategies
- Fix type comparison in ProductSyncStrategy for dual format support
- Update CLAUDE.md with new entities, controllers, and fixtures documentation
- Update frontend submodule with interactive slot selectors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the sync orchestrator that delegates to tagged strategies via
AutowireIterator, and the HTTP controller exposing sync-preview and sync
endpoints with transaction wrapping and role-based access control.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exposes structure as a computed property from pieceSlots, productSlots,
and subcomponentSlots relations, including slotId for frontend quantity
persistence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
normalizeProduct() had customFields hardcoded to [] and was missing
customFieldValues entirely, unlike normalizeComposant and normalizePiece.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getStructure() was returning hardcoded empty customFields arrays after
the JSON-to-tables migration. Now reads from the relational CustomField
entities via serializeCustomFields() for all three categories.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove Composant.structure property, getter/setter
- Remove Piece.productIds property, setProductIds()
- Update fixtures to remove dropped columns
- Add migrations to drop both columns
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ModelType.setStructure() now stores data in pendingStructure instead of
writing to JSON columns. A new ModelTypeProcessor intercepts API Platform
POST/PUT/PATCH operations and delegates skeleton writes to
SkeletonStructureService, which persists to relation tables.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- normalizeComposant : inclure structure du composant dans la réponse
- enrichStructureWithPieceData : résoudre selectedPieceId vers les
données complètes de la pièce catalogue (nom, référence, prix, etc.)
- Update submodule : affichage pièces incluses + quantité machine
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API Platform silently ignored the constructeurs field on PATCH because
Machine was missing the add/remove methods (unlike Composant, Piece, Product).
Also fixes the read-only fournisseur display overflow in MachineInfoCard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add color VARCHAR(7) column to sites entity
- Migration with IF NOT EXISTS for idempotence
- Update reference config
- Frontend: site color picker, dark mode, card styling improvements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove orphaned PUBLIC_ACCESS rule for deleted /api/test route
- Remove JWT login firewall (app is session-based only)
- Set APP_SECRET placeholder (real value must be in .env.local)
- Remove JWT env vars from .env
- Add session regeneration on login (prevent session fixation)
- Remove Document.path from API serialization groups (prevent path leak)
- Restrict health check details to ROLE_ADMIN (anonymes get status only)
- Add path traversal guard in DocumentStorageService
- Convert CreateProfileCommand password to interactive hidden prompt
- Restrict Profile Get endpoint to ROLE_ADMIN
- Change api firewall to stateless: false (matches session-based auth)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract shared ID generation + timestamps into CuidEntityTrait used by all entities
- Create AbstractAuditSubscriber to deduplicate audit logic across 7 subscribers
- Merge per-entity history controllers into single EntityHistoryController
- Delete redundant ComposantHistory/MachineHistory/PieceHistory/ProductHistoryController
- Add OpenApiDecorator for API documentation customization
- Disable failOnDeprecation in PHPUnit (vendor API Platform deprecation)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add nullable TEXT description column to both pieces and composants
tables with corresponding Doctrine entity mappings, getters/setters
and serialization groups.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Patch operation to Site entity (was only Put, causing 405 errors).
Fix migration to use ALTER TABLE DROP CONSTRAINT instead of DROP INDEX
for the piece name unique constraint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create Comment entity with API Platform annotations (GET, PATCH, DELETE).
Add CommentController with POST (create), PATCH (resolve) and GET
(unresolved count) endpoints. Add migration for comments table and
piece reference unique index.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add UniqueEntity validation on Constructeur.name and Piece.reference.
Move unique DB constraint from piece name to piece reference column.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- Add role hierarchy (ADMIN > GESTIONNAIRE > VIEWER > USER) in security.yaml
- Add password authentication on profile activation (SessionProfileController)
- Add SessionProfileAuthenticator with stateless API firewall
- Add ProfilePasswordHasher state processor for API Platform
- Add security annotations on all 18 API Platform entities
- Add denyAccessUnlessGranted on all 13 custom controllers
- Add AdminProfileController for profile/role management (/api/admin/profiles)
- Add InitProfilePasswordsCommand for initial admin setup
- Simplify SessionProfilesController to list-only (removed create/delete)
Frontend (submodule update):
- Add usePermissions composable (isAdmin, canEdit, canView, isGranted)
- Add password login modal on profiles page
- Add admin backoffice page for profile management
- Disable all form fields for ROLE_VIEWER across all edit/create pages
- Show navigation buttons for all roles, hide destructive actions for viewers
- Add readonly mode to ModelTypeForm and site/constructeur modals
- Guard /admin routes in middleware
- Configure Vite proxy for API requests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend service and controller for converting piece categories to component
categories (and vice-versa). Uses raw SQL in a transaction to preserve IDs
and transfer all related data (documents, custom fields, constructeurs).
Includes php-cs-fixer formatting pass on existing controllers/entities.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The path field (base64 data URIs) is now excluded from GetCollection
via document:list group. Individual GET returns path via document:detail
group. Related entities expose id+name in document:list for attachment
display. Frontend lazy-loads path on download/preview click.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update setName() to use mb_strtoupper on the first character so that
category and component names always start with an uppercase letter.
Also update frontend submodule with URL state preservation and back
button improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>