@lightupai/polaris 0.0.54 → 0.0.56

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.
package/README.md CHANGED
@@ -121,21 +121,36 @@ Login — both `polaris login --local` and the dashboard — uses Google SSO, so
121
121
 
122
122
  ### Local Slack app setup (optional)
123
123
 
124
- Slack is optional — without `SLACK_APP_TOKEN`, `make dev` just skips the bridge. Set it up to mirror sessions to Slack channels. Slack has no API to create apps, so this is manual (`scripts/setup-slack-app.sh` walks you through it and **appends** to `.env`, so it won't clobber existing values).
124
+ Slack is optional — without `SLACK_APP_TOKEN`, `make dev` just skips the bridge. Set it up to mirror sessions to Slack channels. Slack has no API to create apps, so this is manual.
125
125
 
126
- 1. Go to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App → From scratch**. Name it "Polaris" and pick your dev workspace.
127
- 2. **OAuth & Permissions**: under **Redirect URLs** add `http://localhost:3000/slack/callback` and Save. Under **Bot Token Scopes**, add: `channels:manage`, `channels:join`, `channels:read`, `chat:write`, `users:read`, `users:read.email`.
126
+ 1. Go to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App → From scratch**. Name it "Polaris" and pick a workspace you can install into. (If your workspace requires admin approval to install apps, an admin must approve it — otherwise use a workspace where you're an admin.)
127
+ 2. **OAuth & Permissions Redirect URLs**: add `http://localhost:3000/slack/callback` and click **Save URLs**. Slack accepts `http://localhost` for local dev — just make sure you actually **Save** it. A missing or unsaved redirect URL is the usual cause of `redirect_uri did not match any configured URIs`. Under **Bot Token Scopes**, add: `channels:manage`, `channels:join`, `channels:read`, `chat:write`, `users:read`, `users:read.email`.
128
128
  3. **Socket Mode**: toggle **Enable Socket Mode** on, then generate an app-level token (scope `connections:write`). Copy it — this is `SLACK_APP_TOKEN` (starts with `xapp-`).
129
- 4. **Event Subscriptions**: toggle **Enable Events** on, and under **Subscribe to bot events** add `message.channels`, then Save. (This is what lets Slack messages reach a session.)
129
+ 4. **Event Subscriptions**: toggle **Enable Events** on, and under **Subscribe to bot events** add `message.channels`, then Save. **Required** for Slack messages to reach a session — without it the bridge connects but never receives messages.
130
130
  5. **Basic Information**: copy the **Client ID** and **Client Secret**.
131
- 6. Add all three to `.env`:
131
+ 6. Add to `.env`:
132
132
  ```
133
133
  SLACK_CLIENT_ID=<client-id>
134
134
  SLACK_CLIENT_SECRET=<client-secret>
135
135
  SLACK_APP_TOKEN=xapp-<socket-mode-token>
136
136
  ```
137
- (`SLACK_REDIRECT_URI` defaults to `http://localhost:3000/slack/callback`.)
138
- 7. Reload: `make clean && make dev`, then click **Connect Slack** on the dashboard to install the bot into your workspace.
137
+ `SLACK_REDIRECT_URI` is optional — it defaults to `http://localhost:3000/slack/callback`. Only set it if you register a different URL (e.g. an `ngrok`/`cloudflared` tunnel when you need a public HTTPS callback).
138
+ 7. `make clean && make dev`, then open the dashboard, log in, and click **Connect Slack → Allow** to install the bot. This stores the bot token on your org.
139
+
140
+ ### Running the Slack bridge locally
141
+
142
+ The bridge (`src/slack/bridge.ts`) mirrors session activity to Slack and injects Slack replies back into sessions. It's part of `make dev` (`dev: dev-up api web daemon bridge`), but it only starts once an org is **Slack-connected** — so the first time there's a chicken-and-egg:
143
+
144
+ 1. `make dev` — the bridge is **skipped** ("no Slack-connected org found"), because nothing is connected yet.
145
+ 2. Complete **Connect Slack** on the dashboard (above) to link your org.
146
+ 3. Start the bridge against the now-connected org **without restarting everything**:
147
+ ```sh
148
+ make bridge # → "Starting Slack bridge for org <id>"
149
+ ```
150
+
151
+ After that, the Slack connection lives in Postgres and **survives `make clean`** (which keeps the volume), so subsequent `make clean && make dev` runs start the bridge **automatically** — no separate `make bridge` needed. You'd only reconnect + re-run `make bridge` if you drop the DB volume (`docker compose down -v`).
152
+
153
+ Bridge logs: `/tmp/polaris-bridge.log`.
139
154
 
140
155
  ### Optional
141
156
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightupai/polaris",
3
- "version": "0.0.54",
3
+ "version": "0.0.56",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "polaris": "bin/polaris",
package/src/service/db.ts CHANGED
@@ -34,7 +34,26 @@ export async function createDb(connectionString?: string): Promise<Sql> {
34
34
  return sql;
35
35
  }
36
36
 
37
+ // Arbitrary fixed key for the schema-init advisory lock (issue #117).
38
+ const SCHEMA_LOCK_KEY = 0x504c5253; // "PLRS"
39
+
37
40
  export async function ensureSchema(sql: Sql): Promise<void> {
41
+ // API and web both call this on startup. Serialize concurrent callers with a
42
+ // session-level advisory lock held on a reserved (dedicated) connection, so
43
+ // they don't race on `CREATE TABLE IF NOT EXISTS` — which isn't concurrency
44
+ // safe: two connections can both pass the existence check and then collide on
45
+ // the underlying pg_type creation (issue #117).
46
+ const lock = await sql.reserve();
47
+ try {
48
+ await lock`SELECT pg_advisory_lock(${SCHEMA_LOCK_KEY}::bigint)`;
49
+ await createSchemaTables(sql);
50
+ } finally {
51
+ await lock`SELECT pg_advisory_unlock(${SCHEMA_LOCK_KEY}::bigint)`;
52
+ lock.release();
53
+ }
54
+ }
55
+
56
+ async function createSchemaTables(sql: Sql): Promise<void> {
38
57
  await sql`
39
58
  CREATE TABLE IF NOT EXISTS orgs (
40
59
  id TEXT PRIMARY KEY,