Skip to content

feat: commission open-window/close-window for multi-admin handoff#51

Merged
p0fi merged 3 commits intomainfrom
feat/commission-open-window
Apr 22, 2026
Merged

feat: commission open-window/close-window for multi-admin handoff#51
p0fi merged 3 commits intomainfrom
feat/commission-open-window

Conversation

@p0fi
Copy link
Copy Markdown
Owner

@p0fi p0fi commented Apr 21, 2026

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.

  • New subcommands: matter @N commission open-window (ECM, plus --basic for BCM) and matter @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 payload is encoded via tlv.NewWriter directly (the generated AdministratorCommissioning struct uses a tlv:",bytes" tag that's not wired into the marshaler).
  • Runs as a Timed Invoke. Uses the session daemon when available, falls back to a direct CASE session otherwise.
  • Daemon's InvokeResp now carries ClusterStatus so 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.
  • Window subcommands override commission's daemon-guard PersistentPreRunE because they only invoke a command; they don't need the BoltDB lock.
  • Setup payload for the QR / manual code gets VID/PID from the local store, falling back to reading BasicInformation over CASE; read failures are non-fatal (VID/PID default to 0).

Test plan

  • mise run test — all packages green (new verifier_test.go covers composition, determinism, input bounds, generator diversity).
  • mise exec -- go build ./... clean.
  • End-to-end against a matter.js virtual On/Off light:
    • open-window prints QR / manual / passcode / discriminator / salt / expiry; device log confirms all 5 TLV fields decoded correctly.
    • AdministratorCommissioning.WindowStatus reads 1 (EnhancedWindowOpen) after open, 0 (WindowNotOpen) after close.
    • close-window on a closed device → WindowNotOpen cluster-status decoded to friendly error.
    • Second open-window while one is active → Busy cluster-status decoded to friendly error.
    • --basic against matter.js returns IM UNSUPPORTED_COMMAND (0x81) (expected — matter.js doesn't advertise the BC feature).
  • Live hardware smoke test (not run — reviewer's call).

Closes #34

🤖 Generated with Claude Code

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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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-window CLI 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 ClusterStatus for 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.

Comment thread cli/commission_window.go Outdated
Comment thread cli/commission_window.go
p0fi and others added 2 commits April 22, 2026 20:31
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>
@p0fi p0fi merged commit ffbd38d into main Apr 22, 2026
@p0fi p0fi deleted the feat/commission-open-window branch April 22, 2026 19:58
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.

Add support to reopen the commissioning window

2 participants