If you’re new here: OneCamp is an open-source, self-hosted workspace — chat, docs, tasks, projects, calls, boards, tables, an API, and optional AI teammates. It runs on your infrastructure, with your choice of model.
This week was release infrastructure, not features. The kind of week that is invisible when it works and very visible when it doesn’t.
OneCamp has always had an AI branch and a non-AI branch, but the tags were drifting. v1.0.0 and v2.0.0 now point to the heads of the two edition branches:
main).without-ai).The AI-free tree is not the same code with features hidden. It is a separate build that has the AI packages, routes, marketplace entry, and AI-only environment keys removed. That means a v1 install never downloads an Ollama image, never exposes an AI endpoint, and never asks an operator to configure keys for a feature that is not there.
Keeping two editions buildable from the same repo means every CI gate has to pass on both. The without-ai workflow was failing on guard tests that assume the full tree — tests that walk every exported function, every environment template, every OpenSearch seam, and every authorization consumer. Those tests are correct for the full edition. In the AI-free edition the right answer is not “make the code look like the full edition”; it is “make the guards understand that this edition intentionally does less.” So the guards now skip or baseline the parts that do not exist in without-ai.
The published install guide told customers to run:
make update-admin-email
make update-server-ip
make replace-domain
make create-traefik-password
make update-traefik-email
make update-allowed-domains
make create-swap
None of those targets existed in the customer Makefile. A paying customer following the official instructions hit No rule to make target on the third line. They had already been charged.
The Makefile they received also pointed at compose.yml, but the zip shipped sample-compose.yml. So even a customer who got past configuration would fail at make build_restart_all with can't find a suitable configuration file.
make doctor reported “No placeholders left in .env” while INTERNAL_SECRET, LIVEKIT_API_PASS, TURN_SECRET, RESEND_API_KEY, and ADMIN_PASSWORD still contained __SET_FROM_SECRET_STORE__. The regex only caught __CHANGE_ME_*__ placeholders.
The fix was not to rewrite the guide. The guide was the spec. The Makefile had to match it:
COMPOSE points at sample-compose.yml.make doctor flags any remaining __...__ placeholder, including secret-store placeholders.make ollama_update exists, because the admin AI panel tells admins to run it.include .env became -include .env so make help works before the operator has copied .sample.env to .env.The public frontend repo has two branches with unrelated histories: ai (v2) and main (v1). main had fallen behind because every sync meant cherry-picking non-AI commits out of an AI-first tree. After a while the only honest thing to do was regenerate it: take the current ai tree, delete the AI-only pages, components, hooks, and utilities, and fix what broke.
That removed ~60 files and ~20k lines. Build and tests pass. The non-AI edition now has the same recent boards, tables, templates, SCIM, two-factor, and call-gating work as the AI edition, without the AI surfaces.
The same failure mode showed up three times this week:
main branch described a non-AI edition that had not been fully synced.In each case the fix was to make the artifact match the stated contract, rather than quietly update the contract. A release is not done when the code works in development; it is done when the thing a customer actually receives behaves the way the documentation says it does.