Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/prompts/autonomy-version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "2025.11"
"version": "2025.11"
}
14 changes: 7 additions & 7 deletions .github/prompts/autonomy.manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"version": "2025.11",
"consent": {
"phrase": "",
"expiresMinutes": 0
},
"actions": []
}
"version": "2025.11",
"consent": {
"phrase": "",
"expiresMinutes": 0
},
"actions": []
}
5 changes: 3 additions & 2 deletions .kilo/kilo.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"snapshot": false
}
"$schema": "https://app.kilo.ai/config.json",
"snapshot": false
}
58 changes: 31 additions & 27 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ Run `pnpm exec prisma generate` again whenever Prisma schema changes.
When adding new endpoints, you must include an integration test that exercises the full request lifecycle against a database.

### Folder Structure and Naming

Integration tests belong in the `src/__tests__/integration/` directory (for cross-module tests) or adjacent to the controller they test (e.g., `src/modules/creators/creators.integration.test.ts`). They must be suffixed with `.test.ts` or `.integration.test.ts`.

### Seeding the Database

Use Prisma to seed test fixtures in a `beforeAll` block, and ensure you clean them up in an `afterAll` block to maintain a pristine test environment. Do not rely on external seed scripts for unit or integration tests.

### Minimal Worked Example
Expand All @@ -71,38 +73,40 @@ import app from '../../app';
import { prisma } from '../../utils/prisma.utils';

describe('GET /api/v1/example', () => {
beforeAll(async () => {
// 1. Seed database with test fixtures
await prisma.user.create({
data: {
id: 'test-user',
email: 'test@example.com',
passwordHash: 'hash',
firstName: 'Test',
lastName: 'User'
}
});
});

afterAll(async () => {
// 2. Clean up fixtures
await prisma.user.delete({ where: { id: 'test-user' } });
await prisma.$disconnect();
});

it('returns 200 and data for an existing record', async () => {
// 3. Execute the request
const res = await supertest(app).get('/api/v1/example/test-user');
// 4. Assert response
expect(res.status).toBe(200);
expect(res.body.success).toBe(true);
});
beforeAll(async () => {
// 1. Seed database with test fixtures
await prisma.user.create({
data: {
id: 'test-user',
email: 'test@example.com',
passwordHash: 'hash',
firstName: 'Test',
lastName: 'User',
},
});
});

afterAll(async () => {
// 2. Clean up fixtures
await prisma.user.delete({ where: { id: 'test-user' } });
await prisma.$disconnect();
});

it('returns 200 and data for an existing record', async () => {
// 3. Execute the request
const res = await supertest(app).get('/api/v1/example/test-user');

// 4. Assert response
expect(res.status).toBe(200);
expect(res.body.success).toBe(true);
});
});
```

### Running Integration Tests Locally

To run only the integration tests, you can use jest with a path or name filter:

```bash
pnpm test -- src/__tests__/integration
# or run a specific file
Expand Down
36 changes: 18 additions & 18 deletions docs/TEMPLATE_SCAFFOLDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ They are **not product logic**. They are development accelerators that should be

## Reusable template files

| File | Purpose | Adapt or keep as-is? |
|------|---------|----------------------|
| `src/template/render-starter-email.ts` | Generic HTML email wrapper for transactional emails | Adapt when Access Layer needs branded email layouts |
| `src/utils/mail.utils.ts` | Gmail-based email transport with starter templates | Keep structure, update templates as product flows are added |
| `src/config.ts` | Zod-validated environment config with common variables | Extend with new env vars as needed |
| `src/middlewares/error.middleware.ts` | Global error handler covering Zod, Prisma, JWT, and syntax errors | Keep as-is, extend for new error types |
| `src/middlewares/rate.middleware.ts` | Rate limiting with dev/prod defaults | Keep as-is, tune limits for production |
| `src/middlewares/cors.middleware.ts` | CORS setup using allowed origins from config | Keep as-is |
| `src/utils/prisma.utils.ts` | Prisma singleton with dev-friendly logging | Keep as-is |
| `src/utils/logger.utils.ts` | Pino logger and HTTP status constants | Keep as-is |
| `src/tspec.config.ts` | OpenAPI doc generation config | Keep, update title and description as API grows |
| `src/types/profile.types.ts` | Domain types and a `STARTER_ACCOUNT_SCHEMA` reference string | Adapt types as data model evolves; schema string is a reference, not a migration |
| File | Purpose | Adapt or keep as-is? |
| -------------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `src/template/render-starter-email.ts` | Generic HTML email wrapper for transactional emails | Adapt when Access Layer needs branded email layouts |
| `src/utils/mail.utils.ts` | Gmail-based email transport with starter templates | Keep structure, update templates as product flows are added |
| `src/config.ts` | Zod-validated environment config with common variables | Extend with new env vars as needed |
| `src/middlewares/error.middleware.ts` | Global error handler covering Zod, Prisma, JWT, and syntax errors | Keep as-is, extend for new error types |
| `src/middlewares/rate.middleware.ts` | Rate limiting with dev/prod defaults | Keep as-is, tune limits for production |
| `src/middlewares/cors.middleware.ts` | CORS setup using allowed origins from config | Keep as-is |
| `src/utils/prisma.utils.ts` | Prisma singleton with dev-friendly logging | Keep as-is |
| `src/utils/logger.utils.ts` | Pino logger and HTTP status constants | Keep as-is |
| `src/tspec.config.ts` | OpenAPI doc generation config | Keep, update title and description as API grows |
| `src/types/profile.types.ts` | Domain types and a `STARTER_ACCOUNT_SCHEMA` reference string | Adapt types as data model evolves; schema string is a reference, not a migration |

## Local-only and example files

| File | Purpose | Notes |
|------|---------|-------|
| `.env.example` | Safe placeholder environment variables | Copy to `.env` locally. Never commit a real `.env` file |
| `docker-compose.yml` | Local PostgreSQL container | Local development only. Not used in production or CI |
| `nodemon.json` | Auto-reload config for `pnpm dev` | Local development convenience |
| `.husky/` | Git hooks for lint-staged | Runs locally on commit, enforced by `prepare` script |
| File | Purpose | Notes |
| -------------------- | -------------------------------------- | ------------------------------------------------------- |
| `.env.example` | Safe placeholder environment variables | Copy to `.env` locally. Never commit a real `.env` file |
| `docker-compose.yml` | Local PostgreSQL container | Local development only. Not used in production or CI |
| `nodemon.json` | Auto-reload config for `pnpm dev` | Local development convenience |
| `.husky/` | Git hooks for lint-staged | Runs locally on commit, enforced by `prepare` script |

## Files that are not scaffolding

Expand Down
10 changes: 5 additions & 5 deletions docs/api-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ Manage trade webhooks for creator profiles.

- Trade webhooks reference (payload shape, retry behavior, delivery guarantees): [`docs/webhooks.md`](./webhooks.md).

| Method | Path | Description |
| :------- | :---------------------------------- | :---------------------------------------------------- |
| `POST` | `/creators/:id/webhooks` | Register a new webhook for trade events. |
| `GET` | `/creators/:id/webhooks` | List all registered webhooks for the creator. |
| `DELETE` | `/creators/:id/webhooks/:webhookId` | Delete a registered webhook. |
| Method | Path | Description |
| :------- | :---------------------------------- | :-------------------------------------------- |
| `POST` | `/creators/:id/webhooks` | Register a new webhook for trade events. |
| `GET` | `/creators/:id/webhooks` | List all registered webhooks for the creator. |
| `DELETE` | `/creators/:id/webhooks/:webhookId` | Delete a registered webhook. |

## Activity Module

Expand Down
18 changes: 11 additions & 7 deletions docs/api-timeouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ All values are in milliseconds unless noted.

## Defaults

| Config key | Default | Source | Description |
|---|---|---|---|
| `RPC_TIMEOUT_MS` (code constant) | `5000` | `src/utils/rpc-timeout.utils.ts` | Max wait for outbound RPC calls. Per-call override via `withRpcTimeout` third arg. |
| `BACKGROUND_JOB_LOCK_TTL_MS` | `300000` | `src/config.ts`, `.env` | How long a background job holds its distributed lock before it is considered stale. |
| `SHUTDOWN_TIMEOUT_MS` (code constant) | `30000` | `src/server.ts` | Hard deadline for graceful shutdown before `process.exit(1)` is forced. |
| `DRAIN_WINDOW_MS` (code constant) | `5000` | `src/server.ts` | Extra drain period after the HTTP server closes to finish in-flight requests. |
| Config key | Default | Source | Description |
| ------------------------------------- | -------- | -------------------------------- | ----------------------------------------------------------------------------------- |
| `RPC_TIMEOUT_MS` (code constant) | `5000` | `src/utils/rpc-timeout.utils.ts` | Max wait for outbound RPC calls. Per-call override via `withRpcTimeout` third arg. |
| `BACKGROUND_JOB_LOCK_TTL_MS` | `300000` | `src/config.ts`, `.env` | How long a background job holds its distributed lock before it is considered stale. |
| `SHUTDOWN_TIMEOUT_MS` (code constant) | `30000` | `src/server.ts` | Hard deadline for graceful shutdown before `process.exit(1)` is forced. |
| `DRAIN_WINDOW_MS` (code constant) | `5000` | `src/server.ts` | Extra drain period after the HTTP server closes to finish in-flight requests. |

## Override examples

Expand Down Expand Up @@ -40,7 +40,11 @@ import { withRpcTimeout } from '../utils/rpc-timeout.utils';
const data = await withRpcTimeout('fetchUser', () => api.getUser(id));

// explicit override for a known-slow operation
const report = await withRpcTimeout('generateReport', () => api.report(), 15_000);
const report = await withRpcTimeout(
'generateReport',
() => api.report(),
15_000
);
```

To change the process-wide defaults, edit the constants directly in their source files and redeploy.
42 changes: 21 additions & 21 deletions docs/api/creator-list-query-precedence.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ which value takes effect.

## Parameter reference

| Parameter | Type | Default | Notes |
| :--------- | :---------------- | :----------- | :------------------------------------------------------- |
| `limit` | integer (1–100) | `20` | Number of results per page |
| `offset` | integer (≥ 0) | `0` | Number of results to skip |
| `sort` | enum | `createdAt` | Field used to order results |
| `order` | `asc` \| `desc` | `desc` | Direction applied to the `sort` field |
| `verified` | boolean | _(absent)_ | Filter by creator verification status |
| `search` | string | _(absent)_ | Full-text filter applied to display name and handle |
| `include` | comma-separated | _(absent)_ | Extra data to embed in each result (e.g. `stats`) |
| Parameter | Type | Default | Notes |
| :--------- | :-------------- | :---------- | :-------------------------------------------------- |
| `limit` | integer (1–100) | `20` | Number of results per page |
| `offset` | integer (≥ 0) | `0` | Number of results to skip |
| `sort` | enum | `createdAt` | Field used to order results |
| `order` | `asc` \| `desc` | `desc` | Direction applied to the `sort` field |
| `verified` | boolean | _(absent)_ | Filter by creator verification status |
| `search` | string | _(absent)_ | Full-text filter applied to display name and handle |
| `include` | comma-separated | _(absent)_ | Extra data to embed in each result (e.g. `stats`) |

## Precedence rules

Expand Down Expand Up @@ -85,18 +85,18 @@ This is consistent with how Express parses repeated scalar query params.

## Behaviour summary table

| Supplied params | Effective behaviour |
| :------------------------------------- | :------------------------------------------------ |
| _(no params)_ | `createdAt desc`, page 1 (limit 20, offset 0) |
| `sort=displayName` | `displayName desc` |
| `order=asc` | `createdAt asc` |
| `sort=displayName&order=asc` | `displayName asc` |
| `verified=true` | verified creators only, `createdAt desc` |
| `search=jazz` | creators matching "jazz", `createdAt desc` |
| `verified=true&search=jazz` | verified creators matching "jazz", `createdAt desc` |
| `verified=true&sort=displayName` | verified creators sorted `displayName desc` |
| `limit=10&offset=20` | page 3 at 10-per-page |
| `unknownParam=x` | `400 Bad Request` |
| Supplied params | Effective behaviour |
| :------------------------------- | :-------------------------------------------------- |
| _(no params)_ | `createdAt desc`, page 1 (limit 20, offset 0) |
| `sort=displayName` | `displayName desc` |
| `order=asc` | `createdAt asc` |
| `sort=displayName&order=asc` | `displayName asc` |
| `verified=true` | verified creators only, `createdAt desc` |
| `search=jazz` | creators matching "jazz", `createdAt desc` |
| `verified=true&search=jazz` | verified creators matching "jazz", `createdAt desc` |
| `verified=true&sort=displayName` | verified creators sorted `displayName desc` |
| `limit=10&offset=20` | page 3 at 10-per-page |
| `unknownParam=x` | `400 Bad Request` |

## Related files

Expand Down
Loading
Loading