Architecture Overview
Runtime components
The embedded document loads App Bridge and Polaris web components from Shopify’s CDN. Admin navigation is rendered with
s-app-nav; route loaders and actions authenticate with authenticate.admin.
Request and trust boundaries
The storefront does not trust a customer ID supplied in JSON. The server uses Shopify’s signed
logged_in_customer_id from the app-proxy request.
Storefront and checkout flow
The theme app embed fetches public configuration through the signed app proxy. In Simple mode, the browser evaluates the entered date of birth and sends a bounded self-certification event to the server, which recalculates the applicable minimum age before recording a successful pass. Enhanced document verification is server-gated by the Enterprise entitlement, enabled settings, and provider readiness. A successful provider callback updates the verification record. For logged-in customers, the app publishes a$app.identity_status customer metafield. For guests, the storefront writes _age_identity_verified and _age_verified_at cart attributes.
Checkout enforcement is published as a $app.checkout_gate shop metafield. The all-plan cart block reads enforcement and customer state through /apps/age-verification/status. The checkout UI extension uses the same shop and customer metafields, but that checkout-step surface renders only on Shopify Plus.
Both checkout surfaces no-op when enforcement is unavailable. They never treat a missing configuration or a network failure as a verified identity result.
Data model and PII minimization
The main Prisma records are:Shop,ShopSubscription, andAppSettingsfor installation, billing, and merchant configuration.CustomerandVerificationfor Shopify-linked customers and verification lifecycle state.VerificationWebhookEventfor provider-event deduplication.VerificationAttemptandVerificationRateLimitCounterfor abuse controls.CustomerDataExportfor Shopify customer-data requests.AuditLogandComplianceAuditLogfor operational and tamper-evident audit history.MerchantApiCredentialfor hashed bearer API credentials (Enterprise).
Verification model stores provider session identifiers, status, the minimum age used, and an optional derived verified age. It has no date-of-birth, document-image, or biometric field. The identity provider remains the system of record for identity documents. The Didit callback stores the derived age for a verified decision, not the raw date of birth. On the Stripe rollback path, the callback reads date-of-birth data to make the age decision without persisting that date.
Shopify privacy webhooks
The three compliance topics perform data work:CUSTOMERS_DATA_REQUESTcreates aCustomerDataExportfor merchant review.CUSTOMERS_REDACTrequests provider redaction, deletes the customer’s verification and export records, removes linked operational audit rows, and deletes the local customer record.SHOP_REDACTrequests redaction for the shop’s verification sessions, deletes stored sessions, purges the protected compliance chain through its authorized whole-shop function, and deletes the shop.
APP_UNINSTALLED marks the shop uninstalled and removes sessions. The scheduled cleanup later cancels stale identity sessions, requests redaction for retained verification sessions, deletes uninstalled shops after the configured retention period, and prunes expired rate-limit counters.