@justfortytwo/telegram 0.1.0 → 0.1.2

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
@@ -39,6 +39,10 @@ channel side: /login <code> -> verify(chatId, code) -> bindin
39
39
  owner chat reach the bridge before any binding exists; it is not required once
40
40
  bindings exist.
41
41
 
42
+ Pending challenges are **persisted in the binding store** (not in process
43
+ memory), so a code minted by one process — e.g. the `fortytwo pair` CLI — is
44
+ redeemable by the separately-running bridge. They are single-use and short-TTL.
45
+
42
46
  The contract is intentionally **channel-agnostic** (`ChannelAdapter` in
43
47
  `src/adapter.ts`) so a future Slack / email / SMS adapter implements the same
44
48
  `issueChallenge` / `verify` shape.
@@ -49,8 +53,9 @@ Authorization must work **even when the memory package is absent**, so the
49
53
  binding store is **self-owned** and does not assume the `@justfortytwo/memory`
50
54
  sqlite db exists:
51
55
 
52
- - `SqliteBindingStore` — default; a tiny `better-sqlite3` table in its own db
53
- file (`state/telegram-bindings.db` by default).
56
+ - `SqliteBindingStore` — default; a tiny `better-sqlite3` db in its own file
57
+ (`state/telegram-bindings.db` by default) holding **bindings + pending
58
+ challenges**, so a CLI-issued pairing code reaches the bridge.
54
59
  - `MemoryBindingStore` — in-process Map, for tests / ephemeral use.
55
60
  - `BindingStore` — the injectable interface. Supply a memory-backed
56
61
  implementation later without touching the login flow.
@@ -75,9 +80,13 @@ Install them alongside this package:
75
80
  npm install @justfortytwo/telegram @justfortytwo/memory @justfortytwo/gate
76
81
  ```
77
82
 
78
- The seams where these peers are wired are marked with `// TODO(wire):` in
79
- `src/bridge.ts`, `src/attachments.ts`, and `src/adapters-config.ts`. Until they
80
- are wired, the bridge runs **channel-only** (no memory/jobs) via no-op shims.
83
+ The **memory** data path is wired: the bridge opens + migrates the memory DB at
84
+ startup and **persists each channel event** to `@justfortytwo/memory`; recall
85
+ happens inside the headless `claude` turn via the Memory MCP tools. If the memory
86
+ peer is absent, the bridge degrades to **channel-only** (messages relay but are
87
+ not persisted) rather than refusing to start. The **gate** "Allow _N_h" path
88
+ still uses a local bash-allowlist fallback; wiring it to `@justfortytwo/gate`'s
89
+ exact-command allowlist is the remaining seam.
81
90
 
82
91
  ## Environment
83
92
 
package/dist/adapter.d.ts CHANGED
@@ -25,14 +25,13 @@ export interface ChallengeOptions {
25
25
  now?: () => number;
26
26
  }
27
27
  /**
28
- * Telegram implementation of ChannelAdapter. Codes live in-process (a wedged
29
- * bridge restart drops outstanding codes — acceptable for a short-TTL,
30
- * owner-initiated flow). Verified bindings persist via the injected BindingStore.
28
+ * Telegram implementation of ChannelAdapter. Pending codes AND verified bindings
29
+ * persist via the injected BindingStore, so a code minted in one process (the
30
+ * `fortytwo pair` CLI) is redeemable in another (the running bridge).
31
31
  */
32
32
  export declare class TelegramAdapter implements ChannelAdapter {
33
33
  private readonly store;
34
34
  readonly channelType: ChannelType;
35
- private readonly pending;
36
35
  private readonly ttlSeconds;
37
36
  private readonly digits;
38
37
  private readonly now;
@@ -43,5 +42,4 @@ export declare class TelegramAdapter implements ChannelAdapter {
43
42
  bindingFor(channelUserId: string): Binding | null;
44
43
  /** Remove a persisted binding (logout). */
45
44
  unbind(channelUserId: string): void;
46
- private sweepExpired;
47
45
  }
package/dist/adapter.js CHANGED
@@ -15,14 +15,13 @@
15
15
  // email / SMS adapter implements the same contract.
16
16
  import { randomInt } from 'node:crypto';
17
17
  /**
18
- * Telegram implementation of ChannelAdapter. Codes live in-process (a wedged
19
- * bridge restart drops outstanding codes — acceptable for a short-TTL,
20
- * owner-initiated flow). Verified bindings persist via the injected BindingStore.
18
+ * Telegram implementation of ChannelAdapter. Pending codes AND verified bindings
19
+ * persist via the injected BindingStore, so a code minted in one process (the
20
+ * `fortytwo pair` CLI) is redeemable in another (the running bridge).
21
21
  */
22
22
  export class TelegramAdapter {
23
23
  store;
24
24
  channelType = 'telegram';
25
- pending = new Map(); // code -> challenge
26
25
  ttlSeconds;
27
26
  digits;
28
27
  now;
@@ -33,24 +32,17 @@ export class TelegramAdapter {
33
32
  this.now = opts.now ?? (() => Date.now());
34
33
  }
35
34
  issueChallenge(owner) {
36
- this.sweepExpired();
35
+ this.store.sweepChallenges(this.now());
37
36
  const max = 10 ** this.digits;
38
37
  const code = String(randomInt(0, max)).padStart(this.digits, '0');
39
- this.pending.set(code, { code, owner, expiresAt: this.now() + this.ttlSeconds * 1000 });
38
+ this.store.putChallenge({ code, owner, expiresAt: this.now() + this.ttlSeconds * 1000 });
40
39
  return { code, ttl: this.ttlSeconds };
41
40
  }
42
41
  verify(channelUserId, proof) {
43
- this.sweepExpired();
44
- const code = proof.trim();
45
- const challenge = this.pending.get(code);
42
+ // Single-use + expiry are enforced by the store's atomic takeChallenge.
43
+ const challenge = this.store.takeChallenge(proof.trim(), this.now());
46
44
  if (!challenge)
47
45
  return null;
48
- if (challenge.expiresAt <= this.now()) {
49
- this.pending.delete(code);
50
- return null;
51
- }
52
- // Single-use: consume the code regardless of downstream outcome.
53
- this.pending.delete(code);
54
46
  const binding = {
55
47
  channelType: this.channelType,
56
48
  channelUserId,
@@ -68,12 +60,5 @@ export class TelegramAdapter {
68
60
  unbind(channelUserId) {
69
61
  this.store.remove(this.channelType, channelUserId);
70
62
  }
71
- sweepExpired() {
72
- const t = this.now();
73
- for (const [code, c] of this.pending) {
74
- if (c.expiresAt <= t)
75
- this.pending.delete(code);
76
- }
77
- }
78
63
  }
79
64
  //# sourceMappingURL=adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,8EAA8E;AAC9E,sEAAsE;AACtE,EAAE;AACF,8CAA8C;AAC9C,iFAAiF;AACjF,sEAAsE;AACtE,0BAA0B;AAC1B,sDAAsD;AACtD,8EAA8E;AAC9E,oEAAoE;AACpE,EAAE;AACF,+EAA+E;AAC/E,oDAAoD;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA+BxC;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAMG;IALpB,WAAW,GAAgB,UAAU,CAAC;IAC9B,UAAU,CAAS;IACnB,MAAM,CAAS;IACf,GAAG,CAAe;IAEnC,YAA6B,KAAmB,EAAE,OAAyB,EAAE;QAAhD,UAAK,GAAL,KAAK,CAAc;QAC9C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,cAAc,CAAC,KAAa;QAC1B,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAClE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC,CAAC;QACzF,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,aAAqB,EAAE,KAAa;QACzC,wEAAwE;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAC5B,MAAM,OAAO,GAAY;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,aAAa;YACb,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,OAAO,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;SAC5C,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,wEAAwE;IACxE,UAAU,CAAC,aAAqB;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,2CAA2C;IAC3C,MAAM,CAAC,aAAqB;QAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACrD,CAAC;CACF"}
@@ -5,21 +5,41 @@ export interface Binding {
5
5
  owner: string;
6
6
  boundAt: string;
7
7
  }
8
- /** The seam. Persists channel-id -> owner bindings; everything else injects this. */
8
+ /**
9
+ * A pending pairing challenge. Persisted in the store (not in adapter memory) so
10
+ * a code minted in one process (e.g. `fortytwo pair`) is redeemable in another
11
+ * (the running bridge).
12
+ */
13
+ export interface PendingChallenge {
14
+ code: string;
15
+ owner: string;
16
+ expiresAt: number;
17
+ }
18
+ /** The seam. Persists channel-id -> owner bindings + pending challenges; everything else injects this. */
9
19
  export interface BindingStore {
10
20
  get(channelType: ChannelType, channelUserId: string): Binding | null;
11
21
  put(binding: Binding): void;
12
22
  remove(channelType: ChannelType, channelUserId: string): void;
13
23
  list(channelType?: ChannelType): Binding[];
24
+ /** Persist a pending pairing challenge so any process sharing the store can redeem it. */
25
+ putChallenge(challenge: PendingChallenge): void;
26
+ /** Fetch + CONSUME a challenge by code (single-use); null if absent or expired. */
27
+ takeChallenge(code: string, now: number): PendingChallenge | null;
28
+ /** Drop expired challenges. */
29
+ sweepChallenges(now: number): void;
14
30
  }
15
31
  /** In-memory store — ideal for tests and ephemeral deployments. */
16
32
  export declare class MemoryBindingStore implements BindingStore {
17
33
  private readonly map;
34
+ private readonly challenges;
18
35
  private key;
19
36
  get(channelType: ChannelType, channelUserId: string): Binding | null;
20
37
  put(binding: Binding): void;
21
38
  remove(channelType: ChannelType, channelUserId: string): void;
22
39
  list(channelType?: ChannelType): Binding[];
40
+ putChallenge(challenge: PendingChallenge): void;
41
+ takeChallenge(code: string, now: number): PendingChallenge | null;
42
+ sweepChallenges(now: number): void;
23
43
  }
24
44
  /**
25
45
  * Self-owned sqlite-backed binding store. Uses its own small db file so it does
@@ -33,4 +53,7 @@ export declare class SqliteBindingStore implements BindingStore {
33
53
  put(binding: Binding): void;
34
54
  remove(channelType: ChannelType, channelUserId: string): void;
35
55
  list(channelType?: ChannelType): Binding[];
56
+ putChallenge(challenge: PendingChallenge): void;
57
+ takeChallenge(code: string, now: number): PendingChallenge | null;
58
+ sweepChallenges(now: number): void;
36
59
  }
package/dist/bindings.js CHANGED
@@ -16,6 +16,7 @@ import { createRequire } from 'node:module';
16
16
  /** In-memory store — ideal for tests and ephemeral deployments. */
17
17
  export class MemoryBindingStore {
18
18
  map = new Map();
19
+ challenges = new Map();
19
20
  key(t, u) { return `${t} ${u}`; }
20
21
  get(channelType, channelUserId) {
21
22
  return this.map.get(this.key(channelType, channelUserId)) ?? null;
@@ -30,6 +31,21 @@ export class MemoryBindingStore {
30
31
  const all = [...this.map.values()];
31
32
  return channelType ? all.filter((b) => b.channelType === channelType) : all;
32
33
  }
34
+ putChallenge(challenge) {
35
+ this.challenges.set(challenge.code, challenge);
36
+ }
37
+ takeChallenge(code, now) {
38
+ const c = this.challenges.get(code);
39
+ if (!c)
40
+ return null;
41
+ this.challenges.delete(code); // single-use: consume regardless of expiry
42
+ return c.expiresAt > now ? c : null;
43
+ }
44
+ sweepChallenges(now) {
45
+ for (const [code, c] of this.challenges)
46
+ if (c.expiresAt <= now)
47
+ this.challenges.delete(code);
48
+ }
33
49
  }
34
50
  // Load the native sqlite driver via createRequire so this ESM module can pull a
35
51
  // CommonJS addon without a top-level static import (which would force the native
@@ -54,6 +70,11 @@ export class SqliteBindingStore {
54
70
  bound_at TEXT NOT NULL,
55
71
  PRIMARY KEY (channel_type, channel_user_id)
56
72
  );
73
+ CREATE TABLE IF NOT EXISTS pending_challenges (
74
+ code TEXT PRIMARY KEY,
75
+ owner TEXT NOT NULL,
76
+ expires_at INTEGER NOT NULL
77
+ );
57
78
  `);
58
79
  }
59
80
  get(channelType, channelUserId) {
@@ -83,5 +104,29 @@ export class SqliteBindingStore {
83
104
  : this.db.prepare('SELECT channel_type, channel_user_id, owner, bound_at FROM channel_bindings').all());
84
105
  return rows.map((r) => ({ channelType: r.channel_type, channelUserId: r.channel_user_id, owner: r.owner, boundAt: r.bound_at }));
85
106
  }
107
+ putChallenge(challenge) {
108
+ this.db
109
+ .prepare(`
110
+ INSERT INTO pending_challenges (code, owner, expires_at)
111
+ VALUES (@code, @owner, @expiresAt)
112
+ ON CONFLICT(code) DO UPDATE SET owner = excluded.owner, expires_at = excluded.expires_at
113
+ `)
114
+ .run(challenge);
115
+ }
116
+ takeChallenge(code, now) {
117
+ // Fetch + delete in one transaction so a code is single-use even under a race.
118
+ const consume = this.db.transaction((c) => {
119
+ const row = this.db.prepare('SELECT code, owner, expires_at FROM pending_challenges WHERE code = ?').get(c);
120
+ this.db.prepare('DELETE FROM pending_challenges WHERE code = ?').run(c);
121
+ return row;
122
+ });
123
+ const row = consume(code);
124
+ if (!row)
125
+ return null;
126
+ return row.expires_at > now ? { code: row.code, owner: row.owner, expiresAt: row.expires_at } : null;
127
+ }
128
+ sweepChallenges(now) {
129
+ this.db.prepare('DELETE FROM pending_challenges WHERE expires_at <= ?').run(now);
130
+ }
86
131
  }
87
132
  //# sourceMappingURL=bindings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.js","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bindings.js","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justfortytwo/telegram",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Telegram channel adapter for fortytwo: a long-polling bridge that drives a headless `claude` turn loop per chat, surfaces gate approvals as inline keyboards, and gates inbound access behind a login/pairing binding flow.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "type": "module",
16
16
  "engines": {
17
- "node": ">=18"
17
+ "node": ">=20"
18
18
  },
19
19
  "main": "./dist/index.js",
20
20
  "types": "./dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "./bridge": "./dist/bridge.js"
27
27
  },
28
28
  "bin": {
29
- "fortytwo-telegram-bridge": "./dist/bridge.js"
29
+ "fortytwo-telegram-bridge": "dist/bridge.js"
30
30
  },
31
31
  "files": [
32
32
  "dist",
@@ -61,7 +61,7 @@
61
61
  }
62
62
  },
63
63
  "dependencies": {
64
- "better-sqlite3": "^11.0.0"
64
+ "better-sqlite3": "^12.0.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/better-sqlite3": "^7.6.0",