All checks were successful
continuous-integration/drone/push Build is passing
Add the exact pip/npm registry endpoints and secret names, the scope-scoped (not global) registry requirement given Verdaccio's missing uplink, the host-scoped _auth rule, the per-item Drone shell caveat, and the Verdaccio storage uid/permissions gotcha behind the confusing "404 no such package available" error on publish.
8 lines
7.3 KiB
JSON
8 lines
7.3 KiB
JSON
{
|
||
"module": "library_registry",
|
||
"content": {
|
||
"path": "library_registry",
|
||
"docstring": "# Library Registry\n\n## Summary\n\nThe Aetos ecosystem provides internal libraries for the shared concerns of\nevery application. **Use them.** Writing a private copy of any capability below\nis a defect.\n\nEach library also exposes its own documentation as an MCP server. An AI agent\ncan read a library's full API by connecting to its MCP and reading\n`docs://index`, `docs://nav`, and `docs://modules/{module}`.\n\n---\n\n## Catalog\n\n| Library | Import | Purpose | Use instead of | MCP |\n|---|---|---|---|---|\n| DAG Pipe | `dagpipe` | Deterministic state-transformation DAG engine | hand-rolled orchestration/topological ordering | `:8006` |\n| Hexa | `hexa` | Declarative DI / composition-root tooling | manual wiring, hand-written factories | `:8008` |\n| Mongo Ops | `mongo_ops` | Async MongoDB repositories, cache, populate, transactions | raw Motor CRUD and connection lifecycle | `:8007` |\n| Omniread | `omniread` | Format-agnostic fetch + parse (HTML, PDF, CSV, XLSX) | custom scrapers/parsers | `:8003` |\n| OpenAPI First | `openapi_first` | Spec-first FastAPI bootstrap, client, codegen | decorator routers and hand-written clients | `:8004` |\n| Mail Intake | `mail_intake` | Provider-agnostic read-only email ingestion | Gmail OAuth + MIME parsing | `:8002` |\n| Py JWT | `jwtlib` | JWT auth primitives (register/login/introspect) | password hashing + token code | `:8005` |\n| Doc Forge | `docforge` | Docstring compiler → MkDocs + MCP docs | custom doc generators | `:8001` |\n| Doc Weaver | `doc-weaver` | JSDoc compiler → TypeDoc + MCP docs (React/TS) | custom TypeScript doc generators | `:8010` |\n| React Auth | `react-auth` | JWT-backed React auth UI: provider, login page, profile screens, bearer axios client | hand-rolled auth contexts and token handling in React apps | `:8011` |\n| React OpenAPI | `react-openapi` | Spec-driven React admin UI (CRUD, tables, forms, SSE) derived from an OpenAPI document | per-resource hand-written admin screens | `:8012` |\n| Auth Server | *(service)* | Central identity service (register/login/me/logout/introspect) | building auth endpoints yourself | spec: `docs://spec` |\n\n## How to choose\n\n| You need to… | Use |\n|---|---|\n| persist and query documents | Mongo Ops |\n| compose dependencies | Hexa |\n| run a multi-step transformation | DAG Pipe |\n| read/parse an arbitrary input format | Omniread |\n| expose a contract-first HTTP API | OpenAPI First |\n| ingest email | Mail Intake |\n| authenticate users / verify tokens | Py JWT (+ Auth Server) |\n| generate documentation | Doc Forge |\n| generate React/TypeScript documentation | Doc Weaver |\n| authenticate a React front-end | React Auth (+ Auth Server) |\n| build a React admin UI from an OpenAPI spec | React OpenAPI |\n\n## Discovery\n\nA single **standards MCP** exposes `find_library(capability)`, which returns the\nmatching library, its import name, its \"use instead of\" guidance, and its MCP\nendpoint (or, for the auth-server service, a spec pointer). It also serves the\npinned auth-server OpenAPI contract at `docs://spec`. Query it before writing\nany infrastructure.\n\n## Publishing & registry auth\n\nPython packages publish to the private index (`pip.aetoskia.com`, `pypiserver`)\nand npm packages to the private registry (`npm.aetoskia.com`, Verdaccio). Both\nauthenticate against the **same `htpasswd` file** (`/auth/htpasswd`) used by the\nDocker registry and the Traefik basic-auth middleware; registration is disabled,\nso the CI credentials (`PIP_USERNAME` / `PIP_PASSWORD`, `NPM_USERNAME` /\n`NPM_PASSWORD`) are one and the same account — there is no separate npm user.\nVerdaccio requires **bcrypt** htpasswd entries; see\n[90 – Drone Pipelines](90_drone_pipelines.md) for the CI wiring.\n\n### Endpoints\n\n| Registry | URL | Backend | CI secret |\n|---|---|---|---|\n| PyPI | `https://pip.aetoskia.com` | pypiserver (`server-pi:6007`) | `PIP_REPO_URL` |\n| npm | `https://npm.aetoskia.com` | Verdaccio (`server-pi:6008`) | `NPM_REPO_URL` |\n\nBoth are exposed through Traefik on the `websecure` entrypoint as **bare\norigins** — no path, no trailing slash. Set the secret values exactly as above.\n\n### npm: scope the registry, never set it globally\n\nVerdaccio here has **no uplink / proxy**, so it can only serve `@aetoskia/*`\npackages. A global `registry=https://npm.aetoskia.com` in `.npmrc` would route\n*every* dependency — including public transitive deps such as\n`zod-to-json-schema` (pulled in by `@modelcontextprotocol/sdk`) — through\nVerdaccio, which 404s on anything it does not host. Always scope the registry to\nthe account:\n\n```\n@aetoskia:registry=https://npm.aetoskia.com\n//npm.aetoskia.com/:_auth=<base64(user:password)>\n```\n\nPublic deps then resolve from `registry.npmjs.org` and only `@aetoskia/*` hits\nthe private registry. The auth line must be **scoped to the host**\n(`//host/:_auth=`), not a bare `_auth=` — modern npm rejects the bare form with\n`ERR_INVALID_AUTH`. The drone template derives both from the package scope and\n`NPM_REPO_URL` automatically; see\n[90 – Drone Pipelines](90_drone_pipelines.md).\n\n> The Drone pipeline runs each `commands:` list item in a **separate shell**, so\n> shell variables defined in one item do not survive into the next. Keep the\n> variable definitions and the commands that use them in the same `|` block.\n\n### Verdaccio storage permissions\n\nVerdaccio runs as uid **10001** (`verdaccio`) inside `verdaccio/verdaccio`.\nThe `storage` directory is bind-mounted from the server\n(`/mnt/omnissiah-vault/data/verdaccio/storage`); if it is owned by `root:root`\n(mode `755`) the process cannot write to it and every publish fails with a\nconfusing `404 no such package available` (`NotFoundError` from\n`local-storage`). Ensure the directory — and its `plugins` subdirectory — are\nowned by `10001:101`:\n\n```sh\nsudo chown -R 10001:101 /mnt/omnissiah-vault/data/verdaccio/storage\ndocker restart npm-registry\n```\n\n## Notes\n\n- **Hexa** is a full library with its own MCP server on `:8008`: read\n `docs://index`, `docs://nav`, and `docs://modules/{module}` (e.g.\n `docs://modules/hexa.container`) to discover the DI surface — `build(cls, *,\n instances, config)` and the `PortNode` model.\n- **Auth Server** is a **service**, not an importable library: it has no MCP\n bundle by design. Read its client contract from the pinned OpenAPI document\n via `docs://spec` and wire it by declaring a `bearerAuth` security scheme in\n the app's own spec (see **Auth Integration**); `py-jwt` covers the\n low-level token path.\n- **Doc Weaver** is the TypeScript counterpart to **Doc Forge**: it reads\n JSDoc comments and emits a TypeDoc site plus the same doc-forge-shaped MCP\n bundle for React packages. Its convention is **RDFC** (the React Doc-forge\n Convention), the JSDoc parallel to GSDFC.\n- **React Auth** and **React OpenAPI** are front-end libraries (TypeScript,\n React 18 + MUI + React Router peers), not Python services — they consume the\n **Auth Server** and an OpenAPI document rather than serving one. Each ships\n a wiki, a TypeDoc site and an MCP bundle like every other library above.\n- Library MCP servers expose **documentation resources** (not executable tools):\n they tell an agent the available API surface so it does not invent code.\n",
|
||
"objects": {}
|
||
}
|
||
} |