Skip to main content
Glama

@ingadhoc/docs-platform

Платформа документации Adhoc: один поисковый движок, одно ядро MCP, один шлюз доступа и один предохранитель утечек, потребляемые пинами из репозиториев контента (oba-docs, odumbo-docs, adhoc-docs).

До этого четыре части жили форкнутыми в трёх репозиториях: один и тот же файл с тремя диалектами, и каждый фикс распространялся вручную — или не распространялся. Измерение находится в docs/unificacion/: lib/mcp/indice.mjs имел 41 различие между тремя копиями, и 17 из них были фиксами, которые были в одном репозитории, а в двух других — нет. Самый дорогой случай: предохранитель утечек был байт-идентичным в двух репозиториях и не существовал в третьем.

  • ADR 0006 из knowledge-management — один репозиторий на корпус контента, а платформа как отдельный пакет: контент и движок имеют разные жизненные циклы и разных владельцев.

  • ADR 0007 из knowledge-management — шлюз и предохранитель утечек принадлежат платформе, а не каждому сайту: защита, которую каждый репозиторий перереализует, — это защита, которой у какого-то репозитория нет.

  • Этап A спеки arquitectura-plataforma-docs: этот пакет с двумя версионированными контрактами и drift-check, который делает видимым отставание пина.

Как потребляется

npm i --ignore-scripts github:ingadhoc/doc-platform#v0.1.0

Точный пин, всегда по тегу. Никаких ^, никакого main, никаких веток: пин — это то, что предотвращает поломку трёх сайтов одновременно из-за фикса платформы, и это то, что позволяет откат в одну строку. Диапазон намеренно заставляет docs-drift-check падать — пин, который не пинит, не является пином.

Рекомендуется --ignore-scripts. У этого пакета нет ни одного install-скрипта, и не будет; флаг предназначен для всего дерева, потому что это выполняется в buildCommand публичных сайтов. По той же причине у пакета одна-единственная зависимость (minisearch, которая нужна поисковому движку) и ноль devDependencies: минимальная поверхность в сборке.

То, что у потребителя уже есть и что этот пакет не объявляет: mcp-handler и zod, которые импортирует lib/mcp/mcp-handler.mjs. Это зависимости репозитория, намеренно: репозиторий решает, с какой версией фреймворка MCP разворачиваться, и пакет не навязывает свою. Все три репозитория имеют их сегодня.

После npm i репозиторий-потребитель получает три строки клея:

// api/mcp.mjs
import { crearMcp } from '@ingadhoc/docs-platform/mcp-handler';
import { crearFeedback } from '@ingadhoc/docs-platform/feedback';
import * as indice from '@ingadhoc/docs-platform/indice';
import { config } from '../docs.mcp.config.mjs';
export const { handler, default: fetchHandler } = crearMcp({
  config,
  indice,
  crearIssue: crearFeedback(config.feedback),
});
// middleware.js — en la RAÍZ del repo (Vercel lo exige ahí)
import { next } from '@vercel/functions';
import { decidir } from '@ingadhoc/docs-platform/gate';
const AUDIENCIAS = ['publico', 'interno']; // adhoc-docs: ['interno']
export default function middleware(request) {
  return decidir(request, process.env, { audiencias: AUDIENCIAS }) ?? next();
}
// package.json del consumidor — el guard, dentro del buildCommand
"build:publico": "node tools/build.mjs --audience=publico && npm --prefix site run build && npx docs-guard-fuga --salida=dist/publico"

&& — не косметика: это то, что прерывает деплой, когда предохранитель выходит с кодом 1. Не меняй его на ;.

Что экспортирует

Импорт

Что это

@ingadhoc/docs-platform/indice

поисковый движок: buscar(), leer(), mapa() по индексу, который выдаёт сборка. Единственный, кто использует minisearch

@ingadhoc/docs-platform/mcp-handler

crearMcp({config, indice, crearIssue}): tools, их схемы по осям, Bearer и транспорт

@ingadhoc/docs-platform/gate

decidir(request, env, {audiencias}) / crearGate(config): решение middleware на edge

@ingadhoc/docs-platform/auth

сравнение токенов за константное время (использует node:crypto: только на стороне функции)

@ingadhoc/docs-platform/tokens

грамматика DOCS_MCP_TOKENS, один раз, общая для edge и функции

@ingadhoc/docs-platform/feedback

crearFeedback(config): tool, которая открывает issue в docs-feedback

@ingadhoc/docs-platform/config

cargarConfig() / validarConfig(): валидатор docs.config.json

@ingadhoc/docs-platform/guard-fuga

correrGuard(), если хочешь вызывать его из своей сборки вместо бина

@ingadhoc/docs-platform/middleware

эталонный middleware.js (тот, что идёт в корень потребителя)

bin docs-guard-fuga

предохранитель утечек, для buildCommand

bin docs-drift-check

drift-check, для CI потребителя

Два контракта

Оба несут schemaVersion, и оба читателя выбрасывают ошибку, если эмитент объявляет более новую версию, чем они умеют читать, — или если не объявляет её вообще. Никакой тихой деградации: неправильный индекс, который отвечает плохо, хуже, чем тот, который не отвечает.

  1. config ↔ платформа: docs.config.json, со схемой, опубликованной в schema/docs.config.schema.json, и валидатором в lib/config.mjs (собственный, без зависимостей: ajv не попадает в сборку публичного сайта). Дизайн каждого поля с измеренными доказательствами — в docs/unificacion/diseno-eje.md; три текущих конфига в переводе — в mapeo-configs.md.

  2. индекс ↔ движок: его выдаёт tools/build.mjs каждого репозитория, а читает lib/mcp/indice.mjs. Он описан в docs/unificacion/contrato-indice.md.

Ось в таблице

Корпус объявляет одну ось как объект: { tipo, default?, valores[] }.

eje.tipo

corpus

param в tools

leer() без значения

подстановочный знак (статьи вне оси)

version

oba-docs

version

выбирает default и сообщает об этом (elegidoPor)

да (relacion/ применяется ко всем)

project

adhoc-docs

project

структурная неоднозначность (не объявляет default)

нет

none

odumbo-docs

(не раскрывается)

Правило leer()одно, и в нём нет if по типу оси: оно выбирает только тогда, когда конфиг объявил, кого выбирать. Поведение меняет наличие eje.default, а не тип, — и есть тест, который это проверяет, подставляя default корпусу с осью project.

Запуск тестов

npm install && npm test        # 227 casos

bloques требует репозиторий контента (он по-настоящему запускает его tools/build.mjs на фикстурах инцидентов) и пропускается с причиной, если его нет:

DOCS_REPO=~/repositorios/oba-docs node --test tests/bloques.test.mjs

Полоса HTTP-обработчика из mcp.test.mjs (16 случаев) также пропускается с причиной, если в checkout нет mcp-handler/zod — это зависимости потребителя, а не этого пакета. С обеими установленными mcp даёт 57. Случай без своей capability пропускается явно; он не выполняется в деградированном режиме.


Для jjs — открытые решения

То, что эта сборка не решает сама. Первые три — из diseno-eje.md §7 и затрагивают контракт; остальные вышли из четырёх анализов и остаются живыми после унификации.

1. Одна ось на корпус: принимаем ли потолок?

schemaVersion: 1 допускает одну ось на конфиг, и сегодня этого хватает для трёх репозиториев. В день, когда корпусу понадобится project × version одновременно, схема этого не выражает, и выход — schemaVersion: 2 с ejes: [...] (множественное число). Рекомендация дизайна: явно принять потолок и позволить реальной потребности открыть его заново с доказательствами (тот же критерий, что и сигнализация о бампах на Этапе B). Это твой вызов, потому что это затрагивает major.

2. metadata.types: словарь по корпусу или единый для Adhoc?

Сегодня только adhoc-docs имеет types, и его 6 значений очень похожи на стандарт из knowledge-management (concepto, referencia, procedimiento, troubleshooting, guia, indice). Если словарь принадлежит Adhoc, он не идёт в конфиг каждого репозитория: он идёт в пакет, а конфиг лишь говорит, требует ли он его. Это решение по управлению контентом, а не по схеме; пока оно не принято, схема оставляет его как список по корпусу (совместимо с обоими выходами).

3. Opt-out предохранителя утечек в adhoc-docs: подписываешь?

Схема обязывает объявлять deploy.guardDeFuga, так что тихое опущение уже невозможно. Остаются два выхода, оба защитимы: {"activo": false, "motivo": "…"} (у этого репозитория нет публичной сборки: его шлюз безусловен, а предохранитель защищает от утечки в публичную сборку), или предохранитель всё равно входит, как ремень. motivo, который сейчас в mapeo-configs.md, буквально гласит "PENDIENTE DE FIRMA (jjs)".

И есть техническая часть, которая не чинится копированием файла (ВОПРОС 1 из analisis-04-seguridad.md): у adhoc-docs нет блоков :::interno, он не выдаёт site/generated.json с аудиторией и у него нет карты deploy.proyectos. С предохранителем, активным как есть, его сборка падает с самого начала из-за "no existe site/generated.json". Строгий вариант — чтобы он выдавал эти две вещи.

4. Список аудиторий остаётся продублированным, и drift-check до сих пор его не сравнивает

docs.config.json → audiences и middleware.js → AUDIENCIAS должны совпадать, и нет способа избежать дублирования: edge не читает из файловой системы. Это ровно тот тип тихого дрейфа, с которого начался форк. Не хватает случая в CI, который бы их сравнивал (сегодняшний docs-drift-check измеряет пин, а не эту согласованность).

5. Три вещи, которые нужно проверить в репозиториях перед тегированием

  • DOCS_AUDIENCE во всех трёх окружениях каждого проекта Vercel (Production, Preview и Development) до merge, который принимает пакет. При fail-closed проект без переменной возвращает 503. Это безопасное направление, но не бесплатное.

  • --esperada в текущих buildCommand: теперь предохранитель отклоняет его при запуске на Vercel. Если какой-то buildCommand передаёт его сегодня, этот деплой начинает падать. По снапшотам проверить не удалось.

  • GET MCP возвращает 503, если деплой не объявляет обслуживаемую аудиторию. Это наблюдаемое изменение для потребителя: preflight от Claude Code получает 503 вместо плаката, когда деплой неправильно сконфигурирован.

6. Измеренный долг, который этот пакет не может закрыть

  • Fail-closed препроцессора выводит данные, а затем падает. При неправильно написанной директиве (::: interno), build.mjs записывает site/docs/** с внутренней строкой внутри и затем завершается с кодом 1. Сегодня утечки нет, потому что buildCommand объединяется через &&: защита находится в операторе, а не в программе. Это объявлено как todo в tests/bloques.test.mjs, и это исправляет унификация build.mjs — которая не вошла в этот этап.

  • tests/bloques.test.mjs записывает в <repo>/site/, потому что в oba и odumbo вывод сборки захардкожен. После запуска набора тестов нужно перегенерировать с помощью npm run gen.

  • Ограничения лексического подхода guard: числа и строки короче 5 символов никогда не имеют зонда (ключ 4821, аббревиатура), изображения не сканируются, и утечка внутри applyBlocks не генерирует зонд. Это указано в заголовке guard; я повторяю это здесь, потому что эту часть можно спутать с покрытием.

  • serverInfo.version по-прежнему захардкожена как '1.0.0' в обработчике. Она должна браться из package.json закреплённого пакета, чтобы клиент MCP мог сообщить, с какой версией платформы он взаимодействовал. Это не изменено: это было бы выдумыванием поведения.

  • Подстановочный знак — свойство tipo оси, а не корпуса. Корпус с осью project не может иметь поперечный документ (eje: null остаётся невидимым для любого фильтра). Если когда-нибудь это понадобится, строгий выход — чтобы контракт индекса запрещал это, пока подстановочный знак выключен, чтобы противоречие падало на этапе сборки, а не в рантайме.

  • В спецификации сказано «vitest» как соглашение о тестах Этапа A, и ни один из трёх репозиториев не использует vitest: реальное соглашение — и соглашение этого пакета — это нативный node:test. Стоит исправить эту строку, прежде чем кто-то установит vitest, чтобы ей соответствовать.

-
license - not tested
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Query any docs site via MCP. Submit a URL, ask questions, get cited answers.

  • A paid remote MCP for Context7 MCP docs, built to return verdicts, receipts, usage logs, and audit-r

  • Knowledge coverage map and health score. Ingest docs into a governed knowledge graph via MCP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ingadhoc/doc-platform'

If you have feedback or need assistance with the MCP directory API, please join our Discord server