sesame-kit 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/LICENSE +26 -0
  2. package/LICENSE.biz3 +21 -0
  3. package/README.ja.md +225 -0
  4. package/README.md +222 -0
  5. package/bin/sesame.js +8 -0
  6. package/clients/js/sesame-client.mjs +208 -0
  7. package/clients/python/pyproject.toml +5 -0
  8. package/clients/python/sesame_client.py +323 -0
  9. package/clients/python/setup.cfg +11 -0
  10. package/docs/architecture.ja.md +132 -0
  11. package/docs/architecture.md +105 -0
  12. package/docs/commands.ja.md +316 -0
  13. package/docs/commands.md +308 -0
  14. package/docs/library.ja.md +152 -0
  15. package/docs/library.md +152 -0
  16. package/docs/migration.ja.md +13 -0
  17. package/docs/migration.md +13 -0
  18. package/package.json +114 -0
  19. package/src/access.js +375 -0
  20. package/src/account.js +36 -0
  21. package/src/auth.js +248 -0
  22. package/src/ble/devicemodel.js +164 -0
  23. package/src/ble/index.js +185 -0
  24. package/src/ble/protocol.js +319 -0
  25. package/src/ble/session.js +235 -0
  26. package/src/ble/transport.js +279 -0
  27. package/src/cli/access.js +373 -0
  28. package/src/cli/company.js +104 -0
  29. package/src/cli/iot.js +400 -0
  30. package/src/cli/org.js +788 -0
  31. package/src/cli/presetir.js +188 -0
  32. package/src/cli/schedule.js +83 -0
  33. package/src/cli/serve.js +308 -0
  34. package/src/cli.js +1815 -0
  35. package/src/client.js +957 -0
  36. package/src/company.js +147 -0
  37. package/src/config.js +575 -0
  38. package/src/crypto.js +162 -0
  39. package/src/devices.js +228 -0
  40. package/src/index.js +55 -0
  41. package/src/iot.js +513 -0
  42. package/src/ir.js +341 -0
  43. package/src/itemcodes.js +29 -0
  44. package/src/lock.js +194 -0
  45. package/src/org.js +803 -0
  46. package/src/paths.js +30 -0
  47. package/src/presetir.js +525 -0
  48. package/src/prompts.js +74 -0
  49. package/src/schedule.js +108 -0
  50. package/src/serve/daemon.js +251 -0
  51. package/src/serve/framing/grpc.js +145 -0
  52. package/src/serve/framing/http.js +144 -0
  53. package/src/serve/framing/ndjson.js +75 -0
  54. package/src/serve/framing/socket.js +73 -0
  55. package/src/serve/framing/stdio.js +28 -0
  56. package/src/serve/framing/token.js +36 -0
  57. package/src/serve/framing/ws.js +56 -0
  58. package/src/serve/grpc-methods.generated.json +378 -0
  59. package/src/serve/jsonrpc.js +164 -0
  60. package/src/serve/registry.js +226 -0
  61. package/src/serve/rpc-params.generated.json +1746 -0
  62. package/src/serve/sesame.proto +470 -0
  63. package/src/session-ui.js +181 -0
  64. package/src/sharekey.js +130 -0
  65. package/src/tokens.js +53 -0
  66. package/src/transport.js +634 -0
  67. package/src/util.js +26 -0
  68. package/types/access.d.ts +193 -0
  69. package/types/access.d.ts.map +1 -0
  70. package/types/account.d.ts +13 -0
  71. package/types/account.d.ts.map +1 -0
  72. package/types/auth.d.ts +80 -0
  73. package/types/auth.d.ts.map +1 -0
  74. package/types/ble/devicemodel.d.ts +212 -0
  75. package/types/ble/devicemodel.d.ts.map +1 -0
  76. package/types/ble/index.d.ts +160 -0
  77. package/types/ble/index.d.ts.map +1 -0
  78. package/types/ble/protocol.d.ts +201 -0
  79. package/types/ble/protocol.d.ts.map +1 -0
  80. package/types/ble/session.d.ts +129 -0
  81. package/types/ble/session.d.ts.map +1 -0
  82. package/types/ble/transport.d.ts +67 -0
  83. package/types/ble/transport.d.ts.map +1 -0
  84. package/types/cli/access.d.ts +6 -0
  85. package/types/cli/access.d.ts.map +1 -0
  86. package/types/cli/company.d.ts +6 -0
  87. package/types/cli/company.d.ts.map +1 -0
  88. package/types/cli/iot.d.ts +6 -0
  89. package/types/cli/iot.d.ts.map +1 -0
  90. package/types/cli/org.d.ts +6 -0
  91. package/types/cli/org.d.ts.map +1 -0
  92. package/types/cli/presetir.d.ts +6 -0
  93. package/types/cli/presetir.d.ts.map +1 -0
  94. package/types/cli/schedule.d.ts +6 -0
  95. package/types/cli/schedule.d.ts.map +1 -0
  96. package/types/cli/serve.d.ts +2 -0
  97. package/types/cli/serve.d.ts.map +1 -0
  98. package/types/cli.d.ts +2 -0
  99. package/types/cli.d.ts.map +1 -0
  100. package/types/client.d.ts +463 -0
  101. package/types/client.d.ts.map +1 -0
  102. package/types/company.d.ts +94 -0
  103. package/types/company.d.ts.map +1 -0
  104. package/types/config.d.ts +111 -0
  105. package/types/config.d.ts.map +1 -0
  106. package/types/crypto.d.ts +61 -0
  107. package/types/crypto.d.ts.map +1 -0
  108. package/types/devices.d.ts +116 -0
  109. package/types/devices.d.ts.map +1 -0
  110. package/types/index.d.ts +23 -0
  111. package/types/index.d.ts.map +1 -0
  112. package/types/iot.d.ts +312 -0
  113. package/types/iot.d.ts.map +1 -0
  114. package/types/ir.d.ts +147 -0
  115. package/types/ir.d.ts.map +1 -0
  116. package/types/itemcodes.d.ts +21 -0
  117. package/types/itemcodes.d.ts.map +1 -0
  118. package/types/lock.d.ts +89 -0
  119. package/types/lock.d.ts.map +1 -0
  120. package/types/org.d.ts +468 -0
  121. package/types/org.d.ts.map +1 -0
  122. package/types/paths.d.ts +10 -0
  123. package/types/paths.d.ts.map +1 -0
  124. package/types/presetir.d.ts +286 -0
  125. package/types/presetir.d.ts.map +1 -0
  126. package/types/prompts.d.ts +39 -0
  127. package/types/prompts.d.ts.map +1 -0
  128. package/types/schedule.d.ts +71 -0
  129. package/types/schedule.d.ts.map +1 -0
  130. package/types/serve/daemon.d.ts +133 -0
  131. package/types/serve/daemon.d.ts.map +1 -0
  132. package/types/serve/framing/grpc.d.ts +14 -0
  133. package/types/serve/framing/grpc.d.ts.map +1 -0
  134. package/types/serve/framing/http.d.ts +14 -0
  135. package/types/serve/framing/http.d.ts.map +1 -0
  136. package/types/serve/framing/ndjson.d.ts +19 -0
  137. package/types/serve/framing/ndjson.d.ts.map +1 -0
  138. package/types/serve/framing/socket.d.ts +14 -0
  139. package/types/serve/framing/socket.d.ts.map +1 -0
  140. package/types/serve/framing/stdio.d.ts +11 -0
  141. package/types/serve/framing/stdio.d.ts.map +1 -0
  142. package/types/serve/framing/token.d.ts +11 -0
  143. package/types/serve/framing/token.d.ts.map +1 -0
  144. package/types/serve/framing/ws.d.ts +13 -0
  145. package/types/serve/framing/ws.d.ts.map +1 -0
  146. package/types/serve/jsonrpc.d.ts +118 -0
  147. package/types/serve/jsonrpc.d.ts.map +1 -0
  148. package/types/serve/registry.d.ts +41 -0
  149. package/types/serve/registry.d.ts.map +1 -0
  150. package/types/session-ui.d.ts +36 -0
  151. package/types/session-ui.d.ts.map +1 -0
  152. package/types/sharekey.d.ts +35 -0
  153. package/types/sharekey.d.ts.map +1 -0
  154. package/types/tokens.d.ts +20 -0
  155. package/types/tokens.d.ts.map +1 -0
  156. package/types/transport.d.ts +138 -0
  157. package/types/transport.d.ts.map +1 -0
  158. package/types/util.d.ts +20 -0
  159. package/types/util.d.ts.map +1 -0
  160. package/vendor/biz3/README.md +37 -0
  161. package/vendor/biz3/constants/cmdCode.d.ts +48 -0
  162. package/vendor/biz3/constants/cmdCode.d.ts.map +1 -0
  163. package/vendor/biz3/constants/cmdCode.js +92 -0
  164. package/vendor/biz3/constants/messageConstants.d.ts +28 -0
  165. package/vendor/biz3/constants/messageConstants.d.ts.map +1 -0
  166. package/vendor/biz3/constants/messageConstants.js +30 -0
  167. package/vendor/biz3/constants/sesameDeviceModel.d.ts +75 -0
  168. package/vendor/biz3/constants/sesameDeviceModel.d.ts.map +1 -0
  169. package/vendor/biz3/constants/sesameDeviceModel.js +77 -0
  170. package/vendor/biz3/package.json +5 -0
package/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ikuma Fukumoto
4
+
5
+ This project is a Node.js port of biz3 (CANDY-HOUSE/biz3, MIT) with the
6
+ Cognito client ID swapped to the official iOS/Android consumer client
7
+ (6ialca0p8u0lsgvbmvsljfm305) for long-lived sessions. See LICENSE.biz3
8
+ for the original biz3 MIT license.
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
package/LICENSE.biz3 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 CANDY HOUSE
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ja.md ADDED
@@ -0,0 +1,225 @@
1
+ <!-- [English](./README.md) | 日本語 -->
2
+
3
+ # sesame-kit — SESAME クラウド CLI & ライブラリ (非公式)
4
+
5
+ > English: [README.md](./README.md)
6
+
7
+ > **ステータス** — pre-1.0 でありバグが残っている可能性があります。実運用で概ね安定が確認できた時点で 1.0 にします。依存する場合はバージョンを固定してください。
8
+ >
9
+ > **免責** — 非公式。CANDY HOUSE とは無関係で、公式の承認も受けていません。公式アプリと同じ方法でクラウド API を叩くため、予告なく変更・破損する可能性があります。`secretKey` とトークンはロックの全権を握るので外部に漏らさないでください。自己責任で利用してください。
10
+
11
+ 公式 SESAME iOS / Android アプリと同じ Cognito Consumer Client で、SESAME クラウドの WebSocket API を叩く Node.js 実装。ロックの開閉、Hub3 IR の発射・学習、デバイス管理、開閉履歴、電池残量を CLI とライブラリで提供する。`sesame serve` を使えば全機能を JSON-RPC として公開し、任意の言語から組み込める。
12
+
13
+ ## 何ができるか
14
+
15
+ - ロック制御: 施錠 / 解錠 / トグル / SESAME Bot クリック
16
+ - Hub3 IR: 既存リモコンの発射、物理リモコンからの学習、リモコン / キー CRUD、プリセット DB 検索
17
+ - デバイス管理: 一覧、リネーム、削除、現在状態、state push 購読
18
+ - 履歴: ロック開閉履歴、電池残量履歴
19
+ - アクセス制御: NFC カード / キーパッド暗証番号の DB 同期
20
+ - 予約 / 会社・組織: スケジュール、法人機能 (社員・役割・デバイスグループ・鍵共有)
21
+ - Hub3 IoT: LED 調光、LTE リレー、ファーム更新、Matter ペアリング
22
+ - BLE 直接制御: Bluetooth でロックを直接操作する。autolock 等の設定系は BLE でのみ実機に反映される
23
+ - 言語非依存バックエンド: `sesame serve` が全機能を stdio / UDS / HTTP / WS / gRPC に JSON-RPC として公開する
24
+ - 対話モード、ライブラリ API
25
+
26
+ 詳細は [コマンドリファレンス](./docs/commands.ja.md) / [ライブラリ利用](./docs/library.ja.md) / [設計ノート](./docs/architecture.ja.md) を参照。
27
+
28
+ ## 出自 (Lineage)
29
+
30
+ 公式 biz3 管理 Web ([CANDY-HOUSE/biz.candyhouse.co](https://github.com/CANDY-HOUSE/biz.candyhouse.co), MIT) の Node.js port。biz3 との差分は Cognito Client ID を公式 iOS / Android アプリと同じ Consumer Client にした点のみで、これにより refreshToken が事実上失効しない。biz3 の MIT ライセンスは [LICENSE.biz3](./LICENSE.biz3) に同梱する。port 対応表は [docs/architecture.md](./docs/architecture.ja.md) を参照。
31
+
32
+ ---
33
+
34
+ ## インストール
35
+
36
+ 要件は Node.js 18 以上 (ESM / `node:` プロトコルを使用)。
37
+
38
+ ```bash
39
+ git clone https://github.com/FukumotoIkuma/sesame-kit.git
40
+ cd sesame-kit
41
+ npm install
42
+ npm link # グローバルに `sesame` コマンドを公開
43
+ # あるいは: node bin/sesame.js ...
44
+ ```
45
+
46
+ ライブラリとして使う場合は `npm link sesame-kit`、または `npm install /path/to/sesame-kit`。
47
+
48
+ ---
49
+
50
+ ## セットアップ
51
+
52
+ `login` と `verify` で認証する。`verify` は companyID・ロック・Hub3 IR を自動で取り込む。
53
+
54
+ ```bash
55
+ sesame init # 設定ディレクトリ初期化 (~/.config/sesame-hub3/)
56
+ sesame login your@email.com # email に確認コードを送る
57
+ sesame verify # コードを入力。companyID / ロック / Hub3 IR を取り込む
58
+ ```
59
+
60
+ デバイスを後から追加したら `sesame setup` で取り込みを再実行する。
61
+ IR を使うには Hub3 と Remote の両方の登録が必要。ロック開閉だけなら Lock の登録だけでよい。
62
+
63
+ ---
64
+
65
+ ## 基本操作
66
+
67
+ 主語はデバイス: `sesame <device> <action>` (device は部分一致)。
68
+
69
+ ```bash
70
+ sesame front unlock # 解錠 (部分一致: sesame 玄関 unlock)
71
+ sesame front lock # 施錠
72
+ sesame front toggle # 現在状態で反転
73
+ sesame front status # 状態 (施錠 / 解錠・位置)
74
+ sesame front autolock 30 # オートロック (BLE 必須。0=無効)
75
+ sesame send 停止 --remote ac # Hub3 IR 発射
76
+ sesame # 全デバイスの対話メニュー (session)
77
+ ```
78
+
79
+ 経路 (cloud / BLE) は自動で選ばれる。固定するときは `--ble-only` / `--cloud-only` を付ける。
80
+ IR 学習・デバイス管理・予約・アクセス制御・会社組織・IoT・BLE の全コマンドは [docs/commands.md](./docs/commands.ja.md) を参照。
81
+
82
+ ### 対話モード
83
+
84
+ TTY 環境 (`--json` 指定なし) では、足りない引数を矢印キー (↑↓) で選択できる。`sesame` だけでトップメニュー。
85
+ `--json` / 非 TTY では prompt を出さず、引数不足はエラーになる (CI 互換)。
86
+
87
+ ---
88
+
89
+ ## JSON 出力契約 (他言語からの subprocess 呼び出し)
90
+
91
+ `--json` を付けると、subprocess から扱える契約で動く。
92
+
93
+ - 成功: stdout に純 JSON を 1 件だけ出力する (進捗・ログは stderr)。
94
+ - エラー: stderr に `{"error": "...", "code": <n>}` を出し、非 0 で終了する。
95
+ - `--json` / 非対話では prompt を出さず、引数不足は即エラー。
96
+ - 終了コード: `0`=成功 / `1`=実行時エラー / `2`=使い方エラー。
97
+
98
+ ```bash
99
+ sesame front status --json # → stdout: {...} exit 0
100
+ sesame login --json # → stderr: {"error":"...","code":1} exit≠0
101
+ ```
102
+
103
+ 出力 JSON の形は各コマンド固有。互換性の判定には契約バージョンを使う:
104
+ 常駐デーモンの `status` が返す `contractVersion`、または `rpc.discover` の `info["x-contractVersion"]`。
105
+ 機械契約の SemVer で、破壊的変更でのみ major が上がる。消費者は major を pin して fail-fast できる。
106
+
107
+ ---
108
+
109
+ ## 言語非依存バックエンド (`sesame serve`)
110
+
111
+ `sesame serve` は常駐 JSON-RPC 2.0 デーモン。1 回ログインして WS 接続を保持したまま、何度でも op を実行し、
112
+ イベントを push する。全機能を、どの言語からでも同一の API で呼べる。
113
+
114
+ ```bash
115
+ sesame serve # Unix socket のみ (既定。~/.config/sesame-hub3/sesame.sock)
116
+ sesame serve --stdio # 埋め込み: 親が子プロセスとして spawn し stdin/stdout で対話
117
+ sesame serve --http 8080 --ws 8081 --grpc 50051 # ネットワーク経由 (token 認証)
118
+ ```
119
+
120
+ 5 つの繋ぎ口があり、どれも同じメソッドを公開する:
121
+
122
+ | 繋ぎ口 | 用途 | イベント | 認証 |
123
+ |---|---|---|---|
124
+ | stdio | 埋め込み (子プロセス) | `event.*` 通知 | 親の信頼を継承 |
125
+ | Unix socket | ローカル常駐・多クライアント | `event.*` 通知 | ファイル権限 0600 |
126
+ | HTTP | 全言語 / ブラウザ | `GET /events` (SSE) | `Authorization: Bearer <token>` |
127
+ | WebSocket | 全言語 / ブラウザ (全二重) | `event.*` 通知 | token |
128
+ | gRPC | 多言語の型付きスタブ生成 | `Subscribe` ストリーム | token (metadata) |
129
+
130
+ - メソッドは `rpc.discover` で機械可読に全列挙する (OpenRPC)。param 名・必須・型は実コードから抽出済み。
131
+ - ロック: `lock.lock` / `lock.unlock` / `lock.toggle` / `lock.status`。名前空間 op は `<ns>.<op>` で全公開する (`org.*` / `iot.*` / `access.*` …)。
132
+ - イベント: `events.subscribe {topics:["lockState","deviceUpdate"]}` で以後 `event.<topic>` 通知が届く。
133
+ - エラーは `{error:{code, message, data:{kind}}}`。`kind` は `not_authenticated` / `connection_lost` / `timeout` / `bad_params` / `not_implemented` / `internal` の 6 種。
134
+
135
+ 別端末で `sesame serve` を起動しておけば、`sesame rpc` が UDS 越しにそのデーモンを叩く:
136
+
137
+ ```bash
138
+ sesame rpc # rpc.discover を人間向けの表で表示
139
+ sesame rpc lock.unlock --params '{"name":"front"}'
140
+ sesame rpc --subscribe lockState # イベントを表示し続ける (Ctrl-C で停止)
141
+ sesame rpc --paths # 接続情報 (socket / token のパス) を JSON で出力
142
+ ```
143
+
144
+ ### 同梱クライアント
145
+
146
+ `clients/` に依存ゼロの薄いクライアントを同梱する。
147
+
148
+ - Python: `pip install ./clients/python` で、どこからでも `import sesame_client`。試すだけなら `PYTHONPATH=clients/python`。
149
+ - JS: `clients/js/sesame-client.mjs` を自プロジェクトにコピー、または相対 import。WebSocket をヘッダ認証で使うなら `npm i ws` (無ければ URL `?token=` にフォールバックする)。
150
+
151
+ ```python
152
+ from sesame_client import SesameClient
153
+ c = SesameClient.unix() # 既定 UDS パスを自動解決
154
+ print(c.status()); print(c.unlock("front"))
155
+ c.subscribe(["lockState"], lambda topic, payload: print("EVENT", topic, payload))
156
+ # HTTP: SesameClient.http("http://127.0.0.1:8080") / 埋め込み: SesameClient.stdio()
157
+ ```
158
+
159
+ ```js
160
+ import { SesameClient } from "./sesame-client.mjs";
161
+ const c = SesameClient.unix(); // UDS (POSIX)
162
+ console.log(await c.unlock("front"));
163
+ await c.subscribe(["lockState"], (topic, p) => console.log("EVENT", topic, p)); // 常に await
164
+ const w = await SesameClient.ws("ws://127.0.0.1:8081"); // WebSocket (全二重)
165
+ ```
166
+
167
+ gRPC は型付き。`src/serve/sesame.proto` が op ごとに型付きメソッドを持つ。
168
+ スタブ生成: `python -m grpc_tools.protoc -I src/serve --python_out=. --grpc_python_out=. src/serve/sesame.proto`。
169
+
170
+ 認証境界: 対話ログインは CLI 専用で、デーモンには載らない。Unix socket は同一ユーザの任意プロセスが操作できる
171
+ (CLI と同じ境界)。HTTP / WS / gRPC は TCP のため、起動時に生成する loopback token を要求する。POSIX 専用
172
+ (Windows の UDS は非対象。stdio / HTTP / WS / gRPC は動く)。
173
+
174
+ ---
175
+
176
+ ## 設定ディレクトリ
177
+
178
+ 優先順位: `--config-dir <path>` → `SESAME_HUB3_HOME` → `$XDG_CONFIG_HOME/sesame-hub3` → `~/.config/sesame-hub3`。
179
+
180
+ ```
181
+ ~/.config/sesame-hub3/
182
+ ├── config.json # devices / remotes / default / apiKeyId
183
+ ├── tokens.json # Cognito state (gitignore 必須)
184
+ ├── login_state.json # sign-in 進行中の一時状態
185
+ └── devices.json # `devices` コマンドの dump
186
+ ```
187
+
188
+ config スキーマと「単一 `devices{}` に保存する」設計は [docs/architecture.md](./docs/architecture.ja.md) を参照。
189
+
190
+ ---
191
+
192
+ ## ドキュメント
193
+
194
+ - [docs/commands.md](./docs/commands.ja.md) — 全 CLI コマンドのリファレンス
195
+ - [docs/library.md](./docs/library.ja.md) — Node ライブラリとしての利用
196
+ - [docs/architecture.md](./docs/architecture.ja.md) — 出自・設計判断・ファイル構成
197
+ - [docs/migration.md](./docs/migration.ja.md) — 旧版からの移行
198
+
199
+ ---
200
+
201
+ ## 既知の制限
202
+
203
+ - 常駐用途では auto-reconnect (exponential backoff 1s→10s)、token refresh callback、idle / sleep 検知が動く。
204
+ - 対応リモコンは自己学習 (`learnEmit`) のみ。プリセットリモコン (メーカー DB から選ぶ方式) の command 生成は未移植。`sesame ir learn` で物理リモコンを取り込んで使う。
205
+ - autolock はクラウド経由では設定できない。BLE の `sesame autolock` を使う。
206
+ - 未実装 op は Stripe 課金切替のみ。それ以外の biz3 op (社員 / グループ / 役割 / デバイスグループ / 鍵共有 / アクセス制御 / 予約 / IoT) はコマンド化済み。
207
+ - WS ステージの既定は `/public`。`/production` は使用しない (config に残っていれば load 時に `/public` へ書き換える)。
208
+ - AWS IoT WS は IPv4 必須。IPv6-only 回線では繋がらない。
209
+ - 新規ペアリング (未登録デバイスの登録) は未対応。登録済みデバイスの操作のみ。
210
+
211
+ ---
212
+
213
+ ## トラブルシュート
214
+
215
+ - `No tokens stored` / `No config at ...`: `sesame init` → `sesame login`、または `sesame migrate`。
216
+ - `UserNotFoundException`: 自動 SignUp は組み込み済み。それでも出る場合は Cognito 側の特殊ケース。
217
+ - `Cognito refresh returned no IdToken`: refreshToken が無効化された (公式アプリでログアウト等)。再 sign-in する。
218
+ - `triggerLock timeout`: `secretKey` 不一致、Hub3 オフライン、または WS の半開接続 (自動再接続で復帰)。
219
+ - `learn timeout`: Hub3 が REGISTER に入ったが波形を受け取れなかった。距離を縮める、別ボタンを試す。
220
+ - `apiKeyId required`: `webapi` 系は config.json に `apiKeyId` を入れる (biz3 dev console で発行)。
221
+
222
+ ## 関連
223
+
224
+ - [CANDY-HOUSE/biz.candyhouse.co](https://github.com/CANDY-HOUSE/biz.candyhouse.co) — port 元の React 管理 Web "biz3"
225
+ - [SesameSDK_iOS_with_DemoApp](https://github.com/CANDY-HOUSE/SesameSDK_iOS_with_DemoApp) / [SesameSDK_Android_with_DemoApp](https://github.com/CANDY-HOUSE/SesameSDK_Android_with_DemoApp) — 参考にした公式 SDK
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ <!-- English | [日本語](./README.ja.md) -->
2
+
3
+ # sesame-kit — SESAME cloud CLI & library (unofficial)
4
+
5
+ A Node.js CLI and library that drives the SESAME cloud WebSocket API using the same Cognito consumer client as the official SESAME iOS / Android apps. It covers lock control, Hub3 IR (emit and learn), device management, history, and battery level. With `sesame serve` it exposes every feature as JSON-RPC so you can drive SESAME from any language.
6
+
7
+ > 日本語版: [README.ja.md](./README.ja.md)
8
+
9
+ > **Status** — Pre-1.0 and may contain bugs. It will reach 1.0 once it has proven stable in real use. Pin a version if you depend on it.
10
+ >
11
+ > **Disclaimer** — Unofficial. Not affiliated with or endorsed by CANDY HOUSE. It drives the cloud API the same way the official apps do, which may change or break without notice. Your `secretKey` and tokens grant full control of your lock; keep them private. Use at your own risk.
12
+
13
+ ## Features
14
+
15
+ - Lock control: lock / unlock / toggle / SESAME Bot click
16
+ - Hub3 IR: emit existing remotes, learn from a physical remote, remote / key CRUD, preset DB search
17
+ - Device management: list, rename, delete, current state, state-push subscriptions
18
+ - History: lock open/close history, battery history
19
+ - Access control: NFC card / keypad passcode DB sync
20
+ - Scheduling / company & org: schedules, enterprise features (employees, roles, device groups, key sharing)
21
+ - Hub3 IoT: LED dimming, LTE relay, firmware update, Matter pairing
22
+ - BLE direct control: operate locks over Bluetooth without the cloud. Settings such as autolock only take effect over BLE
23
+ - Language-agnostic backend: `sesame serve` exposes every feature as JSON-RPC over stdio / UDS / HTTP / WS / gRPC
24
+ - Interactive mode and a library API
25
+
26
+ See [command reference](./docs/commands.md), [library usage](./docs/library.md), and [design notes](./docs/architecture.md) for details.
27
+
28
+ ## Lineage
29
+
30
+ A Node.js port of the official biz3 admin web app ([CANDY-HOUSE/biz.candyhouse.co](https://github.com/CANDY-HOUSE/biz.candyhouse.co), MIT). The only functional difference from biz3 is that the Cognito client ID is set to the same consumer client as the official iOS / Android apps, which keeps the refresh token from effectively expiring. The biz3 MIT license is bundled as [LICENSE.biz3](./LICENSE.biz3). The port mapping is in [docs/architecture.md](./docs/architecture.md).
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ Requires Node.js 18+ (uses ESM and the `node:` protocol).
37
+
38
+ ```bash
39
+ git clone https://github.com/FukumotoIkuma/sesame-kit.git
40
+ cd sesame-kit
41
+ npm install
42
+ npm link # expose the `sesame` command globally
43
+ # or: node bin/sesame.js ...
44
+ ```
45
+
46
+ To use it as a library: `npm link sesame-kit`, or `npm install /path/to/sesame-kit`.
47
+
48
+ ---
49
+
50
+ ## Setup
51
+
52
+ Authenticate with `login` and `verify`. `verify` imports your companyID, locks, and Hub3 IR remotes automatically.
53
+
54
+ ```bash
55
+ sesame init # initialize the config directory (~/.config/sesame-hub3/)
56
+ sesame login your@email.com # send a verification code to your email
57
+ sesame verify # enter the code; imports companyID / locks / Hub3 IR
58
+ ```
59
+
60
+ Run `sesame setup` to re-import after adding devices later.
61
+ IR requires both a Hub3 and a Remote to be registered. For lock control alone, only the Lock is needed.
62
+
63
+ ---
64
+
65
+ ## Basic usage
66
+
67
+ The subject is the device: `sesame <device> <action>` (device matches by substring).
68
+
69
+ ```bash
70
+ sesame front unlock # unlock (substring match: sesame 玄関 unlock)
71
+ sesame front lock # lock
72
+ sesame front toggle # toggle from current state
73
+ sesame front status # state (locked / unlocked, position)
74
+ sesame front autolock 30 # autolock (BLE only. 0 = off)
75
+ sesame send 停止 --remote ac # Hub3 IR emit
76
+ sesame # interactive menu for all devices (session)
77
+ ```
78
+
79
+ The route (cloud / BLE) is chosen automatically. Pin it with `--ble-only` / `--cloud-only`.
80
+ See [docs/commands.md](./docs/commands.md) for the full command set (IR learning, device management, scheduling, access control, org, IoT, BLE).
81
+
82
+ ### Interactive mode
83
+
84
+ In a TTY (no `--json`), missing arguments can be selected with the arrow keys (↑↓). `sesame` alone opens the top menu.
85
+ With `--json` or in a non-TTY, no prompts are shown and missing arguments are errors (CI-friendly).
86
+
87
+ ---
88
+
89
+ ## JSON output contract (calling from other languages)
90
+
91
+ With `--json`, commands behave under a contract that is safe to call from a subprocess.
92
+
93
+ - Success: exactly one pure JSON object on stdout (progress and logs go to stderr).
94
+ - Error: `{"error": "...", "code": <n>}` on stderr, with a non-zero exit code.
95
+ - With `--json` or non-interactive, no prompts; missing arguments are immediate errors.
96
+ - Exit codes: `0` = success / `1` = runtime error / `2` = usage error.
97
+
98
+ ```bash
99
+ sesame front status --json # → stdout: {...} exit 0
100
+ sesame login --json # → stderr: {"error":"...","code":1} exit≠0
101
+ ```
102
+
103
+ The JSON shape is command-specific. Use the contract version to check compatibility:
104
+ the daemon's `status` returns `contractVersion`, and `rpc.discover` returns `info["x-contractVersion"]`.
105
+ It is a SemVer for the machine contract; only breaking changes bump the major. Consumers can pin the major and fail fast.
106
+
107
+ ---
108
+
109
+ ## Language-agnostic backend (`sesame serve`)
110
+
111
+ `sesame serve` is a long-running JSON-RPC 2.0 daemon. It logs in once, keeps the WS connection alive, runs ops repeatedly, and pushes events. Every feature is callable from any language through the same API.
112
+
113
+ ```bash
114
+ sesame serve # Unix socket only (default. ~/.config/sesame-hub3/sesame.sock)
115
+ sesame serve --stdio # embedded: a parent spawns it and talks over stdin/stdout
116
+ sesame serve --http 8080 --ws 8081 --grpc 50051 # over the network (token auth)
117
+ ```
118
+
119
+ There are five framings, all exposing the same methods:
120
+
121
+ | Framing | Use | Events | Auth |
122
+ |---|---|---|---|
123
+ | stdio | embedded (child process) | `event.*` notifications | inherits parent trust |
124
+ | Unix socket | local daemon, multiple clients | `event.*` notifications | file permission 0600 |
125
+ | HTTP | any language / browser | `GET /events` (SSE) | `Authorization: Bearer <token>` |
126
+ | WebSocket | any language / browser (full-duplex) | `event.*` notifications | token |
127
+ | gRPC | typed stub generation for many languages | `Subscribe` stream | token (metadata) |
128
+
129
+ - `rpc.discover` enumerates every method machine-readably (OpenRPC). Param names, requiredness, and types are extracted from the actual code.
130
+ - Locks: `lock.lock` / `lock.unlock` / `lock.toggle` / `lock.status`. Namespace ops are all exposed as `<ns>.<op>` (`org.*` / `iot.*` / `access.*` …).
131
+ - Events: `events.subscribe {topics:["lockState","deviceUpdate"]}` then `event.<topic>` notifications arrive.
132
+ - Errors are `{error:{code, message, data:{kind}}}`. `kind` is one of six: `not_authenticated` / `connection_lost` / `timeout` / `bad_params` / `not_implemented` / `internal`.
133
+
134
+ Start `sesame serve` in one terminal, then call it over the socket from another with `sesame rpc`:
135
+
136
+ ```bash
137
+ sesame rpc # show rpc.discover as a human-readable table
138
+ sesame rpc lock.unlock --params '{"name":"front"}'
139
+ sesame rpc --subscribe lockState # keep printing events (Ctrl-C to stop)
140
+ sesame rpc --paths # print connection info (socket / token paths) as JSON
141
+ ```
142
+
143
+ ### Bundled clients
144
+
145
+ Thin zero-dependency clients live under `clients/`.
146
+
147
+ - Python: `pip install ./clients/python`, then `import sesame_client` from anywhere. For a quick try, `PYTHONPATH=clients/python`.
148
+ - JS: copy `clients/js/sesame-client.mjs` into your project, or import it by relative path. For header-authenticated WebSocket, `npm i ws` (otherwise it falls back to URL `?token=`).
149
+
150
+ ```python
151
+ from sesame_client import SesameClient
152
+ c = SesameClient.unix() # resolves the default UDS path
153
+ print(c.status()); print(c.unlock("front"))
154
+ c.subscribe(["lockState"], lambda topic, payload: print("EVENT", topic, payload))
155
+ # HTTP: SesameClient.http("http://127.0.0.1:8080") / embedded: SesameClient.stdio()
156
+ ```
157
+
158
+ ```js
159
+ import { SesameClient } from "./sesame-client.mjs";
160
+ const c = SesameClient.unix(); // UDS (POSIX)
161
+ console.log(await c.unlock("front"));
162
+ await c.subscribe(["lockState"], (topic, p) => console.log("EVENT", topic, p)); // always await
163
+ const w = await SesameClient.ws("ws://127.0.0.1:8081"); // WebSocket (full-duplex)
164
+ ```
165
+
166
+ gRPC is typed. `src/serve/sesame.proto` has a typed method per op.
167
+ Generate stubs with: `python -m grpc_tools.protoc -I src/serve --python_out=. --grpc_python_out=. src/serve/sesame.proto`.
168
+
169
+ Auth boundary: interactive login is CLI-only and never runs in the daemon. A Unix socket can be used by any process of the same user (the same boundary as the CLI). HTTP / WS / gRPC are over TCP and require a loopback token generated at startup. POSIX only (Windows UDS is out of scope; stdio / HTTP / WS / gRPC work).
170
+
171
+ ---
172
+
173
+ ## Config directory
174
+
175
+ Precedence: `--config-dir <path>` → `SESAME_HUB3_HOME` → `$XDG_CONFIG_HOME/sesame-hub3` → `~/.config/sesame-hub3`.
176
+
177
+ ```
178
+ ~/.config/sesame-hub3/
179
+ ├── config.json # devices / remotes / default / apiKeyId
180
+ ├── tokens.json # Cognito state (must be gitignored)
181
+ ├── login_state.json # transient state during sign-in
182
+ └── devices.json # dump from the `devices` command
183
+ ```
184
+
185
+ The config schema and the "store all devices in a single `devices{}`" design are in [docs/architecture.md](./docs/architecture.md).
186
+
187
+ ---
188
+
189
+ ## Documentation
190
+
191
+ - [docs/commands.md](./docs/commands.md) — full CLI command reference
192
+ - [docs/library.md](./docs/library.md) — using it as a Node library
193
+ - [docs/architecture.md](./docs/architecture.md) — lineage, design decisions, file layout
194
+ - [docs/migration.md](./docs/migration.md) — migrating from older versions
195
+
196
+ ---
197
+
198
+ ## Known limitations
199
+
200
+ - For long-running use, auto-reconnect (exponential backoff 1s→10s), a token refresh callback, and idle / sleep detection are in place.
201
+ - Only self-learned remotes (`learnEmit`) are supported. Command generation for preset remotes (picked from a manufacturer DB) is not ported. Use `sesame ir learn` to capture a physical remote.
202
+ - autolock cannot be set over the cloud. Use `sesame autolock` over BLE.
203
+ - The only unimplemented op is Stripe billing changes. Every other biz3 op (employees / groups / roles / device groups / key sharing / access control / scheduling / IoT) is available as a command.
204
+ - The default WS stage is `/public`. `/production` is never used (if it lingers in config it is rewritten to `/public` on load).
205
+ - AWS IoT WS requires IPv4. It will not connect on IPv6-only networks.
206
+ - New pairing (registering an unregistered device) is not supported; only operating already-registered devices.
207
+
208
+ ---
209
+
210
+ ## Troubleshooting
211
+
212
+ - `No tokens stored` / `No config at ...`: `sesame init` → `sesame login`, or `sesame migrate`.
213
+ - `UserNotFoundException`: auto sign-up is built in. If it still appears, it is a Cognito-side edge case.
214
+ - `Cognito refresh returned no IdToken`: the refresh token was invalidated (e.g., logged out in the official app). Sign in again.
215
+ - `triggerLock timeout`: wrong `secretKey`, Hub3 offline, or a half-open WS (recovers on auto-reconnect).
216
+ - `learn timeout`: the Hub3 entered REGISTER mode but did not receive a waveform. Move closer or try a different button.
217
+ - `apiKeyId required`: for `webapi` commands, set `apiKeyId` in config.json (issue one in the biz3 dev console).
218
+
219
+ ## See also
220
+
221
+ - [CANDY-HOUSE/biz.candyhouse.co](https://github.com/CANDY-HOUSE/biz.candyhouse.co) — the React admin web "biz3" this is ported from
222
+ - [SesameSDK_iOS_with_DemoApp](https://github.com/CANDY-HOUSE/SesameSDK_iOS_with_DemoApp) / [SesameSDK_Android_with_DemoApp](https://github.com/CANDY-HOUSE/SesameSDK_Android_with_DemoApp) — the official SDKs referenced
package/bin/sesame.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "../src/cli.js";
3
+
4
+ run().catch((err) => {
5
+ console.error("Fatal:", err?.message || err);
6
+ if (process.env.DEBUG) console.error(err?.stack);
7
+ process.exit(1);
8
+ });