167 lines
14 KiB
Markdown
167 lines
14 KiB
Markdown
# Endor · Tabularium
|
||
|
||
Endor 文档与制图 monorepo。Tabularium 取古罗马档案馆之意。支持本地开发,并由 Gitea Actions 在 ces-control 上验证与部署。
|
||
|
||
## 本地开发
|
||
|
||
需要 Node.js 22.13+(推荐 LTS)、pnpm 11.25、Python 3.11+ 和 uv。
|
||
首次安装依赖需要访问软件包源。本地开发服务只监听 127.0.0.1。
|
||
|
||
```sh
|
||
pnpm install --frozen-lockfile
|
||
uv sync --project tools/figures --locked
|
||
pnpm dev
|
||
```
|
||
|
||
访问 http://127.0.0.1:3000 ,先使用验证器动态码登录。首次本地使用需按下文初始化私有认证配置;缺少配置时正文关闭访问。站点无外部字体或 CDN 资源。
|
||
|
||
```text
|
||
apps/docs/ Next.js Pages Router + React + TypeScript + Tailwind CSS
|
||
content/docs/ Markdown 文档源,支持目录,路径成为 /docs/<path> 路由
|
||
tools/figures/ 独立 Python 项目,使用 drawsvg 编程制图
|
||
```
|
||
|
||
## 命令
|
||
|
||
- `pnpm dev`:本地开发,修改 Markdown 后刷新页面即可读取新内容。
|
||
- `pnpm figures`:运行 Python 制图,更新 `apps/docs/public/figures`。
|
||
- `pnpm lint` / `pnpm typecheck`:前端静态检查。
|
||
- `pnpm build`:构建文档站。
|
||
- `pnpm start`:在本地预览已构建站点。
|
||
- `pnpm check`:依次执行 lint、类型检查、制图与构建。
|
||
|
||
站点默认浅色,使用本地系统字体。全站搜索支持正文关键词、`⌘/Ctrl K`、方向键与 Enter;代码块提供复制与反馈。桌面提供分组导航和滚动高亮的页内目录,小屏可展开文档菜单与页内目录。首页入口、草案提示、前后篇导航均引用现有 Markdown 内容和资料目录配置。顶部提供文档切换,阅读页左侧只展示当前文档,并有独立图标、名称与返回入口;搜索框标明当前文档范围。界面主要通过留白、轻渐变与状态反馈分层,支持减少动态效果的系统偏好。
|
||
|
||
参考设计截图与研究记录保存在 `design/references`;浏览器验收截图与检查说明保存在 `design/verification`。这些文件不作为站点静态资源发布。
|
||
|
||
文档标题取首个 `# 标题`,文档排序按相对路径。支持多层目录(例如 `content/docs/pretext/01-chapter.md` 对应 `/docs/pretext/01-chapter`);旧文档地址保持可用。`content/catalog.json` 管理合集、分类、摘要、草案与推荐,新增资料无需修改页面代码。首页推荐最多3篇,目录每页8条,可按合集与标题筛选;全站搜索仍覆盖全文。相邻篇目限于当前合集。
|
||
|
||
Pretext 教程位于 `content/docs/pretext`,包含导读与12章,来自本地 Pretext 研究成果。源码链接锁定上游研究版本;实验脚本与原始记录位于 `apps/docs/public/materials/pretext`,和正文一样经过登录验证。普通 Markdown 与 GFM 表格可用,嵌入图使用 `/figures/<name>.svg`。不解析原始 HTML。
|
||
|
||
语言设计问题集位于 `content/docs/language-design`,是第三个资料合集,包含总览与原编号02–14的13个分类,共271项议题。原讨论已确认26项,其余保持待讨论;来源映射和本次状态记录位于 `content/language-design-sources.json`。维护时同步章节、总览计数与来源状态;不会自动从聊天同步,也不把设计记录等同于已实现功能。
|
||
|
||
生产构建会生成文档路由;新增或修改文档后重新运行 build。开发模式按请求读取内容。
|
||
main 推送通过 CI 验证后自动部署;Pull Request 只验证,不部署。工作流也支持手动触发。
|
||
|
||
## Endor 概念图
|
||
|
||
`content/docs/00-endor-concepts-draft.md` 解释全球入口、区域网关与 Runtime、分片、CDN、身份及跨区恢复的概念设计,页面为 `/docs/00-endor-concepts-draft`。
|
||
|
||
图形源码位于 `tools/figures/src/endor_figures/architecture.py`,由 `pnpm figures` 生成 `apps/docs/public/figures/endor-architecture.svg`。Python 负责可复现的节点、全连接和复制路径,正文直接显示图片,点击可放大;大图支持原尺寸查看、滚动和 Escape/空白处关闭。无需外部图标、字体或绘图服务。图中的数量是示意,身份服务/CDN 接入属于建议,所有未实现的关系均以草案说明。
|
||
|
||
拓扑检查:`uv run --locked --project tools/figures python -m unittest discover -s tools/figures/tests -v`。容器检查流程会运行同一检查。
|
||
|
||
## 动态码登录与二维码
|
||
|
||
与 PROMPT 的参考流程一致:共享验证器的6位TOTP动态码,每30秒更新;成功登录的HttpOnly、SameSite=Lax会话有效7天。此方案是动态码单因素登录,不是密码加动态码的双因素组合。
|
||
|
||
正文、SVG、文档数据与API都经过认证,仅登录入口、登录所需代码资源和最小健康检查公开。20次/5分钟的共享尝试上限与已用时间步持久保存在SQLite中,跨进程和重启继续生效。缺失或损坏配置时拒绝访问,不自动降为公开站点。
|
||
|
||
生产认证文件位于服务器 `/opt/endorphin-tabularium-docs/private-auth`,目录0700、文件0600,只挂载进本项目容器。部署只初始化一次,后续更新保留同一验证器密钥与会话签名密钥。生产镜像、Git、CI日志和网页不包含密钥。
|
||
|
||
管理员通过SSH管理:
|
||
|
||
```sh
|
||
sudo /opt/endorphin-tabularium-docs/auth qr
|
||
sudo /opt/endorphin-tabularium-docs/auth verify
|
||
```
|
||
|
||
`qr`只允许交互终端显示;`qr-png`用于通过SSH将PNG直接重定向到私有本地文件,不在CI中运行。二维码等同登录凭据,不放入本仓库或网页。只有明确执行 `auth rotate --confirm` 才更换密钥并使旧二维码、会话失效;重新显示或下载二维码不会轮换。
|
||
|
||
本地先构建CLI,再初始化独立的本地测试配置:
|
||
|
||
```sh
|
||
pnpm build
|
||
AUTH_CONFIG_FILE=/private/tmp/tabularium-auth/config.json node apps/docs/.next/standalone/apps/docs/auth-cli.cjs init
|
||
AUTH_CONFIG_FILE=/private/tmp/tabularium-auth/config.json AUTH_COOKIE_SECURE=false pnpm dev
|
||
```
|
||
|
||
当前服务器入口为HTTP,与参考项目一致使用 `AUTH_COOKIE_SECURE=false`;配置HTTPS后应在独立production.env设置 `AUTH_COOKIE_SECURE=true`。HTTP本身不加密动态码和会话传输。
|
||
|
||
`pnpm test:auth`运行算法、会话、重放及限流测试。容器验证使用自己的匿名测试卷完成登录/并发重放/CSRF/限流测试,并在重启后检查状态仍存在。生产部署只运行无副作用的 `verify`,不会消耗用户动态码或触发生产限流。
|
||
|
||
## AI 公司研究
|
||
|
||
导航入口为 **其他研究 → AI 公司研究**,页面路径是
|
||
`/docs/other-research/ai-company-research/overview`。工作台提供业务分类、公司搜索与筛选、
|
||
公司明细、收入观测、原始证据和数据核查记录。所有页面与
|
||
`GET /api/research/ai-companies` 均使用文档站现有的登录认证。
|
||
|
||
研究数据与登录状态**共用文档站现有的 SQLite 数据库文件**:
|
||
`AUTH_CONFIG_FILE` 同目录下的 `login-state.sqlite`。该文件名是历史名称,未创建第二个数据库。
|
||
`login_state` 保留登录限流与重放状态,新增的 `research_*` 表保存数据版本、分类、
|
||
公司、经营指标、证据与核查记录。沿用现有 `/auth` 持久挂载,数据库不会写入镜像或公开目录。
|
||
|
||
`content/research/ai-companies.seed.json` 是可评审的研究导入快照,
|
||
服务端首次读取该版本时将它以事务导入同一数据库,之后从数据库查询记录。
|
||
导入使用外键校验,不删除登录数据,也不覆盖旧研究版本。每次更新快照必须修改 `version`;
|
||
同一版本内容变化会拒绝导入,避免静默读取旧数据。回退代码时继续读取对应旧版本。
|
||
所有修改都经过工作分支和 PR,部署仍等待人工合并主线。
|
||
|
||
当前资料包含 1,002 条公司/产品记录、10 类业务及待分类组、1,055 条证据记录和 126 条经营观测。
|
||
其中保留 58 家个案资料、928 条目录基础资料,并新增 16 个平台产品/业务样本;目录项不等于完成财务和技术核验。
|
||
它是定向试样,收入披露不足且统计时点不统一,不代表全部 AI 公司。
|
||
界面将公司自述、第三方估算、融资、客户收入和履历收入分开,未知收入不记为零。
|
||
保留被撤回的声明作为核查记录,并排除收入比较;并购后业务、管理层预测与历史里程碑单列。
|
||
团队规模下界在列表中显示比较符,商业成熟度展示公开交付证据,不等于技术能力排名。
|
||
公司披露的 ARR 尚未建立同期同口径比较组。新增平台 MRR 单独计算探索性样本统计,
|
||
不能称行业平均 ARR、总体离散排名或财务造假概率。
|
||
|
||
收入分布:`IncomeDistribution.tsx` 从数据库返回的观测中筛选平台 USD MRR,
|
||
每个产品只保留符合条件的最新值,默认数据日期距截止日不超过7天。
|
||
按业务类别、支付来源及可选收费模式分组,显示均值、中位数、样本CV(标准差分母n−1)、
|
||
均值/中位数和移除最大值后的均值敏感性。n<3标注样本不足;n=1不计算CV。
|
||
MRR×12仅作为显示单位转换,不改写为公司ARR;公司ARR、估算与近30日收入均不混入。
|
||
`ai-income-analysis.json` 是独立Python复算的7日/90日快照参考,用于检查统计选择和计算,
|
||
页面本身从同一SQLite中的公司与观测记录计算,不读取第二个数据库。
|
||
|
||
平台同步时间、连接过期状态、业务描述的可编辑性和产品/法律主体未去重限制均保留。
|
||
默认7日样本14个产品;90日窗口新增Gojiberry的8月历史点,营销样本的均值和CV随之明显变化。
|
||
这提示先核查时间与样本构成,不能将高离散度直接解释为造假。两个近名营养应用按不同App Store ID分别建档。
|
||
|
||
覆盖核查:从 yc-oss 非官方镜像发现 2025—2026 八个 YC 批次的 1,428 条候选,
|
||
逐条读取对应 YC 官方公开页面,以页面中的成立年份、团队字段和业务描述筛选。
|
||
962 条初筛匹配,其中 34 条与原表 URL 重合,实际新增 928 条;268 条年份不符或缺失、
|
||
192 条 AI 业务待确认、6 条成立年份晚于批次年份未纳入本批新增。
|
||
`content/research/ai-companies.coverage.json` 保留逐条筛选结果、来源与响应摘要,
|
||
数据快照中的 `coverage` 也随版本进入同一 SQLite 数据库。只覆盖该候选池,不能称全球全量。
|
||
|
||
新增业务分类优先匹配主营简介,再参考目录标签;未匹配者进入待分类组。
|
||
初分规则位于 `scripts/classify-ai-profiles.py`,只生成待评审标签,不执行抓取或构建。
|
||
所有新增项均标注规则初分,保留 `classificationBasis` 和 `directoryTags` 供复核。
|
||
AI 关键词可能出现在业务背景中,收入、买家和交付状态仍须逐家深查,不能把目录项的未知收入当作未披露。
|
||
界面支持按资料深度、记录团队规模筛选;证据列表每页 30 条,避免一次渲染全部来源。
|
||
|
||
`pnpm test:research` 在远程 Runner 上验证同库持久化、重复读取、版本导入与回退、
|
||
登录限流保留、引用完整性及收入排除规则。镜像冒烟检查会验证研究页面与 API 的认证、
|
||
返回记录数量、只读方法和容器重启后的读取结果。页面筛选交互仍需实际浏览器验证。
|
||
|
||
## CI/CD 与缓存
|
||
|
||
`.gitea/workflows/ci-deploy.yml` 使用已有 ces-control Runner,不修改共享 Runner 配置。
|
||
当前工作流仅在 main 推送或针对 main 的手动运行时执行。工作分支PR完成本地静态核查后,
|
||
完整类型、测试、构建与容器检查在用户手动合并后的主线CI运行;报告须区分未运行与已通过。
|
||
|
||
1. 对实际构建输入计算 SHA-256:前端源码、Markdown、图片、Python 制图源码、依赖锁文件、Dockerfile 和构建脚本。
|
||
2. 命中 `verified-<scope>-<摘要>` 镜像时跳过依赖安装和 Next.js build,只做认证、实际路由与资源冒烟检查。
|
||
3. 输入变化时运行 lint、类型检查、制图一致性检查与构建。pnpm store、uv 和 `.next/cache` 使用持久 Docker 卷,main 与每个 PR 独立;额外保留 Next.js SWC 下载缓存。
|
||
4. 生产镜像只包含 Next.js standalone 产物;Python 留在检查容器,不进入运行镜像。镜像通过动态码认证、重放/限流、重启持久化、健康、全部文档、JS/CSS、SVG 和 404 检查后才标记为 verified。
|
||
5. 部署前检查是否仍为最新 main,使用 `--no-build` 启动,失败恢复上一版镜像。
|
||
|
||
根 README、工作流或部署配置等非构建输入变化不会触发 Next.js 重建;Markdown 正文变化会更新静态页面,仍需要一次增量构建。首次构建必须安装依赖并完整生成产物。缓存可能因基础镜像、工具链或锁文件变化而失效;不要清理共享 Docker 缓存或卷。
|
||
|
||
默认入口为服务器的 **18135** 端口。容器监听 3000,使用独立 Compose 项目 `endorphin-tabularium-docs`。部署前先检查端口是否空闲(或属于本服务),不会停止其他服务以抢占端口。服务器配置位于 `/etc/endorphin-tabularium-docs/production.env`:
|
||
|
||
```dotenv
|
||
TABULARIUM_BIND=0.0.0.0
|
||
TABULARIUM_PORT=18135
|
||
```
|
||
|
||
发布记录位于 `/opt/endorphin-tabularium-docs/releases/<commit>`,`current` 指向最近成功发布。修改服务器入口配置后手动重跑 main 工作流即可,复用现有镜像。
|
||
|
||
健康检查:`/api/health`。本项目不修改 Hestia、PROMPT 或其他服务,也不自动修改防火墙、域名和反向代理。
|
||
|
||
## Git 远程
|
||
|
||
仓库:[endorphin-tabularium-docs](https://gitea.entroia.com/Zayden-Jung/endorphin-tabularium-docs)。开发者 Git 操作使用 codex-bot 专用 SSH;Actions 检出使用 Gitea 内置任务令牌,不保存检出凭据。
|