Commit Graph

679 Commits

Author SHA1 Message Date
Matthieu
f965affc94 feat(mcp) : add MCP resources, documentation, and .mcp.json config
- 3 MCP resources: schema, roles, stats
- docs/mcp/README.md with full user guide (config, tools catalogue, workflows)
- .mcp.json for Claude Code stdio transport
- Design spec and implementation plan

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 15:49:00 +01:00
Matthieu
4340a0e13e feat(mcp) : add business tools — search, history, comments, custom fields, documents, model types
- search_inventory: global search across all 6 entity types
- get_entity_history + get_activity_log: audit trail access
- 4 comment tools: list, create, resolve, unresolved count
- 3 custom field tools: list values, upsert, delete
- 2 document tools: list, delete (upload via REST only)
- 6 model type tools: list, get, create, update, delete, sync
- 69 MCP tests pass total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 15:00:37 +01:00
Matthieu
bd7259ed05 feat(mcp) : add Slots, Machine Links, Structure, and Clone tools
- 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>
2026-03-16 14:49:55 +01:00
Matthieu
2f173e766d feat(mcp) : add CRUD tools for Pieces, Composants, Machines
- 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>
2026-03-16 14:38:55 +01:00
Matthieu
4f1e136dc5 feat(mcp) : add CRUD tools for Sites, Constructeurs, Products
- 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>
2026-03-16 14:31:15 +01:00
Matthieu
e335f4c24c feat(mcp) : add stdio auth, dashboard stats PoC tool, and helper trait
- 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>
2026-03-16 14:18:09 +01:00
Matthieu
46ea3ca8ad feat(mcp) : re-enable MCP bundle config after package install
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:09:29 +01:00
Matthieu
65fbd38b55 fix(config) : disable rate_limiter config requiring uninstalled component
The mcp_auth rate limiter requires symfony/rate-limiter which is not
installed. Renamed to .disabled until the MCP stack is ready.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:02:37 +01:00
Matthieu
37aa755819 fix(config) : disable uninstalled McpBundle to fix boot crash
McpBundle was registered but symfony/ai-mcp-bundle is not installed,
causing a critical error on boot. Disabled all MCP references:
- bundles.php: removed McpBundle
- mcp.yaml: renamed to mcp.yaml.disabled
- routes.yaml: removed mcp route
- services.yaml: commented McpHeaderAuthenticator, excluded src/Mcp/
- security.yaml: commented mcp firewall and access control
- phpunit.dist.xml: excluded tests/Mcp

All marked with TODO for re-enabling when the package is installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:01:19 +01:00
Matthieu
ce3f081a0a refactor(category) : remove quantity field from category structure editor
Quantity is now managed per-component on the component edit page,
not at the category level.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 13:52:49 +01:00
Matthieu
63fba4138e perf(component-edit) : remove redundant full-catalog loads on mount
The 3 loadPieces/loadProducts/loadComposants(200) calls on mount were
redundant since select components now load filtered data server-side.
Removing them eliminates ~3 heavy API calls + constructeur resolution
per page load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 13:50:34 +01:00
Matthieu
d58a8c2479 feat(component-edit) : add inline quantity input for piece slots
Quantity can now be edited directly on the component edit page next to
each piece selector, instead of only being defined in the category.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 13:34:51 +01:00
Matthieu
81f7b1a9ac feat(component-edit) : add link to category edit page from component editor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 13:32:54 +01:00
Matthieu
98caaa148d feat(mcp) : add McpHeaderAuthenticator with rate limiting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:07:32 +01:00
Matthieu
523eed927e feat(mcp) : install symfony/mcp-bundle and configure transports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:02:15 +01:00
Matthieu
9e303426a7 fix(slots) : filter slot select options server-side instead of client-side
PieceSelect, ProductSelect and ComposantSelect were loading up to 200
items then filtering client-side by typeId. If the matching items were
not in the first 200, the dropdown appeared empty.

Now each select component uses API Platform filters (typePiece,
typeProduct, typeComposant) to fetch only relevant items server-side,
with local state to avoid overwriting the global catalog cache.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:59:51 +01:00
Matthieu
43bec07bb8 fix(sync) : preserve slot selections when modifying ModelType structure
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>
2026-03-16 11:32:14 +01:00
Matthieu
d4fc0f1fee fix(slots) : check API response before updating local state on slot selection
The save functions (savePieceSlotSelection, saveProductSlotSelection,
saveSubcomponentSlotSelection) were not checking result.success before
updating local state and showing success toast. Since useApi.patch()
never throws, the catch block was dead code and errors were silently
ignored while the UI showed success.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:31:19 +01:00
Matthieu
0181f18778 docs(submodule) : update frontend pointer with v1.9.1 changelog
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:53:39 +01:00
Matthieu
f8403ddfbc docs(changelog) : add v1.9.1 release notes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:53:21 +01:00
Matthieu
8e0acf4896 chore(release) : bump version to 1.9.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v1.9.1
2026-03-16 10:40:45 +01:00
Matthieu
aa8e043c83 fix(submodule) : update frontend pointer with slot selection cache fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:32:15 +01:00
Matthieu
428da471d1 fix(component-edit) : force reload catalog to display pre-selected slot items
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:32:07 +01:00
Matthieu
b2aff0e414 feat(sync) : add slot selection controllers, custom field sync, and position fallbacks
- 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>
2026-03-13 16:40:44 +01:00
Matthieu
271844efb1 feat(component-edit) : add interactive slot selectors for pieces, products and subcomponents
Replace read-only selections display with PieceSelect, ProductSelect, ComposantSelect
components that allow changing the assigned item in each slot directly from the edit page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:40:11 +01:00
Matthieu
4072abf7ba feat(sync) : add ModelTypeSyncService orchestrator and controller with tests
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>
2026-03-13 14:17:57 +01:00
Matthieu
089ca43404 feat(sync) : implement PieceSyncStrategy with tests 2026-03-13 14:07:04 +01:00
Matthieu
f09c7e4782 feat(sync) : implement ComposantSyncStrategy with tests 2026-03-13 14:00:59 +01:00
Matthieu
07cad19988 feat(sync) : wire sync flow into category edit pages with confirmation modal 2026-03-13 13:57:58 +01:00
Matthieu
6a20dcce54 feat(sync) : implement ProductSyncStrategy with tests 2026-03-13 13:54:47 +01:00
Matthieu
8dacad7a59 refactor(sync) : remove restrictedMode and add sync service + confirmation modal 2026-03-13 13:49:24 +01:00
Matthieu
6e0be3dbf3 feat(sync) : add DTOs and SyncStrategyInterface
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:47:59 +01:00
Matthieu
f66db3f2f0 test(sync) : extend factories for PieceProductSlot and CustomField with ModelType
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:44:52 +01:00
Matthieu
0864af1439 feat(sync) : migration for PieceProductSlot table and version columns
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:41:56 +01:00
Matthieu
5210e53d73 feat(sync) : add version field and PieceProductSlot entity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:38:13 +01:00
Matthieu
3f07162b94 docs(sync) : add implementation plan for ModelType sync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:16:19 +01:00
Matthieu
57615b3e9d docs(sync) : address spec review feedback — atomicity, matching, M2M migration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:02:27 +01:00
Matthieu
46694d11d9 docs(sync) : add ModelType sync design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:57:27 +01:00
Matthieu
44cfa25eca feat(composant) : add ComposantPieceSlotController for slot quantity PATCH
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:22:43 +01:00
Matthieu
7ea4cc8c12 chore(submodule) : update frontend pointer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:22:01 +01:00
Matthieu
bb300a7ca7 feat(composant) : add virtual getStructure() rebuilding legacy JSON from slot tables
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>
2026-03-13 11:21:17 +01:00
Matthieu
556da6e451 fix(custom-fields) : include customFields and customFieldValues in product normalization
normalizeProduct() had customFields hardcoded to [] and was missing
customFieldValues entirely, unlike normalizeComposant and normalizePiece.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:20:28 +01:00
Matthieu
8871440c9a fix(custom-fields) : populate customFields in ModelType structure from relations
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>
2026-03-13 11:19:42 +01:00
Matthieu
5912216a89 fix(piece) : persist slot quantity on blur and send prix as string
- Save composant piece slot quantity via PATCH on blur
- Pass slotId through hierarchy and selection entries
- Send prix as string (not number) to match backend expectation
- Show quantity in view mode when > 1
- Allow quantity edit for all pieces (not just root-level)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:19:09 +01:00
Matthieu
139ba183de fix(custom-fields) : include orphan values with embedded definitions in edit pages
After JSON-to-tables migration, custom field definitions not linked to
a ModelType were invisible on edit pages because buildCustomFieldInputs
only mapped over structure definitions. Now also includes values whose
embedded customField definition has no matching structure entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:18:47 +01:00
Matthieu
6f1756e82e fix(fixtures) : add INSERT statements for new relational tables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:31:02 +01:00
Matthieu
55bed90ac7 test(normalization) : add tests for skeleton requirements, composant slots, piece-product relation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:25:00 +01:00
Matthieu
a6139d7090 feat(normalization) : drop structure and productIds JSON columns
- 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>
2026-03-13 08:19:54 +01:00
Matthieu
8ed5f90b63 feat(structure) : read composant structure from slot relations instead of JSON
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:23:56 +01:00
Matthieu
5194543d16 feat(composant) : create composant slot tables and migrate data from structure JSON
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:20:31 +01:00