logicspike/docs

Guides

LogicSpike Engineering Standards & Rules of Discipline

This document outlines the non-negotiable rules for developing on the LogicSpike platform. Violating these rules corrupts the architecture.


🏗️ 1. Architecture Rules

🚫 Rule 1.1: The Gateway Mandate

  • Rule: NEVER expose a Microservice directly to the public internet.
  • Why: The Gateway is our shield. It handles Rate Limiting, Authentication, and SSL.
  • Flow: Client -> Gateway -> Private Service (Manager/Blog/etc).
  • Enforcement: Services should bind to private ports/IPs only, or verify a shared secret from the Gateway.

🛡️ Rule 1.3: The Gateway Key (Production Grade)

  • Rule: All internal services MUST verify the x-gateway-key header.
  • Implementation:
    1. NEVER Hardcode: Use process.env.GATEWAY_SECRET.
    2. Rotation Support: Services should accept a comma-separated list of secrets (Current + Previous) to allow rotation without downtime.
    3. Length: Minimum 32 characters, high entropy.
  • Behavior: If the key is missing or invalid, return 403 Forbidden.

🔄 Rule 1.4: Service Isolation

  • Rule: Service A CANNOT import code or database models from Service B.
  • Why: Coupling kills microservices. If the Blog service changes its DB schema, it shouldn't break the Billing service.
  • Communication: Use HTTP APIs (REST) or Events (Queue) to talk between services.

💾 2. Database Rules

🏢 Rule 2.1: The Tenant Barrier

  • Rule: Every query touching "Floor Level" data MUST include WHERE tenant_id = ?.
  • Why: Omitting this is a P0 Security Vulnerability (Data Leak).
  • Exception: "Building Level" tables (users, tenants) do not have tenant IDs.

⛓️ Rule 2.2: No Cross-Service Joins

  • Rule: You cannot write a SQL JOIN between the users table (Manager) and the posts table (Blog Service).
  • Why: They might live in different databases physically (or in the future).
  • Solution: Fetch the User ID, then fetch the Posts. Stitch them in code.

🔐 3. Security Rules

🔑 Rule 3.1: Secrets Management

  • Rule: NEVER commit .env files or API keys to Git.
  • Why: If a key leaks, we are compromised.
  • Enforcement: Use .gitignore and environment variables.

🛡️ Rule 3.2: Authentication Context

  • Rule: NEVER trust the User ID sent in the request body.
  • Why: A malicious user can send { "user_id": "admin_id" }.
  • Solution: ALWAYS derive identity from the validated JWT token in the Authorization header.

💻 4. Coding Discipline

🧩 Rule 4.1: Strong Typing

  • Rule: Avoid any in TypeScript.
  • Why: It defeats the purpose of using TypeScript. Define interfaces for everything.

📢 Rule 4.2: Standard Response Envelope

  • Rule: All APIs must return a standard structure.
  • Format:
{
  "data": { ... },     // The payload
  "error": null,       // Or error object
  "meta": { ... }      // Pagination, timestamps
}

🚨 Rule 4.3: Error Handling Standard

  • Rule: Throw structured errors, don't just return 500.
  • Codes:
    • 400 Bad Request: Validation failure (zod).
    • 401 Unauthorized: No token / Invalid token.
    • 403 Forbidden: Valid token, but wrong permissions (role check).
    • 404 Not Found: ID doesn't exist or belongs to another tenant.
    • 429 Too Many Requests: Rate limit hit.
  • Format:
{
  "data": null,
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "The member 'ben' was not found in this workspace.",
    "doc_url": "..."
  }
}

🧪 5. Testing & Quality

� Rule 5.1: The "Critical Path" Test

  • Rule: Every core feature (Login, Invite, Checkout) MUST have an Integration Test.
  • Why: Unit tests pass, but systems fail. We need to know if the flow works.

🧹 Rule 5.2: Clean Commits

  • Rule: Follow Conventional Commits (feat:, fix:, chore:).
  • Why: Auto-generates changelogs and makes history readable.

🎨 6. Frontend Standards (Next.js)

⚛️ Rule 6.1: Server vs Client

  • Rule: Default to Server Components. Use Client Components ("use client") only for interactivity (onClick, useState).
  • Why: Performance and SEO.

🚫 Rule 6.2: No Direct DB Access

  • Rule: UI Components NEVER import prisma or drizzle directly.
  • Solution: Call a Server Action or an API Route.

🐌 Rule 6.3: Lazy Loading Strategy

  • Rule: Heavy UI components (Editors, Charts, Maps) MUST be lazy loaded using next/dynamic.
  • Why: Reduces the initial JavaScript bundle size, making the page load faster (LCP/TBT).
  • Pattern:
import dynamic from 'next/dynamic'
 
// ❌ Bad
import { HeavyChart } from './HeavyChart'
 
// ✅ Good
const HeavyChart = dynamic(() => import('./HeavyChart'), {
  loading: () => <p>Loading Chart...</p>,
  ssr: false // Only if it doesn't need SEO
  ssr: false // Only if it doesn't need SEO
})

📡 Rule 6.4: API Client Layer

  • Rule: Components NEVER call fetch() directly.
  • Why: Centralizes auth headers, error handling, and type definitions.
  • Pattern:
    1. Create src/modules/{feature}/api.ts.
    2. Export typed async functions fetchPosts(), createPost().
    3. Call these functions from UI components or Actions.

🎣 Rule 6.5: Data Fetching Hooks

  • Rule: Use a Hook for data fetching, don't just useEffect -> fetch.
  • Why: Handles isLoading, isError, and data states consistently.
  • Recommendation: Adopt TanStack Query (React Query) or SWR for caching and deduplication as we scale. Code is currently using primitive useEffect or direct calls, which causes waterfalls.

📦 7. Monorepo Architecture (Turbo)

🧱 Rule 7.1: The "App as Consumer" Pattern

  • Rule: Apps (apps/*) should contain minimal logic.
  • Why: Business logic trapped in a Next.js app is hard to reuse (e.g., in a Worker or CLI).
  • Pattern:
    • packages/core-business: Domain logic (User creation, Billing calc).
    • packages/db: Database schema and connection.
    • apps/manager: Imports core-business to verify a user.
    • apps/worker: Imports core-business to process a background job.

🚧 Rule 7.2: No Cross-App Imports

  • Rule: apps/seller-dashboard MUST NOT import from apps/manager.
  • Why: Apps are capable of being deployed independently. Importing creates a hidden monolith.
  • Solution: Move shared code to a packages/* library.

📌 Rule 7.3: Explicit Dependencies

  • Rule: All internal packages must be listed in package.json with workspace:*.
  • Why: Turbo relies on this graph to build correctly.

📜 Summary

  1. Gateway First.
  2. Gateway First.
  3. Tenant ID Always.
  4. No Cross-Imports.
  5. Trust the Token, not the Body.
  6. Standard Errors & Types.
Guides