feat: commission open-window/close-window for multi-admin handoff#51
Merged
feat: commission open-window/close-window for multi-admin handoff#51
Conversation
Adds Enhanced Commissioning Method window reopening so an already-commissioned device can be handed off to another ecosystem (Apple Home, Google Home, Alexa, ...) without a factory reset. - internal/commissioning/verifier.go: ComputePAKEVerifier derives the 97-byte (w0 || L) PAKE passcode verifier and exposes spec-constrained random generators for passcode, salt, and discriminator. - cli/commission_window.go: open-window (ECM + --basic) and close-window subcommands. Runs over a Timed Invoke via the session daemon when available and falls back to a direct CASE session. Decodes cluster-specific status codes (Busy/PAKEParameterError/WindowNotOpen) and generic IM status codes into friendly messages. - internal/daemon: InvokeResp now carries ClusterStatus so cluster-specific error decoding works uniformly whether the daemon handles the call or not. - CLAUDE.md: documents the new subcommands. Closes #34 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds multi-admin commissioning-window support so an already-commissioned node can reopen/close a commissioning window (ECM/BCM) without factory reset, and surfaces cluster-specific status codes consistently via the session daemon.
Changes:
- Introduces
matter @N commission open-window/close-windowCLI subcommands (timed invoke; daemon-first, direct-CASE fallback), including QR/manual code output and VID/PID lookup. - Implements PAKE verifier derivation (
ComputePAKEVerifier) plus random passcode/salt/discriminator generators with spec-constrained bounds and unit tests. - Extends daemon invoke response schema to carry
ClusterStatusfor cluster-specific status decoding.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
cli/commission.go |
Registers the new commissioning window subcommands under commission. |
cli/commission_window.go |
Implements open/close-window flows, TLV encoding, status mapping, and VID/PID fallback read. |
internal/commissioning/verifier.go |
Adds PAKE verifier derivation and random parameter generators with validation/constants. |
internal/commissioning/verifier_test.go |
Adds tests for verifier composition/determinism/bounds and random generators. |
internal/daemon/protocol.go |
Adds ClusterStatus to InvokeResp JSON schema. |
internal/daemon/server.go |
Populates InvokeResp.ClusterStatus from IM response status. |
CLAUDE.md |
Documents new CLI usage examples. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Bounds-check --timeout in int64 seconds before narrowing to uint16 so that
values larger than 65535s cannot wrap into the valid [180,900] range.
Use cmd.Flags().Changed("passcode") so that an explicit --passcode 0 is
rejected by ValidatePasscode rather than silently replaced with a random
one.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ands Print a Unicode half-block QR for the setup payload on every command that already emits a "QR Code:" text line (commission open-window, code parse, code generate) so the resulting code can be scanned directly from the terminal by another commissioner (Apple Home, Google Home, Alexa, ...). Rendering is skipped when stdout is not a TTY so piped output stays machine-readable, and the half-block glyphs pick up the terminal's own foreground/background palette so they render correctly under NO_COLOR without any special-casing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Issue #34 — reopen the commissioning window on a device that's already part of our fabric so a second ecosystem (Apple Home, Google Home, Alexa, …) can commission it without a factory reset.
matter @N commission open-window(ECM, plus--basicfor BCM) andmatter @N commission close-window.ComputePAKEVerifier(passcode, salt, iterations)derives the 97-byte(w0 || L)verifier using the existing SPAKE2+ primitives; random passcode / salt / discriminator generators included with spec-constrained bounds.tlv.NewWriterdirectly (the generatedAdministratorCommissioningstruct uses atlv:",bytes"tag that's not wired into the marshaler).InvokeRespnow carriesClusterStatusso cluster-specific status codes (Busy,PAKEParameterError,WindowNotOpen) and generic IM status codes (e.g.UNSUPPORTED_COMMAND) surface consistently whether the daemon handles the call or not.commission's daemon-guardPersistentPreRunEbecause they only invoke a command; they don't need the BoltDB lock.BasicInformationover CASE; read failures are non-fatal (VID/PID default to 0).Test plan
mise run test— all packages green (newverifier_test.gocovers composition, determinism, input bounds, generator diversity).mise exec -- go build ./...clean.open-windowprints QR / manual / passcode / discriminator / salt / expiry; device log confirms all 5 TLV fields decoded correctly.AdministratorCommissioning.WindowStatusreads1(EnhancedWindowOpen) after open,0(WindowNotOpen) after close.close-windowon a closed device →WindowNotOpencluster-status decoded to friendly error.open-windowwhile one is active →Busycluster-status decoded to friendly error.--basicagainst matter.js returns IMUNSUPPORTED_COMMAND (0x81)(expected — matter.js doesn't advertise the BC feature).Closes #34
🤖 Generated with Claude Code