mcpField
S
seam-access-grants

seam-access-grants

github.com/seamapiセキュリティ244 回インストール26 週間前に更新
リポジトリ

seam-access-grants について

既存コードベースへの Seam Access Grants の組み込みを案内するコーディングスキルです。予約に応じたアクセス権の作成、更新、削除を扱い、部屋ごとのデバイス対応付けと権限 ID の保存を重視します。

主な機能

  1. 01既存ハンドラーに Seam 呼び出しを追加
  2. 02予約時間に合わせたアクセス権の作成
  3. 03部屋ごとにデバイス ID を対応付け
  4. 04保存済み ID による権限の更新・削除
  5. 05アクセスイベント用 Webhook エンドポイントの追加

活用シーン

  1. 01予約作成時にドアへのアクセス権を付与
  2. 02予約変更後にアクセス時間を調整
  3. 03予約キャンセル時にアクセス権を取り消し

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/seamapi/seam-plugin --skill seam-access-grants

インストール後、Claude Code で/seam-access-grantsを入力して読み込まれたか確認します。

同梱ファイルreferences/production-checklist.mdreferences/troubleshooting.md

詳細

Seam アクセス権限

あなたは Seam 統合のエキスパートエンジニアです。開発者の既存のコードベースに、統合コードを直接記述してください。

アプローチ

  1. 迅速に進めます。 主要なファイル(予約ハンドラー、ルート、モデル)を glob で検索して読み、すぐにコードを書き始めます。
  2. 既存のファイルにコードを記述します。 既存のサービス関数やハンドラー関数に Seam の呼び出しを直接追加します。ラッパーサービスは作成しないでください。
  3. 変更を最小限に抑えます。 Seam の呼び出しが必要なファイルと Webhook のルートだけを変更します。SDK をインストールし、インポートを追加して、呼び出しを追加します。

Access Grants の仕組み

ユーザーの本人情報、対象デバイス、要求するアクセス方法(PIN、モバイルキー)、時間枠を指定してアクセス権限を作成します。Seam がロックに認証情報を設定します。後で更新または削除できるよう、access_grant_id を保存する必要があります。

1. SDK をインストールして初期化する

特定のバージョンに固定しないでください。

npm install seam        # Node.js
pip install seam        # Python
bundle add seam         # Ruby

Next.js での重要事項: モジュールスコープで new Seam() を実行すると、next build が失敗します。遅延ゲッターを使用してください。

import { Seam } from "seam";
let _seam: Seam;
function getSeam() {
  if (!_seam) _seam = new Seam({ apiKey: process.env.SEAM_API_KEY! });
  return _seam;
}

Express または標準の Node.js の場合:

import { Seam } from "seam";
const seam = new Seam({ apiKey: process.env.SEAM_API_KEY });
from seam import Seam
seam = Seam(api_key=os.environ["SEAM_API_KEY"])

2. デバイス ID を取得する

Access Grants は device_id で特定のデバイスを対象にします。**各部屋/ドアは、それぞれ独自のデバイス ID に対応付ける必要があります。**すべての部屋で単一のグローバルデバイスを使ってはいけません。

デバイス ID は次の場所を確認してください。

  • 部屋ごとの環境変数:SEAM_DEVICE_ROOM_101、SEAM_DEVICE_ID_ROOM_A1 など
  • アプリのデータモデル(例:room.seamDeviceId、unit.deviceId)

**対応付けが見つからない場合は、処理を失敗させてください。**グローバルデバイスにフォールバックしてはいけません。間違ったドアへのアクセスを許可するより、処理を失敗させるほうが適切です。

3. 予約作成時にアクセス権限を作成する

作成関数の中に直接追加します。予約オブジェクトに access_grant_id を保存してください。

// Inside createBooking(), after saving the booking:
const deviceId = getDeviceIdForRoom(room);  // Must resolve per-room
if (!deviceId) {
  throw new Error(`No Seam device configured for room ${room.id}`);
}
try {
  const accessGrant = await seam.accessGrants.create({
    user_identity: {
      full_name: guest.name,
      email_address: guest.email
    },
    device_ids: [deviceId],
    requested_access_methods: [
      { mode: "code" }           // PIN code
      // { mode: "mobile_key" }  // Add for mobile key + Instant Key
    ],
    starts_at: booking.checkIn,
    ends_at: booking.checkOut
  });
  booking.seamAccessGrantId = accessGrant.access_grant_id;
} catch (err) {
  console.error("Seam access grant failed:", err);
  // Consider: should this fail the booking? If access is required, throw.
}
# Inside create_booking(), after saving:
device_id = get_device_id_for_room(room)  # Must resolve per-room
if not device_id:
    raise ValueError(f"No Seam device configured for room {room.id}")
try:
    access_grant = seam.access_grants.create(
        user_identity={"full_name": guest.name, "email_address": guest.email},
        device_ids=[device_id],
        requested_access_methods=[{"mode": "code"}],
        starts_at=booking.check_in,
        ends_at=booking.check_out
    )
    booking.seam_access_grant_id = access_grant.access_grant_id
except Exception as e:
    print(f"Seam access grant failed: {e}")
    # Consider: should this fail the booking? If access is required, raise.

注意点

  • access_grant_id を保存してください。 更新と削除に必要です。予約モデルにこのフィールドがない場合は追加してください。値が null/undefined の場合、権限の作成に失敗しており、再試行が必要です。
  • グローバルデバイスにフォールバックしてはいけません。 各部屋を専用のデバイスに対応付ける必要があります。間違った部屋へのアクセスを許可するより、アクセスを許可しないほうが適切です。
  • user_identity に指定するのは full_name と email_address であり、name と email ではありません。
  • device_ids は配列です。1 回の呼び出しで複数のドアへのアクセスを許可できます。
  • requested_access_methods では、PIN に "code"、モバイルキーと Instant Key に "mobile_key" を指定します。
  • 失敗時の動作を決めてください。 予約にアクセスが必須(例:ホテルの部屋)である場合は、Seam の処理が失敗したら例外をスローし、コードが使えないまま予約が確定しないようにします。アクセスが任意(例:ジム)である場合は、ログを記録して処理を続けます。

4. 予約変更時にアクセス権限を更新する

if (booking.seamAccessGrantId) {
  await seam.accessGrants.update({
    access_grant_id: booking.seamAccessGrantId,
    starts_at: booking.checkIn,
    ends_at: booking.checkOut
  });
}

5. キャンセル時にアクセス権限を削除する

if (booking.seamAccessGrantId) {
  await seam.accessGrants.delete({
    access_grant_id: booking.seamAccessGrantId
  });
}
if booking.seam_access_grant_id:
    seam.access_grants.delete(
        access_grant_id=booking.seam_access_grant_id
    )

6. Webhook エンドポイントを追加する

コードベースにある既存の Webhook パターンに従ってください。

router.post("/seam", (req, res) => {
  const { event_type, ...data } = req.body;
  switch (event_type) {
    case "access_code.set_on_device":
      console.log("PIN set on lock:", data.access_code_id);
      break;
    case "access_code.failed_to_set_on_device":
      console.log("PIN failed:", data.access_code_id);
      break;
    case "device.disconnected":
      console.log("Lock offline:", data.device_id);
      break;
  }
  res.json({ received: true });
});

7. 関数を async にする

サービス関数を async にし、呼び出し元で await するように更新します。

問題が発生した場合は、references/troubleshooting.md を読んでください。本番環境に向けた準備については、references/production-checklist.md を読んでください。

コメント