Skip to content

The Deploy section documents a retired open-source edition — rewrite it for the commercial runtime #59

Closed

Description

@os-zhuang

ObjectOS is commercial-only; there is no open-source edition (as resources/license.mdx already states correctly). The Deploy section has not followed, and still teaches a licence-free, build-it-yourself path that cannot work.

Measured on content/docs/ at d13ba76.

What is wrong

Across all four Deploy pages — index, docker, kubernetes, air-gapped — the word "licence" appears zero times. For a product whose walled postures refuse to boot without one, the entire deployment section documents a path that does not exist.

deploy/docker.mdx specifically:

Line Says Reality
«Build your own image» git clone …/objectos.git then docker build -f docker/Dockerfile This repository contains only the docs site. There is no docker/, no Dockerfile, no runtime source. The instruction cannot succeed.
«We publish the runtime image … on every push to main» + latest / main / sha-<short> tag table an open-source CI publishing story Not how the commercial runtime is distributed
Node 20 Alpine the runtime image is Node 22
(whole page) no licence step at all a reader following it end to end gets no licence, and therefore either a silent Community degrade or a hard boot refusal depending on posture

deploy/air-gapped.mdx is worse than stale — it is reverse-wrong:

# Leave OS_CLOUD_URL unset to run fully offline

An unset OS_CLOUD_URL resolves to the default public control plane, not to "offline". On the composed shape this combination is now refused at startup. The page teaches a configuration that cannot boot. It also frames air-gap as a network property; for this product air-gap is a licence mode.

Decision taken

Previously published images are out of scope — do not document, reference, or preserve compatibility with them. The section is rewritten to the current rules, not reconciled with the old ones.

What the rewrite must carry

  1. The runtime image is pinned by digest, not by a moving tag.
  2. Licence is not optional and belongs in the happy path, including which licence mode each deployment shape requires.
  3. Air-gap is a licence mode, not a firewall configuration.
  4. OS_CLOUD_URL and licence mode are mutually constrained; incompatible combinations are refused at startup rather than degrading silently. The page must state the supported combinations, not a knob to flip.
  5. Multi-node changes what is mandatory (notably a shared secret — replicas generating their own diverge and the runtime refuses to start).
  6. Supply-chain verification (signature, SBOM, provenance) belongs in the production path.

Content boundary — the part that keeps this from rotting again

⛔ Do not inline the values a customer copies. The .env templates and compose files ship with the release and are covered by tests there; a prose copy on this site has nothing pinning it and will drift, which is exactly how the current pages got here.

The pages carry the decision shape — why digest pinning, which licence mode for which shape, what multi-node makes mandatory — and point at the release's deploy bundle for anything to be copied verbatim.

Locales

Seven locales (en, zh-Hans, ja, de, es, fr, ko); 4 English pages ⇒ 28 files. Fumadocs falls back to English when a translation is missing, so:

⇒ Delete the stale translations of any rewritten page rather than leaving them. A stale translation renders wrong content; a missing one renders correct English. ⛔ Do not leave a translated page asserting the retired story.

Note for whoever picks this up

AGENTS.md's Locale conventions section is itself out of date — it names en + cn with .cn.mdx siblings, while apps/docs/lib/i18n.ts defines the seven tags above and the content tree uses zh-Hans. A file named foo.cn.mdx would never render and would raise no error. Worth correcting in the same pass or as a follow-up.

Activity

  1. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor

    认领 — 派发

    • 座位:repo:cloud whole-repo PM(objectstack#6026)/ 会话 session_0137TnZzVmkSjXxoSVgPFS6S
    • 分支:claude/issue-59-deploy-docs-commercial-rewrite
    • 基线:当前 origin/main(d13ba76)

    ⛔ 认领前已现读:本卡无其它座位认领(新立)。

    事实来源(⛔ 以仓库为准,不要凭印象写)

    运行时的真实规则不在本仓库(产品源码私有)。写作前逐项去读发布物里的部署包与模板,并把读到的规则用自己的话写进页面,⛔ 不要整段拷贝模板内容 —— 内联即漂移,那正是本卡要消灭的东西。

    ⚠️ 若某条规则你读不到实物,⛔ 不要推断,在报告里列成 open question 交回本座位。一页写着看似合理但没人核过的部署指令,比一页空白更贵 —— 这就是现在这四页的由来。

    判据

    • ⛔ 不得保留任何已发布镜像的痕迹:标签表、:latest、sha-<short>、git clone + docker build 自建段,整段删除而非改写。维护者裁定:旧镜像不在故事里。
    • 许可证必须出现在主路径上,不是补充说明。四页当前 licen 命中数为 0,重写后本座位会重新数这个数。
    • air-gap 写成许可证模式,⛔ 不得写成"断网即可"。air-gapped.mdx 里那句 Leave OS_CLOUD_URL unset to run fully offline 必须消失 —— 它现在会把人教到一个起不来的部署上,这是本卡里最急的一条。
    • 不兼容组合的表述是"启动会被拒绝",⛔ 不是"建议不要这样配"。产品在配置加载期就拒,文档要与之一致。
    • 翻译:被重写页面的 7 个语种旧译文删除(Fumadocs 缺译回落英文)。⛔ 不得留下仍在讲旧故事的译文。
    • 英文先行(仓库规约):⛔ 不得只改译文。
    • 顺带更正 AGENTS.md 的 Locale conventions 段(它说 en+cn/.cn.mdx,实际是 7 个 tag、中文为 zh-Hans)—— ⚠️ 按它写出的 .cn.mdx 永远不会渲染且不报错。
    • ⚠️ 本仓库规约要求 UI 改动要在浏览器里跑一遍。若你能起 apps/docs 开发服务器,至少确认四页可渲染、侧边栏与 meta.json 一致;跑不动就明说跑不动,⛔ 不要猜。
    • ⛔ 不 git stash;自查 diff 用 git diff $(git merge-base main <branch>)…<branch>;推送后开 draft PR 引用本卡。
    • ⚠️ 遇 API 529 / 限流 ⇒ 停下报告已完成部分,⛔ 不要重试循环。

    报告按结构化 JSON 交回本座位。


    Generated by Claude Code

  2. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor
    {
      "issue": 59,
      "status": "done",
      "branch": "claude/issue-59-deploy-docs-commercial-rewrite",
      "pr": "https://github.com/objectstack-ai/objectos/pull/62",
      "premise_still_valid": true,
      "summary": "All four English Deploy pages rewritten from the deployment artifacts shipped in the cloud repo's release bundle (read at origin/main, not from the local checkout, which was on an older branch). The git-clone-plus-docker-build section, the latest/main/sha tag table and the every-push-to-main publishing story are deleted wholesale, not rewritten; no previously published image is referenced anywhere. The reverse-wrong 'Leave OS_CLOUD_URL unset to run fully offline' line is gone and replaced by its own heading stating that unset resolves to the public control plane, with air-gap framed as a licence mode and the supported licence/cloud-posture combinations given as a table whose unsupported rows read 'refused at startup'. Licence mentions per page went 0 to 40/57/35/86. Pages carry decision shape only and point at the release's deploy bundle for copyable values; no environment template is inlined. All 24 stale locale siblings deleted (6 locales x 4 pages); AGENTS.md's Locale conventions corrected from en+cn/.cn.mdx to the seven BCP 47 tags with zh-Hans, including that a .cn.mdx file never renders and raises no error.",
      "tests": "All at commit c5ba923, the head of the branch. (1) apps/docs `pnpm run type-check` — clean, exit 0. (2) apps/docs `pnpm run build` — 'Compiled successfully in 44s', 'Generating static pages using 3 workers (740/740)', no MDX errors. (3) Browser: YES, a real browser was driven — headless Chromium via Playwright 1.56.1 (browsers pre-installed at /opt/pw-browsers) against `next start` on the production build. Measured: /docs/deploy, /docs/deploy/docker, /docs/deploy/kubernetes, /docs/deploy/air-gapped all 200 with expected H1/H2 (e.g. air-gapped H1 'Air-gapped Deployment', first H2 'Air-gap is a licence mode'); the Deploy sidebar nav order is exactly index, docker, kubernetes, air-gapped matching meta.json, on every page; /zh-Hans/docs/deploy/air-gapped and /ja, /de equivalents return 200 and now serve the new English content (fallback confirmed, no stale translation); /docs/deploy/nope returns 404 (control, so the 200s mean something); every outbound link target answers 200 (/docs/resources/license, /docs/operate/upgrade, /docs/operate/backup, /docs/operate/production, /docs/operate/observability). (4) Leak scan over the changed files for tracker IDs, ADR numbers, registry hostnames, internal repo paths and internal app hostnames — no hits. (5) Control-character scan over changed files — no hits. NOTE: one console error (React #418 hydration) fires on every page including untouched ones; verified pre-existing by measuring /docs/architecture and /docs/quickstart on the same build, filed as #61 rather than absorbed. This repo has no .changeset directory and no changeset gate, so no changeset and no skip-changeset label applies.",
      "open_questions": [
        {
          "question": "Is Kubernetes a supported deployment shape at all? No chart, manifests, or K8s-specific artifact exists in the release bundle — only the Compose stack. The page now says so plainly and reframes as 'the properties any orchestrator must preserve', each derived from the Compose stack and the runtime's own refusals. If K8s is meant to be supported, the deliverable is missing; if it is not, the page arguably should say 'unsupported, at your own risk'.",
          "options": [
            "A — keep the page as 'properties to preserve', which is honest and useful and claims no support",
            "B — ship a chart or reference manifests in the release bundle and document those",
            "C — mark Kubernetes explicitly unsupported and remove the page"
          ],
          "recommendation": "A for now. It is the only option that is true today and it costs nothing if B lands later. C would delete a page customers land on from search with no replacement."
        },
        {
          "question": "Air-gapped installation of additional packages. The old page documented `os package install ./dist/objectstack.json --runtime ... --email ... --password ...` with a manifest cached under .objectstack/installed-packages/. I could not confirm any of it from the shipped deployment artifacts, and the composed shape declines install-local outright. I removed the section rather than carry an unverified instruction.",
          "options": [
            "A — leave it out until someone can point at the artifact that pins the behaviour",
            "B — restore it from whatever source originally justified it"
          ],
          "recommendation": "A. That command reads as authoritative and would be followed; the whole card exists because plausible-but-unverified deployment prose was published once already."
        },
        {
          "question": "How does an air-gapped customer get the runtime image across the boundary, as a supported procedure? The bundle documents `docker login` plus pull, which a disconnected site cannot do. The page states the property it can defend (verify signature/SBOM/provenance on the connected side, then use the digest to prove the copy inside is the same bytes) but names no transfer mechanism, because none is documented.",
          "options": [
            "A — leave the mechanism unstated, as now",
            "B — document a supported transfer (image archive, or a customer-side mirror registry) once one is decided in the bundle"
          ],
          "recommendation": "B eventually, in the bundle first, then here. A is correct until then."
        },
        {
          "question": "Air-gapped AI. The bundle shows an AI gateway key powering the `ask` agent, but nothing states whether a self-hosted or on-network model endpoint is supported. The page therefore only says an AI provider must be reachable if you configure one, and does not claim in-product AI works air-gapped.",
          "options": [
            "A — keep it vague, as now",
            "B — state the supported air-gapped AI story once it is pinned somewhere readable"
          ],
          "recommendation": "A. Enterprise buys air-gap partly for the AI, so this is the most likely question a customer asks next — worth pinning in the bundle."
        },
        {
          "question": "Licence renewal in an air-gapped site. The runtime resolves signature and expiry locally at each boot, so an air-gap licence expires; the renewal procedure is not documented in any artifact I read. The page says renewal is a delivery rather than something the runtime fetches, and stops there.",
          "options": [
            "A — leave as is",
            "B — document the renewal path once defined"
          ],
          "recommendation": "B, and worth prioritising: an expiring licence with no documented renewal is a support call with a deadline attached."
        }
      ],
      "out_of_scope_findings": [
        "filed as #60: seven pages outside Deploy still document the retired runtime env contract (OS_ARTIFACT_FILE, OS_BUSINESS_DB_URL, OS_CLOUD_API_KEY, OS_DATABASE_DRIVER); reference/environment-variables.mdx is worst, and also describes OS_CLOUD_URL as merely a marketplace switch, which now contradicts deploy/air-gapped.mdx",
        "filed as #61: every docs page throws React hydration error #418 in the browser console, measured pre-existing on untouched pages (labelled `finding`, observation-class)"
      ]
    }

    Generated by Claude Code

  3. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor

    Closed — PR #62 merged. The Deploy section now documents the commercial runtime.

    Verified against the branch before merge, not against the PR description:

    before after
    licence mentioned across the four Deploy pages 0 present on all four
    retired-image traces — moving tags, tag table, git clone + docker build present removed wholesale
    «Leave OS_CLOUD_URL unset to run fully offline» present removed
    stale locale siblings of rewritten pages 24 live deleted

    Air-gap is now framed as a licence mode, and unsupported licence/cloud-posture pairings are stated as refused at startup rather than discouraged — matching what the runtime actually does.

    What keeps this from rotting again

    Pages carry the decision shape; anything a customer copies verbatim points at the deploy bundle shipped with the release. Those templates are covered by tests where they live; a prose copy here would have nothing pinning it — which is precisely how the previous pages came to document a product that no longer exists.

    The one OS_…= line that remains is a shape, not a value:

    OS_EE_IMAGE=<the registry reference from your release>@sha256:<64 hex characters>
    

    The deletions were verified, not assumed

    Deleting a translation is only safe if the site falls back to English. That was measured — /zh-Hans/, /ja/ and /de/ variants return 200 and serve the new English content, with /docs/deploy/nope → 404 as a control so that "200" means something. Sidebar order matches meta.json, every outbound link resolves, and the production build emits 740/740 static pages with no MDX errors.

    Five questions were left open rather than answered

    Each is a rule that could not be confirmed from a shipped artifact, so it was not written. They are recorded on PR #62 for the maintainer. The most consequential: an air-gap licence expires — signature and expiry resolve locally at every boot — and no artifact documents a renewal path.

    The old air-gap package-install instruction was deleted rather than carried, since nothing supported it. Removing an unverifiable instruction is the right trade here: this card exists because plausible-but-unverified deployment prose was published once already, and readers followed it.

    Follow-up now live

    #60 — seven pages outside Deploy still document the retired env contract, and reference/environment-variables.mdx still calls OS_CLOUD_URL a marketplace switch. ⚠️ That contradiction went live the moment this merged: the reference page a reader treats as the contract now disagrees with the deployment page. Dispatched immediately.

    #61 — a pre-existing hydration error, measured on untouched pages before being filed rather than absorbed into this change.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions