diff --git a/CHANGELOG.md b/CHANGELOG.md
index b066dd9..7beb113 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to this project are documented here. Format loosely
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
correspond to git tags (`vX.Y.Z`) and `nodejs/package.json`'s `version`.
+## [1.5.1] - 2026-07-27
+
+### Fixed
+- **`PUT /api/user/:uid` 500'd with `ObjectClassViolationError` (LDAP `0x41`) when setting `sshPublicKey`** on any account created before the `ldapPublicKey` auxiliary objectClass was added to new-user creation (e.g. the bootstrap `admin` account). `User.update`'s `sshPublicKey` handling and `User.addSSHkey` (`nodejs/models/user_ldap.js`) now add the `ldapPublicKey` objectClass first (ignoring `TypeOrValueExistsError` if already present), the same pattern already used for `dateOfBirth`/`theta42Person`.
+- **OAuth Integration parent dropdown was blank.** `populateHostDropdown` in `nodejs/views/directory.ejs` only built options for `kind === 'host'` and `kind === 'service'` — there was no branch for `kind === 'oauth'`, so choosing "OAuth Integration" in the Directory's add-resource modal left the parent-Service picker empty except the placeholder. Added the missing branch.
+
## [1.5.0] - 2026-07-26
### Changed
diff --git a/nodejs/models/user_ldap.js b/nodejs/models/user_ldap.js
index dd82393..e7afd01 100644
--- a/nodejs/models/user_ldap.js
+++ b/nodejs/models/user_ldap.js
@@ -473,6 +473,19 @@ User.update = async function(data){
}
if(data.sshPublicKey){
+ // Ensure the auxiliary objectClass is present before setting the attribute
+ // -- accounts created before ldapPublicKey was added to addPosixAccount's
+ // objectclass list (e.g. the bootstrap admin) won't have it yet.
+ try {
+ await client.modify(this.dn, [
+ new Change({
+ operation: 'add',
+ modification: new Attribute({ type: 'objectClass', values: ['ldapPublicKey'] }),
+ }),
+ ]);
+ } catch(e) {
+ if(e.name !== 'TypeOrValueExistsError') throw e;
+ }
await client.modify(this.dn, [
new Change({
operation: 'replace',
@@ -784,6 +797,19 @@ User.addSSHkey = async function(data) {
let result;
try {
await withClient(async (client) => {
+ // Ensure the auxiliary objectClass is present before setting the attribute
+ // -- accounts created before ldapPublicKey was added to addPosixAccount's
+ // objectclass list (e.g. the bootstrap admin) won't have it yet.
+ try {
+ await client.modify(user.dn, [
+ new Change({
+ operation: 'add',
+ modification: new Attribute({ type: 'objectClass', values: ['ldapPublicKey'] }),
+ }),
+ ]);
+ } catch(e) {
+ if (e.name !== 'TypeOrValueExistsError') throw e;
+ }
await client.modify(user.dn, [
new Change({
operation: 'add',
diff --git a/nodejs/package.json b/nodejs/package.json
index ae51b96..19a80c4 100755
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -1,6 +1,6 @@
{
"name": "t42-sso-manager",
- "version": "1.5.0",
+ "version": "1.5.1",
"description": "A very simple LDAP management and SSO system",
"author": [
{
diff --git a/nodejs/views/directory.ejs b/nodejs/views/directory.ejs
index 955cef6..465f9db 100644
--- a/nodejs/views/directory.ejs
+++ b/nodejs/views/directory.ejs
@@ -572,6 +572,8 @@
$target.append($('