# @sylphx/management

[![npm version](https://img.shields.io/npm/v/@sylphx/management.svg)](https://www.npmjs.com/package/@sylphx/management)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)

Pure-FP Promise client for the [Sylphx Platform](https://sylphx.com)
Management API — **contract-first capability namespaces, zero classes**.

The SDK is a thin, stateless transport over `api.sylphx.com/v1`. No classes,
no mutable state, no business logic — consumers create an immutable `Client`
and pass it to free functions grouped by capability namespace. Every
request / response type is imported from
[`@sylphx/contract`](https://www.npmjs.com/package/@sylphx/contract) — the
Effect Schema single source of truth (ADR-084).

> **Scope: Management plane only** (ADR-083). This SDK covers platform-owner
> operations (project / deployment / environment / secret / domain / audit
> / billing / SAML / OIDC / webhooks / privacy / analytics admin, …) on
> `api.sylphx.com/v1` with Bearer tokens (`svc_...` service tokens or
> OAuth access JWTs). For app-runtime data-plane operations (auth, KV, transactional
> email, push, realtime, `flags.evaluate`, search, analytics.track, AI,
> storage uploads, end-user session replay) use
> [`@sylphx/sdk`](https://www.npmjs.com/package/@sylphx/sdk) — one package,
> Firebase-pattern with `./`, `./react`, `./server`, `./nextjs`,
> `./web-analytics`, `./health` peer-dep-gated entry points. Mixing planes
> (wrong hostname + wrong auth scheme) returns `401 plane_mismatch`.

## Requirements

- Node.js `>= 20` (uses built-in `fetch`) — or Bun `>= 1.3`
- A Sylphx API token:
  - **OAuth access token** (`eyJ...`) — minted by the OAuth/device flow and suitable for user-scoped automation
  - **Service token** (`svc_...`) — for CI / server-side automation, created through the Management API / CLI token flow

## Installation

```bash
bun add @sylphx/management
# or
npm install @sylphx/management
# or
pnpm add @sylphx/management
```

## Quick Start

```typescript
import { createClient, projects, deployments, envVars } from '@sylphx/management'

const client = createClient({
  token: process.env.SYLPHX_TOKEN!,
  // baseUrl defaults to 'https://api.sylphx.com'
})

// List projects (ids are TypeIDs — `proj_xxx`)
const list = await projects.list(client)

// Trigger a deployment
await deployments.trigger(client, 'proj_abc', 'production')

// List env vars for a project + environment
const vars = await envVars.list(client, 'proj_abc', 'production')
```

### Tree-shakable subpath imports

Bundlers that support subpath exports can import a single capability
namespace for better tree-shaking:

```typescript
import { createClient } from '@sylphx/management'
import * as projects from '@sylphx/management/projects'

const client = createClient({ token: process.env.SYLPHX_TOKEN! })
await projects.list(client)
```

### Project preview capacity

Project updates are contract-first through `projects.update`. The
`previewMaxActive` field is the project-level active PR preview override:

```typescript
import { createClient, projects } from '@sylphx/management'

const client = createClient({ token: process.env.SYLPHX_TOKEN! })

await projects.update(client, 'proj_abc', { previewMaxActive: 10 })
await projects.update(client, 'proj_abc', { previewMaxActive: null }) // follow org plan
```

The field is intentionally scoped to the project, not an environment variable
or service setting. It tunes preview admission for a project while the platform
continues to own runner scheduling, queueing, and placement internals.

## Capabilities

Every module exports free functions that take `client` as the first
argument. The root entry point exports 70 capability namespaces; key ones:

| Namespace            | Representative functions                                                                   |
| -------------------- | ------------------------------------------------------------------------------------------ |
| `users`              | `whoami`                                                                                   |
| `auth`, `authSettings` | `getOAuthProviders`, `updateOAuthProviders`, `getAuthSettings`, `updateAuthSettings`, `getAuthStats` |
| `projects`           | `list`, `create`, `delete`                                                                 |
| `deployments`        | `status`, `trigger`, `history`, `rollback`                                                 |
| `environments`       | `list`, `resolveId`, `logs`, `create`, `update`, `delete`, `promote`                       |
| `envVars`            | `list`, `set`, `setMany`, `delete`                                                         |
| `domains`            | `list`, `create`, `addHostname`, `removeHostname`, `checkHostname`, `enableEmail`, `checkEmail`, `disableEmail` |
| `databases`          | `list`, `create`, `get`, `delete`, `branch`                                                |
| `services`           | `list`, `get`, `deploy`, `delete`                                                          |
| `volumes`            | `list`, `create`, `delete`                                                                 |
| `storage`            | `list`, `create`, `delete`                                                                 |
| `secrets`            | `list`, `get`, `create`, `update`, `rollback`, `delete`                                    |
| `remoteConfig`       | `list`, `get`, `set`, `delete`                                                             |
| `tasks`              | `list`, `create`, `get`, `update`, `delete`                                                |
| `resourceBindings`   | `list`, `create`, `delete`                                                                 |
| `organizations`      | `current`, `listMembers`, `inviteMember`, `removeMember`                                   |
| `sandboxes`          | `create`, `list`, `get`, `terminate`                                                       |
| `logs`               | `stream` (returns `{ url, token }` for SSE)                                                |
| `email`              | `listLogs`, `getSettings`, `updateSettings` (admin only — `send` lives in `@sylphx/sdk`)   |
| `notifications`      | `listInbox` (admin only — `send` lives in `@sylphx/sdk`)                                   |
| `billing`            | account / plan / invoice endpoints                                                         |
| `saml`, `oidc`       | SSO configuration admin                                                                    |
| `webhooks`           | outbound webhook endpoint CRUD                                                             |
| `analytics`          | admin queries (runtime `analytics.track` lives in `@sylphx/sdk`)                           |
| `flags`              | flag admin CRUD (runtime `flags.evaluate` lives in `@sylphx/sdk`)                          |
| `experiments`        | A/B test admin CRUD                                                                        |
| `ai`                 | model / completion admin                                                                   |
| `backups`            | managed-data backup + restore                                                              |
| `certs`              | TLS cert inspection                                                                        |
| `consent`, `privacy` | GDPR / CCPA admin                                                                          |
| `engagement`, `newsletter`, `referrals` | marketing admin                                                         |
| `runners`            | self-hosted runner admin                                                                   |
| `sessionReplay`      | session-replay admin (runtime capture lives in `@sylphx/sdk/web-analytics`)                |
| `monitoring`         | metric / alert admin                                                                       |
| `realtime`           | channel admin (runtime pub/sub lives in `@sylphx/sdk`)                                     |
| `search`             | index admin (runtime queries live in `@sylphx/sdk`)                                        |
| `serviceTokens`      | service-token issuance + revocation                                                        |

Full, IDE-autocompleted surface is available on the re-exported
namespaces from the root `@sylphx/management` entry point.

Serverless function lifecycle is intentionally absent from the Management SDK
until the Management API owns `/projects/:projectId/functions/*`. Runtime
function execution remains on `@sylphx/sdk`.

> **Plane discipline (ADR-083).** Runtime BaaS verbs — `kv.*`, `email.send`,
> `notifications.send`, MFA `challenge.*`, `flags.evaluate`,
> `analytics.track` — are **not** part of `@sylphx/management`. Deployed
> applications (both server-side and browser-side) use
> [`@sylphx/sdk`](https://www.npmjs.com/package/@sylphx/sdk) with its
> peer-dep-gated entry points (`@sylphx/sdk`, `@sylphx/sdk/react`,
> `@sylphx/sdk/server`, `@sylphx/sdk/nextjs`,
> `@sylphx/sdk/web-analytics`, `@sylphx/sdk/health`).

## Error Handling

Every non-2xx response throws a single error type. Consumers discriminate on
`status` or match on `body` shape.

```typescript
import { ApiError } from '@sylphx/management'
import * as projects from '@sylphx/management/projects'

try {
  await projects.delete(client, 'non-existent')
} catch (err) {
  if (err instanceof ApiError) {
    console.error(`API Error ${err.status}: ${err.message}`)
  }
}
```

## Architecture

- **Contract-first** (ADR-084). Every type in this SDK — `Project`,
  `Deployment`, `EnvVar`, request / response envelopes — is imported from
  [`@sylphx/contract`](https://www.npmjs.com/package/@sylphx/contract). Hand-written type
  shims are a bug. Adding a new capability starts with a contract entry,
  not this package.
- **Promise-first, Effect-free public surface.** The server uses Effect-TS
  internally (ADR-058), but no Effect types leak through the published
  `.d.ts` — consumers see plain `Promise<T>`.
- **Immutable value type `Client`.** Cheap to construct, safe to share
  across parallel calls. No hidden globals, no singletons.
- **ESM-only, tree-shakable.** `"type": "module"`, `sideEffects: false`,
  per-namespace subpath exports.
- See **ADR-077** (Trio Completeness) for the design rationale,
  **ADR-083** (Two-Plane SDK Architecture) for the management /
  BaaS split, and **ADR-084** (Effect Schema Contract) for the
  contract SSOT. (ADRs live in the Sylphx-internal architecture
  records.)

## Agent integration

The `sylphx` CLI (built on top of this SDK) is the first-class agent surface
for Claude Code / Cursor / ChatGPT Apps. Sylphx does not ship a standalone
stdio MCP binary; if you want a bespoke MCP for your own workflows, compose
one directly on top of `@sylphx/management` — every method is a pure
`Promise<T>` and fully typed from `@sylphx/contract`.

## Related packages

- [`@sylphx/contract`](https://www.npmjs.com/package/@sylphx/contract) —
  Effect Schema SSOT this SDK derives its types from (peer).
- [`@sylphx/sdk`](https://www.npmjs.com/package/@sylphx/sdk) — runtime
  BaaS SDK for deployed apps (different plane).
- [`@sylphx/cli`](https://www.npmjs.com/package/@sylphx/cli) — interactive
  CLI built on this SDK.

## License

MIT — see [LICENSE](./LICENSE).
