@mercury-fw/channel-google-chat 0.1.0 → 0.1.1

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 (3) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +163 -2
  3. package/package.json +2 -2
package/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # @mercury-fw/channel-google-chat
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 51bd439: `mfw google-chat set-key <key-file> [--subscription <name>]` writes the Google Chat channel's service account key (and its subscription) into the app's env file, the key on one line the way the channel reads it and never printed. The channel's setup uses it in place of the hand-written `sed`/`printf` step.
8
+ - de8b1e7: The README walks through setting up the Chat app step by step (gcloud wherever it can, the two Cloud Console pages field by field) and creates the Pub/Sub subscription with no expiration. A new section covers a subscription Pub/Sub deleted after 31 idle days: how to recreate it and give the service account its role back.
package/README.md CHANGED
@@ -16,8 +16,169 @@ channels: [googleChatChannel],
16
16
  |---|---|
17
17
  | `GOOGLE_CHAT_PUBSUB_SUBSCRIPTION` | `projects/<project>/subscriptions/<subscription>` the Chat app's events arrive on. Empty leaves the channel inert. |
18
18
  | `GOOGLE_CHAT_APP_CLIENT_EMAIL` | The service account the app authenticates as. |
19
- | `GOOGLE_CHAT_APP_PRIVATE_KEY` | That service account's private key. |
19
+ | `GOOGLE_CHAT_APP_PRIVATE_KEY` | That service account's private key, on one line with literal `\n` (step 5 writes it that way). |
20
20
 
21
- Each instance needs a Chat app of its own (its own Google Cloud project, topic, subscription and service account): two instances on one subscription either both answer or split a conversation between them. The [reference instance's README](https://github.com/lucabro81/mercury-fw/tree/main/apps/mercury#setting-up-the-chat-apps-google-cloud-project) has the `gcloud` commands, and the one step Cloud Console only does by hand.
21
+ ## Table of contents
22
+
23
+ - [Setting up the Chat app](#setting-up-the-chat-app)
24
+ - [1. Name things](#1-name-things)
25
+ - [2. Create the project](#2-create-the-project)
26
+ - [3. Create the topic, and let Google Chat publish on it](#3-create-the-topic-and-let-google-chat-publish-on-it)
27
+ - [4. Create the subscription](#4-create-the-subscription)
28
+ - [5. Create the service account and its key](#5-create-the-service-account-and-its-key)
29
+ - [6. Configure the consent screen (Cloud Console)](#6-configure-the-consent-screen-cloud-console)
30
+ - [7. Configure the Chat app (Cloud Console)](#7-configure-the-chat-app-cloud-console)
31
+ - [8. Start and try it](#8-start-and-try-it)
32
+ - [When the subscription disappears](#when-the-subscription-disappears)
33
+
34
+ ## Setting up the Chat app
35
+
36
+ Each Mercury instance needs a Chat app of its own: its own Google Cloud project, Pub/Sub topic, subscription and service account. Two instances on one subscription either both answer or split a conversation between them, each with no memory of the other's half.
37
+
38
+ Everything goes through `gcloud` except two pages of Cloud Console (steps 6 and 7), which have no command or API. You need:
39
+
40
+ - a Google Workspace Business or Enterprise account: Chat apps don't exist for personal Gmail accounts;
41
+ - `gcloud` logged in with that account (`gcloud auth login <you@company.com>`), allowed to create projects and link a billing account;
42
+ - the app with its dependencies installed (`bun install`), for `bunx mfw` in step 5.
43
+
44
+ ### 1. Name things
45
+
46
+ Every command below reads these variables, so set them once in the shell you'll run the steps from:
47
+
48
+ ```bash
49
+ PROJECT_ID=<a new project id, globally unique>
50
+ BILLING_ACCOUNT_ID=<from: gcloud billing accounts list>
51
+ TOPIC=mercury-chat-events
52
+ SUBSCRIPTION=mercury-chat-sub
53
+ SA_NAME=mercury-bot
54
+ SA_EMAIL="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
55
+ ```
56
+
57
+ ### 2. Create the project
58
+
59
+ Pub/Sub needs billing on the project even when its usage stays inside the free tier.
60
+
61
+ ```bash
62
+ gcloud projects create "$PROJECT_ID" --name="Mercury"
63
+ gcloud billing projects link "$PROJECT_ID" --billing-account="$BILLING_ACCOUNT_ID"
64
+ gcloud services enable chat.googleapis.com pubsub.googleapis.com iam.googleapis.com --project="$PROJECT_ID"
65
+ ```
66
+
67
+ ### 3. Create the topic, and let Google Chat publish on it
68
+
69
+ Google Chat delivers the app's events by publishing them on this topic as its own service account, `chat-api-push@system.gserviceaccount.com`, which needs the publisher role there.
70
+
71
+ ```bash
72
+ gcloud pubsub topics create "$TOPIC" --project="$PROJECT_ID"
73
+ gcloud pubsub topics add-iam-policy-binding "$TOPIC" \
74
+ --project="$PROJECT_ID" \
75
+ --member="serviceAccount:chat-api-push@system.gserviceaccount.com" \
76
+ --role="roles/pubsub.publisher"
77
+ ```
78
+
79
+ ### 4. Create the subscription
80
+
81
+ `--expiration-period=never` matters: by default Pub/Sub deletes a subscription nobody has pulled from in 31 days, so an instance that stays off for a month would come back to a `NOT_FOUND` (see [When the subscription disappears](#when-the-subscription-disappears)).
82
+
83
+ ```bash
84
+ gcloud pubsub subscriptions create "$SUBSCRIPTION" --topic="$TOPIC" --expiration-period=never --project="$PROJECT_ID"
85
+ ```
86
+
87
+ ### 5. Create the service account and its key
88
+
89
+ The service account is who Mercury runs as: it reads the subscription and posts to Chat. It needs the subscriber role on the subscription and nothing on the project.
90
+
91
+ ```bash
92
+ gcloud iam service-accounts create "$SA_NAME" --project="$PROJECT_ID" --display-name="Mercury bot"
93
+ gcloud pubsub subscriptions add-iam-policy-binding "$SUBSCRIPTION" \
94
+ --project="$PROJECT_ID" \
95
+ --member="serviceAccount:${SA_EMAIL}" \
96
+ --role="roles/pubsub.subscriber"
97
+ gcloud iam service-accounts keys create key.json --iam-account="$SA_EMAIL"
98
+ ```
99
+
100
+ A service account takes a few seconds to become visible to the rest of Google Cloud: if the binding fails saying the account doesn't exist, wait a moment and run it again.
101
+
102
+ Then, from the app's folder, write the key and the subscription into its `.env` with the app's own CLI, and delete the key file. The command replaces the lines `mfw create` left empty (or an older key), puts the private key on one line the way the channel reads it, and never prints it:
103
+
104
+ ```bash
105
+ bunx mfw google-chat set-key key.json --subscription "projects/${PROJECT_ID}/subscriptions/${SUBSCRIPTION}"
106
+ rm key.json
107
+ ```
108
+
109
+ ### 6. Configure the consent screen (Cloud Console)
110
+
111
+ Open [Google Auth Platform → Branding](https://console.cloud.google.com/auth/branding) with the project selected (the project picker is at the top of the page), click **Get Started**, then:
112
+
113
+ 1. **App name**: what users see, e.g. `Mercury`. **User support email**: your address. Click **Next**.
114
+ 2. **Audience**: pick **Internal**. Click **Next**.
115
+ 3. **Contact Information**: your address. Click **Next**.
116
+ 4. Check **I agree to the Google API Services: User Data Policy**, click **Continue**, then **Create**.
117
+
118
+ No scopes to add: an internal app doesn't list them.
119
+
120
+ ### 7. Configure the Chat app (Cloud Console)
121
+
122
+ Open the Chat API's configuration page for the project, `https://console.developers.google.com/apis/api/chat.googleapis.com/hangouts-chat?project=<PROJECT_ID>` (or **APIs & Services → Enabled APIs & Services → Google Chat API → Configuration**), and set:
123
+
124
+ 1. **Build this Chat app as a Google Workspace add-on**: unchecked (confirm in the dialog if it asks).
125
+ 2. **App name**: the name users search for in Chat (up to 25 characters). **Avatar URL**: an HTTPS link to a square image. **Description**: one line (up to 40 characters).
126
+ 3. **Interactive features**: enabled. Without them nobody can write to the app or click its confirmation buttons.
127
+ 4. **Functionality**: check **Join spaces and group conversations**.
128
+ 5. **Connection settings**: pick **Cloud Pub/Sub** and paste the topic's full name, `projects/<PROJECT_ID>/topics/<TOPIC>`.
129
+ 6. **Visibility**: check **Make this Google Chat app available to specific people and groups in <your domain>** and enter who can use it (people or a group).
130
+ 7. **Logs**: check **Log errors to Logging**, so a delivery error from Chat shows up in the project's logs.
131
+
132
+ Click **Save**. The field names here come from Google's own Pub/Sub quickstart; Console moves things around now and then, so trust the meaning over the exact position.
133
+
134
+ ### 8. Start and try it
135
+
136
+ Start the app (`bunx mfw start`) and check that the channel came up without errors:
137
+
138
+ ```bash
139
+ bunx mfw logs mercury
140
+ ```
141
+
142
+ `[channel] google-chat started` with no `pubsub stream error` after it means Mercury is pulling from the subscription. Then, in Google Chat, start a new chat and search the app's name (it shows up only for the people and groups in **Visibility**), or add it to a space; write to it and it answers.
143
+
144
+ ## When the subscription disappears
145
+
146
+ A subscription created before `--expiration-period=never` was in step 4 still has the default policy, and Pub/Sub deletes it after 31 days without a pull. The channel then logs `NOT_FOUND` on the subscription, while the topic, the service account and the Chat app's configuration are all still there.
147
+
148
+ Set the variables again first, taking them from the app's `.env`: `GOOGLE_CHAT_PUBSUB_SUBSCRIPTION` is `projects/<PROJECT_ID>/subscriptions/<SUBSCRIPTION>`, and `SA_EMAIL` is `GOOGLE_CHAT_APP_CLIENT_EMAIL`. The topic isn't written anywhere in the app: `gcloud pubsub topics list --project="$PROJECT_ID"` shows it (a project made with these steps has only that one).
149
+
150
+ ```bash
151
+ PROJECT_ID=<the part after projects/>
152
+ SUBSCRIPTION=<the part after subscriptions/>
153
+ SA_EMAIL=<GOOGLE_CHAT_APP_CLIENT_EMAIL>
154
+ TOPIC=<the last part of the name the topics list prints>
155
+ ```
156
+
157
+ To tell which piece is missing:
158
+
159
+ ```bash
160
+ gcloud pubsub topics list --project="$PROJECT_ID"
161
+ gcloud pubsub subscriptions list --project="$PROJECT_ID"
162
+ ```
163
+
164
+ If only the subscription is gone, recreate it on the same topic and with the same name, so `GOOGLE_CHAT_PUBSUB_SUBSCRIPTION` doesn't change, then give the service account its subscriber role back (it went away with the subscription):
165
+
166
+ ```bash
167
+ gcloud pubsub subscriptions create "$SUBSCRIPTION" --topic="$TOPIC" --expiration-period=never --project="$PROJECT_ID"
168
+ gcloud pubsub subscriptions add-iam-policy-binding "$SUBSCRIPTION" \
169
+ --project="$PROJECT_ID" \
170
+ --member="serviceAccount:${SA_EMAIL}" \
171
+ --role="roles/pubsub.subscriber"
172
+ ```
173
+
174
+ Then restart the app (`bunx mfw restart`). The messages sent while the subscription was missing are lost, though: Pub/Sub keeps messages only for a subscription that exists.
175
+
176
+ If the topic is gone too, redo steps 3 to 5 and, in step 7, paste the new topic in **Connection settings**.
177
+
178
+ To keep a subscription that's still there from expiring:
179
+
180
+ ```bash
181
+ gcloud pubsub subscriptions update "$SUBSCRIPTION" --expiration-period=never --project="$PROJECT_ID"
182
+ ```
22
183
 
23
184
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mercury-fw/channel-google-chat",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "@mercury-fw/channel-types": ">=0.24.0 <1.0.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@mercury-fw/channel-types": "0.25.0",
37
+ "@mercury-fw/channel-types": "0.28.0",
38
38
  "@mercury-fw/typescript-config": "*",
39
39
  "@types/bun": "^1.4.0",
40
40
  "typescript": "^6.0.3"