Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Specove

轻量、离线的 OpenAPI 文档浏览组件。读取现有 catalog,按消费方、API 系列、文档版本和生命周期展示文档。页面由包内固定版本的 Swagger UI 渲染,不依赖 CDN,不要求使用者安装 Node.js。

版本:0.1.0a8(Alpha 预览版)。支持 Python 3.7–3.14、Flask 和 FastAPI;最低环境使用 Flask 2.2.5 / FastAPI 0.103.2 起的兼容版本,不代表最新框架支持 Python 3.7。

本仓 Demo

在源码仓库根目录使用项目自身虚拟环境启动(已安装 Flask extra):

.venv\Scripts\python.exe test\demo.py

macOS/Linux 使用 .venv/bin/python test/demo.py。打开 http://127.0.0.1:8765/doc/, 即可预览当前源码、切换消费者及下载示例文档;不需要真实服务、数据库或外部文档。 本地 demo 显式匿名,仅监听 127.0.0.1;全部生成内容在 tmp/demo/,重启会重建脱敏样例。 Ctrl+C 停止,端口被占用时加 --port 8766。后台运行时可按对应进程 PID 停止。Demo 会隐藏访问日志中的全部查询参数,避免记录可重放的分享凭证。 需要验证 INI 账号和签名分享地址时,加 --auth;首次自动创建 tmp/demo-auth/docs/openapi/.specove.ini,从该文件受控获取登录账号密码。

安装与接入

按使用框架选择对应的安装方式:

python -m pip install "specove[flask]==0.1.0a11"
python -m pip install "specove[fastapi]==0.1.0a11"

只使用哪个框架,就安装对应 extra。框架无关的核心没有第三方运行依赖。

from pathlib import Path
from flask import Flask
from specove.flask import register_docs

root = Path(__file__).resolve().parent
app = Flask(__name__)
viewer = register_docs(
    app,
    project_root=root,
)

FastAPI 使用同样的注册参数:

from pathlib import Path
from fastapi import FastAPI
from specove.fastapi import register_docs

root = Path(__file__).resolve().parent
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
viewer = register_docs(
    app,
    project_root=root,
)

访问 /doc/,账号密码从文档目录的 .specove.ini 受控获取。默认用户名为 docs,首次生成随机密码。宿主自行决定是否在 development/testing 注册;Specove 不判断服务环境,不修改原有路由或业务鉴权。FastAPI 原生 /docs、/redoc、/openapi.json 由宿主决定是否关闭,Specove 不会替换它们。

浏览器标签标题

Flask、FastAPI 和 Viewer 均使用 browser_title 指定浏览器标签标题:

register_docs(app, docs_dir=docs_dir, project_root=project_root,
              browser_title="SMAIFiles · 接口文档")

省略或传入 None 时,默认使用 Specove · 接口文档。旧参数 title 保留为兼容别名; 两者同时传入时,非 None 的 browser_title 优先,否则沿用 title。 标题须为非空单行文本,输出时进行 HTML 转义;不会修改 OpenAPI 中的 info.title。

文档目录

项目根/
└── docs/openapi/
    ├── .specove.ini
    ├── catalog.json
    └── service/v1.0.0/openapi.json

catalog.json 示例:

{
  "format_version": 1,
  "api_version": "v1",
  "documents": [
    {
      "consumer": "service",
      "title": "内部服务",
      "api_version": "v1",
      "document_version": "v1.0.0",
      "path": "docs/openapi/service/v1.0.0/openapi.json",
      "lifecycle": "workspace-snapshot",
      "operation_count": 1
    }
  ]
}

初始化只需 project_root;docs_dir 可选,默认 project_root/docs/openapi。path 相对于 project_root,必须解析到 docs_dir 内。只展示目录声明的条目,不扫描历史文件、不要求 all 目录;默认按注册时的快照展示,更新目录后需重建应用。OpenAPI JSON 在读取时重新校验。

首版展示 OpenAPI 3.0.x、3.1.x 自包含 JSON,仅支持 JSON Pointer 内部引用;拒绝外部引用和目录越界。不宣称完成完整 OpenAPI Schema 验证;契约生成和完整规范验证仍由服务构建流程负责。

下载当前文档

在顶部「JSON ▾」菜单选择「下载 JSON」,将当前选中的消费者/版本保存为 openapi.json。 下载复用 /doc/spec/<标识>?download=1,仅返回 catalog 登记且通过校验的单份 JSON, 与 JSON API 一样验证当前文档的 access_key(显式匿名模式除外),禁止缓存。不提供路径参数、目录打包或凭据下载。 下载 JSON 使用两空格缩进、UTF-8 中文及末尾换行,内容与浏览接口一致,不保证源文件逐字节格式。下载失败时在原页面提示,保留文档选择,支持重试。

网关 URL 前缀

页面资源、目录、JSON 及下载均相对当前文档页面定位。0.1.0a11 还将 /doc 补尾斜杠的跳转改为相对地址:外部访问 /gateway/service/doc 时会进入 /gateway/service/doc/,不会跳回站点根目录 /doc/。网关可剥离前缀后转发, 无需额外设置 X-Forwarded-Prefix;已有 Flask SCRIPT_NAME / FastAPI root_path 挂载方式仍兼容。服务内注册路径继续使用 url_prefix="/doc",也支持 /internal/docs。

网关须将该外部文档路径及其子路径一致转发;复制的分享链接会保留外部前缀。 此功能针对文档浏览与 JSON 访问;在线接口调用仍关闭,原始 OpenAPI servers 不改写。 本功能自 0.1.0a11 起提供;CommonLib 需升级固定依赖并在服务中安装对应版本。

JSON API 与 AI 接入

顶部「JSON ▾」菜单合并「复制 JSON 链接」和「下载 JSON」。选择复制后,即可将当前文档链接交给同事或 AI 工具直接读取。 默认不展示完整 URL,复制成功短暂提示;复制均被浏览器拒绝时,才在菜单中展开地址供手动选择。 菜单支持键盘操作、Escape 关闭及点击外部关闭,底部提示分享链接含访问凭证。 地址含受限签名,只授权选中的消费者/版本,无需额外提供 Basic 账号密码;不能用它访问其它文档、 页面、catalog 或静态资源。JSON(含下载)仅接受 access_key,HTTP Basic 不能替代该签名;显式匿名模式例外。 签名绑定有效用户名、密码及随机服务端密钥;任一变更并重启全部 worker 后,旧链接失效。 凭据不变时链接持续有效,无自动过期机制。链接本身是访问凭证,请勿公开传播。 使用 HTTPS,宿主及代理日志应隐藏 access_key 查询参数;URL 不含账号密码原文或签名私钥。 地址基于当前浏览器路径生成,支持代理前缀;剪贴板受限时提供兼容复制或选中地址供手动复制。 接口按请求读取校验文档,目录新增/删除条目的即时识别仍需显式 auto_reload=True。

JSON 鉴权失败统一返回 HTTP 401、application/json,不发送 WWW-Authenticate、不重定向到登录页:

{"code": "missing_credentials", "detail": "缺少访问凭证,请使用包含 access_key 的完整分享链接。"}
{"code": "invalid_credentials", "detail": "访问凭证无效,请重新获取分享链接。"}

未传 access_key 属于缺失;空值、错误、重复、其它文档的签名或凭据轮换后的旧链接均属于无效。错误不返回账号、密码或签名值。

可选目录刷新

Flask、FastAPI 和 Viewer 均支持初始化参数 auto_reload=True,默认 False。 启用后,每次目录或接口 JSON 请求都重读 catalog 并完整校验全部条目; 刷新浏览器即可看到新增、删除或版本变化,不需要重启服务,没有后台线程或浏览器自动轮询。 无效更新使受保护的目录/接口请求返回通用 503,修正后恢复;凭据保持注册时的值。 该选项会增加文件读取与校验开销,适合文档频繁更新的开发环境。

register_docs(app, docs_dir=docs_dir, project_root=project_root, auto_reload=True)

只读目录检查

specove check docs/openapi --project-root .
python -m specove check docs/openapi --project-root .

共用注册和刷新时的目录、路径及引用校验,不加载 Web 框架、不注册路由、不生成密码或说明。 成功返回 0,校验失败返回 1,参数错误返回 2;不会修改目录内容,支持相对或绝对路径。 自定义密码位置可通过 --password-file 路径 提供,只用于排除该文件;不验证实际认证配置。 不替代完整 OpenAPI Schema 验证。

自动维护目录说明

实际注册时,Specove 在调用方传入且已经存在的 docs_dir 内维护 SPECOVE.md。 缺失时生成,文档规范版本变化时原子更新;同规范版本不因工具升级重写。 文件明确标注规范版本、生成工具版本和“请勿修改”的提示,项目补充约定请另建文件。 内容包括目录结构、catalog 字段及示例、最小 OpenAPI 文档、凭据保护及 AI 迁移指引。 说明在目录内容校验前生成,便于校验失败时参考;生成失败仅记录警告,不放宽原有校验。 不存在的目录不会被创建;未调用 Specove(如 CommonLib production 模式)没有生成行为。 本功能不修改 catalog、接口文档或宿主 Git 配置,不通过 HTTP 暴露说明文件。

用户配置与访问保护

docs_dir/.specove.ini 是用户名、密码和分享签名密钥的唯一持久化权威,默认 docs/openapi/.specove.ini:

[auth]
username = docs
password = <首次自动生成的随机密码>
share_key = <首次自动生成的64位十六进制密钥>

以上仅是格式示意,不要用占位值替换实际配置。管理员可受控编辑用户名/密码,保留自动生成的 share_key。 project_root 仍然必需,用于解析 catalog 中相对项目根的 path,并在省略 docs_dir 时定位默认文档目录;不再决定配置文件位置。 旧项目根 .specove.ini 自动迁入 docs_dir,保留完整原始内容、用户名、密码及 share_key,因此原有分享链接继续有效。 迁移目标通过校验且内容一致后才删除旧根配置;两份配置内容不同(包含注释/扩展字段)则报错并保留两份,不覆盖或猜测。 写入/验证失败保留原文件,清理失败保留有效目标配置,下次初始化可重试;匿名模式不执行迁移。 既无文档目录 INI、也无旧根 INI 时才原子初始化,多 worker 共用;默认不再生成 .specove-password。 修改用户名、密码或 share_key 后重启所有 worker,auto_reload 不刷新凭据。 INI 不存在时,自动检查 project_root/.specove-password 和 docs_dir/.specove-password,保留旧密码,无需传 password_file。 新 INI 原子保存并复核成功后,删除这两处约定的普通旧文件;若两处旧密码不同则报错,保留原文件。 已有有效 INI 始终优先,并重试遗留旧文件的清理;保存失败不删除旧文件,清理失败保留 INI,修复权限后重试。 自定义位置的旧文件仍可通过 password_file 首次导入,但不会自动删除。 旧 username/password 仅在创建 INI 时校验,已有 INI 时忽略其值,不覆盖文件;新调用无需传入。 匿名必须显式 allow_anonymous=True,不读写 INI,不可与指定 password 并用。 配置损坏、权限异常或无法原子保存均拒绝启用,不覆盖或降级匿名;首次创建需要文件系统支持硬链接。 Windows 清理旧文件及临时凭据时,对短暂共享占用最多尝试10次、间隔20毫秒;持续权限错误或占用仍拒绝启用并保留有效配置。 异常终止可能遗留 .specove-config-* 临时凭据,须与正式配置一并排除 Git、文档导出及静态/代理服务。 配置是 UTF-8 INI,不启用变量插值,用户名不能包含冒号;用户名/密码须为非空单行且不带首尾空白。 将 **/.specove.ini、**/.specove-config-*、**/.specove-password 及自定义旧文件加入宿主 Git 和文档导出排除, 禁止普通日志、公开接口或其它静态/代理服务暴露配置或签名私钥。Specove 不改写宿主 Git 配置。 页面、目录及包资源使用 HTTP Basic;JSON(含下载)仅使用绑定该文档的 access_key,不要求也不接受 Basic 作为替代凭证。所有响应禁止缓存。 页面内部加载、下载也携带签名链接,并使用 credentials=omit,不携带 Basic 或 Cookie。 Specove 不替换业务接口鉴权,不开放整个文件目录;是否在 development/testing 启用由宿主决定。

开发与发布

测试在 test/,全部缓存与临时产物在 tmp/。使用项目自身虚拟环境:

python -m pip install ".[dev,flask,fastapi]"
python -m ruff format --check src test
python -m ruff check src test
python -m mypy
python -m pytest
python -m build
python test/check_artifacts.py
python -m twine check dist/*

发行包只包含必要的用户说明与许可,不包含 docs/ 下的开发设计、交接或发布过程文档;这些资料仅供源码仓库维护使用。

Specove 采用 MIT;固定版本 Swagger UI 保留独立 Apache-2.0 许可,来源和校验值随包记录。公开 PyPI 的源码和资源公开,即使 GitHub 仓库为私有。

Metadata

Release files for specove 0.1.0a11

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for specove 0.1.0a11
File Size Uploaded Provenance Actions
specove-0.1.0a11.tar.gz 625.0 kB Without provenance Details for specove-0.1.0a11.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for specove 0.1.0a11
File Interpreter ABI Platform Actions
specove-0.1.0a11-py3-none-any.whl Python 3 none any Details for specove-0.1.0a11-py3-none-any.whl

Total release size: 1.2 MB

Release files / specove-0.1.0a11.tar.gz

Download URL specove-0.1.0a11.tar.gz
Size 625.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9bfde6696ababf60284121e380c3616958f1bb66acb475fa727b78d92e8d32d8
BLAKE2b-256 checksum
How to use checksums
c59e7796315f28e1f6c28116a85ebb36e6bd53133e07c9bfc5fe41f4a8ff53ce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.12

Release files / specove-0.1.0a11-py3-none-any.whl

Download URL specove-0.1.0a11-py3-none-any.whl
Size 604.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9168d1af6e5dad61cdb502025487e5aee14284a746027ae9df784fb797cd7660
BLAKE2b-256 checksum
How to use checksums
214cd6dc3959f2b1b3f588e267457adc5de5ed31b0875b019e524db575e761d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.12

Security for specove 0.1.0a11

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page