* chore(#428,#430): remove deprecated admin-bridge, add vendor cleanup script
admin-bridge was fully replaced by admin-surface — all 11 src files were
marked @deprecated with zero external consumers. Also adds
bin/clean-package-vendors to remove per-package vendor dirs (~283 MB).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: monorepo cleanup — remove stubs, duplicates, and stale artifacts
- Remove empty graphql stub package and all references (composer, phpstan, split workflow, layer test, CLAUDE.md)
- Remove duplicate LICENSE.txt (identical to LICENSE)
- Remove obsolete bin/git-hooks/ (superseded by tools/git-hooks/)
- Move VERSIONING.md and REPO_ADMIN_SETUP.md to docs/
- Untrack .phpunit.cache/test-results and add to .gitignore
- Update CLAUDE.md layer table: remove admin-bridge/graphql, add admin-surface
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add dev-main branch alias to all packages
All 41 packages had branch aliases targeting only dev-develop/v1.1,
which broke composer resolution on the main branch. Adding dev-main
alias unblocks composer update/require operations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(#429): implement GraphQL query and mutation layer
Add packages/graphql/ with webonyx/graphql-php — auto-generates a full
GraphQL schema from entity type definitions, mirroring the JSON:API
auto-route pattern.
Architecture (8 source files):
- GraphQlEndpoint: HTTP boundary, parses GET/POST, executes queries
- SchemaFactory: builds Schema with Query + Mutation types per entity type
- EntityTypeBuilder: EntityType → ObjectType/InputObjectType with lazy thunks
- TypeRegistry: memoized type store, prevents duplicate names
- FieldTypeMapper: Waaseyaa field types → GraphQL scalar types
- EntityResolver: query + mutation resolvers, reuses QueryApplier
- ReferenceLoader: deferred batched loader (N+1 prevention)
- GraphQlAccessGuard: wraps EntityAccessHandler for GraphQL
Features:
- Queries: single entity by ID, list with filter/sort/pagination
- Mutations: create, update, delete
- Nested entity_reference resolution with depth limiting
- Full access control parity with JSON:API layer
- Deferred batch loading via webonyx Deferred
Integration:
- Route registered in BuiltinRouteRegistrar at /graphql (GET+POST)
- Dispatch branch added to ControllerDispatcher
- 12 unit tests, all passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(#429): address PR review findings
- Fix multi-value entity reference resolution (was treating arrays as single refs)
- Narrow catch block in GraphQlEndpoint: schema build errors propagate,
only execution exceptions caught, stack trace logged
- Log access denials in resolveSingle for audit visibility
- Log warnings for unknown field types and missing target types in registry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>