Snapshots

Read only connectors on a fixed cadence, with Arata's protected in code

Settled
  • Shopify, Meta, Google Ads, GA4, Klaviyo, Judge.me and Slack; Marketplaces stay off.
  • Reads run every 3 to 12 hours, plus a re-read when a member opens the brand.
  • After 3 failures or four missed cadences, numbers go stale and stop being evidence.
  • Tokens are encrypted, and Arata's live connections are never disconnected.
  • Connected numbers are the team's source of truth, for the team only.
3failed reads mark data stale
Your call

Who joins Arata on the protected list? Proposal: every partner once an account connects.

Engineering · 5.10

Connectors

DraftLast checked Mon Oct 26Owner Param

Answer

Connectors read a brand's own accounts, read only, encrypt every token, refresh on a fixed cadence per account, and make the team's numbers the source of truth for the team only; Arata's live connections are protected in code and are never disconnected.

Today

The accounts

Connector How it connects Scopes or access Read every Source
Shopify The brand's own app (client id and secret) through own-oauth; the public app "Brew" is under review read_products,read_inventory; read_orders,read_customers with protected-data approval or the own app 3 h brew/connectors/shopify.js:11-13, 92 brew/connectors/index.js:37 memory brew-shopify-connector-qa
Meta Ads Facebook Login for Business on SquareUp's Meta app (config 2157080375167128), one or more ad accounts ads_read, business_management; Graph v26.0 3 h brew/connectors/meta.js:1-12 brew/deploy.sh:39
Google Ads Google sign-in with the developer token (GOOGLE_OAUTH=1) adwords, analytics.readonly, openid, email 6 h brew/connectors/google.js:18 memory brew-google-oauth-scopes
Google Analytics Same sign-in, or a property ID with Brew's service account added as Viewer analytics.readonly 6 h brew/connectors/google.js:29, 182
Klaviyo A pasted read-only private key lists, sizes, the five flows 12 h brew/connectors/klaviyo.js:1-3
Judge.me OAuth or the store's token read_reviews read_shops 6 h brew/connectors/reviews.js:1-14
Slack OAuth on the Brew Slack app chat:write, chat:write.public, incoming-webhook, channels:join, channels:read, groups:read, channels:history, groups:history, users:read, users:read.email, team:read event-driven brew/connectors/slack.js:11
Marketplaces Off; shown as "Coming soon" brew/connectors/index.js:32 brew/DUMMY.md

Slack is never evidence: no cards, no ledger. brew/connectors/index.js:5-7

Freshness and failure

  • A member opening the brand re-reads an account due within OPEN_H (Shopify and Meta 1 h, Google and GA4 and Judge.me 2 h, Klaviyo 6 h). brew/connectors/index.js:40, 315
  • A failed read waits for the platform's Retry-After, else doubles from 15 minutes. brew/connectors/index.js:44-50
  • After 3 failures in a row, or once the last good read is older than four cadences (at least 24 hours), numbers are marked stale and stop being evidence. Owners and admins hear a week before a Meta sign-in ends. brew/connectors/index.js:51-60
  • A new connector needs entries in EVERY_H, OPEN_H, NAMES and PRECEDENCE. memory brew-connected-facts

Who sees what

  • Tokens are AES-256-GCM in private/vault/, never sent to the page, never logged. brew/vault.js:1-3
  • Account reads live in private/live/<id>.json; numbers reach only members. A visitor never gets one. brew/connectors/index.js:1-4 memory brew-connected-facts
  • On the fact sheet, connected numbers beat the site read for members; demo and stale rows never count. memory brew-connected-facts
  • Only admins (owner or staff) connect or disconnect; teammates can sync. memory brew-real-connectors
  • A GA4 property already used by another brand, or whose web stream is not the brand's site, is refused unless staff override; 6 tries per person per 15 minutes. brew/SCOPE.md

Protected connections

PROTECTED_CONNECTIONS (default arata-in, set on production) refuses disconnect, re-select, a new key or a reconnect unless a root admin forces it; the vault refuses to drop the token too. brew/connectors/protected.js brew/connectors/index.js:148-150, 267-269, 429 brew/tools/prod-env.sh:9

Rules around it:

  • Never call DELETE /me/permissions on disconnect: one Meta grant may serve several brands. memory brew-meta-connector-qa
  • Disconnect tests run on Cozy only. memory never-disconnect-arata-meta
  • Arata's Shopify token (own app) never expires and Meta has no refresh, so the same vault serves both sites; connector reads run on both. memory brew-prod-backend

What a connection changes

The first connected account rewrites every Play privately (cap $40); later accounts rewrite only the Plays they touch. Best sellers become heroes in the team's view, and readings fill the health rings. memory brew-connect-refresh brew/on-connect.js:1-3

The demo

On the demo every connector is simulated from the brand's public read, tagged Dummy, and never evidence. brew/DUMMY.md brew/connectors/index.js:67

Approvals

Platform State Source
Google Verified 21 Oct for adwords and analytics.readonly; a new scope re-triggers review memory brew-google-oauth-scopes
Shopify public app Submitted 21 Oct; after approval deploy with SHOPIFY_OAUTH=1 and the install URL memory brew-shopify-app-review
Meta App Review Draft filled 24 Oct; blocked on business verification and two screencasts memory brew-meta-app-review

Both sites' callbacks (/auth/google/callback, /connect/<id>/callback) are registered with Google, Meta and Slack; Slack events go to production, which relays workspaces it does not serve to staging. brew/.wt-prod/docs/production.md

Tomorrow

Item Version Tag
Read only, every connector v1 Stays
One-click Shopify through the public app v1 Changes after Shopify approves
Meta for any brand (out of development tier) v1 Changes after App Review
Connections and secrets in their own table v2 New
Marketplace seller APIs v3 New
Write scopes (post, pause, change budgets) v3 New, only behind a person's yes per action

How we do it

  1. Audit what Brew shows against the platform, read only:
node tools/meta-audit.mjs <slug>      # needs FEED_VAULT_KEY and the Meta app secrets
node tools/shopify-audit.mjs <slug>   # needs FEED_VAULT_KEY

memory brew-meta-connector-qa memory brew-shopify-connector-qa

  1. Check that connectors still read on both sites:
gcloud run jobs execute brew-prod-ping --region=asia-south1 --wait
gcloud run jobs execute brew-staging-ping --region=asia-south1 --wait

memory brew-prod-backend

  1. Any script touching private/vault/meta.json, connections.json or disconnect must skip arata-in. memory never-disconnect-arata-meta
  2. Do not hammer syncs; Meta throttles "too many calls to this ad-account". memory brew-brand-book
  3. Bump META_GRAPH_VERSION and GOOGLE_ADS_API_VERSION when the platforms announce a sunset. memory brew-meta-connector-qa memory brew-real-connectors

Numbers

Metric Definition Where measured
Live connections Connections in state live, per brand connections.json; db/status.mjs
Stale connections Connections marked stale same
Read success rate Good reads over all reads per connector Proposed (from connections.json fails)

Open

  1. When should Marketplaces become real? Proposal: after Meta App Review, starting with Amazon seller data for India.
  2. Who besides Arata goes on the protected list? Proposal: every design partner once their first account connects.
Sources
  • brew origin/main: connectors/index.js:1-72, 113-330, 429; connectors/protected.js; connectors/shopify.js:8-20, 92; connectors/meta.js:1-12; connectors/google.js:7-29, 182-200; connectors/klaviyo.js:1-3; connectors/reviews.js:1-14; connectors/slack.js:11; vault.js:1-12; shopify-app.js:27
  • brew origin/main: SCOPE.md (Connectors row); DUMMY.md rows 1, 2, 7; docs/shopify.app.toml; docs/slack-app-manifest.json; deploy.sh:39
  • brew/.wt-prod/docs/production.md (sign-ins and outside settings)
  • memory brew-real-connectors, brew-connected-facts, never-disconnect-arata-meta, brew-meta-connector-qa, brew-shopify-connector-qa, brew-google-oauth-scopes, brew-shopify-app-review, brew-meta-app-review, brew-connect-refresh, brew-prod-backend

Source file content/engineering/connectors.md · For agents: Markdown · JSON