4.5 KiB
4.5 KiB
Tasks: enterprise-network-registry
Change ID: enterprise-network-registry
Package: @suaveplan/network-registry
Target path: universal/network/network-registry
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/events, @suaveplan/logger
1. Scaffold
- Create
universal/network/network-registry/withsrc/,tests/, and all feature subdirectories. - Write
package.jsonat version0.1.0:"sideEffects": false, exports map, deps perproposal.md. - Write
tsconfig.json,vitest.config.ts, scripts.
2. Types and error codes
- Define all public types in
src/types/common.ts:RegistryEntry,HealthStatus,RegistrationHandle,RegistryQuery,RegistryFilter,RegistryChangeHandler,RegistryChange,NetworkRegistryOptions. - Write
src/types/common.md(≥200 words, simple + advanced examples). - Define error codes in
src/error-codes.ts. - Write Zod schemas in
src/types/schemas.ts+src/types/schemas.md.
3. TTL manager (src/core/ttl-manager/)
- Implement
createTtlManager(clock):- Tracks
expiresAtper entry. isExpired(entry)— compare againstclock.now().purge(entries)— returns list of expired entry IDs.- Runs GC on
gcIntervalMsinterval via injectable timer.
- Tracks
- Write
ttl-manager.test.ts+ttl-manager.md.
4. Query engine (src/core/query-engine/)
- Implement
evaluateQuery(entry: RegistryEntry, query: RegistryQuery): boolean:type: match entry type (array = OR, string = exact).capabilities(AND): entry must have ALL capabilities.anyCapabilities(OR): entry must have AT LEAST ONE.tags: all key/value pairs must match.region: exact match.healthyOnly: entry.health.healthy must be true.
- Implement
runQuery(entries: RegistryEntry[], query: RegistryQuery): RegistryEntry[]:- Filter via
evaluateQuery, sort by latency (lowest first), applylimit.
- Filter via
- Write
query-engine.test.ts(≤500 lines): each filter type, AND/OR capabilities, limit. - Write
query-engine.md(≥200 words).
5. Network registry (src/core/registry/)
- Implement
createNetworkRegistry(options?):- Validates options with Zod.
- Stores entries in
Map<string, RegistryEntry>. - Wires TTL manager for expiry.
- Stores subscriptions as
Array<{ query: RegistryQuery; handler: RegistryChangeHandler }>.
- Implement
registry.register(entry):- Validate with Zod; throw
REGISTRY_INVALID_ENTRYon schema failure. - Throw
REGISTRY_DUPLICATE_IDif already registered. - Check
maxEntries; throwREGISTRY_CAPACITY_EXCEEDEDif at limit. - Compute
expiresAt = clock.now() + (entry.ttlMs ?? options.ttlDefaultMs). - Return
RegistrationHandlewithrenew()andderegister(). - Emit event-bus
registry.registeredevent; notify matching subscriptions. - OTel: counter
registry.register_total.
- Validate with Zod; throw
- Implement
registry.deregister(id)— remove; emitregistry.deregistered; notify subscriptions. - Implement
registry.lookup(query)— delegates to query engine; OTel counterregistry.lookup_total, histogramregistry.lookup_results. - Implement
registry.get(id)— direct lookup; throwsREGISTRY_EXPIREDif TTL elapsed. - Implement
registry.list(filter?)— returns all non-expired entries matching optional filter. - Implement
registry.updateHealth(id, status)— updates health; emitshealth-changed. - Implement
registry.subscribe(query, handler)— returns unsubscribe. - Implement
registry.purgeExpired()— delegates to TTL manager; emitsexpiredfor each. - Write
registry.test.ts(≤500 lines): register, lookup, health update, TTL expiry, subscription notification, capacity exceeded. - Write
registry.md(≥200 words).
6. Property-based tests (tests/property.test.ts)
lookup(q)results are always a subset oflist().- After
purgeExpired(), no expired entries remain inlist(). capabilitiesAND: result set is always subset of result with only one capability filter.
7. Docs and verify
- All per-file
.mdfiles per layout inproposal.md. universal/network/network-registry/README.md.bunx turbo lint typecheck test test:coverage --filter=@suaveplan/network-registry— all green, 100%.bun scripts/publish.ts --package @suaveplan/network-registry.- Update
CLAUDE.md. Archive change folder.