Design model
Graph-first landing, navbar shell, global registry, code-doc vs platform-spec separation, and MCP connect surface.
Document layout: Feature capability layoutconforms
## Purpose## Requirements
Design model Specification
Purpose
Graph-first landing, navbar shell, global registry, code-doc vs platform-spec separation, and MCP connect surface.
Requirements
Requirement: Design model conformance status
This capability SHALL remain non-conformant and MUST NOT be cited as an implemented Beskid guarantee until a validated OpenSpec change adds explicit behavioral requirements.
Stable ID: BSP-REQ-A4847E932F66
Scenario: Capability has descriptive material only
- GIVEN the migrated sources contain no uppercase BCP-14 obligation or accepted ADR decision
- WHEN an implementation reports Beskid conformance
- THEN it MUST NOT claim conformance based on this capability
Informative Source Provenance
The records below preserve migration history and are not normative except where text was extracted into a requirement above.
Source Record: Design model
Authority: informative provenance
Legacy path: /platform-spec/tooling/nexus/design-model/
Source: site/spec-content/platform-spec/tooling/nexus/design-model/content.md
SHA-256: 2172729ea529619ab2ca0002b1c3a92ea4ce861ce4a58228f57f55a38f6c4cee
Migrated source text
## UX shell
Nexus **must** align with tracker and site chrome:
| Element | Contract |
| --- | --- |
| Layout | Top navbar (not sidebar) |
| Kicker | `Beskid / Nexus / {repo}` |
| Repo switch | `<Select>` bound to public catalog |
| Search | Symbol search over active graph |
| Theme | Light/dark toggle |
| Hub | `BeskidHub` launcher from `@beskid/beskid-ui` |
Interactive UI **must** use `@beskid/ui-react` primitives via the `#/components/ui` alias. Styles **must** import `@beskid/ui-react/styles/shadcn-entry.css` and `@beskid/beskid-ui/styles/hub.css`.
## Graph-first landing
| Rule | Behavior |
| --- | --- |
| N-01 | `/` **must** load the first **enabled, indexed** catalog entry by ascending `sortOrder` |
| N-02 | When no indexed entry exists, show empty state with sign-in CTA for repo owners |
| N-03 | Deep link `?repo=<catalog-id>` **must** select that entry and load its graph |
| N-04 | Default view **must** be the graph explorer — not a catalog home grid |
Admin flows (add repo, re-index, delete) **must** appear as dialog or sheet overlays, not separate full-page phases.
## Global registry model
The server maintains `catalog.json` — the authoritative list of public Nexus entries.
| Field | Role |
| --- | --- |
| `id` | Stable catalog identifier; used in `?repo=` and admin routes |
| `displayName`, `description`, `gitUrl`, `defaultBranch` | Public metadata |
| `sortOrder` | Landing and selector ordering |
| `indexed`, `registryName` | Whether a LadybugDB export exists and its storage key |
| `lastIndexedCommit`, `indexedAt`, `stats` | Index freshness and graph size |
| `docStatus` | Coarse doc pipeline state (`idle` \| `running` \| `failed` \| `ready`) — no AI vendor details |
Index pipeline: clone → analyze worker → `.gitnexus/` index → optional code-doc maintenance worker.
## Code documentation vs platform spec
Two distinct layers. Implementations **must never** merge or paraphrase platform spec into code documentation.
| Layer | Source | Stored in | Public exposure |
| --- | --- | --- | --- |
| **Code documentation** | Graph + source snippets | `code-docs/{registryName}.json` | `properties.codeDoc` on graph nodes/clusters |
| **Platform spec** | `site/website/.../platform-spec/` | Site only — **not copied** | Never inlined |
| **Spec links** | Read-only spec index search | Same JSON sidecar | `properties.specLinks` — `{ title, href }[]` |
### CodeDocRecord
```typescript
interface CodeDocRecord {
entityId: string;
entityKind: 'node' | 'cluster';
/** Repo-scoped explanation. Must NOT contain platform-spec prose. */
codeDoc: string;
/** 0–3 canonical platform-spec URLs. href must exist in spec index. */
specLinks: Array<{ title: string; href: string }>;
contentHash: string;
updatedAt: string;
}
```
Doc worker rules:
1. **Code doc text** is generated solely from graph context and file snippets.
2. Spec search is used **only** by `resolve_spec_links` to propose canonical URLs — models **must not** invent paths.
3. When a spec page fully covers a topic, `codeDoc` stays brief and points via `specLinks`.
4. Anti-copy validation rejects records where `codeDoc` contains long n-grams matching spec index chunks.
Public graph API **must** merge `codeDoc` and `specLinks` as **separate** node properties. UI **must** render them in distinct sections.
## Server architecture
```
┌─────────────────────────────────────────────────────────────┐
│ gitnexus serve (single process) │
├─────────────────────────────────────────────────────────────┤
│ /api/catalog public registry + graph metadata │
│ /api/graph cached LadybugDB export (stream) │
│ /api/admin/catalog/* repo-owner gated CRUD + analyze │
│ /api/mcp StreamableHTTP (Bearer token) │
│ /api/internal/code-docs/* server-only job status (no UI) │
├─────────────────────────────────────────────────────────────┤
│ catalog.json → clone → analyze → .gitnexus/ index │
│ post-analyze → doc-maintenance (OpenRouter, hidden) │
│ code-docs/{registryName}.json │
│ spec-index.json (read-only link resolution) │
└─────────────────────────────────────────────────────────────┘
```
## MCP connect surface
| Rule | Contract |
| --- | --- |
| N-MCP-01 | MCP endpoint **must** be same-origin `{origin}/api/mcp` |
| N-MCP-02 | Transport **must** require `Authorization: Bearer $NEXUS_MCP_AUTH_TOKEN` |
| N-MCP-03 | Header button **Connect MCP** **must** be visible when user is signed in |
| N-MCP-04 | Dialog **must** show endpoint URL, auth header template, copy actions, and link to [MCP contracts](/platform-spec/tooling/nexus/contracts-and-edge-cases#mcp) |
Token value is a deployment secret — UI shows placeholder guidance for operators, not the live secret.
## Ownership verification
On mutating catalog operations the server **must** call GitHub `GET /repos/{owner}/{repo}` with the user's hub token and require `permissions.admin` or owner login match. Env-based admin rosters **must not** gate per-repo CRUD (operator setup endpoints excepted).
## Decisions
<!-- spec:generate:adr-index -->
No ADRs published under **`adr/`** yet.
<!-- /spec:generate:adr-index -->
## Articles
<!-- spec:generate:article-index -->
_No articles in this bundle yet._
<!-- /spec:generate:article-index -->