fullstackgtm 0.39.0 → 0.40.0

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/CHANGELOG.md CHANGED
@@ -7,6 +7,40 @@ The path to 1.0 is planned in [docs/roadmap-to-1.0.md](./docs/roadmap-to-1.0.md)
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.40.0] — 2026-06-23
11
+
12
+ ### Added
13
+
14
+ - **Salesforce reaches full parity with HubSpot.** `create_record` — the
15
+ `enrich acquire` net-new-lead path — is now implemented for Salesforce: it
16
+ resolve-firsts (SOQL search on the mapped match key, create only on a confirmed
17
+ miss), stamps the canonical `ownerId` onto `OwnerId` so a lead is never born
18
+ ownerless, and optionally resolve-or-creates and links the associated account.
19
+ With this, **every write operation works across both providers** — `set_field`,
20
+ `clear_field`, `link_record`, `create_task`, `archive_record`, `merge_records`
21
+ (Salesforce: Account/Contact), and `create_record` (Salesforce: contact/account).
22
+ HubSpot and Salesforce are now equally first-class; the audit → plan → apply
23
+ contract is identical across them. Verified end-to-end against a live Salesforce
24
+ org (create-on-miss, company auto-link, in-run dedup, cross-run resolve-first).
25
+
26
+ ### Fixed
27
+
28
+ - **HubSpot date-field writes no longer false-conflict.** `readField` now
29
+ normalizes `closeDate` the same way `fetchSnapshot` does (`split("T")[0]`), so
30
+ compare-and-set stops seeing spurious drift between the date-only value baked
31
+ into the plan and HubSpot's raw `…T00:00:00Z` read-back. Previously, every
32
+ date-field `set_field` on HubSpot dead-ended in a false `conflict`. (Salesforce
33
+ was already correct here.)
34
+
35
+ ### Documentation
36
+
37
+ - Corrected `docs/api.md`: the Salesforce connector implements the full operation
38
+ set, with its two platform constraints (Account/Contact-only merge, resolve-first
39
+ contact/account create) — replacing a stale "Salesforce skips merge/create" note.
40
+ - Documented the quickest Salesforce token path for one-off / sandbox use via the
41
+ `sf` CLI (`sf org display --verbose --json`), including the short-lived-token
42
+ caveat; durable use still wants the Connected App device flow.
43
+
10
44
  ## [0.39.0] — 2026-06-23
11
45
 
12
46
  ### Added
package/README.md CHANGED
@@ -352,6 +352,18 @@ Device-flow login requires a Connected App in your org — if you're not an admi
352
352
 
353
353
  Writeback needs no extra OAuth scope — applies are gated by the logged-in user's normal object/field permissions.
354
354
 
355
+ **Quickest token for a one-off or sandbox test (the `sf` CLI).** If you already have the [Salesforce CLI](https://developer.salesforce.com/tools/salesforcecli) authenticated to an org, you can skip the Connected App entirely and feed a session token straight in:
356
+
357
+ ```bash
358
+ # --verbose is required to include the access token. Note: the command prints a
359
+ # sensitive-info warning *before* the JSON, so slice from the first '{' when parsing.
360
+ sf org display --target-org <alias> --verbose --json
361
+ # then hand the accessToken + instanceUrl to the CLI (token on stdin, never a flag):
362
+ echo "$ACCESS_TOKEN" | fullstackgtm login salesforce --instance-url "$INSTANCE_URL"
363
+ ```
364
+
365
+ This is a **short-lived session token with no refresh** — ideal for a one-off audit or a sandbox parity test, but it expires within hours and `doctor` will show it as a static login. For durable, unattended use, set up the Connected App device flow above instead (it refreshes silently).
366
+
355
367
  ### Stripe: a restricted key is enough (read-only connector)
356
368
 
357
369
  The Stripe connector only reads customers and subscriptions, and `apply` is read-only by construction. Create a **restricted key** with just **Customers: Read** and **Subscriptions: Read** (Developers → API keys → Create restricted key) instead of pasting a full-access secret key: `echo "$KEY" | fullstackgtm login stripe`.
package/docs/api.md CHANGED
@@ -40,8 +40,8 @@ release.
40
40
  - `GtmConnector` — `{ provider, fetchSnapshot(), applyOperation?, readField?, fetchChanges? }`.
41
41
  - Connectors never silently drop unresolvable records; audits surface them.
42
42
  - `fetchChanges(sinceIso)` returns a partial snapshot; change feeds may omit associations.
43
- - `createHubspotConnector(options)` — read/write/readField/fetchChanges. `applyOperation` implements every `PatchOperationType`: `set_field`, `clear_field`, `link_record`, `create_task`, `create_record` (resolve-first net-new contact/company create — re-checks the dedupe key at apply, never double-creates), `archive_record`, `merge_records` (HubSpot v3 merge — pairwise, irreversible; survivor must belong to the duplicate group). The Salesforce connector skips `merge_records` and `create_record` honestly (platform-specific).
44
- - `createSalesforceConnector(options)` — read/write/readField/fetchChanges; probabilities normalized to 0..1; `applyOperation` implements every operation type.
43
+ - `createHubspotConnector(options)` — read/write/readField/fetchChanges. `applyOperation` implements every `PatchOperationType`: `set_field`, `clear_field`, `link_record`, `create_task`, `create_record` (resolve-first net-new contact/company create — re-checks the dedupe key at apply, never double-creates), `archive_record`, `merge_records` (HubSpot v3 merge — pairwise, irreversible; survivor must belong to the duplicate group). (The Salesforce connector implements the same operation set, with the platform-specific constraints noted below.)
44
+ - `createSalesforceConnector(options)` — read/write/readField/fetchChanges; probabilities normalized to 0..1. `applyOperation` implements every operation type, with two platform constraints: `merge_records` covers **Accounts and Contacts** only (Salesforce exposes no Opportunity merge), and `create_record` resolve-first creates **contacts/accounts** (SOQL search on the match key, create only on a confirmed miss; stamps the canonical `ownerId` onto `OwnerId`).
45
45
  - `createStripeConnector(options)` — read-only billing by design (`applyOperation` returns `skipped`); email domains are the cross-system merge keys. Implements `fetchChanges` (incremental via `created[gte]`).
46
46
 
47
47
  ## Multi-system operations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullstackgtm",
3
- "version": "0.39.0",
3
+ "version": "0.40.0",
4
4
  "description": "Open-source agentic GTM ops framework: canonical GTM data model, pluggable deterministic audits, reviewable dry-run patch plans, approval-gated write-back with conflict detection, and cross-system entity resolution. HubSpot, Salesforce, and Stripe connectors included.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Full Stack GTM LLC <ryan@fullstackgtm.com> (https://fullstackgtm.com)",