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
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ jobs:
# present or enabled on the runner.
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down Expand Up @@ -316,7 +316,7 @@ jobs:

- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down Expand Up @@ -392,7 +392,7 @@ jobs:

- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down Expand Up @@ -455,7 +455,7 @@ jobs:

- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down Expand Up @@ -509,7 +509,7 @@ jobs:

- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

# setup-node and setup-go include runner OS and architecture in their cache
Expand Down Expand Up @@ -574,7 +574,7 @@ jobs:
# present or enabled on the runner.
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down Expand Up @@ -1805,7 +1805,7 @@ jobs:

- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-sdk-typescript.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 11.25.0
version: 11.28.7
run_install: false

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand Down
2 changes: 1 addition & 1 deletion apps/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# one commit, and a change spanning all three needs no intermediate SDK release.
#
# Shape (multi-stage):
# 1. build — node:26-slim (Debian + shell + toolchain): pnpm 12.4.2 via
# 1. build — node:26-slim (Debian + shell + toolchain): pnpm 12.15.0 via
# corepack (the `packageManager` pin in package.json; Node 25+
# no longer bundles corepack, so it is installed first), a frozen
# lockfile installs for SDK and Studio, `pnpm build` (contracts
Expand Down
39 changes: 19 additions & 20 deletions apps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,20 @@ product features, starting with chat. The published image is
`ghcr.io/stacklok/mecatl/studio`.

Mecatl Studio is a browser UI for a mecatl deployment, split in three packages that form
one self-contained pnpm workspace (pnpm 12.4.2, Node 26, see `package.json`):
one self-contained pnpm workspace (pnpm 12.15.0, Node 26, see `package.json`):

| Package | What it is |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `server/` (`@mecatl-studio/server`) | A Hono **backend for frontend (BFF)**. Holds the user's mecatl credential, talks to the daemon through the checked-out `@stacklok-oss/mecatl-sdk`, serves the SPA and `/api` from one origin. |
| `web/` (`@mecatl-studio/web`) | A Vite + React SPA. Calls only the BFF's `/api/v1`; imports neither the SDK nor daemon protocol types. |
| `contracts/` (`@mecatl-studio/contracts`) | Zod schemas, the generated `openapi.json`, and the generated Hey API / TanStack Query client. Generated files are committed and drift-gated. |
| Package | What it is |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `server/` (`@mecatl-studio/server`) | A Hono **backend for frontend (BFF)**. Holds the user's mecatl credential, talks to the daemon through the checked-out `@stacklok-oss/mecatl-sdk`, serves the SPA and `/api` from one origin. |
| `web/` (`@mecatl-studio/web`) | A Vite + React SPA. Calls only the BFF's `/api/v1`; imports neither the SDK nor daemon protocol types. |
| `contracts/` (`@mecatl-studio/contracts`) | Zod schemas, the generated `openapi.json`, and the generated Hey API / TanStack Query client. Generated files are committed and drift-gated. |

The architecture guide has a [Mecatl Studio](../docs/architecture/api-surface.md#mecatl-studio)
section.

## Boundary

Studio is a consumer of Mecatl's public surface, not part of the Go build:

- **Checked-out SDK.** `server/` uses the repository's `sdk/typescript` through a
frozen `file:` dependency, so Studio, its SDK, and the daemon contract it targets
are built from one commit, and a change spanning all three lands without an
Expand Down Expand Up @@ -103,14 +102,14 @@ The BFF connects to a mecatl runtime in exactly one of three modes, chosen from
environment at startup (a conflicting combination exits non-zero before listening, naming
the offending variable):

| Mode | Selected by | What happens |
| ---------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `external` | `MECATL_BASE_URL` | Connects to an existing mecatl gRPC listener. The only mode allowed inside the image. Interactive login is discovered from the deployment's RFC 9728 resource document. |
| `spawn` | neither `MECATL_BASE_URL` nor `MECATL_DEV_MOCK` | Spawns a local `mecated` from `MECATED_BIN` or `PATH`. Development only; refused when `STUDIO_IMAGE=1`. |
| `mock` | `MECATL_DEV_MOCK=1` | Spawns `mecated --mock` (offline, no model). Development only; refused when `STUDIO_IMAGE=1` or with `MECATL_BASE_URL`. |
| Mode | Selected by | What happens |
| ---------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `external` | `MECATL_BASE_URL` | Connects to an existing mecatl gRPC listener. The only mode allowed inside the image. Interactive login is discovered from the deployment's RFC 9728 resource document. |
| `spawn` | neither `MECATL_BASE_URL` nor `MECATL_DEV_MOCK` | Spawns a local `mecated` from `MECATED_BIN` or `PATH`. Development only; refused when `STUDIO_IMAGE=1`. |
| `mock` | `MECATL_DEV_MOCK=1` | Spawns `mecated --mock` (offline, no model). Development only; refused when `STUDIO_IMAGE=1` or with `MECATL_BASE_URL`. |

Authentication follows from the mode and the target: **interactive** (Authorization Code
+ PKCE against the single issuer the resource document names), **static**
Authentication follows from the mode and the target: **interactive** (Authorization
Code + PKCE against the single issuer the resource document names), **static**
(`MECATL_AUTH_TOKEN`, one service identity for every browser), or **none** (the target has
no issuer, e.g. a local `mecated` with no auth). Static and none WARN at startup and are
reported as `mode: "static"` / `"none"`; inside the image they additionally require
Expand All @@ -128,12 +127,12 @@ only local development. All configuration is environment variables read once at

Variables that matter only for development:

| Variable | Default | Meaning |
| ----------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| `MECATL_DEV_MOCK` | unset | `1` only. Spawns `mecated --mock`. Rejected together with `MECATL_BASE_URL` and inside the image. |
| `MECATED_BIN` | `PATH` lookup | Path of the `mecated` binary for spawn mode (`task studio:dev` sets it to `bin/mecated`). |
| `STUDIO_HOST` | `127.0.0.1` outside the image | Listen address. The development server binds loopback only unless you set this. |
| `STUDIO_WEB_DIST` | `../web/dist` relative to the server package | Directory holding the built SPA the BFF serves. The Dockerfile sets it for the image. |
| Variable | Default | Meaning |
| ----------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `MECATL_DEV_MOCK` | unset | `1` only. Spawns `mecated --mock`. Rejected together with `MECATL_BASE_URL` and inside the image. |
| `MECATED_BIN` | `PATH` lookup | Path of the `mecated` binary for spawn mode (`task studio:dev` sets it to `bin/mecated`). |
| `STUDIO_HOST` | `127.0.0.1` outside the image | Listen address. The development server binds loopback only unless you set this. |
| `STUDIO_WEB_DIST` | `../web/dist` relative to the server package | Directory holding the built SPA the BFF serves. The Dockerfile sets it for the image. |

Any startup error exits non-zero before listening, with a stderr line naming the variable.

Expand Down
4 changes: 2 additions & 2 deletions apps/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Taskfile for Mecatl Studio (apps/), included in the root Taskfile as `studio:`.
# The checked-out SDK is compiled before pnpm installs the BFF's local file
# dependency; the browser never imports SDK sources.
version: '3'
version: "3"

tasks:
install:
Expand Down Expand Up @@ -116,7 +116,7 @@ tasks:
`task build` from the repository root first (for bin/mecated).
deps: [install]
env:
MECATED_BIN: '{{.TASKFILE_DIR}}/../bin/mecated'
MECATED_BIN: "{{.TASKFILE_DIR}}/../bin/mecated"
cmds:
- cmd: |
test -x "$MECATED_BIN" || {
Expand Down
3 changes: 2 additions & 1 deletion apps/biome.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.14/schema.json",
"$schema": "https://biomejs.dev/schemas/2.6.2/schema.json",
"files": {
"includes": [
"**",
"!**/dist",
"!**/node_modules",
"!pnpm-lock.yaml",
"!web/src/routeTree.gen.ts",
"!contracts/openapi.json",
"!contracts/src/generated"
Expand Down
2 changes: 1 addition & 1 deletion apps/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@tanstack/react-query": "5.104.4",
"@tanstack/react-query": "5.104.5",
"zod": "4.6.7"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions apps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"engines": {
"node": ">=26 <27"
},
"packageManager": "pnpm@12.4.2",
"packageManager": "pnpm@12.15.0",
"scripts": {
"build": "pnpm generate && pnpm -r --if-present run build",
"check": "biome check . && pnpm typecheck && pnpm test && pnpm generated:check",
Expand All @@ -20,7 +20,7 @@
"typecheck": "pnpm -r --if-present run typecheck"
},
"devDependencies": {
"@biomejs/biome": "2.5.15",
"@biomejs/biome": "2.6.2",
"@playwright/test": "1.64.1",
"@types/node": "26.6.5",
"typescript": "6.0.3"
Expand Down
Loading
Loading