Real example

SEE IT WORK BEFORE YOU BUY

A real example report

These are real outputs of the Master of All Skills Claude Code plugin (version 1.1), run on a small sample online-shop app built for this demonstration. Nothing was written by hand or polished afterwards; only local folder paths were removed.

The sample project: a Next.js shop with a home page, a contact form, an orders API using Firestore, an admin page and open database rules — the kind of small problems real projects have. Each report below was produced by one service.

/master-of-all-skills:inspect

Inspect

Read-only inspection of the project: stack, routes, data, integrations, risks.

Show the full output

Inspection report: sample-shop

I only read files. Nothing was changed, installed or run beyond git commands, and I made no ledger entry because this skill only asks for one when files change, checks run or outside services are called.

Git state

  • Branch: main. The working tree is clean, so there's no uncommitted work to protect.
  • History (2 commits): 377d861 added the pages, contact form, orders API and admin page. 0f8a8b1 added the project map and ledger in .mos/.
  • git diff --stat: empty.
  • Project map: .mos/project-map.md was recorded at 377d861. Since then only .mos/ files changed, so the map is still accurate and I checked it against the code.

Stack

Item Finding Tag
Framework Next.js 15.0.0 using the app/ folder, React 19.0.0, plain JavaScript Observed: package.json:5
Database Firestore via firebase-admin 13.0.0, set up on the server only Observed: lib/firebase.js:1-4
CLAUDE.md / AGENTS.md None Observed
.gitignore, lockfile, node_modules None Observed: file listing
README One line describing the project Observed: README.md:3

Pages and API endpoints

Route File Auth Notes Tag
/ app/page.js:2 none Static page that links to /contact Observed
/contact missing — The link on the home page leads to a 404 Observed
/admin app/admin/page.js:1 none Shows only a heading and loads no data Observed
POST /api/contact app/api/contact/route.js:1-4 none Reads the message, then throws it away: nothing is stored or emailed Observed
GET /api/orders app/api/orders/route.js:2-5 none Returns up to 20 full order records to anyone Observed
POST /api/orders app/api/orders/route.js:6-10 none Saves whatever data it receives, unchecked Observed

None of the routes handle errors, check their input or limit request rates. Nothing in the app calls either API.

Data, rules and integrations

  • Firestore orders: there's no defined shape for an order. It's whatever the caller sends (observed).
  • firestore.rules:4: allow read, write: if true lets anyone who has the project ID read, change or delete every order through the Firebase client libraries (observed). The server routes use the admin SDK, which skips these rules anyway (inferred).
  • Environment variable names in .env.example: FIREBASE_PROJECT_ID is read at lib/firebase.js:3. SMTP_USER and SMTP_APP_PASSWORD are never read (observed).
  • Firebase credentials: none are passed in code, so the app falls back to the host's default Google credentials (inferred).
  • Email: SMTP is set up in the env file but not built, and no mail library is installed (observed).
  • Login, payments, file storage, analytics, AI providers: none found (observed).

Checks

  • Scripts: dev, build and start only (package.json:4). There are no tests, linting or type-checking (observed).
  • I ran no checks. A build would need npm install, which this read-only skill doesn't allow. There are no tests to run.

Deployment

  • Hosting: there's no vercel.json, firebase.json, Dockerfile or CI setup (observed). It probably targets Vercel or a generic Node host (inferred).
  • Firestore rules: no config shows whether they are deployed.

Risks

  1. Public database rules: anyone can read and write all orders.
  2. Open orders API: order data can be read without logging in, and anyone can write unchecked records.
  3. Admin page: /admin has no login. It's harmless today because it shows no data, but it will matter once it does.
  4. Contact form: the endpoint silently drops messages, and the /contact page doesn't exist.
  5. Route safety: there's no error handling, rate limiting, input checking or check that environment variables are set at startup.
  6. No .gitignore: a real .env file could be committed by accident.
  7. No lockfile: Next 15.0.0 is an early release with security advisories that later patches fix. npm audit was not run.

Unknowns

  • Where the app is deployed, and whether it's live.
  • Which Firestore rules are actually deployed.
  • How Firebase credentials are supplied at runtime.
  • What an order should contain, and who may create or read orders.
  • Which SMTP provider sends contact messages, and who receives them.
TASK: Read-only inspection of sample-shop
STATUS: Review — inspection complete, no changes made
LANES: single
TESTS: 0 passed, 0 failed, 0 not run (no test suite exists; build/npm audit NOT RUN — needs npm install)
DEPLOYMENT: 0f8a8b1 — not deployed / deployment target unknown
APPROVALS: none pending
RISKS: public read/write Firestore rules; unauthenticated, unvalidated orders API; unprotected /admin; contact submissions dropped, /contact missing; no .gitignore or lockfile; next@15.0.0 advisories unchecked
NEXT: Choose whether to (a) plan fixes starting with Firestore rules and orders API auth (security/data approvals required), (b) allow npm install + build + npm audit, or (c) confirm deployment target and Firebase credentials setup

/master-of-all-skills:map

Project map

The living project map, pinned to a commit, that later changes are checked against.

Show the full output

Project map — sample-shop

  • Commit: 377d8611206c1503b3a4777ca35d27b549171862 (main, "Sample Shop: pages, contact form, orders API, admin")
  • Date: 2026-11-11
  • Working tree at mapping time: clean
  • Previous map: none (first map — no drift to report)

Legend: [O] observed in the named file · [I] inferred (not directly evidenced)

Stack

Item Value Source
Framework Next.js 15.0.0, App Router (app/), React 19.0.0 [O] package.json, app/
Language JavaScript (no TypeScript) [O] file extensions
Database Firestore via firebase-admin 13.0.0 (server SDK) [O] lib/firebase.js
Package lock none committed [O] file listing
.gitignore none committed [O] file listing

Pages / routes

Route File Renders Auth Data Tag
/ app/page.js Static heading, tagline, link to /contact none none [O]
/admin app/admin/page.js Static "Orders admin" heading only; does not fetch orders none none [O]
/contact — (no app/contact/page.js) Linked from /, but the page does not exist → 404 — — [O] missing

Shared components and layouts

Item File Notes Tag
Root layout app/layout.js <html lang="en"><body>; metadata.title = 'Sample Shop' [O]
Shared components none No components/ directory [O]

API endpoints / server actions

Method + path File Auth Validation Rate limit Data touched Tag
POST /api/contact app/api/contact/route.js none none none Parses JSON body and discards it; returns { ok: true }. Sends no email, stores nothing. [O]
GET /api/orders app/api/orders/route.js none — none Reads up to 20 docs from Firestore orders; returns full document data publicly [O]
POST /api/orders app/api/orders/route.js none none — arbitrary JSON written as-is none Writes a new doc to Firestore orders [O]
Server actions none found — — — — [O]

No route has try/catch; errors surface as unhandled 500s. [O]

Data stores and collections

Store Collection Read by Written by Tag
Firestore (Admin SDK, initialised in lib/firebase.js) orders app/api/orders/route.js GET app/api/orders/route.js POST [O]

Document schema for orders: undefined — whatever the client posts. [O]

Security rules and policies

File Rule Effect Tag
firestore.rules match /orders/{id} { allow read, write: if true; } Any client-SDK caller who knows the project ID can read, modify and delete all orders [O]
— Admin SDK bypasses Firestore rules, so the API routes are unaffected by this file — [I] (standard firebase-admin behaviour)
Middleware / auth none (middleware.js absent, no auth library) — [O]
Deployment of rules No firebase.json / .firebaserc; how and whether firestore.rules is deployed is unknown — [O] absent / unknown

Environment variables (names only)

Name Declared in Read in Tag
FIREBASE_PROJECT_ID .env.example lib/firebase.js:3 [O]
SMTP_USER .env.example not read anywhere [O]
SMTP_APP_PASSWORD .env.example not read anywhere [O]

Firebase Admin credentials: none passed explicitly; initializeApp will rely on Application Default Credentials (GOOGLE_APPLICATION_CREDENTIALS or the hosting runtime's service account). [I] No env validation at startup. [O]

External integrations

Integration Status Files Tag
Google Firebase / Firestore Active lib/firebase.js, app/api/orders/route.js, firestore.rules [O]
SMTP email (likely Gmail app password) Declared but not implemented; no mail library in package.json .env.example [O] declared / [I] provider

Background jobs and schedules

None found (no cron config, no vercel.json, no Cloud Functions). [O]

Deployment targets and config

Item Finding Tag
Hosting config None committed (no vercel.json, firebase.json, Dockerfile, CI workflows) [O]
Likely target Vercel or any Node host via next build / next start [I]
Scripts dev, build, start [O] package.json

Tests

None. No test runner, no test files, no test script. All areas uncovered. [O]

Dependency table

Dependency Depended on by Tag
Firestore orders collection GET /api/orders, POST /api/orders (app/api/orders/route.js); /admin is named for orders but does not use it yet [O] / [I] for admin intent
lib/firebase.js (db) app/api/orders/route.js [O]
FIREBASE_PROJECT_ID lib/firebase.js → all orders endpoints [O]
firestore.rules Any client-SDK access to orders (none in this repo) [O]
POST /api/contact No caller in repo (intended /contact page is missing) [O]
GET/POST /api/orders No caller in repo (no UI fetches it) [O]
SMTP (SMTP_USER, SMTP_APP_PASSWORD) Nothing yet; presumably intended for /api/contact [I]
app/layout.js All pages (/, /admin) [O]

Risks observed (for follow-up; not fixed by this service)

  1. firestore.rules allows public read/write of orders.
  2. GET /api/orders exposes order data without authentication.
  3. POST /api/orders accepts unauthenticated, unvalidated arbitrary JSON.
  4. /admin has no authentication (currently harmless — renders no data).
  5. Contact form endpoint silently drops submissions; /contact page missing (broken link on /).
  6. No try/catch, rate limiting, input validation or env validation on any route.
  7. No .gitignore — a local .env or node_modules could be committed accidentally.
  8. No lockfile; next@15.0.0 is an early 15.x release with published security advisories in later patch releases — check npm audit (not run).

Unknowns

  • Where the app is deployed and whether a production deployment exists.
  • Whether firestore.rules has been deployed to the Firebase project, and what rules are live.
  • How Firebase Admin credentials are provided at runtime.
  • Intended orders schema and who should be allowed to create/read orders.
  • Intended SMTP provider and recipient for contact submissions.
  • Whether there are other Firestore collections in the live project not referenced by code.

/master-of-all-skills:plan

Scope Contract and plan

Plan for a real request, with approval checkpoints and parallel lanes. Nothing is changed before approval.

Show the full output

Scope Contract: lock down orders and make the contact form send email

Basis: repo at 0f8a8b1. .mos/project-map.md was made at 377d861, and only .mos/ files have changed since, so the map is still accurate. Working tree clean. Today is Wed 2026-11-11, so the deadline is Fri 2026-11-13.

Goal Only signed-in admins can read or change orders. Contact form submissions arrive as email.
In scope Admin sign-in using Firebase Auth (the project already uses Firebase) with an admin flag on each admin account. Admin-only GET/POST /api/orders. A protected /admin page that lists orders. Firestore rules that block all direct client access. A real contact page and contact API that sends mail through SMTP (SMTP_USER/SMTP_APP_PASSWORD already exist). Input validation, try/catch, rate limits and safe errors on the routes I touch. .gitignore, lockfile, tests.
Out of scope A customer checkout flow. Customer accounts. Upgrading Next.js (risk noted below). Hosting changes. Auditing or cleaning up existing order data. Styling beyond basic accessible forms.
Must not change Home page content and layout. Root layout. Existing orders documents and their shape. The GET /api/orders response shape for admins. Existing env var names. Firestore project.
Acceptance tests AT1 GET /api/orders: no session → 401, non-admin → 403, admin → 200 with the same array shape as now. AT2 POST /api/orders: same auth results, and a bad body from an admin → 400. AT3 /admin: signed out → redirect to /login; non-admin → 403 with no order data in the HTML; admin → orders listed. AT4 Firestore rules emulator: signed-out and signed-in client reads and writes on orders/{id} are all denied. AT5 POST /api/contact: valid → 200 and mail goes to CONTACT_TO with reply-to set to the sender; invalid → 400; hidden spam-trap field filled → 200 with nothing sent; 6th request per IP per minute → 429; SMTP failure → 502 with a generic message and no secrets in logs. AT6 /contact works at 375px, fields have labels, success and error states show, and the home page link no longer 404s. AT7 npm run build and npm test pass. AT8 Session cookie is HttpOnly, Secure in production and SameSite=Lax; sign-out revokes it. Manual: one real email is received in the inbox, confirmed by you.
Risks Firestore rules are publicly read/write right now, so the leak is live until the rules are deployed. Next 15.0.0 has known advisories, including a middleware auth bypass, so auth checks go in each route and page, not in middleware. I don't know where the app is hosted or how it gets Firebase admin credentials. Session cookies need service-account credentials. An in-memory rate limit only holds per server instance. Gmail allows roughly 500 sends a day. Something outside this repo may use the client SDK on orders.
Approval mode standard
Approvals needed A1 Auth and permission change: admin-only orders API and /admin, plus a new /api/session route. A2 Firestore rules change to allow read, write: if false on orders, plus a new firebase.json. A3 New service and keys: turn on Firebase Authentication (email/password), add the client firebase SDK, add NEXT_PUBLIC_FIREBASE_* and service-account env vars. A4 Give the admin flag to the accounts you name, using a script you run. A5 Send email through Gmail SMTP with an app password, using the nodemailer package and a new CONTACT_TO env var. A6 Public-facing text on /contact and /login. A7 Production deploys, split into A7a Firestore rules and A7b app.
Est. changes About 20 files (about 11 new, 9 modified) in 7–9 commits on one branch, with one PR.
Deadline Fri 2026-11-13

Questions to answer in your edits:

  • Q1 Who may create orders? I recommend admins only, since nothing in the repo calls POST. If you choose public, I'll keep POST open but validated against a field allowlist and rate-limited.
  • Q2 Which inbox should contact mail go to, and which account sends it?
  • Q3 Admin email address(es)?
  • Q4 Where is the app hosted, and how does it get Firebase admin credentials?
  • Q5 Sign in with email/password (recommended) or Google?

Tasks

# Task Files / mapped areas Depends on Acceptance Check to run Risk Approval Paid / new access
T0 Create the branch. Add .gitignore, all new dependencies (firebase, nodemailer, vitest, @firebase/rules-unit-testing) and the lockfile. Run a baseline build. package.json, .gitignore none AT7 baseline npm install && npm run build Low none No
T1 Add startup env checks. Let lib/firebase.js accept explicit service-account credentials or fall back to the host's default credentials. Add a shared rate limiter. Add every new env var name to .env.example. lib/env.js, lib/firebase.js, lib/rate-limit.js, .env.example. Env: FIREBASE_PROJECT_ID + new vars T0 Unit tests: missing vars fail clearly npm test Med A3 Service-account key
T2 Add server auth helpers (check the session cookie and the admin flag). Add POST/DELETE /api/session to sign in and out. lib/auth.js, app/api/session/route.js (new endpoint) T1 AT8, plus unit tests for helpers npm test High A1, A3 Firebase Auth enabled
T3 Build the /login page using the client SDK. app/login/page.js, lib/firebase-client.js (new route) T2 Sign in, then land on /admin build + manual Med A3, A6 No
T4 Lock down the orders API: admin check, try/catch, body validation, 401/403/400. app/api/orders/route.js. Collection: orders T2 AT1, AT2 npm test High A1 No
T5 Protect /admin (redirect or 403) and list orders for admins. app/admin/page.js. Collection: orders T2 AT3 npm test + manual High A1 No
T6 Add scripts/set-admin.mjs <email> to set the admin flag. You run it. scripts/ T2 The account's token shows admin: true you run it Med A4 No
T7 Change the rules to deny all client access to orders, add firebase.json, add an emulator test. firestore.rules, firebase.json, tests/rules.test.js T0 AT4 firebase emulators:exec "npm run test:rules" (BLOCKED if Java isn't installed) High A2 No
T8 Contact API: validation, spam-trap field, rate limit, mail through lib/mailer.js, safe errors, logs with personal data removed. app/api/contact/route.js, lib/mailer.js. Env: SMTP_*, CONTACT_TO T1 AT5, with the mail transport mocked npm test Med A5 Gmail app password
T9 Build the /contact page form. app/contact/page.js (new route) T8 AT6 build + 375px check Low A6 No
T10 Independent review of the auth and rules changes by a fresh subagent, checked against this plan, as the policy requires. diff for T2–T7 T2–T7 Findings fixed or accepted — — — No
T11 Full verification, README update, ledger entry, PR. README.md, .mos/ledger.md T0–T10 AT1–AT8 npm run build && npm test — — No
T12 Deploy the rules first, then the app, then check the deployment for that exact commit. Deployment targets T11 Live 401 on /api/orders, plus the manual email verify-deploy High A7a, A7b Hosting access

Parallel lanes

  • Lane 0 (sequential, first): T0 → T1. These change package.json, .env.example and lib/firebase.js, which everything else depends on. Adding all dependencies and env var names up front means no later lane needs to touch those files.
  • Lane A (sequential): T2 → T3, T4, T5, T6. These all share lib/auth.js, the session cookie and the Firebase Auth env vars, so they stay in one lane.
  • Lane B: T8 → T9. These touch only the contact files and the SMTP env vars. They share no files, collections, rules or deploy settings with A or C.
  • Lane C: T7. It touches only firestore.rules and firebase.json. The server code uses the admin SDK, which ignores Firestore rules, so this lane doesn't affect A.
  • Final (sequential): T10 → T11 → T12.

Suggested order for Friday: do T7 and A7a on Thursday. That closes the open Firestore hole without waiting for the app deploy.

Costs (nothing gets purchased)

I didn't fetch pricing pages this session. Treat every line as verify at checkout.

  • Firebase Authentication, email/password: free on Spark and Blaze for up to about 50k monthly active users (from my knowledge, not checked today). Phone/SMS sign-in costs extra and isn't used here. Source: firebase.google.com/pricing.
  • Firestore: already in use, no change in usage.
  • Gmail SMTP with an app password: free on a personal Gmail account (needs 2-Step Verification), with a limit of roughly 500 sends a day. Sending from a business domain needs Google Workspace; plans are listed at workspace.google.com/pricing.
  • npm packages: firebase, nodemailer, vitest, @firebase/rules-unit-testing, firebase-tools are open source and free.
  • Hosting: unchanged, provider unknown (Q4).

Approve, edit, or reject? I'll wait for your answer, and answers to Q1–Q5, before changing anything. Once you approve, I'll save this to .mos/approved-brief.md with the date and your exact edits.

TASK: Admin-only orders + contact form email (deadline Fri 2026-11-13)
STATUS: Planned — Scope Contract and 13-task plan waiting for approval
LANES: Lane 0 (T0–T1) → parallel A (auth/orders), B (contact), C (rules) → final review/verify/deploy
TESTS: 0 passed, 0 failed, all not run (planning only; repo has no tests yet)
DEPLOYMENT: not deployed (HEAD 0f8a8b1; live hosting unknown)
APPROVALS: plan approval pending; A1–A7 to be requested at their tasks
RISKS: Firestore rules publicly read/write right now; Next 15.0.0 advisories; admin credentials/hosting unknown; per-instance rate limit; possible outside client-SDK use of orders
NEXT: Approve, edit or reject the plan, and answer Q1–Q5

I didn't write a ledger entry for this step because no files were changed and no external services were called. The only commands run were read-only git commands.

/master-of-all-skills:security-review

Security review

Read-only security findings with file and line, the attack each allows, and the fix.

Show the full output

I found 2 critical and 3 high-severity issues. The most urgent: the Firestore rules let anyone read, change or delete every order, and the orders API has no login check at all. The installed Next.js and React versions are also in ranges with a published unauthenticated remote-code-execution advisory.

What I checked (commit 0f8a8b1): I read every file in the repo. The map from 377d861 is still accurate, since only .mos/ files changed after it.

  • Secrets: none committed. The search covers history too, because the app files haven't changed since the first commit.
  • Logging: the app logs nothing, so nothing sensitive leaks, but there's also no record of who did what.
  • npm audit: not run. There's no lockfile, and creating one in the scratchpad was blocked by this session's permissions. The dependency finding (C3) comes from published advisories I know of, not from an audit.
  • Ledger: writing to .mos/ledger.md was blocked by the same permissions, so the entry has not been added. The text is ready; say the word and I'll append it.

Critical

C1. The database rules allow public read and write: firestore.rules:4 (allow read, write: if true)

  • Attack: the Firebase project ID is meant to be public. Anyone with it can use the client SDK to read every order, change or delete orders, and write junk you pay to store.
  • Fix: allow read, write: if false;. The server's Admin SDK ignores these rules, so the API keeps working. Later, add an admin-only rule if needed.
  • Unknown: whether this file has been deployed. Check the live rules in the Firebase console.

C2. Anyone can list orders: app/api/orders/route.js:2-5

  • Attack: an anonymous GET /api/orders returns the full contents of up to 20 orders, including any names and addresses stored in them.
  • Fix: check the user's sign-in token on the server and require an admin role. Return only the fields the admin view needs.

C3. Vulnerable framework versions: package.json:5 (next@15.0.0, react@19.0.0)

  • Attack: these versions fall inside the published React Server Components advisories (CVE-2025-55182 / CVE-2025-66478), which allow unauthenticated remote code execution against App Router apps. This app uses the App Router.
  • Other advisories: a middleware auth bypass (CVE-2025-29927, fixed in 15.2.3) will matter as soon as login is added through middleware.
  • Fix: upgrade to the latest patched 15.x of next and the matching react/react-dom, commit a lockfile, then run npm audit.

High

H1. Orders can be forged: app/api/orders/route.js:6-10

  • Attack: whatever JSON a caller sends is stored as an order, with no login and no checks. Anyone can create orders with a made-up price or "paid": true, overwrite fields, or send documents up to 1 MiB to run up costs.
  • Fix: require sign-in, check the request against a schema that only allows known fields and caps size, and work out prices and status on the server. Store the customer's user ID on each order.

H2. No rate limiting on any route (/api/orders, /api/contact)

  • Attack: spam, write floods and a growing Firestore bill.
  • Fix: a per-IP limit, and/or Firebase App Check.

H3. Customers aren't separated from each other

  • Orders have no owner field, so once customers can view their own orders, the code has no way to restrict them to their own.
  • Fix: add a uid field and filter queries by the signed-in user. This also needs a matching database rule.

Medium

  • M1. No error handling (orders/route.js:3,7-8; contact/route.js:2): sending malformed JSON or a Firestore failure produces an unhandled 500 with no log entry. Add try/catch, return 400 for bad input, and log errors with personal data removed.
  • M2. /admin needs no login (app/admin/page.js:1): it shows no data today, but it becomes C2 as soon as it does. Check login and role inside the page or its layout on the server. Don't rely on middleware alone.
  • M3. No .gitignore: a local .env file or a service-account key file could be committed by accident. Ignore .env* (keep .env.example), node_modules, .next and *service-account*.json.

Low

  • L1. No startup check of settings (lib/firebase.js:3): if FIREBASE_PROJECT_ID is missing, the app quietly falls back to whatever credentials the host provides.
  • L2. Contact form (contact/route.js): submissions are thrown away. When email sending is added, validate and limit the length of fields, and strip line breaks from header fields to block email header injection. SMTP_APP_PASSWORD is not used anywhere yet.

Needs a specialist

  • Penetration test: before launch, once the fixes for C1–H3 are in.
  • Legal / compliance: if the open rules (C1) were ever live with real customer data, get a privacy lawyer to assess whether this was a reportable breach under GDPR or CCPA. The Firestore audit logs show whether anyone accessed the data.
  • Payments: card details must never go into orders. Use a hosted checkout from a payment provider so PCI DSS card-security rules stay minimal.

Fixes awaiting your approval

ID Change Covers
A1 Change firestore.rules to deny all client access C1
A2 Server-side login and admin-role checks on /api/orders and /admin, and a uid owner field on orders C2, H1, H3, M2
A3 Upgrade next/react/react-dom to patched versions and commit a lockfile C3
A4 Rate limiting (may need a new service, possibly paid) or App Check H2
A5 Schema validation, try/catch, startup settings check, .gitignore H1, M1, M3, L1

A1, A2 and A3 change security or authentication, so another reviewer will check those changes before I propose merging them.

TASK: Security review of sample-shop (read-only)
STATUS: Review — 2 critical, 3 high, 3 medium, 2 low findings
LANES: single
TESTS: 2 passed (file review, secret search), 0 failed, 2 not run (npm audit and git history search: blocked by permissions; no test suite exists)
DEPLOYMENT: 0f8a8b1 — not deployed (no deployment config)
APPROVALS: A1–A5 pending; ledger write blocked by permissions, entry not added
RISKS: live Firestore rules unknown; dependency advisories not confirmed by npm audit; whether data was exposed is unknown
NEXT: approve A1 + A3 first (urgent), then A2/A5; allow the ledger write and npm audit

/master-of-all-skills:fix

Fix with proof

An approved bug fix on a branch, with a test that fails before and passes after.

Show the full output

I fixed the crash: POST /api/contact now returns a 400 instead of a 500 when the body isn't valid JSON. The new test failed on 3 of 4 cases before the fix and passes 4 of 4 after it. I haven't run the app itself or next build, because there's no node_modules here.

Cause: app/api/contact/route.js:2 calls await req.json() with no error handling. A malformed, empty or plain-text body throws a SyntaxError there, and Next.js turns that into a 500.

Fix (app/api/contact/route.js, branch fix/contact-invalid-json, commit b92811b):

  • If the body can't be read as JSON, it returns 400 with { ok: false, error: "Request body must be valid JSON." }.
  • I also wrapped the whole handler in a try/catch, as the project's policy requires. Any other error returns a plain 500 message and logs only the error type, never what was submitted.
  • Valid requests behave the same as before (200 { ok: true }).
  • Risk is low: only bad requests change behaviour, and they now get a 400 where they used to get a 500.

Test (tests/contact-route.test.mjs): it uses Node's built-in test runner, so it needs no new packages. It checks one valid request and three bad ones (malformed JSON, plain text, empty body).

  • Before the fix: 1 passed, 3 failed with the SyntaxError at route.js:2.
  • After the fix: 4 passed. Command: node --test tests/contact-route.test.mjs, on Node v22.23.4.

Also:

  • There's no test script in package.json; adding one would go beyond the scope you approved. Until then, run the test with node --test tests/.
  • I added an entry to .mos/ledger.md as the project policy requires, in a separate commit (bb7450f), so you can drop it from the PR if you want.
  • Nothing has been pushed or deployed.
TASK: Return 400 instead of 500 when POST /api/contact gets a body that isn't valid JSON
STATUS: Review — fixed on branch fix/contact-invalid-json (b92811b + ledger bb7450f), not pushed
LANES: single
TESTS: 4 passed, 0 failed (node --test tests/contact-route.test.mjs); not run: next build, HTTP request to a running app, npm audit
DEPLOYMENT: not deployed (bb7450f exists only locally)
APPROVALS: none pending
RISKS: not checked inside the actual Next.js runtime; the contact form still throws submissions away and has no field validation or rate limiting; no test script in package.json
NEXT: push the branch and open a PR? and whether to approve adding "test": "node --test tests/" to package.json

/master-of-all-skills:status

Mission Control

The status view of work in progress, approvals and risks.

Show the full output

Here's where things stand. The contact-form fix is finished and its tests passed, but it hasn't been reviewed, pushed or deployed yet. I didn't change any files.

Sources read: .mos/ledger.md, .mos/project-map.md, git status, git log and the branches. There is no .mos/approved-brief.md, so no Scope Contract has been approved yet.

Repo: you're on branch fix/contact-invalid-json. Nothing is uncommitted. It is 2 commits ahead of main (b92811b is the fix and bb7450f is its ledger entry), and main itself is at 0f8a8b1.

Deployment: NOT CHECKED. The repo has no git remote and no hosting config (no vercel.json or firebase.json), and neither the vercel nor the firebase CLI is installed. So nothing tells me where bb7450f would deploy.

Project map: it is out of date. It was made at 377d861, and app/api/contact/route.js, which the map covers, has changed since. Run map again before relying on it for the contact endpoint.

Board

Stage Items
Planned — (there's no approved brief)
Building —
Review Contact-form fix: a request with invalid JSON now gets a 400 error instead of 500 (b92811b). It needs your review, plus a push or merge, which only you can approve.
Verified — (only the unit tests ran; the fix hasn't been checked on a running app)
Deployed —
Blocked —

Lanes: single.

NOT RUN / NOT VERIFIED

  • next build: NOT RUN (node_modules isn't installed).
  • A real request to a running dev server: NOT RUN.
  • npm audit: NOT RUN.
  • Deployment of bb7450f: NOT CHECKED (no remote and no hosting set up).
  • The map doesn't reflect the contact route as it is now.

Open risks (from the ledger and map)

  • Firestore: the orders rules let anyone read and write.
  • Orders API: it has no login check and no input validation.
  • /admin: the page has no protection.
  • Contact form:
    • It still throws submissions away and has no field validation or rate limiting.
    • The /contact page it links to is missing, so it returns 404.
  • SMTP: the variables are defined but nothing uses them.
  • Repo hygiene:
    • There's no .gitignore or lockfile.
    • There's no test script in package.json.

No ledger entry was added because this service only read files and git state.

TASK: Contact-form fix — return 400 instead of 500 on invalid JSON (branch fix/contact-invalid-json)
STATUS: Review — committed at b92811b (+ ledger bb7450f); 4/4 unit tests passed; not pushed, merged or deployed
LANES: single
TESTS: 4 passed, 0 failed, 3 not run (passed: node --test tests/contact-route.test.mjs; not run: next build, real request to a dev server, npm audit)
DEPLOYMENT: bb7450f — NOT CHECKED (no remote, no hosting config, no hosting CLI); not deployed
APPROVALS: none pending with IDs; merge/push of fix/contact-invalid-json needs your explicit approval
RISKS: orders Firestore rules let anyone read/write; orders API has no login or validation; /admin unprotected; contact form discards submissions and /contact page is 404; map out of date; no .gitignore or lockfile; fix not checked on a running app
NEXT: Review the fix and decide whether to merge it into main. Separately, tell me where the app is hosted, and whether to run /master-of-all-skills:map and /master-of-all-skills:plan for the security risks.

Get this for your own projects

The plugin runs in your own Claude Code with your own accounts. You approve every change that matters.

One-off purchase with 12 months of updates. Claude subscription and usage are not included.