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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ VITE_NEKIRO_PROVIDER_NAME=""
VITE_NEKIRO_PROVIDER_TOKEN=""
VITE_NEKIRO_OWNER_TOKEN=""
VITE_NEKIRO_DEFAULT_WORKSPACE_ID=""
VITE_NEKIRO_PUBLIC_AGENT_ORIGIN=https://agents.nekiro.test
166 changes: 67 additions & 99 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
name: Console CI
name: CI

on:
push:
pull_request:
push:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
frontend:
quality:
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
with:
version: 11.3.0
run_install: false

- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.16.0
cache: pnpm
Expand All @@ -38,113 +43,76 @@ jobs:
- name: Test
run: pnpm run test

- name: Build
run: pnpm run build

browser-acceptance:
needs: frontend
build:
runs-on: ubuntu-latest
timeout-minutes: 40
env:
# Deterministic CI-only fixtures. These credentials and signing values
# are never used as production configuration or emitted as artifacts.
POSTGRES_USER: nekiro_acceptance
POSTGRES_PASSWORD: acceptance-only-password
POSTGRES_DB: nekiro_acceptance
POSTGRES_PORT: "55432"
CONTROL_PLANE_PORT: "18080"
A2A_ROUTER_PORT: "18081"
NEKIRO_COMPOSE_DATABASE_URL: postgresql://nekiro_acceptance:acceptance-only-password@postgres:5432/nekiro_acceptance?sslmode=disable
NEKIRO_DEV_AUTH_PRINCIPALS_JSON: '[{"id":"browser-provider","tokenSha256":"b44e989af5cb9bb1b315c9754b348747bc2adc400d20f413c96b0caf6cd76283"},{"id":"browser-owner","tokenSha256":"2db89754f354a623af6c54bb48473555bf68ae165f1d63001cb041e064078047"}]'
NEKIRO_INTERNAL_DEV_AUTH_PRINCIPALS_JSON: '[{"id":"router-internal","tokenSha256":"f9232718425b5ebee721187a79703448bce513ecf0600eb161f9256ddac27c4d"}]'
NEKIRO_ROUTER_SERVICE_PRINCIPALS_JSON: '[{"id":"control-plane","tokenSha256":"5abfd00de27c6b2f57d45fdc90999134e4e088414ba1f39bf67ee0d1c9cec554"}]'
NEKIRO_ROUTER_AGENT_PRINCIPALS_JSON: '[{"workspaceId":"workspace-browser","agentId":"runtime-a","tokenSha256":"e304d0370532633d535824a897d5c03445b636e8d1649064aa35a8fb50fef200"},{"workspaceId":"workspace-browser","agentId":"runtime-b","tokenSha256":"9b990de9bb74efd4e1d26a43a01e132deb60d563d49faf6878dca4af40858a38"}]'
NEKIRO_ROUTER_INTERNAL_BEARER_TOKEN: router-internal-token
NEKIRO_CONTROL_PLANE_SERVICE_TOKEN: control-plane-internal-token
NEKIRO_CORS_ALLOWED_ORIGINS: http://127.0.0.1:4173
NEKIRO_ENDPOINT_CHALLENGE_TTL_SECONDS: "300"
NEKIRO_ENDPOINT_VERIFICATION_TIMEOUT_MS: "10000"
NEKIRO_ENDPOINT_ALLOWED_PRIVATE_HOSTS_JSON: '["runtime-a","runtime-b"]'
NEKIRO_CONTROL_PLANE_INTERNAL_REQUEST_MAX_BYTES: "1048576"
NEKIRO_GATEWAY_INVOCATION_REQUEST_MAX_BYTES: "1048576"
NEKIRO_GATEWAY_SSE_EVENT_MAX_BYTES: "65536"
NEKIRO_GATEWAY_METADATA_RESPONSE_MAX_BYTES: "1048576"
NEKIRO_GATEWAY_INVOCATION_DEADLINE_MS: "30000"
NEKIRO_ROUTER_INTERNAL_REQUEST_LIMIT_BYTES: "1048576"
NEKIRO_ROUTER_AGENT_REQUEST_LIMIT_BYTES: "1048576"
NEKIRO_ROUTER_CONTROL_PLANE_RESPONSE_LIMIT_BYTES: "1048576"
NEKIRO_ROUTER_AGENT_RESPONSE_LIMIT_BYTES: "1048576"
NEKIRO_ROUTER_A2A_EVENT_LIMIT_BYTES: "1048576"
NEKIRO_ROUTER_SSE_EVENT_LIMIT_BYTES: "65536"
NEKIRO_ROUTER_RESOLUTION_DEADLINE_MS: "30000"
NEKIRO_ROUTER_AGENT_DEADLINE_MS: "30000"
NEKIRO_ROUTER_AGENT_CREDENTIAL_ISSUER: https://a2a-router.nekiro.test
NEKIRO_ROUTER_AGENT_CREDENTIAL_KEY_ID: ci-browser-key-1
NEKIRO_ROUTER_AGENT_CREDENTIAL_PRIVATE_KEY_BASE64URL: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8DoQe_884Qvh1w3RjnS8CZZ-TWMJulDV8d3IZkElUxuA
NEKIRO_ROUTER_AGENT_CREDENTIAL_TTL_SECONDS: "30"
NEKIRO_AGENT_ROUTER_ISSUER: https://a2a-router.nekiro.test
NEKIRO_AGENT_ROUTER_KEY_ID: ci-browser-key-1
NEKIRO_AGENT_ROUTER_PUBLIC_KEY_BASE64URL: A6EHv_POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg
RUNTIME_A_ROUTER_TOKEN: runtime-a-router-token
RUNTIME_A_RESPONSE_LIMIT_BYTES: "1048576"
RUNTIME_A_EVENT_LIMIT_BYTES: "65536"
RUNTIME_B_ROUTER_TOKEN: runtime-b-router-token
RUNTIME_B_RESPONSE_LIMIT_BYTES: "1048576"
RUNTIME_B_EVENT_LIMIT_BYTES: "65536"
NEKIRO_E2E_BASE_URL: http://127.0.0.1:4173
NEKIRO_E2E_COMPOSE_PROJECT: nekiro-console-browser
NEKIRO_E2E_COMPOSE_FILE: ${{ github.workspace }}/nekiro-platform/deploy/compose.yaml
VITE_NEKIRO_API_BASE_URL: http://gateway.nekiro.test:18080
VITE_NEKIRO_PROVIDER_ID: browser-provider
VITE_NEKIRO_PROVIDER_NAME: Browser Provider
VITE_NEKIRO_PROVIDER_TOKEN: browser-provider-token
VITE_NEKIRO_OWNER_TOKEN: browser-owner-token
VITE_NEKIRO_DEFAULT_WORKSPACE_ID: workspace-browser

timeout-minutes: 15
steps:
- name: Check out Console
uses: actions/checkout@v4

- name: Check out platform acceptance dependency
uses: actions/checkout@v4
with:
repository: NeKiro-project/NeKiro
ref: dec548e7b85da79c5982167688f0c698677d47c7
path: nekiro-platform
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
with:
version: 11.3.0
run_install: false

- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.16.0
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Install frontend dependencies
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Map the Gateway to an explicit non-IP origin
run: echo "127.0.0.1 gateway.nekiro.test" | sudo tee -a /etc/hosts

- name: Start fresh platform Compose
working-directory: nekiro-platform
run: docker compose --project-name "$NEKIRO_E2E_COMPOSE_PROJECT" --file deploy/compose.yaml up --build --detach --wait --wait-timeout 120

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Build production Console with explicit browser configuration
- name: Build production Console
run: pnpm run build

- name: Run production browser acceptance
run: pnpm run test:e2e

- name: Tear down fresh platform Compose
if: always()
working-directory: nekiro-platform
run: docker compose --project-name "$NEKIRO_E2E_COMPOSE_PROJECT" --file deploy/compose.yaml down --volumes --remove-orphans
security:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Verify license
shell: bash
run: test -s LICENSE

- name: Scan tracked source for credential material
shell: bash
run: |
if git grep -nEI -- '-----BEGIN (RSA |EC |OPENSSH |DSA |)?PRIVATE KEY-----|gh[pousr]_[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}'; then
echo "credential-like material is tracked"
exit 1
fi

- name: Reject cross-repository source checkout
shell: bash
run: |
pattern='repository:[[:space:]]*NeKiro-project/'"NeKiro"'|nekiro-platform/deploy/'"compose.yaml"
if git grep -nE "$pattern" -- .github; then
echo "Console CI must not assemble the platform source"
exit 1
fi

required:
if: ${{ always() }}
needs:
- quality
- build
- security
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Require every CI gate
shell: bash
env:
QUALITY_RESULT: ${{ needs.quality.result }}
BUILD_RESULT: ${{ needs.build.result }}
SECURITY_RESULT: ${{ needs.security.result }}
run: |
test "$QUALITY_RESULT" = success
test "$BUILD_RESULT" = success
test "$SECURITY_RESULT" = success
135 changes: 43 additions & 92 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,59 @@
# NeKiro Console MVP
# NeKiro Console

React/Vite/TypeScript/Tailwind Console for the NeKiro Agent Operating Platform.
The production React/Vite/TypeScript Console for the NeKiro Agent Operating
Platform. This repository is the canonical Console source; the core platform
repository does not maintain a production UI copy after the repository split.

This Console follows the MVP spec in docs/superpowers/specs/2026-07-16-nekiro-console-mvp-spec.md.

## Live surfaces

- Registry: GET/POST /v3/agents, exact reads, publish, and disable for Agent Card v0.2.
- Workspace: POST /v3/workspaces and GET /v3/workspaces/{workspaceId} from the header.
- Installations: install, list, enable, disable, and uninstall through /v3/workspaces/{workspaceId}/installations.
- Trusted Publication: provider-owned Binding, Challenge, and immutable Release lifecycle through public /v4 Gateway routes.
- Installation trust handoff: an explicit Release ID is preflighted through GET /v4/releases/{releaseId}; Catalog publication alone is not trusted publication.

## Runtime surfaces

- Invocations uses `POST /v4/workspaces/{workspaceId}/invocations` for JSON and
SSE results, with strict correlation and terminal-event validation.
- Ledger reads metadata-only Invocation and Trace projections through the same
Workspace-scoped Gateway API. No fake traces, task streams, or timeout events
are rendered.
- The canonical nested path is `Agent B -> Agent SDK -> A2A Router -> Agent A`.
The Console invokes B through Gateway v4 and reads the root/child lineage from
the metadata-only Ledger; it never accepts an Agent endpoint or runtime
credential in the form.
- The browser uses separate provider and Workspace-owner bearer contexts. Agent
authentication is declaration-only and never collects Agent secrets.
The Console talks only to the NeKiro Gateway. It supports trusted Agent
publication, public Agent share URLs, Catalog discovery, exact Release
installation, managed JSON/SSE invocation, and Workspace-scoped Ledger reads.

## Configuration

Create .env.local or export these six values for local development:

VITE_NEKIRO_API_BASE_URL=https://gateway.example.test
VITE_NEKIRO_PROVIDER_ID=
VITE_NEKIRO_PROVIDER_NAME=
VITE_NEKIRO_PROVIDER_TOKEN=
VITE_NEKIRO_OWNER_TOKEN=
VITE_NEKIRO_DEFAULT_WORKSPACE_ID=

`VITE_NEKIRO_PROVIDER_TOKEN` is used only for provider Catalog and Trusted
Publication operations. `VITE_NEKIRO_OWNER_TOKEN` is used only for Discovery,
Workspace, Installation, Invocation, and Ledger operations. Both are sent only
as Authorization headers and are not written to browser storage.
Copy `.env.example` to `.env.local` and provide every value explicitly:

The standalone repository is the upstream source for Console Issues #2/#4/#3.
The platform repository imports the reviewed runtime source into `apps/console`
and owns the root workspace lockfile and fresh-environment CI; do not maintain
a second hand-edited production Console implementation.
```text
VITE_NEKIRO_API_BASE_URL=https://gateway.example.test
VITE_NEKIRO_PROVIDER_ID=provider-id
VITE_NEKIRO_PROVIDER_NAME=Provider Name
VITE_NEKIRO_PROVIDER_TOKEN=provider-token
VITE_NEKIRO_OWNER_TOKEN=workspace-owner-token
VITE_NEKIRO_DEFAULT_WORKSPACE_ID=workspace-id
VITE_NEKIRO_PUBLIC_AGENT_ORIGIN=https://agents.example.test
```

The operational path is:
Provider and Workspace credentials are sent only as authorization headers and
are not written to browser storage. Missing, blank, whitespace-padded, or
otherwise invalid required configuration fails at startup.

1. Register an Agent Card with the provider context.
2. Create and verify an Endpoint Binding, then create, verify, and publish an immutable Release.
3. Give the Release ID to the Workspace owner.
4. Preflight that exact Release in Installations, accept permissions, and install the exact Card version.
5. Invoke only an enabled Installation that has a returned `installedReleaseId`.
## Development

## Failure and recovery ownership

The Console preserves the Gateway HTTP status, stable error code, trace ID, and
correlated invocation IDs where the contract returns them. Timeout, cancellation,
unavailable endpoint, disabled Installation, suspended/revoked Release, invalid
proof, expired/reused challenge, and malformed SSE are distinct failure
categories; the Console does not retry or turn them into success.

Provider recovery is owned by the provider: issue a fresh challenge, repair the
declared endpoint, or create a new Release when the server requires it. Workspace
owner recovery is owned by the owner: review the exact Release ID and permissions,
enable or uninstall an Installation according to the server state, and submit a
new invocation only through an enabled trusted Installation. Router and Ledger
facts remain server-owned and are inspected through the public Gateway.

## Run locally

npm install
npm run dev
```text
pnpm install --frozen-lockfile
pnpm dev
```

## Verification

npm test
npm run typecheck
npm run lint
npm run build
rg "/v4/workspaces/.+invocations|/v4/workspaces/.+traces" src docs -n
rg "INITIAL_AGENTS|INITIAL_INSTALLATIONS|TRACE_HISTORIES" src -n

## Browser acceptance
```text
pnpm typecheck
pnpm test
pnpm build
```

The browser acceptance suite runs against a fresh real Gateway and Compose
environment. It requires an explicitly installed Chromium and these values:
Console CI verifies only Console-owned behavior. Full backend/browser product
acceptance is owned by
[NeKiro-Stack](https://github.com/NeKiro-project/NeKiro-Stack), which checks out
an exact Console commit and invokes the retained Playwright suite against its
immutable component manifest.

NEKIRO_E2E_BASE_URL=http://127.0.0.1:4173
NEKIRO_E2E_COMPOSE_FILE=/absolute/path/to/deploy/compose.yaml
NEKIRO_E2E_COMPOSE_PROJECT=nekiro-browser-acceptance
VITE_NEKIRO_API_BASE_URL=http://gateway.nekiro.test
VITE_NEKIRO_PROVIDER_ID=browser-provider
VITE_NEKIRO_PROVIDER_NAME=Browser Provider
VITE_NEKIRO_PROVIDER_TOKEN=...
VITE_NEKIRO_OWNER_TOKEN=...
VITE_NEKIRO_DEFAULT_WORKSPACE_ID=workspace-browser
## Related repositories

Build the production Console with the five VITE_NEKIRO_* values before
running npm run test:e2e. Missing or whitespace-padded values fail
configuration. The suite uses the Gateway only, creates server-backed state,
and never stores credentials or challenge proofs in browser storage.
- [NeKiro core](https://github.com/NeKiro-project/NeKiro)
- [NeKiro Stack](https://github.com/NeKiro-project/NeKiro-Stack)
- [NeKiro Samples](https://github.com/NeKiro-project/NeKiro-Samples)
- [NeKiro Go SDK](https://github.com/NeKiro-project/nekiro-sdk-go)

Playwright traces, screenshots, videos, and HTML reports are disabled for this
acceptance path and are ignored by Git if a local runner creates them.
Fallback behavior is not implemented in the Console. Dependency, contract,
authorization, lifecycle, timeout, cancellation, and malformed-response states
remain explicit failures.
Loading
Loading