File size: 5,748 Bytes
1b2323a
 
8bf0d31
 
 
 
 
 
 
 
1b2323a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# MediaRouter Analytics & Insights

## Status

The current working tree implements the bounded Analytics service at
`app/analytics/`, exposes `/v1/analytics` routes, and provides frontend,
TypeScript/Python SDK, MCP, and n8n transport surfaces. PostgreSQL schema,
RLS certification, Docker/Hugging Face runtime verification, and provider
certification remain deferred until all planned product phases are complete.

## Architecture

Phase 10 extends the authoritative Social analytics boundary. Provider calls
remain behind `SocialProviderAdapter.get_metrics`, OAuth execution remains
inside `OAuthService`/`TokenService`, and credentials never enter analytics
records or transports.

The flow is:

`REST/MCP/SDK/n8n -> AnalyticsDomainService -> AnalyticsRepository ->
Social AnalyticsService -> provider adapter -> normalized snapshots`

Workspace and project dashboards read durable normalized snapshots. They never
call providers directly and never synthesize missing metrics.

## Database

Migration `app/social/migrations/0010_analytics_insights.sql` is additive and
creates:

- `analytics_sync_runs`
- `analytics_metric_snapshots`
- `analytics_post_metrics`
- `analytics_platform_metrics`

Common values are normalized into typed columns. JSON dimensions are bounded
provider-specific metadata, not complete provider responses. Snapshot
uniqueness is workspace + provider + external object + metric + bucket.

All four tables enable and force PostgreSQL RLS using the transaction-local
`app.workspace_id`. Social post, target, and account foreign keys enforce
authoritative publishing relationships. Project references are verified
through `ProjectService`; project and Social databases may be independently
configured, so an unsafe cross-database foreign key is not introduced.

## Permissions and rate limits

- `analytics:read` reads dashboards, posts, capabilities, and sync status.
- `analytics:sync` queues or cancels synchronization.
- `analytics:export` is reserved for a future explicitly bounded export API.

Viewer roles receive read access. Operator and developer roles receive sync
access. Analytics reads use the established analytics rate-limit category;
sync mutations use a stricter bounded category. SDK, MCP, and n8n calls pass
through the same authentication, authorization, and rate limits.

## Metrics and capabilities

The common metric vocabulary currently includes views, impressions, likes,
comments, shares, and engagement rate. A provider advertises these controls
only when its existing registered analytics capability is enabled. Missing
values stay `null`. Unsupported and unsynchronized states are distinct from
zero.

Provider limitations remain explicit:

- YouTube channel analytics requires a separate authorized product flow.
- Facebook and Instagram analytics require explicit analytics consent/scopes.
- TikTok metrics require a resolvable public video identity.
- X is limited to authorized public metrics.
- LinkedIn support depends on member/organization authorization.
- Telegram and WhatsApp analytics remain unsupported unless their registered
  adapters acquire verified provider contracts.

No provider certification claim is made by this phase.

## Synchronization

`POST /v1/analytics/sync` creates a durable idempotent run and returns `202`.
The worker atomically claims bounded runs and follows:

`queued -> running -> succeeded | partial | failed | cancelled`

Retries use bounded exponential backoff with jitter. A run is partial when
some targets return authoritative metrics and others are unavailable. Existing
external post IDs connect MediaRouter publishing targets to provider metrics.
No manual or heuristic post mapping is used.

Audit events are bounded:

- `analytics.sync_requested`
- `analytics.sync_started`
- `analytics.sync_completed`
- `analytics.sync_failed`
- `analytics.sync_cancelled`

They contain IDs, status, provider, and counts only.

## API

- `GET /v1/analytics/capabilities`
- `GET /v1/analytics/overview`
- `GET /v1/analytics/timeseries`
- `GET /v1/analytics/platforms`
- `GET /v1/analytics/platforms/{provider}`
- `GET /v1/analytics/posts`
- `GET /v1/analytics/posts/{post_id}`
- `GET /v1/analytics/projects/{project_id}`
- `GET /v1/analytics/sync-runs`
- `GET /v1/analytics/sync-runs/{run_id}`
- `POST /v1/analytics/sync-runs/{run_id}/cancel`
- `POST /v1/analytics/sync`

Date ranges are limited to 366 days, pagination is bounded, sorting uses a
closed enum, and timezones must be valid IANA names. UTC is returned explicitly
when no authoritative workspace timezone is supplied.

## Frontend

`/analytics` and `/projects/[projectId]/analytics` use the Workspace shell,
TanStack Query, authenticated BFF, existing cards and chart containers. UI
controls are capability-driven. Empty, unavailable, unsupported, error,
loading, partial, and freshness states are represented without zero-filling.

Search can deep-link authoritative analytics post results. Commands include
Open Analytics, View Top Content, and permission-gated Sync Analytics.

## SDK, MCP, and n8n

The TypeScript and Python clients expose `client.analytics` with capabilities,
overview, time series, platforms, posts, project analytics, sync, sync status,
sync listing, and cancellation.

MCP exposes narrow typed analytics tools rather than arbitrary query or
provider execution. The official n8n Social node uses the SDK for overview,
time series, platform, project, top-content, sync, and sync-status operations.

## Runtime status

Provider live certification, PostgreSQL/RLS runtime verification, Docker,
Hugging Face startup, production OpenAPI verification, and final production
certification are intentionally **DEFERRED** until all planned MediaRouter
product phases are complete.