@hraness/ghostget 0.17.6 → 0.18.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/CHANGELOG.md +301 -0
- package/README.md +16 -9
- package/dist/apple-photos-client.js +2 -1
- package/dist/beeper-client.js +2 -1
- package/dist/client.js +1 -0
- package/dist/imessage-direct-install-2gm3kge7.js +324 -0
- package/dist/index-01eeae9e.js +5 -0
- package/dist/index-2ymnp8xv.js +145 -0
- package/dist/index-en5hycxp.js +175 -0
- package/dist/{index-cytf8d9p.js → index-hfbygww8.js} +1 -1
- package/dist/index-n4szk3nw.js +50 -0
- package/dist/index-yq6maz71.js +1105 -0
- package/dist/index-z1w83f81.js +4 -0
- package/dist/index.js +4 -47
- package/dist/messaging-automation-api.js +21 -0
- package/dist/messaging-automation-j4274hvc.js +609 -0
- package/dist/messaging-native-install-8w1j36ah.js +16 -0
- package/dist/messaging.js +1 -0
- package/dist/omni-client.js +1 -0
- package/dist/whatsapp-automation-runtime-hgh1e9rm.js +845 -0
- package/dist/whatsapp-client.js +1 -0
- package/docs/control-panel.md +147 -0
- package/docs/imessage-direct-provider.md +31 -7
- package/docs/messaging-automation.md +103 -0
- package/package.json +66 -7
- package/skills/ghostget/SKILL.md +3 -1
- package/skills/ghostget/references/control-panel.md +43 -0
- package/skills/ghostget/references/install.md +5 -5
- package/skills/ghostget/references/linkedin-adapter.md +222 -12
- package/skills/ghostget/references/platform-patterns.md +1 -1
- package/src/args.ts +18 -5
- package/src/assets/adapters/imessage/wrench-web-adapter.json +126 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.json +1 -1
- package/src/assets/adapters/whatsapp/wrench-web-adapter.json +144 -0
- package/src/assets/messaging-runtime/NOTICE.txt +2580 -0
- package/src/assets/messaging-runtime/imsg-darwin-arm64.gz +0 -0
- package/src/assets/messaging-runtime/phone-number-info.plist.gz +0 -0
- package/src/assets/messaging-runtime/phone-number-metadata.json.gz +0 -0
- package/src/assets/messaging-runtime/phone-number-privacy.plist.gz +0 -0
- package/src/assets/messaging-runtime/wacli-darwin-arm64.gz +0 -0
- package/src/auth.ts +35 -1
- package/src/beeper-client-types.ts +1 -1
- package/src/cli.ts +18 -0
- package/src/confirmed-write-platform.ts +16 -1
- package/src/control/account-revision.ts +16 -0
- package/src/control/activity.ts +104 -0
- package/src/control/approval-broker.ts +59 -0
- package/src/control/approval-client.ts +49 -0
- package/src/control/bundled-interfaces.ts +20 -0
- package/src/control/cli.ts +20 -0
- package/src/control/connections.ts +87 -0
- package/src/control/credential-helper.ts +152 -0
- package/src/control/helper.ts +79 -0
- package/src/control/interface-cli.ts +22 -0
- package/src/control/interface-json.ts +94 -0
- package/src/control/interface-schema.ts +120 -0
- package/src/control/interfaces.ts +438 -0
- package/src/control/protocol.ts +182 -0
- package/src/control/service.ts +104 -0
- package/src/control/validation.ts +103 -0
- package/src/control/vault.ts +105 -0
- package/src/control/web-gateway.ts +62 -0
- package/src/control/web-policy.ts +56 -0
- package/src/ghostget.ts +18 -4
- package/src/messaging-automation-api.ts +12 -0
- package/src/messaging-automation-descriptors.ts +29 -0
- package/src/messaging-automation-factory.ts +148 -0
- package/src/messaging-automation-server.ts +183 -0
- package/src/messaging-automation-types.ts +155 -0
- package/src/messaging-automation-validation.ts +110 -0
- package/src/messaging-automation.ts +356 -0
- package/src/messaging-runtime.ts +3 -0
- package/src/oauth-google.ts +11 -5
- package/src/omni-runtime.ts +18 -3
- package/src/operation-permission-store.ts +92 -0
- package/src/operation-permission.ts +308 -0
- package/src/pinned-https.ts +5 -0
- package/src/plugins/imessage-direct/plugin.ts +12 -1
- package/src/plugins/imessage-direct/vendor/0003-feat-rpc-add-no-fetch-rich-cards.patch +276 -0
- package/src/plugins/imessage-direct/vendor/provenance.json +84 -10
- package/src/plugins/linkedin-web/plugin.ts +1 -1
- package/src/plugins/whatsapp-linked-device/plugin.ts +7 -2
- package/src/plugins/whatsapp-linked-device/vendor/0001-ghostget-private-messaging.patch +1093 -0
- package/src/plugins/whatsapp-linked-device/vendor/README.md +39 -0
- package/src/plugins/whatsapp-linked-device/vendor/provenance.json +45 -0
- package/src/provider-http.ts +11 -3
- package/src/provider-plugin-contract-identity.ts +2 -2
- package/src/provider-plugin-import-analysis.ts +52 -0
- package/src/provider-plugin-module-analysis.ts +21 -1
- package/src/provider-plugin-registry.ts +4 -8
- package/src/provider-plugin.ts +18 -8
- package/src/providers/imessage-automation.ts +250 -0
- package/src/providers/imessage-direct-install.ts +7 -0
- package/src/providers/imessage-direct-runtime.ts +32 -2
- package/src/providers/imessage-direct.ts +13 -3
- package/src/providers/linkedin-contact-failure.ts +21 -0
- package/src/providers/linkedin-contact-platform.ts +8 -1
- package/src/providers/linkedin-contact-program.ts +34 -5
- package/src/providers/linkedin-web-contact.ts +1223 -35
- package/src/providers/linkedin-web-profile-browser.ts +659 -45
- package/src/providers/linkedin-web-runtime.ts +1 -0
- package/src/providers/linkedin-web.ts +46 -2
- package/src/providers/messaging-native-artifacts.ts +38 -0
- package/src/providers/messaging-native-install.ts +75 -0
- package/src/providers/whatsapp-automation-runtime.ts +240 -0
- package/src/providers/whatsapp-automation.ts +153 -0
- package/src/read-client.ts +12 -2
- package/src/runtime.ts +81 -9
- package/src/state-helper.ts +2 -0
- package/src/storage.ts +71 -1
- package/src/usage.ts +9 -1
- package/src/version.ts +1 -1
- package/src/web-session-contract-definitions.ts +1 -1
- package/tsconfig.json +3 -0
|
@@ -232,23 +232,55 @@ relationship on that vanity from the profile page. Current LinkedIn pages are
|
|
|
232
232
|
SDUI/RSC and often omit classic `bpr-guid-*` Profile embeds. The binder
|
|
233
233
|
therefore walks both those Voyager code payloads and `window.__como_rehydration__`.
|
|
234
234
|
Current pages assign that global as either a JSON object (`= { … }`) or an RSC
|
|
235
|
-
flight array (`= [ "1:I[…]\\n2:{…}" ]`).
|
|
236
|
-
flight
|
|
235
|
+
flight array (`= [ "1:I[…]\\n2:{…}" ]`). Some current arrays also carry a
|
|
236
|
+
non-flight SDUI string slot (not `1:…` rows) that still contains
|
|
237
|
+
`networkDistance` and `vieweeMemberUrn`. The binder accepts both assignment
|
|
238
|
+
shapes, decodes flight rows that carry JSON objects, arrays, or JSON strings,
|
|
239
|
+
feeds non-flight string slots through the same bootstrap decoder, and treats
|
|
237
240
|
`memberDistance`, `networkDistance`, or `distance` of `DISTANCE_1`,
|
|
238
241
|
`1`, or `"1"` as first-degree when that value is joined to the requested vanity
|
|
239
|
-
or its profile URN (`entityUrn`, `objectUrn`, `profileUrn`,
|
|
240
|
-
|
|
242
|
+
or its profile URN (`entityUrn`, `objectUrn`, `profileUrn`, `vieweeMemberUrn`,
|
|
243
|
+
or `vieweeProfileId` plus vanity). Current Como trees can nest around depth 60,
|
|
244
|
+
so the walk keeps a node ceiling and a depth ceiling of 128 instead of aborting
|
|
245
|
+
at depth 32. Distance may appear on PROFILE_VIEW breadcrumb or RSC string rows,
|
|
246
|
+
including multi-escaped Como fragments such as `networkDistance\":1` beside a
|
|
247
|
+
`vieweeMemberUrn` or member id that is not the same `fsd_profile` URN bound
|
|
248
|
+
from `vieweeProfileId`. A unique first-degree distance on that viewee join is
|
|
249
|
+
accepted. Incidental viewer or other `fsd_profile` URNs
|
|
250
|
+
in the same breadcrumb do not steal identity. Empty, missing, ambiguous, or
|
|
251
|
+
contradictory distances stay fail-closed.
|
|
241
252
|
|
|
242
253
|
When the same page already embeds Contact-info fields, including a labeled
|
|
243
254
|
Email row, the operation projects those fields and does not issue a second
|
|
244
|
-
fetch.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
255
|
+
fetch. Long SDUI strings used as field labels are skipped instead of aborting
|
|
256
|
+
the profile-stage walk. Otherwise it first inspects the page's exact
|
|
257
|
+
Contact-info NavigateToScreen action. A reviewed action still admits only
|
|
258
|
+
the ProfileContactDetailsOverlay URL (`sduiid` equal to that overlay
|
|
259
|
+
`screenId`). Adapter 1.36.2 then clicks the unique accessible name
|
|
260
|
+
`Contact info` on the already-loaded 1st-degree profile and projects Email
|
|
261
|
+
from that modal DOM, including when that control's `href` matches
|
|
262
|
+
`/overlay/contact-info/` and contained Chrome follows that reviewed vanity
|
|
263
|
+
overlay pathname after click. Malformed or unsupported action fields stop
|
|
264
|
+
the operation. Zero or two-plus matching controls, a path other than the
|
|
265
|
+
bound profile or `/in/:publicIdentifier/overlay/contact-info/`, or a
|
|
266
|
+
missing or ambiguous dialog, fail closed. The contained path does not mint
|
|
267
|
+
a synthetic navigation POST or track headers, and it does not fetch that
|
|
268
|
+
overlay href as a navigation GET. Only when the
|
|
269
|
+
action is absent
|
|
270
|
+
does it use a page-resolved GraphQL `queryId` for
|
|
271
|
+
`voyagerIdentityDashProfileContactInfo`, when the HTML contains exactly one
|
|
272
|
+
decorated revision. Variables are exactly `(profileUrn:{urn})`. When that
|
|
273
|
+
queryId is absent, or when the GraphQL GET returns a reviewed HTTP 403
|
|
274
|
+
`text/html` rejection, the operation GETs the exact vanity
|
|
275
|
+
`/in/:publicIdentifier/overlay/contact-info/` overlay with RSC browser
|
|
276
|
+
binding. ScreenId-only and `profileUrn`-bound
|
|
277
|
+
`/flagship-web/rsc-action/actions/navigation` overlay GET URLs stay rejected
|
|
278
|
+
because live dormant sessions return HTTP 500 `application/octet-stream`.
|
|
279
|
+
Classic `/voyager/api/identity/profiles/{vanity}/profileContactInfo` now
|
|
280
|
+
returns HTTP 410 and is rejected. The executable contract is those reviewed
|
|
281
|
+
first-party reads, the reviewed Contact info click and modal snapshot, or
|
|
282
|
+
the page-embedded fields. It accepts no caller-selected RSC body, selector,
|
|
283
|
+
or script. This contact read does not message, connect, or InMail.
|
|
252
284
|
|
|
253
285
|
The projection returns `email` when LinkedIn shows it, plus any of the vanity
|
|
254
286
|
profile link, connected-since date, phone numbers, websites, and birthday.
|
|
@@ -273,6 +305,184 @@ string still carried vanity-joined `networkDistance: 1` next to
|
|
|
273
305
|
array form and still uses `queryName` when the page embeds no decorated
|
|
274
306
|
queryId.
|
|
275
307
|
|
|
308
|
+
A 2026-09-10 signed-in capture of another 1st-degree profile still bound
|
|
309
|
+
`profiles.read` and still omitted classic `entityUrn` / `objectUrn` /
|
|
310
|
+
`profileUrn` keys on vanity records. Those records carried `vanityName`,
|
|
311
|
+
`vieweeProfileId`, and `isSelfView` instead, and the live Como tree reached
|
|
312
|
+
about depth 59 with far fewer than the node ceiling. The depth-32 abort treated
|
|
313
|
+
that page as contract-drift. After a deeper walk, identity still failed because
|
|
314
|
+
the binder required a classic URN on the vanity record and required
|
|
315
|
+
`networkDistance` on a decoded object. Adapter 1.24.0 joins `vieweeProfileId`
|
|
316
|
+
plus vanity and reads breadcrumb or RSC string-row distance.
|
|
317
|
+
|
|
318
|
+
A 2026-09-11 signed-in capture of another 1st-degree profile still bound
|
|
319
|
+
`profiles.read` and still reached a unique `vieweeProfileId` profile URN after
|
|
320
|
+
the 1.24.0 walk. `contacts.read` then failed closed because relationship
|
|
321
|
+
distance sat on a PROFILE_VIEW breadcrumb next to `vieweeMemberUrn` / member
|
|
322
|
+
ids, not on a vanity or `fsd_profile` record the binder treated as the same
|
|
323
|
+
target. Adapter 1.25.0 joins that unique viewee distance, including when the
|
|
324
|
+
breadcrumb also carries an incidental viewer URN, and still fails closed for
|
|
325
|
+
self, non-first-degree, and contradictory distances.
|
|
326
|
+
|
|
327
|
+
A later 2026-09-11 signed-in capture of another 1st-degree profile still bound
|
|
328
|
+
`profiles.read` and still joined `vieweeProfileId` identity after the 1.25.0
|
|
329
|
+
walk. `contacts.read` then failed closed because PROFILE_VIEW breadcrumbs kept
|
|
330
|
+
`networkDistance` and `vieweeMemberUrn` in multi-escaped Como string rows
|
|
331
|
+
(`networkDistance\":1`), so the walk produced no distance records for the
|
|
332
|
+
viewee join. Adapter 1.26.0 peels those JSON string escapes and reads the
|
|
333
|
+
escaped key/value form. Self, non-first-degree, and contradictory distances
|
|
334
|
+
still fail closed.
|
|
335
|
+
|
|
336
|
+
A later 2026-09-11 signed-in capture of another 1st-degree profile still bound
|
|
337
|
+
`profiles.read` and still joined `vieweeProfileId` identity after the 1.26.0
|
|
338
|
+
walk. `contacts.read` then failed closed because distance lived in Como
|
|
339
|
+
rehydration array slot `[6]`, a ~25KB SDUI string with `networkDistance` and
|
|
340
|
+
`vieweeMemberUrn`. That slot was not an RSC flight, so
|
|
341
|
+
`decodeComoRehydrationValue` discarded it (`[]`) before the 1.26.0 peel.
|
|
342
|
+
`decodeStringBootstrap` already recovered the distance record from the same
|
|
343
|
+
string. Adapter 1.27.0 feeds non-flight Como string slots through that
|
|
344
|
+
decoder and still routes true RSC flights through `decodeRscFlightRecords`.
|
|
345
|
+
Self, non-first-degree, and contradictory distances still fail closed.
|
|
346
|
+
|
|
347
|
+
A later signed-in capture of a known 1st-degree profile still bound
|
|
348
|
+
identity, profile HTML, and distance, but Contact-info GraphQL returned
|
|
349
|
+
HTTP 403 `text/html` and the page still omitted
|
|
350
|
+
`voyagerIdentityDashProfileContactInfo.<32hex>`. The signed-in UI opens
|
|
351
|
+
Contact info through `ProfileContactDetailsOverlay`, not GraphQL.
|
|
352
|
+
Adapter 1.28.0 GETs that overlay with the bound `profileUrn` when queryId
|
|
353
|
+
is absent or after that reviewed GraphQL rejection, and projects Email
|
|
354
|
+
from the RSC or SDUI overlay payload. ScreenId-only overlay URLs stay
|
|
355
|
+
rejected. Self, non-first-degree, and contradictory distances still fail
|
|
356
|
+
closed.
|
|
357
|
+
|
|
358
|
+
A later signed-in capture of the same 1st-degree path still bound
|
|
359
|
+
identity and distance, but the 1.28.0 navigation GET returned HTTP 500
|
|
360
|
+
`application/octet-stream` for screenId-only, `profileUrn`-bound, and
|
|
361
|
+
html variants. `/in/:publicIdentifier/overlay/contact-info/` returned
|
|
362
|
+
HTML 200 for the signed-in Contact-info modal. Long SDUI strings in
|
|
363
|
+
profile HTML also aborted the best-effort embedded walk at profile
|
|
364
|
+
stage and misreported as relationship-binding contract-drift. Adapter
|
|
365
|
+
1.29.0 skips non-bounded field labels during that walk and GETs the
|
|
366
|
+
exact vanity overlay path with RSC headers instead of the 500
|
|
367
|
+
navigation route. GraphQL Contact-info remains a 403 `text/html` path
|
|
368
|
+
when a unique queryId is present. Self, non-first-degree, and
|
|
369
|
+
contradictory distances still fail closed.
|
|
370
|
+
|
|
371
|
+
A later 2026-09-11 smoke of the same 1st-degree path after adapter 1.29.0
|
|
372
|
+
still bound identity and distance, and the vanity overlay GET returned
|
|
373
|
+
HTML 200. That body was the signed-in profile HTML shell (~500KB+): no
|
|
374
|
+
projectable Email, no mailto, and no Contact-info JSON or RSC flight.
|
|
375
|
+
GraphQL Contact-info stayed HTTP 403 `text/html` with `queryId=null`.
|
|
376
|
+
The live Contact-info Email still appears only after the headed UI opens
|
|
377
|
+
the modal. Dormant contained Chrome stays GET-only and cannot mint that
|
|
378
|
+
client-filled payload. Adapter 1.30.0 treats an HTML-200 shell as
|
|
379
|
+
omitted Contact-info fields after 1st-degree binding, still projects
|
|
380
|
+
overlay HTML that carries Como Email, a unique mailto, or an RSC/SDUI
|
|
381
|
+
flight, and keeps `/flagship-web/rsc-action/actions/navigation` overlay
|
|
382
|
+
GETs rejected.
|
|
383
|
+
|
|
384
|
+
A later headed signed-in capture of the same 1st-degree Contact-info
|
|
385
|
+
click showed Email in the modal. The first network response that
|
|
386
|
+
contained the Email label was POST
|
|
387
|
+
`/flagship-web/rsc-action/actions/navigation?screenId=com.linkedin.sdui.flagshipnav.profile.ProfileContactDetailsOverlay&sduiid=com.linkedin.sdui.flagshipnav.profile.ProfileContactDetailsOverlay`
|
|
388
|
+
with `Accept: */*`, `Content-Type: application/json`, no RSC or Next
|
|
389
|
+
router headers, and JSON body keys `clientArguments` and `isModal`. The
|
|
390
|
+
response was HTTP 200 `application/octet-stream` RSC flight. Headed
|
|
391
|
+
capture bound `sduiid` to that same overlay `screenId` constant. Dormant
|
|
392
|
+
profile HTML NavigateToScreen for Contact info carries `pageKey`
|
|
393
|
+
`profile_view_base_contact_details` and `requestedArguments.payload`
|
|
394
|
+
(`vanityName`, `givenName`, `familyName`, `isVanityNameResolved`) but
|
|
395
|
+
omits `sduiid`. Adapter 1.31.0 POSTs the exact allowlisted URL after
|
|
396
|
+
1st-degree bind, peels reviewed payload keys, and copies `$type` /
|
|
397
|
+
`requestedStateKeys` / `requestMetadata` only when those reviewed fields
|
|
398
|
+
are already on the action. It does not invent a stolen `sduiid`, `$type`,
|
|
399
|
+
or `requestMetadata`. A different `sduiid` fails closed. GraphQL
|
|
400
|
+
Contact-info stays a 403 `text/html` fallback. Navigation overlay GETs
|
|
401
|
+
stay rejected. The vanity overlay GET remains HTML-shell honesty when
|
|
402
|
+
the profile page omits that NavigateToScreen action. Soft-labels stay.
|
|
403
|
+
Keep cookies, `li_at`, CSRF, `JSESSIONID`, live emails, and raw HARs out
|
|
404
|
+
of Git.
|
|
405
|
+
|
|
406
|
+
A later signed-in smoke after adapter 1.31.0 still bound 1st-degree
|
|
407
|
+
distance and selected the navigation POST family, but live
|
|
408
|
+
NavigateToScreen `requestedArguments` keeps `requestMetadata` a sibling
|
|
409
|
+
of `payload` and uses `$type` values `proto.sdui.actions.requests.RequestedArguments`
|
|
410
|
+
and `proto.sdui.common.RequestMetadata`. Treating `requestMetadata` as an
|
|
411
|
+
unreviewed extra key, or rejecting `proto.sdui.*` in favor of
|
|
412
|
+
`com.linkedin.*` only, aborted before POST. A payload-only body then
|
|
413
|
+
returned HTTP 500. Adapter 1.32.0 copies that reviewed sibling shape,
|
|
414
|
+
lifts headed nested `payload.requestMetadata` to the sibling placement
|
|
415
|
+
when the two agree, and admits `proto.sdui.*` types only on this overlay
|
|
416
|
+
POST body. Extra keys and unrelated proto prefixes still fail closed.
|
|
417
|
+
|
|
418
|
+
A later signed-in smoke after adapter 1.32.0 peeled that sibling
|
|
419
|
+
`proto.sdui` shape as `kind=action`, then the POST still returned HTTP
|
|
420
|
+
500 `text/html`. The body sent empty sibling `RequestMetadata{$type}`
|
|
421
|
+
only. Headed 200 Email capture `POST-navigation-body-shape-20260912.md`
|
|
422
|
+
nests `requestMetadata` under `payload` with `$type`, `states: []`,
|
|
423
|
+
overlay `screenId`, and `knownTemplates: []`, and keeps
|
|
424
|
+
`clientArguments.$type` plus `requestedStateKeys: []`. Adapter 1.33.0
|
|
425
|
+
emits that exact headed shape, including when dormant HTML omits
|
|
426
|
+
metadata, copies reviewed string lists when the page already has them,
|
|
427
|
+
and does not invent opaque state objects. Contained Chrome already
|
|
428
|
+
sends `Accept: */*`, `Content-Type: application/json`, and session
|
|
429
|
+
`csrf-token`; it does not mint `X-Li-*` track values. The query string
|
|
430
|
+
stays `sduiid=` matching overlay `screenId`. If a later 500 persists
|
|
431
|
+
after this exact body, the remaining gap is headed-only non-empty
|
|
432
|
+
`states` / `knownTemplates`, not sibling placement.
|
|
433
|
+
|
|
434
|
+
A later signed-in smoke after adapter 1.33.0 kept that exact headed
|
|
435
|
+
body and still returned HTTP 500 `text/html` from contained Chrome.
|
|
436
|
+
The POST ran from the signed-in origin fetch context, not the loaded
|
|
437
|
+
profile document, so it omitted page-instance headers the SPA sets.
|
|
438
|
+
Adapter 1.34.0 opens the exact reviewed profile URL, copies a unique
|
|
439
|
+
`d_flagship3_profile*` `x-li-page-instance` from observed same-origin
|
|
440
|
+
rsc-action or voyager requests or that document, and forwards optional
|
|
441
|
+
`x-li-track` (`mpName` `web` or `voyager-web`),
|
|
442
|
+
`x-li-application-version`, `x-li-application-instance`,
|
|
443
|
+
`x-li-anchor-page-key`, and `x-li-rsc-stream=true` only when the same
|
|
444
|
+
observation already has those values.
|
|
445
|
+
|
|
446
|
+
A later signed-in smoke after adapter 1.34.0 kept that exact headed
|
|
447
|
+
body and forwarded page-instance, track (`mpName=web`), application
|
|
448
|
+
version/instance, anchor page key, and `rscStream=true`, then still
|
|
449
|
+
returned HTTP 500 `text/html`. The same contained-browser
|
|
450
|
+
`/flagship-web/rsc-action/` observations on the bound profile already
|
|
451
|
+
carried `x-li-page-instance-tracking-id`, `x-li-pageforestid`,
|
|
452
|
+
`x-li-traceparent`, and `x-li-tracestate`; 1.34.0 left those names off.
|
|
453
|
+
Adapter 1.35.0 copies those original strings from the same selected
|
|
454
|
+
rsc-action observation under a reviewed allowlist, copies
|
|
455
|
+
`x-li-layout-tree` only when that observation has it, and does not mint
|
|
456
|
+
any of those values when they are absent. Missing or malformed observed
|
|
457
|
+
values fail closed before POST. Live query key stays `sduiid=` (headed
|
|
458
|
+
200 Email POST and public SDUI `server-request` / `pagination` routes);
|
|
459
|
+
`sduid=` notes are transcription typos. Missing or ambiguous
|
|
460
|
+
page-instance fails closed before POST. Headed successful body
|
|
461
|
+
Content-Length was 400; compact emit at 398 stays.
|
|
462
|
+
|
|
463
|
+
A later signed-in headed proof on 2026-09-12 opened tessbloch, clicked
|
|
464
|
+
Contact info, and showed Email in the modal DOM. The same contained
|
|
465
|
+
synthetic navigation POST still returned HTTP 500 `text/html` after the
|
|
466
|
+
exact headed body and the full observed X-Li set. Adapter 1.36.0 kept
|
|
467
|
+
the page-instance bind, then clicked only the unique reviewed Contact
|
|
468
|
+
info control and projected that modal. Operator smoke the same day
|
|
469
|
+
found that unique control and fail-closed before click because its
|
|
470
|
+
href matched `/overlay/contact-info/`. The raw eval error was exactly
|
|
471
|
+
`Contact-info control targeted the vanity overlay GET`. Adapter 1.36.1
|
|
472
|
+
clicks that unique control even when the href is the vanity overlay
|
|
473
|
+
GET. Operator smoke after that click fail-closed because contained
|
|
474
|
+
Chrome left `/in/tessbloch/` for
|
|
475
|
+
`/in/tessbloch/overlay/contact-info/`. Adapter 1.36.2 treats that
|
|
476
|
+
reviewed vanity overlay pathname as still bound after click, then
|
|
477
|
+
snapshots the unique dialog. Authwall and any other path still fail
|
|
478
|
+
closed. It does not mint a navigation POST or track headers. Cloud has
|
|
479
|
+
no signed-in LinkedIn session; do not treat this landing as live green.
|
|
480
|
+
|
|
481
|
+
```sh
|
|
482
|
+
printf '%s' '{"profile_url":"https://www.linkedin.com/in/tessbloch/"}' \
|
|
483
|
+
| ghostget invoke linkedin-web contacts.read --input - --auth linkedin-dormant-20260911 --json
|
|
484
|
+
```
|
|
485
|
+
|
|
276
486
|
Self profiles fail closed with guidance to use `profiles.read`. Second-degree,
|
|
277
487
|
third-degree, and out-of-network profiles fail closed because LinkedIn hid
|
|
278
488
|
Contact info from that viewer. The operation never invents a hidden email.
|
|
@@ -20,7 +20,7 @@ Leave the state `capture-required` when current evidence is absent, ambiguous, e
|
|
|
20
20
|
## LinkedIn
|
|
21
21
|
|
|
22
22
|
- Use `linkedin-web` with a browser-session/cookie realm for consumer Home feed, a member's recent-activity posts, inbox folders, conversations, and native article-editor surfaces. The separate official `linkedin` OAuth adapter covers approved post, comment, reply, repost, and reaction scopes; it does not supply the consumer Home feed, recent-activity pager, or inbox.
|
|
23
|
-
- Current bundle 1.
|
|
23
|
+
- Current bundle 1.36.2 observes `linkedin-web profiles.read@1`, `organizations.read@1`, `contacts.read@1`, `feeds.read@2` for `feed=profile-activity`, `articles.draft.save@7`, and image-only `posts.publish@3`. The two profile-stat reads use a path-backed contained Chrome realm, bind the current member before projecting one exact self profile or requested organization Page, and keep the optional private connection read sequential with the self-profile read. `contacts.read@1` uses the same contained Chrome path, requires a 1st-degree relationship on the requested vanity from classic Profile embeds or Como rehydration (JSON object, RSC flight array, non-flight Como string slots through `decodeStringBootstrap`, `vieweeProfileId` plus vanity, and breadcrumb, string-row, or `vieweeMemberUrn` distance, including multi-escaped PROFILE_VIEW rows and when that member id is not the bound `fsd_profile` URN), and projects Contact-info email plus any shown profile link, connected-since date, phones, websites, or birthday from page-embedded fields while skipping non-bounded SDUI field labels, or from the modal opened by clicking the unique reviewed Contact info control on that already-loaded 1st-degree profile after the same page-instance bind, including when that control's href matches `/overlay/contact-info/` and the document pathname stays on the bound profile or that reviewed vanity overlay path. A present NavigateToScreen action still admits only the reviewed ProfileContactDetailsOverlay URL (`sduiid` equal to that overlay `screenId`); the contained path does not mint a synthetic navigation POST or track headers. GraphQL Contact-info stays a 403 `text/html` fallback when a unique queryId is present and no navigation action is bound. The vanity `/overlay/contact-info/` RSC GET remains HTML-shell honesty when the profile omits that action. An HTML-200 profile shell that omits Email fails as omitted Contact-info fields after that 1st-degree bind; overlay, navigation-flight, or modal HTML that still carries Como Email, a unique mailto, or an RSC/SDUI flight still projects. ScreenId-only, `profileUrn`-bound, and GET `/flagship-web/rsc-action/actions/navigation` overlay URLs stay rejected because live dormant sessions return HTTP 500. The profile-activity page uses the same contained Chrome path, binds the signed-in viewer, resolves the live `voyagerFeedDashProfileUpdates` query, and projects one recent-activity page with engagement counts when present; `feed=home` remains capture-required. The fixed browser evaluation performs only bounded, exact-route first-party fetches, except the reviewed unique Contact info click and modal snapshot on `contacts.read`; it does not accept a caller-selected selector. A cookie-only standalone client is not a fallback because current live evidence shows LinkedIn invalidates an exported `li_at` outside its browser/device context. The Article contract binds the numeric member subject to the normalized Article-author profile, creates or replaces one exact private draft, keeps a supplied cover in the Article banner rather than the body, and can preserve the independently read existing banner during an exact replacement without another cover upload. It supports paragraphs/H1/H2/native blockquotes, native HTTPS links, and 1–20 bounded inline JPEG/PNG/WebP images with required alt text and optional captions, and verifies the exact unpublished editor-response readback. Its fixed cover and inline-image single-upload registrations, byte transfers, autosaves, and readbacks run inside contained Chrome without DOM automation. The separate post contract stages a real-size optional PNG through bounded ordered commands, admits one exact image transfer and post create, durably retains the accepted share target, and independently verifies it. `linkedin-web media.publish@1` separately reserves an MP4 route but remains capture-required; the official `linkedin posts.publish` OAuth contract already observes MP4.
|
|
24
24
|
- Every other LinkedIn web operation remains capture-required. Explicit inert reservations cover inbox folders, one bounded page of recommended connections, one connection invitation, Article reads/publication, and other comment/message/repost surfaces. Their retained candidates do not confer executable internal requests.
|
|
25
25
|
- Exclude presence, messaging badges, delivery acknowledgements, seen/read receipts, and notification badge traffic from every R1 contract.
|
|
26
26
|
- Bind the current viewer's person/member identity to the auth realm. `organizations.read` views a Page and does not confer Page-actor authority. For organization actions, additionally bind the administered organization actor selected by the plan.
|
package/src/args.ts
CHANGED
|
@@ -36,6 +36,8 @@ type MessagingArguments = {
|
|
|
36
36
|
|
|
37
37
|
export type GhostgetArguments =
|
|
38
38
|
| { readonly command: "help" }
|
|
39
|
+
| { readonly command: "messaging-automation-serve" }
|
|
40
|
+
| { readonly command: "whatsapp-automation-install"; readonly binary?: string; readonly json: boolean }
|
|
39
41
|
| { readonly command: "clip"; readonly arguments: readonly string[] }
|
|
40
42
|
| { readonly command: "read"; readonly arguments: readonly string[] }
|
|
41
43
|
| { readonly command: "media"; readonly arguments: readonly string[] }
|
|
@@ -69,7 +71,7 @@ export type GhostgetArguments =
|
|
|
69
71
|
}
|
|
70
72
|
| {
|
|
71
73
|
readonly command: "imessage-transport-install";
|
|
72
|
-
readonly binary
|
|
74
|
+
readonly binary?: string;
|
|
73
75
|
readonly json: boolean;
|
|
74
76
|
}
|
|
75
77
|
| { readonly command: "doctor"; readonly json: boolean }
|
|
@@ -464,6 +466,11 @@ function optionalPositiveInteger(
|
|
|
464
466
|
|
|
465
467
|
function parseMessagingArguments(raw: readonly string[]): ParseGhostgetResult {
|
|
466
468
|
const operation = raw[0];
|
|
469
|
+
if (operation === "automation") {
|
|
470
|
+
return raw.length === 3 && raw[1] === "serve" && raw[2] === "--stdio"
|
|
471
|
+
? { ok: true, value: { command: "messaging-automation-serve" } }
|
|
472
|
+
: { ok: false, message: "Use messaging automation serve --stdio; all owner configuration and message data must arrive on stdin." };
|
|
473
|
+
}
|
|
467
474
|
if (operation === "reconcile") {
|
|
468
475
|
const runId = raw[1];
|
|
469
476
|
if (runId === undefined) {
|
|
@@ -923,6 +930,13 @@ export function parseGhostgetArguments(raw: readonly string[]): ParseGhostgetRes
|
|
|
923
930
|
};
|
|
924
931
|
}
|
|
925
932
|
if (first === "whatsapp") {
|
|
933
|
+
if (raw[1] === "automation" && raw[2] === "install") {
|
|
934
|
+
const parsed = optionValues(raw.slice(3), ["--binary"], ["--json"]);
|
|
935
|
+
if (isFailure(parsed)) return parsed;
|
|
936
|
+
const binary = parsed.values["--binary"];
|
|
937
|
+
if (binary !== undefined && (!isAbsolute(binary) || resolve(binary) !== binary || Buffer.byteLength(binary) > 4096 || /[\0\r\n]/u.test(binary))) return { ok: false, message: "whatsapp automation install requires --binary <normalized-absolute-reviewed-wacli-file>" };
|
|
938
|
+
return { ok: true, value: { command: "whatsapp-automation-install", ...(binary === undefined ? {} : { binary }), json: parsed.booleans.has("--json") } };
|
|
939
|
+
}
|
|
926
940
|
if (raw[1] !== "export-message-like-me") {
|
|
927
941
|
return {
|
|
928
942
|
ok: false,
|
|
@@ -966,11 +980,10 @@ export function parseGhostgetArguments(raw: readonly string[]): ParseGhostgetRes
|
|
|
966
980
|
if (isFailure(parsed)) return parsed;
|
|
967
981
|
const binary = parsed.values["--binary"];
|
|
968
982
|
if (
|
|
969
|
-
binary
|
|
970
|
-
|| !isAbsolute(binary)
|
|
983
|
+
binary !== undefined && (!isAbsolute(binary)
|
|
971
984
|
|| resolve(binary) !== binary
|
|
972
985
|
|| Buffer.byteLength(binary, "utf8") > 4_096
|
|
973
|
-
|| /[\0\r\n]/u.test(binary)
|
|
986
|
+
|| /[\0\r\n]/u.test(binary))
|
|
974
987
|
) {
|
|
975
988
|
return {
|
|
976
989
|
ok: false,
|
|
@@ -982,7 +995,7 @@ export function parseGhostgetArguments(raw: readonly string[]): ParseGhostgetRes
|
|
|
982
995
|
ok: true,
|
|
983
996
|
value: {
|
|
984
997
|
command: "imessage-transport-install",
|
|
985
|
-
binary,
|
|
998
|
+
...(binary === undefined ? {} : { binary }),
|
|
986
999
|
json: parsed.booleans.has("--json"),
|
|
987
1000
|
},
|
|
988
1001
|
};
|
|
@@ -231,6 +231,132 @@
|
|
|
231
231
|
"timeoutMs": 30000,
|
|
232
232
|
"maxOutputBytes": 1048576
|
|
233
233
|
}
|
|
234
|
+
},
|
|
235
|
+
"messaging.automation.read": {
|
|
236
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
237
|
+
"risk": "R1",
|
|
238
|
+
"sideEffect": "none",
|
|
239
|
+
"idempotency": "none",
|
|
240
|
+
"dedupeWindowMs": 0,
|
|
241
|
+
"input": {
|
|
242
|
+
"properties": {},
|
|
243
|
+
"required": []
|
|
244
|
+
},
|
|
245
|
+
"localCli": {
|
|
246
|
+
"surface": "imessage",
|
|
247
|
+
"action": "messaging.automation.read",
|
|
248
|
+
"contractVersion": 1,
|
|
249
|
+
"timeoutMs": 30000,
|
|
250
|
+
"maxOutputBytes": 8388608
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"messaging.automation.send.text": {
|
|
254
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
255
|
+
"risk": "R3",
|
|
256
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
257
|
+
"idempotency": "local-at-most-once",
|
|
258
|
+
"dedupeWindowMs": 86400000,
|
|
259
|
+
"input": {
|
|
260
|
+
"properties": {},
|
|
261
|
+
"required": []
|
|
262
|
+
},
|
|
263
|
+
"localCli": {
|
|
264
|
+
"surface": "imessage",
|
|
265
|
+
"action": "messaging.automation.send.text",
|
|
266
|
+
"contractVersion": 1,
|
|
267
|
+
"timeoutMs": 30000,
|
|
268
|
+
"maxOutputBytes": 8388608
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"messaging.automation.send.attachment": {
|
|
272
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
273
|
+
"risk": "R3",
|
|
274
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
275
|
+
"idempotency": "local-at-most-once",
|
|
276
|
+
"dedupeWindowMs": 86400000,
|
|
277
|
+
"input": {
|
|
278
|
+
"properties": {},
|
|
279
|
+
"required": []
|
|
280
|
+
},
|
|
281
|
+
"localCli": {
|
|
282
|
+
"surface": "imessage",
|
|
283
|
+
"action": "messaging.automation.send.attachment",
|
|
284
|
+
"contractVersion": 1,
|
|
285
|
+
"timeoutMs": 30000,
|
|
286
|
+
"maxOutputBytes": 8388608
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"messaging.automation.send.reaction": {
|
|
290
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
291
|
+
"risk": "R3",
|
|
292
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
293
|
+
"idempotency": "local-at-most-once",
|
|
294
|
+
"dedupeWindowMs": 86400000,
|
|
295
|
+
"input": {
|
|
296
|
+
"properties": {},
|
|
297
|
+
"required": []
|
|
298
|
+
},
|
|
299
|
+
"localCli": {
|
|
300
|
+
"surface": "imessage",
|
|
301
|
+
"action": "messaging.automation.send.reaction",
|
|
302
|
+
"contractVersion": 1,
|
|
303
|
+
"timeoutMs": 30000,
|
|
304
|
+
"maxOutputBytes": 8388608
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
"messaging.automation.send.sticker": {
|
|
308
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
309
|
+
"risk": "R3",
|
|
310
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
311
|
+
"idempotency": "local-at-most-once",
|
|
312
|
+
"dedupeWindowMs": 86400000,
|
|
313
|
+
"input": {
|
|
314
|
+
"properties": {},
|
|
315
|
+
"required": []
|
|
316
|
+
},
|
|
317
|
+
"localCli": {
|
|
318
|
+
"surface": "imessage",
|
|
319
|
+
"action": "messaging.automation.send.sticker",
|
|
320
|
+
"contractVersion": 1,
|
|
321
|
+
"timeoutMs": 30000,
|
|
322
|
+
"maxOutputBytes": 8388608
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
"messaging.automation.send.link": {
|
|
326
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
327
|
+
"risk": "R3",
|
|
328
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
329
|
+
"idempotency": "local-at-most-once",
|
|
330
|
+
"dedupeWindowMs": 86400000,
|
|
331
|
+
"input": {
|
|
332
|
+
"properties": {},
|
|
333
|
+
"required": []
|
|
334
|
+
},
|
|
335
|
+
"localCli": {
|
|
336
|
+
"surface": "imessage",
|
|
337
|
+
"action": "messaging.automation.send.link",
|
|
338
|
+
"contractVersion": 1,
|
|
339
|
+
"timeoutMs": 30000,
|
|
340
|
+
"maxOutputBytes": 8388608
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"messaging.automation.send.poll": {
|
|
344
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
345
|
+
"risk": "R3",
|
|
346
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
347
|
+
"idempotency": "local-at-most-once",
|
|
348
|
+
"dedupeWindowMs": 86400000,
|
|
349
|
+
"input": {
|
|
350
|
+
"properties": {},
|
|
351
|
+
"required": []
|
|
352
|
+
},
|
|
353
|
+
"localCli": {
|
|
354
|
+
"surface": "imessage",
|
|
355
|
+
"action": "messaging.automation.send.poll",
|
|
356
|
+
"contractVersion": 1,
|
|
357
|
+
"timeoutMs": 30000,
|
|
358
|
+
"maxOutputBytes": 8388608
|
|
359
|
+
}
|
|
234
360
|
}
|
|
235
361
|
}
|
|
236
362
|
}
|
|
@@ -395,6 +395,150 @@
|
|
|
395
395
|
"timeoutMs": 600000,
|
|
396
396
|
"maxOutputBytes": 8388608
|
|
397
397
|
}
|
|
398
|
+
},
|
|
399
|
+
"messaging.automation.read": {
|
|
400
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
401
|
+
"risk": "R1",
|
|
402
|
+
"sideEffect": "none",
|
|
403
|
+
"idempotency": "none",
|
|
404
|
+
"dedupeWindowMs": 0,
|
|
405
|
+
"input": {
|
|
406
|
+
"properties": {},
|
|
407
|
+
"required": []
|
|
408
|
+
},
|
|
409
|
+
"webSession": {
|
|
410
|
+
"site": "whatsapp",
|
|
411
|
+
"action": "messaging.automation.read",
|
|
412
|
+
"contractVersion": 1,
|
|
413
|
+
"timeoutMs": 30000,
|
|
414
|
+
"maxOutputBytes": 8388608
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
"messaging.automation.sync": {
|
|
418
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
419
|
+
"risk": "R2",
|
|
420
|
+
"sideEffect": "Maintain an explicitly started linked-device sync session; may emit protocol acknowledgements.",
|
|
421
|
+
"idempotency": "local-at-most-once",
|
|
422
|
+
"dedupeWindowMs": 86400000,
|
|
423
|
+
"input": {
|
|
424
|
+
"properties": {},
|
|
425
|
+
"required": []
|
|
426
|
+
},
|
|
427
|
+
"webSession": {
|
|
428
|
+
"site": "whatsapp",
|
|
429
|
+
"action": "messaging.automation.sync",
|
|
430
|
+
"contractVersion": 1,
|
|
431
|
+
"timeoutMs": 30000,
|
|
432
|
+
"maxOutputBytes": 8388608
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
"messaging.automation.send.text": {
|
|
436
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
437
|
+
"risk": "R3",
|
|
438
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
439
|
+
"idempotency": "local-at-most-once",
|
|
440
|
+
"dedupeWindowMs": 86400000,
|
|
441
|
+
"input": {
|
|
442
|
+
"properties": {},
|
|
443
|
+
"required": []
|
|
444
|
+
},
|
|
445
|
+
"webSession": {
|
|
446
|
+
"site": "whatsapp",
|
|
447
|
+
"action": "messaging.automation.send.text",
|
|
448
|
+
"contractVersion": 1,
|
|
449
|
+
"timeoutMs": 30000,
|
|
450
|
+
"maxOutputBytes": 8388608
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
"messaging.automation.send.attachment": {
|
|
454
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
455
|
+
"risk": "R3",
|
|
456
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
457
|
+
"idempotency": "local-at-most-once",
|
|
458
|
+
"dedupeWindowMs": 86400000,
|
|
459
|
+
"input": {
|
|
460
|
+
"properties": {},
|
|
461
|
+
"required": []
|
|
462
|
+
},
|
|
463
|
+
"webSession": {
|
|
464
|
+
"site": "whatsapp",
|
|
465
|
+
"action": "messaging.automation.send.attachment",
|
|
466
|
+
"contractVersion": 1,
|
|
467
|
+
"timeoutMs": 30000,
|
|
468
|
+
"maxOutputBytes": 8388608
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
"messaging.automation.send.reaction": {
|
|
472
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
473
|
+
"risk": "R3",
|
|
474
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
475
|
+
"idempotency": "local-at-most-once",
|
|
476
|
+
"dedupeWindowMs": 86400000,
|
|
477
|
+
"input": {
|
|
478
|
+
"properties": {},
|
|
479
|
+
"required": []
|
|
480
|
+
},
|
|
481
|
+
"webSession": {
|
|
482
|
+
"site": "whatsapp",
|
|
483
|
+
"action": "messaging.automation.send.reaction",
|
|
484
|
+
"contractVersion": 1,
|
|
485
|
+
"timeoutMs": 30000,
|
|
486
|
+
"maxOutputBytes": 8388608
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
"messaging.automation.send.sticker": {
|
|
490
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
491
|
+
"risk": "R3",
|
|
492
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
493
|
+
"idempotency": "local-at-most-once",
|
|
494
|
+
"dedupeWindowMs": 86400000,
|
|
495
|
+
"input": {
|
|
496
|
+
"properties": {},
|
|
497
|
+
"required": []
|
|
498
|
+
},
|
|
499
|
+
"webSession": {
|
|
500
|
+
"site": "whatsapp",
|
|
501
|
+
"action": "messaging.automation.send.sticker",
|
|
502
|
+
"contractVersion": 1,
|
|
503
|
+
"timeoutMs": 30000,
|
|
504
|
+
"maxOutputBytes": 8388608
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
"messaging.automation.send.link": {
|
|
508
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
509
|
+
"risk": "R3",
|
|
510
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
511
|
+
"idempotency": "local-at-most-once",
|
|
512
|
+
"dedupeWindowMs": 86400000,
|
|
513
|
+
"input": {
|
|
514
|
+
"properties": {},
|
|
515
|
+
"required": []
|
|
516
|
+
},
|
|
517
|
+
"webSession": {
|
|
518
|
+
"site": "whatsapp",
|
|
519
|
+
"action": "messaging.automation.send.link",
|
|
520
|
+
"contractVersion": 1,
|
|
521
|
+
"timeoutMs": 30000,
|
|
522
|
+
"maxOutputBytes": 8388608
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
"messaging.automation.send.poll": {
|
|
526
|
+
"description": "Scoped owner automation permission; use ghostget messaging automation serve --stdio. Generic invocation is unavailable.",
|
|
527
|
+
"risk": "R3",
|
|
528
|
+
"sideEffect": "Submit one exact action through an enrolled conversation and an unexpired bounded owner grant; delivery remains unknown.",
|
|
529
|
+
"idempotency": "local-at-most-once",
|
|
530
|
+
"dedupeWindowMs": 86400000,
|
|
531
|
+
"input": {
|
|
532
|
+
"properties": {},
|
|
533
|
+
"required": []
|
|
534
|
+
},
|
|
535
|
+
"webSession": {
|
|
536
|
+
"site": "whatsapp",
|
|
537
|
+
"action": "messaging.automation.send.poll",
|
|
538
|
+
"contractVersion": 1,
|
|
539
|
+
"timeoutMs": 30000,
|
|
540
|
+
"maxOutputBytes": 8388608
|
|
541
|
+
}
|
|
398
542
|
}
|
|
399
543
|
}
|
|
400
544
|
}
|