@stackbone/cli 0.1.0-alpha.13 → 0.1.0-alpha.15

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.
@@ -0,0 +1,67 @@
1
+ -- 0021_trigger_subscriptions.sql — the inbound side of Stackbone Connect
2
+ -- (feature 89): an operator links a connector polling TRIGGER to a World
3
+ -- workflow, and a polling intake engine starts that workflow for each new item.
4
+ --
5
+ -- This is the emulator's OWN inbound state — deliberately NOT the classic
6
+ -- `automation*` tables (which live in cloud and feed the deprecated `/invoke`
7
+ -- pipeline). The model mirrors that pipeline's SHAPE (config + cursor state +
8
+ -- a delivery journal) without coupling to it: the classic engine stays running
9
+ -- and untouched; its retirement is tied to the World runtime's port to prod.
10
+ --
11
+ -- `trigger_subscriptions` holds the operator-owned link plus its polling state
12
+ -- (the opaque cursor + last-poll marker, owned by the platform; the
13
+ -- remote-subscription id is reserved for a future webhook/push source).
14
+ -- `trigger_deliveries` is the at-least-once dedup journal: one row per
15
+ -- (subscription, provider item) so two overlapping ticks or a mid-restart
16
+ -- re-poll never start the same item's workflow twice.
17
+
18
+ CREATE TABLE IF NOT EXISTS stackbone_platform.trigger_subscriptions (
19
+ id uuid PRIMARY KEY,
20
+ -- Integration id — the SAME id resolves the credential (broker) and the
21
+ -- trigger capability (connector kit). e.g. 'gmail'.
22
+ connector text NOT NULL,
23
+ -- Capability trigger id, e.g. 'message-received'. Not the reserved word
24
+ -- `trigger`, so the column is `trigger_id`.
25
+ trigger_id text NOT NULL,
26
+ -- Which broker grant to poll with: 'app' | 'user:<issuer>:<id>'.
27
+ principal_key text NOT NULL,
28
+ -- The World workflow this link starts.
29
+ workflow_name text NOT NULL,
30
+ -- Optional JSONata event→input mapping; identity when null.
31
+ mapping text,
32
+ enabled boolean NOT NULL DEFAULT true,
33
+ -- Opaque polling cursor (Gmail historyId, etc), platform-owned. Advanced
34
+ -- atomically at the END of a tick.
35
+ poll_cursor jsonb,
36
+ -- Reserved for a future push source (a provider-side subscription id); the
37
+ -- polling path never reads it.
38
+ remote_subscription_id text,
39
+ last_polled_at timestamptz,
40
+ created_at timestamptz NOT NULL DEFAULT now(),
41
+ updated_at timestamptz NOT NULL DEFAULT now()
42
+ );
43
+
44
+ -- The reconcile sweep loads ACTIVE links to arm one repeatable each.
45
+ CREATE INDEX IF NOT EXISTS trigger_subscriptions_enabled_idx
46
+ ON stackbone_platform.trigger_subscriptions (enabled, created_at)
47
+ WHERE enabled;
48
+
49
+ CREATE TABLE IF NOT EXISTS stackbone_platform.trigger_deliveries (
50
+ id uuid PRIMARY KEY,
51
+ subscription_id uuid NOT NULL,
52
+ -- The connector's stable provider item id (Gmail messageId) — the dedup key.
53
+ provider_item_id text NOT NULL,
54
+ status text NOT NULL DEFAULT 'claimed'
55
+ CHECK (status IN ('claimed', 'started', 'rejected')),
56
+ -- The projected World run id once the workflow started.
57
+ run_id text,
58
+ -- Validation/mapping issues when the delivery was rejected.
59
+ issues jsonb,
60
+ created_at timestamptz NOT NULL DEFAULT now(),
61
+ updated_at timestamptz NOT NULL DEFAULT now()
62
+ );
63
+
64
+ -- The at-least-once dedup guarantee: claiming a delivery is an INSERT that
65
+ -- collapses on this unique pair, so a re-polled item is a no-op, not a re-run.
66
+ CREATE UNIQUE INDEX IF NOT EXISTS trigger_deliveries_dedup_idx
67
+ ON stackbone_platform.trigger_deliveries (subscription_id, provider_item_id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackbone/cli",
3
- "version": "0.1.0-alpha.13",
3
+ "version": "0.1.0-alpha.15",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "bin": {