@apitrail/studio 0.1.0-alpha.2 → 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +98 -48
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,77 +1,127 @@
1
1
  # @apitrail/studio
2
2
 
3
- > Standalone dev dashboard for [apitrail](https://apitrail.io). Run `pnpm dlx @apitrail/studio --db $DATABASE_URL` and get a real-time UI on `localhost:4545`.
3
+ > **Prisma-Studio-style standalone dashboard** for [apitrail](https://github.com/osharim/apitrail). `pnpm dlx @apitrail/studio` `localhost:4545` beautiful dark UI with KPIs, filters, and Chrome-DevTools-style waterfalls of every captured request. No embedding, no auth gymnastics.
4
4
 
5
- Think of this as **Prisma Studio for your API logs**. No embedding, no auth gymnastics, no production weight — just a beautiful standalone tool for monitoring, debugging, and exploring what your Next.js app is doing.
5
+ [![npm](https://img.shields.io/npm/v/@apitrail/studio/alpha?color=a78bfa&label=npm)](https://www.npmjs.com/package/@apitrail/studio)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
- ## Why standalone?
8
+ ## 60-second quick start
8
9
 
9
- The embeddable `@apitrail/dashboard` is Server-Component-only (no client interactivity, limited styling flexibility). `@apitrail/studio` is the opposite:
10
-
11
- - **Full SPA** — React 19, client-side state, URL filters, polling refresh, eventually live tail over SSE
12
- - **Its own server** — Hono, tiny JSON API, no Next.js weight
13
- - **Not in your app bundle** — ship `apitrail` core to prod, run studio only in dev / ops
14
- - **Works with any framework** — as long as the data lives in `apitrail_spans`
10
+ ```bash
11
+ DATABASE_URL='postgres://…' pnpm dlx @apitrail/studio
12
+ ```
15
13
 
16
- ## Usage
14
+ A browser tab opens at `http://127.0.0.1:4545`. If the table doesn't exist yet:
17
15
 
18
16
  ```bash
19
- # One-off via dlx (no global install)
20
- pnpm dlx @apitrail/studio --db $DATABASE_URL
21
-
22
- # Install globally and run
23
- pnpm add -g @apitrail/studio
24
- apitrail-studio --db postgres://…
17
+ pnpm dlx @apitrail/cli init
25
18
  ```
26
19
 
27
- Output:
20
+ ## Why a separate server?
28
21
 
29
- ```
30
- ● apitrail studio v0.1.0-alpha.0
31
- → http://127.0.0.1:4545
32
- Press Ctrl+C to stop.
33
- ```
22
+ The embeddable `@apitrail/dashboard` is Server-Component-only — limited interactivity, CSS constrained by the host app, auth has to be wired manually. `@apitrail/studio` is the opposite:
34
23
 
35
- ## Options
24
+ - **Full SPA** — React 19, client-side state, URL-shareable filters, polling refresh
25
+ - **Its own server** — Hono + tiny JSON API, no Next.js weight
26
+ - **Not in your app bundle** — ship `apitrail` core to prod, run studio only in dev / ops
27
+ - **Works with any framework** — as long as the data lives in `apitrail_spans`
28
+
29
+ ## CLI
30
+
31
+ ```bash
32
+ apitrail-studio [options]
33
+ pnpm dlx @apitrail/studio [options]
34
+ ```
36
35
 
37
36
  | Flag | Default | Description |
38
37
  |---|---|---|
39
- | `--db <url>` | `$APITRAIL_DATABASE_URL`, `$DATABASE_URL`, `$POSTGRES_URL` | Connection string |
38
+ | `--db <url>` | `$APITRAIL_DATABASE_URL` / `$DATABASE_URL` / `$POSTGRES_URL` | Postgres connection string |
40
39
  | `--port <n>` | `4545` | HTTP port |
41
- | `--host <addr>` | `127.0.0.1` | Bind address. Use `0.0.0.0` for LAN |
40
+ | `--host <addr>` | `127.0.0.1` | Bind address. Use `0.0.0.0` for LAN (**requires `--auth-basic`**) |
42
41
  | `--table <name>` | `apitrail_spans` | Span table to read from |
42
+ | `--auth-basic <u:p>` | — | Enable HTTP Basic Auth. **Required when host is non-loopback.** |
43
43
  | `--no-ssl` | — | Disable SSL on the pg connection |
44
44
  | `--no-open` | — | Don't auto-open the browser |
45
- | `--dev` | — | Enable CORS, skip UI serving (only JSON API used when developing studio itself) |
45
+ | `--dev` | — | CORS on, skip serving the built UI (for developing studio itself) |
46
+ | `-v`, `--version` | — | Print version |
47
+ | `-h`, `--help` | — | Show help |
46
48
 
47
- ## Features (v0.1)
49
+ ### Environment
48
50
 
49
- - **Overview** requests/24h, errors, slow, p50, p95 (polling every 10 s)
50
- - **Requests explorer** — method / status-class / path filters, sticky top, selectable rows
51
- - **Trace detail** side drawer with meta, waterfall of child spans, request/response headers + bodies (JSON pretty-printed)
52
- - **Dark, fast, keyboard-friendly** — no framework overhead on the wire
51
+ | Variable | Purpose |
52
+ |---|---|
53
+ | `APITRAIL_DATABASE_URL` | Preferred connection string |
54
+ | `DATABASE_URL` | Fallback |
55
+ | `POSTGRES_URL` | Fallback |
56
+ | `APITRAIL_STUDIO_AUTH` | `user:pass` for basic auth (alternative to `--auth-basic`) |
57
+ | `NO_COLOR=1` | Disable colored CLI output |
53
58
 
54
- ## Roadmap (v0.2+)
59
+ ## What you see
55
60
 
56
- - Live tail via SSE
57
- - Full-text search in bodies
58
- - Error grouping by fingerprint
59
- - Endpoint analytics (per-path latency percentiles)
60
- - Saved filter presets in URL
61
- - Auth for remote deployments (`--auth-basic user:pass` or an `--auth-token`)
61
+ | View | Contents |
62
+ |---|---|
63
+ | **Overview** | Requests/24h, errors, slow, p50, p95 — polls every 10 s |
64
+ | **Requests explorer** | Method / status-class / path-substring filters, 5 s polling, Enter/Space on a focused row opens the detail drawer |
65
+ | **Trace detail drawer** | Full meta (trace_id, span_id, route, runtime, host, UA, referer), Chrome-DevTools-style waterfall of child spans, Request / Response headers + bodies pretty-printed with masking applied |
62
66
 
63
- ## Security
67
+ ## Deployment patterns
64
68
 
65
- - **Default binding: `127.0.0.1`.** Only processes on your machine reach studio.
66
- - **Refuses to start on non-loopback hosts without `--auth-basic`.** This is enforced at CLI parse time — you cannot accidentally expose logs.
67
- - **HTTP Basic Auth** (`--auth-basic user:pass` or `APITRAIL_STUDIO_AUTH=user:pass`) uses constant-time SHA-256 comparison.
68
- - **Strict security headers** on every response: CSP, `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`, `Referrer-Policy: no-referrer`, `X-Robots-Tag: noindex, nofollow`.
69
- - **Rate limit** on `/api/*` routes: 300 req / min per client IP.
70
- - **Parametrized SQL**: every user input hits Postgres as a bound parameter; table names are regex-validated identifiers; trace IDs must match `/^[0-9a-f]{32}$/`.
71
- - **Sanitized error responses**: 500s return `{"error":"internal error"}` the actual SQL / stack trace is logged server-side only.
69
+ ### Local dev (default)
70
+
71
+ ```bash
72
+ pnpm dlx @apitrail/studio
73
+ ```
74
+
75
+ Binds `127.0.0.1:4545`. Only processes on your machine can reach it. No auth needed.
76
+
77
+ ### Team dev server on LAN
78
+
79
+ ```bash
80
+ APITRAIL_STUDIO_AUTH="alice:$(openssl rand -hex 16)" \
81
+ pnpm dlx @apitrail/studio --host 0.0.0.0
82
+ ```
83
+
84
+ If you try `--host 0.0.0.0` **without** auth, studio refuses to start. This is intentional — your logs contain bodies and headers that may include sensitive data even after masking.
85
+
86
+ ### Behind a reverse proxy with TLS
87
+
88
+ ```caddy
89
+ apitrail.mycompany.com {
90
+ reverse_proxy 127.0.0.1:4545
91
+ }
92
+ ```
93
+
94
+ See the full walkthrough in [docs/STUDIO_SETUP.md](https://github.com/osharim/apitrail/blob/main/docs/STUDIO_SETUP.md).
95
+
96
+ ## Security
72
97
 
73
- For LAN / remote deploys, see the full threat model in [SECURITY.md](../../SECURITY.md) and the [setup walkthrough](../../docs/STUDIO_SETUP.md).
98
+ - **Default binding: `127.0.0.1`.** Only your machine reaches studio.
99
+ - **Refuses to start on non-loopback without `--auth-basic`.** Enforced at CLI parse time.
100
+ - **HTTP Basic Auth** uses constant-time SHA-256 comparison (no timing-leak).
101
+ - **Strict response headers** on every request:
102
+ ```
103
+ Content-Security-Policy: default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; object-src 'none'
104
+ X-Content-Type-Options: nosniff
105
+ X-Frame-Options: DENY
106
+ Referrer-Policy: no-referrer
107
+ X-Robots-Tag: noindex, nofollow
108
+ ```
109
+ - **Rate limit** on `/api/*`: 300 req/min/IP.
110
+ - **Parametrised SQL** — every value binds through pg. Identifier regex-whitelisted. Trace IDs must match `/^[0-9a-f]{32}$/`.
111
+ - **Strict numeric validation** — `/api/spans?minStatus=…` refuses floats, scientific notation, hex, trailing garbage.
112
+ - **Sanitised error responses** — 500s return `{"error":"internal error"}`; the real SQL / stack trace is logged server-side only.
113
+
114
+ Full threat model in [SECURITY.md](https://github.com/osharim/apitrail/blob/main/SECURITY.md).
115
+
116
+ ## Roadmap
117
+
118
+ - ⏳ Live tail over SSE
119
+ - ⏳ Full-text search in request/response bodies
120
+ - ⏳ Error grouping by stack fingerprint
121
+ - ⏳ Per-endpoint latency percentile charts
122
+ - ⏳ Saved filter presets in the URL
123
+ - ⏳ Keyboard shortcuts (⌘K command palette)
74
124
 
75
125
  ## License
76
126
 
77
- MIT
127
+ MIT — [full repo](https://github.com/osharim/apitrail)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apitrail/studio",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "description": "Prisma-Studio-style standalone dashboard for apitrail. `pnpm dlx @apitrail/studio` → localhost:4545 → beautiful dark UI with KPIs, filters, and Chrome-DevTools-style waterfalls of every captured request. No embedding, no auth gymnastics.",
5
5
  "license": "MIT",
6
6
  "author": "apitrail contributors",