# Route Spec

## Route ID
`hubs-create`

## Endpoint
`POST /api/v1/hubs`

## Human Description
Creates a hub with required name and hub image. Description and custom link are optional. Creator becomes backend `super_admin`, displayed in the app as manager.

## Authentication
- Required: `yes`

## Client Preconditions
- The mobile app must require local contacts access before exposing hub creation flows.
- Local contacts access is an OS/app permission only. The API does not receive or store the user's full contact book.
- When invite endpoints are defined, the backend should receive only phone numbers that the user explicitly selected for that action.

## Request
### Headers
- `Content-Type: application/json`

### Body
```json
{
  "name": "Cairo Startups",
  "description": "Founders and builders",
  "profileAssetId": "ast_1",
  "initialInvitees": [
    {"phoneCountryCode": "+972", "phoneNumber": "501234567"}
  ],
  "customLink": "cairo-startups"
}
```

### Validation Rules
- `name`: required, 3-60 chars.
- `profileAssetId`: required completed hub image asset owned by creator, purpose `hub_photo`.
- `initialInvitees`: optional, 1-50 selected phone numbers. These are admin invitations because the creator is the hub manager.
- `description`: optional, max 1000 chars.
- `customLink`: optional, unique slug 3-40 chars.

## Responses
### Success: `201 Created`
```json
{"success": true, "message": "Hub created", "data": {"hubId": "hub_1", "role": "super_admin", "initialInvitations": []}}
```

### Error: `401 Unauthorized`
When returned:
- Missing or invalid access token.

Body:
```json
{"success": false, "error": {"code": "UNAUTHORIZED", "message": "Authentication required.", "details": {}}}
```

### Error: `409 Conflict`
When returned:
- Hub custom link already exists.

Body:
```json
{"success": false, "error": {"code": "HUB_LINK_TAKEN", "message": "Hub link is already taken.", "details": {}}}
```

### Error: `422 Unprocessable Entity`
When returned:
- Invalid hub payload.

Body:
```json
{"success": false, "error": {"code": "VALIDATION_FAILED", "message": "Please fix highlighted fields.", "details": {}}}
```

## Data & Caching Dependencies
- **Spanner Tables:** `hubs, hub_memberships (Write), hub_member_counters (Update), hub_invitations (Write when initialInvitees supplied), notifications (Write when initialInvitees match existing users)`
- **Redis Cache:** `None`
- **GCS Storage:** `None`
- **Edge Cache (CDN):** `No`

## Side Effects
- Creates new hub entity and default settings.
- Assigns creator as backend `super_admin` and first member. The app displays this role as manager.
- Creates initial admin invitations and `hub_invite_received` notifications for matching existing users when `initialInvitees` is supplied. These invitees become active members when they accept.
- Reserves custom link slug when provided.
