尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A private workspace for legal matters. The current build covers legal-notice intake, private evidence, fact reconciliation, recipient confirmation, Razorpay test-mode payment, grounded document generation, automated QA, recorded human advocate review, and private final-PDF delivery. RTI-specific screens remain deferred.
• Node.js 22 or 24 LTS
• pnpm 10.30.3 (corepack enable, or use corepack pnpm in place of pnpm)
• Docker Desktop with Compose running, or an existing PostgreSQL server檢視完整 README ↗A private workspace for legal notices, RTI applications, and ₹199 lending certificates, with web and Expo mobile clients, private evidence, grounded AI drafting/QA, Razorpay payments, advocate review and private PDF delivery.
The current hosting plan is Hostinger for the Next.js website and DigitalOcean for the Nest API, PostgreSQL and Caddy. Follow docs/deploy-vps.md for deployment, environment values, Razorpay setup, mobile rebuilds, and the advocate's signed-certificate workflow. See the security review and operations plan before launch.
Adding valid RAZORPAY_KEY_ID and RAZORPAY_KEY_SECRET to the API environment automatically replaces the old manual payment flow on both clients. Configure the signed payment.captured webhook before going live so payments still complete after checkout is closed. Only captured payments start document work.
Lending certificates record money already paid or lent. The in-house advocate reviews the facts and uploads the final signed and stamped PDF on their letterhead; ordinary approval and automatic PDF generation cannot bypass that upload. Delivery is within 24 hours of verified payment and complete information. This product is a lending record, not an affidavit or notarisation. Its price comes from LENDING_CERTIFICATE_PRICE_PAISE=19900.
corepack enable, or use corepack pnpm in place of pnpm)Copy-Item .env.example .env
Copy-Item apps/api/.env.example apps/api/.env
Copy-Item apps/web/.env.example apps/web/.env
Choose a local database password and put the same value in the root POSTGRES_PASSWORD and the API DATABASE_URL (URL-encode special characters in the URL). Set the API's JWT_SECRET to a random value of at least 32 characters; placeholder secrets are rejected. You can generate one with:
node -e "console.log(require('node:crypto').randomBytes(48).toString('hex'))"
Add a Google AI Studio key to apps/api/.env as GEMINI_API_KEY. The key stays server-side. AI_PROVIDER=gemini and GEMINI_MODEL=gemini-3.8-flash are configuration values and can be changed without modifying application code. The application still starts and accepts private uploads when the key is empty: AI analysis shows a retryable failure instead of crashing.
Evidence files default to apps/api/.local/private-files (or the API process's equivalent working directory) and are ignored by Git. Set PRIVATE_STORAGE_DIR to an absolute path in production. EVIDENCE_MAX_BYTES defaults to 10 MB. FILE_SIGNING_SECRET should be a separate random value of at least 32 characters; local development falls back to JWT_SECRET when it is omitted.
The legal-notice price is configured in paise using LEGAL_NOTICE_PRICE_PAISE (default 29900, meaning ₹299). For Razorpay test mode, add RAZORPAY_KEY_ID, RAZORPAY_KEY_SECRET, and a separate RAZORPAY_WEBHOOK_SECRET to apps/api/.env. Configure Razorpay’s payment.captured webhook to call https://your-api.example/payments/razorpay/webhook. Missing Razorpay values leave review available and show a payment-setup message instead of crashing.
Then:
pnpm install
docker compose up -d --wait
pnpm db:generate
pnpm db:migrate
pnpm --filter @lawmedy/api db:seed
pnpm dev
The seed command creates the local advocate from ADVOCATE_EMAIL, ADVOCATE_FULL_NAME, and ADVOCATE_PASSWORD in apps/api/.env. Copy the placeholders from apps/api/.env.example, replace the password for your own environment, run the seed command, then sign in at /login. Advocate accounts are sent to the role-protected /advocate workspace.
Legal-notice and RTI final PDFs are drawn with pdfkit using the Noto fonts in apps/api/assets/fonts (Hindi text uses Noto Serif Devanagari). No browser or system fonts are needed. The API runs on the shared DigitalOcean droplet; see docs/deploy-shared-droplet.md.
Email delivery uses Resend. For sandbox testing, put RESEND_API_KEY and a verified RESEND_FROM sender in apps/api/.env. When these values are absent, advocate approval still creates the private PDF and completes the matter; the user sees the download in Lawmedy with a clear local email-configuration note.
Open localhost:3000. The Nest API runs at http://127.0.0.1:4000. If pnpm is not on PATH, all commands work as corepack pnpm …. If Docker is unavailable, provision PostgreSQL and set DATABASE_URL before running migrations. Do not use docker compose down -v unless you intend to delete the database; normal docker compose down preserves it.
If Turborepo reports that it cannot find the package manager, run corepack enable --install-directory node_modules/.bin after installation. This creates project-local pnpm shims without changing the system installation.
For a fresh checkout without Docker, run node scripts/local-db.mjs after pnpm install, before copying an API .env. This development-only helper runs real PostgreSQL 17 on loopback port 5433 and creates apps/api/.env with random local credentials and a JWT secret. It never overwrites an existing .env. Keep that terminal running, then run pnpm db:generate, pnpm db:migrate, and pnpm dev in a second terminal. Ctrl+C stops PostgreSQL and preserves data in the ignored .local/ directory. Restart using the same command. The bundled helper is a beta npm wrapper around PostgreSQL; Docker Compose remains the standard setup. Do not sync or commit .local/ or use this helper for production.
/signup and check that the dashboard opens.GEMINI_API_KEY empty, upload another file. The upload remains safely stored and listed, while extraction shows a handled Failed state with a retry button.payment.captured webhook./advocate groups assigned work into pending, waiting for user, and completed queues.pnpm typecheck
pnpm test
pnpm build
# Isolated PostgreSQL + API integration checks (no live providers or existing databases):
node scripts/verify-integration.mjs
# Adversarial API + production website checks and 50/100-request read bursts:
node scripts/verify-integration.mjs --security
node scripts/security-static.mjs
# With API and database running: exercises real auth, persistence, and ownership.
node scripts/smoke.mjs
# With API + database running, exercises the successful answer path using a
# deterministic database fixture (no external AI call):
node --env-file=apps/api/.env scripts/phase2-success-smoke.mjs
# With API + database running, validates upload, private download, missing-key
# handling, retry, and cross-user isolation:
node scripts/phase3-smoke.mjs
# Start the API with the same temporary webhook secret, then run the deterministic
# reconciliation and webhook smoke test (no Gemini or Razorpay API call):
$env:RAZORPAY_WEBHOOK_SECRET='phase4-local-webhook-secret-at-least-32-characters'
node scripts/phase4-smoke.mjs
On Windows, stop the API before pnpm build or pnpm db:generate: its running process locks Prisma's engine DLL. Ordinary pnpm typecheck does not regenerate that DLL and can run while developing.
The smoke test creates two uniquely named test users and matters in the configured database and leaves those records for inspection. Only run it against a development/test database. It does not print passwords or tokens.
apps/web: Next.js App Router, TypeScript, Tailwind CSS. Server actions forward requests to Nest; the browser never receives the JWT in JavaScript. The JWT lives in a one-day HTTP-only, SameSite cookie (Secure in production). Protected server layouts validate it through /users/me, and every API operation independently checks the active account and session version. Logout revokes all sessions; staff password resets and account deactivation revoke old tokens too. State-changing website requests validate Origin against the configured APP_ORIGIN.apps/api: NestJS owns all business logic. Validation rejects unknown fields; auth endpoints are throttled; passwords use bcrypt with cost 12 and a 72-byte limit. Deploy behind HTTPS; throttling is in-memory for this single-instance foundation.apps/api/prisma: PostgreSQL schema and committed migrations. References use a database sequence, e.g. MAT-2026-000001, avoiding concurrent count-based collisions. The sequence is global, does not reset annually, and may have gaps after rollbacks.currentStatementId identifies the active version. Each analysis points to the exact statement and AI run that produced it, so an older response cannot replace a newer intake.ai_runs with provider, configured model, prompt version, statement reference, raw output when available, token usage, latency, status, and a sanitized error code. Matter work is claimed under PostgreSQL row locks, with five-minute leases for crash recovery. Each provider fallback chain has a two-minute client deadline; this leaves time for private file reads and commits before an attempt can be reclaimed.audit_logs records. No statement text, answer text, API key, or password is copied into audit logs.PrivateStorage abstraction. Local files use opaque server-generated keys outside static hosting. The API validates the declared MIME type, file signature, and size before storage, records a SHA-256 checksum, and never exposes the storage key.API_URL is server-only. No secrets use a NEXT_PUBLIC_ prefix. Only .env.example files are committed. The local servers bind to loopback by default. Production deployment templates are in deploy/vps; see the deployment guide for persistent storage, backups, HTTPS and hosting configuration. Rate limiting remains per API process.
Useful routes include POST /advocate/matters/:id/approve, GET /matters/:id/final-document, POST /matters/:id/final-document/retry, and GET /matters/:id/final-document/file.
For schema changes use pnpm --filter @lawmedy/api db:migrate:dev --name descriptive_name. Apply committed migrations using pnpm db:migrate.
Framework references: Next.js App Router, NestJS authentication, Prisma 6 migration history, and Razorpay Standard Checkout.
EVIDENCE_EXTRACTION row in ai_runs; parsed results and confidence are stored in EvidenceExtraction. The prompt forbids guessing and requires visible source text for each extracted value. Upload, success, and failure transitions are recorded in audit_logs.CaseFact rows with their source references.READY_FOR_PAYMENT. Statement, answer, and evidence mutations are then locked so the confirmed record cannot silently change.Payment and Matter to PAID. Signature-verified checkout callbacks also fetch Razorpay’s payment status and confirm capture, amount, currency and order before settlement.AiRun; generated paragraphs keep their supporting CaseFact ids, and a failed QA pass never enters advocate review.UNDER_ADVOCATE_REVIEW. Advocate edits create immutable DocumentVersion rows with ADVOCATE provenance. Information requests, user responses, approvals, notifications, assignment transitions, and advocate access are audited./advocate/* is protected in both Next.js and Nest by the authenticated user's database role. Approval requires an explicit confirmation and records reviewedById plus reviewedAt on the legal document.FinalDocument; the private storage key is never exposed.