Skip to content

Openclaw/repo boundaries 20260506#30

Open
sitiouno wants to merge 37 commits into
WW-AI-Lab:mainfrom
SiteOneTech:openclaw/repo-boundaries-20260506
Open

Openclaw/repo boundaries 20260506#30
sitiouno wants to merge 37 commits into
WW-AI-Lab:mainfrom
SiteOneTech:openclaw/repo-boundaries-20260506

Conversation

@sitiouno
Copy link
Copy Markdown

@sitiouno sitiouno commented May 9, 2026

No description provided.

Alekhine and others added 30 commits April 24, 2026 16:49
- VITE_OFFICE_TITLE: customizes the header title (default: OpenClaw Office)
- VITE_BRANCH_LABEL: customizes the neon branch badge (default: SitioUno)
- fix: pass agent prop to LocalSkillsTab in AgentDetailTabs
Alekhine and others added 7 commits April 25, 2026 18:54
Adds a "Setup GCP" item to the Console sidebar that lets HQ operators
manage the SitioUno fleet against the new fleet-registry-api endpoints
(see SiteOneTech/gcloud-office#1):

  - View / approve / reject pending pairing requests from new branch
    nodes that join over Tailscale.
  - Create, configure, set-secret, test, enable/disable, and delete
    notification channels (Telegram first), with secret values written
    to GCP Secret Manager via the registry API and never persisted in
    the browser.

The page talks to the registry API over REST (admin bearer), separate
from the existing gateway WebSocket adapter which has no REST proxy.
Base URL + token are resolved from VITE_REGISTRY_API_URL/TOKEN or from
runtime injection via window.__OPENCLAW_CONFIG__.registryApiUrl/Token,
mirroring how the gateway URL/token are resolved in src/App.tsx.

Channels page now also surfaces a small banner pointing to Setup GCP
for Telegram alerts, and the telegram channel-schema gains the required
chatId field so any future channel-config UI built on the existing
schema picks it up automatically.

i18n keys added under setupGcp.* and consoleNav.setupGcp in both en
and zh; channels.fields.chatId / placeholders.chatId added; channels.gcpNotice.* added.

Tests:
  - registry-api-client URL/header/body resolution + error mapping
  - SetupGcpPage smoke render + not-configured hint

build / typecheck / vitest (483 tests) all green.

Co-authored-by: Jean Garcia (via Codex Local) <jean@flexipos.us>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…bearer) (#2)

Adjust the registry-API client introduced in PR #1 to talk to a NEW local
HQ sidecar on the Tailscale tailnet (`http://openclaw-hq:8781`) instead of
a public Cloud Run endpoint, and remove the bearer-token plumbing.

Why
- Shipping a long-lived admin token in the browser bundle (even via runtime
  injection) is a meaningful security regression: any XSS, devtools peek,
  or accidental log capture leaks an admin credential. This was flagged by
  Jean as exposed surface.
- The architecture rework moves all admin traffic inside the Tailscale VPN.
  The HQ sidecar listens only on the tailnet and validates the source
  identity server-side via `tailscale whois`. The VPN is the trust
  boundary, not a token.

Changes
- `src/lib/registry-api-client.ts`:
  - Default base URL `http://openclaw-hq:8781` (override via
    `VITE_REGISTRY_API_URL` or `window.__OPENCLAW_CONFIG__.registryApiUrl`).
  - Drop all token handling: no `Authorization` header, no
    `VITE_REGISTRY_API_TOKEN`, no `__OPENCLAW_CONFIG__.registryApiToken`,
    no token field on the resolved config.
  - Keep all typed methods (pairing.list/get/approve/reject/smokeTest,
    channels.list/get/create/update/delete/setSecret/test).
  - Add `notify.broadcast({ scope, text })` -> POST `/v1/notify`.
- Tests:
  - `registry-api-client.test.ts`: drop bearer-header assertions; add
    explicit assertions that no `Authorization` header is sent; add
    coverage for the new Tailscale default and for `notify.broadcast`.
  - `SetupGcpPage.test.tsx`: rewrite the "not configured" expectation —
    with the new default the base URL is always populated, so we instead
    assert the default `openclaw-hq:8781` URL is rendered. Stub `fetch`
    so the auto-loaded pairing/channels lists don't hit the network.
- `src/vite-env.d.ts`: drop `VITE_REGISTRY_API_TOKEN`, document the new
  default for `VITE_REGISTRY_API_URL`.
- `.env.example`: drop the token line, point the URL example at the
  Tailscale HQ sidecar, explain the trust model in the comment.
- i18n (`en` + `zh` `setupGcp.notConfigured.body`): rephrase to mention
  only the URL knob and the VPN trust boundary.

The `ChannelsPage` GCP banner is unchanged — it already links to
`/setup-gcp` with copy that does not reference the bearer or the external
URL.

Validation
- `npm run typecheck`: clean.
- `npm test`: 483/483 passing across 57 files.
- `npm run build`: succeeds.

Co-authored-by: Jean Garcia (via Codex Local) <jean@flexipos.us>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
The Setup GCP page mounted, fired auto-loads against the HQ sidecar at
http://openclaw-hq:8781, and — when the user was off the Tailscale tailnet
or the sidecar returned a non-array payload — an unhandled exception
inside the page's render path unmounted the entire React tree and left
the browser tab blank. Reload reproduced; the only escape was Back.

This commit:

- Adds a small reusable ErrorBoundary and wraps both the /setup-gcp
  route and the active tab subtree, so a render-time throw shows a
  retry-able panel instead of crashing the app.
- Hardens registry-api-client list endpoints to coerce non-array
  payloads to []; defensive coercion is repeated at the store and view
  layer (belt-and-suspenders).
- In setupgcp-store, fetch failures are caught and surfaced as `error`
  state with a friendly "cannot reach sidecar at <url>" hint when the
  underlying error looks like a network/DNS/mixed-content failure.
- Defends StatusPill and DetailGrid against missing/unknown fields so
  malformed pairing rows can no longer throw at render.
- Adds two regression tests: one for a fetch that rejects with a
  TypeError ("Failed to fetch") and one for a sidecar that returns a
  non-array envelope. Both used to white-screen; now both render the
  page chrome plus a friendly state.

No new dependencies, no URL default change, no bearer token reintroduced.

Co-authored-by: Jean García <jean@flexipos.us>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…#4)

The previous defensive `ensureArray(raw)` always returned [] because the
sidecar responds with `{requests: [...]}` and `{channels: [...]}` envelopes,
not bare arrays. Caller saw empty list even though backend had records.

Now: extract `.requests`/`.channels` from envelope; fallback to plain array
if shape differs. 2 regression tests added.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Adds a third tab to Setup GCP for managing LLM provider profiles consumed
by Alekhine's OpenHands wrapper. Profiles bind a {provider, model, label}
to a GCP-Secret-Manager-backed API key; the tab supports create / activate
(default) / set-secret / test / edit / delete via the HQ sidecar at
/v1/openhands/profiles.

- registry-api-client: new openhands.profiles namespace + types
  (OpenHandsProvider, OpenHandsProfile)
- setupgcp-store: openhandsProfiles slice with the same defensive
  error handling as the pairing/channels slices
- OpenHandsAdminView: card grid with provider badge, default star,
  secret-set/no-secret pills, inline test result, edit/secret/test panels
- SetupGcpPage: third tab "OpenHands" wrapped in the existing ErrorBoundary
- i18n: setupGcp.openhands.* keys in en + zh
- Tests: smoke + activate/test interactions for the view, plus envelope
  extraction + URL coverage for the new client method

Backend contract is shipped concurrently in another branch (HQ-sidecar
expects whois-over-Tailscale; no bearer added on this side).

Co-authored-by: Jean García <jean@flexipos.us>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant