Deploy on DigitalOcean App Platform (GitHub-source build) + consolidate audit-fixes
Deploy config: - .do/app.yaml: build the Dockerfile directly from GitHub (deploy_on_push) instead of a pre-built DOCR image; NEXT_PUBLIC_* set RUN_AND_BUILD_TIME with the propertymanagement.network domain so they bake into the client bundle; add custom domains block (apex + www); wire Sentry DSN (server + browser). Included pending work from the audit-fixes branch: - AI provider abstraction (OpenAI/Anthropic, admin-selectable; Anthropic default) - Per-landlord e-signature (DocuSign OAuth + Dropbox Sign) + migration 0010 - Outbound webhooks / Zapier integration - PayPal removal (Stripe-only billing) - Storage hardening (fail-loud when Spaces unconfigured), security fixes Verified: full production Docker build (same build-args as DO) passes clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
917a06ee85
commit
5495b94924
@@ -254,6 +254,7 @@ export function getEnvHealth() {
|
||||
"STRIPE_WEBHOOK_SECRET",
|
||||
"NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY",
|
||||
"OPENAI_API_KEY",
|
||||
"ANTHROPIC_API_KEY",
|
||||
"SMTP_HOST",
|
||||
"SMTP_USER",
|
||||
"GOOGLE_CLIENT_ID",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
CREATE TABLE "esign_connections" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"provider" text NOT NULL,
|
||||
"access_token" text NOT NULL,
|
||||
"refresh_token" text,
|
||||
"expires_at" timestamp with time zone,
|
||||
"account_id" text,
|
||||
"base_uri" text,
|
||||
"account_name" text,
|
||||
"status" text DEFAULT 'active' NOT NULL,
|
||||
"last_error" text,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "esign_connections" ADD CONSTRAINT "esign_connections_user_id_profiles_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."profiles"("id") ON DELETE cascade ON UPDATE no action;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,13 @@
|
||||
"when": 1782994066547,
|
||||
"tag": "0009_amusing_blackheart",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"version": "7",
|
||||
"when": 1783017593260,
|
||||
"tag": "0010_esign_connections",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -631,6 +631,32 @@ export const signature_requests = pgTable("signature_requests", {
|
||||
updated_at: updatedAt(),
|
||||
})
|
||||
|
||||
// ============================================================
|
||||
// E-SIGN CONNECTIONS (per-landlord DocuSign OAuth / Dropbox Sign API key)
|
||||
// ============================================================
|
||||
// One row per (owner, provider). Each landlord connects THEIR OWN e-signature
|
||||
// account, so leases are sent from their brand with their audit trail. DocuSign
|
||||
// uses OAuth (access + refresh tokens); Dropbox Sign uses an API key stored in
|
||||
// `access_token`. All secrets are AES-256-GCM encrypted (see lib/crypto.ts).
|
||||
export const esign_connections = pgTable("esign_connections", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
user_id: text("user_id")
|
||||
.notNull()
|
||||
.references(() => profiles.id, { onDelete: "cascade" }),
|
||||
provider: text("provider").$type<"docusign" | "dropbox_sign">().notNull(),
|
||||
access_token: text("access_token").notNull(), // encrypted (DocuSign access token / Dropbox Sign API key)
|
||||
refresh_token: text("refresh_token"), // encrypted (DocuSign only)
|
||||
expires_at: tstz("expires_at"),
|
||||
// DocuSign account id + base uri from /oauth/userinfo (null for Dropbox Sign).
|
||||
account_id: text("account_id"),
|
||||
base_uri: text("base_uri"),
|
||||
account_name: text("account_name"),
|
||||
status: text("status").$type<"active" | "error" | "revoked">().notNull().default("active"),
|
||||
last_error: text("last_error"),
|
||||
created_at: createdAt(),
|
||||
updated_at: updatedAt(),
|
||||
})
|
||||
|
||||
// ============================================================
|
||||
// WEBHOOK ENDPOINTS (outbound webhooks / Zapier integration)
|
||||
// ============================================================
|
||||
|
||||
Reference in New Issue
Block a user