* feat(shopify): Shopify order/refund feed into the transactions inbox
New extensions/general/shopify feed extension, modeled on the WooCommerce
feed: connect a Shopify store with Dev Dashboard custom-app client
credentials (client credentials grant, ~24h tokens, never stored), then a
nightly cron + manual sync imports paid orders and refunds via the GraphQL
Admin API (pinned 2026-07) into the transactions inbox on clearing account
1584. Feed-only: nothing auto-books. Zero PII fields are queried, keeping
the app outside Shopify's protected customer data program.
- shopify_connections migration (RLS, revoke-never-delete, encrypted
client id/secret) + shopify_sync capability and bank_sync-mirrored
backfill
- frozen external_id scheme shopify_{shop_domain}_order|refund_{id},
scoped on the shop domain so reconnects never re-import
- cursor sync on updated_at windows with 24h overlap, lock-date drop at
map time, ingest-failure cursor floor, deadline stop-and-resume,
revoked-credential flip
- /import card + settings panel, sv/en i18n, cron 03:15 in vercel.json +
regenerated Docker crontabs, logo, events, panel registry
- 65 unit tests + pg-real RLS test; extensions.schema.json enum also
gains the missing stripe entry (pre-existing drift)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(shopify): review findings from PR 1474
- token exchange: a 429 that survives every retry is throttling, not a
credential failure; stop remapping retryable 4xx to 401 so sustained
throttling can no longer flip the connection to revoked and delete the
stored credentials (CodeRabbit critical)
- order sync: advance a scanned-through watermark (run start, capped by
the failure floor) after a fully-listed window, so empty first runs and
quiet stores rotate to the back of the cron's oldest-first selection
instead of permanently occupying the 50-connection batch (CodeRabbit
major, starvation)
- add handler-level tests for the orders cron route (auth 401, disabled
503, unconfigured no-op, query failure, capability skip, happy path,
per-connection failure isolation, revoked marking)
- add 401 tests for /sync, /transaction-sync and /disconnect; pin the
cursor floor rule with a two-order page; stub the encryption key via
vi.stubEnv
- note in the panel description (sv/en) that orders can mix VAT rates and
must be split at booking (Swedish review advisory)
- DECISIONS.md: wrap underscore identifiers in backticks (MD037)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
6 lines
870 B
XML
6 lines
870 B
XML
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
|
<path fill="#95BF47" d="M17.9 5.3c0-.1-.1-.2-.2-.2l-1.9-.1-1.4-1.4c-.1-.1-.4-.1-.5 0l-.6.2c-.4-1-1-1.9-2.1-1.9h-.2c-.3-.4-.7-.6-1.1-.6C7.7 1.3 6.6 3.4 6.2 5l-2 .6c-.6.2-.6.2-.7.8L2 18.6l11.4 2.1 6.2-1.3S18 5.4 17.9 5.3zM12.7 4l-1 .3v-.2c0-.6-.1-1.2-.2-1.6.5.1.9.8 1.2 1.5zm-1.9.6-2.1.6c.2-.8.6-1.6 1.1-2.1.2-.2.5-.4.8-.5.2.5.2 1.3.2 2zm-1.3-2.7c.2 0 .3 0 .5.1-.3.2-.6.4-.9.7-.7.7-1.2 1.9-1.4 3l-1.7.5c.4-1.5 1.6-4.2 3.5-4.3z"/>
|
|
<path fill="#5E8E3E" d="m17.7 5.1-1.9-.1-1.4-1.4c-.1-.1-.1-.1-.2-.1v17.2l6.2-1.3S18 5.4 17.9 5.3c0-.1-.1-.2-.2-.2z"/>
|
|
<path fill="#FFF" d="m12.9 7.8-.8 2.3s-.7-.4-1.5-.4c-1.2 0-1.3.8-1.3 1 0 1 2.8 1.4 2.8 3.9 0 2-1.3 3.2-2.9 3.2-2 0-3-1.2-3-1.2l.5-1.8s1 .9 1.9.9c.6 0 .8-.4.8-.8 0-1.4-2.3-1.4-2.3-3.7 0-1.9 1.4-3.8 4.2-3.8 1.1.1 1.6.4 1.6.4z"/>
|
|
</svg>
|