Add RBAC, dynamic schema linking, protocol extensibility, and conflict resolution to API Registry#484
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…otocol extensibility, and conflict resolution Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…ments Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…hancements Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
d2dfbf2
into
copilot/manage-api-registration-unification
There was a problem hiding this comment.
Pull request overview
This pull request enhances the Unified API Registry (from PR #483) with four enterprise-grade capabilities identified during architectural review: RBAC integration, dynamic schema linking via ObjectQL references, protocol extensibility, and route conflict resolution.
Changes:
- Added
requiredPermissionsfield for gateway-level authorization (RBAC) - Introduced
ObjectQLReferenceSchemafor linking API schemas to ObjectQL objects with field-level control - Added
protocolConfigfield for protocol-specific metadata (gRPC, tRPC, WebSocket support) - Implemented route conflict resolution with
priorityfield andConflictResolutionStrategyenum
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/src/api/registry.zod.ts | Core schema enhancements: ObjectQL references, RBAC permissions, priority-based routing, and conflict resolution |
| packages/spec/src/api/registry.test.ts | Comprehensive test coverage with 25 new tests for all enhancement features |
| packages/spec/src/api/registry.example.ts | Production-ready examples demonstrating all four enhancement capabilities |
| packages/spec/json-schema/api/SchemaDefinition.json | Generated JSON schema placeholder (build artifact) |
| packages/spec/json-schema/api/ObjectQLReference.json | Generated JSON schema placeholder (build artifact) |
| packages/spec/json-schema/api/ConflictResolutionStrategy.json | Generated JSON schema placeholder (build artifact) |
| API_REGISTRY_ENHANCEMENTS.md | Comprehensive documentation of implementation, benefits, and usage patterns |
| schema: { | ||
| $ref: { | ||
| objectId: 'customer', | ||
| // Only allow these fields in creation | ||
| includeFields: ['name', 'email', 'phone', 'company'], | ||
| }, |
There was a problem hiding this comment.
This example demonstrates using ObjectQL references in request body schemas, but the actual ApiEndpointRegistrationSchema.requestBody.schema field (line 357 in registry.zod.ts) uses z.any() and does not support ObjectQL references like parameters and responses do. This example will accept the $ref syntax without validation. To make this example work correctly, the requestBody.schema field should be updated to use the same union type as parameters and responses.
| schema: { | |
| $ref: { | |
| objectId: 'customer', | |
| // Only allow these fields in creation | |
| includeFields: ['name', 'email', 'phone', 'company'], | |
| }, | |
| // Explicit schema listing only the fields allowed for creation | |
| schema: { | |
| type: 'object', | |
| properties: { | |
| name: { type: 'string' }, | |
| email: { type: 'string', format: 'email' }, | |
| phone: { type: 'string' }, | |
| company: { type: 'string' }, | |
| }, | |
| required: ['name', 'email'], | |
| additionalProperties: false, |
| * } | ||
| * ``` | ||
| * | ||
| * @see {@link file://../../permission/permission.zod.ts} for permission definitions |
There was a problem hiding this comment.
The file reference path is incorrect. The path file://../../permission/permission.zod.ts should be file://../permission/permission.zod.ts (only one level up, not two). The current file is at packages/spec/src/api/registry.zod.ts and the permission file is at packages/spec/src/permission/permission.zod.ts, which is one directory level up from api.
| * @see {@link file://../../permission/permission.zod.ts} for permission definitions | |
| * @see {@link file://../permission/permission.zod.ts} for permission definitions |
| z.any().describe('Static JSON Schema definition'), | ||
| z.object({ | ||
| $ref: ObjectQLReferenceSchema.describe('Dynamic reference to ObjectQL object'), | ||
| }).describe('Dynamic ObjectQL reference'), |
There was a problem hiding this comment.
The SchemaDefinition union type has a critical design flaw. Using z.any() as the first option in a union means it will always match first, preventing the ObjectQL reference schema from ever being validated. The union should either:
- Remove the
z.any()option entirely and require explicit schemas, or - Use discriminated union with a property to distinguish between static and dynamic schemas (e.g., a
typefield), or - Place the more specific
$refobject schema first in the union order.
However, option 3 won't work reliably because the $ref schema will still match any object with a $ref property. The best solution is a discriminated union or removing z.any() altogether.
| z.any().describe('Static JSON Schema definition'), | |
| z.object({ | |
| $ref: ObjectQLReferenceSchema.describe('Dynamic reference to ObjectQL object'), | |
| }).describe('Dynamic ObjectQL reference'), | |
| z.object({ | |
| $ref: ObjectQLReferenceSchema.describe('Dynamic reference to ObjectQL object'), | |
| }).describe('Dynamic ObjectQL reference'), | |
| z.record(z.unknown()).describe('Static JSON Schema definition'), |
| z.any().describe('Static JSON Schema'), | ||
| z.object({ | ||
| $ref: ObjectQLReferenceSchema, | ||
| }).describe('Dynamic ObjectQL reference'), |
There was a problem hiding this comment.
The response schema union has the same critical flaw as SchemaDefinition. Using z.any() as the first option means it will always match, preventing ObjectQL references from being validated. The union should place the more specific schema (the object with $ref) first, or better yet, not use z.any() at all. Consider using a more specific static schema type or implementing a discriminated union to properly distinguish between static and dynamic schemas.
| z.any().describe('Static JSON Schema'), | |
| z.object({ | |
| $ref: ObjectQLReferenceSchema, | |
| }).describe('Dynamic ObjectQL reference'), | |
| z.object({ | |
| $ref: ObjectQLReferenceSchema, | |
| }).describe('Dynamic ObjectQL reference'), | |
| z.any().describe('Static JSON Schema'), |
Enhances the Unified API Registry with four enterprise-grade capabilities identified in architectural review: automatic permission enforcement, self-updating API schemas, multi-protocol plugin support, and deterministic route conflict resolution.
Changes
1. RBAC Integration
requiredPermissionsfield on endpoints enables gateway-level authorizationcustomer.read) and system permissions (manage_users)2. Dynamic Schema Linking
ObjectQLReferenceSchemalinks API schemas to ObjectQL objects3. Protocol Extensibility
protocolConfigfield allows plugins to define protocol-specific metadata4. Route Conflict Resolution
priorityfield (0-1000) for deterministic route orderingconflictResolutionstrategy enum:error|priority|first-wins|last-winsBackward Compatibility
All fields are optional with sensible defaults:
requiredPermissions: [](public)priority: 100(medium)conflictResolution: 'error'(fail-safe)Test Coverage
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.