socialcli 0.3.0__py3-none-any.whl
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.
Potentially problematic release.
This version of socialcli might be problematic. Click here for more details.
- socialcli-0.3.0.dist-info/METADATA +168 -0
- socialcli-0.3.0.dist-info/RECORD +224 -0
- socialcli-0.3.0.dist-info/WHEEL +4 -0
- socialcli-0.3.0.dist-info/entry_points.txt +3 -0
- socialcli-0.3.0.dist-info/licenses/LICENSE +21 -0
- socialctl/__init__.py +0 -0
- socialctl/__main__.py +6 -0
- socialctl/adapters/__init__.py +6 -0
- socialctl/adapters/base.py +68 -0
- socialctl/adapters/errores.py +56 -0
- socialctl/adapters/facebook.py +180 -0
- socialctl/adapters/instagram.py +442 -0
- socialctl/adapters/tiktok.py +535 -0
- socialctl/adapters/youtube.py +331 -0
- socialctl/agent_errors.py +176 -0
- socialctl/agent_guide.py +23 -0
- socialctl/approval_cli.py +27 -0
- socialctl/auth.py +139 -0
- socialctl/authflow.py +344 -0
- socialctl/brands.py +194 -0
- socialctl/capabilities.py +57 -0
- socialctl/capabilities.yml +5945 -0
- socialctl/cli.py +1766 -0
- socialctl/connection_service/__init__.py +0 -0
- socialctl/connection_service/__main__.py +33 -0
- socialctl/connection_service/app.py +496 -0
- socialctl/connection_service/assets/PLATFORM-LOGOS-LICENSE.txt +50 -0
- socialctl/connection_service/assets/connection.css +75 -0
- socialctl/connection_service/assets/facebook.webp +0 -0
- socialctl/connection_service/assets/instagram.svg +194 -0
- socialctl/connection_service/assets/socialcli-logo.png +0 -0
- socialctl/connection_service/assets/tiktok.png +0 -0
- socialctl/connection_service/assets/youtube.svg +1 -0
- socialctl/connection_service/landing.py +146 -0
- socialctl/connection_service/legacy.py +48 -0
- socialctl/connection_service/peer.py +13 -0
- socialctl/connection_service/providers.py +324 -0
- socialctl/connection_service/settings.py +76 -0
- socialctl/connection_service/store.py +124 -0
- socialctl/connections/__init__.py +0 -0
- socialctl/connections/account_cli.py +438 -0
- socialctl/connections/cli.py +379 -0
- socialctl/connections/client.py +126 -0
- socialctl/connections/credential_cli.py +224 -0
- socialctl/connections/credential_store.py +49 -0
- socialctl/connections/file_store.py +193 -0
- socialctl/connections/keychain.py +78 -0
- socialctl/connections/meta_user.py +81 -0
- socialctl/connections/rotation_cli.py +116 -0
- socialctl/connections/saas_client.py +91 -0
- socialctl/connections/temporary_media.py +62 -0
- socialctl/delivery_options.py +70 -0
- socialctl/engagement.py +200 -0
- socialctl/engagement_cli.py +50 -0
- socialctl/executor.py +135 -0
- socialctl/formatter.py +291 -0
- socialctl/hosted_media.py +152 -0
- socialctl/identity.py +200 -0
- socialctl/inbox.py +298 -0
- socialctl/inbox_cli.py +46 -0
- socialctl/inventory.py +155 -0
- socialctl/inventory_cli.py +171 -0
- socialctl/inventory_sources.py +101 -0
- socialctl/management/__init__.py +1 -0
- socialctl/management/batch_cli.py +115 -0
- socialctl/management/batches.py +325 -0
- socialctl/management/changes.py +485 -0
- socialctl/management/cli.py +227 -0
- socialctl/management/comments_cli.py +352 -0
- socialctl/management/community_batch_cli.py +63 -0
- socialctl/management/community_batches.py +294 -0
- socialctl/management/community_changes.py +370 -0
- socialctl/management/community_cli.py +142 -0
- socialctl/management/community_schema.py +119 -0
- socialctl/management/facebook_groups.py +1118 -0
- socialctl/management/groups_cli.py +274 -0
- socialctl/management/inbox_readers.py +87 -0
- socialctl/management/meta_changes.py +197 -0
- socialctl/management/meta_cli.py +342 -0
- socialctl/management/meta_client.py +631 -0
- socialctl/management/meta_comment_inbox.py +565 -0
- socialctl/management/meta_comments.py +587 -0
- socialctl/management/meta_errors.py +59 -0
- socialctl/management/meta_pagination.py +52 -0
- socialctl/management/meta_schema.py +128 -0
- socialctl/management/meta_webhooks.py +147 -0
- socialctl/management/metadata_parts.py +144 -0
- socialctl/management/owned_assets.py +85 -0
- socialctl/management/owned_changes.py +470 -0
- socialctl/management/owned_cli.py +128 -0
- socialctl/management/owned_reorder.py +62 -0
- socialctl/management/owned_schema.py +368 -0
- socialctl/management/reply_context.py +24 -0
- socialctl/management/reply_evidence.py +80 -0
- socialctl/management/resource_changes.py +407 -0
- socialctl/management/resource_cli.py +136 -0
- socialctl/management/snippet_readback.py +26 -0
- socialctl/management/stories.py +713 -0
- socialctl/management/stories_cli.py +172 -0
- socialctl/management/youtube.py +323 -0
- socialctl/management/youtube_community.py +326 -0
- socialctl/management/youtube_metadata.py +122 -0
- socialctl/management/youtube_owned.py +259 -0
- socialctl/management/youtube_resources.py +305 -0
- socialctl/media.py +269 -0
- socialctl/media_cli.py +183 -0
- socialctl/media_ingress.py +211 -0
- socialctl/media_preflight.py +114 -0
- socialctl/media_registry.py +301 -0
- socialctl/media_requirements.py +52 -0
- socialctl/metricas/__init__.py +6 -0
- socialctl/metricas/almacen.py +133 -0
- socialctl/metricas/analytics_changes.py +295 -0
- socialctl/metricas/analytics_cli.py +191 -0
- socialctl/metricas/analytics_client.py +304 -0
- socialctl/metricas/analytics_ingest.py +260 -0
- socialctl/metricas/analytics_schema.py +174 -0
- socialctl/metricas/base.py +147 -0
- socialctl/metricas/facebook.py +418 -0
- socialctl/metricas/insights.py +227 -0
- socialctl/metricas/instagram.py +133 -0
- socialctl/metricas/modelos.py +87 -0
- socialctl/metricas/piezas.py +134 -0
- socialctl/metricas/reach.py +94 -0
- socialctl/metricas/reporting_client.py +112 -0
- socialctl/metricas/resumen.py +251 -0
- socialctl/metricas/slugs.py +89 -0
- socialctl/metricas/tiktok.py +185 -0
- socialctl/metricas/youtube.py +403 -0
- socialctl/migration_cli.py +60 -0
- socialctl/migration_files.py +68 -0
- socialctl/models.py +150 -0
- socialctl/native_schedule/__init__.py +13 -0
- socialctl/native_schedule/api_delivery.py +15 -0
- socialctl/native_schedule/api_reconcile.py +40 -0
- socialctl/native_schedule/approval.py +160 -0
- socialctl/native_schedule/cadence.py +73 -0
- socialctl/native_schedule/cli.py +510 -0
- socialctl/native_schedule/dispatcher.py +120 -0
- socialctl/native_schedule/facebook.py +112 -0
- socialctl/native_schedule/facebook_reels.py +140 -0
- socialctl/native_schedule/first_comment.py +181 -0
- socialctl/native_schedule/handoff.py +193 -0
- socialctl/native_schedule/instagram_delivery.py +224 -0
- socialctl/native_schedule/instagram_runtime.py +66 -0
- socialctl/native_schedule/inventory.py +70 -0
- socialctl/native_schedule/migration.py +310 -0
- socialctl/native_schedule/models.py +103 -0
- socialctl/native_schedule/reconcile.py +83 -0
- socialctl/native_schedule/remote_data.py +177 -0
- socialctl/native_schedule/report.py +151 -0
- socialctl/native_schedule/store.py +560 -0
- socialctl/native_schedule/verification.py +32 -0
- socialctl/native_schedule/youtube.py +339 -0
- socialctl/operation_output.py +87 -0
- socialctl/plantillas/accounts.yml +33 -0
- socialctl/plantillas/brand.md +95 -0
- socialctl/plantillas/estrategia.md +64 -0
- socialctl/postfile.py +240 -0
- socialctl/preflight.py +73 -0
- socialctl/publication_policy.py +34 -0
- socialctl/publication_status.py +75 -0
- socialctl/publication_steps.py +398 -0
- socialctl/publish_output.py +96 -0
- socialctl/publisher.py +445 -0
- socialctl/queue_migration.py +302 -0
- socialctl/read_budget.py +224 -0
- socialctl/read_reports.py +91 -0
- socialctl/rutas.py +103 -0
- socialctl/saas/__init__.py +1 -0
- socialctl/saas/access.py +75 -0
- socialctl/saas/auth.py +213 -0
- socialctl/saas/backup.py +124 -0
- socialctl/saas/billing.py +327 -0
- socialctl/saas/billing_enrollment.py +1237 -0
- socialctl/saas/billing_enrollment_schema.py +519 -0
- socialctl/saas/billing_inventory.py +775 -0
- socialctl/saas/billing_reconcile.py +127 -0
- socialctl/saas/billing_routes.py +27 -0
- socialctl/saas/budget.py +66 -0
- socialctl/saas/connections.py +374 -0
- socialctl/saas/consent.py +52 -0
- socialctl/saas/lifecycle.py +341 -0
- socialctl/saas/mail.py +89 -0
- socialctl/saas/maintenance.py +68 -0
- socialctl/saas/meta_user.py +298 -0
- socialctl/saas/meta_webhooks.py +358 -0
- socialctl/saas/migration.py +107 -0
- socialctl/saas/models.py +8 -0
- socialctl/saas/operations.py +102 -0
- socialctl/saas/pages.py +126 -0
- socialctl/saas/pairing.py +158 -0
- socialctl/saas/permissions.py +57 -0
- socialctl/saas/reminders.py +128 -0
- socialctl/saas/renewal.py +74 -0
- socialctl/saas/restore_guard.py +229 -0
- socialctl/saas/revocation.py +97 -0
- socialctl/saas/rotation.py +114 -0
- socialctl/saas/routes.py +221 -0
- socialctl/saas/settings.py +34 -0
- socialctl/saas/store.py +106 -0
- socialctl/saas/temporary_media.py +245 -0
- socialctl/saas/webhooks.py +76 -0
- socialctl/schedule_remote.py +262 -0
- socialctl/schedule_sqlite.py +44 -0
- socialctl/scheduler.py +581 -0
- socialctl/scheduler_launchd.py +319 -0
- socialctl/scheduler_systemd.py +167 -0
- socialctl/source_links.py +119 -0
- socialctl/ui/__init__.py +1 -0
- socialctl/ui/assets/agent-manual.md +850 -0
- socialctl/ui/assets/agents.md +27 -0
- socialctl/ui/assets/components.css +20 -0
- socialctl/ui/assets/connection-layout.css +53 -0
- socialctl/ui/assets/otp.template.html +10 -0
- socialctl/ui/assets/tokens.css +1 -0
- socialctl/ui/assets/trial.template.html +11 -0
- socialctl/ui/assets/web-layout.css +38 -0
- socialctl/ui/email/otp.html +10 -0
- socialctl/ui/email/trial.html +11 -0
- socialctl/upload_consent.py +13 -0
- socialctl/workspace.py +8 -0
- socialctl/youtube_data.py +471 -0
- socialctl/youtube_data_service.py +225 -0
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
# SocialCli for AI agents — 0.3.0
|
|
2
|
+
|
|
3
|
+
Setup instructions for SocialCli 0.3.0. Require published metadata before installing;
|
|
4
|
+
do not replace an existing 0.2.6 installation or migrate its credentials silently.
|
|
5
|
+
Stripe remains in test mode. Google is External / In production with verified branding, but sensitive YouTube scopes remain unverified, with an unverified-app warning and user cap.
|
|
6
|
+
Real-agent acceptance is performed by the owner; do not claim it from installation.
|
|
7
|
+
|
|
8
|
+
SocialCli gives terminal-enabled agents tools for creator-owned social accounts.
|
|
9
|
+
You need a persistent shell workspace, Python 3.11+, macOS or Linux, and protected
|
|
10
|
+
credential storage. SocialCli does not include a model or MCP server. Provider
|
|
11
|
+
availability depends on account eligibility; Google sensitive-scope verification is still pending.
|
|
12
|
+
|
|
13
|
+
## Install the reviewed release
|
|
14
|
+
|
|
15
|
+
Use the official PyPI release metadata (or TestPyPI `https://test.pypi.org/pypi/socialcli/0.3.0/json` during pre-PyPI verification):
|
|
16
|
+
https://pypi.org/pypi/socialcli/0.3.0/json
|
|
17
|
+
|
|
18
|
+
1. Require HTTP 200 and package name `socialcli`, version `0.3.0`. If this
|
|
19
|
+
release is unavailable, stop and report it; do not install a similarly named package.
|
|
20
|
+
2. Select exactly `socialcli-0.3.0-py3-none-any.whl` from `urls`. Download its
|
|
21
|
+
HTTPS `url` and verify the file against that entry's `digests.sha256`.
|
|
22
|
+
3. Install that verified local wheel into an isolated environment. Resolve
|
|
23
|
+
dependencies from normal PyPI, not TestPyPI. For example:
|
|
24
|
+
|
|
25
|
+
uv tool install --python 3.12 '/absolute/path/socialcli-0.3.0-py3-none-any.whl[headless-credentials]'
|
|
26
|
+
socialcli --version
|
|
27
|
+
socialcli agent-guide
|
|
28
|
+
|
|
29
|
+
Without uv, use a new Python virtual environment and its `python -m pip install`
|
|
30
|
+
with the same local wheel and `headless-credentials` extra. Do not use system pip.
|
|
31
|
+
If an existing SocialCli tool is installed, use a separate virtual environment
|
|
32
|
+
for this pilot and its absolute executable; do not upgrade it automatically.
|
|
33
|
+
|
|
34
|
+
Verify the installed version is exactly 0.3.0 before continuing. Verify the
|
|
35
|
+
wheel's SHA256 before installing rather than running an unverified `uv tool install socialcli`.
|
|
36
|
+
|
|
37
|
+
For headless agents, configure encrypted-file storage with an external key file with mode `0600` in
|
|
38
|
+
a directory with mode `0700` before login. Keep the key outside the workspace and preserve both
|
|
39
|
+
across conversations. Never fall back to plaintext storage. Follow the protected
|
|
40
|
+
storage procedure at:
|
|
41
|
+
https://socialcli.app/connections.html#headless-encrypted-capability-storage.
|
|
42
|
+
|
|
43
|
+
If uv is missing, use the virtual-environment route or its official installation
|
|
44
|
+
instructions at https://docs.astral.sh/uv/getting-started/installation/.
|
|
45
|
+
If Python is older than 3.11, select a supported interpreter first. If the installed
|
|
46
|
+
tool is not on PATH, use its absolute executable or `uv tool update-shell` and
|
|
47
|
+
start a new shell. Video validation needs ffprobe (from FFmpeg); missing ffprobe
|
|
48
|
+
must be resolved before a video submission. Never generate or reencode media.
|
|
49
|
+
|
|
50
|
+
## Authorize the installation, then the social account
|
|
51
|
+
|
|
52
|
+
The owner must accept the current privacy policy in the browser and separately acknowledge assistant data access. Check the actual assistant plan/settings: Google data must not be used for advertising or general-purpose model training or unrelated human access/transfer. If these controls cannot be established, do not connect that configuration. An agent compatibility label is not provider-wide approval. Existing installations without the new receipt must be revoked and linked again by the owner; never erase local credentials as a shortcut.
|
|
53
|
+
|
|
54
|
+
Use `https://pilot.socialcli.app` for this pilot. The main site is the human landing.
|
|
55
|
+
Ask for the brand name; never infer it. Replace MyBrand below with that exact name.
|
|
56
|
+
Keep the workspace outside the application repository:
|
|
57
|
+
|
|
58
|
+
socialcli brand new MyBrand
|
|
59
|
+
mkdir -m 700 -p "$HOME/.local/share/socialcli-credentials"
|
|
60
|
+
socialcli credentials generate-key --key-file "$HOME/.local/share/socialcli-credentials/master.key"
|
|
61
|
+
socialcli credentials configure --brand MyBrand --backend encrypted-file --store-file "$HOME/.local/share/socialcli-credentials/store.json" --key-file "$HOME/.local/share/socialcli-credentials/master.key" --yes
|
|
62
|
+
socialcli account login --brand MyBrand --service https://pilot.socialcli.app --no-browser --label "My AI assistant"
|
|
63
|
+
|
|
64
|
+
Give the printed URL directly to the user. Do not open, fetch, preview or follow
|
|
65
|
+
it yourself. Keep the process alive with a runner timeout longer than 30 minutes.
|
|
66
|
+
The user signs in by email and explicitly approves this installation. Do not ask
|
|
67
|
+
for their OTP, password, session cookie or provider token in chat.
|
|
68
|
+
|
|
69
|
+
socialcli connect youtube --brand MyBrand --management --analytics --no-browser
|
|
70
|
+
|
|
71
|
+
Use the same browser handoff for TikTok:
|
|
72
|
+
|
|
73
|
+
socialcli connect tiktok --brand MyBrand --no-browser
|
|
74
|
+
|
|
75
|
+
Facebook and Instagram also use `connect PLATFORM --no-browser`; add the
|
|
76
|
+
documented management/analytics options only when needed and owner-authorized.
|
|
77
|
+
Never ask SaaS users for a developer `client_key`, `client_secret` or localhost
|
|
78
|
+
OAuth setup. After account login, `auth PLATFORM` also routes to the SaaS
|
|
79
|
+
connection flow. Without a signed-in installation it fails with login guidance.
|
|
80
|
+
Legacy developer-owned app prompts require explicit `auth --independent` in an
|
|
81
|
+
interactive terminal. Do not use that mode for SaaS users.
|
|
82
|
+
|
|
83
|
+
The provider step has its own 10-minute window. The user grants access and chooses
|
|
84
|
+
the exact account in their browser; the SaaS flow does not require guessing an
|
|
85
|
+
account ID or interactive terminal confirmation. Connecting does not authorize
|
|
86
|
+
publication. Do not use --yes as blanket authorization.
|
|
87
|
+
|
|
88
|
+
The trial lasts 14 days from the first successful connection, without a card.
|
|
89
|
+
Then hosted access costs USD 10 per month. You can subscribe during the trial without losing free days; the first monthly charge is due at its original end.
|
|
90
|
+
Only the user's browser completes payment. The current candidate uses Stripe
|
|
91
|
+
test mode; it is not collecting live subscriptions.
|
|
92
|
+
|
|
93
|
+
## Persist and recover
|
|
94
|
+
|
|
95
|
+
Managed YouTube API observations expire after six days. User-supplied originals and independent Studio imports are preserved. Re-read the platform when needed; do not report absent old snapshots as zero or invent weekly growth. Unknown ages and failed cleanup block affected data. Disconnect, terminal authorization failure and account deletion trigger a managed-data purge when observed by this runner. Exported reports, chats and independent backups require separate deletion.
|
|
96
|
+
|
|
97
|
+
Concurrent commands can briefly contend for a managed-store lock. Cleanup waits
|
|
98
|
+
up to two seconds per lock. `local_data_busy` means wait for the other command to
|
|
99
|
+
finish and retry; it does not mean corruption and never calls for deleting files.
|
|
100
|
+
Retention remains enforced while cleanup is blocked.
|
|
101
|
+
|
|
102
|
+
Preview the daily cleanup service for this exact brand and root, show it to the owner, then install only with their authorization:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
socialcli data-cleanup-install --brand NAME --root /absolute/workspace --dry-run
|
|
106
|
+
socialcli data-cleanup-install --brand NAME --root /absolute/workspace --yes
|
|
107
|
+
socialcli data-cleanup-status --brand NAME --root /absolute/workspace
|
|
108
|
+
socialcli data-cleanup --brand NAME --root /absolute/workspace
|
|
109
|
+
# Only for an authorized deletion request:
|
|
110
|
+
socialcli data-cleanup --brand NAME --root /absolute/workspace --purge-youtube
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The daily macOS LaunchAgent needs the user session; the Linux user timer needs its user manager (check Linger in status). No cleanup can execute on a stopped runner. Status must confirm the supervisor; a preview is not installation. Do not install on another brand or infer the workspace. Keep the original interpreter/venv available.
|
|
114
|
+
|
|
115
|
+
Keep the brand folder, its .secrets metadata and the configured credential backend
|
|
116
|
+
between conversations. Never upload credentials or keys to Git. A changed path
|
|
117
|
+
can change OS-keyring lookup; use the same absolute SOCIALCLI_ROOT or --root.
|
|
118
|
+
Ephemeral agents must arrange protected persistent storage before authorizing.
|
|
119
|
+
A fresh conversation alone does not require reconnecting YouTube.
|
|
120
|
+
|
|
121
|
+
socialcli account status --brand MyBrand --json
|
|
122
|
+
socialcli connections --brand MyBrand --json
|
|
123
|
+
|
|
124
|
+
`connections` retains successful platforms and identifies each failed platform in
|
|
125
|
+
`errors` with a fixed code, next action and HTTP status when available. Exit 3 is
|
|
126
|
+
partial, exit 1 means the read failed, and exit 0 is complete. Do not discard a
|
|
127
|
+
healthy YouTube result because another platform returns `connection_unavailable`.
|
|
128
|
+
After the owner revokes and relinks an assistant, explicit `account attach` can
|
|
129
|
+
restore an existing approved connection even when its old capability was deleted.
|
|
130
|
+
The current installation must still have owner-approved access, and an existing
|
|
131
|
+
local account must match exactly. This does not repeat OAuth or approve publication.
|
|
132
|
+
|
|
133
|
+
Use `account attach PLATFORM --brand MyBrand` to attach an existing owner-approved
|
|
134
|
+
connection after signing in on a second installation. Use `account recover
|
|
135
|
+
PLATFORM --brand MyBrand` after interrupted local installation; do not blindly
|
|
136
|
+
repeat OAuth. `account rotate --brand MyBrand` renews this installation's local
|
|
137
|
+
credentials. A network failure is not proof the social account was revoked.
|
|
138
|
+
Check --help on the installed version before using a proposed flag.
|
|
139
|
+
|
|
140
|
+
Preserve stdout JSON separately from stderr progress. Give read operations their
|
|
141
|
+
own --timeout and a longer runner limit. For stats, inbox and report, exit 3 means partial observations; exit 1 means error. Older clients and other read commands may return partial data with exit 1;
|
|
142
|
+
never treat an incomplete empty inbox as proof there are no comments.
|
|
143
|
+
|
|
144
|
+
## Publication gate
|
|
145
|
+
|
|
146
|
+
For every YouTube upload, show the Community Guidelines certification in the complete preview. The owner’s approval must include that statement; account connection is not upload consent. Old upload approvals without the certification require a fresh preview and approval. Never accept privacy or assistant terms on the owner’s behalf.
|
|
147
|
+
|
|
148
|
+
Use only media supplied by the user. Show the complete --dry-run preview and wait
|
|
149
|
+
for explicit approval of that exact account and content before any publication.
|
|
150
|
+
Keep confirmed, pending and uncertain results distinct. Never repeat an uncertain
|
|
151
|
+
write. Sign-in, subscription and connection approval do not approve publication.
|
|
152
|
+
|
|
153
|
+
## Temporary Instagram media
|
|
154
|
+
|
|
155
|
+
For SaaS Instagram connections, `publish` accepts local JPEG, MP4 and MOV files
|
|
156
|
+
without `media_url_base`. Approved original bytes are uploaded to the SocialCli
|
|
157
|
+
server on florentino.pro (up to 512 MiB), then fetched by Instagram through an
|
|
158
|
+
opaque HTTPS URL. The URL expires 15 minutes after reservation, including upload
|
|
159
|
+
time. The CLI requests deletion when the operation ends; automatic cleanup also
|
|
160
|
+
handles crashes and interrupted uploads. Media is excluded from backups.
|
|
161
|
+
This is temporary staging, not a file library. Keep the original on your runner.
|
|
162
|
+
A scheduled local job uploads only at dispatch; its runner must remain available.
|
|
163
|
+
Native Instagram video delivery already supports direct upload to Meta. Native
|
|
164
|
+
image/carousel helpers with explicit URLs retain their existing hosting contract.
|
|
165
|
+
|
|
166
|
+
## Canonical publishing workflow
|
|
167
|
+
|
|
168
|
+
Read this installed guide with `socialcli agent-guide`. It works offline. Keep the
|
|
169
|
+
same explicit workspace for every command (`SOCIALCLI_ROOT` or `--root`). Inspect
|
|
170
|
+
`socialcli delivery-options --brand MyBrand --json` before promising a delivery mode.
|
|
171
|
+
That report describes configuration, not verified provider authorization.
|
|
172
|
+
|
|
173
|
+
For an existing user-supplied post and original media:
|
|
174
|
+
|
|
175
|
+
socialcli publish my-post --brand MyBrand --only youtube --dry-run
|
|
176
|
+
|
|
177
|
+
Show the complete preview, including account, text, media, privacy and follow-up
|
|
178
|
+
comments. Wait for the user's explicit approval of that exact preview. Then:
|
|
179
|
+
|
|
180
|
+
socialcli publish my-post --brand MyBrand --only youtube --yes
|
|
181
|
+
|
|
182
|
+
`--yes` only bypasses a terminal prompt after approval. Inspect the persisted
|
|
183
|
+
result and publication journal before repeating any command. Upload accepted,
|
|
184
|
+
scheduled, public and awaiting creator confirmation are different outcomes.
|
|
185
|
+
Use `comments publication-status PUBLICATION_ID --brand MyBrand` to inspect a
|
|
186
|
+
recorded follow-up; never upload the video again to retry a comment.
|
|
187
|
+
|
|
188
|
+
TikTok defaults to `mode: inbox` in the brand's accounts.yml: the file goes directly
|
|
189
|
+
to TikTok and the creator finishes from its inbox notification. Report **awaiting
|
|
190
|
+
creator confirmation**, not published or scheduled. `mode: direct` is disabled and excluded
|
|
191
|
+
from the current offer, regardless of `auditada`. Use creator-reviewed inbox
|
|
192
|
+
upload; the creator must finish publishing in TikTok. Configuration is not
|
|
193
|
+
provider approval evidence.
|
|
194
|
+
|
|
195
|
+
SaaS Instagram publishing uses temporary hosting automatically when no
|
|
196
|
+
`media_url_base` is configured. Independent credentials still need their own
|
|
197
|
+
HTTPS media host. Video/image preparation
|
|
198
|
+
and validation never authorize generating, cropping or transcoding the originals.
|
|
199
|
+
|
|
200
|
+
## Scheduling and temporary media
|
|
201
|
+
|
|
202
|
+
YouTube remote scheduling receipts need a verified platform reconciliation at least every six days. Without it, receipt expiry blocks local management while preserving the occupied slot; a video already scheduled on YouTube can still publish there. Use YouTube Studio to inspect or cancel it if the local receipt expired. Do not dispatch a replacement or assume the remote schedule was canceled. Supplied future plans without provider receipts are preserved.
|
|
203
|
+
|
|
204
|
+
The SaaS stores account and connection metadata. Instagram may temporarily stage
|
|
205
|
+
original media for at most 15 minutes after reservation; it is excluded from backups.
|
|
206
|
+
Do not use the server for documents, archival media or long-lived scheduling files.
|
|
207
|
+
Other uploads go from the customer’s runner directly to the destination platform.
|
|
208
|
+
|
|
209
|
+
YouTube and Facebook can hold future publications on the platform. SocialCli's
|
|
210
|
+
native API route is a gated candidate, not a completed public pilot. Before using it,
|
|
211
|
+
the operator must record real account/project eligibility and calendar pilot evidence;
|
|
212
|
+
agents must never fabricate that evidence or select their own account.
|
|
213
|
+
|
|
214
|
+
socialcli native-schedule prepare native.json --brand MyBrand --dry-run
|
|
215
|
+
|
|
216
|
+
Show the complete native preview and its final time; after the creator approves the
|
|
217
|
+
exact digest, persist and approve that same intent:
|
|
218
|
+
|
|
219
|
+
socialcli native-schedule prepare native.json --brand MyBrand --persist --approval-digest APPROVED_DIGEST
|
|
220
|
+
socialcli native-schedule approve JOB_ID --brand MyBrand --approval-digest APPROVED_DIGEST
|
|
221
|
+
socialcli native-schedule submit-api JOB_ID --brand MyBrand --eligibility operator-pilot.json
|
|
222
|
+
socialcli native-schedule status --brand MyBrand
|
|
223
|
+
|
|
224
|
+
For new customer schedules, use `schedule: {"mode":"exact","timezone":"Europe/Madrid"}`
|
|
225
|
+
with the customer's actual IANA timezone and a matching local offset in `publish_at`.
|
|
226
|
+
Each publication can have its own date, time and timezone, including multiple posts
|
|
227
|
+
per day. SocialCli preserves the exact instant or rejects a conflict; it never moves
|
|
228
|
+
an exact request to 09:00 or another day. Explicit offsets resolve repeated DST hours;
|
|
229
|
+
nonexistent local times are rejected. Complete input examples are included below.
|
|
230
|
+
Manifests without `schedule` retain the legacy 09:00 America/New_York daily policy.
|
|
231
|
+
Existing legacy reservations still protect their whole New York date; they must not
|
|
232
|
+
be silently rewritten or bypassed. Facebook API delivery currently covers
|
|
233
|
+
Reels only, with a conservative window greater than ten minutes and at most 28 days.
|
|
234
|
+
|
|
235
|
+
`pending_verification` means the API response was checked but calendar confirmation
|
|
236
|
+
is still pending. `uncertain` means reconcile the saved remote attempt, never start
|
|
237
|
+
another upload. Only verified platform scheduling removes the need for a running
|
|
238
|
+
agent at publication time. First comments remain separate work after public visibility.
|
|
239
|
+
If API eligibility is unavailable, prepare a separately approved official UI handoff;
|
|
240
|
+
never change an approved route or publish immediately as a fallback.
|
|
241
|
+
|
|
242
|
+
Instagram and TikTok's posting APIs do not provide this native future-publication
|
|
243
|
+
flow. Offer publication now (or TikTok creator review) in the SaaS launch scope.
|
|
244
|
+
The compatibility `schedule` queue for Facebook/Instagram is local: it needs the
|
|
245
|
+
original file, credentials, connectivity and a persistent executor at delivery time.
|
|
246
|
+
|
|
247
|
+
socialcli schedule-doctor --brand MyBrand --json
|
|
248
|
+
|
|
249
|
+
Exit 1 requires attention. A recent heartbeat proves only a recent run, not that
|
|
250
|
+
Muse/Grok will keep an executor alive between conversations. On a persistent,
|
|
251
|
+
customer-owned Linux machine, `schedule-install --brand MyBrand` installs systemd
|
|
252
|
+
user service/timer units for that exact workspace and installed interpreter. On
|
|
253
|
+
macOS it loads a launchd agent. Both fail instead of reporting success from files alone.
|
|
254
|
+
|
|
255
|
+
Linux units run `run-due` without a shell, five seconds after timer activation and
|
|
256
|
+
60 seconds after each completed run. They cannot keep a disappearing agent runtime
|
|
257
|
+
alive. The user manager must be available. The installer does not change host policy:
|
|
258
|
+
if logout persistence is unverified, an authorized operator can enable linger with
|
|
259
|
+
`loginctl enable-linger USER_ID` and then run `schedule-doctor` again.
|
|
260
|
+
|
|
261
|
+
On Linux, doctor exits 0 only when the matching loaded configuration, enabled active
|
|
262
|
+
timer, service result, logout persistence and recent executor heartbeat are verified
|
|
263
|
+
now. Even `ready` does not guarantee future power, credentials, files or connectivity.
|
|
264
|
+
macOS persistent supervision still requires operator verification beyond heartbeat.
|
|
265
|
+
Use `schedule-uninstall --brand MyBrand --root WORKSPACE` to disable future Linux
|
|
266
|
+
runs; an already running approved operation may finish. Queue, media and credentials
|
|
267
|
+
remain intact. Different workspace roots have different Linux unit identities.
|
|
268
|
+
This is not a reason to move media onto the SaaS server.
|
|
269
|
+
|
|
270
|
+
## Native scheduling input examples (offline)
|
|
271
|
+
|
|
272
|
+
These are fictional schemas, not authorization or pilot evidence. Store each file
|
|
273
|
+
inside the selected brand directory under `SOCIALCLI_ROOT`. Replace every sample
|
|
274
|
+
identity, date, copy and hash with verified values. Keep the user's original
|
|
275
|
+
`clip.mp4` there; never generate a replacement. The example destination must match
|
|
276
|
+
`facebook.page_id` in that brand's accounts.yml. All timestamps require an offset.
|
|
277
|
+
|
|
278
|
+
First read the complete official destination calendar for the publication period.
|
|
279
|
+
Save `native-calendar.json` with the actual observation time (at most 24 hours old),
|
|
280
|
+
coverage spanning full local days, and every existing scheduled item. An empty
|
|
281
|
+
`objects` array is valid only after verifying that the covered calendar is empty;
|
|
282
|
+
never substitute an API error or partial read for a complete inventory. Each object
|
|
283
|
+
has `platform`, `account_id`, `remote_ref`, `publish_at` and optional `occurrence_id`.
|
|
284
|
+
|
|
285
|
+
Example `native-calendar.json`:
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"observed_at": "2035-01-01T12:00:00Z",
|
|
290
|
+
"coverage_start": "2035-01-01T00:00:00-05:00",
|
|
291
|
+
"coverage_end": "2035-01-08T00:00:00-05:00",
|
|
292
|
+
"accounts": [{"platform": "facebook", "account_id": "page-example", "complete": true}],
|
|
293
|
+
"objects": []
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Example `native.json` (standalone Reel, no source-video follow-up). `dispatch_after`
|
|
298
|
+
is the earliest upload time, not publication time. It must precede `publish_at`;
|
|
299
|
+
submission also obeys existing account cooldowns. The example uses the customer's
|
|
300
|
+
chosen 19:30 in Europe/Madrid. Confirm that timezone with the customer; never infer
|
|
301
|
+
it from the server, the agent's machine or a brand name. Inspect the local time,
|
|
302
|
+
UTC time and **final** preview before approving. Platform eligibility and publication
|
|
303
|
+
windows still apply; choosing a time does not prove the platform accepted it.
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"id": "example-reel",
|
|
308
|
+
"platform": "facebook",
|
|
309
|
+
"account_id": "page-example",
|
|
310
|
+
"publish_at": "2035-01-03T19:30:00+01:00",
|
|
311
|
+
"dispatch_after": "2035-01-01T12:00:00Z",
|
|
312
|
+
"route": "api",
|
|
313
|
+
"schedule": {"mode": "exact", "timezone": "Europe/Madrid"},
|
|
314
|
+
"payload": {
|
|
315
|
+
"calendar": "Meta Business Suite",
|
|
316
|
+
"visibility": "public",
|
|
317
|
+
"copy": "Creator-approved caption",
|
|
318
|
+
"content_origin": "standalone",
|
|
319
|
+
"source_video_id": null,
|
|
320
|
+
"options": {"format": "reel", "share_to_facebook_story": false},
|
|
321
|
+
"first_comment": null,
|
|
322
|
+
"media": [{"path": "clip.mp4", "origin": "user-provided"}]
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
For a derivative of a YouTube long video, set `content_origin: "youtube_long"`,
|
|
328
|
+
`source_video_id` to the exact 11-character source ID, and the approved first comment
|
|
329
|
+
to `🎥 Video completo en https://www.youtube.com/watch?v=SOURCE_ID`. That comment is
|
|
330
|
+
separate work after public visibility, never proof of completion at scheduling time.
|
|
331
|
+
|
|
332
|
+
The operator must supply a real, nonempty local evidence file for the named account.
|
|
333
|
+
Example `operator-pilot.json` below is deliberately disabled. Never change flags
|
|
334
|
+
based on these examples; only the operator's verified pilot can enable them.
|
|
335
|
+
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"version": 1,
|
|
339
|
+
"platform": "facebook",
|
|
340
|
+
"account_id": "page-example",
|
|
341
|
+
"api_enabled": false,
|
|
342
|
+
"page_pilot_verified": false,
|
|
343
|
+
"evidence_ref": "operator-pilot-evidence.txt"
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
For YouTube, use `platform: "youtube"`, the verified `youtube.channel_id`, calendar
|
|
348
|
+
`YouTube Studio`, and options such as `{"format":"video","title":"Approved title",
|
|
349
|
+
"selfDeclaredMadeForKids":false}` (the creator must decide the kids declaration).
|
|
350
|
+
The eventual visibility is `public`; the adapter uploads privately with the approved
|
|
351
|
+
future time. YouTube eligibility replaces `page_pilot_verified` with
|
|
352
|
+
`project_verified` and `studio_pilot_verified`, both false until operator verification.
|
|
353
|
+
New upload is the default; scheduling an existing video additionally requires its
|
|
354
|
+
exact `video_id` and truthful `never_published: true`. Apply the same preview and
|
|
355
|
+
approval commands above. Do not invent provider approval or assume upload acceptance
|
|
356
|
+
proves future publication.
|
|
357
|
+
|
|
358
|
+
After API submission, record fresh official-calendar evidence locally (for example
|
|
359
|
+
`calendar-evidence.png`, without tokens or signed links). Verify the exact account,
|
|
360
|
+
remote ID, copy, processing state and final time. Use the SHA-256 of that actual file.
|
|
361
|
+
`content_hash` comes from `intent.content_hash` in the saved preview; `approval_digest`
|
|
362
|
+
is the exact approved digest. `remote_ref` comes from the recorded remote attempt.
|
|
363
|
+
Example `calendar-observation.json` below uses placeholder hashes; it is not evidence:
|
|
364
|
+
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"job_id": "example-reel",
|
|
368
|
+
"platform": "facebook",
|
|
369
|
+
"account_id": "page-example",
|
|
370
|
+
"content_hash": "REPLACE_WITH_PREVIEW_CONTENT_HASH",
|
|
371
|
+
"approval_digest": "REPLACE_WITH_APPROVED_DIGEST",
|
|
372
|
+
"remote_ref": "REPLACE_WITH_CONFIRMED_REMOTE_ID",
|
|
373
|
+
"publish_at": "2035-01-03T19:30:00+01:00",
|
|
374
|
+
"observed_at": "2035-01-01T12:05:00Z",
|
|
375
|
+
"source": "ui",
|
|
376
|
+
"calendar_visible": true,
|
|
377
|
+
"state": "native_scheduled",
|
|
378
|
+
"public_visible": false,
|
|
379
|
+
"processing_complete": false,
|
|
380
|
+
"evidence_path": "calendar-evidence.png",
|
|
381
|
+
"evidence_sha256": "REPLACE_WITH_ACTUAL_FILE_SHA256"
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Set the booleans/state to what was actually observed; never copy success from an
|
|
386
|
+
example. The observation must be newer than the job and any reconciliation barrier.
|
|
387
|
+
Keep the original media unchanged while reconciling. Then run:
|
|
388
|
+
|
|
389
|
+
socialcli native-schedule reconcile JOB_ID --observation calendar-observation.json --brand MyBrand
|
|
390
|
+
socialcli native-schedule status --brand MyBrand
|
|
391
|
+
|
|
392
|
+
Before rescheduling an exact-time job, refresh `native-calendar.json` with complete
|
|
393
|
+
coverage of the new local day. Preview, approval and the submit marker each require
|
|
394
|
+
fresh account-bound evidence; an old calendar cannot authorize moving into an
|
|
395
|
+
unobserved day. To change a verified schedule, show a new complete action preview with the local
|
|
396
|
+
ISO timestamp (including its correct offset for the stored timezone):
|
|
397
|
+
|
|
398
|
+
socialcli native-schedule reschedule JOB_ID --publish-at 2035-01-04T20:15:00+01:00 --brand MyBrand --dry-run
|
|
399
|
+
|
|
400
|
+
Only after approval, use the same command with `--approval-digest ACTION_DIGEST`
|
|
401
|
+
instead of `--dry-run`, then follow the approved official-UI handoff and reconciliation.
|
|
402
|
+
Both times remain reserved until fresh evidence confirms the change. Cancellation
|
|
403
|
+
also requires its own preview and approval; it does not authorize deleting the video.
|
|
404
|
+
|
|
405
|
+
Reconciliation reads local evidence and changes only the ledger; it does not publish.
|
|
406
|
+
Check the resulting `state` and notices: command completion alone does not establish
|
|
407
|
+
`native_scheduled`. A missing or conflicting observation stays unresolved. Preserve
|
|
408
|
+
the existing remote target; never create a second upload to repair it.
|
|
409
|
+
|
|
410
|
+
## Check supplied media locally
|
|
411
|
+
|
|
412
|
+
socialcli media check POST_SLUG --brand MyBrand --json
|
|
413
|
+
socialcli media check POST_SLUG --brand MyBrand --only instagram --json
|
|
414
|
+
|
|
415
|
+
This checks ordinary `post.yml` routes without credentials, network requests,
|
|
416
|
+
uploads, copying or conversion. Shared files are inspected once. Read every
|
|
417
|
+
platform's `assets`, `issues` and `coverage`; a missing or unreadable file does
|
|
418
|
+
not discard other platform results. `passed` means the implemented local checks
|
|
419
|
+
passed, not that the provider will accept or publish the file. `partial` retains
|
|
420
|
+
passed platforms while others are blocked. Neither result approves publication.
|
|
421
|
+
|
|
422
|
+
Issue actions distinguish installing `ffprobe`, inspecting a timed-out file,
|
|
423
|
+
supplying compatible original media, configuring an account and reviewing post
|
|
424
|
+
text. Each ffprobe run is capped at30seconds and can open local files only.
|
|
425
|
+
The command does not download URLs or resolve remote hosting. Provider account
|
|
426
|
+
eligibility, TikTok creator-specific duration/privacy, public media URL availability
|
|
427
|
+
and full-file decoder integrity remain unchecked. Actual provider processing and
|
|
428
|
+
visibility still require readback after an explicitly approved operation.
|
|
429
|
+
|
|
430
|
+
Instagram image and Reel constraints are separate: the generic ordinary route
|
|
431
|
+
checks observed codec/container/frame rate plus its applicable dimensions and
|
|
432
|
+
size limits. TikTok's route also checks observed video codec/container/frame rate
|
|
433
|
+
and dimensions. For Facebook/YouTube the existing configured route policy is not
|
|
434
|
+
claimed to be a complete provider codec specification. Inspection metadata stays
|
|
435
|
+
outside durable approval payloads; supplied bytes are never modified. Native
|
|
436
|
+
manifests, Stories and group assets have their own validators and are outside
|
|
437
|
+
this command's scope. Continue to show the full publication dry-run for approval.
|
|
438
|
+
|
|
439
|
+
## Read metrics and prepare engagement
|
|
440
|
+
|
|
441
|
+
socialcli stats --brand MyBrand --only youtube --timeout 120 --json
|
|
442
|
+
socialcli inbox --brand MyBrand --since yesterday --timezone America/New_York --timeout 120 --json
|
|
443
|
+
|
|
444
|
+
Set the external runner timeout longer than the command timeout. Keep stdout as one
|
|
445
|
+
JSON document and progress stderr separate. Aggregate partial results use exit 3
|
|
446
|
+
in rc2 (exit 1 in rc1). Inspect coverage and errors; a partial empty inbox never means no
|
|
447
|
+
comments. TikTok comments are unsupported. Missing metrics are unknown, not zero.
|
|
448
|
+
`--since` on stats filters publication dates, not the metrics reporting window.
|
|
449
|
+
For an offline brand report from already saved snapshots:
|
|
450
|
+
|
|
451
|
+
socialcli report --brand MyBrand --days 7 --top 5 --json
|
|
452
|
+
socialcli report --brand MyBrand --days 7 --as-of 2026-10-13 --only youtube
|
|
453
|
+
|
|
454
|
+
This does not refresh metrics or access accounts. It shows per-platform account
|
|
455
|
+
changes, an available previous daily window, top observed lifetime views and top
|
|
456
|
+
observed view changes. The actual observation timestamps and elapsed intervals
|
|
457
|
+
are included; daily files do not imply reads occurred at exactly the same hour.
|
|
458
|
+
A missing exact baseline is not replaced by another date. Missing values/items
|
|
459
|
+
never count as zero. New content absent from the baseline has no measured change.
|
|
460
|
+
Rankings cover observed items only, not a guaranteed complete account inventory.
|
|
461
|
+
Counter corrections and duplicate IDs remain explicit.
|
|
462
|
+
|
|
463
|
+
Account comparisons require saved matching account identity and dated observations.
|
|
464
|
+
Observations whose timestamp date differs from the daily file are not silently
|
|
465
|
+
assigned a timezone: the comparison stays unavailable. Existing snapshots do not
|
|
466
|
+
record the collector timezone, so legitimate midnight-boundary reads may need
|
|
467
|
+
explicit timezone provenance in a future format. Known values remain available.
|
|
468
|
+
Legacy snapshots lacking identity still provide known current values and lifetime
|
|
469
|
+
rankings, with partial status. Do not add identity retroactively from accounts.yml.
|
|
470
|
+
TikTok comparisons stay unavailable if its current response does not supply an
|
|
471
|
+
open_id; configured identity is not inferred as authenticated evidence. Failed,
|
|
472
|
+
stale and partial sources remain explicit, and exit1 may contain useful results.
|
|
473
|
+
The existing audience data has no audience-online-hours series: best posting time
|
|
474
|
+
is unavailable. Do not invent peak hours or causal recommendations from top posts.
|
|
475
|
+
|
|
476
|
+
For one supervised workflow across saved YouTube/Facebook/Instagram comments:
|
|
477
|
+
|
|
478
|
+
socialcli inbox-review --brand MyBrand --json
|
|
479
|
+
socialcli inbox-draft --file inbox-replies.yml --brand MyBrand --dry-run --timeout 120 --json
|
|
480
|
+
|
|
481
|
+
`inbox` reads owner replies from the platform and saves account/media/parent-bound
|
|
482
|
+
evidence, including after reinstalling or attaching an existing connection.
|
|
483
|
+
`inbox-review` is offline: it joins those observations to the actual reply journals.
|
|
484
|
+
`reply_state` is `observed`, `draft`, `blocked`, `uncertain` or `replied`.
|
|
485
|
+
`replied` can come from a verified local write or an observed platform reply by
|
|
486
|
+
the connected account. It does not recheck present visibility. Local uncertain
|
|
487
|
+
writes remain uncertain even if other owner replies are found.
|
|
488
|
+
`platform_reply_state` distinguishes `owner_reply_found`, `no_owner_reply_found`
|
|
489
|
+
and `unknown`. Unknown means incomplete or unverifiable evidence, never proof
|
|
490
|
+
that a comment is unanswered. A partial later scan retains positive evidence.
|
|
491
|
+
Former-account observations and proposals are excluded with explicit counts;
|
|
492
|
+
a foreign-brand journal still blocks review. An empty saved view never proves there
|
|
493
|
+
are no comments. Refresh with `inbox` first,
|
|
494
|
+
inspect its coverage, and preserve the selected account/comment identities.
|
|
495
|
+
|
|
496
|
+
The explicit reply file is:
|
|
497
|
+
|
|
498
|
+
```yaml
|
|
499
|
+
version: 1
|
|
500
|
+
replies:
|
|
501
|
+
- platform: youtube
|
|
502
|
+
account_id: EXACT_CHANNEL_ID
|
|
503
|
+
comment_id: EXACT_TOP_LEVEL_COMMENT_ID
|
|
504
|
+
text: "Exact proposed reply"
|
|
505
|
+
- platform: facebook
|
|
506
|
+
account_id: EXACT_PAGE_ID
|
|
507
|
+
comment_id: EXACT_TOP_LEVEL_COMMENT_ID
|
|
508
|
+
text: "Exact proposed reply"
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Replace IDs with observed values; never infer an account. Instagram uses the same
|
|
512
|
+
schema with `platform: instagram`. Select 1–100 comments, each once. TikTok
|
|
513
|
+
comments remain unsupported. For a nested observation, explicitly provide the
|
|
514
|
+
verified top-level `reply_parent_id` as described under Resumable batches and
|
|
515
|
+
reply context; the preview shows the actual target without inventing deeper nesting.
|
|
516
|
+
|
|
517
|
+
Drafting checks every local selection before provider reads, rechecks author/text
|
|
518
|
+
and owner replies against the provider, and creates immutable child proposals plus one
|
|
519
|
+
community batch. It does not send replies. The complete batch preview is on stderr;
|
|
520
|
+
JSON stdout includes `batch.id`, `batch.fingerprint` and `prepared` child references.
|
|
521
|
+
If a later preparation fails, `status: partial`, `batch: null` and `prepared` retain
|
|
522
|
+
finished local drafts. Review them; no batch was approved or applied. Do not claim
|
|
523
|
+
that the unprepared comments were handled. An existing uncertain or verified reply
|
|
524
|
+
blocks a fresh unified draft. Resolve it before considering another response.
|
|
525
|
+
Incomplete owner-reply coverage also blocks preparation. Follow-ups in an already
|
|
526
|
+
answered thread require separate, deliberate review through the lower-level
|
|
527
|
+
proposal commands; never bypass the guard automatically. Two independent agents
|
|
528
|
+
can still race after preparation: this is read-backed prevention, not a provider
|
|
529
|
+
transaction or a cross-installation lock.
|
|
530
|
+
|
|
531
|
+
Show the full preview and obtain explicit approval of that exact fingerprint:
|
|
532
|
+
|
|
533
|
+
socialcli changes apply-batch BATCH_ID --approval APPROVED_DIGEST --brand MyBrand --json
|
|
534
|
+
socialcli changes status-batch BATCH_ID --brand MyBrand --json
|
|
535
|
+
socialcli changes reconcile-batch BATCH_ID --brand MyBrand --json
|
|
536
|
+
socialcli inbox-review --brand MyBrand --json
|
|
537
|
+
|
|
538
|
+
Reconciliation only reads existing attempts and never starts pending replies.
|
|
539
|
+
An interrupted apply reports the batch ID; inspect its status and child journals.
|
|
540
|
+
Meta inbox-bound replies retain their existing frequency limit and durable inbox
|
|
541
|
+
status. Partial batches are not cross-provider transactions and have no rollback.
|
|
542
|
+
|
|
543
|
+
Existing individual `comments draft/apply-draft` and YouTube community proposal
|
|
544
|
+
commands remain available. To group already reviewed child proposals, use
|
|
545
|
+
`changes prepare-batch --file children.yml --brand MyBrand --dry-run --json` with
|
|
546
|
+
`version: 1` and `children: [{provider: meta-comments, change_id: EXACT_UUID}]`.
|
|
547
|
+
The `children` reference file is different from the explicit `replies` file above.
|
|
548
|
+
Never automatically reply merely because an inbox read found a new comment.
|
|
549
|
+
|
|
550
|
+
## Recovery and error actions
|
|
551
|
+
|
|
552
|
+
`account login --json` and `account status --json` return structured failure
|
|
553
|
+
documents with `error.code`, `error.action`, `error.retryable` and a fixed diagnostic.
|
|
554
|
+
`retry_later` applies to a safe read; `recover` resumes installation delivery;
|
|
555
|
+
`reconcile` checks an uncertain operation; `sign_in` concerns the installation;
|
|
556
|
+
`reconnect` requires explicit user authorization for that social account. A 409 or
|
|
557
|
+
network failure alone is never proof of revoked provider access. Unknown failures
|
|
558
|
+
require inspection, not automatic retries.
|
|
559
|
+
|
|
560
|
+
With explicit `--json`, `stats` and unified `inbox` preserve verified observations
|
|
561
|
+
and expose each diagnostic in `errors[]` with `code`, `action`, `retryable`,
|
|
562
|
+
`requires_user_action`, sanitized `message` and fixed `guidance`. Legacy comments
|
|
563
|
+
and YouTube community partial dictionaries retain items, cursors and flags and add
|
|
564
|
+
`error_detail`; do not assume they have the same envelope as `stats`. A missing
|
|
565
|
+
workspace also produces a structured error in these explicit JSON read modes.
|
|
566
|
+
`adjust_read` means reduce scope or adjust the budget, not repeat unchanged.
|
|
567
|
+
`unsupported` cannot be repaired by reconnecting. Generic authentication failure
|
|
568
|
+
requests account review; it does not prove revoked access. A token-refresh POST
|
|
569
|
+
with uncertain delivery must not become a safe read retry. Some legacy adapters
|
|
570
|
+
wrap typed causes, so their conservative fallback is inspection or account review.
|
|
571
|
+
|
|
572
|
+
Meta `comments apply/reconcile/status/apply-draft/reconcile-draft` and YouTube
|
|
573
|
+
`content youtube-community apply/reconcile/status` support explicit `--json`.
|
|
574
|
+
Keep stdout and stderr separate: the complete preview and exact fingerprint prompt
|
|
575
|
+
are on stderr; stdout is one result/error document. JSON does not approve anything.
|
|
576
|
+
Show the complete preview to the owner before supplying their approved fingerprint.
|
|
577
|
+
There is no `--yes` shortcut for these operations. EOF or a mismatched fingerprint
|
|
578
|
+
stops before the mutation service.
|
|
579
|
+
|
|
580
|
+
Successful results keep their existing fields. Nonverified durable results add
|
|
581
|
+
`error_detail`; inspect their status, IDs and journal even if a legacy reconcile
|
|
582
|
+
command exits 0. Failures before returning a durable result use `error`, plus
|
|
583
|
+
`change_id` when known. A failure after entering the apply service conservatively
|
|
584
|
+
requires reconciliation, including a failed journal save or interruption; it never
|
|
585
|
+
means the write was rejected. Use the corresponding reconcile/status command,
|
|
586
|
+
not a fresh proposal or another apply to retry a possibly completed write.
|
|
587
|
+
|
|
588
|
+
`publish --json` and `retry --json` also reserve stdout for one versioned document.
|
|
589
|
+
Full preview, progress and confirmation remain on stderr; a dry-run additionally
|
|
590
|
+
returns the exact `preview` string. Preserve both streams and show the owner the
|
|
591
|
+
complete preview. `--json` never grants approval; existing `--yes` still requires
|
|
592
|
+
prior explicit consent to that complete preview.
|
|
593
|
+
|
|
594
|
+
Publication reports include `status`, `resultados`, `errors` and `persistence`;
|
|
595
|
+
retry additionally reports `retry.selected` and `retry.blocked`. A report can be
|
|
596
|
+
`preview`, `cancelled`, `noop`, `ok`, `partial` or `error`. Each result retains its
|
|
597
|
+
original platform state, confirmed IDs, durable attempt IDs and visibility fields.
|
|
598
|
+
`error_detail` describes a failed/uncertain/pending media result;
|
|
599
|
+
`first_comment_error_detail` concerns only the comment, never a reason to upload
|
|
600
|
+
media again. Pending TikTok confirmation remains pending even with exit 0.
|
|
601
|
+
An unfinished first comment may likewise produce `partial` with the legacy exit 0.
|
|
602
|
+
Always inspect the document instead of inferring completion from the exit alone.
|
|
603
|
+
|
|
604
|
+
`persistence.complete` is true only after both resultado.json and history were
|
|
605
|
+
saved; false after an attempted publication whose persistence is incomplete, and
|
|
606
|
+
null before publication. Keep all returned observations after an interruption or
|
|
607
|
+
persistence failure. Confirmed results are not permission to replay an uncertain
|
|
608
|
+
platform; use the durable journal and provider observations for reconciliation.
|
|
609
|
+
|
|
610
|
+
Every `native-schedule` command accepts `--json`. It produces one versioned
|
|
611
|
+
`kind: native-schedule` envelope on stdout; preserve stderr for the complete local
|
|
612
|
+
preview. `data` contains approval documents or operation observations, `jobs`
|
|
613
|
+
contains the latest readable job snapshot, and `jobs_complete` says whether that
|
|
614
|
+
snapshot completed. An error can retain earlier jobs and confirmed IDs: preserve
|
|
615
|
+
them and check `errors` before acting. Checkpoint IDs are observations of an
|
|
616
|
+
existing upload, never proof of a public or scheduled post.
|
|
617
|
+
|
|
618
|
+
`status: ok` means the command completed, not that its jobs are public. Inspect
|
|
619
|
+
job/result `state` and `next_action`: prepared needs approval, waiting needs time,
|
|
620
|
+
UI handoff needs an authorized operator, and uncertain/verifying needs readback.
|
|
621
|
+
Native scheduling evidence does not establish publication. The original date,
|
|
622
|
+
timezone and approval document remain unchanged; JSON grants no new approval.
|
|
623
|
+
|
|
624
|
+
SSH executors must support the same JSON envelope. The client validates command,
|
|
625
|
+
brand, exit and safe output and never replays an invalid/lost remote response.
|
|
626
|
+
For an older executor, inspect authoritative state and upgrade or use legacy
|
|
627
|
+
read-only status; do not repeat a mutation to obtain a prettier response.
|
|
628
|
+
Parser errors (such as missing required CLI flags) remain standard CLI usage errors.
|
|
629
|
+
|
|
630
|
+
Typed failure codes now survive sanitized authentication, YouTube metadata/resource
|
|
631
|
+
and Meta management/comment wrappers. A provider GET timeout or rate limit can
|
|
632
|
+
request a bounded read retry; a lost token-refresh or SaaS token POST requires
|
|
633
|
+
reconciliation even when the outer command only requested a read. A generic
|
|
634
|
+
401/403 does not prove expired authorization. Only a recognized service expiry
|
|
635
|
+
code requests reconnection, which still requires the owner. Partial comment and
|
|
636
|
+
community pagination, comments sync and the unified inbox retain verified rows
|
|
637
|
+
and the specific recovery action.
|
|
638
|
+
|
|
639
|
+
Other management commands are not all converted to this taxonomy; inspect
|
|
640
|
+
their exit code, stderr and durable result as well. No action hint grants approval
|
|
641
|
+
to reconnect, publish, delete or replay a write.
|
|
642
|
+
|
|
643
|
+
Meta management journals preserve sanitized errors, typed guidance, and request
|
|
644
|
+
stage/HTTP status when available. `write_intent` does not prove a request reached
|
|
645
|
+
Meta or a response arrived. Older journals cannot recover a discarded response.
|
|
646
|
+
Report `uncertain` as attempted and unconfirmed, never as applied. Reconcile the
|
|
647
|
+
existing ChangeSet with reads only; a fresh UUID cannot bypass an unresolved
|
|
648
|
+
operation on the same target.
|
|
649
|
+
|
|
650
|
+
Before a Meta Page profile update, every patch field must appear in the profile
|
|
651
|
+
read. Missing does not mean "currently not set". If Meta omits the field, the
|
|
652
|
+
change cannot be previewed or verified and is blocked before writing. Do not
|
|
653
|
+
silently map `bio` to `about` or another field; a different field needs its own
|
|
654
|
+
explicit preview and approval. A field missing during readback is unavailable
|
|
655
|
+
evidence, not proof of failure or success.
|
|
656
|
+
|
|
657
|
+
Revoking an installation is supported. Fine-grained, server-enforced permissions
|
|
658
|
+
such as “publish but never delete” are not implemented: the current client receives
|
|
659
|
+
provider tokens. Do not advertise local agent instructions as an access-control boundary.
|
|
660
|
+
|
|
661
|
+
Container checks require verified MOV/MP4 brand metadata. Ambiguous Matroska/WebM
|
|
662
|
+
identification is currently blocked even though TikTok supports WebM; supply an
|
|
663
|
+
existing MOV/MP4 or use a separately validated route. No automatic conversion.
|
|
664
|
+
|
|
665
|
+
## Installation connection access
|
|
666
|
+
|
|
667
|
+
When the owner links an assistant, the browser lets them select its SocialCli
|
|
668
|
+
connections by platform. The service checks this selection before OAuth, attaching
|
|
669
|
+
an existing grant, migration, activation and token delivery. `account status --json`
|
|
670
|
+
can include `platform_access` from installation status. Existing installations
|
|
671
|
+
keep their previously approved access after the schema upgrade.
|
|
672
|
+
|
|
673
|
+
`platform_not_allowed` and `installation_permissions_invalid` require owner review;
|
|
674
|
+
never retry by silently reconnecting, choosing another brand or another installation.
|
|
675
|
+
The account page shows the selection. To change it, the owner revokes the old
|
|
676
|
+
installation and explicitly links a new one.
|
|
677
|
+
|
|
678
|
+
This is a connection-broker boundary. It does not narrow provider tokens, which may
|
|
679
|
+
carry permissions for linked accounts and additional actions. Per-action restrictions
|
|
680
|
+
remain unavailable. Previously delivered provider tokens can remain valid after
|
|
681
|
+
SocialCli revocation until they expire or are separately revoked at the provider.
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
## Read diagnostics in Candidate 0.3.0rc3
|
|
685
|
+
|
|
686
|
+
- Aggregate `stats`, `inbox` and `report` JSON envelopes: exit 0 = ok,
|
|
687
|
+
exit 3 = partial, exit 1 = error, exit 2 = invalid command arguments.
|
|
688
|
+
Always inspect coverage and retain verified observations, including after errors.
|
|
689
|
+
A partial empty inbox never proves that no comments exist.
|
|
690
|
+
- `stats` and `inbox` default to a 300-second total budget. Give the process
|
|
691
|
+
additional time for persistence. Use `--only youtube` (repeat `--only` for more
|
|
692
|
+
platforms) to devote the read budget to selected providers. Increase `--timeout`
|
|
693
|
+
for large catalogs; the budget remains finite. `--since` on stats filters video
|
|
694
|
+
publication dates, not the analytics period. Inbox still examines older videos
|
|
695
|
+
because they can have new comments.
|
|
696
|
+
- Progress is summarized at most once every five seconds. YouTube audience is
|
|
697
|
+
requested before per-video retention and traffic enrichment. Unverifiable Meta
|
|
698
|
+
comments remain excluded and counted; more time cannot repair missing fields.
|
|
699
|
+
- YouTube inbox's authenticated moderation filter requires management consent.
|
|
700
|
+
`connect --management` and `--analytics` exist in rc1 too. Inspect the installed
|
|
701
|
+
`connect --help`. Only with owner authorization, use the connection example above
|
|
702
|
+
to add missing consent; reads never reconnect automatically. A single 403 can
|
|
703
|
+
also mean disabled comments or resource eligibility, not missing OAuth scopes.
|
|
704
|
+
- `local_configuration` indicates a local URL/proxy/CA setup issue, not server
|
|
705
|
+
rejection. `transport_failure` means connectivity failed. Preserve environment
|
|
706
|
+
proxies and credentials; correct configuration rather than bypassing it.
|
|
707
|
+
- In `delivery-options`, `native_schedule_authorization_verified` concerns native
|
|
708
|
+
scheduling only. The legacy `authorization_verified` alias has the same meaning,
|
|
709
|
+
identified by `authorization_verified_scope`. Neither verifies general read access.
|
|
710
|
+
- `credentials generate-key` writes a new external Fernet key privately, never to
|
|
711
|
+
stdout and never over an existing file. The parent must already be owned by you
|
|
712
|
+
with mode 0700; the file is created with mode 0600. Use a separate protected
|
|
713
|
+
directory per independent brand. The key is URL-safe base64 for 32 random bytes,
|
|
714
|
+
not a password or hexadecimal string.
|
|
715
|
+
|
|
716
|
+
## Comment API corrections in Candidate 0.3.0rc3
|
|
717
|
+
|
|
718
|
+
YouTube comments with disabled discussion return `comments_disabled`, not a
|
|
719
|
+
reconnection request. Valid reply-list cursor traversal tolerates an omitted
|
|
720
|
+
total count while retaining supplied-data consistency checks. Meta may withhold
|
|
721
|
+
a comment author; read observations retain `author_id: null`. Do not invent the
|
|
722
|
+
author or draft replies from that unverified identity. Facebook verification can
|
|
723
|
+
resolve a receipt/list ID difference using exact provider comment permalinks and
|
|
724
|
+
owned-target membership; unknown outcomes must still never be resent.
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
## Explicit approval and preflight
|
|
728
|
+
|
|
729
|
+
The approval path is: display the complete preview, obtain the creator's explicit
|
|
730
|
+
approval, then pass its exact fingerprint to the execution command. Supplying a
|
|
731
|
+
flag is the transport for that approval; it does not grant an agent permission.
|
|
732
|
+
|
|
733
|
+
```sh
|
|
734
|
+
socialcli publish clip --brand Example --only facebook --dry-run
|
|
735
|
+
# After the creator approves that complete preview:
|
|
736
|
+
socialcli publish clip --brand Example --only facebook --approval-fingerprint APPROVED_DIGEST
|
|
737
|
+
|
|
738
|
+
socialcli schedule clip --at 2030-01-01T12:00:00Z --brand Example --only facebook --dry-run
|
|
739
|
+
# After the creator approves the content and exact scheduled time:
|
|
740
|
+
socialcli schedule clip --at 2030-01-01T12:00:00Z --brand Example --only facebook --approval-fingerprint APPROVED_DIGEST
|
|
741
|
+
|
|
742
|
+
socialcli content youtube-owned prepare --file change.yml --brand Example --dry-run
|
|
743
|
+
# Keep the returned ChangeSet ID and its fingerprint together.
|
|
744
|
+
socialcli content youtube-owned status CHANGE_ID --brand Example
|
|
745
|
+
socialcli content youtube-owned apply CHANGE_ID --brand Example --approval-fingerprint APPROVED_FINGERPRINT
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
`--approval` and `--approval-digest` are aliases for `--approval-fingerprint` on
|
|
749
|
+
these commands and on the management apply commands. The same options are
|
|
750
|
+
available on `changes apply`, `meta apply`, `comments apply`, `comments apply-draft`,
|
|
751
|
+
`content youtube-assets apply`, `content youtube-community apply`,
|
|
752
|
+
`content youtube-analytics apply`, `story apply` and `group handoff`.
|
|
753
|
+
Check each installed command's help; native scheduling has its existing explicit
|
|
754
|
+
`--approval-digest` contract.
|
|
755
|
+
|
|
756
|
+
Management proposals are durable and include a proposal identity and observations.
|
|
757
|
+
Preparing again can produce a new ID and fingerprint even for the same input
|
|
758
|
+
file. Preserve the exact returned pair, inspect that stored proposal, and approve
|
|
759
|
+
that fingerprint. Do not substitute a digest from a different preparation.
|
|
760
|
+
Publication digests bind the selected account, content and media bytes; queue
|
|
761
|
+
digests additionally bind the scheduled instant. Changed inputs require a fresh
|
|
762
|
+
complete preview and approval. Execution rechecks before writing.
|
|
763
|
+
|
|
764
|
+
Without a terminal or explicit approval, these commands fail promptly without
|
|
765
|
+
reading an open input pipe. To deliberately provide approval through stdin:
|
|
766
|
+
|
|
767
|
+
```sh
|
|
768
|
+
printf '%s\n' "$APPROVED_FINGERPRINT" | socialcli content youtube-owned apply CHANGE_ID --brand Example --approval-stdin
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
`--approval-stdin` reads one line and can wait for that line by explicit choice.
|
|
772
|
+
It cannot be combined with a fingerprint argument. Do not blindly pipe a newly
|
|
773
|
+
generated digest into an apply command: the creator must review and approve the
|
|
774
|
+
complete preview first. On an interactive terminal, the existing prompts remain.
|
|
775
|
+
|
|
776
|
+
For `publish` and `schedule`, the previously authorized `--yes` workflow remains
|
|
777
|
+
supported, including displaying the complete preview and checking for changes.
|
|
778
|
+
For management commands that historically required an exact fingerprint,
|
|
779
|
+
`--yes` still cannot replace it. A supplied wrong fingerprint is never overridden
|
|
780
|
+
by `--yes`. Local schedule output is text; `publish --json` keeps its complete
|
|
781
|
+
preview and approval UI on stderr and returns one JSON document on stdout.
|
|
782
|
+
|
|
783
|
+
### Combined read-only preflight
|
|
784
|
+
|
|
785
|
+
`preflight` is an alias of `doctor`. Both accept explicit supplied files and/or a
|
|
786
|
+
post slug, and collect local validation alongside account identity checks:
|
|
787
|
+
|
|
788
|
+
```sh
|
|
789
|
+
socialcli doctor --brand Example --platform youtube --post clip --media /path/to/supplied.jpeg --json
|
|
790
|
+
socialcli preflight --brand Example --platform youtube --require-scope https://www.googleapis.com/auth/youtube.force-ssl --json
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
`--media` is repeatable and inspects existing files without modifying them.
|
|
794
|
+
`--post` reuses `media check` and preserves each platform's diagnostics when
|
|
795
|
+
another supplied file is invalid. Account and credential-store diagnostics remain
|
|
796
|
+
in the report alongside media failures. Encrypted-store checks validate the
|
|
797
|
+
protected key and existing store without creating lock files or repairing state.
|
|
798
|
+
A directory with owner permissions 0700 and no group/other access is accepted,
|
|
799
|
+
including mode 2700; credential files still require mode 0600.
|
|
800
|
+
|
|
801
|
+
Scope checks compare exact scopes recorded as granted in the token response;
|
|
802
|
+
they never substitute requested OAuth scopes or the capability matrix. Unknown
|
|
803
|
+
scope grants remain unknown and cannot satisfy `--require-scope`, which requires
|
|
804
|
+
an explicit `--platform`. Identity verification and recorded scopes do not prove
|
|
805
|
+
write permissions or provider approval. No token refresh, reconnection, remote
|
|
806
|
+
mutation, publication, media generation or reencoding is performed. TikTok
|
|
807
|
+
identity checks compare the authenticated provider `open_id` with the configured
|
|
808
|
+
account using a read-only request; they do not verify publishing permission.
|
|
809
|
+
Without `--media` or `--post`, file integrity is not
|
|
810
|
+
checked. A supplied image passing inspection alone does not prove eligibility
|
|
811
|
+
for a particular publishing route; use `--post` for route validation.
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
## Resumable batches and reply context
|
|
815
|
+
|
|
816
|
+
Community batches remain sequential, resumable operations, not atomic cross-provider transactions. Each child must verify before the next starts. A received comment receipt now permits one additional bounded, read-only reconciliation during apply, covering delayed provider readback without another POST. A lost receipt, incomplete evidence or contradictory identity still stops the batch. Reconciliation never starts pending children.
|
|
817
|
+
|
|
818
|
+
Batch JSON preserves existing keys and adds all children to `outcomes`, including `not_attempted`, with child index, provider, platform and change ID. `summary` includes total and verified/pending/uncertain/blocked counts and ID lists. A partial batch with only untouched children reports `batch_pending` and `action: apply_remaining`; an uncertain child reports `operation_uncertain` and `action: reconcile`. Continue the same approved batch with its exact fingerprint, retaining all verified outcomes. Progress is on stderr; stdout contains one JSON document.
|
|
819
|
+
|
|
820
|
+
`inbox-draft` errors include `failed.child_index` (one-based), platform, account/comment IDs, stage and a safe reason. Completed immutable children remain in `prepared` after a later failure. Diagnostics do not reproduce arbitrary provider or storage exception text.
|
|
821
|
+
|
|
822
|
+
Facebook reply preparation accepts an unavailable external comment author when exact comment membership and media ownership can be verified. The author remains null in the approved baseline. Changes to text, identity or membership block the write. Own-comment edit/delete and created-reply verification still require the authenticated account's exact author ID.
|
|
823
|
+
|
|
824
|
+
A nested observation can explicitly map a new thread reply to its observed top-level parent:
|
|
825
|
+
|
|
826
|
+
```yaml
|
|
827
|
+
version: 1
|
|
828
|
+
replies:
|
|
829
|
+
- platform: youtube
|
|
830
|
+
account_id: fictional-channel
|
|
831
|
+
comment_id: observed-reply-id
|
|
832
|
+
reply_parent_id: observed-top-level-comment-id
|
|
833
|
+
text: Exact supplied reply text
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
The source and mapped parent must both be observed for the same account/media/thread. The parent must be top-level and satisfy the existing eligibility rules. Source membership/text/author are read again during preparation and immediately before the write. The full preview binds `before.reply_context` and the actual write parent. This is supported through the existing YouTube, Facebook and Instagram reply edges; it does not invent a deeper provider nesting relationship or imply a mention. Multiple selections mapping to the same parent are rejected. Existing replied/uncertain parent protections remain in effect. Inbox review links the resulting journal to both the parent and selected source observation.
|
|
837
|
+
## Add another social platform without signing out
|
|
838
|
+
|
|
839
|
+
If `connect` reports `platform_not_allowed`, run
|
|
840
|
+
`socialcli account permissions --brand MyBrand --no-browser --json`.
|
|
841
|
+
Give its `browser_url` directly to the owner; never open or approve it for them.
|
|
842
|
+
The owner adds platforms to this installation in their SocialCli browser account.
|
|
843
|
+
The command only reads status and provides the link; it does not grant access.
|
|
844
|
+
After confirmation, check `socialcli account status --brand MyBrand --json`
|
|
845
|
+
and run `socialcli connect PLATFORM --brand MyBrand --no-browser`.
|
|
846
|
+
Existing YouTube and other connections remain active. Do not log out, revoke the
|
|
847
|
+
assistant or disconnect existing accounts just to add a network. If the service
|
|
848
|
+
does not support expansion yet, keep the connections and report the required
|
|
849
|
+
service update. Platform access does not replace provider consent or publication
|
|
850
|
+
approval.
|