Initial scaffold: Shopify recesso (withdrawal) compliance app

- Remix (TypeScript) + Polaris, official Shopify app template
- Prisma multi-tenant schema (Settings, ExclusionRule, WithdrawalRequest, AuditLog, WebhookEvent) on Postgres
- Mandatory GDPR compliance webhooks (data_request, redact, shop/redact) + HMAC handlers
- API version pinned 2026-04, scopes read_orders/read_products
- Fly deploy config; two-env strategy (custom now, public later)
- Dev setup: shopify.web.toml + Vite allowedHosts for tunnels
- Docs: PLAN.md, ANALISI-REQUISITI-LEGALI.md (Art. 54-bis compliance)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mv83a29B4eFv5ixoj6PoE1
This commit is contained in:
2026-07-06 18:02:17 +02:00
commit 4586b2e557
62 changed files with 2968 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
-- CreateEnum
CREATE TYPE "ExclusionScope" AS ENUM ('PRODUCT', 'COLLECTION', 'TAG', 'ALL');
-- CreateEnum
CREATE TYPE "ExclusionReason" AS ENUM ('CUSTOM', 'PERISHABLE', 'HYGIENE', 'OTHER');
-- CreateEnum
CREATE TYPE "WithdrawalChannel" AS ENUM ('GUEST', 'ACCOUNT');
-- CreateEnum
CREATE TYPE "WithdrawalStatus" AS ENUM ('RECEIVED', 'ACKNOWLEDGED', 'GOODS_PENDING', 'CLOSED', 'REJECTED');
-- CreateTable
CREATE TABLE "Session" (
"id" TEXT NOT NULL,
"shop" TEXT NOT NULL,
"state" TEXT NOT NULL,
"isOnline" BOOLEAN NOT NULL DEFAULT false,
"scope" TEXT,
"expires" TIMESTAMP(3),
"accessToken" TEXT NOT NULL,
"userId" BIGINT,
"firstName" TEXT,
"lastName" TEXT,
"email" TEXT,
"accountOwner" BOOLEAN NOT NULL DEFAULT false,
"locale" TEXT,
"collaborator" BOOLEAN DEFAULT false,
"emailVerified" BOOLEAN DEFAULT false,
"refreshToken" TEXT,
"refreshTokenExpires" TIMESTAMP(3),
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Settings" (
"id" TEXT NOT NULL,
"shop" TEXT NOT NULL,
"buttonLabel" TEXT NOT NULL DEFAULT 'Recedere dal contratto qui',
"confirmLabel" TEXT NOT NULL DEFAULT 'Conferma recesso',
"brandPrimaryColor" TEXT,
"returnAddress" TEXT,
"defaultWindowDays" INTEGER NOT NULL DEFAULT 14,
"withdrawalInfoText" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Settings_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ExclusionRule" (
"id" TEXT NOT NULL,
"shop" TEXT NOT NULL,
"scope" "ExclusionScope" NOT NULL,
"targetId" TEXT,
"reason" "ExclusionReason" NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "ExclusionRule_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "WithdrawalRequest" (
"id" TEXT NOT NULL,
"shop" TEXT NOT NULL,
"orderId" TEXT NOT NULL,
"orderName" TEXT,
"customerName" TEXT NOT NULL,
"email" TEXT NOT NULL,
"statementText" TEXT NOT NULL,
"transmittedAt" TIMESTAMP(3) NOT NULL,
"locale" TEXT,
"channel" "WithdrawalChannel" NOT NULL,
"productType" TEXT,
"status" "WithdrawalStatus" NOT NULL DEFAULT 'RECEIVED',
"receiptSentAt" TIMESTAMP(3),
"computedDeadline" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "WithdrawalRequest_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "AuditLog" (
"id" TEXT NOT NULL,
"shop" TEXT NOT NULL,
"event" TEXT NOT NULL,
"payloadHash" TEXT,
"detail" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "WebhookEvent" (
"id" TEXT NOT NULL,
"shop" TEXT NOT NULL,
"topic" TEXT NOT NULL,
"webhookId" TEXT,
"receivedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"processed" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "WebhookEvent_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "Settings_shop_key" ON "Settings"("shop");
-- CreateIndex
CREATE INDEX "Settings_shop_idx" ON "Settings"("shop");
-- CreateIndex
CREATE INDEX "ExclusionRule_shop_idx" ON "ExclusionRule"("shop");
-- CreateIndex
CREATE INDEX "WithdrawalRequest_shop_idx" ON "WithdrawalRequest"("shop");
-- CreateIndex
CREATE INDEX "WithdrawalRequest_shop_orderId_idx" ON "WithdrawalRequest"("shop", "orderId");
-- CreateIndex
CREATE INDEX "AuditLog_shop_idx" ON "AuditLog"("shop");
-- CreateIndex
CREATE UNIQUE INDEX "WebhookEvent_webhookId_key" ON "WebhookEvent"("webhookId");
-- CreateIndex
CREATE INDEX "WebhookEvent_shop_idx" ON "WebhookEvent"("shop");

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"