Releases: theta42/theta-suite
Release list
v1.34.5
v1.34.4
v1.34.3
v1.34.2
v1.34.1
v1.33.0
v1.31.1: sso v1.17.2 + /vault policy fix (setup.sh)
[v1.31.1] - 2026-08-01
Pairs the sso v1.17.2 post-deploy fixes with the theta-suite half of the
/vault secrets-list 403 fix (the sso-admin OpenBao policy grant that lives
in setup.sh), and rolls the sso-manager-node submodule gitlink to v1.17.2.
proxy (v1.13.1), jump-host (v1.14.1), and ldap-client (v1.23.0) are
unchanged.
Changed (theta-suite)
setup.sh—sso-adminpolicy: added alistgrant on the bare KV mount
rootsecret/metadataso an admin can list the top-level dirs in the/vault
UI.secret/metadata/*already covered nested paths, but not the mount root
itself — so the secrets list 403'd. (The matching per-user/per-app directory
grants ship in sso v1.17.2'svault_broker.js.)setup.sh—ensure_policy: now always (re)writes the policy instead of
skipping when it exists.bao policy writeis an idempotent overwrite, so a
re-run applies policy edits (like the new grant above) instead of stranding
the old HCL with "already exists — keeping."
Changed (submodule gitlinks)
- sso-manager-node:
v1.17.1→v1.17.2— the post-deploy fixes (auto-slug
plugins, schedule dropdown,/profilerendering, plugin-edit persistence,
nmap in the image, the sso-side/vaultpolicy grants) plus the SMS (VoIP.ms)
and Terms-of-Service configuration on/conf. Full changelog below.
Deploy
Operators upgrading from v1.31.0:
git pullandgit submodule update --init --recursive.- Re-run
./setup.sh— required: applies the newsso-admin
secret/metadatalist grant and theensure_policyalways-write refresh
(idempotent). Per-user vault policies self-heal on the next/vaultvisit
(sso v1.17.2 re-writes them). docker compose build && docker compose up -d— the rebuild installsnmap
in the sso image (fixes the nmap plugin "not found" error).
Bundled submodule release notes
sso-manager-node v1.17.2 — post-deploy fixes + SMS/TOS on /conf
Post-deploy fixes from testing the v1.31.0 stack, plus the SMS (VoIP.ms) and
Terms-of-Service configuration the /conf page was missing.
Fixed
- Plugin slug is now auto-generated from the instance name — the New Plugin
modal no longer asks for a Slug (it derives a stable, unique handle from the
name, appending-2,-3, … on collision). The generated slug still shows in
the table and the Edit (read-only) modal.POST /api/pluginsslugis now
optional; an explicit slug is still accepted and validated. - Plugin schedule is a dropdown, not a raw cron box: Hourly / Daily /
Weekly, plus Custom which reveals the raw 5-field cron input. Stored value
is still a cron string, so the server is unchanged. /vaultsecrets list no longer 403s. The per-user, per-app, and admin
OpenBao policies grantedlistonly onsecret/metadata/.../*(nested
paths), never on the directory path itself — so listing a directory's
contents (which checksliston the directory, e.g.
secret/metadata/users/<uid>or the mount rootsecret/metadata) was denied.
vault_broker.js'suserPolicyHcl/appPolicyHclnow also grantliston the
bare directory path, andensurePolicynow always re-writes the policy
(idempotent) so already-createduser-<uid>policies pick up the new grant on
the next vault-page visit. The matchingsso-adminmount-root grant ships in
theta-suite v1.31.1 (setup.sh), whereensure_policyis likewise made
always-write so re-running./setup.shapplies policy edits./profileno longer shows literal{{…}}tags. Three template fragments
sat outside thejq-repeat="user"scope, so they rendered raw: the card
headerProfile: {{user.uid}}, theMembers of {{user.uid}}'s Grouptab
label, and the Admin Actions block's{{#isActive}}/{{#isInactive}}
buttons. The header/label are now populated by JS (theMemberslabel
already had a setter pointing at a missing id); the Admin Actions block is
moved inside the scope so{{uid}}/{{#isActive}}/{{#isInactive}}render
and the correct Activate/Deactivate button shows.- Editing a plugin now persists. The Edit modal had been prefilled with the
masked secret values and rendered them as fields, butPUT /:idonly saves
non-secret config — so an edited secret was silently dropped. The Edit modal
now shows non-secret fields only (secrets have their own Edit-Secrets
modal), removing the confusion. - nmap plugin: "NMAP not found at command location: nmap" — the
nmap
binary was not installed in the app image.Dockerfile.openldapnowapk addsnmapin the runtime stage, andplugins/discovery/nmap.jstranslates
the opaque node-nmap spawn-missing error into an actionablelastError.
Added
- SMS (VoIP.ms) configuration on
/conf. The existing VoIP.ms SMS sender
(models/sms.js, used for 2FA OTP delivery) was configurable only via env /
config files. It now has an SMS card on/conf(API username, DID, API
password), saved to OpenBao atsecret/sso-manager/confundervoipms, with
the API password masked (********) and leave-blank-to-keep — mirroring the
SMTP card exactly.models/sms.jsreadsconf.voipms.*at call time, so a
saved change takes effect live without a restart. - Terms of Service editor moved to
/conffrom the admin Overview
dashboard, where it never belonged. The sameapp.tos.get/updateflow,
the "require all users to re-accept" checkbox, and theapp_sso_admingate
(matchingroutes/tos.js's PUT gate) are preserved. The Overview page keeps
stats, notifications, and metrics.
[v1.31.0] - 2026-08-01
v1.31.0 — roll up submodules (sso v1.17.1 + ldap-client v1.23.0)
[v1.31.0] - 2026-08-01
Roll-up release: bumps the composed submodules to their latest tags so a fresh
git clone + ./setup.sh deploys the SSO Manager plugin system, the /conf
SMTP/OAuth secret masking, and the ldap-client changelog. proxy (v1.13.1) and
jump-host (v1.14.1) were already at latest and are unchanged.
Changed (submodule gitlinks)
- sso-manager-node:
v1.16.1→v1.17.1(the plugin system shipped in
v1.17.0, plus the v1.17.1/confsecret-masking hardening). - ldap-client:
v1.1.1→v1.23.0— a CHANGELOG-only release (the new
CHANGELOG.mddocumenting v1.1.0/v1.0.0; no code change — the "UI polish"
tag message is misleading, the v1.1.1…v1.23.0 diff isCHANGELOG.mdonly).
Deploy
Operators upgrading from a prior release:
git pullandgit submodule update --init --recursive(or a fresh clone).- Re-run
./setup.sh— this is required if you haven't yet applied the
v1.30.1sso-brokerOpenBao policy grant forsecret/plugins/*(idempotent;
it grants the existingSSO_VAULT_TOKENaccess live, so plugin-secrets
storage works). docker compose build && docker compose up -d. Existing
conf.discovery.pluginssetups auto-migrate intoPluginInstancerows +
OpenBao secrets on first boot of sso v1.17.x.
Bundled submodule release notes
sso-manager-node v1.17.0 — real plugin system (loadable instances + OpenBao secrets)
[1.17.0] - 2026-08-01
A real plugin system: the half-built discovery plugins (statically
configured in sso-secrets.js, only toggleable for cron/enabled) become
configurable, loadable/unloadable plugin instances you manage from a
dedicated Plugins page and the /api/plugins API, with multiple runtime
copies of each type and per-instance secrets stored in OpenBao.
Added
- Plugin instances — a new
PluginInstanceORM model
(nodejs/models/plugin_instance.js, Sequelize) is the registry of
configured, scheduled plugin copies. Each has apluginType, a unique
slug(the discovery source name), a cron schedule, anenabledflag
(load/unload), non-secretconfig(JSON), and last-run bookkeeping. Multiple
instances of the same type are supported. - Plugin registry (
nodejs/services/plugin_registry.js) — generalizes the
one-shot discovery-plugin scan inscheduler.js. Plugin types are modules
undernodejs/plugins/<category>/<type>.jsexporting a manifest
(type,category,name,description,configSchema,validate,
run/discover). ExposesgetTypes,getModule,splitConfig(secret vs
non-secret),mask, and required-field helpers for the UI/API. - Per-instance secrets in OpenBao (
nodejs/utils/plugin_secrets.js) —
configSchemafields flaggedsecret:true(e.g. a ProxmoxtokenSecret,
UniFipassword) are stored atsecret/plugins/<instance-id>/conf, never in
the DB. The UI only ever sees masked (********) values. Plugins run
in-process (BullMQ workers), so they need no OpenBao token of their own — the
SSO reads/writes via thesso-brokertoken. Requires theta-suite ≥ v1.30.1
for thesso-brokerpolicy grant onsecret/plugins/*; the API fails-soft
with a clear error if absent. /api/pluginsAPI (nodejs/routes/api_plugins.js, replaces the old
routes/plugins.js) —GET /types, list/get/create/update/update-secrets/
test/load/unload/run/delete/runs. Admin-only
(app_sso_admin/app_sso_directory_admin/app_super_admin).- Plugins page (
/plugins,views/plugins.ejs) + nav entry — instance
table with New/Edit/Edit-Secrets/Test/Run-now/Load/Unload/Delete, config forms
rendered from each type'sconfigSchema. validate("Test" button) on the built-in Proxmox/UniFi/Nmap plugins.
Changed
services/scheduler.jsnow schedules from thePluginInstancetable instead
of staticconf.discovery.plugins+ a Redis override hash. Each instance owns
a stable BullMQ JobScheduler id (plugin:<instanceId>) so load/unload
upsert/remove one schedule without disturbing the rest. Discovery plugins
reconcile results under the instance'sslug.- The three discovery plugins (
plugins/discovery/{proxmox,unifi,nmap}.js)
gained manifests (configSchema,validate,runalias).nmap's
targetRangeis non-secret; ProxmoxtokenSecretand UniFipasswordare
secret. - The
/pluginspage route renders the page instead of redirecting to
/directory; the Agents & Scheduler tab was removed from/directory
(plugins are now managed on the Plugins page). The/docs/agentslink is
aliased to/docs/plugins. docs/plugins.md,docs/vault.md,docs/_config.yml(nav), andAPI.md
(Plugin Endpoints section) document the new system.
Legacy migration
On first boot of v1.17.0, if the PluginInstance table is empty and
conf.discovery.plugins has entries, one instance per configured type is seeded
automatically (secret fields copied into OpenBao). After that the static
config is ignored — manage plugins from the UI/API. Idempotent (guarded by the
empty-table check).
Prerequisite
theta-suite ≥ v1.30.1 — re-run ./setup.sh after upgrading so the
sso-broker OpenBao policy is granted secret/plugins/*. Without it, storing
plugin secrets fails with a clear error.
sso-manager-node v1.17.1 — mask SMTP/OAuth secrets + leave-blank-to-keep on /conf
[1.17.1] - 2026-08-01
Hardens the runtime SMTP/OAuth secret handling on the /conf admin page to
match the plugin-secrets discipline: the SMTP password and OAuth JWT secret are
no longer returned in cleartext by GET /api/conf or round-tripped through the
form. They remain saved in OpenBao at secret/sso-manager/conf at runtime
(unchanged) — only how they're surfaced to the admin changes.
Changed
GET /api/confnow maskssmtp.passandoauth.jwtSecretto********
(was: returned in cleartext). Non-secret fields (host, port, user, from,
secure, issuer, token lifetimes) are returned as before.POST /api/confnow treats a blank or********secret-field submission
as "keep the current stored value" — so an admin editing the From address or
token lifetimes no longer has to re-enter (or leak) the SMTP password / JWT
secret. Only a genuinely new, non-blank value overwrites. The preserved values
are re-applied to liveconfimmediately, as before./confpage (views/conf.ejs): the Password and JWT Secret fields carry
a "leave unchanged to keep the current value stored in OpenBao" hint; the page
copy notes secret fields are masked. No JSON-textarea editing is involved —
SMTP is and remains configured through structured form fields.
Notes
- SMTP (and OAuth) config was already saved to OpenBao at runtime before
this release (viaPOST /api/conf→baoConf.set('sso-manager/conf'), and
overlaid back at boot bybao-conf.init). This release closes the
cleartext-exposure gap; it does not move the storage path. - No theta-suite policy change required —
secret/sso-manager/confwas already
granted to thesso-brokerpolicy.
ldap-client v1.23.0 — CHANGELOG-only (no code change)
Adds a CHANGELOG.md documenting v1.1.0 (app_super_admin / app_jump_admin
group support in SSSD access filters; the sso/jump-host TLS-validation
divergence) and v1.0.0 (initial SSSD LDAP auth release). No source changes vs
v1.1.1; the v1.23.0 tag commit only adds this file.
v1.30.1 — sso-broker OpenBao access to secret/plugins/*
[v1.30.1] - 2026-08-01
Prerequisite release for the SSO Manager plugin system (shipped in
sso-manager-node v1.17.0). Grants the sso-broker OpenBao policy access to the
new per-instance plugin secrets namespace so the SSO can store plugin secrets in
OpenBao instead of sso-secrets.js.
Changed (theta-suite orchestration)
setup.sh: addedsecret/data/plugins/*(CRUD+list) and
secret/metadata/plugins/*(list/read/delete) to thesso-brokerpolicy
HCL.ensure_policy sso-brokeris idempotent, so re-running./setup.sh
immediately grants the existingSSO_VAULT_TOKENaccess tosecret/plugins/*
(policies are evaluated live; the token keeps its id). The SSO side fails-soft
with a clear error if this grant is absent.- Docs:
docs/secrets.md(new "Plugin secrets" section +sso-broker
policy row) anddocs/architecture.md(sso-manager access row) now list
secret/plugins/*.
The plugin system itself (configurable plugin instances, load/unload, UI/API,
multi-copy, secrets in OpenBao) is in sso-manager-node v1.17.0; theta-suite
will bump its submodule gitlink to that release next.
v1.30.0 — renamed to theta-suite
[v1.30.0] - 2026-08-01
The project is renamed theta-env → theta-suite — it has grown from a
docker-compose wiring two projects into an integrated suite of four
applications around a shared OpenBao secrets store, and the name should reflect
that. The GitHub repository is renamed theta42/theta-env →
theta42/theta-suite (old URLs redirect), and the docs site moves to
https://theta42.github.io/theta-suite/.
Changed (theta-suite orchestration)
- Renamed theta-env → theta-suite across the superproject:
docs/_config.yml
(title+baseurl: /theta-suite+ repo URLs),README.md,setup.sh
(incl. theTHETA_SUITE_REEXECEDself-update sentinel),docker-compose.yml,
bootstrap/bootstrap.js,.github/workflows/lint.yml,config.example/*,
docs/robots.txt, all docs pages, and this changelog. - Compose project name note: docker compose derives the project name from
the clone directory, so named volumes follow it (<project>_openbao-data).
A freshgit cloneoftheta-suiteuses thetheta-suiteproject name; an
existing deployment that keeps itstheta-envdirectory keeps its
theta-env_*volumes — no data migration is required, just don't mix the two. - Docs site baseurl is now
/theta-suite, matching the renamed repo's
GitHub Pages URL.
Docs
architecture.mdrewritten. Replaced the outdated "The two containers"
/ "The three repos" framing with the actual topology — four always-on
services (openbao,sso-manager,proxy,jump-host) plus the
ldap-clienthost-enrollment tool — a real diagram, a full Secrets
(OpenBao) section (central store, scoped per-app policies/tokens, the
@simpleworkjs/bao-confboot overlay, per-user KV, external-app minting),
and an OpenBao-aware "how config reaches the apps". Removed the
LDAP-"legacy apps" wording (direct LDAP binds are first-class: Linux hosts
PAM/SSSD, sudo, SSH keys).index.md— integrated-suite framing; added Central secrets (OpenBao)
and ldap-client to "What you get" and "Related projects".standalone.md+README.md— standalone is now framed as an advanced
opt-in; the integrated./setup.shstack is the supported path.
Submodule bump
- sso-manager-node → v1.16.1 — fixes the 401 on
/confand/vaultfor
a logged-in admin. Both view routes 401'd because this app's auth-token is a
header set by client JS (localStorage), not a cookie, soreq.useris
undefined on a browser navigation; the routes now render the shell and gate
client-side (app.auth.forceLogin), with/api/conf+/api/vaultstill
enforcing auth + OpenBao scope server-side. See the
sso v1.16.1 release.