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.