Skip to content

feat: route User Code CC setValue calls through access control API, bump schema to 51#1566

Open
raman325 wants to merge 5 commits into
masterfrom
user-code-setvalue-compat
Open

feat: route User Code CC setValue calls through access control API, bump schema to 51#1566
raman325 wants to merge 5 commits into
masterfrom
user-code-setvalue-compat

Conversation

@raman325

@raman325 raman325 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

zwave-js (zwave-js/zwave-js#8930, targeting next) made the unified Access Control API the source of truth for User Code CC: the userCode/userIdStatus/adminCode values became internal and their setValue/pollValue support was removed. Clients that manage user codes via the node.set_value path (e.g. existing Home Assistant installs) would silently break once the server ships a driver containing that change.

This PR routes those legacy setValue calls through the access control API on a best-effort basis, covering every path the old UserCodeCC SET_VALUE implementation supported:

Legacy setValue call Routed to
userCode (string) accessControl.setCredential(...)
userIdStatus = Available accessControl.deleteCredential(...)
userIdStatus = Enabled accessControl.setUser(userId, { active: true })
userIdStatus = Disabled accessControl.setUser(userId, { active: false })
userIdStatus = Messaging accessControl.setUser(userId, { active: true, userType: NonAccess })
adminCode / masterCode (string) accessControl.setAdminCode(...)

Not routed: keypadMode still works through setValue upstream, and userIdStatus = PassageMode has no access control equivalent (documented as no longer supported).

Implementation notes:

  • The credential type is derived from getCredentialCapabilitiesCached() (PIN code, or Password for locks that allow non-PIN characters) rather than hardcoded
  • The endpoint is resolved from valueId.endpoint, and anything unroutable (other properties/values, non-numeric propertyKey, unsupported endpoint/type) falls back to node.setValue unchanged
  • Results are converted back to SetValueResult (SetCredentialResult/SetUserResult via local converters, setAdminCode's supervision result via supervisionResultToSetValueResult) so the response shape is unchanged for callers

The routing intentionally applies to all schema versions: the clients that need it are the ones that have not adopted the access control API, and the legacy behavior it would otherwise preserve no longer exists in zwave-js. Schema 51 documents the behavior change; clients targeting schema 51+ should use the endpoint.access_control commands directly.

Changes

  • src/lib/node/message_handler.ts: trySetUserCodeValue() shim + result converters
  • src/lib/const.ts: maxSchemaVersion 50 → 51
  • API_SCHEMA.md: Schema 51 entry

Testing

  • prettier --check, tsc --noEmit, and eslint pass
  • tsx src/test/integration.ts passes

🤖 Generated with Claude Code

…ump schema to 51

zwave-js removed setValue support for User Code CC user codes, making
the unified access control API the only way to manage them. Route
legacy setValue calls (setting userCode, or setting userIdStatus to
Available) through that API so clients that still use the setValue
path keep working. The routing applies to all schema versions since
the legacy path no longer exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 5, 2026 02:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR preserves compatibility for legacy clients that use node.set_value to manage User Code CC credentials by routing those specific setValue calls through the unified Access Control API introduced/required by upstream zwave-js changes. It also bumps the documented API schema to reflect this behavioral change while keeping the response shape stable for callers.

Changes:

  • Add a best-effort shim in the node setValue handler to translate legacy User Code CC writes into accessControl.setCredential(...) / accessControl.deleteCredential(...).
  • Convert SetCredentialResult back into a SetValueResult so the outward node.set_value response remains consistent.
  • Bump maxSchemaVersion to 51 and document the behavior in API_SCHEMA.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/lib/node/message_handler.ts Adds User Code CC setValue routing via Access Control API and result conversion logic
src/lib/const.ts Bumps supported schema max from 50 to 51
API_SCHEMA.md Documents schema 51 behavior change for legacy User Code CC node.set_value writes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lib/node/message_handler.ts
Comment thread src/lib/node/message_handler.ts Outdated
Comment thread src/lib/node/message_handler.ts
@raman325
raman325 marked this pull request as draft July 5, 2026 17:30
raman325 and others added 2 commits July 5, 2026 13:32
…rol API

Audit of the legacy UserCodeCC setValue implementation against the next
branch found two more removed paths that have access control
equivalents:

- adminCode (and the pre-rename masterCode alias) -> setAdminCode(),
  converted via supervisionResultToSetValueResult
- userIdStatus Enabled/Disabled/Messaging -> setUser() with the
  matching active/userType options, mirroring the reverse mapping
  zwave-js uses internally

userIdStatus = PassageMode has no access control equivalent and is
documented as no longer supported. keypadMode keeps working through
setValue upstream and needs no routing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@raman325
raman325 marked this pull request as ready for review July 5, 2026 17:40
@raman325
raman325 marked this pull request as draft July 7, 2026 03:56
Comment thread src/lib/node/message_handler.ts Outdated
Comment thread src/lib/node/message_handler.ts
…o SetValueResult

- Accept Uint8Array user codes in the setValue shim, matching the removed
  UserCodeCC SET_VALUE implementation and accessControl.setCredential
- Catch the Argument_Invalid error thrown by setUser when a User Code CC
  slot has no cached code and convert it to an InvalidValue SetValueResult
  so all routed paths return a consistent result shape

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@raman325
raman325 marked this pull request as ready for review July 7, 2026 14:53
…ed slot

setCredential on User Credential CC devices requires an existing user, so
legacy clients could never create a new user/code through the shim. Route
through addUser when no cached user exists for the slot, which creates the
user and credential together on both CC paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@AlCalzone AlCalzone left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Do you have any way to test this?

@raman325

raman325 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

If I build everything locally I can try the old services in HA which will exercise this path. I can't test all the conditions but I can validate at least the set and delete get done properly. I'll look into this later today

@raman325

raman325 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

tested and successfully working (I had to send Websocket commands manually since, per my comment on Discord, HA services are going to break and there's nothing we can do about it)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants