@drawbridge/drawbridge-agents 0.1.58 → 0.1.59
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/claude/CLAUDE.md
CHANGED
|
@@ -478,6 +478,28 @@ failure never does. Sync's step-runner errors the connection on that code during
|
|
|
478
478
|
anywhere transient flips healthy connections to error on a blip; renaming it in either repo
|
|
479
479
|
means dead grants retry into Sentry forever (the Shopify 08-16 incident, ecosystem-wide).
|
|
480
480
|
|
|
481
|
+
**A segment's `connections` rows have one writer, and the api ships first (utils ↔ sync ↔ api
|
|
482
|
+
↔ app-web).** `segment.connections[]` — `{ connection, id, slug, type, url }`, one row per
|
|
483
|
+
connection that publishes the segment — is written ONLY by drawbridge-sync's
|
|
484
|
+
`step.segment.register` (cleared by `step.segment.remove`), through the shared descriptors in
|
|
485
|
+
utils `lib/connections/segment-rows.js`. api and app-web read the rows raw; the `url` is built
|
|
486
|
+
inside the hook, where the settings are decrypted, so nothing downstream may recompute it. Two
|
|
487
|
+
deploy orders, both silent when violated: the api must have **booted** with `schema/segment.js`
|
|
488
|
+
before any sync writes a row (strict validator, `additionalProperties : false` → Mongo 121, row
|
|
489
|
+
lost), and the api's pin must land before sync provisions a workflow, because `enums.step.type`
|
|
490
|
+
derives from the installed utils and the workflow route validates against it ("Document failed
|
|
491
|
+
validation", naming no field). Detail: `drawbridge-docs/reference/connection-hooks.md`.
|
|
492
|
+
|
|
493
|
+
**A system step's workflow is provisioned from the manifest's `trigger` (utils ↔ sync).**
|
|
494
|
+
`ensureSystemWorkflows` in sync walks every system step a manifest declares and creates one
|
|
495
|
+
workflow per step that names a `trigger` — no trigger means nothing fires it, which is how
|
|
496
|
+
Shopify's audit-only token steps stay undispatched. No PUBLISHED manifest carries a trigger yet,
|
|
497
|
+
so sync must not merge ahead of the utils pin bump: on the older package the walk finds no
|
|
498
|
+
trigger, provisions nothing, and Klaviyo connections silently stop getting their daily health
|
|
499
|
+
workflow. Provisioning is idempotent on `(connection, system, title)` with nothing
|
|
500
|
+
unique-indexing it, so a system step's `key` must stay static — a key that varied by account
|
|
501
|
+
would provision a second workflow every time it changed.
|
|
502
|
+
|
|
481
503
|
**The SMS inbound URL is one string two repos must agree on (api ↔ sync ↔ webhooks).**
|
|
482
504
|
`APP_CLIENT_WEBHOOKS_URI + '/connection/drawbridge/sms'` is written to each purchased
|
|
483
505
|
number by api (`route/organization-networking.js`) and re-asserted by sync's daily identity
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Migrations live in the api
|
|
2
|
+
|
|
3
|
+
Every one-off migration and backfill goes in `drawbridge-api/scripts.js`.
|
|
4
|
+
|
|
5
|
+
**The only exception is media processing** — work that needs ffmpeg or sharp to
|
|
6
|
+
open an image or a video. Those dependencies exist in `drawbridge-sync` and
|
|
7
|
+
nowhere else, so a migration that re-encodes a file or extracts a video frame
|
|
8
|
+
has to run there. Nothing else qualifies.
|
|
9
|
+
|
|
10
|
+
"It dispatches queue work" is **not** an exception. The api has BullMQ and Redis
|
|
11
|
+
and already enqueues onto the workers' queues, so a migration that needs a worker
|
|
12
|
+
enqueues the job from the api and lets the worker do it. That is the same split
|
|
13
|
+
every live code path already uses: the api decides, the workers execute.
|
|
14
|
+
|
|
15
|
+
## Why
|
|
16
|
+
|
|
17
|
+
A migration is a thing somebody runs once, under supervision, reading the dry run
|
|
18
|
+
before the real one. Keeping them in one file in one repo means there is one
|
|
19
|
+
place to look on release day, one run-list to work down, and one review surface
|
|
20
|
+
when someone asks what a release will do to production data. Splitting them
|
|
21
|
+
across two repos means the release plan has two homes, and the second one gets
|
|
22
|
+
forgotten — which is exactly what happened to the segment connection rows
|
|
23
|
+
migration.
|
|
24
|
+
|
|
25
|
+
It also means the file that runs migrations cannot break the worker. Sync
|
|
26
|
+
crashed on boot for several days because its `index.js` required a migrations
|
|
27
|
+
file the Dockerfile never copied, and App Platform rolled every deploy back so
|
|
28
|
+
quietly that dev served stale code the whole time.
|
|
29
|
+
|
|
30
|
+
## How
|
|
31
|
+
|
|
32
|
+
- Add the function to `drawbridge-api/scripts.js`, alongside the others.
|
|
33
|
+
- Add a commented invocation to the numbered run-list at the bottom. Nothing runs
|
|
34
|
+
until somebody uncomments a line and deploys.
|
|
35
|
+
- Take `dryRun` and report what it would do. The first run of a migration is a
|
|
36
|
+
read.
|
|
37
|
+
- Add it to the release document in `drawbridge-docs/releases/` for the launch it
|
|
38
|
+
belongs to, with the ordering constraint stated: what has to be deployed before
|
|
39
|
+
it can run, and what breaks if it runs early.
|
|
40
|
+
- If the work needs a worker, enqueue the job the live path enqueues, with the
|
|
41
|
+
same job id shape, so a migration-queued run and a live run coalesce rather
|
|
42
|
+
than doubling.
|
|
43
|
+
|
|
44
|
+
## Media migrations, the one exception
|
|
45
|
+
|
|
46
|
+
A media migration still follows everything above, except it lives in
|
|
47
|
+
`drawbridge-sync/scripts/` as a standalone script run by hand with `ENV_FILE`,
|
|
48
|
+
rather than in a `scripts.js` the service requires at boot. **Sync's `index.js`
|
|
49
|
+
must never require a migrations module** — that coupling is what took the worker
|
|
50
|
+
down.
|
package/package.json
CHANGED