@drawbridge/drawbridge-agents 0.1.61 → 0.1.63

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.
@@ -42,6 +42,20 @@ skill) so it stops living only in tribal memory.
42
42
  granted keys — that string is data, never rename it without a migration.)
43
43
  - Cascade cleanup of dependent rows belongs in a sync change-stream listener, not inline in the
44
44
  API route that triggered the delete (see `cascade-cleanup.md`).
45
+ - **A product is owned through `product.organizations[]`, never through a connection** (utils ↔
46
+ api ↔ sync). `$addToSet` in utils' Shopify `commerce.product` write and api's campaign/ad
47
+ attach routes; `$pull` in ONE place — sync `stream/organization.js`, on organization delete.
48
+ Disconnect (`queue/connection.js`) pulls `connections[]` only, so a disconnected or hook-less
49
+ provider still lists its products by owner (api `route/organization-product.js`). Orphan
50
+ deletion (`lib/orphan-products.js`) needs ALL of: no organizations, no `campaign.products[]`
51
+ or `advertisement.product` ref, and no `order.lines[].productId` naming it — orders survive the
52
+ org cascade on purpose (dev lost three orders' products before the order lookup existed).
53
+ `order.lines[].product` is the product DOCUMENT, resolved by the utils order hook on
54
+ `provider.id` + `provider.slug` + `source.domain`; the raw `productId` is provider-scoped and
55
+ never a join key on its own. Deploy the api (validator) BEFORE sync/utils consumers write
56
+ either field — `additionalProperties:false` rejects the unknown key — and never backfill on
57
+ dev under a validator not yet on `develop`: the next api deploy reverts it and every
58
+ backfilled doc 121s.
45
59
  - A collection with no `queue/<collection>.js` handler is watched but its events are **silently
46
60
  dropped**. Adding a reactive collection means wiring `stream/index.js`, `lib/queue.js`, and
47
61
  `queue/index.js` together.
@@ -77,8 +91,12 @@ skill) so it stops living only in tribal memory.
77
91
  api registers the number's SmsUrl at twilio connect (`lib/twilio.js`) and `scripts.js
78
92
  registerTwilioWebhooks` backfills — a deployed webhooks route with unregistered numbers hears
79
93
  nothing, silently.
80
- - **`audience` picks the FROM-address; `intent` picks the opt-out machinery** (utils ↔ sync ↔
81
- api). `resolveEmailSender` (sync `queue/notification.js`) resolves verified `identity` row →
94
+ - **`audience` picks the FROM-address; `intent` picks the unsubscribe plumbing — and NOTHING
95
+ passes the suppression gate** (utils ↔ sync ↔ api). Every suppression source blocks every
96
+ lead-facing send, the winner claim included: api's draw route refuses up front ("Disqualify
97
+ this draw and draw again"), sync's `canSend` takes no intent (decided 2026-09-23, reversing
98
+ the 09-02 pass-through; a `$ne : 'unsubscribe'` anywhere on that path is the regression).
99
+ `resolveEmailSender` (sync `queue/notification.js`) resolves verified `identity` row →
82
100
  `subAddress( leadSender, organization.shortId )` for lead-facing mail → `accountSender` for
83
101
  member and platform mail. The tag is `shortId`, never `subdomain` — a rename and a custom-plan
84
102
  downgrade both rewrite subdomain, and the from-address is frozen into delivered mail; api's
@@ -519,6 +537,15 @@ api's identity/organization routes); the merged keys keep the old names. Reading
519
537
  `providerSettings({ slug : 'drawbridge' })` anywhere finds no row — it was split on dev
520
538
  2026-09-08 and prod is seeded per-vendor. Detail: `drawbridge-docs/reference/providers.md`.
521
539
 
540
+ - **A step is switched off by the vendors IT declares, not by every vendor its manifest names
541
+ (utils ↔ sync, since utils 0.0.204).** A step declaration may carry `vendors : [ … ]`, a subset
542
+ of its manifest's list (build() refuses a slug the manifest does not name); sync's
543
+ `attempt()` reads that list into `vendorsEnabled({ slug, vendors })` and only falls back to the
544
+ manifest's whole list when the step declares none. `drawbridge` names sendgrid, twilio,
545
+ hubspot and brightdata; its email steps declare sendgrid, sms twilio, segment.sync none. Add a
546
+ drawbridge step without `vendors` and any one of the four switched off refuses it — HubSpot
547
+ off on dev refused every email send for two days (2026-09-21 to 23).
548
+
522
549
  - **The embedded app's install paths ARE `INSTALL_ENDPOINTS`** (utils `lib/connections/contract.js`
523
550
  ↔ drawbridge-shopify-app `app/drawbridge.server.ts`). The api's `POST /connection/:vendor/*`
524
551
  allows exactly those thirteen and 404s anything else; shopify-app does not depend on utils, so
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawbridge/drawbridge-agents",
3
- "version": "0.1.61",
3
+ "version": "0.1.63",
4
4
  "description": "Shared agent-instruction content (rules, code style, conventions) for the drawbridge-* monorepo.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {