# Apps

An app is the unit that app users belong to. It has a public `app_key` and a
private `app_secret`.

## App fields

| field | type | notes |
|---|---|---|
| `id` | integer | numeric id used in management paths |
| `app_key` | string | public identifier, `app_...` |
| `owner_client_id` | integer | the owning client |
| `parent_app_id` | integer or null | set for a sub-app |
| `name` | string | up to 80 characters |
| `description` | string | up to 500 characters |
| `redirect_uris` | list of strings | allowed OAuth redirects |
| `allow_master_login` | boolean | per-app sign-in policy flag |
| `status` | `active` or `disabled` | disabled apps cannot issue tokens |
| `created_at` | unix seconds | |
| `updated_at` | unix seconds | |

## Create an app

```bash
curl -sS -X POST "$MANAGE/apps" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "acme-app",
    "description": "The Acme dashboard",
    "redirect_uris": ["https://acme.example/cb"],
    "allow_master_login": false
  }'
```

Response:

```json
{
  "id": 1,
  "app_key": "app_1a2b3c4d5e6f7a8b",
  "owner_client_id": 1,
  "parent_app_id": null,
  "name": "acme-app",
  "description": "The Acme dashboard",
  "redirect_uris": ["https://acme.example/cb"],
  "allow_master_login": false,
  "status": "active",
  "app_secret": "gsk_...",
  "warning": "Store app_secret now; it is not recoverable."
}
```

Store `app_secret`. It is shown once.

## Create a sub-app

```bash
curl -sS -X POST "$MANAGE/apps" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d '{"name":"acme-app-mobile","parent_app_id":1}'
```

A sub-app shares its parent's user pool. Sub-apps cannot have sub-apps.

## Update an app

```bash
curl -sS -X PATCH "$MANAGE/apps/1" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d '{"name":"acme-app","description":"Updated","status":"active"}'
```

`redirect_uris` may be a list or a newline-separated string.

## Disable or enable

```bash
curl -sS -X PATCH "$MANAGE/apps/1" -H "$AUTH" \
  -H "Content-Type: application/json" -d '{"status":"disabled"}'
```

A disabled app cannot issue tokens and its app users cannot sign in.

## Rotate the app secret

```bash
curl -sS -X POST "$MANAGE/apps/1/rotate-secret" -H "$AUTH"
```

This revokes every existing app secret and issues one new one. The response
contains the new `app_secret` once.

## Delete an app

```bash
curl -sS -X DELETE "$MANAGE/apps/1" -H "$AUTH"
```

Deleting an app deletes its app users and their keys.

## Redirect URIs

A redirect URI must match exactly, including scheme, host, port and path. The
authorization endpoint rejects anything that is not registered.

## Listing

```bash
curl -sS "$MANAGE/apps" -H "$AUTH"
curl -sS "$MANAGE/apps?q=acme&page=1&per=50" -H "$AUTH"
```

The response includes `total`, `page`, `per` and an `apps` array. Each app
carries `users` and `subapps` counts in the list view.
