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
34 changes: 34 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project

**phoenixvc-dev-api** — Development API for the phoenixvc organization. Built with FastAPI.

## Status: Integration Review Pending

Needs analysis of where this fits between the templating repos (azure-project-template, azure-infrastructure), other APIs (ai-gateway, codeflow-engine), and how it serves the phoenixvc ecosystem (cognitive-mesh, PhoenixRooivalk, Mystira, etc.).

## Tech Stack

- **Backend**: Python, FastAPI
- **Org**: phoenixvc
- **Environment**: dev

## Key Commands

```bash
pip install -r requirements.txt # Install dependencies
uvicorn main:app --reload # Start dev server
pytest # Run tests
mypy . # Type check
```

## AgentKit Forge

This project has not yet been onboarded to [AgentKit Forge](https://github.com/phoenixvc/agentkit-forge). To request onboarding, [create a ticket](https://github.com/phoenixvc/agentkit-forge/issues/new?title=Onboard+phoenixvc-dev-api-fastapi&labels=onboarding).

## Baton Integration

Baton is the shared task graph for cross-repo work. When the `baton` MCP server is available, agents should check for existing work with `task_check` at the start of meaningful tasks, create or claim visible work with `task_notify`/`log_agent_message`, update the task when significant new information becomes available, and log completion or blockers before handing off.
6 changes: 4 additions & 2 deletions src/api-hexagonal/domain/entities/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
from datetime import datetime
from typing import Optional


@dataclass
class User:
"""User domain entity"""

id: Optional[int]
email: str
name: str
password_hash: str
created_at: datetime
updated_at: datetime

def is_valid_email(self) -> bool:
return '@' in self.email and '.' in self.email.split('@')[1]
return "@" in self.email and "." in self.email.split("@")[1]
5 changes: 4 additions & 1 deletion src/api-hexagonal/domain/repositories/user_repository.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from abc import ABC, abstractmethod
from abc import ABC
from typing import Optional

from domain.entities.user import User


class UserRepository(ABC):
async def create(self, user: User) -> User:
pass

async def get_by_id(self, user_id: int) -> Optional[User]:
pass
11 changes: 7 additions & 4 deletions src/api-standard/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from fastapi import FastAPI

app = FastAPI()

@app.get('/')

@app.get("/")
async def root():
return {'message': 'API Standard'}
return {"message": "API Standard"}


@app.get('/health')
@app.get("/health")
async def health():
return {'status': 'healthy'}
return {"status": "healthy"}
46 changes: 46 additions & 0 deletions tests/unit/test_user_entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from datetime import datetime
from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path


def load_user_class():
user_path = (
Path(__file__).parents[2]
/ "src"
/ "api-hexagonal"
/ "domain"
/ "entities"
/ "user.py"
)
spec = spec_from_file_location("user_entity", user_path)
module = module_from_spec(spec)
spec.loader.exec_module(module)
return module.User


def test_user_validates_email_shape():
User = load_user_class()
user = User(
id=1,
email="user@example.com",
name="Test User",
password_hash="hashed",
created_at=datetime(2026, 1, 1),
updated_at=datetime(2026, 1, 1),
)

assert user.is_valid_email()


def test_user_rejects_email_without_domain_dot():
User = load_user_class()
user = User(
id=1,
email="user@example",
name="Test User",
password_hash="hashed",
created_at=datetime(2026, 1, 1),
updated_at=datetime(2026, 1, 1),
)

assert not user.is_valid_email()
Loading