Skip to content

Commit c507a4b

Browse files
chore(dashboard): purge dashboard-api references from frontend codebase (#21)
The dashboard frontend talks directly to api.instanode.dev for every operation — auth, claim, billing, team, resources, stacks. The dashboard-api Go service is being retired. This change cleans up documentation comments, the README architecture section, and the ContractsPage/DeploymentsPage banners that still mentioned dashboard-api. No runtime behavior changes: vite.config.ts and src/api/index.ts already only point at the agent API. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent abdf8fb commit c507a4b

8 files changed

Lines changed: 34 additions & 36 deletions

File tree

README.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# instanode.dev Dashboard
22

3-
React 18 + TypeScript + Vite frontend for the customer dashboard. This is where users log in, view their provisioned resources, upgrade their plan, and manage their team. It talks exclusively to `dashboard-api/` (port 8081, NodePort 30082) — not directly to the agent-facing `api/`.
3+
React 18 + TypeScript + Vite frontend for the customer dashboard. This is where users log in, view their provisioned resources, upgrade their plan, and manage their team. It talks directly to the agent-facing API at `api.instanode.dev`.
44

55
---
66

7-
## Why Two APIs?
7+
## Architecture
88

9-
`api/` (port 8080) is designed for agents and automation: anonymous-friendly, no sessions, simple HTTP, no cookies. It intentionally has no concept of "logged-in user."
9+
The dashboard is a single-page app that calls the agent API at `api.instanode.dev` for every operation: auth, claim, billing, team management, resource CRUD, and stacks. There is no intermediate backend — the browser holds a bearer token (`localStorage.instanode.token`) and includes it on every request.
1010

11-
`dashboard-api/` (port 8081) is designed for humans: it manages JWT sessions, team membership, billing state, and exposes resource management UI that proxies reads from the platform database. The two services have different auth models, different latency tolerances, and different security concerns. Keeping them separate means a bug in the human-facing session layer cannot affect agent provisioning, and vice versa.
11+
In dev, Vite proxies `/api`, `/auth`, `/claim`, `/db`, `/cache`, `/nosql`, `/queue`, `/storage`, `/webhook`, `/.well-known` to `AGENT_API_URL` (default `http://api.instanode.dev`). In prod, the dashboard ships as a static bundle on GitHub Pages and issues cross-origin fetches directly to `https://api.instanode.dev` (set via the `VITE_API_URL` build env).
1212

1313
---
1414

@@ -20,9 +20,9 @@ npm install
2020
npm run dev # Vite dev server at http://localhost:5173
2121
```
2222

23-
Requires `dashboard-api` running and reachable at `http://localhost:30082` (k8s NodePort). If you're not running k8s, start it with docker-compose:
23+
To point the dev proxy at a local k8s cluster:
2424
```bash
25-
cd infra && docker compose up -d
25+
AGENT_API_URL=http://localhost:30080 npm run dev
2626
```
2727

2828
To run unit tests:
@@ -37,16 +37,16 @@ npm test
3737
```
3838
src/
3939
├── hooks/
40-
│ ├── useAuth.ts # JWT session management — login, logout, auto-refresh
41-
│ └── useResources.ts # Fetches and caches the resource list from dashboard-api
40+
│ ├── useAuth.ts # Bearer-token session management
41+
│ └── useResources.ts # Fetches and caches the resource list
4242
├── pages/
43-
│ ├── LoginPage.tsx # GitHub OAuth / magic link entry point
43+
│ ├── LoginPage.tsx # Email magic link / PAT entry point
4444
│ ├── DashboardPage.tsx # Main resource list view
4545
│ ├── ClaimPage.tsx # Anonymous → account conversion (arrives via /start?t=jwt)
4646
│ ├── BillingPage.tsx # Plan status + upgrade flow
4747
│ ├── SettingsPage.tsx # Team name, member management
4848
│ ├── ResourceDetailPage.tsx # Per-resource view + rotate credentials
49-
│ └── DeployPage.tsx # (Phase 6) Container deploy entrypoint
49+
│ └── DeployPage.tsx # Container deploy entrypoint
5050
└── components/
5151
├── Layout/ # Sidebar + top nav shell
5252
├── ResourceCard/ # Resource summary card used in DashboardPage
@@ -59,27 +59,26 @@ src/
5959

6060
## Auth Flow
6161

62-
1. User clicks "Login with GitHub" on `LoginPage` — browser goes to `dashboard-api/auth/github`.
63-
2. OAuth redirect returns to `dashboard-api/auth/callback`, which issues a JWT and sets a `__session` HttpOnly cookie.
64-
3. `useAuth.ts` calls `/auth/me` on mount to hydrate session state. The JWT is kept in memory (not localStorage) to avoid XSS exposure.
65-
4. `useAuth.ts` silently calls `/auth/refresh` every 23 hours to extend the session without prompting the user.
66-
5. On logout, `/auth/logout` clears the cookie and the in-memory token.
62+
1. User pastes a PAT or completes the email magic-link flow on `LoginPage`.
63+
2. The bearer token is stored in `localStorage.instanode.token` and attached as `Authorization: Bearer <token>` on every subsequent request.
64+
3. `useAuth.ts` calls `GET /auth/me` on mount to hydrate session state.
65+
4. On 401, the client clears the token, stores the current path under `instanode.return_to`, and redirects to `/login`.
6766

6867
---
6968

7069
## The Claim Page (Anonymous to Account)
7170

72-
When an anonymous user hits a resource limit, `api/` embeds an upgrade URL in the response:
71+
When an anonymous user hits a resource limit, the agent API embeds an upgrade URL in the response:
7372
```
7473
https://instanode.dev/start?t=<signed-jwt>
7574
```
7675

77-
That URL hits `api/GET /start`, which validates the JWT and issues a 302 redirect to:
76+
That URL hits `GET /start` on the agent API, which validates the JWT and issues a 302 redirect to:
7877
```
7978
http://localhost:5173/claim?t=<jwt>
8079
```
8180

82-
`ClaimPage.tsx` picks up the `t` parameter, lets the user choose a login method, and calls `api/POST /claim` to atomically convert the anonymous session into a full account. The JWT in the claim is single-use — a second call returns 409 Conflict, preventing double-conversion.
81+
`ClaimPage.tsx` picks up the `t` parameter, lets the user choose a login method, and calls `POST /claim` on the agent API to atomically convert the anonymous session into a full account. The JWT in the claim is single-use — a second call returns 409 Conflict, preventing double-conversion.
8382

8483
---
8584

@@ -88,7 +87,7 @@ http://localhost:5173/claim?t=<jwt>
8887
107 tests covering auth guards, the upgrade journey, and resource interactions.
8988

9089
```bash
91-
# Requires: Vite dev server running (npm run dev) + k8s API at localhost:30080
90+
# Requires: Vite dev server running (npm run dev) + agent API at localhost:30080
9291
E2E_API_URL=http://localhost:30080 npx playwright test --project=chromium
9392

9493
# Run a single spec
@@ -106,13 +105,14 @@ npx playwright test --headed --project=chromium
106105

107106
| Variable | Purpose | Default |
108107
|---|---|---|
109-
| `VITE_API_URL` | dashboard-api base URL | `http://localhost:30082` |
108+
| `AGENT_API_URL` | Upstream the Vite dev proxy points at | `http://api.instanode.dev` |
109+
| `VITE_API_URL` | Build-time override for the production bundle | `https://api.instanode.dev` |
110110
| `VITE_NO_PROXY` | Disables Vite proxy (set to `1` in E2E) | unset |
111111
| `E2E_API_URL` | Agent API base URL used by Playwright tests | `http://localhost:30080` |
112112

113113
---
114114

115115
## Known Gaps
116116

117-
- **RotateCredentials**: the UI calls `POST /api/v1/resources/:id/rotate` on dashboard-api, which proxies to `api/`. Rotation is implemented for Postgres, Redis, and MongoDB.
118-
- **Razorpay Checkout**: the "Upgrade to Pro" button opens `instanode.dev/pricing` when checkout is not configured. A real `POST /api/v1/billing/checkout` endpoint in dashboard-api returns a Razorpay short URL when keys are configured.
117+
- **RotateCredentials**: the UI calls `POST /api/v1/resources/:id/rotate-credentials` on the agent API. Rotation is implemented for Postgres, Redis, and MongoDB.
118+
- **Razorpay Checkout**: the "Upgrade to Pro" button calls `POST /api/v1/billing/checkout` on the agent API and redirects to the returned Razorpay short URL. When Razorpay isn't configured (503), the button falls back to `instanode.dev/pricing`.

src/api/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Stubbed API client — adds a small fake-network delay so loading states
2-
// behave like the real thing. Swap this for `apiFetch()` against
3-
// dashboard-api when backend is ready.
2+
// behave like the real thing. Swap this for `apiFetch()` against the agent
3+
// API when wiring an endpoint that's still fixture-backed.
44
//
55
// Exact contract reference (when wiring real backend):
66
// GET /api/v1/resources — locked

src/api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Real API surface — talks to api.instanode.dev (via Vite proxy in dev,
22
// same-origin in prod). Endpoints that do NOT exist on the live backend
3-
// (vault list, activity feed, dashboard-team, members CRUD) fall back to
3+
// (vault list, activity feed, team metadata, members CRUD) fall back to
44
// fixtures so the dashboard remains usable end-to-end while engineering
55
// catches up. Each fallback is annotated `[FIXTURE]` in the comment.
66

src/api/types.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// ------------------------------------------------------------------
2-
// Types — mirror the locked dashboard-api + proto contracts exactly.
3-
// Source of truth: /InstaNode/proto/dashboard/v1/dashboard.proto
4-
// /InstaNode/dashboard-api/internal/handlers/*
2+
// Types — mirror the agent API JSON shapes the dashboard consumes.
3+
// Source of truth: /InstaNode/api/internal/handlers/*
54
// ------------------------------------------------------------------
65

76
export type Tier = 'anonymous' | 'hobby' | 'pro' | 'team' | 'growth'

src/pages/ContractsPage.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function ContractsPage() {
1919
<SummaryStat color="blue" label="delegated" v="3" sub="via agent api" subCls="dim" />
2020
</div>
2121

22-
<SectionH label="LOCKED" badgeBg="var(--accent)" title="26 endpoints · ready for parallel build" sub="source · /dashboard-api/internal/handlers/" />
22+
<SectionH label="LOCKED" badgeBg="var(--accent)" title="26 endpoints · ready for parallel build" sub="source · /api/internal/handlers/" />
2323
<Card style={{ padding: 0 }}>
2424
<Group title="Resources · 4">
2525
<ContractLine method="GET" path="/api/v1/resources" status="→ {ok, items: Resource[], total}" />
@@ -132,7 +132,7 @@ export function ContractsPage() {
132132
<BlockedCard
133133
icon="⟳"
134134
title="Deploy actions & logs · 4 endpoints"
135-
intro="Redeploy/rollback/stop and logs SSE all go directly to agent api today. Should proxy via dashboard-api for auth + audit."
135+
intro="Redeploy/rollback/stop and logs SSE all go directly to agent api today. Audit hooks need wiring on the agent side."
136136
contracts={[
137137
['POST', '/api/v1/stacks/:slug/redeploy', 'proxy → agent'],
138138
['POST', '/api/v1/stacks/:slug/rollback', 'propose'],
@@ -161,7 +161,7 @@ data: {}`}</>}
161161
<strong>Trial vs. immediate Hobby.</strong> <code>plans.yaml</code> declares <code>trial_days: 14</code>; <code>auth.go:151</code> assigns <code>hobby</code> with no trial fields. Brief journey 1 assumes a trial. <strong>Lock:</strong> add <code>teams.trial_ends_at</code> + worker, OR drop trial language from copy.
162162
</ContractBanner>
163163
<ContractBanner kind="warning" badge="#2">
164-
<strong>"Deployments" vs "Stacks".</strong> Brief uses "Deployments"; proto + dashboard-api use "Stacks". <strong>Lock:</strong> dashboard URL is <code>/deployments</code> (user language), API stays <code>/stacks</code> (existing).
164+
<strong>"Deployments" vs "Stacks".</strong> Brief uses "Deployments"; the API uses "Stacks". <strong>Lock:</strong> dashboard URL is <code>/deployments</code> (user language), API stays <code>/stacks</code> (existing).
165165
</ContractBanner>
166166
<ContractBanner kind="warning" badge="#3">
167167
<strong>Multi-env scoping.</strong> Resource shape includes <code>env</code> but list endpoint has no <code>?env=</code> filter. <strong>Lock:</strong> add server-side filter param + <code>teams.default_env</code> in PATCH body.
@@ -174,7 +174,7 @@ data: {}`}</>}
174174
</ContractBanner>
175175
</div>
176176

177-
<SectionH label="DELEGATED" badgeBg="var(--blue)" title="3 surfaces · routes to agent api" sub="not in dashboard-api · already documented in /flows" />
177+
<SectionH label="DELEGATED" badgeBg="var(--blue)" title="3 surfaces · routes to agent api" sub="anonymous / cross-origin paths · already documented in /flows" />
178178
<Card style={{ padding: '18px 20px' }}>
179179
<ContractLine method="POST" path="api.instanode.dev/db/new · /cache/new · /mongo/new · /queue/new · /storage/new · /webhook/new · /deploy/new" status="→ agent api" />
180180
<ContractLine method="POST" path="api.instanode.dev/claim · /start?t=jwt · /claim/preview" status="→ agent api" />

src/pages/DeployDetailPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export function DeployDetailPage() {
8585
</ROBanner>
8686

8787
<ContractBanner kind="blocked" badge="🔒 blocked">
88-
<strong>Redeploy / Rollback / Stop are missing from dashboard-api.</strong> <code>POST /api/v1/stacks/:slug/redeploy</code> currently routes to the agent API directly. Rollback and Stop don't exist anywhere yet.
88+
<strong>Redeploy / Rollback / Stop are partially wired.</strong> <code>POST /api/v1/stacks/:slug/redeploy</code> routes to the agent API. Rollback and Stop don't exist on the agent API yet.
8989
</ContractBanner>
9090

9191
<div className="tabs">

src/pages/DeploymentsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function DeploymentsPage() {
2020
return (
2121
<>
2222
<ContractBanner kind="warning" badge="naming gap">
23-
<strong>"Deployments" in the brief = "Stacks" in the code.</strong> The dashboard-api exposes <code>GET /api/v1/stacks</code>{' '}
23+
<strong>"Deployments" in the brief = "Stacks" in the code.</strong> The agent API exposes <code>GET /api/v1/stacks</code>{' '}
2424
(returns <code>DashboardStack</code>). UI keeps <code>/deployments</code> (user language); API stays <code>/stacks</code> (existing).
2525
</ContractBanner>
2626

vite.config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import react from '@vitejs/plugin-react';
33

44
// AGENT_API_URL — the agent-facing instanode.dev API (defaults to the live
55
// cluster; override locally with AGENT_API_URL=http://localhost:30080).
6-
// All dashboard fetches go through this single upstream — no separate
7-
// dashboard-api in this build of the project.
6+
// All dashboard fetches go through this single upstream.
87
const agentApiURL = process.env.AGENT_API_URL || 'http://api.instanode.dev';
98

109
// In tests we set VITE_NO_PROXY=1 so Playwright's page.route() globs match

0 commit comments

Comments
 (0)