Consolidate audit-fixes branch: webhooks, integrations, and deploy hardening
Batch commit of the pending working tree on security/audit-fixes-2026-07. Major areas: - Outbound webhooks / Zapier: schema + signed delivery with retries, public v1 API (REST-hook subscribe/unsubscribe), settings UI, cron drain. - Deploy hardening: email via SMTP2GO (Resend fully removed), verified DB TLS (DATABASE_SSL=require + DATABASE_CA), storage fails loud in production when Spaces is unconfigured instead of silently using ephemeral disk. - Integrations & features (concurrent work): accounting (QuickBooks/Xero), e-signature (DocuSign/Dropbox Sign), PayPal, geocoding/maps, onboarding, expanded legal pages. - DB migrations 0006–0009. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
969d5d4c8a
commit
c9968531e4
@@ -1,7 +1,7 @@
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="public/logo-light.svg">
|
||||
<img alt="Property Management Network" src="public/logo-dark.svg" width="360">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="public/logo-light.png">
|
||||
<img alt="Property Management Network" src="public/logo-dark.png" width="360">
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
**Property management SaaS for independent landlords.** Track properties, tenants, rent, maintenance, leases, and expenses — all in one clean dashboard.
|
||||
|
||||
Built with Next.js 16, PostgreSQL (Drizzle ORM), Better Auth, Stripe, and OpenAI. Ready to deploy on Vercel in under 10 minutes.
|
||||
Built with Next.js 16, PostgreSQL (Drizzle ORM), Better Auth, Stripe, and OpenAI. Deploys to DigitalOcean App Platform (see [DIGITALOCEAN.md](DIGITALOCEAN.md)).
|
||||
|
||||
---
|
||||
|
||||
@@ -25,7 +25,7 @@ Property Management Network replaces the spreadsheet + WhatsApp chaos that most
|
||||
- **Expenses** — categorized logging with recurring expense support
|
||||
- **Documents** — file vault per property with drag-and-drop upload to local disk, served through an auth-gated route
|
||||
- **AI features** — AI-powered recommendations, predictions, and impact tracking (Pro+)
|
||||
- **Automated emails** — rent reminders, overdue alerts, lease expiry notifications via Resend
|
||||
- **Automated emails** — rent reminders, overdue alerts, lease expiry notifications via SMTP (SMTP2GO)
|
||||
- **Tenant portal** — token-based (no login), tenants can view rent history and submit maintenance
|
||||
|
||||
---
|
||||
@@ -51,12 +51,12 @@ Subscription billing via Stripe. Lifetime deal is ideal for Flippa buyers who wa
|
||||
| Styling | Tailwind CSS + Geist font |
|
||||
| Database | PostgreSQL (via Drizzle ORM) |
|
||||
| Auth | Better Auth (email/password + Google OAuth) |
|
||||
| Storage | Local disk (auth-gated file serving) |
|
||||
| Storage | DigitalOcean Spaces (S3-compatible, CDN, auth-gated) |
|
||||
| Payments | Stripe (subscriptions + payment links) |
|
||||
| AI | OpenAI (gpt-4o-mini) |
|
||||
| Email | Resend |
|
||||
| Cron | Vercel Cron Jobs |
|
||||
| Deploy | Vercel |
|
||||
| Email | SMTP (SMTP2GO) |
|
||||
| Cron | DigitalOcean Functions (scheduled triggers) |
|
||||
| Deploy | DigitalOcean App Platform (Docker image via DOCR) |
|
||||
|
||||
---
|
||||
|
||||
@@ -91,20 +91,20 @@ GOOGLE_CLIENT_SECRET=
|
||||
# File storage (local disk)
|
||||
STORAGE_DIR=./storage
|
||||
|
||||
# Stripe
|
||||
# Stripe (no price IDs needed — resolved by lookup key, auto-created on first checkout)
|
||||
STRIPE_SECRET_KEY=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
||||
STRIPE_PRO_MONTHLY_PRICE_ID=
|
||||
STRIPE_LANDLORD_MONTHLY_PRICE_ID=
|
||||
STRIPE_LIFETIME_PRICE_ID=
|
||||
|
||||
# OpenAI
|
||||
OPENAI_API_KEY=
|
||||
|
||||
# Resend
|
||||
RESEND_API_KEY=
|
||||
RESEND_FROM_EMAIL=Property Management Network <noreply@yourdomain.com>
|
||||
# Email (SMTP — e.g. SMTP2GO)
|
||||
SMTP_HOST=mail.smtp2go.com
|
||||
SMTP_PORT=2525
|
||||
SMTP_USER=
|
||||
SMTP_PASS=
|
||||
EMAIL_FROM=postmaster@yourdomain.com
|
||||
|
||||
# App
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
@@ -123,10 +123,7 @@ To regenerate migrations after changing the schema, use `npm run db:generate`. F
|
||||
|
||||
### 4. Configure Stripe
|
||||
|
||||
Create three products in your Stripe dashboard:
|
||||
- **Pro Monthly** — $29/mo recurring → copy Price ID to `STRIPE_PRO_MONTHLY_PRICE_ID`
|
||||
- **Landlord Monthly** — $59/mo recurring → copy Price ID to `STRIPE_LANDLORD_MONTHLY_PRICE_ID`
|
||||
- **Lifetime** — $199 one-time → copy Price ID to `STRIPE_LIFETIME_PRICE_ID`
|
||||
Add your API keys (`STRIPE_SECRET_KEY`, `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`) — that's it. Products and prices are resolved by stable **lookup keys** and auto-created on first checkout (Pro $29/mo, Landlord $59/mo, Lifetime $199, plus annual), so there are **no price IDs to configure** and going live is just an API-key swap. To pre-create the catalog, optionally run `node scripts/stripe-setup.mjs`.
|
||||
|
||||
Set up a webhook at `https://yourdomain.com/api/stripe/webhook` listening to:
|
||||
- `checkout.session.completed`
|
||||
@@ -136,9 +133,9 @@ Set up a webhook at `https://yourdomain.com/api/stripe/webhook` listening to:
|
||||
- `invoice.payment_failed`
|
||||
- `payment_intent.succeeded`
|
||||
|
||||
### 5. Configure Resend
|
||||
### 5. Configure email (SMTP)
|
||||
|
||||
Add a verified sending domain in your Resend dashboard. Update `RESEND_FROM_EMAIL` with your domain address.
|
||||
Use any SMTP provider (e.g. SMTP2GO). Verify your sending domain with the provider, then set `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, and `EMAIL_FROM`.
|
||||
|
||||
### 6. (Optional) Google OAuth
|
||||
|
||||
@@ -152,11 +149,9 @@ npm run dev
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000).
|
||||
|
||||
### 8. Deploy to Vercel
|
||||
### 8. Deploy (DigitalOcean App Platform)
|
||||
|
||||
Connect the repo in the Vercel dashboard and add all environment variables under **Settings → Environment Variables**.
|
||||
|
||||
Cron jobs are pre-configured in `vercel.json` and run automatically on Vercel.
|
||||
The repo ships a production `Dockerfile` (Next.js standalone output), an App Platform spec at [`.do/app.yaml`](.do/app.yaml), DO Functions cron under [`functions/`](functions/), and a `/api/health` liveness probe. See **[DIGITALOCEAN.md](DIGITALOCEAN.md)** for the full walkthrough: build/push the image to DOCR, create the app, wire up Managed Postgres + Spaces, and deploy the scheduled cron functions.
|
||||
|
||||
---
|
||||
|
||||
@@ -184,7 +179,7 @@ app/
|
||||
│ ├── expenses/ # CRUD
|
||||
│ ├── documents/ # Document metadata (files on local disk)
|
||||
│ ├── ai/ # Rent receipts + maintenance summaries
|
||||
│ ├── notifications/ # Send emails via Resend
|
||||
│ ├── notifications/ # Send emails via SMTP (SMTP2GO)
|
||||
│ ├── stripe/ # Checkout, portal, webhook
|
||||
│ └── cron/ # Rent reminders + lease expiry alerts
|
||||
└── tenant-portal/[token]/ # Public tenant portal (no login)
|
||||
@@ -195,7 +190,7 @@ lib/
|
||||
├── storage.ts # Local-disk file storage helpers
|
||||
├── stripe/ # Client, plans, payment links
|
||||
├── ai/ # OpenAI client + prompts
|
||||
├── email/ # Resend client + HTML templates
|
||||
├── email/ # SMTP (SMTP2GO) client + HTML templates
|
||||
└── validations/ # Zod schemas for all entities
|
||||
|
||||
drizzle.config.ts # Drizzle ORM config (DATABASE_URL, migrations dir)
|
||||
|
||||
Reference in New Issue
Block a user