# Public Collection Registry Schema — Layer 3 Entity Type # KNO Schema Version: 0.1.0 # Status: Experimental # # Defines the shape of `content/registries/public-collections.kno` — the # canonical, hand-authored registry of public Hive collections (REQ-18). # # WHY THIS EXISTS (#2449): # Before this schema, the list of public collections was duplicated in three # inline TypeScript arrays: # - services/pspace-api/src/lib/public-collections.ts (PUBLIC_COLLECTIONS) # - services/pspace-site/src/lib/public-collections.ts (PUBLIC_COLLECTIONS) # - scripts/lint-public-surface-parity.ts (PUBLIC_COLLECTIONS) # Plus several derived structures (`McpScopes`, `COLLECTION_SCOPES`, # `MCP_SERVER_PATHS`, bootstrap-config `MCP_SERVERS`, mcp/routes.ts # `MCP_SERVERS`) — five mirrors and three maps that drifted in practice # (e.g., the api side used a declarative `discriminator` while the site + # lint side still used a `filter: (c) => boolean` callback). The # `routed-collection-cascade` instruction file documents the full # substrate; this schema + its single instance compress steps 1 + 2 + 3a # of the add-a-routed-collection runbook into a single .kno edit. # # WHAT THIS DOES NOT REPLACE: # - `content/mcp-servers/*.kno` remains the source of truth for the MCP # Registry (`/v0.1/servers`) projection — load-bearing for both # collection MCP servers AND bespoke MCP servers (identity, secrets, # catalog, dynamic-api, …). A3' derives `mcp/routes.ts:MCP_SERVERS`, # `bootstrap-config.ts:MCP_SERVERS`, and `MCP_SERVER_PATHS` from # that directory, NOT from this registry. # - `specs/.kno` files still own `visibility: public` per REQ-18. # This registry only enumerates which schemas/dirs participate. # # EXTENDS: registry-schema (this is a `subtype: public-collections` # specialization of the generic registry concept) # # THREE-GATE TEST (Schema-Minimization Principle): # Gate 1 (Distinctness): YES — a "registry of public collections" is # fundamentally different from a single registry pointer (mcp-registry, # a2a-registry). The mcp-registry entity says "the MCP Registry lives # at /v0.1/servers"; this entity says "guides, rfcs, apis, … are public # and these are their per-collection routing knobs." Different shape, # different consumers. # Gate 2 (Reusability): YES — a single instance today, but the same shape # scales to other collection registries (e.g., a future # `private-collections.kno` for tenant-scoped collections, or # `partner-collections.kno` for federated peers). Three-instance # reusability is achievable within current roadmap. # Gate 3 (Clarity): YES — keeping collections enumerated declaratively # (rather than scanning specs/*.kno for `visibility: public` at runtime) # gives the parity lint a deterministic input and lets the MCP scope # list be generated at build time. The scan-based alternative was # considered and rejected because (a) it makes ordering implicit, # (b) it forces every consumer to re-scan, and (c) it loses the per- # collection routing metadata (route_prefix, mcp.endpoint_path) that # does not belong on the schema itself. # # PROVIDER OPACITY: Not applicable — no vendor names appear in collection # entries. $schema: kno@0.0.9 # ============================================================================= # IDENTITY # ============================================================================= id: 01KQZ2QTVA96325NZBMV75CVT6 slug: public-collection-registry-schema type: spec version: 0.1.0 # ============================================================================= # VISIBILITY (REQ-18) — collection default # ============================================================================= # This schema describes a public reference-knowledge registry. Per REQ-18, # instances may override per-entity (the canonical `public-collections.kno` # instance does NOT override and is therefore public). visibility: public # ============================================================================= # STANDARD TIER # ============================================================================= title: "Public Collection Registry Schema" purpose: | Schema for a single Layer 3 entity that enumerates public Hive collections and their per-collection routing/MCP-projection knobs. Consumers (TypeScript loaders in pspace-api, pspace-site, and the public-surface-parity lint) read this entity as the canonical source of truth for which collections participate in the four-surface contract (REST + llms.txt + MCP + A2A) and what their per-collection metadata is. The schema deliberately keeps fields declarative — no callback hooks, no function-typed filters. The legacy `filter: (entity) => boolean` callback on the site loader is removed in favor of `discriminator: { type, subtype? }` so the registry can be parsed by minimal YAML loaders that have no JS runtime context (e.g., the pre-commit lint). # ============================================================================= # RICH TIER — Provenance # ============================================================================= provenance: origin: id: 01KQZ2QTVA96325NZBMV75CVT6 timestamp: "2026-05-06T00:00:00Z" tool: manual references: - "kno://rfcs/REQ-18" - "kno://specs/registry-schema" taxonomy: topics: - registry - public-surface - four-surface-contract - schema-minimization keywords: - public-collections - REQ-18 - mcp-coverage - parity-lint # ============================================================================= # RICH TIER — Relationships # ============================================================================= relationships: extends: - xri: "kno://specs/registry-schema" reason: "subtype:public-collections specialization" related_to: - xri: "kno://rfcs/REQ-18" reason: "Visibility Declaration — every entry's `schema` MUST declare visibility: public" - xri: "kno://specs/mcp-server-schema" reason: "Collection MCP servers are projected via this registry's `mcp` block" # ============================================================================= # SCHEMA BODY (informal — describes instance shape) # ============================================================================= # The single canonical instance is `content/registries/public-collections.kno`. # Its top-level shape: # # $schema: kno@0.0.9 # id, slug, type: registry, subtype: public-collections, version # visibility: public # title # collections: # - # - … # # Each has the following fields: # # REQUIRED: # name string — directory name under content/ (e.g., "guides") # title string — human-readable section title # # OPTIONAL: # schema string — schema name (without .kno) under specs/ that # declares this collection's `visibility: public` # default. Omit only for collections without a # dedicated schema (e.g., "examples", "bridges") # where per-entity visibility is mandatory. # # route_prefix string|null # — site URL prefix for entity pages (e.g., # "/docs/guides"). `null` means the collection # is public-data but has no entity route on the # site. Such collections are still enumerated # for parity lints but excluded from outline # projections to avoid honeypot links. # # discriminator object — declarative content filter for collections # whose directory hosts mixed entity subtypes. # Replaces the legacy callback-typed `filter`. # Shape: { type: string, subtype?: string }. # Currently used only for `mcp-servers` to # narrow to `{type: service-config, subtype: # mcp-server}` (the directory also contains # bespoke MCP server entities that share the # same shape but project to /v0.1/servers # independently). # # mcp object — collection MCP server projection knobs. # Meaningful only when `route_prefix !== null` # (i.e., the collection has an MCP surface # generated by `createCollectionServer()`). # All sub-fields are derivable from `name` — # explicit values override the defaults. # Sub-fields: # endpoint_path string — defaults to `/mcp/{name}`. # scope string — defaults to `pspace:{name}:read`. # scope_constant string — defaults to `{NAME_UPPER_UNDERSCORE}_READ`. # This is the McpScopes enum key in # services/pspace-api/src/mcp/types.ts. # server_slug string — defaults to `pspace-{name}-mcp`. The # `content/mcp-servers/{server_slug}.kno` # file is the load-bearing record for the # MCP Registry projection. # description string — bootstrap-config label (the human- # readable string alongside the path in # bootstrap-config.ts:MCP_SERVERS). # # private_rationale string — required-by-convention when route_prefix is # null. One-sentence reason why the collection # is public-data-but-unrouted. Surfaces in the # parity lint output and prevents accidental # drift back to "we forgot to route it." # # DRIFT GUARDS: # - scripts/lint-public-surface-parity.ts asserts every entry's schema # (when present) declares `visibility: public`. # - A drift test asserts the three TypeScript loaders return identical # PublicCollection[] data derived from this registry. # - The mcp_coverage_missing rule asserts every routed entry has its # corresponding `content/mcp-servers/{server_slug}.kno`. # # CHANGE PROCEDURE: # To add a new public collection: # 1. Declare `visibility: public` on the collection's schema (REQ-18). # 2. Add an entry to `content/registries/public-collections.kno`. # 3. If routed: create `content/mcp-servers/pspace-{name}-mcp.kno`. # That's it. The five mirrors and three maps regenerate at build time. # Compare to the pre-#2449 12-step runbook in the # routed-collection-cascade instruction file. # ============================================================================= # QUALITY # ============================================================================= quality: completeness: 0.9 last_reviewed: "2026-05-06" review_status: experimental # ============================================================================= # HISTORY # ============================================================================= _history: version: 1 created: "2026-05-06T00:00:00Z" created_by: "pspace-core-team" changes: - "v0.1.0: Initial schema for #2449 substrate fix — single source of truth for public collection enumeration, replacing three inline TypeScript arrays."