## Related issue
Follow-up to #4673.
## Summary
- Add a typed, default-off release-feature registry driven by one comma-separated `OMNIGENT_FEATURES` environment variable, with strict validation and lifecycle metadata.
- Gate the web Usage route/navigation and page-only report enrichment while preserving the existing `GET /v1/usage` CLI API.
- Migrate web-driven harness installation to the same immutable startup snapshot and wire rollout configuration across Docker, Kubernetes, Render, Railway, and Databricks.
ELI5: the server reads one list of enabled features when it starts, enforces that same list on backend routes, and tells the web app which controls and pages to show.
```text
OMNIGENT_FEATURES
|
v
FeatureFlags snapshot
/ \
backend gates GET /v1/info
|
v
frontend gates
```
## Test Plan
- `uv run pytest tests/server/test_feature_flags.py tests/host/test_local_server.py tests/server/integration/test_utility_endpoints.py tests/server/integration/test_hosts_install_harness.py tests/server/integration/test_hosts_store_credential.py tests/server/routes/test_usage_report.py tests/server/test_openapi_drift.py -q`
- `cd web && pnpm vitest run src/lib/capabilities.test.ts src/lib/harnessSetup.test.ts src/App.test.tsx src/shell/Sidebar.test.tsx`
- `uv run pytest tests/e2e_ui/sessions/test_usage_page_feature.py -q`
- `uv run python scripts/dump_openapi.py --check`
- `pre-commit run --files <changed files>`
- Verified default-off and enabled Usage route/sidebar behavior, strict unknown-feature rejection, legacy CLI usage compatibility, and harness route enforcement.
## Demo
- Default off: the updated visual baselines show the original sidebar without the Usage row.
- Enabled Usage page: https://github.com/user-attachments/assets/8385d4f0-47ad-430f-bf2c-06c35af6c499
## Type of change
- [ ] Bug fix
- [x] Feature
- [x] UI / frontend change
- [ ] Refactor / chore
- [x] Docs
- [ ] Test / CI
- [ ] Breaking change
## Test coverage
- [x] Unit tests added / updated
- [x] Integration tests added / updated
- [x] E2E tests added / updated
- [x] Manual verification completed
- [x] Existing tests cover this change
- [ ] Not applicable
## Coverage notes
Manually reviewed the default-off visual output and verified that the Usage route is absent while the capability is disabled. Targeted backend and frontend tests cover both flag states, capability parsing, startup snapshots, and harness enforcement.
## Changelog
Usage and web-driven harness setup can now be enabled per deployment with `OMNIGENT_FEATURES`.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* docs(deploy): correct docker admin bootstrap flow (no auto-generated password)
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
* docs(deploy): correct remaining generated-password and /data-persistence claims
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
* docs(deploy): scrub generated-password flow from remaining platform guides
The Docker docs were corrected earlier, but fly / railway / render / modal /
hf-spaces still told operators to read a generated admin password out of the
logs / /data/admin-credentials — a flow that no longer exists (bootstrap never
auto-generates a password; the first admin is claimed via the web Create-admin
form or a pre-seeded OMNIGENT_ACCOUNTS_INIT_ADMIN_PASSWORD).
- Rewrite the first-admin step in each guide to the real flow, and drop the
fake "Created initial admin ... password: <generated>" log block.
- Add a first-visitor security note (unauthenticated /auth/setup while no
password-bearing account exists) to every public-facing guide; fold it into
hf-spaces' "make the Space Public" step where the exposure is most direct.
- render: correct the disk bullet (hashes live in Postgres, not on /data) and
the render.yaml comment that called the anchor path a password file.
Co-authored-by: Isaac <isaac@example.com>
Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
---------
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
Co-authored-by: Pat Sukprasert <pattara.sk127@gmail.com>
Co-authored-by: Isaac <isaac@example.com>
* feat: add Kiro native CLI harness
Signed-off-by: Michael Gardner <gardnmi@gmail.com>
* fix(kiro): avoid ambient env in tmux attach
Signed-off-by: Michael Gardner <gardnmi@users.noreply.github.com>
* fix: restore uv.lock pypi.org sources (drop accidental databricks-proxy re-lock)
A local `uv run` during the merge re-locked uv.lock against this machine's
Databricks-internal pypi proxy, flipping every package source URL. Kiro changes
no dependencies and pyproject.toml is unchanged vs main, so restore main's
uv.lock verbatim (pypi.org sources). Only registry URLs differed — no version
or hash changes.
Co-authored-by: Isaac
* test(e2e-ui): add native-kiro render-parity suite (E2E UI Required gate)
The E2E UI Required gate flagged that #899 changes the agent-picker/session UI
(adds Kiro) without a tests/e2e_ui/** test. Add test_native_kiro_render_parity.py
mirroring the cursor/goose siblings — composer-IN parity, a TUI-originated turn
surfacing OUT, and no duplicate rendering — plus the native_kiro_session fixture.
Skip-gated on kiro-cli + tmux, so it skips in CI (no Kiro account provisioned)
exactly like the goose/cursor suites, and runs for real where Kiro is signed in.
Verified: collects + skips cleanly (kiro-cli absent); ruff clean.
Co-authored-by: Isaac
* fix: restore ap-web/package-lock.json npmjs.org sources (drop databricks npm-proxy)
Same root cause as the uv.lock fix: an npm command during round-1 merge re-resolved
one dependency (yaml-1.10.3) against this machine's Databricks-internal npm proxy
(npm-proxy.cloud.databricks.com), which CI (pinned to registry.npmjs.org) can't reach
-> 'npm ci' ETIMEDOUT. ap-web/package.json is unchanged vs main and Kiro adds no npm
dependency, so restore main's package-lock.json verbatim (clean npmjs.org sources).
Co-authored-by: Isaac
* test(e2e): exclude kiro-native from the live-harness matrix coverage check
test_run_harness_live_matrix_covers_registered_coding_harnesses asserts every
registered coding harness is either in the live no-AGENT e2e matrix or explicitly
excluded. kiro-native is a terminal-first TUI launched via `omni kiro` (tmux pane
+ bridge dir), not `omnigent run --harness kiro-native`, so — like goose-native /
qwen-native / cursor-native — it can't run in this matrix. Add it to the exclusion
set with the matching rationale; its coverage is the kiro-native bridge/executor/
forwarder unit tests + the test_native_kiro_render_parity e2e_ui suite.
Co-authored-by: Isaac
* test(ap-web): set isNativeWrapper in /compact composer menu tests
#1139 gated "/compact" behind isNativeWrapper (hidden for non-native
harnesses), but the three slash-menu-UX tests that assert "/compact"
tops/appears in the suggestions still rendered a non-native composer,
so they now fail on main (and on every PR that merges main).
Render those three with isNativeWrapper:true so "/compact" is offered,
restoring the built-in ordering the tests pin. Test-only; no behavior
change. Fixes the inherited ChatPage.composer.test.tsx red on this PR.
Co-authored-by: Isaac
* test(kiro): cover kiro_native launcher helpers (raise coverage 43%→70%)
The kiro-native launcher (omnigent/kiro_native.py) was the largest
coverage gap on this PR: its CLI/daemon orchestration is only exercised
by the live render-parity e2e, which skips in CI when kiro-cli is
absent. Add focused unit tests (with a fake httpx client) for the
unit-testable surface: executable resolution, launch-argv assembly,
terminal-payload decoding, tmux attach gating, startup-progress
forwarding, preflight, resume-id resolution, and the create/fetch/
ensure/find/wait session helpers (success + error branches).
Lifts kiro_native.py from 43% to 70%; remaining misses are the
daemon-driven async orchestration covered by runner/e2e paths.
Co-authored-by: Isaac
* test(kiro): rename test env var to avoid exfil-scan false positive
The CI exfil scanner flags any added file containing a secret-named
source (regex `[A-Z0-9]+_SECRET\b`) together with a network sink. The
tmux-allowlist test used `OMNIGENT_SECRET` purely as a non-allowlisted
sample var, which matched the secret regex and — combined with the
fake httpx client's .post()/.get() in the same file — tripped the
"secret-named source + network sink" block. Rename it to a neutral
`OMNIGENT_UNLISTED_VAR`; the test's intent (filtering non-allowlisted
keys) is unchanged.
Co-authored-by: Isaac
---------
Signed-off-by: Michael Gardner <gardnmi@gmail.com>
Signed-off-by: Michael Gardner <gardnmi@users.noreply.github.com>
Co-authored-by: Pat Sukprasert <pattara.sk127@gmail.com>
Header-auth mode now honors OMNIGENT_AUTH_HEADER_STRIP_PREFIX, removing a
configured prefix from the trusted identity header value. Google IAP
forwards X-Goog-Authenticated-User-Email namespaced as
accounts.google.com:<email>; stripping the prefix recovers the bare email
used for ownership/sharing. Generic (not IAP-specific) so any proxy that
namespaces its identity header is supported.
Reserved-name rejection runs after stripping, and a value that is only the
prefix (empty after strip) fails closed. Default unset = strip nothing, so
existing header-mode deploys are unaffected.
* feat(server): configurable header-auth identity header (OMNIGENT_AUTH_HEADER)
Header-auth mode hardcoded reading X-Forwarded-Email, so deploys behind a
proxy that authenticates with a different header name (e.g. Cloudflare
Access' Cf-Access-Authenticated-User-Email) could not authenticate without
an extra proxy hop to rename the header.
Add OMNIGENT_AUTH_HEADER to override the trusted identity header name,
defaulting to X-Forwarded-Email so existing deploys are unaffected. The
override replaces the header read rather than adding a fallback, so the old
name is no longer accepted once set — keeping exactly one trusted input.
Closes#877
* docs(server): generalize stale X-Forwarded-Email docstrings to the configured identity header
Found and fixed 8 broken relative markdown links pointing at files
or directories that don't exist:
- deploy/README.md → trycloudflare/README.md (dir absent — only
daytona/docker/fly/hf-spaces/modal/railway/render exist under deploy/)
- docs/AGENT_YAML_SPEC.md → SANDBOXING.md (×2, file doesn't exist;
repointed prose at `sandbox:` examples + omnigent/inner/ source)
- ap-web/README.md → ../designs/ui/WEB_UI.md (×2, no designs/ dir;
reworded prose and removed See-also entry)
- tests/resources/examples/databricks_supervisor/README.md →
../../designs/DATABRICKS_SUPERVISOR_API_INTEGRATION.md (repointed
at the supervisor source dir)
- deploy/docker/README.md → ../aws/README.md (deploy/aws/ doesn't
exist; removed the EC2 with Terraform bullet)
- deploy/docker/SKILL.md → ../databricks/SKILL.md and ../aws/SKILL.md
(neither dir exists; removed both Related-skills entries)
Verified with a recursive relative-link check after the edits:
0 broken markdown links remain.
No code changes, no API changes — docs only.
Signed-off-by: mjwsolo <19599997+mjwsolo@users.noreply.github.com>