Skip to main content

Proofpack opens soon. Accounts and payments are not live yet. The sample report shows what you get.

This is a sample. TaskPilot is a small demo SaaS with problems planted on purpose. This page is the report exactly as a buyer sees it through a share link. Your report comes from your own repo.

Scan my repo free

Verified by Proofpack

Repository
proofpack-demo/tasks-saas
Commit
0000000
Scanned
1 Nov 2026
Version
v1
Content hash (SHA-256)
0aa193635309868558c0afb9c9a84dff35a08a5c9f098036abdb3776cd53fc79

Proofpack report

Technical due-diligence report

proofpack-demo/tasks-saas · main

Summary

57OF 100
Needs work

Capped at 69: 3 critical findings still count.

  • Security0 of 100
  • Dependencies94 of 100
  • Code health66 of 100
  • Docs52 of 100
  • Operability86 of 100
  • Ownership80 of 100

Summary

AI-suggested. Check before you rely on it.

TaskPilot is an AI task planner for small teams, built with Next.js 14, Supabase and Stripe. Users open a dashboard, enter their goals, and the app asks OpenAI to turn them into a weekly task list that is saved in a Supabase table. Paid plans are sold with Stripe Checkout, and a webhook upgrades the team after payment. The codebase is small and easy to read, but it was built fast: a live Stripe key is written in the code, one table has no row-level security, the payment webhook accepts unsigned events and the task API does not check who the caller is. There are no tests, no CI and only a short README, so a buyer will need time to verify and run it. Most of these problems take hours, not weeks, to fix.

Strengths

  • A small, conventional Next.js App Router structure that a new owner can read in an afternoon.

    app/page.tsxapp/dashboard/page.tsx

  • The database schema is versioned as a Supabase migration.

    supabase/migrations/20240901120000_init.sql

  • Row-level security is on for the main teams and tasks tables.

    supabase/migrations/20240901120000_init.sql

  • All AI calls go through one helper module, so the provider is easy to change.

    lib/ai.ts

Top risks for a buyer

  1. Live Stripe secret key in the source codeAnyone with the code can charge customers or issue refunds. The key must be rotated before the sale, and old commits still contain it.Fix: Revoke the key in the Stripe dashboard, read it from STRIPE_SECRET_KEY, and remove it from the git history.

    lib/stripe.ts

  2. The Stripe webhook accepts unsigned eventsA forged checkout.session.completed request can upgrade any team to Pro for free.Fix: Verify the Stripe-Signature header with stripe.webhooks.constructEvent on the raw request body.

    app/api/webhooks/stripe/route.ts

  3. The team_invites table has no row-level securityWith the public anon key, anyone can read every invite email and token.Fix: Enable row-level security on team_invites and add policies that allow team members only.

    supabase/migrations/20240901120000_init.sql

  4. The task API creates tasks without checking the callerAnyone can create tasks for any team ID and spend the OpenAI budget.Fix: Read the signed-in user first, check team membership, and add a rate limit.

    app/api/tasks/route.ts

  5. No tests and no CIChanges after the handover are risky, because nothing catches regressions.Fix: Add tests for checkout, the webhook and the task API, and run them in CI.

    package.json

Questions a buyer will ask

  • Has the Stripe key in lib/stripe.ts been rotated?Show the Stripe event that revoked the old key, and the new environment variable setup.

    lib/stripe.ts

  • How are paid upgrades verified?Point to the webhook signature check after you add it, and to Stripe's event log.

    app/api/webhooks/stripe/route.ts

  • Who can read the team_invites table?Share the migration that turns on row-level security and its policies.

    supabase/migrations/20240901120000_init.sql

  • What does OpenAI cost each month?Share the OpenAI billing page for the last three months and the number of active teams.

    lib/ai.ts

  • How do I set up and deploy the app?Add setup and deploy steps to the README, and list every environment variable in .env.example.

    README.mdpackage.json

Findings (24)

All findings (24)

CriticalSecurity · SEC-01

A stripe live secret key (sk_l…8D) is written in lib/stripe.ts, line 4. Anyone who can read this repository can use it.

lib/stripe.ts · line 4

export const stripe = new Stripe("sk_l…8D", { apiVersion: "2024-04-10" });

Why buyers care

Anyone with the code can spend your money or read your data. A buyer will ask you to rotate every key before the sale.

How to fix

1. Revoke the key in the provider's dashboard and make a new one. 2. Remove it from the code and read it from an environment variable. 3. Remove it from the git history (for example with git filter-repo): old commits still contain it.

CriticalSecurity · SEC-03

The migration creates public.team_invites, but no migration turns on row-level security for it. With the public anon key, anyone can read and change every row.

supabase/migrations/20240901120000_init.sql · line 16

create table public.team_invites (

Why buyers care

Any user, or anyone with the public key, can read every row.

How to fix

1. Add a migration: alter table public.team_invites enable row level security; 2. Add policies that allow only the rows that each user may see. 3. Test with two users that one cannot read the other's rows.

CriticalSecurity · SEC-06

GHSA-2464-fhr4-w9xw: Next.js: Unauthenticated Remote Code Execution in Image Optimization API when SVG files are used · GHSA-2xp9-vwfh-vxw4: Next.js: Unauthenticated Remote Code Execution in Image Optimization API when AVIF files are used · GHSA-36qx-fr4f-26g5: Next.js has a Middleware / Proxy bypass in Pages Router applications using i18n

package-lock.json

next@14.2.3

Why buyers care

Known exploit paths that attackers can look up.

How to fix

1. Update next to a fixed version (see the advisories). 2. Run the tests. 3. Scan again to confirm.

HighSecurity · SEC-06

GHSA-29mw-wpgm-hmr9: Regular Expression Denial of Service (ReDoS) in lodash · GHSA-35jh-r3h4-6jhm: Command Injection in lodash · GHSA-f23m-r3pf-42rh: lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and `_.omit`

package-lock.json

lodash@4.17.15

Why buyers care

Known exploit paths that attackers can look up.

How to fix

1. Update lodash to a fixed version (see the advisories). 2. Run the tests. 3. Scan again to confirm.

HighSecurity · SEC-08

app/api/webhooks/stripe/route.ts handles Stripe events but does not verify the Stripe-Signature header.

app/api/webhooks/stripe/route.ts · line 6

  if (event.type === "checkout.session.completed") {

Why buyers care

Anyone can send a fake "payment succeeded" event and unlock paid features.

How to fix

1. Read the raw request body. 2. Call stripe.webhooks.constructEvent(body, signature, webhookSecret) before you use the event. 3. Return HTTP 400 when the check fails.

HighCode health · COD-01

The repository has 11 source files and no test files.

package.json

Why buyers care

Every change is risky: nothing shows when something breaks.

How to fix

1. Add a test runner (for example Vitest or pytest). 2. Write tests for the most important flows first: sign-in, payments, data access. 3. Run them in CI.

HighDocs & handover · DOC-01

README.md has 26 words. A buyer needs at least an overview, the setup steps and how to deploy.

README.md

Why buyers care

The buyer cannot start the app without asking you.

How to fix

1. Write what the product does and its stack. 2. Add the setup commands, the environment variables and the deploy steps. 3. Add how to run the tests.

HighDocs & handover · DOC-03

The code reads 4 environment variables (NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_URL, OPENAI_API_KEY and SUPABASE_SERVICE_ROLE_KEY), but there is no .env.example that lists them.

.env.example

Why buyers care

The buyer cannot configure the app.

How to fix

1. Add .env.example with every variable name and an empty value. 2. Add a comment that says where to get each value.

HighOwnership & provenance · OWN-02

LICENSE gives everyone the right to use, copy and change this code under the MIT licence.

LICENSE

MIT License

Why buyers care

The buyer may not get exclusive rights: copies already have a licence.

How to fix

1. Check whether the licence came from a template, and keep that template's notice where it applies. 2. For your own code, replace the licence with a proprietary notice. 3. Ask a lawyer if the code was ever published under this licence.

MediumCode health · COD-03

No GitHub Actions, GitLab CI, CircleCI or similar configuration was found.

.github/workflows/

Why buyers care

Nothing checks changes before they reach production.

How to fix

1. Add .github/workflows/ci.yml. 2. Run install, typecheck, lint, tests and build on each push and pull request.

MediumDocs & handover · DOC-02

README.md does not show the commands to install and run the app.

README.md

Why buyers care

The handover takes longer, and the buyer may set it up wrong.

How to fix

1. Add a "Develop" section with the exact commands, for example pnpm install and pnpm dev. 2. Add the commands for tests and the database.

MediumOperability · OPS-02

No deploy file (for example vercel.json, Dockerfile or fly.toml) was found, and the README does not explain hosting.

README.md

Why buyers care

The buyer does not know where and how the app runs.

How to fix

1. Add a "Deploy" section to the README: the host, the build command and the environment variables. 2. Commit the host's config file if it has one.

MediumSecurity · SEC-09

AI-suggested. Check before you rely on it.

The handler reads teamId from the request body and inserts tasks with the service-role client, without reading a session. (AI review of app/api/tasks/route.ts.)

app/api/tasks/route.ts

Why buyers care

An open endpoint that anyone can call.

How to fix

1. Get the signed-in user (or verify the webhook signature) before the route reads or changes data. 2. Return HTTP 401 when the check fails. 3. Add a test that calls the route without a session.

MediumSecurity · SEC-09

AI-suggested. Check before you rely on it.

The webhook parses the JSON body without verifying the Stripe-Signature header. (AI review of app/api/webhooks/stripe/route.ts.)

app/api/webhooks/stripe/route.ts

Why buyers care

An open endpoint that anyone can call.

How to fix

1. Get the signed-in user (or verify the webhook signature) before the route reads or changes data. 2. Return HTTP 401 when the check fails. 3. Add a test that calls the route without a session.

LowSecurity · SEC-11

No Content-Security-Policy, X-Frame-Options or Strict-Transport-Security header is set in the code or config.

next.config.js

Why buyers care

Weaker browser protection against clickjacking and script injection.

How to fix

1. Add security headers in the framework config (for Next.js: headers() in next.config). 2. Start with X-Frame-Options: DENY, Referrer-Policy and a strict CSP.

LowDependencies & licences · DEP-03

The root folder has package-lock.json and yarn.lock. Different package managers can install different versions.

package-lock.json

yarn.lock

Why buyers care

Confusing builds: it is not clear which install is the real one.

How to fix

1. Choose one package manager. 2. Delete the other lockfiles. 3. Set "packageManager" in package.json.

LowDependencies & licences · DEP-04

package.json uses Git URLs, "*" or "latest" for left-pad (latest).

package.json

"left-pad": "latest"

Why buyers care

Builds that change over time without a code change.

How to fix

1. Replace each one with a published version range, for example ^1.2.3. 2. Install again and commit the lockfile.

LowCode health · COD-04

tsconfig.json does not set "strict": true, so TypeScript does not report many common bugs (for example null values).

tsconfig.json

Why buyers care

More hidden bugs that the compiler could catch.

How to fix

1. Set "strict": true in tsconfig.json. 2. Fix the errors that the compiler reports, one folder at a time.

LowCode health · COD-05

No ESLint, Biome, Prettier, Ruff, Black or similar configuration was found.

package.json

Why buyers care

Inconsistent code that is harder to read and change.

How to fix

1. Add a linter and a formatter (for example ESLint and Prettier, or Ruff). 2. Run them in CI.

LowOperability · OPS-03

No error-tracking package (for example Sentry or Bugsnag) was found.

package.json

Why buyers care

Errors in production go unseen until a customer complains.

How to fix

1. Add an error-tracking service (for example Sentry). 2. Put its DSN in .env.example.

LowOperability · OPS-04

No /health (or similar) route was found for uptime monitors.

app/api/health/route.ts

Why buyers care

Nothing simple to monitor, so outages are found late.

How to fix

1. Add a GET /api/health route that returns HTTP 200 with {"ok": true}. 2. Point an uptime monitor at it.

InfoOperability · OPS-05

The app uses OpenAI, Stripe and Supabase. Each one is an account to transfer and a cost to expect.

package.json

Why buyers care

Accounts to transfer and monthly costs to plan for.

How to fix

1. List each service in the data room with its plan and monthly cost. 2. Plan how each account moves to the buyer.

InfoOwnership & provenance · OWN-04

Signs of AI-assisted development: CLAUDE.md, .cursorrules and 31 commits with an AI co-author.

CLAUDE.md

.cursorrules

Why buyers care

Disclose AI use in the sale agreement. Buyers ask about it.

How to fix

1. Say in the data room which AI tools were used and how the code was reviewed. 2. Check the tools' terms for code ownership.

InfoOwnership & provenance · OWN-05

The repository has one contributor (46 commits).

.git

Why buyers care

Context for the buyer: the bus factor and how mature the code is.

How to fix

1. Explain the history in the data room. 2. Offer a handover call or a support period after the sale.

Dependencies

Direct dependencies (10)

  • next 14.2.3

    MITOK

    Critical37 (GHSA-2464-fhr4-w9xw, GHSA-2xp9-vwfh-vxw4, GHSA-36qx-fr4f-26g5, and 34 more)
  • lodash 4.17.15

    MITOK

    High6 (GHSA-29mw-wpgm-hmr9, GHSA-35jh-r3h4-6jhm, GHSA-f23m-r3pf-42rh, and 3 more)
  • @types/react 18.3.3 · dev

    Unknown licenceOK

    None known
  • typescript 5.4.5 · dev

    Unknown licenceOK

    None known
  • left-pad 1.3.0

    MITOK

    None known
  • openai 4.47.1

    MITOK

    None known
  • stripe 15.8.0

    MITOK

    None known
  • @supabase/supabase-js 2.43.4

    MITOK

    None known
  • react-dom 18.3.1

    MITOK

    None known
  • react 18.3.1

    MITOK

    None known

Architecture

Languages
TypeScript (9), SQL (1), JavaScript (1)
Frameworks
Next.js, React
Third-party services
OpenAI, Stripe, Supabase
Size
11 source files · 115 lines · 0 test files

Architecture

AI-suggested. Check before you rely on it.

TaskPilot is one Next.js 14 App Router application. Pages render on the server and read tasks from Supabase with the anon key. Route handlers under app/api create tasks with the OpenAI API and receive Stripe webhooks. A Supabase admin client with the service-role key writes data from the server. Stripe Checkout takes payments. There are no background jobs; everything runs inside request handlers.

Components: Web pages, Task API, Stripe webhook, Database access, Database schema.
Drawing the diagram…
  • Web pagesThe landing page and the task dashboard (server components).

    app/page.tsxapp/dashboard/page.tsxapp/layout.tsx

  • Task APITurns goals into tasks with OpenAI and saves them.

    app/api/tasks/route.tslib/ai.ts

  • Stripe webhookUpgrades a team to Pro after checkout.

    app/api/webhooks/stripe/route.tslib/stripe.ts

  • Database accessSupabase clients: the anon key for pages, the service-role key for server writes.

    lib/supabase.tslib/supabase-admin.ts

  • Database schemaThe teams, tasks and team_invites tables.

    supabase/migrations/20240901120000_init.sql

Findings: Code health (4)

HighCode health · COD-01

The repository has 11 source files and no test files.

package.json

Why buyers care

Every change is risky: nothing shows when something breaks.

How to fix

1. Add a test runner (for example Vitest or pytest). 2. Write tests for the most important flows first: sign-in, payments, data access. 3. Run them in CI.

MediumCode health · COD-03

No GitHub Actions, GitLab CI, CircleCI or similar configuration was found.

.github/workflows/

Why buyers care

Nothing checks changes before they reach production.

How to fix

1. Add .github/workflows/ci.yml. 2. Run install, typecheck, lint, tests and build on each push and pull request.

LowCode health · COD-04

tsconfig.json does not set "strict": true, so TypeScript does not report many common bugs (for example null values).

tsconfig.json

Why buyers care

More hidden bugs that the compiler could catch.

How to fix

1. Set "strict": true in tsconfig.json. 2. Fix the errors that the compiler reports, one folder at a time.

LowCode health · COD-05

No ESLint, Biome, Prettier, Ruff, Black or similar configuration was found.

package.json

Why buyers care

Inconsistent code that is harder to read and change.

How to fix

1. Add a linter and a formatter (for example ESLint and Prettier, or Ruff). 2. Run them in CI.

Operations

Deploy config
None found
CI config
None found
Scripts
dev, build, start
Environment variables
4 used · 4 not in .env.example

Handover plan

AI-suggested. Check before you rely on it.

Set up a new copy

  1. Install Node.js 20 or newer.
  2. Run npm install.
  3. Make a Supabase project and run the migration in supabase/migrations.
  4. Put the environment variables below in .env.local.
  5. Run npm run dev and open http://localhost:3000.

Environment variables

  • NEXT_PUBLIC_SUPABASE_URL · requiredThe Supabase project URL.
  • NEXT_PUBLIC_SUPABASE_ANON_KEY · requiredThe public key for page reads.
  • SUPABASE_SERVICE_ROLE_KEY · requiredThe server-only key for writes in route handlers.
  • OPENAI_API_KEY · requiredWrites task plans.

Services and costs

  • SupabaseDatabase and auth. A free tier, then a monthly plan for each project.

    lib/supabase.ts

  • OpenAITask plans. Billed per token. It grows with the number of active teams.

    lib/ai.ts

  • StripePayments. A fee on each successful payment.

    lib/stripe.ts

Runbook

  • Rotate the Stripe key and move it to an environment variable before the transfer.
  • Make each database change as a new migration in supabase/migrations.
  • Watch OpenAI usage after each pricing change.
  • Scan again with Proofpack after each fix.

Known gaps

  • There are no tests and no CI.

    package.json

  • There is no .env.example, so the configuration is not documented.

    lib/supabase.tslib/ai.ts

  • The README has no setup or deploy steps.

    README.md

Ownership

Commits
46
Contributors
1
First commit
2 Sept 2026
Last commit
28 Oct 2026
Commits with an AI co-author
31 of 46

Licences to review (0)

All direct dependencies use permissive licences.

Data room

AI-suggested. Check before you rely on it.

TaskPilot

TaskPilot is an AI task planner for small teams. A team lead enters the goals for the week, and TaskPilot turns them into a list of tasks that the whole team can see.

Users

  • Small teams of 3 to 15 people who plan work every week.
  • A free plan, and a Pro plan sold through Stripe Checkout.

Stack

  • Next.js 14 with the App Router (app/).
  • Supabase Postgres for data (supabase/migrations/20240901120000_init.sql).
  • OpenAI for the task plans (lib/ai.ts).
  • Stripe for payments (lib/stripe.ts).

AI-suggested. Check before you rely on it.

Components

  • Pages render on the server and read tasks with the Supabase anon key (app/dashboard/page.tsx).
  • Task API turns goals into tasks with OpenAI and saves them with the service-role key (app/api/tasks/route.ts).
  • Stripe webhook upgrades a team after checkout (app/api/webhooks/stripe/route.ts).

Data flow

  1. A user submits goals.
  2. The task API asks OpenAI for a plan.
  3. The tasks are saved in Supabase.
  4. A payment through Stripe Checkout calls the webhook, which sets the plan to Pro.

AI-suggested. Check before you rely on it.

Requirements

  • Node.js 20 or newer
  • A Supabase project
  • An OpenAI API key and a Stripe account

Steps

  1. Run npm install.
  2. Run the migration in supabase/migrations.
  3. Put the environment variables in .env.local (see the environment variables document).
  4. Run npm run dev.

AI-suggested. Check before you rely on it.

Services

ServiceWhat it doesHow it is billed
SupabaseDatabase and authFree tier, then a monthly plan
OpenAIWrites task plansPer token
StripePaymentsA fee on each payment

OpenAI is the cost that grows with use. See lib/ai.ts.

Environment variables

Names only. Values are never stored or shown.

NameRead in codeIn .env.examplePurpose (AI-suggested)
NEXT_PUBLIC_SUPABASE_ANON_KEYyesnoThe public key for page reads.
NEXT_PUBLIC_SUPABASE_URLyesnoThe Supabase project URL.
OPENAI_API_KEYyesnoWrites task plans.
SUPABASE_SERVICE_ROLE_KEYyesnoThe server-only key for writes in route handlers.

Dependencies & licences

10 direct dependencies.

Known vulnerabilities

  • next@14.2.3: 37 advisories
  • lodash@4.17.15: 6 advisories

Licences to review

All direct dependencies use permissive licences.

AI-suggested. Check before you rely on it.

Before the transfer

  • Rotate the Stripe key that is written in lib/stripe.ts, and move it to an environment variable.
  • Turn on row-level security for team_invites.
  • Add a signature check to the Stripe webhook.

Accounts to transfer

  • Supabase project
  • Stripe account
  • OpenAI organization

Known gaps

  • No tests or CI.
  • No .env.example.

Disclosures

Facts a buyer may ask the seller to state in the sale agreement.

History

  • 46 commits by 1 contributor
  • First commit 2026-09-02, last commit 2026-10-28
  • 31 commits name an AI co-author

Ownership & provenance

  • High: The product carries an open-source licence (MIT)
  • Info: Built with AI coding tools
  • Info: One contributor

Proofpack is an automated screening tool. It reads your repository and reports patterns that buyers often ask about. It is not a security audit, a legal opinion, an IP opinion or a valuation. Check important findings with a qualified professional.

Proofpack is an automated screening tool. It reads your repository and reports patterns that buyers often ask about. It is not a security audit, a legal opinion, an IP opinion or a valuation. Check important findings with a qualified professional.