Skip to content
21 changes: 21 additions & 0 deletions .ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Used by AI AGENTS to skip analyzing these files
.history
.tmp
_.bak
node_modules/
/coverage/
/dist/
/env/
_.DS*Store
.vscode/values-schema.yaml
*.env
/.secrets
chart/apl/values.schema.json
chart/apl/README.md
workflow/
\_.new
.envrc
otomi.cpuprofile
/.idea/
tmp
\*\*values-repo.yaml
26 changes: 26 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## OVERVIEW

App Platform API — Express/TypeScript REST API managing Kubernetes teams, workloads, and services. Uses **Git as database** (YAML files in a values repo).

## CONVENTIONS

- **OpenAPI-first**: Never add routes manually. Define in YAML spec, implement handler matching `operationId`
- **Handler signature (all versions)**: `export const opId = (req: OpenApiRequestExt, res: Response): void` — send via `res.json()`
- **Path params use curly braces in filesystem**: `src/api/v1/teams/{teamId}/services.ts` — Express resolves `:teamId`

## Deprecations

- /v1 is deprecated, new endpoints implemented in /v2
- src/ai not used

## KEY PATTERNS

- **Git-as-Database**: CRUD → OtomiStack → FileStore (memory) + Git (disk) → commit → deploy
- **Multi-tenant isolation**: Team resources scoped by `teamId` in paths and CASL abilities
- **OpenAPI validation**: express-openapi-validator validates all requests/responses against specs
- **FileStore path mapping**: FileMap defines glob patterns + templates per AplKind (e.g., `env/teams/{teamId}/services/{name}.yaml`)

## ANTI-PATTERNS

- **DO NOT** edit `src/generated-schema.ts` — auto-generated from `npm run build:models`
- **DO NOT** add routes without OpenAPI spec — express-openapi-validator rejects unspecified routes
27 changes: 27 additions & 0 deletions src/api/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# API Route Handlers

## OVERVIEW

Versioned REST endpoint handlers. Each file exports functions matching OpenAPI `operationId`s.

## STRUCTURE

```
api/
├── v1/ # Legacy handlers — (req, res) signature, call req.otomi.*
├── v2/ # Current handlers — (req, res) signature, call req.otomi.*Apl*
│ └── teams/{teamId}/ # Team-scoped with sub-resource dirs
├── alpha/ # Experimental (AI features, team extensions)
│ ├── ai/ # Deprecated
│ └── teams/ # Deprecated
└── apiDocs.ts # Swagger UI endpoint
```

## CONVENTIONS

- **v2 handlers**: `export const opId = (req: OpenApiRequestExt, res: Response): void` — call `req.otomi.*Apl*()`, send via `res.json()`

## ANTI-PATTERNS

- **DO NOT** put business logic in handlers — delegate to `req.otomi` (OtomiStack)
- **DO NOT** create handler files without corresponding OpenAPI spec entry
22 changes: 22 additions & 0 deletions src/openapi/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# OpenAPI Specifications

## OVERVIEW

YAML specs defining all API endpoints, schemas, ACLs, and documentation links. Single source of truth for the entire API surface.

## CONVENTIONS

- **`operationId`**: Must match exported function name in handler file
- **`x-eov-operation-handler`**: Path to handler file relative to `src/api/` (e.g., `v1/teams`)
- **`x-aclSchema`**: References schema name for CASL authorization
- **`x-acl`**: Maps roles to CRUD abilities (`create-any`, `read`, `update`, `delete-any`)
- **`x-formtype`**: UI hint for console form generation (`SelectWidget`, etc.)
- **`x-externalDocsPath`**: Appended to base docs URL for per-resource documentation
- **Schema files** define the resource type at top level (e.g., `Service:` in `service.yaml`)

## ANTI-PATTERNS

- **DO NOT** add paths without `operationId` and `x-eov-operation-handler`
- **DO NOT** define schemas inline in `api.yaml` — create separate `{resource}.yaml`
- **DO NOT** forget `x-aclSchema` — endpoints without it bypass authorization
- After changes: run `npm run build:models` to regenerate `generated-schema.ts`
Loading