3.5 KiB
3.5 KiB
5. API Specification & Server Architecture
The application will not expose a public REST или GraphQL API. All communication between the frontend and backend will occur internally via Nuxt 4 Server Routes. This approach is secure, performant, and perfectly suited for a monolithic fullstack application.
Server Directory Structure (server/)
The server-side logic will be organized as follows:
server/
├── api/
│ ├── cells/
│ │ ├── index.post.ts # Create a new Cell
│ │ └── [id]/
│ │ ├── index.get.ts # Get Cell details
│ │ └── join.post.ts # Join a Cell (as consumer/executor)
│ ├── citizens/
│ │ ├── index.post.ts # Create a new Citizen (onboarding)
│ │ └── invite.get.ts # Generate an invitation link
│ └── vault/
│ ├── index.post.ts # Create a Vault account
│ ├── login.post.ts # Login via Vault
│ └── recover.post.ts # Initiate/approve social recovery
├── middleware/
│ └── auth.ts # Middleware to check Citizen authentication
└── utils/
├── prisma.ts # Exports a singleton Prisma Client instance
└── crypto.ts # Cryptographic helper functions
Core API Endpoints (MVP)
| Endpoint | Method | Description | Request Body | Response |
|---|---|---|---|---|
/api/citizens |
POST |
Creates the first Citizen or a new one via invite. | { name, publicKey } |
Citizen |
/api/citizens/invite |
GET |
Generates a single-use invitation link. | (none) | { inviteUrl } |
/api/cells |
POST |
Creates a new "Cell". | { commonGood, executors } |
LedgerEntry |
/api/cells/[id] |
GET |
Retrieves the full state of a "Cell". | (none) | CellState |
/api/cells/[id]/join |
POST |
Joins a "Cell" as Executor or Consumer. | { role, item? } |
LedgerEntry |
/api/cells/[id]/confirm |
POST |
Confirms payment from a Consumer. | { consumerKey } |
LedgerEntry |
Core Workflow: The Cryptographic Signing Process
This sequence diagram illustrates the fundamental process for every action in the system.
sequenceDiagram
participant Browser as Citizen's Browser
participant NuxtServer as Nuxt Server / API
participant Prisma
participant Ledger as The Main Ledger (DB)
Browser->>Browser: 1. User performs action (e.g., clicks "Create Cell")
Browser->>Browser: 2. Prepare `payload` (e.g., { commonGood: "Суп" })
Browser->>Browser: 3. Get `previousHash` from last Ledger entry
Browser->>Browser: 4. Create `entryHash` from payload + previousHash
Browser->>Browser: 5. Sign `entryHash` with private key to get `signature`
Browser->>NuxtServer: 6. POST /api/cells (sends payload, publicKey, signature)
NuxtServer->>NuxtServer: 7. Receive request
NuxtServer->>NuxtServer: 8. Validate signature using sender's `publicKey`
alt Signature is Invalid
NuxtServer-->>Browser: 9a. Return 401 Unauthorized
else Signature is Valid
NuxtServer->>Prisma: 9b. Get latest `previousHash` from DB
NuxtServer->>NuxtServer: 10. Verify client's `previousHash` matches server's
NuxtServer->>Prisma: 11. `prisma.ledgerEntry.create(...)`
Prisma->>Ledger: 12. INSERT INTO "LedgerEntry"
Ledger-->>Prisma: 13. Return new entry
Prisma-->>NuxtServer: 14. Return new entry
NuxtServer-->>Browser: 15. Return new LedgerEntry (success)
end