Setup repo: migrate architecture specs, code stubs, and tasks from alkhub_ts
Copy architecture docs, ADRs, storage domain specs, research, reviews, and 56 storage architecture tasks from the alkhub_ts monorepo. Adapt for standalone @alkdev/hub repo structure (src/ not packages/hub/). Sanitize all sensitive information: - Replace private IPs (10.0.0.1) with localhost defaults - Remove internal server hostnames (dev1, ns528096) - Replace /workspace/ private paths with npm package references - Remove hardcoded credentials from examples - Rewrite infrastructure.md without private network details Add Deno project scaffolding: deno.json (pinned deps), .gitignore, AGENTS.md, entry point. Migrate existing code stubs (crypto, config types, logger) with updated import paths.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
---
|
||||
id: split-operations-into-definitions-and-registrations
|
||||
name: Split operation_specs into operations (definitions) + operation_registrations
|
||||
status: completed
|
||||
depends_on: []
|
||||
scope: broad
|
||||
risk: high
|
||||
impact: phase
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The current `operation_specs` table conflates two concepts:
|
||||
|
||||
1. **Operation Definition**: The schema/contract — what the operation is named, its input/output types, access level. Shared across multiple provider instances (e.g., 5 opencode instances all provide the same `chat.complete` operation).
|
||||
|
||||
2. **Operation Registration**: A specific provider (spoke or client) offering that operation right now. Ephemeral — registrations come and go as spokes connect/disconnect.
|
||||
|
||||
This conflation creates problems:
|
||||
- No way to distinguish "a spoke provides this" from "this operation exists as a concept"
|
||||
- Disconnect lifecycle ambiguity (delete vs soft-deactivate) becomes a schema design problem
|
||||
- OpenAPI/MCP spec imports create definitions without any provider; the current schema has no home for these
|
||||
- Same-named operations from multiple spokes have no natural representation
|
||||
|
||||
### Design Decision (D3)
|
||||
|
||||
Split into two tables:
|
||||
|
||||
**`operations`** (definitions):
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| id | text PK | |
|
||||
| namespace | text | Post-remap identifier (e.g., `dev.{spokeId}.fs.read`) |
|
||||
| name | text | |
|
||||
| type | text | query, mutation, subscription |
|
||||
| inputSchema | jsonb | TypeBox schema |
|
||||
| outputSchema | jsonb | TypeBox schema |
|
||||
| accessLevel | text | |
|
||||
| description | text | |
|
||||
| ...commonCols | | createdAt, updatedAt |
|
||||
|
||||
**`operation_registrations`** (instances):
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| id | text PK | |
|
||||
| operationId | text FK → operations.id | CASCADE on delete (def deleted → registrations gone) |
|
||||
| providerType | text | "spoke" or "client" |
|
||||
| providerId | text FK → spokes.id or clients.id | Polymorphic — see notes |
|
||||
| status | text | "active" or "inactive" |
|
||||
| preRemapNamespace | text | Original spoke identifier (e.g., `dev.fs.read`) for traceability |
|
||||
| preRemapName | text | Original spoke name |
|
||||
| metadata | jsonb | Provider-specific metadata |
|
||||
| registeredAt | timestamp | |
|
||||
| ...commonCols | | createdAt, updatedAt |
|
||||
|
||||
### Key Implications
|
||||
|
||||
- **On spoke disconnect** → `operation_registrations.status` set to `inactive`. Definitions survive. Reconnection re-activates or creates new registration.
|
||||
- **On admin spoke-row deletion** → `operation_registrations` CASCADE (ephemeral config, D1). If no other registrations exist for an operation, the definition may be cleaned up by a separate process.
|
||||
- **OpenAPI/MCP imports** → create `operations` rows from spec, no registration until a client connects.
|
||||
- **Namespace convention** → `operations.namespace`/`name` store **post-remap** identifiers. `operation_registrations` stores the pre-remap identifiers for traceability.
|
||||
- **Call routing** → lookup operation by namespace+name, then find active registrations, dispatch to provider.
|
||||
- **Partial unique indexes** → `operations` has unique on `(namespace, name)` (no more spoke-scoped partial unique). `operation_registrations` has partial unique on `(operationId, providerType, providerId) WHERE status = 'active'`.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `spokes.md` documents the `operations` table schema with all columns
|
||||
- [ ] `spokes.md` documents the `operation_registrations` table schema with all columns
|
||||
- [ ] `operation_specs` references are replaced with `operations`/`operation_registrations` across all docs
|
||||
- [ ] `table-reference.md` has FK entries for: `operation_registrations.operationId → operations.id` (CASCADE), `operation_registrations.providerId → spokes.id` (SET NULL on disconnect — providerId becomes null when spoke row is deleted; or RESTRICT if spoke rows are never deleted)
|
||||
- [ ] `spokes.md` disconnect lifecycle is unambiguous: "deactivates the spoke's operation_registrations (sets status to inactive). Operation definitions persist."
|
||||
- [ ] ADR-006 is updated to reflect the definitions/registrations split (or superseded by a new ADR)
|
||||
- [ ] `README.md` Open Question #2 is resolved with a cross-reference to the decision
|
||||
- [ ] The review item W04 (pre/post-remap namespace) is resolved: `operations` stores post-remap, `operation_registrations` stores pre-remap
|
||||
- [ ] `call-graph.md` and `coordination.md` references to `operation_specs` are updated if applicable
|
||||
|
||||
## References
|
||||
|
||||
- docs/reviews/storage-architecture-review-2026-04-21.md#C03
|
||||
- docs/reviews/storage-architecture-review-2026-04-21.md#W04
|
||||
- docs/decisions/storage-spec-phase1-resolutions.md#D3
|
||||
- docs/architecture/storage/spokes.md
|
||||
- docs/architecture/storage/table-reference.md
|
||||
- docs/decisions/ADR-006
|
||||
- docs/architecture/spoke-runner.md:62
|
||||
|
||||
## Notes
|
||||
|
||||
This task subsumes the original `resolve-op-specs-lifecycle` and `clarify-operation-specs-namespace` tasks. Both are resolved by the definitions/registrations split.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Reference in New Issue
Block a user