@hraness/ghostget 0.17.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 +458 -0
- package/LICENSE +21 -0
- package/README.md +1359 -0
- package/bunfig.toml +2 -0
- package/dist/apple-photos-client.js +704 -0
- package/dist/beeper-client.js +4602 -0
- package/dist/client.js +1605 -0
- package/dist/index-26yq8q16.js +31 -0
- package/dist/index-9t13b4k7.js +508 -0
- package/dist/index-axwm9b3v.js +5 -0
- package/dist/index-gwk7rbyj.js +30 -0
- package/dist/index.js +701 -0
- package/dist/messaging.js +1130 -0
- package/dist/omni-client.js +1406 -0
- package/dist/whatsapp-client.js +355 -0
- package/docs/imessage-direct-provider.md +106 -0
- package/docs/rental-listings.md +94 -0
- package/package.json +600 -0
- package/skills/ghostget/SKILL.md +251 -0
- package/skills/ghostget/agents/openai.yaml +4 -0
- package/skills/ghostget/references/adapter-contract.md +181 -0
- package/skills/ghostget/references/apple-photos.md +115 -0
- package/skills/ghostget/references/article-drafts.md +235 -0
- package/skills/ghostget/references/code-owned-provider-scaffold.md +134 -0
- package/skills/ghostget/references/cross-posting-video.md +139 -0
- package/skills/ghostget/references/cross-posting.md +82 -0
- package/skills/ghostget/references/derivation.md +390 -0
- package/skills/ghostget/references/hraness-social-profile-stats.json +269 -0
- package/skills/ghostget/references/install.md +66 -0
- package/skills/ghostget/references/linkedin-adapter.md +442 -0
- package/skills/ghostget/references/messaging.md +168 -0
- package/skills/ghostget/references/meta-comet-contract.md +153 -0
- package/skills/ghostget/references/platform-patterns.md +122 -0
- package/skills/ghostget/references/provider-plugins.md +496 -0
- package/skills/ghostget/references/reddit-flair.md +78 -0
- package/skills/ghostget/references/safety-and-state.md +214 -0
- package/skills/ghostget/references/settlement-and-duplicate-cleanup.md +79 -0
- package/skills/ghostget/references/social-platform-routing.md +66 -0
- package/skills/ghostget/references/social-profile-stats.md +195 -0
- package/skills/ghostget/references/social-video-platform-routing.md +89 -0
- package/skills/ghostget/references/whatsapp-adapter.md +101 -0
- package/skills/ghostget/references/x-adapter.md +332 -0
- package/skills/ghostget/references/x-ai-disclosure.md +71 -0
- package/src/apple-photos-cli.ts +639 -0
- package/src/apple-photos-client-types.ts +168 -0
- package/src/apple-photos-client.ts +201 -0
- package/src/apple-photos-contact-evidence.ts +838 -0
- package/src/apple-photos-local-source.ts +1131 -0
- package/src/args.ts +2053 -0
- package/src/article-draft-document.ts +417 -0
- package/src/article-draft-embeds.ts +123 -0
- package/src/article-draft-images.ts +214 -0
- package/src/assets/adapter-template/wrench-adapter.json +40 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.json +1500 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v1.0.0.json +129 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v1.1.0.json +207 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.0.0.json +1463 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.1.0.json +1463 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.2.0.json +1475 -0
- package/src/assets/adapters/beeper/wrench-web-adapter.v2.3.0.json +1488 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.json +684 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.0.0.json +581 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.1.0.json +581 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.2.0.json +581 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.3.0.json +615 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.4.0.json +684 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.5.0.json +684 -0
- package/src/assets/adapters/bluesky/wrench-web-adapter.v1.6.0.json +684 -0
- package/src/assets/adapters/clasificados/wrench-web-adapter.json +54 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.json +750 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.v1.0.0.json +706 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.v1.1.0.json +703 -0
- package/src/assets/adapters/facebook/wrench-web-adapter.v1.2.0.json +750 -0
- package/src/assets/adapters/facebook-group/wrench-web-adapter.json +682 -0
- package/src/assets/adapters/facebook-group/wrench-web-adapter.v1.0.0.json +583 -0
- package/src/assets/adapters/facebook-group/wrench-web-adapter.v1.1.0.json +682 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.json +437 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.0.0.json +383 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.1.0.json +437 -0
- package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.1.1.json +437 -0
- package/src/assets/adapters/facebook-page/wrench-web-adapter.json +880 -0
- package/src/assets/adapters/facebook-page/wrench-web-adapter.v1.0.0.json +740 -0
- package/src/assets/adapters/facebook-page/wrench-web-adapter.v1.1.0.json +880 -0
- package/src/assets/adapters/github/wrench-web-adapter.json +69 -0
- package/src/assets/adapters/github/wrench-web-adapter.v1.0.0.json +42 -0
- package/src/assets/adapters/github/wrench-web-adapter.v1.1.0.json +69 -0
- package/src/assets/adapters/gmail/wrench-adapter.json +161 -0
- package/src/assets/adapters/gmail/wrench-adapter.v1.2.0.json +157 -0
- package/src/assets/adapters/hacker-news/wrench-web-adapter.json +315 -0
- package/src/assets/adapters/hacker-news/wrench-web-adapter.v1.0.0.json +315 -0
- package/src/assets/adapters/imessage/wrench-web-adapter.json +236 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.json +719 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.0.0.json +627 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.1.0.json +609 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.2.0.json +640 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.3.0.json +671 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.4.0.json +710 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.5.0.json +710 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.6.0.json +719 -0
- package/src/assets/adapters/instagram/wrench-web-adapter.v1.7.0.json +719 -0
- package/src/assets/adapters/linkedin/wrench-adapter.json +442 -0
- package/src/assets/adapters/linkedin/wrench-adapter.v0.4.0.json +124 -0
- package/src/assets/adapters/linkedin/wrench-adapter.v1.0.0.json +411 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.json +914 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.0.0.json +604 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.1.0.json +604 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.10.0.json +809 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.11.0.json +809 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.12.0.json +820 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.13.0.json +819 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.14.0.json +819 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.15.0.json +819 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.16.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.17.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.18.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.19.0.json +874 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.2.0.json +731 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.3.0.json +768 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.4.0.json +808 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.5.0.json +808 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.6.0.json +808 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.7.0.json +825 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.8.0.json +792 -0
- package/src/assets/adapters/linkedin/wrench-web-adapter.v1.9.0.json +809 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.json +855 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.0.0.json +577 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.1.0.json +604 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.10.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.11.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.12.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.2.0.json +653 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.3.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.4.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.5.0.json +712 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.6.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.7.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.8.0.json +713 -0
- package/src/assets/adapters/reddit/wrench-web-adapter.v1.9.0.json +713 -0
- package/src/assets/adapters/substack/wrench-web-adapter.json +936 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.0.0.json +817 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.1.0.json +812 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.2.0.json +812 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.3.0.json +902 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.4.0.json +936 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.5.0.json +936 -0
- package/src/assets/adapters/substack/wrench-web-adapter.v1.6.0.json +936 -0
- package/src/assets/adapters/threads/wrench-web-adapter.json +692 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.0.0.json +629 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.1.0.json +623 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.2.0.json +622 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.3.0.json +622 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.4.0.json +622 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.5.0.json +699 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.6.0.json +693 -0
- package/src/assets/adapters/threads/wrench-web-adapter.v1.7.0.json +692 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.json +762 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.0.0.json +681 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.1.0.json +708 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.2.0.json +762 -0
- package/src/assets/adapters/tiktok/wrench-web-adapter.v1.3.0.json +762 -0
- package/src/assets/adapters/twitch/wrench-web-adapter.json +42 -0
- package/src/assets/adapters/twitch/wrench-web-adapter.v1.0.0.json +42 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.json +400 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.0.0.json +355 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.1.0.json +386 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.2.0.json +386 -0
- package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.3.0.json +400 -0
- package/src/assets/adapters/x/wrench-adapter.json +749 -0
- package/src/assets/adapters/x/wrench-adapter.v1.0.0.json +700 -0
- package/src/assets/adapters/x/wrench-adapter.v1.1.0.json +707 -0
- package/src/assets/adapters/x/wrench-web-adapter.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.1.0.json +579 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.10.0.json +685 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.11.0.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.12.0.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.13.0.json +712 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.2.0.json +578 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.3.0.json +610 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.4.0.json +617 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.5.0.json +634 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.6.0.json +632 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.7.0.json +649 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.8.0.json +649 -0
- package/src/assets/adapters/x/wrench-web-adapter.v1.9.0.json +683 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.json +561 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.0.0.json +465 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.1.0.json +519 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.2.0.json +561 -0
- package/src/assets/adapters/youtube/wrench-web-adapter.v1.3.0.json +561 -0
- package/src/assets/code-owned-provider-template/plugin.test.ts.template +54 -0
- package/src/assets/code-owned-provider-template/plugin.ts.template +102 -0
- package/src/assets/code-owned-provider-template/runtime.internal.test.ts.template +44 -0
- package/src/assets/code-owned-provider-template/runtime.ts.template +59 -0
- package/src/assets/code-owned-provider-template/wrench-adapter.json.template +33 -0
- package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
- package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
- package/src/assets/fonts/nebula-sans/PROVENANCE.md +14 -0
- package/src/assets.d.ts +4 -0
- package/src/auth.ts +1157 -0
- package/src/beeper-client-types.ts +169 -0
- package/src/beeper-client.ts +250 -0
- package/src/beeper-contact-interactions-cli.ts +180 -0
- package/src/beeper-contact-interactions.ts +1612 -0
- package/src/beeper-message-bundle-v1.ts +257 -0
- package/src/beeper-message-like-me-cli.ts +84 -0
- package/src/beeper-message-like-me-export.ts +2274 -0
- package/src/beeper-message-like-me-recovery.ts +931 -0
- package/src/beeper-message-like-me-source.ts +4034 -0
- package/src/browser-admission.ts +928 -0
- package/src/browser-snapshots.ts +260 -0
- package/src/browser.ts +3873 -0
- package/src/canonical-json.ts +60 -0
- package/src/catalog-cli.ts +638 -0
- package/src/cli.ts +208 -0
- package/src/client-types.ts +301 -0
- package/src/client.ts +2726 -0
- package/src/confirmed-write-failure.ts +44 -0
- package/src/confirmed-write-model.ts +72 -0
- package/src/confirmed-write-platform.ts +1055 -0
- package/src/confirmed-write-program.ts +224 -0
- package/src/confirmed-write-runtime.ts +16 -0
- package/src/cursor-token.ts +228 -0
- package/src/derivation-dnr-readiness.ts +367 -0
- package/src/derivation-file-chooser.ts +384 -0
- package/src/derivation-network-boundary.ts +835 -0
- package/src/derivation-network-guard.ts +782 -0
- package/src/derivation-network-proxy-helper.ts +440 -0
- package/src/derivation-network-proxy.ts +385 -0
- package/src/derive-command-helper.ts +693 -0
- package/src/derive-fixtures.ts +343 -0
- package/src/derive-review.ts +980 -0
- package/src/derive.ts +4754 -0
- package/src/fixtures/beeper-message-like-me-v1/accounts.ndjson +2 -0
- package/src/fixtures/beeper-message-like-me-v1/conversations.ndjson +1 -0
- package/src/fixtures/beeper-message-like-me-v1/manifest.json +1 -0
- package/src/fixtures/beeper-message-like-me-v1/messages.ndjson +2 -0
- package/src/fixtures/beeper-message-like-me-v1/participants.ndjson +3 -0
- package/src/fixtures/beeper-message-like-me-v1/reactions.ndjson +1 -0
- package/src/fixtures/beeper-message-like-me-v1/tombstones.ndjson +1 -0
- package/src/ghostget.ts +3672 -0
- package/src/gmail-capture.ts +1244 -0
- package/src/har-internal.ts +1242 -0
- package/src/har.ts +743 -0
- package/src/index.ts +218 -0
- package/src/invocation-read-platform.ts +55 -0
- package/src/invocation-read-program.ts +93 -0
- package/src/invocation-read-runtime.ts +11 -0
- package/src/linked-device-lifecycle-admission.ts +450 -0
- package/src/linked-device-lifecycle-journal.ts +1560 -0
- package/src/linked-device-lifecycle-runtime.ts +1602 -0
- package/src/local-cli-admission.ts +135 -0
- package/src/local-cli-contracts.ts +271 -0
- package/src/local-cli-execution.ts +98 -0
- package/src/local-cli-surface-contract.ts +1510 -0
- package/src/local-cli-tool-identity.ts +336 -0
- package/src/media/archive.ts +2325 -0
- package/src/media/args.ts +303 -0
- package/src/media/cli.ts +287 -0
- package/src/media/doctor.ts +475 -0
- package/src/media/ffmpeg.ts +1330 -0
- package/src/media/http-capture.ts +711 -0
- package/src/media/http-probe.ts +593 -0
- package/src/media/http.ts +387 -0
- package/src/media/index.ts +10 -0
- package/src/media/local-transcription.ts +613 -0
- package/src/media/lock.ts +321 -0
- package/src/media/manifest.ts +1712 -0
- package/src/media/metadata.ts +906 -0
- package/src/media/process.ts +723 -0
- package/src/media/revision.ts +166 -0
- package/src/media/runtime-closure.ts +1063 -0
- package/src/media/source-router.ts +187 -0
- package/src/media/transcriber-config.ts +1122 -0
- package/src/media/transcript-persistence-model.ts +15 -0
- package/src/media/transcript-persistence-platform.ts +89 -0
- package/src/media/transcript-persistence-program.ts +39 -0
- package/src/media/transcript-persistence-runtime.ts +24 -0
- package/src/media/transcript.ts +616 -0
- package/src/media/utf8-order.ts +30 -0
- package/src/media/whisper-cpp.ts +464 -0
- package/src/media/whisper-language.ts +58 -0
- package/src/media/yt-dlp.ts +439 -0
- package/src/message-like-me-agentic-messaging.ts +882 -0
- package/src/messaging-action-store.ts +793 -0
- package/src/messaging-runtime.ts +2136 -0
- package/src/messaging-store.ts +539 -0
- package/src/messaging-types.ts +1663 -0
- package/src/messaging.ts +334 -0
- package/src/model.ts +2671 -0
- package/src/oauth-google.ts +888 -0
- package/src/omni-client-types.ts +306 -0
- package/src/omni-client.ts +2225 -0
- package/src/omni-limits.ts +34 -0
- package/src/omni-model.ts +1614 -0
- package/src/omni-request.ts +379 -0
- package/src/omni-runtime.ts +1632 -0
- package/src/operation-deadline.ts +189 -0
- package/src/path-helper.ts +1656 -0
- package/src/pinned-https.ts +194 -0
- package/src/plan-assets.ts +832 -0
- package/src/platform-catalog.ts +1832 -0
- package/src/plugins/beeper-linked-device/plugin.ts +310 -0
- package/src/plugins/bluesky-web/plugin.ts +178 -0
- package/src/plugins/clasificados-web/plugin.ts +66 -0
- package/src/plugins/github-web/plugin.ts +80 -0
- package/src/plugins/gmail-official/plugin.ts +110 -0
- package/src/plugins/hacker-news-web/plugin.ts +52 -0
- package/src/plugins/imessage-direct/plugin.ts +195 -0
- package/src/plugins/imessage-direct/vendor/0001-fix-keep-AppleScript-send-payloads-out-of-child-argv.patch +1430 -0
- package/src/plugins/imessage-direct/vendor/0002-feat-rpc-add-exact-chat-lookup.patch +225 -0
- package/src/plugins/imessage-direct/vendor/provenance.json +80 -0
- package/src/plugins/linkedin-official/plugin.ts +84 -0
- package/src/plugins/linkedin-web/plugin.ts +412 -0
- package/src/plugins/meta-web/plugin.ts +317 -0
- package/src/plugins/reddit-web/flair.ts +492 -0
- package/src/plugins/reddit-web/plugin.ts +477 -0
- package/src/plugins/substack-web/plugin.ts +124 -0
- package/src/plugins/tiktok-web/plugin.ts +67 -0
- package/src/plugins/twitch-web/plugin.ts +54 -0
- package/src/plugins/whatsapp-linked-device/plugin.ts +105 -0
- package/src/plugins/x-official/plugin.ts +64 -0
- package/src/plugins/x-web/plugin.ts +488 -0
- package/src/plugins/youtube-web/plugin.ts +101 -0
- package/src/portable-run-recovery.ts +466 -0
- package/src/process-identity.ts +501 -0
- package/src/profile-clone-helper.ts +104 -0
- package/src/provider-catalog-views.ts +51 -0
- package/src/provider-context.ts +69 -0
- package/src/provider-contract-definitions-x.ts +45 -0
- package/src/provider-contract-definitions.ts +948 -0
- package/src/provider-contract-input-gmail.ts +176 -0
- package/src/provider-contract-input-linkedin.ts +77 -0
- package/src/provider-contract-input-x.ts +304 -0
- package/src/provider-contract-planning.ts +23 -0
- package/src/provider-contract-semantic-identity.ts +54 -0
- package/src/provider-contracts.ts +251 -0
- package/src/provider-http.ts +723 -0
- package/src/provider-plugin-auth.ts +36 -0
- package/src/provider-plugin-builtins.ts +229 -0
- package/src/provider-plugin-cleanup-barrier.ts +229 -0
- package/src/provider-plugin-cleanup-execution.ts +79 -0
- package/src/provider-plugin-cleanup-resource.ts +470 -0
- package/src/provider-plugin-contract-identity.ts +707 -0
- package/src/provider-plugin-host.ts +1972 -0
- package/src/provider-plugin-identifiers.ts +60 -0
- package/src/provider-plugin-invocation-lease.ts +889 -0
- package/src/provider-plugin-lifecycle-kernel.ts +566 -0
- package/src/provider-plugin-lifecycle.ts +1455 -0
- package/src/provider-plugin-module-analysis.ts +336 -0
- package/src/provider-plugin-package.ts +2530 -0
- package/src/provider-plugin-portable-authority.ts +106 -0
- package/src/provider-plugin-portable-catalog.ts +94 -0
- package/src/provider-plugin-portable-identity.ts +315 -0
- package/src/provider-plugin-portable-runtime.ts +2057 -0
- package/src/provider-plugin-protocol.ts +1625 -0
- package/src/provider-plugin-registry.ts +3342 -0
- package/src/provider-plugin-store.ts +2155 -0
- package/src/provider-plugin-test-fixture.ts +5 -0
- package/src/provider-plugin.ts +4907 -0
- package/src/provider-plugins.generated.ts +43 -0
- package/src/provider-plugins.ts +8 -0
- package/src/provider-subject.ts +41 -0
- package/src/provider.ts +315 -0
- package/src/providers/beeper-local-runtime.ts +5426 -0
- package/src/providers/beeper-local.ts +2739 -0
- package/src/providers/beeper-messaging.ts +462 -0
- package/src/providers/beeper-omni.ts +1159 -0
- package/src/providers/bluesky-web-runtime.ts +2895 -0
- package/src/providers/bluesky-web.ts +1614 -0
- package/src/providers/clasificados-web-runtime.ts +255 -0
- package/src/providers/clasificados-web.ts +503 -0
- package/src/providers/contact-projection.ts +301 -0
- package/src/providers/github-read-model.ts +94 -0
- package/src/providers/github-read-platform.ts +165 -0
- package/src/providers/github-read-program.ts +97 -0
- package/src/providers/github-web-runtime.ts +320 -0
- package/src/providers/github-web.ts +403 -0
- package/src/providers/gmail-api.ts +2834 -0
- package/src/providers/gmail-omni.ts +830 -0
- package/src/providers/gmail.ts +1130 -0
- package/src/providers/hacker-news-web-runtime.ts +220 -0
- package/src/providers/hacker-news-web.ts +809 -0
- package/src/providers/imessage-direct-install.ts +354 -0
- package/src/providers/imessage-direct-messaging.ts +532 -0
- package/src/providers/imessage-direct-omni.ts +400 -0
- package/src/providers/imessage-direct-runtime.ts +1498 -0
- package/src/providers/imessage-direct.ts +351 -0
- package/src/providers/instagram-video-foundations.ts +913 -0
- package/src/providers/instagram-web-profile-browser.ts +600 -0
- package/src/providers/iso-bmff.ts +338 -0
- package/src/providers/linkedin-company-platform.ts +42 -0
- package/src/providers/linkedin-company-program.ts +88 -0
- package/src/providers/linkedin-contact-failure.ts +84 -0
- package/src/providers/linkedin-contact-platform.ts +45 -0
- package/src/providers/linkedin-contact-program.ts +91 -0
- package/src/providers/linkedin-profile-activity-failure.ts +76 -0
- package/src/providers/linkedin-profile-activity-platform.ts +41 -0
- package/src/providers/linkedin-profile-activity-program.ts +67 -0
- package/src/providers/linkedin-read-failure.ts +52 -0
- package/src/providers/linkedin-self-platform.ts +53 -0
- package/src/providers/linkedin-self-program.ts +122 -0
- package/src/providers/linkedin-web-article-browser.ts +794 -0
- package/src/providers/linkedin-web-bootstrap.ts +146 -0
- package/src/providers/linkedin-web-contact.ts +830 -0
- package/src/providers/linkedin-web-feed-browser.ts +832 -0
- package/src/providers/linkedin-web-feed.ts +864 -0
- package/src/providers/linkedin-web-post-browser.ts +653 -0
- package/src/providers/linkedin-web-profile-browser.ts +683 -0
- package/src/providers/linkedin-web-runtime.ts +2388 -0
- package/src/providers/linkedin-web.ts +3305 -0
- package/src/providers/linkedin.ts +1885 -0
- package/src/providers/meta-bootstrap.ts +1043 -0
- package/src/providers/meta-facebook-group.ts +690 -0
- package/src/providers/meta-marketplace-relay.ts +747 -0
- package/src/providers/meta-omni.ts +373 -0
- package/src/providers/meta-relay-bundle.ts +1049 -0
- package/src/providers/meta-web-descriptors.ts +1740 -0
- package/src/providers/meta-web-runtime.ts +3388 -0
- package/src/providers/meta-web.ts +2931 -0
- package/src/providers/read-failure.ts +139 -0
- package/src/providers/reddit-omni.ts +462 -0
- package/src/providers/reddit-web-runtime.ts +1929 -0
- package/src/providers/reddit-web.ts +1611 -0
- package/src/providers/rental-listings.ts +460 -0
- package/src/providers/substack-omni.ts +406 -0
- package/src/providers/substack-video-mp4.ts +33 -0
- package/src/providers/substack-web-runtime.ts +2812 -0
- package/src/providers/substack-web.ts +1502 -0
- package/src/providers/tiktok-video-mp4.ts +33 -0
- package/src/providers/tiktok-web-runtime.ts +770 -0
- package/src/providers/tiktok-web.ts +2786 -0
- package/src/providers/twitch-web-runtime.ts +226 -0
- package/src/providers/twitch-web.ts +274 -0
- package/src/providers/whatsapp-account-identity.ts +55 -0
- package/src/providers/whatsapp-contact-projection-helper.ts +874 -0
- package/src/providers/whatsapp-contact-projection-protocol.ts +403 -0
- package/src/providers/whatsapp-interaction-projection-helper.ts +1452 -0
- package/src/providers/whatsapp-interaction-projection-protocol.ts +462 -0
- package/src/providers/whatsapp-message-export-projection-protocol.ts +532 -0
- package/src/providers/whatsapp-messaging.ts +132 -0
- package/src/providers/whatsapp-omni.ts +586 -0
- package/src/providers/whatsapp-web-runtime.ts +3108 -0
- package/src/providers/whatsapp-web.ts +1037 -0
- package/src/providers/x-image-provenance.ts +523 -0
- package/src/providers/x-made-with-ai.ts +106 -0
- package/src/providers/x-transaction-id.ts +413 -0
- package/src/providers/x-web-runtime.ts +3485 -0
- package/src/providers/x-web.ts +2332 -0
- package/src/providers/x.ts +1889 -0
- package/src/providers/youtube-web-runtime.ts +1400 -0
- package/src/providers/youtube-web.ts +1221 -0
- package/src/read-admission-runtime.ts +91 -0
- package/src/read-client.ts +521 -0
- package/src/read-effect-platform.ts +7 -0
- package/src/read-effect-runtime.ts +14 -0
- package/src/read-effect.ts +52 -0
- package/src/read-projection-admission.ts +866 -0
- package/src/read-projections.ts +3151 -0
- package/src/recovery.ts +1492 -0
- package/src/reviewed-template.ts +146 -0
- package/src/run-journal.ts +1272 -0
- package/src/runtime.ts +5116 -0
- package/src/scripts/generate-provider-plugin-catalog.ts +121 -0
- package/src/scripts/install-whatsapp-protocol.sh +232 -0
- package/src/scripts/recover-install-stages.ts +1491 -0
- package/src/scripts/resolve-state-home.ts +30 -0
- package/src/scripts/scaffold-web-provider.ts +973 -0
- package/src/scripts/sync-bundled-adapters.ts +695 -0
- package/src/session-secrets.ts +1183 -0
- package/src/state-helper.bunfig.toml +2 -0
- package/src/state-helper.ts +2914 -0
- package/src/storage.ts +3842 -0
- package/src/transport-policy.ts +2 -0
- package/src/usage.ts +182 -0
- package/src/version.ts +2 -0
- package/src/web-session-authentication-policy.ts +136 -0
- package/src/web-session-cleanup-admission.ts +2344 -0
- package/src/web-session-cleanup-join.ts +99 -0
- package/src/web-session-client.ts +996 -0
- package/src/web-session-contract-definitions.ts +820 -0
- package/src/web-session-contract-planning.ts +42 -0
- package/src/web-session-contracts.ts +228 -0
- package/src/web-session-cookies.ts +500 -0
- package/src/web-session-execution.ts +385 -0
- package/src/web-session-http.ts +373 -0
- package/src/web-session-read-errors.ts +19 -0
- package/src/web-session-read-runtime.ts +124 -0
- package/src/web-session-recovery.ts +818 -0
- package/src/web-session-sites.ts +58 -0
- package/src/web-session-template.ts +994 -0
- package/src/web-session.ts +93 -0
- package/src/whatsapp-client-binding.ts +21 -0
- package/src/whatsapp-client-types.ts +75 -0
- package/src/whatsapp-client.ts +395 -0
- package/src/whatsapp-export-coordinate.ts +17 -0
- package/src/whatsapp-message-bundle-v2.ts +195 -0
- package/src/whatsapp-message-like-me-cli.ts +195 -0
- package/src/whatsapp-message-like-me-export.ts +1072 -0
- package/src/whatsapp-message-like-me-source.ts +1012 -0
- package/tsconfig.json +67 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Authenticated API safety and state
|
|
2
|
+
|
|
3
|
+
Use this reference before recording signed-in traffic, resolving browser-held secrets, or invoking R2/R3 operations.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Separate authority from mechanism](#separate-authority-from-mechanism)
|
|
8
|
+
- [Bind the authenticated account](#bind-the-authenticated-account)
|
|
9
|
+
- [Use persistent reads without changing their meaning](#use-persistent-reads-without-changing-their-meaning)
|
|
10
|
+
- [Constrain native provider CLIs](#constrain-native-provider-clis)
|
|
11
|
+
- [Keep browser authority narrow](#keep-browser-authority-narrow)
|
|
12
|
+
- [Constrain first-party HTTP](#constrain-first-party-http)
|
|
13
|
+
- [Minimize HAR exposure](#minimize-har-exposure)
|
|
14
|
+
- [Interpret execution states](#interpret-execution-states)
|
|
15
|
+
- [Reconcile uncertainty](#reconcile-uncertainty)
|
|
16
|
+
- [Clean up task-owned state](#clean-up-task-owned-state)
|
|
17
|
+
|
|
18
|
+
## Separate authority from mechanism
|
|
19
|
+
|
|
20
|
+
Confirm that the user authorized the exact account, target, and remote effect. An exploratory request to inspect a site or derive a client does not authorize a live mutation.
|
|
21
|
+
|
|
22
|
+
The five-minute digest binds the installed adapter, code-owned contract hash, transport, exact input, attachment content, auth-realm fingerprint, risk, and complete dispatch schedule. It proves what will run. It does not decide whether the action is wise, lawful, permitted by provider rules, or authorized.
|
|
23
|
+
|
|
24
|
+
Use disposable or low-stakes fixtures. Keep employment, recruiting, financial, medical, legal, security, and intimate conversations out of pressure tests.
|
|
25
|
+
|
|
26
|
+
Schema-v5 version-1 reviewed-template manifests are inert derivation reservations, not request authority. Keep every operation `capture-required`; validation rejects `reviewed`, and planning or execution must fail before cookie acquisition, token resolution, or network I/O. Use a code-owned contract for executable operations until a future contract version 2 provides a reviewed current-account preflight and response-scope binding.
|
|
27
|
+
|
|
28
|
+
## Bind the authenticated account
|
|
29
|
+
|
|
30
|
+
Treat every auth ID as one stable provider-account realm. A cookie/profile name is not account proof.
|
|
31
|
+
|
|
32
|
+
After adding a signed-in realm, probe and persist its current stable subject explicitly:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
ghostget auth bind linkedin-main --site linkedin
|
|
36
|
+
ghostget auth bind x-main --site x
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Before a private read or any dispatch:
|
|
40
|
+
|
|
41
|
+
1. Resolve the current viewer/account through a reviewed first-party identity request.
|
|
42
|
+
2. Require one stable provider ID.
|
|
43
|
+
3. Compare it with the realm's expected account binding.
|
|
44
|
+
4. For actor-bearing requests, require the request actor to equal that binding.
|
|
45
|
+
5. Require the response actor and requested target/parent bindings to match the plan.
|
|
46
|
+
|
|
47
|
+
Fail before dispatch on a missing, ambiguous, changed, or mismatched identity. Use a new auth ID for a second account. Require an explicit reviewed rebind after a deliberate login change; do not mutate an existing realm silently.
|
|
48
|
+
|
|
49
|
+
Official OAuth auth is a separate realm and must satisfy its own subject/scope binding. Never fall back between browser-session and OAuth auth.
|
|
50
|
+
|
|
51
|
+
## Use persistent reads without changing their meaning
|
|
52
|
+
|
|
53
|
+
A successful subject-bound R1 invocation publishes one encrypted snapshot of
|
|
54
|
+
its exact validated input and bounded output. Repeat the same invocation with
|
|
55
|
+
`--cache-only` to read it without a browser or provider roundtrip. Omit the flag
|
|
56
|
+
to rerun the reviewed R1 contract and publish a newer validation.
|
|
57
|
+
|
|
58
|
+
Treat the adapter hash, operation, full auth realm, verified subject, validated
|
|
59
|
+
input, transport, and exact executable contract as part of the query identity.
|
|
60
|
+
Do not drop a cursor, change a limit, expand a folder, or substitute an auth ID
|
|
61
|
+
to force a hit. A contract or account change intentionally produces a miss.
|
|
62
|
+
|
|
63
|
+
Cache freshness is an observation, not provider authority. An unchanged
|
|
64
|
+
revalidation advances validation time without fabricating a data revision.
|
|
65
|
+
Failed, partial, or indeterminate reads retain the last good snapshot.
|
|
66
|
+
Revalidation reruns the selected R1 operation; it does not silently
|
|
67
|
+
perform `auth sync`, and it must not introduce acknowledgement or presence
|
|
68
|
+
effects outside that operation's reviewed contract.
|
|
69
|
+
|
|
70
|
+
The separate omni storage class derives a strict shared Conversation, Message,
|
|
71
|
+
or Notification only through a provider-owned, versioned materializer. Its
|
|
72
|
+
account-lifetime identity includes the adapter, provider plugin closure,
|
|
73
|
+
surface, and auth incarnation. Provider pages retain explicit completeness,
|
|
74
|
+
membership, cursor, and tombstone evidence. Absence never means deletion
|
|
75
|
+
without a complete partition or explicit tombstone. Omni v1 has no
|
|
76
|
+
provider-authored write-invalidation tags. Auth-incarnation, materializer, and
|
|
77
|
+
plugin implementation identity changes strand the prior normalized
|
|
78
|
+
coordinates, while exact-query freshness advances only through explicit
|
|
79
|
+
revalidation. A materializer failure records the failed exact data revision and
|
|
80
|
+
retains the last good entities as `retained-after-drift`; it must not weaken
|
|
81
|
+
parsing or mutate the exact snapshot to make drift disappear.
|
|
82
|
+
|
|
83
|
+
Auth replacement and removal rotate a durable local lifetime identity before
|
|
84
|
+
cleanup. Projection and provider-session ciphertext from an earlier lifetime
|
|
85
|
+
must remain unreadable even if identical locator bytes are later recreated.
|
|
86
|
+
|
|
87
|
+
The projection key is bound to an authenticated store-ownership marker. Ghostget
|
|
88
|
+
refuses a missing, malformed, or replacement key while projection ciphertext
|
|
89
|
+
or that marker remains. If the key is irretrievably lost, remove exactly
|
|
90
|
+
`read-projections/`, `omni-read-projections/`, `.projection-encryption-key`, and
|
|
91
|
+
`read-projection-control/store-key.json` beneath `GHOSTGET_STATE_HOME`, retain the
|
|
92
|
+
other control records, and rebuild snapshots through live revalidation.
|
|
93
|
+
|
|
94
|
+
## Constrain native provider CLIs
|
|
95
|
+
|
|
96
|
+
Treat a provider CLI as one reviewed transport, not as a shell. Require a
|
|
97
|
+
schema-v6 `localCli` selector backed by a source-plugin tool identity that pins
|
|
98
|
+
the final executable digest for the current platform. A package-manager name,
|
|
99
|
+
version range, release tag, reported version, or launcher digest is not enough.
|
|
100
|
+
|
|
101
|
+
Use only operation-owned fixed argument templates. Strip ambient credentials,
|
|
102
|
+
targets, account defaults, proxies, update settings, debug state, and user
|
|
103
|
+
plugin discovery from the child environment. Give the process private bounded
|
|
104
|
+
config, data, cache, and temporary roots. Require exact account, target,
|
|
105
|
+
conversation, message, and other resource IDs. Never use an interactive picker
|
|
106
|
+
or fuzzy selector for a mutation.
|
|
107
|
+
|
|
108
|
+
Parse stdout and stderr strictly from `unknown`; cap both and enforce a
|
|
109
|
+
Ghostget-owned deadline because an upstream timeout flag may not be effective.
|
|
110
|
+
Do not log or persist argv. When the upstream CLI accepts private text only in
|
|
111
|
+
argv, document the same-account process-inspection exposure and minimize the
|
|
112
|
+
child lifetime.
|
|
113
|
+
|
|
114
|
+
For a mutation, enter the durable dispatch boundary before process start. A
|
|
115
|
+
timeout, signal, malformed response, or lost response after that point is
|
|
116
|
+
indeterminate. Never let an upstream retry option or a new process invocation
|
|
117
|
+
bypass Ghostget's at-most-once fence. Reconcile only through a separate exact
|
|
118
|
+
read declared by the semantic operation.
|
|
119
|
+
|
|
120
|
+
## Keep browser authority narrow
|
|
121
|
+
|
|
122
|
+
Prefer target-filtered cookies. Use a path-backed private profile snapshot only when capture or a reviewed token source needs storage beyond cookies. Schema-v1/v2 DOM recipes are retired and fail validation, installation, planning, and execution for every origin; the direct browser-recipe executor is disabled as well. Never automate a concurrently running source profile.
|
|
123
|
+
|
|
124
|
+
Use agent-browser only for:
|
|
125
|
+
|
|
126
|
+
- rendered capture or HAR recording;
|
|
127
|
+
- sign-in/session bootstrap in a task-owned profile;
|
|
128
|
+
- cookie acquisition;
|
|
129
|
+
- one reviewed meta/storage/captured-header secret source;
|
|
130
|
+
- one current registered-operation revision lookup.
|
|
131
|
+
|
|
132
|
+
Do not use it to click, type, upload, publish, react, or send at runtime for a supported capability. DOM state is neither the operation contract nor its verification result.
|
|
133
|
+
|
|
134
|
+
Profile mode may have broader public-host egress than filtered cookies. `--trust-profile-egress` acknowledges that exposure; it does not widen allowed API origins or permit private-network access.
|
|
135
|
+
|
|
136
|
+
## Constrain first-party HTTP
|
|
137
|
+
|
|
138
|
+
Keep request construction in code. Fix the origin, method, path structure, query names, body shape, headers, timeout, response limit, successful status/content-type pairs, projections, and bindings. Reject redirects.
|
|
139
|
+
|
|
140
|
+
Send session cookies only to the reviewed exact origin. Send CSRF/XSRF and authorization values only from the reviewed source to the fixed matching header. Keep those values in memory and never return them from the bootstrap helper.
|
|
141
|
+
|
|
142
|
+
Do not add a generic HTTP, GraphQL, Rest.li, header, or URL interface. A captured endpoint is evidence, not authority. If a contract is absent or drifted, return `capture-required` and perform no request.
|
|
143
|
+
|
|
144
|
+
## Minimize HAR exposure
|
|
145
|
+
|
|
146
|
+
- Default to `--content none`.
|
|
147
|
+
- Record one operation and one bounded fixture at a time.
|
|
148
|
+
- Use mode-`0700` directories and mode-`0600` files.
|
|
149
|
+
- Avoid printing or searching raw HAR values in terminal output.
|
|
150
|
+
- Finish or discard every managed derivation.
|
|
151
|
+
- Delete externally supplied HARs after `ghostget derive analyze`.
|
|
152
|
+
- Use `ghostget derive review` only while the managed HAR is task-owned private state. The first review seals recording, list output exposes only bounded sanitized entry metadata, and `--fixtures -` accepts labeled strings only over stdin without echoing or persisting their values. The entry-only `--field-names -` probe accepts 1–50 unique, bounded, non-credential schema-key hypotheses on stdin and reports only candidate indices, fixed structural locations, structural value types, and truncation. It compares exact own keys in bounded parsed JSON, never values, and keeps credential subtrees and dynamic-map positions opaque. The two stdin probes are mutually exclusive and invalid input fails before sealing. `--review-origin` may select one canonical exact HTTPS origin only when its hostname was admitted by the immutable `--domains` declaration at derivation start; undeclared origins fail before sealing. Review cannot replay a request.
|
|
153
|
+
- Serialize each derivation from preflight through cleanup with its fixed identity-bound lifecycle gate. Publish an initialization marker as soon as the socket boundary exists, and publish readiness only after HAR capture, final in-origin validation, and exact session-metadata binding. Only `list` and `discard` may inspect unready or post-reboot state; never delete a live helper that could not be closed.
|
|
154
|
+
- Treat the local OS account as the filesystem trust boundary. Inode binding, no-follow traversal, and unpredictable quarantine names protect against symlink swaps and accidental or cooperative same-account races; they cannot defend against hostile code already running as the same account, which can mutate `GHOSTGET_STATE_HOME` and browser state directly. Keep that account and machine trusted.
|
|
155
|
+
- Never commit a raw HAR, authenticated DOM, screenshot, profile, cookie file, or storage dump.
|
|
156
|
+
|
|
157
|
+
Successful finish deletes the managed raw HAR and emits inert structural evidence. Even that evidence can reveal operation names and response field names; review it before publishing.
|
|
158
|
+
|
|
159
|
+
## Interpret execution states
|
|
160
|
+
|
|
161
|
+
- `capture-required`: no current reviewed runtime contract exists. No request or browser-action fallback may run.
|
|
162
|
+
- `pending`: ghostget durably reserved a confirmed action, but no terminal result exists. Reconcile it.
|
|
163
|
+
- `succeeded`: an R1 request passed its exact response contract.
|
|
164
|
+
- `submitted`: every planned R2/R3 dispatch passed its exact response and target/account bindings.
|
|
165
|
+
- `failed`: execution stopped before dispatch. Diagnose and create a fresh preview only if the action remains authorized.
|
|
166
|
+
- `partial`: earlier dispatches were verified, but the schedule stopped before completion.
|
|
167
|
+
- `indeterminate`: a dispatch started, but its response or binding could not be verified.
|
|
168
|
+
|
|
169
|
+
Never retry `pending`, `partial`, or `indeterminate` automatically. Do not clear the ledger or change whitespace/metadata to evade duplicate refusal.
|
|
170
|
+
|
|
171
|
+
`submitted` is stronger than a cleared composer because it requires a reviewed response contract. It still does not create a provider-side exactly-once transaction. Inspect remote state when the action matters.
|
|
172
|
+
|
|
173
|
+
## Reconcile uncertainty
|
|
174
|
+
|
|
175
|
+
1. Record the run ID and inspect `ghostget runs show <run-id>`.
|
|
176
|
+
2. For a supported exact desired-state readback, run `ghostget runs reconcile
|
|
177
|
+
<run-id> --json`. Current runs recover their original input only from the
|
|
178
|
+
encrypted run-, auth-, and contract-bound capsule. The recognized legacy X
|
|
179
|
+
bookmark run instead requires its exact original input through `--input`;
|
|
180
|
+
ghostget verifies the receipt's canonical input hash before any read.
|
|
181
|
+
3. Use only a separate reviewed R1 request that inspects the exact target
|
|
182
|
+
without acknowledgement traffic. The reconciler validates the returned
|
|
183
|
+
state kind and target before recording it.
|
|
184
|
+
4. Treat every reconciliation as an append-only observation. It never changes
|
|
185
|
+
the original receipt, idempotency ledger, or provider state and never
|
|
186
|
+
creates retry authority.
|
|
187
|
+
Once an exact readback durably records `desired-state-observed`, ghostget
|
|
188
|
+
releases only that run's encrypted capsule and digest-bound attachment
|
|
189
|
+
bundle. A nonmatching or inconclusive observation retains both so another
|
|
190
|
+
bounded inspection remains possible.
|
|
191
|
+
5. A currently absent desired state does not prove that an earlier write never
|
|
192
|
+
applied briefly. Leave the ledger intact whether the effect is present,
|
|
193
|
+
absent, or still uncertain.
|
|
194
|
+
6. Wait and inspect again when provider processing may be delayed. Issue a
|
|
195
|
+
materially new action only after fresh authorization and a new exact
|
|
196
|
+
preview; never retry the unsettled action automatically.
|
|
197
|
+
|
|
198
|
+
Receipts keep hashes, contract identity, transport, account-realm fingerprint, dispatch counts, origin, timestamps, and categorical errors. They omit credentials, response bodies, message/post text, private identifiers not required for reconciliation, and original attachment paths.
|
|
199
|
+
|
|
200
|
+
Recovery capsules are private AES-GCM state under `GHOSTGET_STATE_HOME`. They contain
|
|
201
|
+
the exact confirmed input needed for a bounded readback but never appear in
|
|
202
|
+
receipts, plans, logs, or reconciliation observations. Do not delete the
|
|
203
|
+
recovery key or capsule for an unsettled run; a missing key is not regenerated
|
|
204
|
+
during readback, and new writes are refused while older capsules remain,
|
|
205
|
+
because replacing the key would only destroy recoverability. Confirmed
|
|
206
|
+
attachment bundles follow the same lifecycle: settled and proven pre-dispatch
|
|
207
|
+
outcomes remove them, while `pending`, `partial`, and `indeterminate` runs keep
|
|
208
|
+
them until an exact successful reconciliation is durably recorded.
|
|
209
|
+
|
|
210
|
+
## Clean up task-owned state
|
|
211
|
+
|
|
212
|
+
Cancel unused plans with `ghostget plans cancel <digest> --yes`, discard derivations with `ghostget derive discard <id> --yes`, and remove obsolete auth locators explicitly. Uninstalling the wrapper does not recursively remove browser credentials or ghostget state.
|
|
213
|
+
|
|
214
|
+
If browser capture/bootstrap shutdown cannot be verified, preserve the exact recovery handle and close only that task-owned session before deleting its directories. Do not use broad recursive cleanup against shared browser state.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Social settlement and duplicate cleanup
|
|
2
|
+
|
|
3
|
+
Use this after every confirmation and before any possible repost or deletion.
|
|
4
|
+
|
|
5
|
+
## Settle one publish attempt
|
|
6
|
+
|
|
7
|
+
1. Run `ghostget runs show <run-id> --json` and append the result state to the task ledger.
|
|
8
|
+
2. Record any response-bound provider locator. Do not recover a target by text search, profile-feed position, or approximate time.
|
|
9
|
+
3. For `submitted`, use the publish contract's independently verified readback evidence. When it does not establish external availability and an observed `posts.read` accepts the exact returned locator, invoke that exact R1 schema and record the observation.
|
|
10
|
+
4. For `pending`, `partial`, or `indeterminate`, preserve all evidence. Run `ghostget runs reconcile <run-id> --json` only when the installed exact contract advertises reconciliation. Reconciliation is read-only, append-only, and never repeats the mutation.
|
|
11
|
+
5. Treat an absent or inconclusive read as unresolved, not as proof that the write never happened. Repeat only the bounded read/reconciliation when supported; never repeat the mutation.
|
|
12
|
+
6. For pre-dispatch `failed`, create a new preview only while the exact original action remains authorized.
|
|
13
|
+
|
|
14
|
+
If a current legacy reconciler explicitly requests original input, supply only the exact confirmed input that Ghostget verifies against the receipt. Never reconstruct or alter it to force a match.
|
|
15
|
+
|
|
16
|
+
## Keep an exact duplicate ledger
|
|
17
|
+
|
|
18
|
+
Maintain a private append-only event ledger with one attempt row containing:
|
|
19
|
+
|
|
20
|
+
- package identity and exact scalar-input hash;
|
|
21
|
+
- ordered attachment hashes and media types;
|
|
22
|
+
- platform, adapter, transport, auth-realm label, and bound subject;
|
|
23
|
+
- plan digest and expiry, run ID, and current run state;
|
|
24
|
+
- exact provider locator returned or retained after acceptance;
|
|
25
|
+
- readback kind and first observed time;
|
|
26
|
+
- `duplicate-risk-of` links to earlier attempt run IDs;
|
|
27
|
+
- any canonical delete plan/run and exact post-delete proof.
|
|
28
|
+
|
|
29
|
+
Do not put credentials, cookie values, response bodies, post text, or original local paths in the ledger. Never merge two attempts because their text looks alike. Record one provider object per exact locator, including an intentional duplicate.
|
|
30
|
+
|
|
31
|
+
## Create a fresh duplicate-tolerant intent
|
|
32
|
+
|
|
33
|
+
Only proceed when the user freshly authorizes the exact platform, exact package, and possibility that the unresolved source run already created the post. Append the source link to the private task ledger, then create a fresh preview:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
ghostget invoke <adapter> posts.publish \
|
|
37
|
+
--input @/absolute/private/post-input.json \
|
|
38
|
+
--auth <bound-auth-id> \
|
|
39
|
+
--duplicate-risk-of <indeterminate-run-id> \
|
|
40
|
+
--preview --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Version 1 accepts exactly one source run and only a one-dispatch R3 `web-session-api` `posts.publish` operation. An official OAuth or other `provider-api` attempt is ineligible. Ghostget must prove that the source is an unclaimed, retained, terminal `indeterminate` run with the exact same adapter, auth realm, operation, risk, input, contract, receipt, journal, ledger, recovery capsule, and retained attachment bytes. A historical attempt under another contract or adapter remains in the task ledger but is not a valid source. Review the warning and successor fingerprint in the new preview, then confirm its digest once; never put `--duplicate-risk-of` on `ghostget confirm`.
|
|
44
|
+
|
|
45
|
+
Ghostget permanently elects only one successor for the source and keeps successful successor idempotency evidence from expiring. If the source changes, reconciles, lacks exact retained evidence, already elected a successor, or fails any binding check, stop and report the refusal. Do not select a looser source, add a nonce, clear state, or bypass the check.
|
|
46
|
+
|
|
47
|
+
If a duplicate-intent child fails before successor election, its dispatch remains at zero and the source can remain eligible; re-check both runs, then re-preview that same source to derive the same successor intent. If the source was elected but a later local journal step failed, the lineage is intentionally stranded and must not be retried. If a child becomes `indeterminate` after dispatch and another possible duplicate is freshly authorized, cite that eligible child—not any ancestor—to extend one linear chain. Never branch or reuse an already claimed source.
|
|
48
|
+
|
|
49
|
+
This does not settle or replace an older run. Keep its Ghostget ledger and recovery material intact, and reconcile it separately when exact evidence becomes available.
|
|
50
|
+
|
|
51
|
+
## Delete a proven duplicate
|
|
52
|
+
|
|
53
|
+
Deletion is eligible only when all of these are true:
|
|
54
|
+
|
|
55
|
+
1. The exact provider locator is in the duplicate ledger.
|
|
56
|
+
2. An observed exact `posts.read` proves the object, current-account authorship, and content/media binding before deletion.
|
|
57
|
+
3. The same installed adapter exposes canonical `content.delete` as observed and executable. An absent or `capture-required` operation, or an R4 runtime block, means deletion is unavailable.
|
|
58
|
+
4. Its schema accepts that exact locator; the preview binds the account, target, side effect, and contract; and the user confirms that digest once.
|
|
59
|
+
5. A separate exact post-delete R1 contract proves a target-bound tombstone or exact not-found result whose reviewed semantics establish deletion. General feed absence is not proof.
|
|
60
|
+
|
|
61
|
+
If deletion becomes `pending`, `partial`, or `indeterminate`, preserve it and reconcile only through its advertised exact readback. Never retry deletion. Never substitute `posts.delete`, another semantic name, direct browser interaction, raw HTTP, or capture replay for `content.delete`.
|
|
62
|
+
|
|
63
|
+
For the observed Bluesky contract, carry the exact authored `post_uri` and the
|
|
64
|
+
authoritative current `expected_cid` into the preview. CID drift is a refusal,
|
|
65
|
+
not permission to delete a newer revision. A successful mutation is settled
|
|
66
|
+
only by authoritative PDS `RecordNotFound`; AppView/feed absence alone is not
|
|
67
|
+
proof. Never use this cleanup path for an intended post merely because another
|
|
68
|
+
platform attempt is uncertain.
|
|
69
|
+
|
|
70
|
+
## Report availability time precisely
|
|
71
|
+
|
|
72
|
+
Keep these times distinct:
|
|
73
|
+
|
|
74
|
+
- plan creation/confirmation: local authorization, not publication;
|
|
75
|
+
- dispatch start/finish: Ghostget transport timing, not external availability;
|
|
76
|
+
- provider-created time: a provider-authored value, when strictly bound;
|
|
77
|
+
- first observed time: when exact independent readback saw the object.
|
|
78
|
+
|
|
79
|
+
Report first observation as “available no later than” that time; the actual visibility onset may have been earlier. When readback remains unresolved, say “provider accepted” only when proven and “external availability unverified.”
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Social platform routing
|
|
2
|
+
|
|
3
|
+
Use this as routing guidance only. Always inspect `ghostget capabilities <adapter> --json`; installed adapter state and schemas are authoritative and may change.
|
|
4
|
+
|
|
5
|
+
| Surface | Candidate adapter | Signed-in realm | Reference post shape | Meaning |
|
|
6
|
+
| --- | --- | --- | --- | --- |
|
|
7
|
+
| X | `x-web` | Browser cookies/profile | `body`; optional image fields when exposed | Consumer X post |
|
|
8
|
+
| X | `x` | Official OAuth | `body`, optional `media` and aligned alt-text fields; leave `made_with_ai` unset or `false` for user-supplied cross-post copy | Documented API post |
|
|
9
|
+
| LinkedIn | `linkedin-web` | Browser cookies/profile | `body`, `visibility`, optional image and accessibility fields | Member or explicitly bound organization post |
|
|
10
|
+
| LinkedIn | `linkedin` | Official OAuth | Inspect installed schema | Documented API post |
|
|
11
|
+
| Bluesky | `bluesky-web` | Profile-backed Bluesky web session | `body`, optional image, media type, and alt text | AT Protocol feed post |
|
|
12
|
+
| Substack | `substack-web` | Browser cookies/profile | `body`, optional Note media | Public Substack Note, not an article/newsletter |
|
|
13
|
+
| Threads | `meta-web` | Browser cookies/profile | Text/image `posts.publish`: `body`, audience, optional one PNG. Video `media.publish`: `body`, audience, one MP4. | Threads post |
|
|
14
|
+
|
|
15
|
+
Cleanup is capability-driven too. At this reference revision, `bluesky-web`
|
|
16
|
+
exposes observed `content.delete@1` only for one current-account post URI plus
|
|
17
|
+
its exact confirmed CID. `reddit-web` exposes observed `content.delete@1` only
|
|
18
|
+
for one exact current-account post fullname plus its confirmed title, followed
|
|
19
|
+
by independent absence readback. `x-web` reserves `content.delete@1` as
|
|
20
|
+
`capture-required`; `substack-web content.delete@1` is observed for one exact
|
|
21
|
+
authored personal Note with exact actor/body pre-read and independent 404
|
|
22
|
+
absence. LinkedIn and Threads
|
|
23
|
+
deletion remain unavailable unless their installed canonical capability
|
|
24
|
+
independently says otherwise.
|
|
25
|
+
|
|
26
|
+
## Selection rules
|
|
27
|
+
|
|
28
|
+
- Use exactly one adapter and one stable bound account realm per surface.
|
|
29
|
+
- Prefer the transport the user named or already configured. Do not fall back from browser-session to OAuth, or vice versa, because one operation is unavailable.
|
|
30
|
+
- Require `posts.publish.state == "observed"`. An invalid adapter or `capture-required` operation must produce no request.
|
|
31
|
+
- Treat each current schema's required fields, file cardinality, byte/media bounds, and accessibility-field shape literally. The table is not a capability promise.
|
|
32
|
+
- Preserve input image order. Require alt-text arrays to align one-to-one when the schema exposes them.
|
|
33
|
+
- Re-check capabilities before every new preview. A plan or run remains governed by its bound contract identity when installed support later changes.
|
|
34
|
+
- A provider may reject an otherwise valid image for dimensions, animation, color profile, or account entitlement. Report that provider-owned failure without converting the file unless the user asks for a derivative.
|
|
35
|
+
- For user-supplied cross-post copy, never mark the package as AI-generated. Follow [X AI disclosure](x-ai-disclosure.md). Leave official `x` `made_with_ai` unset or `false`. `x-web` `posts.publish` has no such input field.
|
|
36
|
+
- Prefer a Ghostget transport over the X composer. If the user explicitly requested a composer fallback, require Content disclosure Made with AI OFF before Post, then open the live permalink. A sparkle label means that target failed.
|
|
37
|
+
|
|
38
|
+
## Common invocation shape
|
|
39
|
+
|
|
40
|
+
Write exact input JSON to a private task file when shell quoting would be fragile, then invoke:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
ghostget invoke <adapter> posts.publish \
|
|
44
|
+
--input @/absolute/private/post-input.json \
|
|
45
|
+
--auth <bound-auth-id> \
|
|
46
|
+
--preview --json [--headed]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Review the returned digest and confirm it within five minutes:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
ghostget confirm <plan-digest> --json [--headed]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Use headed execution when the installed signed-in web adapter or bound realm requires it and the user authorized it. Follow the preview's returned `confirmCommand` exactly so headed mode is preserved.
|
|
56
|
+
|
|
57
|
+
Do not place credentials in the input file. Delete task input files after planning; Ghostget's plan owns encrypted confirmed input and attachment bundles for its lifecycle.
|
|
58
|
+
|
|
59
|
+
## Parity decisions
|
|
60
|
+
|
|
61
|
+
- If text exceeds one platform's bound, request shorter shared copy or an explicit platform-specific variant. Do not silently use `threads.publish`.
|
|
62
|
+
- If the ordered image set exceeds one platform's bound, request a smaller shared set or an explicit per-platform set. Do not manufacture a collage.
|
|
63
|
+
- If LinkedIn requires visibility and the user requested a public cross-post, use `public`; otherwise obtain the user's audience choice.
|
|
64
|
+
- If Threads requires `audience` and the user requested ordinary posting, use the installed schema's ordinary/default audience only when that meaning is explicit in the capability description.
|
|
65
|
+
- At this reference revision, reviewed Threads text/image publication accepts no attachment or exactly one PNG, and reviewed video publication requires exactly one MP4. A dummy PNG, collage, or composer click-path changes the package and is not an installed fallback. JPEG and other image types remain unavailable unless the installed schema independently lists them.
|
|
66
|
+
- If image alt text is supported on only some targets, preserve the same factual description on every target that accepts it; unsupported alt text is not a reason to alter the visible post.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Social profile statistics
|
|
2
|
+
|
|
3
|
+
Use this workflow for a scheduled, read-only collection of exact counters from
|
|
4
|
+
explicitly selected social profiles, owned publications, and organization
|
|
5
|
+
pages. Ghostget owns acquisition, invocation authority, and target binding. The consumer
|
|
6
|
+
owns history, public field selection, presentation, and delivery.
|
|
7
|
+
|
|
8
|
+
## Preconditions
|
|
9
|
+
|
|
10
|
+
Run `ghostget operator doctor --json`, then inspect each named adapter with
|
|
11
|
+
`ghostget capabilities <adapter> --json`. Every requested operation must be
|
|
12
|
+
installed, `observed`, and R1. Every authenticated operation must be bound to
|
|
13
|
+
the intended account realm; a public operation must instead prove its exact
|
|
14
|
+
requested target. Record a gap for a missing, changed, ambiguous, or
|
|
15
|
+
cleanup-unsafe realm and continue with the independent rows. `capture-required`
|
|
16
|
+
is not a partial success and performs no provider request.
|
|
17
|
+
|
|
18
|
+
Use a normal invocation, never `--cache-only`, for today's observation. A
|
|
19
|
+
cached value may explain the last known level, but it cannot become today's
|
|
20
|
+
sample. Do not use general browser automation, selectors, raw HTTP, or a public
|
|
21
|
+
page's rounded display as a fallback.
|
|
22
|
+
|
|
23
|
+
## Hraness account manifest
|
|
24
|
+
|
|
25
|
+
The authoritative ordered collection contract is the strict
|
|
26
|
+
[Hraness social-profile manifest](hraness-social-profile-stats.json). Load it
|
|
27
|
+
as foreign JSON, reject unknown fields and duplicate account keys, then flatten
|
|
28
|
+
each account's ordered `reads` array without changing order. Its auth IDs are
|
|
29
|
+
local Ghostget locators, not credentials.
|
|
30
|
+
|
|
31
|
+
Before invoking a read, confirm that the current installed adapter still owns
|
|
32
|
+
the named operation with `state: "observed"`, `risk: "R1"`, and
|
|
33
|
+
`sideEffect: "none"`. Confirm its public or authenticated authority kind, exact
|
|
34
|
+
input, output provider and canonical target URL, metric keys, expected gaps,
|
|
35
|
+
and `requiredDelayBeforeMs`. A mismatch is a categorical contract gap for that
|
|
36
|
+
read. Do not reinterpret the manifest or fall back to a different capability.
|
|
37
|
+
The current X accounts are `x-hraness` and `x-lifedaysleft`.
|
|
38
|
+
The second exact handle is `lifedaysleft`.
|
|
39
|
+
|
|
40
|
+
Bluesky and GitHub profile and organization statistics come from public target-bound APIs.
|
|
41
|
+
Invoke these rows without `--auth`. Ghostget assigns each reviewed operation a
|
|
42
|
+
deterministic public authority for receipts and exact R1 caching. Supplying an
|
|
43
|
+
auth locator is an error.
|
|
44
|
+
|
|
45
|
+
The Twitch row targets exactly
|
|
46
|
+
`https://www.twitch.tv/hranessdotcom`. Invoke the installed observed
|
|
47
|
+
`twitch-web profiles.read` capability with `{"profile":"hranessdotcom"}` and
|
|
48
|
+
the `twitch-chrome` realm. Ghostget binds the authenticated current viewer before
|
|
49
|
+
it binds the fixed login-parameterized channel response to that viewer's
|
|
50
|
+
immutable identity, then accepts followers only as an exact nonnegative
|
|
51
|
+
integer. A missing, changed, or mismatched realm, an ambiguous target, or
|
|
52
|
+
provider drift creates a categorical gap. Do not substitute browser
|
|
53
|
+
automation, raw HTTP, a rounded public display, a cached value, or an estimate.
|
|
54
|
+
|
|
55
|
+
Keep the two X calls sequential, both LinkedIn calls sequential, and both
|
|
56
|
+
Substack calls sequential because each pair shares one authenticated realm.
|
|
57
|
+
`linkedin-chrome` must be a path-backed `browser-profile` locator over a
|
|
58
|
+
private dormant Chrome snapshot, optionally overlaid with current filtered
|
|
59
|
+
cookies from the selected Chrome profile. A cookie-source-only LinkedIn realm
|
|
60
|
+
is not an acceptable scheduled fallback because LinkedIn invalidates the
|
|
61
|
+
exported session outside its browser/device context. Before the initial
|
|
62
|
+
snapshot, or after a contained identity preflight returns 401, load LinkedIn
|
|
63
|
+
normally in the source Chrome profile, confirm the session is current, fully
|
|
64
|
+
quit Chrome, and replace the dormant snapshot. A filtered cookie overlay does
|
|
65
|
+
not revive a stale source session.
|
|
66
|
+
Leave a 60-second idle interval after the LinkedIn personal read before the
|
|
67
|
+
company read; current live evidence shows shorter intervals can trigger a
|
|
68
|
+
temporary identity-preflight redirect even when the realm remains correctly
|
|
69
|
+
bound. Do not routinely rebind or rotate the locator.
|
|
70
|
+
The first scheduled version should run the whole table sequentially. This is a
|
|
71
|
+
small daily workload and avoids provider bootstrap, keychain, and session-lock
|
|
72
|
+
contention. A later caller may parallelize distinct realms with a small bound,
|
|
73
|
+
but must never overlap work on the same `(surface, auth ID)` pair.
|
|
74
|
+
|
|
75
|
+
Invoke each row with bounded stdin and exact JSON output:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
printf '%s' '<input-json>' \
|
|
79
|
+
| ghostget invoke <adapter> <operation> --input - --auth <auth-id> --json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
For the public Bluesky and GitHub rows, omit the auth option:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
printf '%s' '{"handle":"hraness.bsky.social"}' \
|
|
86
|
+
| ghostget invoke bluesky-web profiles.read --input - --json
|
|
87
|
+
printf '%s' '{"username":"0thernet"}' \
|
|
88
|
+
| ghostget invoke github-web profiles.read --input - --json
|
|
89
|
+
printf '%s' '{"organization":"hraness"}' \
|
|
90
|
+
| ghostget invoke github-web organizations.read --input - --json
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`status: "failed"` R1 envelopes include one secret-free `readFailure`
|
|
94
|
+
projection with a closed `category` and its only valid
|
|
95
|
+
`retryDisposition`. A caller may make at most one retry for the read, after
|
|
96
|
+
60 seconds, and only when the disposition is
|
|
97
|
+
`retry-once-after-60s`. A transport retry consumes that same budget. Never
|
|
98
|
+
retry `repair-auth` or `do-not-retry`; report the bounded category and
|
|
99
|
+
continue with the next independent row. Do not parse receipt errors or
|
|
100
|
+
provider exception text to invent a retry policy. Do not clear durable cleanup
|
|
101
|
+
admission or reboot a host without separate operator authorization.
|
|
102
|
+
|
|
103
|
+
`github-web organizations.read` first binds the exact organization and its
|
|
104
|
+
declared public repository count, then completes the fixed public repository
|
|
105
|
+
pagination before summing `stargazers_count`. It returns `stars` only when the
|
|
106
|
+
complete repository set is available and bound; it never substitutes a partial
|
|
107
|
+
page, a rounded display total, or a prior observation.
|
|
108
|
+
|
|
109
|
+
The manifest marks Threads `recentViews` with the exact unavailable reason
|
|
110
|
+
`not-authorized` as an expected categorical gap until the account becomes
|
|
111
|
+
eligible. Keep reporting only that reason as unavailable. Treat
|
|
112
|
+
`provider-drift`, `not-exposed`, and every other unavailable reason as an
|
|
113
|
+
unexpected failure. Accept the metric normally once the same target-bound read
|
|
114
|
+
returns an exact available count.
|
|
115
|
+
|
|
116
|
+
Do not put an auth ID, provider receipt, cache key, run ID, subject identifier,
|
|
117
|
+
or raw provider response in the consumer snapshot. Do not print or persist
|
|
118
|
+
cookies, headers, tokens, HTML, first-party response bodies, or exception text.
|
|
119
|
+
|
|
120
|
+
## Accept exact metric observations
|
|
121
|
+
|
|
122
|
+
Accept a row only when the live invocation reports a succeeded R1 receipt and
|
|
123
|
+
its live output binds the requested provider and canonical target, plus the
|
|
124
|
+
current realm for authenticated operations. The profile-stat envelope is
|
|
125
|
+
version 1 and contains:
|
|
126
|
+
|
|
127
|
+
- `provider`, `target`, `observedAt`, and `completeness`;
|
|
128
|
+
- one metric record per requested counter, including categorical unavailable
|
|
129
|
+
records when the provider cannot expose an exact value;
|
|
130
|
+
- bounded public metadata such as handle, display name, bio, or public website.
|
|
131
|
+
|
|
132
|
+
Each publishable metric must have `status: "available"`,
|
|
133
|
+
`precision: "exact"`, `unit: "count"`, and a nonnegative safe-integer `value`.
|
|
134
|
+
Reject `500+`, `1.2K`, estimated, lower-bound, rounded, hidden, unavailable, and
|
|
135
|
+
provider-drift values. A provider may return them as categorical unavailable
|
|
136
|
+
evidence, but the consumer must not coerce them. Accept each exact available
|
|
137
|
+
metric independently once the invocation and target are valid. A partial
|
|
138
|
+
provider output may therefore advance followers while leaving recent views
|
|
139
|
+
unavailable. Substack is an intentional two-read join, but either target-bound
|
|
140
|
+
read may contribute its own exact metrics when the other read fails.
|
|
141
|
+
|
|
142
|
+
An unavailable metric creates a gap only for that metric. Never write zero,
|
|
143
|
+
copy the previous day into the scheduled date, or suppress a different exact
|
|
144
|
+
metric from the same account. Report failed consumer keys and metric keys with
|
|
145
|
+
bounded categorical reasons after the sequential collection completes.
|
|
146
|
+
|
|
147
|
+
## Install into Hraness
|
|
148
|
+
|
|
149
|
+
Build one mode-private temporary document with this exact public handoff:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"schemaVersion": 1,
|
|
154
|
+
"scheduledDate": "YYYY-MM-DD",
|
|
155
|
+
"timezone": "America/New_York",
|
|
156
|
+
"observations": [
|
|
157
|
+
{
|
|
158
|
+
"accountKey": "x-hraness",
|
|
159
|
+
"observedAt": "YYYY-MM-DDTHH:mm:ss.sssZ",
|
|
160
|
+
"metrics": {
|
|
161
|
+
"followers": 1,
|
|
162
|
+
"following": 1
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Run the consumer's installer from a clean, current Jungle worktree:
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
bun run --cwd projects/hraness social:install --input /absolute/private/run.json
|
|
173
|
+
bun run --cwd projects/hraness social:validate
|
|
174
|
+
bun run check:affected
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
For the Hraness consumer, the preferred daily entry point performs the fixed
|
|
178
|
+
sequential collection and installs its validated public subset directly:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
bun run --cwd projects/hraness social:refresh
|
|
182
|
+
bun run --cwd projects/hraness social:validate
|
|
183
|
+
bun run check:affected
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The installer is the only process allowed to update
|
|
187
|
+
`projects/hraness/app/social-stats.generated.json`. It validates the exact
|
|
188
|
+
configured metric subset, derives the Eastern date from each observation time,
|
|
189
|
+
preserves a newer same-day success, retains fourteen days, and writes canonical
|
|
190
|
+
JSON. Remove the temporary document after installation.
|
|
191
|
+
|
|
192
|
+
Review that the task diff contains only the checked social snapshot. Commit and
|
|
193
|
+
deliver it through the repository's current-main workflow, then verify the
|
|
194
|
+
Hraness production deployment. Never commit an empty or synthetic observation,
|
|
195
|
+
raw Ghostget output, capture evidence, or local state.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Social video platform routing
|
|
2
|
+
|
|
3
|
+
Use this as routing guidance only. Always inspect
|
|
4
|
+
`ghostget capabilities <adapter> --json`; installed adapter state and schemas
|
|
5
|
+
are authoritative and may change.
|
|
6
|
+
|
|
7
|
+
| Surface | Candidate adapter | Video operation | Meaning |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| X | `x-web` | `posts.publish` when the installed schema accepts `video/mp4` | Consumer X post. Observed `x-web` `posts.publish` now accepts one plan-bound PNG or one MP4. |
|
|
10
|
+
| X | `x` | `posts.publish` when the installed schema accepts `video/mp4` | Official OAuth post. Already schemas MP4. |
|
|
11
|
+
| LinkedIn | `linkedin` | video-capable `posts.publish` | Observed official OAuth member or explicitly bound organization post. |
|
|
12
|
+
| LinkedIn | `linkedin-web` | `media.publish` when observed | Consumer-web member video; currently a separate capture-required route so image `posts.publish` remains unchanged. |
|
|
13
|
+
| Bluesky | `bluesky-web` | `media.publish` | Observed AT Protocol video feed post; image `posts.publish` remains a separate observed contract. |
|
|
14
|
+
| Substack | `substack-web` | `media.publish` when observed | Public Substack Note, not an article or newsletter. |
|
|
15
|
+
| TikTok | `tiktok-web` | `media.publish` when observed | Native TikTok video |
|
|
16
|
+
| Instagram | `meta-web` on the Instagram surface | `media.publish` when observed | Instagram video or Reel only when the schema says so. |
|
|
17
|
+
| Threads | `meta-web` on the Threads surface | `media.publish` | Observed single-MP4 Threads video post; text/image `posts.publish` remains a separate contract. |
|
|
18
|
+
| YouTube Shorts | `youtube-web` | `media.publish` when observed | Studio video upload. Community `posts.publish` is not a Short. |
|
|
19
|
+
| Reddit | `reddit-web` | `media.publish` when observed | One video post in one exact confirmed subreddit. |
|
|
20
|
+
|
|
21
|
+
At the 2026-08-23 reference revision, `x-web` `posts.publish` is observed
|
|
22
|
+
for one plan-bound `image/png` or one plan-bound `video/mp4`. Official `x`
|
|
23
|
+
and official `linkedin` already observe MP4 post contracts. `reddit-web`
|
|
24
|
+
`media.publish@9` observes one plan-bound MP4 plus a required plan-bound
|
|
25
|
+
PNG/JPEG poster and explicit NSFW, spoiler, and reply declarations. Threads
|
|
26
|
+
`media.publish@1` observes one plan-bound ISO BMFF MP4, exact dimensions, its
|
|
27
|
+
single-request video upload, durable created-post identity, and independent
|
|
28
|
+
permalink actor/text/video readback. Bluesky `media.publish@2` observes one
|
|
29
|
+
plan-bound ISO BMFF MP4, the fixed first-party legacy upload and response-bound
|
|
30
|
+
processing job, processed blob, exact repository record, durable accepted
|
|
31
|
+
target, and authoritative PDS plus public AppView readbacks. LinkedIn web,
|
|
32
|
+
Substack Notes, TikTok, Instagram, and YouTube expose bounded video `media.publish`
|
|
33
|
+
reservations. Those routes stay `capture-required` until their exact upload,
|
|
34
|
+
processing, request, response, actor/target, and independent readback contracts
|
|
35
|
+
are implemented and proven.
|
|
36
|
+
For Substack specifically, an authorized profile-backed fixture proved 200
|
|
37
|
+
initialization, ordered raw multipart transfer, transcode, status polling, and
|
|
38
|
+
video-attachment creation. The final Note create returned 403 twice, including
|
|
39
|
+
one Ghostget-native attempt, so there is no provider-created video Note or exact
|
|
40
|
+
readback to graduate. `content.delete@1` is independently observed for cleanup
|
|
41
|
+
of an exact authored personal Note; that does not imply video publication.
|
|
42
|
+
Treat them as unavailable until the installed capability independently says
|
|
43
|
+
`observed`.
|
|
44
|
+
|
|
45
|
+
## Selection rules
|
|
46
|
+
|
|
47
|
+
- Use exactly one adapter and one stable bound account realm per surface.
|
|
48
|
+
- Prefer the transport the user named or already configured. Do not fall
|
|
49
|
+
back from browser-session to OAuth, or vice versa, because one operation
|
|
50
|
+
is unavailable.
|
|
51
|
+
- Require the chosen video operation's `state == "observed"`. An invalid
|
|
52
|
+
adapter or `capture-required` operation must produce no request.
|
|
53
|
+
- A text or image `posts.publish` is not a substitute for video.
|
|
54
|
+
- Re-check capabilities before every new preview.
|
|
55
|
+
- Tags are an explicit platform-specific variant only for TikTok,
|
|
56
|
+
Instagram, and YouTube Shorts. Leave X, LinkedIn, Substack, Bluesky,
|
|
57
|
+
Threads, and Reddit tag-free.
|
|
58
|
+
- Set each supported synthetic-media or AI declaration explicitly and
|
|
59
|
+
truthfully from the actual video's provenance; caption authorship does not
|
|
60
|
+
determine the media declaration. Follow [X AI disclosure](x-ai-disclosure.md)
|
|
61
|
+
for the official `x` `made_with_ai` choice, and do not invent a disclosure
|
|
62
|
+
field on an adapter whose installed schema does not expose one.
|
|
63
|
+
|
|
64
|
+
## Common invocation shape
|
|
65
|
+
|
|
66
|
+
Write exact input JSON to a private task file when shell quoting would be
|
|
67
|
+
fragile, then invoke:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
ghostget invoke <adapter> media.publish \
|
|
71
|
+
--input @/absolute/private/video-input.json \
|
|
72
|
+
--auth <bound-auth-id> \
|
|
73
|
+
--preview --json [--headed]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Use `posts.publish` instead only when the installed schema for that
|
|
77
|
+
adapter accepts `video/mp4` on that operation.
|
|
78
|
+
|
|
79
|
+
Review the returned digest and confirm it within five minutes:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
ghostget confirm <plan-digest> --json [--headed]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Follow the preview's returned `confirmCommand` exactly so headed mode is
|
|
86
|
+
preserved.
|
|
87
|
+
|
|
88
|
+
Do not place credentials in the input file. Delete task input files after
|
|
89
|
+
planning.
|