docs: consolidate product roadmap and source docs
This commit is contained in:
@@ -18,6 +18,10 @@ Use the documents in this order when there is ambiguity:
|
||||
8. `docs/development-rules.md`
|
||||
9. `docs/rust-code-rules.md`
|
||||
10. `docs/implementation-plan.md`
|
||||
11. `docs/product-editions.md`
|
||||
12. `docs/commercial-boundaries.md`
|
||||
13. `docs/frontend-roadmap.md`
|
||||
14. `docs/refactoring-roadmap.md`
|
||||
|
||||
If code and docs diverge, update docs first or together with code.
|
||||
|
||||
|
||||
@@ -2,30 +2,327 @@
|
||||
|
||||
## Current
|
||||
|
||||
### `feat/agent-scoped-machine-auth`
|
||||
### `feat/community-agent-key-cutover`
|
||||
|
||||
Status: in_progress
|
||||
|
||||
Goal:
|
||||
- довести открытую редакцию до продуктово завершенного машинного доступа через ключ AI-агента.
|
||||
|
||||
Main code areas:
|
||||
- `crates/crank-core/src/agent.rs`
|
||||
- `crates/crank-core/src/auth.rs`
|
||||
- `crates/crank-registry/src/postgres/agent.rs`
|
||||
- `crates/crank-registry/src/postgres/api_key.rs`
|
||||
- `apps/admin-api/src/service.rs`
|
||||
- `apps/admin-api/src/app.rs`
|
||||
- `apps/mcp-server/src/app.rs`
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/js/api-keys.js`
|
||||
- `apps/ui/html/agents.html`
|
||||
- `apps/ui/html/api-keys.html`
|
||||
- `apps/ui/js/i18n.js`
|
||||
|
||||
Implementation slices:
|
||||
1. Закрыть remaining workspace/platform-key assumptions в `admin-api` и `mcp-server`.
|
||||
2. Нормализовать list/create/revoke/delete flow для agent keys.
|
||||
3. Привести UI страницы `Agents` и `API Keys` к одной модели agent-scoped machine access.
|
||||
4. Явно ограничить `Community` на `security_level = standard`.
|
||||
|
||||
Progress:
|
||||
- done: `mcp-server` принимает ключ только по `(workspace_slug, agent_slug, secret_hash)`;
|
||||
- done: `admin-api` уже отдает и принимает agent-scoped key routes;
|
||||
- done: UI `API Keys` переведен на agent-scoped machine access;
|
||||
- done: removed legacy workspace-key routes, demo/bootstrap assumptions, and per-agent key count bug.
|
||||
|
||||
DoD:
|
||||
- ключ создается и принадлежит конкретному AI-агенту;
|
||||
- UI объясняет назначение ключа без ссылок на старую workspace-key модель;
|
||||
- `mcp-server` принимает Community machine access только по agent key;
|
||||
- Community flow не требует short-lived token service.
|
||||
|
||||
Verification:
|
||||
- backend unit and integration tests for key lifecycle;
|
||||
- MCP tool-call tests through agent endpoint;
|
||||
- e2e smoke for agent key create/reveal/revoke.
|
||||
|
||||
## Next
|
||||
|
||||
### `feat/edition-capability-model`
|
||||
|
||||
Status: ready
|
||||
|
||||
DoD:
|
||||
- AI agent can receive its own long-lived agent key from the admin UI
|
||||
- operation has an explicit security level: `standard`, `elevated`, or `strict`
|
||||
- machine calls to MCP can use short-lived agent tokens for elevated operations
|
||||
- one-time token mode is defined for strict operations
|
||||
- transition path from workspace-wide keys is explicit in docs and implementation slices
|
||||
Goal:
|
||||
- ввести capability model по редакциям и перестать смешивать Community и premium surface.
|
||||
|
||||
## Next
|
||||
Main code areas:
|
||||
- `crates/crank-core/src/*`
|
||||
- `apps/admin-api/src/service.rs`
|
||||
- `apps/admin-api/src/app.rs`
|
||||
- `apps/ui/js/*`
|
||||
- `apps/ui/html/*`
|
||||
- `docs/product-editions.md`
|
||||
- `docs/frontend-roadmap.md`
|
||||
|
||||
Implementation slices:
|
||||
1. Ввести серверную модель capabilities:
|
||||
- protocols
|
||||
- auth modes
|
||||
- security levels
|
||||
- workspace/user/agent limits
|
||||
2. Отдавать capability flags в `admin-api`.
|
||||
3. Привести UI к capability gating вместо скрытых продуктовых допущений.
|
||||
4. Зафиксировать Community defaults в docs и runtime config.
|
||||
|
||||
DoD:
|
||||
- UI знает, какие функции входят в текущую редакцию;
|
||||
- Community не показывает рабочие controls для premium-only features;
|
||||
- capability checks существуют не только в UI, но и на сервере.
|
||||
|
||||
Verification:
|
||||
- API tests for capability payloads;
|
||||
- frontend smoke for hidden/locked states;
|
||||
- manual verification on Community build.
|
||||
|
||||
### `feat/private-token-service-seam`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- подготовить public codebase к private реализации короткоживущих и одноразовых токенов.
|
||||
|
||||
Main code areas:
|
||||
- `crates/crank-core/src/auth.rs`
|
||||
- `crates/crank-core/src/agent.rs`
|
||||
- `apps/admin-api/src/app.rs`
|
||||
- `apps/admin-api/src/service.rs`
|
||||
- `apps/mcp-server/src/app.rs`
|
||||
- `docs/agent-auth-model.md`
|
||||
- `docs/admin-api.md`
|
||||
- `docs/mcp-interface.md`
|
||||
|
||||
Implementation slices:
|
||||
1. Определить stable contracts для:
|
||||
- `POST /mcp-auth/v1/token`
|
||||
- `POST /mcp-auth/v1/token/one-time`
|
||||
2. Ввести abstraction для token verification в `mcp-server`.
|
||||
3. Подготовить capability-gated UI/API surface без private implementation в Community.
|
||||
4. Отделить Community `standard` flow от commercial `elevated/strict`.
|
||||
|
||||
DoD:
|
||||
- public contracts зафиксированы и тестируемы;
|
||||
- Community продолжает работать без private token service;
|
||||
- premium auth paths не размазываются по Community logic.
|
||||
|
||||
Verification:
|
||||
- contract tests for auth payload shapes;
|
||||
- unit tests for credential-kind enforcement;
|
||||
- docs sync check.
|
||||
|
||||
### `feat/community-surface-trim`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- привести открытую редакцию к честному product surface и убрать расхождение между текущим кодом и edition policy.
|
||||
|
||||
Main code areas:
|
||||
- `apps/ui/js/wizard.js`
|
||||
- `apps/ui/js/wizard-model.js`
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/js/settings.js`
|
||||
- `apps/ui/js/i18n.js`
|
||||
- `docs/product-editions.md`
|
||||
- `docs/architecture.md`
|
||||
- `docs/mcp-interface.md`
|
||||
|
||||
Implementation slices:
|
||||
1. Скрыть или честно заблокировать:
|
||||
- `WebSocket`
|
||||
- `SOAP`
|
||||
- `gRPC streaming`
|
||||
- streaming execution modes
|
||||
- `elevated/strict` security levels
|
||||
в Community.
|
||||
2. Привести copy и feature affordances к open-core границе.
|
||||
3. Добавить edition-aware explanation в wizard и agents UI.
|
||||
|
||||
DoD:
|
||||
- Community UX не создает ложного ожидания наличия premium functionality;
|
||||
- protocol set и security levels совпадают в docs, UI и runtime contracts.
|
||||
|
||||
Verification:
|
||||
- e2e checks for wizard protocol list;
|
||||
- manual Community smoke;
|
||||
- localized copy review.
|
||||
|
||||
## Planned
|
||||
|
||||
### `feat/frontend-commercial-polish`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- закрыть оставшиеся UI/UX дефекты, мешающие коммерческой демонстрации и продажной версии продукта.
|
||||
|
||||
Main code areas:
|
||||
- `apps/ui/js/api-keys.js`
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/js/secrets.js`
|
||||
- `apps/ui/js/usage.js`
|
||||
- `apps/ui/js/settings.js`
|
||||
- `apps/ui/js/workspace-setup.js`
|
||||
- `apps/ui/js/auth.js`
|
||||
- `apps/ui/css/*`
|
||||
- `docs/frontend-roadmap.md`
|
||||
|
||||
Implementation slices:
|
||||
1. Перевести mobile tables в card layouts для:
|
||||
- `API Keys`
|
||||
- `Secrets`
|
||||
- `Usage`
|
||||
2. Доделать `Agents` page и modal:
|
||||
- объяснение отдельных agent endpoints
|
||||
- empty states
|
||||
- slug hints
|
||||
3. Добить `Settings` and workspace flows:
|
||||
- terminology cleanup
|
||||
- navigation spacing
|
||||
- notifications honesty
|
||||
- mobile sticky bug
|
||||
4. Довести agent-key UX на `API Keys` page.
|
||||
|
||||
DoD:
|
||||
- mobile UI не требует обязательного горизонтального скролла для primary actions;
|
||||
- terminology и product copy согласованы;
|
||||
- коммерческая демонстрация проходит без UI contradictions.
|
||||
|
||||
Verification:
|
||||
- targeted Playwright coverage;
|
||||
- manual mobile checks at 375px width;
|
||||
- EN/RU copy audit.
|
||||
|
||||
### `feat/open-core-repo-boundary`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- закрепить техническую границу между public Community repo и private commercial delivery.
|
||||
|
||||
Main code areas:
|
||||
- `docs/commercial-boundaries.md`
|
||||
- `docs/module-decomposition.md`
|
||||
- `docs/development-rules.md`
|
||||
- `docs/implementation-plan.md`
|
||||
- release scripts / Docker manifests / future packaging files
|
||||
|
||||
Implementation slices:
|
||||
1. Определить extension seams в public code.
|
||||
2. Подготовить отдельные delivery manifests для Community.
|
||||
3. Убрать из public repo assumptions о размещении private code рядом с Community logic.
|
||||
4. Подготовить naming и packaging strategy для private repositories.
|
||||
|
||||
DoD:
|
||||
- можно объяснить, что именно публикуется как OSS, а что уходит в private delivery;
|
||||
- Community release path отделен от commercial release path;
|
||||
- документация не ссылается на удаленные review files.
|
||||
|
||||
Verification:
|
||||
- docs consistency pass;
|
||||
- release checklist review.
|
||||
|
||||
### `feat/enterprise-access-governance`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- реализовать enterprise access layer вне Community scope.
|
||||
|
||||
Main code areas:
|
||||
- private `enterprise` services and crates
|
||||
- public contracts in:
|
||||
- `docs/admin-api.md`
|
||||
- `docs/agent-auth-model.md`
|
||||
- `docs/product-editions.md`
|
||||
|
||||
Implementation slices:
|
||||
1. `SSO`
|
||||
2. `2FA`
|
||||
3. extended `RBAC`
|
||||
4. `audit log`
|
||||
5. enterprise admin flows in UI through capability gating
|
||||
|
||||
DoD:
|
||||
- governance features не живут как полумеры в Community;
|
||||
- enterprise access model согласован с public contracts.
|
||||
|
||||
### `feat/cloud-metering-control-plane`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- подготовить hosted-редакцию как отдельный продуктовый контур.
|
||||
|
||||
Main code areas:
|
||||
- private cloud services
|
||||
- usage/metering integration points
|
||||
- `docs/product-editions.md`
|
||||
- `docs/commercial-boundaries.md`
|
||||
|
||||
Implementation slices:
|
||||
1. usage metering by workspace / agent / token;
|
||||
2. billing integration;
|
||||
3. hosted tenant controls;
|
||||
4. cloud operational tooling.
|
||||
|
||||
DoD:
|
||||
- Cloud edition не зависит от ручного учета usage;
|
||||
- hosted product surface согласован с feature matrix.
|
||||
|
||||
### `feat/release-protection-distribution`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- подготовить безопасную поставку Community и коммерческих редакций.
|
||||
|
||||
Main code areas:
|
||||
- CI workflows
|
||||
- Dockerfiles
|
||||
- deployment manifests
|
||||
- release docs
|
||||
|
||||
Implementation slices:
|
||||
1. public GitHub release flow for Community;
|
||||
2. private registry flow for Enterprise;
|
||||
3. signed artifacts and provenance;
|
||||
4. release checklist for edition-specific packaging.
|
||||
|
||||
DoD:
|
||||
- Community публикуется из public repo;
|
||||
- Enterprise и Cloud используют private delivery path;
|
||||
- коммерческий код не требуется публиковать в open source ради поставки.
|
||||
|
||||
### `feat/live-authenticated-staging-entry`
|
||||
|
||||
Status: ready
|
||||
|
||||
Goal:
|
||||
- держать реальный staging/demo контур в состоянии, пригодном для демонстрации и регрессии.
|
||||
|
||||
Main code areas:
|
||||
- `docs/demo-runbook.md`
|
||||
- `docs/deploy-and-staging-smoke.md`
|
||||
- `docs/authenticated-staging-pass.md`
|
||||
- deployment workflows
|
||||
|
||||
Implementation slices:
|
||||
1. актуализировать demo user flow;
|
||||
2. прогнать authenticated staging pass;
|
||||
3. зафиксировать regressions и manual checks;
|
||||
4. синхронизировать deploy docs с реальным окружением.
|
||||
|
||||
DoD:
|
||||
- authenticated staging flow runs against the real deployed environment
|
||||
- operator docs match the current deploy/runtime model
|
||||
- staging validation is captured without relying on local fixtures
|
||||
|
||||
## Completed
|
||||
|
||||
- `feat/websocket-test-run-polish`
|
||||
- `feat/frontend-wizard-modularization`
|
||||
- `feat/distributed-mcp-session-store`
|
||||
- staging validation не зависит от локальных фикстур;
|
||||
- documentation matches deployed behavior;
|
||||
- demo flow reproducible on real environment.
|
||||
|
||||
-1333
File diff suppressed because it is too large
Load Diff
@@ -1,832 +0,0 @@
|
||||
# Frontend Refactoring Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the frontend refactoring track for the Alpine.js UI. It is based on the current implementation, the observed code smells, and the explicit review findings.
|
||||
|
||||
The goal is not to replace Alpine.js. The stack choice is valid for the current product size. The goal is to make the UI:
|
||||
|
||||
- safe against obvious XSS classes;
|
||||
- internally consistent;
|
||||
- easier to maintain;
|
||||
- easier to test;
|
||||
- easier to ship and profile.
|
||||
|
||||
This document is implementation-oriented and split into concrete tracks, slices, file ownership, and acceptance criteria.
|
||||
|
||||
## Scope
|
||||
|
||||
The frontend refactoring scope covers:
|
||||
|
||||
1. XSS hardening and safe DOM rendering;
|
||||
2. shell/nav/auth unification;
|
||||
3. wizard modularization;
|
||||
4. module-pattern unification;
|
||||
5. removal of inline event handler patterns;
|
||||
6. lightweight build pipeline introduction;
|
||||
7. CSS class cleanup instead of imperative inline styles;
|
||||
8. low-risk performance improvements;
|
||||
9. frontend observability and testability improvements.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
This plan does not assume:
|
||||
|
||||
- migration to React/Vue/Svelte;
|
||||
- a full SPA rewrite;
|
||||
- a design-system rewrite;
|
||||
- replacing Alpine.js as the core UI model.
|
||||
|
||||
The target is a cleaner Alpine-compatible codebase, not a framework migration.
|
||||
|
||||
## Current State Summary
|
||||
|
||||
### Valid architectural choices
|
||||
|
||||
- Alpine.js is an appropriate choice for this admin UI size.
|
||||
- `api.js` is already a strong shared transport layer.
|
||||
- `ui-feedback.js` is simple and correct.
|
||||
- the visual language and token system are already above average for an admin panel.
|
||||
- EN/RU i18n support is already broad and worth preserving.
|
||||
|
||||
### Primary issues
|
||||
|
||||
1. unsafe `innerHTML` and string-built DOM with API data;
|
||||
2. mixed UI architecture:
|
||||
- Alpine on some pages;
|
||||
- imperative DOM on others;
|
||||
3. `wizard.js` is a monolith;
|
||||
4. duplicated shell logic between `auth.js` and `nav.js`;
|
||||
5. inconsistent module patterns;
|
||||
6. inline `onclick="..."` string injection in some renderers;
|
||||
7. no bundling/build pipeline;
|
||||
8. direct `element.style` mutation where CSS classes should be used;
|
||||
9. avoidable repeated filtering/computation in Alpine render paths.
|
||||
|
||||
## Guiding Rules
|
||||
|
||||
- Keep Alpine.js.
|
||||
- Centralize common frontend primitives instead of re-implementing them page by page.
|
||||
- Prefer DOM node construction and `textContent` over string-built HTML.
|
||||
- Restrict `innerHTML` to trusted, static, translation-reviewed content only.
|
||||
- Keep shared shell state in one place.
|
||||
- Break the wizard by concern, not by arbitrary line count alone.
|
||||
- Introduce the lightest build pipeline that solves the real problems.
|
||||
|
||||
## Track A: XSS Hardening
|
||||
|
||||
### Problem
|
||||
|
||||
Several files still render data from API responses through `innerHTML` and string concatenation without guaranteed escaping.
|
||||
|
||||
Known examples from review:
|
||||
|
||||
- `apps/ui/js/secrets.js`
|
||||
- `apps/ui/js/workspace.js`
|
||||
- error rendering paths where backend-provided strings are interpolated into HTML
|
||||
|
||||
This is a real frontend safety issue even in an authenticated admin panel.
|
||||
|
||||
### Goal
|
||||
|
||||
No untrusted API data is inserted through raw `innerHTML`.
|
||||
|
||||
### Target Design
|
||||
|
||||
Introduce a small shared DOM/safety utility module:
|
||||
|
||||
```text
|
||||
apps/ui/js/utils/
|
||||
dom.js
|
||||
escape.js
|
||||
```
|
||||
|
||||
### `utils/escape.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- `escapeHtml(value)`
|
||||
- `escapeAttr(value)` if attribute-safe escaping is still needed during transition
|
||||
|
||||
Rule:
|
||||
|
||||
- this file becomes the only source of escape helpers;
|
||||
- page scripts stop defining local copies such as the current `escapeHtml()` inside `wizard.js`.
|
||||
|
||||
### `utils/dom.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- helper builders for repetitive patterns:
|
||||
- `textNode(value)`
|
||||
- `el(tag, className?, text?)`
|
||||
- `clear(node)`
|
||||
- `appendChildren(node, children)`
|
||||
- helper renderers for empty/error banners when they currently rely on string HTML
|
||||
|
||||
### Required Migrations
|
||||
|
||||
#### Slice A1: shared escape helpers
|
||||
|
||||
Files:
|
||||
|
||||
- `apps/ui/js/wizard.js`
|
||||
- `apps/ui/js/secrets.js`
|
||||
- `apps/ui/js/workspace.js`
|
||||
- any other file using local escape helpers or raw string interpolation into HTML
|
||||
|
||||
Actions:
|
||||
|
||||
- move escape helpers into shared `utils/escape.js`;
|
||||
- remove duplicate local definitions.
|
||||
|
||||
#### Slice A2: high-risk string renderers
|
||||
|
||||
Priority files:
|
||||
|
||||
- `apps/ui/js/secrets.js`
|
||||
- `apps/ui/js/workspace.js`
|
||||
- `apps/ui/js/api-keys.js` if any dynamic HTML remains
|
||||
- `apps/ui/js/logs.js` / `usage.js` review for dynamic interpolation patterns
|
||||
|
||||
Actions:
|
||||
|
||||
- replace `innerHTML` row rendering with node creation;
|
||||
- use `textContent` for names, labels, and API-provided error strings;
|
||||
- use explicit element creation for buttons and actions.
|
||||
|
||||
#### Slice A3: error rendering contract
|
||||
|
||||
Actions:
|
||||
|
||||
- never assign backend error text to `innerHTML`;
|
||||
- render API errors through:
|
||||
- `textContent`
|
||||
- safe toast body
|
||||
- pre-defined empty/error state templates
|
||||
|
||||
Explicit case to fix:
|
||||
|
||||
- `apps/ui/js/secrets.js`
|
||||
- current pattern builds `profilesList.innerHTML` using `state.error`
|
||||
- `state.error` is populated from caught API/fetch error text
|
||||
- that makes server-provided message text an unsafe HTML source
|
||||
- this renderer must be rewritten to build DOM nodes and place the message through `textContent`
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no API-provided field is rendered via raw `innerHTML`;
|
||||
- `escapeHtml()` exists once, in a shared utility file;
|
||||
- XSS-sensitive renderers use `textContent` or safe DOM builders.
|
||||
|
||||
## Track B: Shell/Auth/Nav Unification
|
||||
|
||||
### Problem
|
||||
|
||||
`auth.js` and `nav.js` both:
|
||||
|
||||
- read `localStorage.getItem('crank_user')`;
|
||||
- derive role/workspace labels;
|
||||
- update `.nav-avatar`, `.user-dropdown-name`, `.user-dropdown-role`.
|
||||
|
||||
This creates duplicate state and drift.
|
||||
|
||||
### Goal
|
||||
|
||||
One module owns shell identity state and shell rendering.
|
||||
|
||||
### Target Design
|
||||
|
||||
Introduce:
|
||||
|
||||
```text
|
||||
apps/ui/js/shell/
|
||||
identity.js
|
||||
nav.js
|
||||
routes.js
|
||||
```
|
||||
|
||||
### Ownership
|
||||
|
||||
#### `shell/identity.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- session cache;
|
||||
- local mirror persistence;
|
||||
- deriving initials;
|
||||
- deriving role label;
|
||||
- deriving current workspace label;
|
||||
- rendering shell identity DOM;
|
||||
- broadcasting session change events.
|
||||
|
||||
Functions to absorb from current files:
|
||||
|
||||
- from `auth.js`:
|
||||
- `roleLabel`
|
||||
- `currentWorkspaceLabel`
|
||||
- `clearUserMirror`
|
||||
- `primaryMembership`
|
||||
- `initials`
|
||||
- `persistUserMirror`
|
||||
- `mirroredUser`
|
||||
- `renderShellIdentity`
|
||||
- `replaceSession`
|
||||
- from `nav.js`:
|
||||
- `currentUser`
|
||||
- `fillUserInfo`
|
||||
|
||||
#### `shell/nav.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- dropdown open/close behavior;
|
||||
- mobile nav behavior;
|
||||
- binding click handlers for:
|
||||
- logout
|
||||
- profile
|
||||
- settings
|
||||
|
||||
It must not own identity derivation anymore.
|
||||
|
||||
#### `auth.js`
|
||||
|
||||
Responsibilities after refactor:
|
||||
|
||||
- login/logout/session fetch;
|
||||
- route guarding;
|
||||
- delegating shell identity updates to `shell/identity.js`.
|
||||
|
||||
### Slice Plan
|
||||
|
||||
##### Slice B1: move identity rendering
|
||||
|
||||
- create `shell/identity.js`;
|
||||
- move identity ownership there;
|
||||
- update `auth.js` and `nav.js` to consume it.
|
||||
|
||||
##### Slice B2: remove duplicate storage constants
|
||||
|
||||
- `STORAGE_KEY` exists once;
|
||||
- `roleLabel()` exists once.
|
||||
|
||||
##### Slice B3: event-driven shell refresh
|
||||
|
||||
- shell reacts to `crank:sessionchange`;
|
||||
- individual page scripts stop updating shell identity directly.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- only one module owns mirrored user state;
|
||||
- `auth.js` and `nav.js` no longer duplicate shell rendering logic;
|
||||
- shell identity remains correct after login/logout/workspace switch.
|
||||
|
||||
## Track C: Wizard Modularization
|
||||
|
||||
### Problem
|
||||
|
||||
`apps/ui/js/wizard.js` is a monolith of roughly 3k lines, holding:
|
||||
|
||||
- global state;
|
||||
- step navigation;
|
||||
- 5 protocol flows;
|
||||
- file uploads;
|
||||
- mapping;
|
||||
- test-run handling;
|
||||
- import/export;
|
||||
- UI state transitions.
|
||||
|
||||
This is the frontend equivalent of the `postgres.rs` monolith.
|
||||
|
||||
### Goal
|
||||
|
||||
Split wizard code by stable responsibility while keeping the current HTML-driven workflow.
|
||||
|
||||
### Target Layout
|
||||
|
||||
```text
|
||||
apps/ui/js/wizard/
|
||||
index.js
|
||||
state.js
|
||||
navigation.js
|
||||
protocol-capabilities.js
|
||||
upstream.js
|
||||
auth-selector.js
|
||||
mapping.js
|
||||
test-run.js
|
||||
protocol-rest.js
|
||||
protocol-graphql.js
|
||||
protocol-grpc.js
|
||||
protocol-websocket.js
|
||||
protocol-soap.js
|
||||
shared.js
|
||||
```
|
||||
|
||||
### Ownership by Module
|
||||
|
||||
#### `wizard/state.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- encapsulate all mutable wizard state;
|
||||
- replace top-level globals with a single state object and accessors.
|
||||
|
||||
State currently to move:
|
||||
|
||||
- `currentStep`
|
||||
- `wizardProtocol`
|
||||
- `wizardMode`
|
||||
- `wizardEditId`
|
||||
- `wizardWorkspaceId`
|
||||
- `wizardCurrentOperation`
|
||||
- `wizardCurrentVersion`
|
||||
- upload buffers
|
||||
- protocol capability cache
|
||||
- test-run preview state
|
||||
|
||||
Target API:
|
||||
|
||||
- `createWizardState()`
|
||||
- `getWizardState()`
|
||||
- `resetWizardState()`
|
||||
|
||||
#### `wizard/navigation.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- dynamic step loading;
|
||||
- `goToStep`
|
||||
- `loadStep`
|
||||
- `step3PanelId`
|
||||
- sidebar/progress rendering;
|
||||
- continue/back button states.
|
||||
|
||||
Important cleanup:
|
||||
|
||||
- replace inline style mutation for disabled buttons with CSS classes.
|
||||
|
||||
#### `wizard/protocol-capabilities.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- defaults and fetched capability model;
|
||||
- `defaultProtocolCapabilities()`
|
||||
- `currentProtocolCapabilities()`
|
||||
- `loadProtocolCapabilities()`
|
||||
|
||||
#### `wizard/upstream.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- upstream dropdown rendering;
|
||||
- upstream auth badge rendering;
|
||||
- upstream create/edit interactions;
|
||||
- upstream selection state.
|
||||
|
||||
#### `wizard/auth-selector.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- secret/auth profile selection;
|
||||
- quick-create secret/profile flows;
|
||||
- auth form validation and serialization.
|
||||
|
||||
#### `wizard/mapping.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- input/output mapping;
|
||||
- preview helpers;
|
||||
- field inference helpers;
|
||||
- path defaulting.
|
||||
|
||||
#### `wizard/test-run.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- test-run request build;
|
||||
- test-run submission;
|
||||
- mode-aware result rendering for:
|
||||
- unary
|
||||
- window
|
||||
- session
|
||||
- async job
|
||||
|
||||
#### `wizard/protocol-*.js`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- only protocol-specific behavior.
|
||||
|
||||
Examples:
|
||||
|
||||
`protocol-graphql.js`
|
||||
|
||||
- selected GraphQL type;
|
||||
- query/mutation defaults;
|
||||
- operation name extraction;
|
||||
- top-level field extraction.
|
||||
|
||||
`protocol-grpc.js`
|
||||
|
||||
- descriptor upload;
|
||||
- service/method rendering;
|
||||
- reflection-related flow.
|
||||
|
||||
`protocol-websocket.js`
|
||||
|
||||
- subscribe/unsubscribe templates;
|
||||
- heartbeat/reconnect form state.
|
||||
|
||||
`protocol-soap.js`
|
||||
|
||||
- WSDL/XSD upload;
|
||||
- service catalog inspection;
|
||||
- binding apply.
|
||||
|
||||
### Migration Order
|
||||
|
||||
##### Slice C1: state + navigation split
|
||||
|
||||
- extract state and navigation first;
|
||||
- preserve current behavior.
|
||||
|
||||
##### Slice C2: protocol capability + shared helpers
|
||||
|
||||
- move generic helper logic out of main file.
|
||||
|
||||
##### Slice C3: GraphQL/gRPC/REST protocol extraction
|
||||
|
||||
- highest-traffic protocol flows first.
|
||||
|
||||
##### Slice C4: WebSocket/SOAP protocol extraction
|
||||
|
||||
- move less common but newer protocol flows.
|
||||
|
||||
##### Slice C5: auth selector + test-run split
|
||||
|
||||
- finalize with secret/auth and result handling modules.
|
||||
|
||||
##### Slice C6: thin entrypoint
|
||||
|
||||
- `wizard/index.js` becomes the only page bootstrap file.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no frontend file comparable in maintenance risk to current `wizard.js`;
|
||||
- wizard state is centralized, not scattered across globals;
|
||||
- protocol-specific logic is isolated by file.
|
||||
|
||||
## Track D: Module Pattern Unification
|
||||
|
||||
### Problem
|
||||
|
||||
Current JS modules use mixed patterns:
|
||||
|
||||
- IIFE modules with encapsulation;
|
||||
- top-level globals in page scripts;
|
||||
- direct `window` leakage.
|
||||
|
||||
### Goal
|
||||
|
||||
Move all first-party UI code to one consistent browser-friendly module pattern.
|
||||
|
||||
### Recommended Target
|
||||
|
||||
Use build-generated ES module bundles, while keeping runtime API globals explicit where needed.
|
||||
|
||||
During transition:
|
||||
|
||||
- keep page entrypoints small;
|
||||
- expose only intentionally public page bootstrap functions on `window`;
|
||||
- no free-floating utility functions in global scope.
|
||||
|
||||
### Rules
|
||||
|
||||
- utility modules must never write to `window` unless they are explicitly public;
|
||||
- page entrypoints may attach one namespace if needed:
|
||||
- `window.CrankWizard`
|
||||
- `window.CrankShell`
|
||||
- generic helpers must stay module-local.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no stray utility functions like `escapeHtml()` living in global scope;
|
||||
- global exposure is explicit and minimal.
|
||||
|
||||
## Track E: Event Handling Cleanup
|
||||
|
||||
### Problem
|
||||
|
||||
Some renderers still inject handlers through HTML strings such as:
|
||||
|
||||
- `onclick="switchWorkspace('...')"`
|
||||
|
||||
This is brittle and unsafe if values contain quotes.
|
||||
|
||||
### Goal
|
||||
|
||||
All dynamic UI actions use bound event listeners, not injected inline JS.
|
||||
|
||||
### Required Migrations
|
||||
|
||||
Priority files:
|
||||
|
||||
- `apps/ui/js/workspace.js`
|
||||
- any renderer that currently injects action handlers via HTML strings
|
||||
|
||||
Approach:
|
||||
|
||||
- build nodes;
|
||||
- attach `addEventListener`;
|
||||
- carry identifiers through closures or `data-*` attributes.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no dynamic `onclick="..."` string generation remains in first-party code.
|
||||
|
||||
## Track F: Build Pipeline
|
||||
|
||||
### Problem
|
||||
|
||||
The current UI ships many discrete JS files directly, without bundling or minification. Vendor files are committed in-repo and loaded directly.
|
||||
|
||||
This is acceptable for early stages but no longer ideal for:
|
||||
|
||||
- cache invalidation;
|
||||
- dependency graph hygiene;
|
||||
- payload count;
|
||||
- module splitting;
|
||||
- future lint/test integration.
|
||||
|
||||
### Goal
|
||||
|
||||
Introduce a lightweight build pipeline without turning the UI into a heavyweight SPA toolchain.
|
||||
|
||||
### Recommended Tooling
|
||||
|
||||
Use `esbuild`.
|
||||
|
||||
Reasoning:
|
||||
|
||||
- minimal configuration;
|
||||
- fast;
|
||||
- good enough for bundling this codebase;
|
||||
- easy Docker integration.
|
||||
|
||||
### Target Layout
|
||||
|
||||
```text
|
||||
apps/ui/
|
||||
src/
|
||||
js/
|
||||
...
|
||||
public/
|
||||
...
|
||||
dist/
|
||||
```
|
||||
|
||||
This does not require a full source tree rewrite immediately. A transitional layout is acceptable:
|
||||
|
||||
- keep current HTML layout;
|
||||
- bundle JS entrypoints into `dist/js/*.js`;
|
||||
- keep CSS mostly as-is initially.
|
||||
|
||||
### Required Outputs
|
||||
|
||||
- one bundle per page entrypoint where needed:
|
||||
- `catalog`
|
||||
- `agents`
|
||||
- `api-keys`
|
||||
- `logs`
|
||||
- `usage`
|
||||
- `settings`
|
||||
- `workspace-setup`
|
||||
- `wizard`
|
||||
- `secrets`
|
||||
- shared chunk for common utilities
|
||||
|
||||
### Docker Changes
|
||||
|
||||
UI Docker build should:
|
||||
|
||||
1. install npm deps;
|
||||
2. run build;
|
||||
3. serve bundled assets via nginx.
|
||||
|
||||
### Vendor Policy
|
||||
|
||||
Move from committed vendor runtime files toward npm-managed dependencies where possible:
|
||||
|
||||
- `alpinejs`
|
||||
- `js-yaml`
|
||||
|
||||
If some vendored asset remains, it must be intentional and documented.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- first-party JS is bundled and minified;
|
||||
- cache invalidation is deterministic;
|
||||
- page HTML references built bundles, not a long list of raw scripts.
|
||||
|
||||
## Track G: CSS State Cleanup
|
||||
|
||||
### Problem
|
||||
|
||||
Some UI states are expressed by directly mutating inline styles in JS.
|
||||
|
||||
Example class of issue:
|
||||
|
||||
- button disabled visuals set by `element.style.opacity`, `style.cursor`, etc.
|
||||
|
||||
### Goal
|
||||
|
||||
Move stateful visuals into CSS classes.
|
||||
|
||||
### Target Approach
|
||||
|
||||
Introduce semantic classes:
|
||||
|
||||
- `.is-disabled`
|
||||
- `.is-hidden`
|
||||
- `.is-loading`
|
||||
- `.is-active`
|
||||
- `.is-selected`
|
||||
|
||||
JS only toggles classes and attributes.
|
||||
|
||||
### Priority File
|
||||
|
||||
- `apps/ui/js/wizard.js`
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no UI state requires imperative style strings when a reusable class can express it.
|
||||
|
||||
## Track H: Performance Polish
|
||||
|
||||
### Problem
|
||||
|
||||
Some Alpine getters recompute filters repeatedly.
|
||||
|
||||
Known example:
|
||||
|
||||
- operations tab counts in `catalog.js` recompute filtered lists multiple times per render.
|
||||
|
||||
### Goal
|
||||
|
||||
Reduce avoidable repeated work without introducing premature complexity.
|
||||
|
||||
### Strategy
|
||||
|
||||
#### `catalog.js`
|
||||
|
||||
Replace repeated tab filtering with a cached derived snapshot, for example:
|
||||
|
||||
- one getter that computes filtered operations once;
|
||||
- one derived count map per tab;
|
||||
- `tabCount(tabId)` reads from that cached map.
|
||||
|
||||
#### General Rule
|
||||
|
||||
Only optimize:
|
||||
|
||||
- repeated O(n) list filters inside render loops;
|
||||
- repeated expensive formatting inside x-for;
|
||||
- repeated DOM queries in hot paths.
|
||||
|
||||
Do not over-engineer with memoization everywhere.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- obvious repeated list filtering in Alpine render paths is removed;
|
||||
- rendered behavior remains identical.
|
||||
|
||||
## Track I: Template and i18n Safety Cleanup
|
||||
|
||||
### Problem
|
||||
|
||||
There are small but risky patterns around naming collisions and template ergonomics.
|
||||
|
||||
Known example:
|
||||
|
||||
- `x-for="t in tabDefs"` where `t` also exists globally as the translation function.
|
||||
|
||||
### Goal
|
||||
|
||||
Avoid template variable names that collide with global utility names.
|
||||
|
||||
### Required Rule
|
||||
|
||||
Within Alpine templates:
|
||||
|
||||
- do not use `t`, `tf`, or other globally meaningful helper names as loop variables.
|
||||
|
||||
Use:
|
||||
|
||||
- `tab`
|
||||
- `item`
|
||||
- `entry`
|
||||
- `profile`
|
||||
- `workspace`
|
||||
|
||||
instead.
|
||||
|
||||
### Immediate Fixes
|
||||
|
||||
- rename `x-for="t in tabDefs"` to `x-for="tab in tabDefs"` in operations UI;
|
||||
- review similar short variable names across templates.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no Alpine template variable shadows translation helpers or globally meaningful names.
|
||||
|
||||
## Track J: Frontend Observability and Testability
|
||||
|
||||
### Problem
|
||||
|
||||
As the UI grows, debugging and regression confidence depend on:
|
||||
|
||||
- shared state boundaries;
|
||||
- consistent render helpers;
|
||||
- stable e2e selectors;
|
||||
- predictable logs and request tracing.
|
||||
|
||||
### Goal
|
||||
|
||||
Make the UI easier to verify and debug.
|
||||
|
||||
### Work Items
|
||||
|
||||
#### Shared test selectors
|
||||
|
||||
Add stable `data-testid` or equivalent hooks in critical areas:
|
||||
|
||||
- wizard protocol cards
|
||||
- secret create/rotate flows
|
||||
- auth selector
|
||||
- shell identity
|
||||
|
||||
#### Console discipline
|
||||
|
||||
- no stray debug logging in production code;
|
||||
- user-facing failures flow through toasts or error states only.
|
||||
|
||||
#### Request ID surfacing
|
||||
|
||||
When backend tracing lands, expose request IDs in developer-facing error surfaces where appropriate:
|
||||
|
||||
- test-run result panel;
|
||||
- logs detail drawer;
|
||||
- adapter failure toasts where safe.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- critical UI flows have stable automation hooks;
|
||||
- frontend failures are easier to trace to backend request IDs once that backend work lands.
|
||||
|
||||
## Delivery Order
|
||||
|
||||
Recommended order:
|
||||
|
||||
1. `feat/frontend-refactoring-plan`
|
||||
2. `feat/frontend-xss-hardening`
|
||||
3. `feat/frontend-shell-unification`
|
||||
4. `feat/frontend-template-safety-cleanup`
|
||||
5. `feat/frontend-wizard-modularization`
|
||||
6. `feat/frontend-build-pipeline`
|
||||
7. `feat/frontend-css-state-cleanup`
|
||||
8. `feat/frontend-performance-polish`
|
||||
9. `feat/frontend-observability-and-testability`
|
||||
|
||||
## Per-Slice Verification
|
||||
|
||||
Each slice must run the smallest realistic verification set for the affected area.
|
||||
|
||||
Baseline:
|
||||
|
||||
- `node --check` for touched JS files
|
||||
- UI Docker build
|
||||
- relevant Playwright specs where available
|
||||
|
||||
Additional rules:
|
||||
|
||||
- XSS hardening slices must include targeted regression checks for renderer behavior;
|
||||
- shell unification slices must include login/logout/workspace switch smoke;
|
||||
- wizard modularization slices must preserve existing wizard e2e coverage;
|
||||
- build pipeline slices must validate production asset serving in Docker.
|
||||
|
||||
## Success Definition
|
||||
|
||||
The frontend refactoring track is complete when:
|
||||
|
||||
- untrusted API data is no longer rendered through unsafe HTML paths;
|
||||
- shell identity logic has one owner;
|
||||
- the wizard no longer lives in a single giant file;
|
||||
- page scripts follow a consistent module pattern;
|
||||
- inline event handler injection is removed;
|
||||
- the UI ships through a lightweight build pipeline;
|
||||
- common UI states are driven by CSS classes instead of imperative style strings;
|
||||
- obvious repeated render-time computations are cleaned up.
|
||||
|
||||
At that point, the frontend remains Alpine-based but becomes significantly safer and easier to evolve.
|
||||
-736
@@ -1,736 +0,0 @@
|
||||
# UX and Copy Remediation Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the UX, copywriting, and localization cleanup track for the current UI. It is separate from `__REVIEW_FRONT.md`:
|
||||
|
||||
- `__REVIEW_FRONT.md` focuses on frontend architecture, safety, module structure, and delivery mechanics;
|
||||
- `__REVIEW_UX.md` focuses on user-facing clarity, consistency, language quality, and product honesty.
|
||||
|
||||
The goal is to remove developer-facing language, broken localization patterns, misleading placeholders, and half-functional UI signals from the product surface.
|
||||
|
||||
## Core Principle
|
||||
|
||||
The UI must speak to operators, not to developers.
|
||||
|
||||
That means:
|
||||
|
||||
- no implementation jargon such as "slice", "wired", "resolved at runtime" unless the user truly needs it;
|
||||
- no debug-style booleans in user-visible success messages;
|
||||
- no fake functionality presented as nearly available unless the user can act on it;
|
||||
- no mixed EN/RU phrasing where the product can speak normally in one language.
|
||||
|
||||
## Scope
|
||||
|
||||
This plan covers:
|
||||
|
||||
1. English copy cleanup;
|
||||
2. Russian copy cleanup;
|
||||
3. pluralization support;
|
||||
4. login UX cleanup;
|
||||
5. settings honesty cleanup;
|
||||
6. command palette decision and follow-through;
|
||||
7. wizard message polish;
|
||||
8. terminology consistency rules.
|
||||
|
||||
## Track A: English Copy Quality
|
||||
|
||||
### Problem Types
|
||||
|
||||
#### A1. Literal formatting markers leaking into UI
|
||||
|
||||
Examples:
|
||||
|
||||
- `apikeys.callout.body`
|
||||
- `wizard.step2.auth_profile_hint`
|
||||
|
||||
Current issue:
|
||||
|
||||
- backticks are rendered literally as characters;
|
||||
- they do not become semantic formatting in HTML;
|
||||
- the user sees developer-style markdown notation.
|
||||
|
||||
### Decision
|
||||
|
||||
Do not use markdown-style backticks in translation strings rendered through normal text nodes.
|
||||
|
||||
Allowed alternatives:
|
||||
|
||||
- plain text without emphasis;
|
||||
- explicit `<code>` only when rendered through a trusted HTML path that is intended for markup;
|
||||
- a dedicated visual class if code-like styling is actually needed.
|
||||
|
||||
### Required fixes
|
||||
|
||||
- `apikeys.callout.body`
|
||||
- replace `` `Last used` `` with plain text or a proper code-like span in a trusted template
|
||||
- `wizard.step2.auth_profile_hint`
|
||||
- remove `` `execution_config.auth_profile_ref` `` from user-facing copy
|
||||
|
||||
### Preferred rewrites
|
||||
|
||||
Instead of:
|
||||
|
||||
- `Last used updates after successful MCP authentication.`
|
||||
|
||||
Use:
|
||||
|
||||
- `Last used updates after a successful MCP call.`
|
||||
|
||||
Instead of:
|
||||
|
||||
- `Selected profile will be resolved at runtime and attached through execution_config.auth_profile_ref.`
|
||||
|
||||
Use:
|
||||
|
||||
- `The selected auth profile is applied automatically when this tool runs.`
|
||||
|
||||
#### A2. Internal planning jargon visible to users
|
||||
|
||||
Examples:
|
||||
|
||||
- `secrets.profiles.empty_body`
|
||||
|
||||
Current issue:
|
||||
|
||||
- `next slice` is a delivery-planning term, not a product term.
|
||||
|
||||
### Decision
|
||||
|
||||
All planning jargon must be removed from UI strings.
|
||||
|
||||
Forbidden user-facing phrases:
|
||||
|
||||
- `next slice`
|
||||
- `this build does not pretend`
|
||||
- `wired yet`
|
||||
- `not wired`
|
||||
- `backed by`
|
||||
- `resolved at runtime` unless the user truly configures runtime behavior
|
||||
|
||||
### Preferred rewrite
|
||||
|
||||
Instead of:
|
||||
|
||||
- `Create auth profiles in the next slice to bind secrets to upstream authentication.`
|
||||
|
||||
Use:
|
||||
|
||||
- `Create auth profiles in the Wizard when configuring an operation.`
|
||||
|
||||
#### A3. Unsafe or awkward symbols in plain text
|
||||
|
||||
Examples:
|
||||
|
||||
- `agents.drawer.recommendation`
|
||||
|
||||
Current issue:
|
||||
|
||||
- `<15` appears directly in text and should not rely on plain text rendering safety.
|
||||
|
||||
### Decision
|
||||
|
||||
Prefer natural language over symbolic shorthand in user guidance.
|
||||
|
||||
Preferred rewrite:
|
||||
|
||||
- `LLMs usually work best when an agent has fewer than 15 tools.`
|
||||
|
||||
#### A4. Debug-style status messages
|
||||
|
||||
Examples:
|
||||
|
||||
- `wizard.test.window_completed_body`
|
||||
- `wizard.test.session_started_body`
|
||||
|
||||
Current issue:
|
||||
|
||||
- booleans like `true/false` are shown directly to users;
|
||||
- milliseconds are exposed when approximate guidance is enough.
|
||||
|
||||
### Decision
|
||||
|
||||
User-visible status text must describe outcome, not internal flags.
|
||||
|
||||
### Required rewrites
|
||||
|
||||
`wizard.test.window_completed_body`
|
||||
|
||||
Current:
|
||||
|
||||
- `Window complete: {window_complete}. Truncated: {truncated}. Has more: {has_more}.`
|
||||
|
||||
Target behavior:
|
||||
|
||||
- message should describe:
|
||||
- how many items were collected;
|
||||
- whether data was truncated;
|
||||
- whether more data is available.
|
||||
|
||||
Preferred shape:
|
||||
|
||||
- `Collected {count} items.`
|
||||
- `Collected {count} items. Results were truncated.`
|
||||
- `Collected {count} items. More data is available if you extend the window or continue polling.`
|
||||
|
||||
`wizard.test.session_started_body`
|
||||
|
||||
Current:
|
||||
|
||||
- `Poll after {poll_after_ms} ms from the stream sessions view.`
|
||||
|
||||
Preferred:
|
||||
|
||||
- `Session started. Check Stream sessions in a few seconds.`
|
||||
|
||||
#### A5. Awkward English phrasing
|
||||
|
||||
Examples:
|
||||
|
||||
- `logs.range.1h: Last 1 hour`
|
||||
|
||||
Preferred:
|
||||
|
||||
- `Last hour`
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no markdown backticks in plain-text translations;
|
||||
- no delivery jargon in user-facing EN strings;
|
||||
- no debug booleans in wizard result messaging;
|
||||
- obvious awkward phrases are normalized to natural English.
|
||||
|
||||
## Track B: Russian Copy Quality
|
||||
|
||||
### Problem Types
|
||||
|
||||
#### B1. Missing keys
|
||||
|
||||
Known example:
|
||||
|
||||
- `wizard.step2.auth_basic` exists in EN and must exist in RU with product-quality copy.
|
||||
- `secrets.profiles.subtitle_count` in the RU section is effectively still English and must be treated as a translation-parity defect, not just as weak wording.
|
||||
|
||||
### Decision
|
||||
|
||||
Translation parity is mandatory for both locales.
|
||||
|
||||
Every newly added EN key must either:
|
||||
|
||||
- be translated in RU in the same change;
|
||||
- or fail verification.
|
||||
|
||||
### Required future safeguard
|
||||
|
||||
Add a translation parity checker to detect:
|
||||
|
||||
- missing RU keys;
|
||||
- missing EN keys;
|
||||
- exact duplicate placeholder keys if unintended.
|
||||
|
||||
#### B2. Russian pluralization is currently structurally incomplete
|
||||
|
||||
Known examples:
|
||||
|
||||
- `workspace_setup.member_count`
|
||||
- `workspace_setup.members.days_ago`
|
||||
- `secrets.used_by_count`
|
||||
|
||||
Current problem:
|
||||
|
||||
- templates like `{count} участников` fail for `1`;
|
||||
- templates like `{count} дня назад` fail for `5`.
|
||||
|
||||
### Decision
|
||||
|
||||
Introduce plural helpers based on `Intl.PluralRules`.
|
||||
|
||||
### Target API
|
||||
|
||||
In `i18n.js`, add a helper such as:
|
||||
|
||||
```js
|
||||
function tPlural(count, forms) {
|
||||
// locale-aware choice
|
||||
}
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
- English uses `one / other`
|
||||
- Russian uses `one / few / many`
|
||||
|
||||
### Target translation style
|
||||
|
||||
Instead of one flat string:
|
||||
|
||||
- `workspace_setup.member_count: '{count} участников'`
|
||||
|
||||
Use grouped forms, for example:
|
||||
|
||||
- `workspace_setup.member_count.one`
|
||||
- `workspace_setup.member_count.few`
|
||||
- `workspace_setup.member_count.many`
|
||||
|
||||
Or an equivalent plural storage format, as long as the API is stable.
|
||||
|
||||
### First keys to migrate
|
||||
|
||||
- `workspace_setup.member_count`
|
||||
- `workspace_setup.members.days_ago`
|
||||
- `secrets.used_by_count`
|
||||
- `secrets.profiles.subtitle_count`
|
||||
- `wizard.step3.grpc.streaming_hidden`
|
||||
- `wizard.grpc.services_found`
|
||||
|
||||
#### B3. Developer calques and transliterated jargon
|
||||
|
||||
Examples:
|
||||
|
||||
- `резолвиться`
|
||||
- `в следующем срезе`
|
||||
- `notification settings`
|
||||
- `lifecycle`
|
||||
- `usage references`
|
||||
- `advanced future integrations`
|
||||
|
||||
### Decision
|
||||
|
||||
Russian copy should be plain product Russian, while keeping real technical terms intact.
|
||||
|
||||
Keep in English only true technical terms such as:
|
||||
|
||||
- `gRPC`
|
||||
- `WSDL`
|
||||
- `JSON`
|
||||
- `Bearer`
|
||||
- `Query`
|
||||
- `Mutation`
|
||||
- `WebSocket`
|
||||
|
||||
Rewrite non-terms into Russian.
|
||||
|
||||
### Required rewrites
|
||||
|
||||
`wizard.step2.auth_profile_hint`
|
||||
|
||||
Instead of:
|
||||
|
||||
- `Выбранный профиль будет резолвиться в runtime...`
|
||||
|
||||
Use:
|
||||
|
||||
- `Выбранный профиль применяется автоматически при каждом вызове инструмента.`
|
||||
|
||||
`secrets.callout.body`
|
||||
|
||||
Remove mixed language and rewrite as:
|
||||
|
||||
- `После создания или ротации API возвращает только метаданные, поэтому на этой странице доступны управление секретами и просмотр их использования.`
|
||||
|
||||
`secrets.hint.generic`
|
||||
|
||||
Avoid:
|
||||
|
||||
- `advanced future integrations`
|
||||
|
||||
Use:
|
||||
|
||||
- `Подходит для произвольного JSON, если секрет нужно использовать в нестандартной интеграции.`
|
||||
|
||||
`workspace_setup.create.footer`
|
||||
|
||||
Replace:
|
||||
|
||||
- `Owner`
|
||||
|
||||
With:
|
||||
|
||||
- `Владелец`
|
||||
|
||||
`secrets.profiles.subtitle_count`
|
||||
|
||||
Current RU text is still English-like and must be translated fully.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- no missing translation keys between EN/RU;
|
||||
- Russian plural forms are grammatically correct;
|
||||
- no developer calques remain in user-facing RU strings;
|
||||
- role names are translated consistently.
|
||||
|
||||
## Track C: Login Experience Cleanup
|
||||
|
||||
### Problem
|
||||
|
||||
The login screen currently highlights unavailable functionality:
|
||||
|
||||
- Forgot password
|
||||
- Google SSO
|
||||
- Request access
|
||||
|
||||
all with `Planned` badges.
|
||||
|
||||
This creates the impression of unfinished product state on the very first screen.
|
||||
|
||||
There is also a developer-style note explaining what is not wired.
|
||||
|
||||
### Decision
|
||||
|
||||
The login page must present only working entry points.
|
||||
|
||||
### Recommended product behavior
|
||||
|
||||
#### Production/default mode
|
||||
|
||||
Show:
|
||||
|
||||
- email
|
||||
- password
|
||||
- sign-in button
|
||||
|
||||
Optionally show a single unobtrusive note:
|
||||
|
||||
- `Password reset and SSO will be added later.`
|
||||
|
||||
But only if product really needs that promise visible.
|
||||
|
||||
Preferred option:
|
||||
|
||||
- hide non-working actions completely.
|
||||
|
||||
#### Development-only mode
|
||||
|
||||
If the team wants visibility for future auth work, gate it behind a development flag.
|
||||
|
||||
Example:
|
||||
|
||||
- `window.CrankFeatures.showPlannedAuth`
|
||||
|
||||
### Required changes
|
||||
|
||||
#### Remove or gate:
|
||||
|
||||
- disabled `Forgot password?`
|
||||
- disabled `Google SSO`
|
||||
- disabled `Request access`
|
||||
- `login.password_only` developer note from production HTML
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- login page does not lead with unavailable features;
|
||||
- no developer-facing implementation note is shown in normal product mode.
|
||||
|
||||
## Track D: Settings Honesty Pass
|
||||
|
||||
### Problem
|
||||
|
||||
The settings page still contains a full `Notifications` section and other planned capability language that reads like UI cargo cult:
|
||||
|
||||
- detailed controls that do nothing;
|
||||
- developer-style subtitle text;
|
||||
- explanation written from the implementation perspective.
|
||||
|
||||
### Decision
|
||||
|
||||
If a settings area is not functional, it should not be represented as a near-complete interactive configuration panel.
|
||||
|
||||
### Product rule
|
||||
|
||||
There are only two acceptable states:
|
||||
|
||||
1. fully functional configuration;
|
||||
2. compact informational placeholder.
|
||||
|
||||
Avoid:
|
||||
|
||||
- large fake forms;
|
||||
- multiple toggles with `Planned` badges;
|
||||
- controls that imply persistence when none exists.
|
||||
|
||||
### Required changes
|
||||
|
||||
#### `settings.page.subtitle`
|
||||
|
||||
Current EN subtitle speaks about capabilities being visible but not wired.
|
||||
|
||||
Replace with a user-centered subtitle such as:
|
||||
|
||||
- `Manage your profile, password, and workspace settings.`
|
||||
|
||||
#### Notifications section
|
||||
|
||||
Replace the current detailed pseudo-settings with one compact informational card:
|
||||
|
||||
- title
|
||||
- short explanation
|
||||
- possibly one sentence: `Notification routing and per-user preferences will be added later.`
|
||||
|
||||
No fake toggles.
|
||||
|
||||
#### Planned security capabilities
|
||||
|
||||
Keep only if:
|
||||
|
||||
- they are clearly informational;
|
||||
- they do not look like interactive controls.
|
||||
|
||||
If they look interactive, collapse them into one planned card as well.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- settings page describes what users can do now;
|
||||
- non-functional areas are compact and clearly informational;
|
||||
- no fake detailed settings remain.
|
||||
|
||||
## Track E: Command Palette Decision
|
||||
|
||||
### Problem
|
||||
|
||||
`⌘K` is visible in the navigation, but there is no working command palette attached to it.
|
||||
|
||||
This is worse than not showing it at all.
|
||||
|
||||
### Decision Matrix
|
||||
|
||||
#### Option 1: Remove it
|
||||
|
||||
Choose this if:
|
||||
|
||||
- there is no actual command palette implementation;
|
||||
- there is no near-term product need for it;
|
||||
- keeping the hint only creates false expectation.
|
||||
|
||||
#### Option 2: Implement it
|
||||
|
||||
Choose this only if the product has a real command list worth exposing.
|
||||
|
||||
Minimum useful scope:
|
||||
|
||||
- go to Operations
|
||||
- go to Agents
|
||||
- go to API Keys
|
||||
- go to Secrets
|
||||
- go to Logs
|
||||
- go to Usage
|
||||
- go to Settings
|
||||
- switch workspace
|
||||
- create new operation
|
||||
- create new agent
|
||||
|
||||
### Current recommendation
|
||||
|
||||
Based on current code surface, remove it first.
|
||||
|
||||
Reason:
|
||||
|
||||
- there is visible affordance;
|
||||
- there is no working interaction;
|
||||
- product already has enough active work without adding a new shell feature mid-stream.
|
||||
|
||||
If later implemented, it should land as its own feature:
|
||||
|
||||
- `feat/frontend-command-palette`
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- either `⌘K` is removed everywhere;
|
||||
- or a real command palette exists and is keyboard-accessible.
|
||||
|
||||
No middle state.
|
||||
|
||||
## Track F: Wizard Messaging and Step Clarity
|
||||
|
||||
### Problem
|
||||
|
||||
Wizard copy still includes:
|
||||
|
||||
- technical internal language;
|
||||
- poor plural handling;
|
||||
- insufficiently clear streaming result messages;
|
||||
- protocol-step context that changes without enough explicit signaling.
|
||||
|
||||
### Required changes
|
||||
|
||||
#### F1. Auth selector copy
|
||||
|
||||
Remove implementation references such as:
|
||||
|
||||
- `execution_config.auth_profile_ref`
|
||||
|
||||
Replace with operator language:
|
||||
|
||||
- `The selected auth profile is applied automatically when the tool runs.`
|
||||
|
||||
#### F2. Streaming result messages
|
||||
|
||||
Replace technical booleans and milliseconds with outcome-focused language.
|
||||
|
||||
For:
|
||||
|
||||
- `window`
|
||||
- `session`
|
||||
- `async_job`
|
||||
|
||||
#### F3. gRPC plural and summary strings
|
||||
|
||||
Fix:
|
||||
|
||||
- `streaming method(s)`
|
||||
- `1 services`
|
||||
|
||||
Use locale-aware pluralization helpers.
|
||||
|
||||
#### F4. Step-3 protocol clarity
|
||||
|
||||
The sidebar label changing per protocol is useful, but not always obvious enough after protocol switching.
|
||||
|
||||
Recommended UI change:
|
||||
|
||||
- add a small protocol badge near the step title on step 3:
|
||||
- `REST config`
|
||||
- `GraphQL operation`
|
||||
- `gRPC method`
|
||||
- `WebSocket stream`
|
||||
- `SOAP binding`
|
||||
|
||||
This should exist both:
|
||||
|
||||
- in the main pane heading;
|
||||
- optionally in the sidebar if compact enough.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- wizard status/result text reads like product UX, not runtime telemetry;
|
||||
- plural forms are correct;
|
||||
- step 3 protocol-specific context is explicit.
|
||||
|
||||
## Track G: Terminology Rules
|
||||
|
||||
### Problem
|
||||
|
||||
The UI currently mixes three categories without a clear rule:
|
||||
|
||||
1. real technical terms;
|
||||
2. product concepts;
|
||||
3. implementation jargon.
|
||||
|
||||
### Terminology Policy
|
||||
|
||||
#### Keep as technical terms
|
||||
|
||||
- `Query`
|
||||
- `Mutation`
|
||||
- `gRPC`
|
||||
- `REST`
|
||||
- `WebSocket`
|
||||
- `SOAP`
|
||||
- `WSDL`
|
||||
- `JSON`
|
||||
- `Bearer token`
|
||||
|
||||
#### Translate to product language
|
||||
|
||||
- `workflow`
|
||||
- `settings`
|
||||
- `usage`
|
||||
- `notifications`
|
||||
- `workspace`
|
||||
- `owner`
|
||||
|
||||
#### Never expose as user-facing jargon
|
||||
|
||||
- `slice`
|
||||
- `wired`
|
||||
- `resolved at runtime`
|
||||
- `metadata only` if better phrasing exists
|
||||
- `future integrations`
|
||||
- `usage references`
|
||||
- `backed by`
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- technical terms remain technical;
|
||||
- implementation jargon disappears from UI.
|
||||
|
||||
## Track H: Verification and Guardrails
|
||||
|
||||
### Problem
|
||||
|
||||
Without guardrails, translation and UX regressions will return.
|
||||
|
||||
### Required safeguards
|
||||
|
||||
#### H1. Translation parity check
|
||||
|
||||
Add a script/test that verifies:
|
||||
|
||||
- EN and RU contain the same key set;
|
||||
- missing keys fail CI.
|
||||
|
||||
#### H2. Dangerous copy lint
|
||||
|
||||
Add a lightweight scan for forbidden phrases in user-facing translations:
|
||||
|
||||
- `next slice`
|
||||
- `wired`
|
||||
- `resolved at runtime`
|
||||
- backticks in plain text translations
|
||||
- `(s)` plural suffix
|
||||
|
||||
This can be a simple repo script at first.
|
||||
|
||||
#### H3. UX regression checklist
|
||||
|
||||
Extend manual regression docs with:
|
||||
|
||||
- login first impression check;
|
||||
- no dead nav affordances;
|
||||
- no fake settings sections;
|
||||
- pluralization smoke in RU.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- parity regressions are caught automatically;
|
||||
- obvious UX copy anti-patterns are detectable before release.
|
||||
|
||||
## Delivery Order
|
||||
|
||||
Recommended order:
|
||||
|
||||
1. `feat/frontend-ux-review-plan`
|
||||
2. `feat/frontend-i18n-remediation`
|
||||
3. `feat/frontend-login-simplification`
|
||||
4. `feat/frontend-settings-honesty-pass`
|
||||
5. `feat/frontend-command-palette-decision`
|
||||
6. `feat/frontend-wizard-copy-polish`
|
||||
7. `feat/frontend-plural-rules`
|
||||
8. `feat/frontend-ux-guardrails`
|
||||
|
||||
## Per-Slice Verification
|
||||
|
||||
Each slice should include:
|
||||
|
||||
- targeted `node --check` for touched JS
|
||||
- targeted Playwright smoke if the affected page already has coverage
|
||||
- manual locale switch smoke for EN and RU
|
||||
|
||||
Additional rules:
|
||||
|
||||
- login cleanup must be visually checked on first load;
|
||||
- plural-rule slice must include sample assertions for RU forms;
|
||||
- command-palette decision slice must verify no dead `⌘K` affordance remains.
|
||||
|
||||
## Success Definition
|
||||
|
||||
This UX cleanup track is complete when:
|
||||
|
||||
- the product no longer exposes developer planning language;
|
||||
- EN and RU feel intentional rather than partially translated;
|
||||
- plural forms are correct in both locales;
|
||||
- login shows only meaningful actions;
|
||||
- settings no longer presents fake detailed controls;
|
||||
- the command palette affordance is either real or removed;
|
||||
- wizard status and streaming messages are understandable without internal knowledge.
|
||||
|
||||
At that point, the UI stops feeling like a well-built internal tool and starts reading like a finished product surface.
|
||||
@@ -143,6 +143,8 @@ AI-агент не должен:
|
||||
- статический ключ AI-агента как режим совместимости;
|
||||
- короткоживущие токены по OAuth 2.0 как рекомендуемый режим.
|
||||
|
||||
Реализация этого режима должна рассматриваться как коммерческий контур и не должна требовать размещения private token-issuer logic в public repository.
|
||||
|
||||
Соответственно, платформа может обслуживать операции уровня:
|
||||
|
||||
- `standard`;
|
||||
@@ -156,6 +158,8 @@ AI-агент не должен:
|
||||
- короткоживущий токен;
|
||||
- одноразовый токен.
|
||||
|
||||
Enterprise-реализация должна поставляться через private delivery и опираться на capability-gated integrations в public codebase.
|
||||
|
||||
Соответственно, допускаются операции уровня:
|
||||
|
||||
- `standard`;
|
||||
|
||||
@@ -218,6 +218,28 @@ Crank - платформа для публикации внешних API в в
|
||||
- request headers
|
||||
- operation template
|
||||
- variables mapping
|
||||
|
||||
## 8. Open-core граница
|
||||
|
||||
Crank развивается как open-core продукт.
|
||||
|
||||
Это означает:
|
||||
|
||||
- `Community` должна полностью собираться из этого репозитория;
|
||||
- коммерческие возможности не должны храниться здесь как рабочий private code;
|
||||
- различия между редакциями должны отражаться в capability model, API, UI и delivery pipeline.
|
||||
|
||||
Ключевые продуктовые различия зафиксированы в `docs/product-editions.md`.
|
||||
|
||||
## 9. Коммерческий контур
|
||||
|
||||
Коммерческий контур не должен защищаться "скрытием" уже опубликованного исходного кода. Правильная архитектурная граница выглядит так:
|
||||
|
||||
- в public repo остается Community runtime и extension seams;
|
||||
- коммерческие реализации поставляются из private repositories или private artifacts;
|
||||
- критичные правила лицензирования, metering и token issuance исполняются на серверной стороне.
|
||||
|
||||
Практические правила зафиксированы в `docs/commercial-boundaries.md`.
|
||||
- извлечение результата из `data`
|
||||
|
||||
GraphQL в MCP публикуется как фиксированная операция с предсказуемой структурой ответа.
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
# Границы open-core и защита коммерческого кода
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ определяет:
|
||||
|
||||
- как разделять открытый и коммерческий функционал;
|
||||
- какие части должны оставаться в публичном репозитории;
|
||||
- какие части должны выноситься в private delivery;
|
||||
- как защищать коммерческий код без ложной ставки на обфускацию и "антидекомпиляцию".
|
||||
|
||||
## 2. Базовый принцип
|
||||
|
||||
Коммерческий код нужно защищать не попытками спрятать уже опубликованный исходный код, а правильной границей поставки.
|
||||
|
||||
Принцип:
|
||||
|
||||
- открытый код остается действительно открытым;
|
||||
- коммерческий код не попадает в public repository;
|
||||
- коммерческие сервисы и модули поставляются из приватного контура;
|
||||
- критичные правила лицензирования, metering и security policy исполняются на серверной стороне.
|
||||
|
||||
## 3. Что считается открытым контуром
|
||||
|
||||
В публичном репозитории должны оставаться:
|
||||
|
||||
- доменная модель Community;
|
||||
- `admin-api`, `mcp-server` и `ui`, необходимые для Community;
|
||||
- `REST`, `GraphQL` и `gRPC unary` в открытой редакции;
|
||||
- секреты, auth profiles, agent publishing, logs и usage;
|
||||
- статический ключ AI-агента;
|
||||
- контейнерное развертывание Community;
|
||||
- документация, тесты и демо-сценарии Community.
|
||||
|
||||
## 4. Что считается коммерческим контуром
|
||||
|
||||
В приватный контур должны выноситься:
|
||||
|
||||
- short-lived token service;
|
||||
- one-time token service;
|
||||
- `SSO`, `2FA`, расширенная `RBAC`, `audit log`;
|
||||
- `WebSocket`, `SOAP`, `gRPC streaming`, если они не включаются в Community;
|
||||
- advanced streaming execution modes;
|
||||
- metering и billing;
|
||||
- cloud control plane;
|
||||
- enterprise licensing and entitlement checks;
|
||||
- private operational tooling and support tooling.
|
||||
|
||||
## 5. Модель разделения репозиториев
|
||||
|
||||
### 5.1. Public repository
|
||||
|
||||
Этот репозиторий должен содержать только:
|
||||
|
||||
- Community runtime;
|
||||
- extension points;
|
||||
- capability model;
|
||||
- честные product contracts для открытой редакции.
|
||||
|
||||
### 5.2. Private repositories
|
||||
|
||||
Коммерческие возможности должны жить отдельно:
|
||||
|
||||
- либо в приватных crates;
|
||||
- либо в приватных приложениях и сервисах;
|
||||
- либо в отдельных private repositories с собственной поставкой.
|
||||
|
||||
Рекомендуемая схема:
|
||||
|
||||
- `crank` — public Community repo;
|
||||
- `crank-enterprise` — private self-hosted extensions;
|
||||
- `crank-cloud` — private cloud control plane и hosted-only logic.
|
||||
|
||||
## 6. Техническая стратегия разделения
|
||||
|
||||
### 6.1. Capability-first design
|
||||
|
||||
Открытый код должен опираться на capability model:
|
||||
|
||||
- edition capabilities;
|
||||
- protocol capabilities;
|
||||
- auth capabilities;
|
||||
- security capabilities.
|
||||
|
||||
Это позволяет:
|
||||
|
||||
- скрывать недоступные функции в UI;
|
||||
- не смешивать Community и commercial code paths;
|
||||
- добавлять private implementations без форка всей архитектуры.
|
||||
|
||||
### 6.2. Extension seams
|
||||
|
||||
В public repo должны быть только контракты и точки расширения:
|
||||
|
||||
- trait boundaries;
|
||||
- service contracts;
|
||||
- edition flags;
|
||||
- protocol registry abstraction;
|
||||
- token issuer abstraction;
|
||||
- feature availability checks.
|
||||
|
||||
Private code должен подключаться как реализация этих контрактов, а не как условные ветки по всему коду Community.
|
||||
|
||||
### 6.3. Server-side enforcement
|
||||
|
||||
Критичные коммерческие ограничения должны исполняться только на сервере:
|
||||
|
||||
- edition capabilities;
|
||||
- token issuance policy;
|
||||
- licensing checks;
|
||||
- metering;
|
||||
- protocol availability;
|
||||
- per-operation security rules.
|
||||
|
||||
Фронтенд может только отображать состояние. Он не должен быть единственным местом, где проверяется "можно / нельзя".
|
||||
|
||||
## 7. Что не является реальной защитой
|
||||
|
||||
Нельзя считать надежной защитой:
|
||||
|
||||
- минификацию frontend-кода;
|
||||
- обфускацию JavaScript;
|
||||
- "сложность" Rust binary как основную линию защиты;
|
||||
- попытку скрыть коммерческую логику в публичном репозитории через feature flags, если исходный код уже доступен.
|
||||
|
||||
Все это может немного повысить порог извлечения, но не решает задачу защиты коммерческого IP.
|
||||
|
||||
## 8. Реальная защита коммерческого кода
|
||||
|
||||
### 8.1. Не публиковать исходный код
|
||||
|
||||
Основное правило:
|
||||
|
||||
- коммерческий исходный код не должен попадать в public repo.
|
||||
|
||||
### 8.2. Поставлять private artifacts
|
||||
|
||||
Коммерческий контур должен поставляться как:
|
||||
|
||||
- private container images;
|
||||
- private binary artifacts;
|
||||
- private `Helm` charts;
|
||||
- private configuration bundles.
|
||||
|
||||
### 8.3. Подписывать артефакты
|
||||
|
||||
Для коммерческой поставки должны использоваться:
|
||||
|
||||
- подписанные контейнерные образы;
|
||||
- проверяемая provenance metadata;
|
||||
- versioned private releases.
|
||||
|
||||
### 8.4. Хранить ключевую логику на сервере
|
||||
|
||||
Наиболее чувствительные части должны оставаться на серверной стороне:
|
||||
|
||||
- licensing;
|
||||
- token issuance;
|
||||
- cloud metering;
|
||||
- enterprise access policy;
|
||||
- hosted control plane logic.
|
||||
|
||||
### 8.5. Не включать private UI в OSS bundle
|
||||
|
||||
Если функция коммерческая, ее UI не должен полноценно поставляться в Community build.
|
||||
|
||||
Допустимы:
|
||||
|
||||
- capability-driven hiding;
|
||||
- ограниченный teaser copy.
|
||||
|
||||
Недопустимы:
|
||||
|
||||
- полностью рабочие commercial screens в open-source bundle;
|
||||
- наличие private API contracts без server-side gating.
|
||||
|
||||
## 9. Что нужно сделать в кодовой базе
|
||||
|
||||
Для подготовки к коммерческой реализации в open-source коде должны появиться:
|
||||
|
||||
- edition capability model;
|
||||
- protocol capability model;
|
||||
- auth capability model;
|
||||
- интерфейсы для token issuer и enterprise access services;
|
||||
- server-side policy checks;
|
||||
- UI gating по capability flags;
|
||||
- отдельные delivery manifests для Community.
|
||||
|
||||
## 10. Связанные документы
|
||||
|
||||
- `docs/product-editions.md`
|
||||
- `docs/agent-auth-model.md`
|
||||
- `docs/module-decomposition.md`
|
||||
- `docs/frontend-roadmap.md`
|
||||
- `docs/refactoring-roadmap.md`
|
||||
- `docs/implementation-plan.md`
|
||||
@@ -174,6 +174,15 @@
|
||||
- домен не знает про HTTP, SQL, storage и transport;
|
||||
- adapters и repositories реализуют контракты, заданные ближе к домену.
|
||||
|
||||
## 7.4. Open-core правило
|
||||
|
||||
Для проекта фиксируется дополнительное правило:
|
||||
|
||||
- код `Community` живет в public repository;
|
||||
- коммерческий код не должен попадать в public repository "на будущее";
|
||||
- в public code допустимы только extension seams, capability flags и контракты для private implementations;
|
||||
- edition gating должно проверяться на серверной стороне, а не только в UI.
|
||||
|
||||
## 8. Git workflow
|
||||
|
||||
## 8.1. Remote
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
# Frontend roadmap
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует оставшийся фронтенд-backlog после уже выполненных крупных cleanup и refactoring slices.
|
||||
|
||||
Он заменяет старые review-документы и должен использоваться вместе с `TASKS.md`.
|
||||
|
||||
## 2. Что уже считается закрытым
|
||||
|
||||
Выполненными считаются следующие большие треки:
|
||||
|
||||
- базовая локализация и plural rules;
|
||||
- XSS hardening основных dynamic render paths;
|
||||
- template safety cleanup;
|
||||
- CSS state cleanup;
|
||||
- frontend build pipeline;
|
||||
- wizard modularization;
|
||||
- базовая frontend observability and testability;
|
||||
- websocket test-run polish;
|
||||
- command palette removal;
|
||||
- settings honesty initial pass.
|
||||
|
||||
## 3. Что остается актуальным
|
||||
|
||||
### 3.1. Product gating by edition
|
||||
|
||||
UI должен честно отражать различия редакций:
|
||||
|
||||
- Community не должен показывать доступные к настройке `WebSocket`, `SOAP`, `gRPC streaming`, если они не входят в открытую поставку;
|
||||
- `security_level = elevated` и `security_level = strict` не должны выглядеть рабочими в Community;
|
||||
- multi-user и enterprise controls должны скрываться или отображаться как capability-locked.
|
||||
|
||||
Основные файлы:
|
||||
|
||||
- `apps/ui/js/wizard.js`
|
||||
- `apps/ui/js/operations.js`
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/js/api-keys.js`
|
||||
- `apps/ui/js/settings.js`
|
||||
- `apps/ui/js/i18n.js`
|
||||
|
||||
### 3.2. Agent key UX
|
||||
|
||||
После перехода от platform/workspace keys к agent keys UI должен быть доведен до продуктового состояния:
|
||||
|
||||
- список ключей должен уметь показывать привязку к AI-агенту;
|
||||
- модалка создания ключа должна позволять выбрать режим и область применения;
|
||||
- copy должен объяснять, зачем нужен agent-scoped key и чем он отличается от будущих токенных режимов.
|
||||
|
||||
Основные файлы:
|
||||
|
||||
- `apps/ui/js/api-keys.js`
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/html/api-keys.html`
|
||||
- `apps/ui/html/agents.html`
|
||||
- `apps/ui/js/i18n.js`
|
||||
|
||||
### 3.3. Mobile-first restructuring for data-heavy pages
|
||||
|
||||
На мобильных экранах нужно убрать desktop-table anti-pattern для:
|
||||
|
||||
- `API Keys`
|
||||
- `Secrets`
|
||||
- `Usage`
|
||||
- частично `Agents`
|
||||
|
||||
Целевой подход:
|
||||
|
||||
- карточки вместо широких таблиц;
|
||||
- постоянная видимость primary actions;
|
||||
- отсутствие скрытого горизонтального скролла как обязательного пути.
|
||||
|
||||
Основные файлы:
|
||||
|
||||
- `apps/ui/js/api-keys.js`
|
||||
- `apps/ui/js/secrets.js`
|
||||
- `apps/ui/js/usage.js`
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/css/*`
|
||||
|
||||
### 3.4. Workspace and settings polish
|
||||
|
||||
Остаются открытые UI/UX-проблемы:
|
||||
|
||||
- глобальная терминология `workspace` против `пространство`;
|
||||
- структура `Account Settings`;
|
||||
- честное состояние раздела `Notifications`;
|
||||
- mobile navigation overlap / sticky bug;
|
||||
- выравнивание dropdown и workspace switcher behavior.
|
||||
|
||||
Основные файлы:
|
||||
|
||||
- `apps/ui/js/settings.js`
|
||||
- `apps/ui/js/workspace-setup.js`
|
||||
- `apps/ui/js/auth.js`
|
||||
- `apps/ui/index.html`
|
||||
- `apps/ui/css/*`
|
||||
|
||||
### 3.5. Agent creation and operations wizard clarity
|
||||
|
||||
Нужно добить:
|
||||
|
||||
- copy для причин существования отдельных agent endpoints;
|
||||
- empty states без багов с пустыми запросами;
|
||||
- пояснения вокруг `slug`;
|
||||
- более явное описание security level на операции;
|
||||
- capability-based hiding недоступных протоколов и execution modes.
|
||||
|
||||
Основные файлы:
|
||||
|
||||
- `apps/ui/js/agents.js`
|
||||
- `apps/ui/js/wizard.js`
|
||||
- `apps/ui/js/wizard-live.js`
|
||||
- `apps/ui/js/wizard-model.js`
|
||||
- `apps/ui/js/i18n.js`
|
||||
|
||||
## 4. Глобальные правила для UI
|
||||
|
||||
- никакой developer-facing copy в пользовательском интерфейсе;
|
||||
- capability-locked функция либо скрыта, либо помечена честно;
|
||||
- мобильная версия не должна требовать обязательного горизонтального скролла для primary actions;
|
||||
- действия создания должны жить в одном месте и не дублироваться в пустом состоянии без причины;
|
||||
- все новые user-facing строки должны обновляться одновременно в `EN` и `RU`.
|
||||
|
||||
## 5. Правила приемки
|
||||
|
||||
Frontend-задача считается закрытой только если:
|
||||
|
||||
- измененный UI соответствует capability model редакции;
|
||||
- строка есть в `EN` и `RU`;
|
||||
- мобильный сценарий проверен вручную или через e2e;
|
||||
- не остались старые product contradictions в copy.
|
||||
+110
-159
@@ -2,217 +2,168 @@
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует порядок перехода от текущего состояния проекта к целевой product-ready integration platform модели.
|
||||
Этот документ фиксирует актуальный порядок подготовки Crank к коммерческой реализации как open-core продукта.
|
||||
|
||||
Документ не повторяет уже выполненные исторические этапы. Он описывает только тот план, по которому проект должен двигаться дальше.
|
||||
|
||||
## 2. Базовый принцип
|
||||
|
||||
Работа делится на два контура:
|
||||
|
||||
1. завершение и hardening открытой редакции `Community`;
|
||||
2. подготовка архитектурных, продуктовых и delivery-границ для `Enterprise` и `Cloud`.
|
||||
|
||||
Принцип:
|
||||
|
||||
- сначала перепроектирование `as is -> to be`;
|
||||
- потом foundation под workspace/agent model;
|
||||
- потом возврат к end-to-end UI сценариям;
|
||||
- потом observability и access layer;
|
||||
- потом polish и demo readiness;
|
||||
- потом расширение до полного protocol platform scope.
|
||||
- сначала нужно сделать честную и законченную `Community`-основу;
|
||||
- затем нужно отделить commercial seams и private delivery;
|
||||
- только после этого имеет смысл реализовывать коммерческие расширения.
|
||||
|
||||
## 2. Этап 1. Перепроектирование `As Is -> To Be`
|
||||
## 3. Этап 1. Open-core product boundary
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- зафиксировать новую доменную модель и page-driven backend contract.
|
||||
Зафиксировать, что входит в `Community`, а что уходит в `Enterprise` и `Cloud`.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- зафиксирован `as is -> to be` план;
|
||||
- page-by-page gap analysis покрывает все целевые экраны;
|
||||
- разобраны все архитектурные конфликты UI vs current backend;
|
||||
- документы `architecture`, `data-model`, `database-schema`, `admin-api`, `mcp-interface` синхронизированы.
|
||||
- документы `product-editions`, `commercial-boundaries`, `architecture`, `module-decomposition` синхронизированы;
|
||||
- в кодовой базе определена capability model по редакциям;
|
||||
- UI и API не обещают Community-функции, которых там не должно быть;
|
||||
- старые review-файлы не требуются как отдельный источник истины.
|
||||
|
||||
## 3. Этап 2. Workspace foundation
|
||||
## 4. Этап 2. Community machine access completion
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- перевести хранение и API на workspace-scoped модель.
|
||||
Довести базовую модель машинного доступа Community до полностью рабочего состояния.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- операции и auth profiles принадлежат workspace;
|
||||
- registry умеет фильтровать данные по workspace;
|
||||
- есть default workspace migration path.
|
||||
- у AI-агента есть собственный ключ;
|
||||
- UI умеет выпускать, показывать, отзывать и удалять agent keys;
|
||||
- `mcp-server` использует agent-scoped machine access;
|
||||
- Community поддерживает только `security_level = standard`;
|
||||
- в системе не остается product-facing assumptions про workspace-wide machine key как основной способ вызова.
|
||||
|
||||
## 4. Этап 3. Agent publishing foundation
|
||||
## 5. Этап 3. Edition capability model
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- ввести `Agent` и agent-scoped MCP publishing.
|
||||
Подготовить инфраструктуру, которая позволит одной кодовой базе честно различать редакции продукта.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- можно создать agent и привязать к нему published operations;
|
||||
- `mcp-server` выдает tools в контексте конкретного agent;
|
||||
- один agent видит только свой curated toolset.
|
||||
- существует server-side capability model:
|
||||
- protocols
|
||||
- auth modes
|
||||
- security levels
|
||||
- workspace/user limits
|
||||
- `admin-api` возвращает capability flags для UI;
|
||||
- UI скрывает или честно блокирует premium functionality;
|
||||
- Community build не содержит ложных "почти доступных" product paths.
|
||||
|
||||
## 5. Этап 4. Operations and wizard integration
|
||||
## 6. Этап 4. Private auth-service seam
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- посадить operations catalog и wizard на реальные backend contracts.
|
||||
Подготовить публичный код к private реализации короткоживущих и одноразовых токенов.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- каталог операций и wizard работают без `localStorage` overrides;
|
||||
- operation edit/delete/publish/test выполняются через backend;
|
||||
- все протоколы работают в рамках одного UI flow.
|
||||
- зафиксированы контракты для:
|
||||
- `POST /mcp-auth/v1/token`
|
||||
- `POST /mcp-auth/v1/token/one-time`
|
||||
- в `mcp-server` существует abstraction для проверки токенов;
|
||||
- `admin-api` и `mcp-interface` знают про эти контракты документированно;
|
||||
- Community при этом остается полностью работоспособной без private token service.
|
||||
|
||||
## 6. Этап 5. Agents UI and backend
|
||||
## 7. Этап 5. Commercial protocol split
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- реализовать agent-centric слой.
|
||||
Перестать считать весь текущий protocol surface частью открытой редакции.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- agent CRUD работает;
|
||||
- binding operations к agent работает;
|
||||
- published agent появляется в MCP runtime.
|
||||
- определен canonical Community protocol set;
|
||||
- premium protocol families и premium execution modes вынесены в коммерческий план;
|
||||
- UI capability-gated по протоколам;
|
||||
- release model для Community не требует shipping premium flow как рабочей open-source функции.
|
||||
|
||||
## 7. Этап 6. Agent-scoped machine access
|
||||
## 8. Этап 6. Frontend launch readiness
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- реализовать machine access на уровне AI-агента и ввести обязательный уровень защиты операции.
|
||||
Довести UI до коммерчески пригодного состояния для `Community` и подготовить edition-aware product surface.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- UI умеет выпускать и отзывать ключи конкретного AI-агента;
|
||||
- длинноживущий машинный доступ больше не описывается ключом рабочей области;
|
||||
- у операции появляется обязательный `security_level`;
|
||||
- machine access не смешивается с upstream auth profiles;
|
||||
- Community поддерживает базовый режим со статическим ключом AI-агента.
|
||||
- agent key UX доведен до продукта;
|
||||
- mobile layouts для data-heavy страниц больше не ломают primary actions;
|
||||
- terminology и localization согласованы;
|
||||
- settings и workspace flows не содержат misleading или half-functional sections;
|
||||
- UI понимает разницу между Community и premium capabilities.
|
||||
|
||||
## 8. Этап 7. Token exchange and short-lived auth
|
||||
## 9. Этап 7. Enterprise access and governance
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- внедрить расширенные режимы доступа для операций повышенной чувствительности.
|
||||
Реализовать коммерческий access/governance слой в private delivery.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- существует конечная точка выдачи токена по ключу агента;
|
||||
- есть модель одноразового токена для чувствительных вызовов;
|
||||
- токены ограничены по сроку жизни, области действия и числу использований;
|
||||
- операции уровня `elevated` нельзя вызвать по статическому ключу;
|
||||
- операции уровня `strict` можно вызвать только по одноразовому токену.
|
||||
- есть `SSO`;
|
||||
- есть `2FA`;
|
||||
- есть расширенная `RBAC`;
|
||||
- есть `audit log`;
|
||||
- существует private delivery path для self-hosted customers.
|
||||
|
||||
## 9. Этап 8. Observability
|
||||
## 10. Этап 8. Cloud control plane
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- реализовать логи и usage.
|
||||
Подготовить hosted-редакцию как отдельный продуктовый контур.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- `Logs` page и `Usage` page работают на реальных данных;
|
||||
- есть продуктовые endpoints, а не только application logs;
|
||||
- rollups и detail views согласованы с UI.
|
||||
- есть metering;
|
||||
- есть billing integration;
|
||||
- есть hosted tenant model;
|
||||
- есть cloud deployment and support tooling;
|
||||
- capability model синхронизирована с hosted plans.
|
||||
|
||||
## 10. Этап 9. Alpine UI integration
|
||||
## 11. Этап 9. Release and distribution hardening
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- довести `apps/ui` до полной работы на реальном backend.
|
||||
Подготовить безопасную поставку открытой и коммерческой редакций.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- `apps/ui` содержит целевой Alpine.js UI;
|
||||
- mock JSON больше не используется на критическом пути;
|
||||
- UI, backend и docs синхронизированы.
|
||||
- Community публикуется из public GitHub repository;
|
||||
- Enterprise поставляется через private container registry и private manifests;
|
||||
- Cloud использует отдельный private operational contour;
|
||||
- build provenance и подпись артефактов документированы;
|
||||
- коммерческий код не требуется публиковать в public repository.
|
||||
|
||||
## 11. Этап 10. Secret store and upstream auth
|
||||
## 12. Этап 10. Live staging and demo readiness
|
||||
|
||||
Цель:
|
||||
### Цель
|
||||
|
||||
- заменить UI placeholder-модель `${secrets.*}` на рабочий backend/runtime слой secrets.
|
||||
Поддерживать реальный стенд и демонстрационный сценарий в состоянии, пригодном для продажи и демонстрации.
|
||||
|
||||
DoD:
|
||||
### DoD
|
||||
|
||||
- есть workspace-scoped `Secrets` resource;
|
||||
- secret values хранятся только в зашифрованном виде;
|
||||
- `AuthProfile` ссылается на `secret_id`, а не на строковый placeholder;
|
||||
- runtime умеет применять bearer/basic/api-key auth к реальному upstream request;
|
||||
- wizard имеет auth selector и quick-create flow для secrets/auth profiles.
|
||||
- live authenticated staging pass воспроизводим;
|
||||
- deploy smoke и operator docs совпадают с реальной поставкой;
|
||||
- demo user flow подтвержден на реальном окружении;
|
||||
- регрессии в publish/call/auth flow ловятся до релиза.
|
||||
|
||||
## 12. Этап 11. Hardening and demo readiness
|
||||
## 13. Связанные документы
|
||||
|
||||
Цель:
|
||||
|
||||
- довести продукт до стабильного демо-сценария.
|
||||
|
||||
DoD:
|
||||
|
||||
- end-to-end demo воспроизводим;
|
||||
- deployment и healthchecks стабильно зелёные;
|
||||
- документация и продуктовый сценарий совпадают.
|
||||
|
||||
## 13. Этап 12. MCP streaming proxy support
|
||||
|
||||
Цель:
|
||||
|
||||
- довести Crank до controlled streaming model поверх MCP `Streamable HTTP`.
|
||||
|
||||
DoD:
|
||||
|
||||
- `mcp-server` соответствует transport semantics `2025-06-18`;
|
||||
- execution modes `window`, `session`, `async_job` формально описаны и реализованы;
|
||||
- REST SSE и gRPC server-streaming поддерживаются в bounded форме;
|
||||
- UI умеет конфигурировать streaming limits, aggregation и lifecycle;
|
||||
- e2e сценарии покрывают window/session/job calls.
|
||||
|
||||
## 14. Этап 13. WebSocket upstream support
|
||||
|
||||
Цель:
|
||||
|
||||
- добавить полноценный WebSocket upstream adapter в общую execution model.
|
||||
|
||||
DoD:
|
||||
|
||||
- есть WebSocket target model;
|
||||
- runtime поддерживает bounded `window`, `session` и `async_job`;
|
||||
- heartbeat, reconnect и subscription lifecycle конфигурируются явно;
|
||||
- docs, UI и e2e синхронизированы.
|
||||
|
||||
## 15. Этап 14. SOAP support
|
||||
|
||||
Цель:
|
||||
|
||||
- добавить SOAP как enterprise-oriented protocol family.
|
||||
|
||||
DoD:
|
||||
|
||||
- есть WSDL/XSD-driven target model;
|
||||
- runtime умеет строить SOAP envelopes и нормализовать SOAP Faults;
|
||||
- operator может выбрать service, port и operation;
|
||||
- test-run, publish и observability работают так же, как для остальных протоколов.
|
||||
|
||||
## 16. Этап 15. Detailed streaming specs
|
||||
|
||||
Цель:
|
||||
|
||||
- довести streaming-docs до function-level и field-level design спецификации.
|
||||
|
||||
DoD:
|
||||
|
||||
- есть отдельные docs для streaming admin-api, runtime, UI и capability matrix;
|
||||
- protocol docs не противоречат общей execution model;
|
||||
- roadmap и `TASKS.md` синхронизированы с full-detail architecture.
|
||||
|
||||
## 17. Этап 16. Streaming implementation slices
|
||||
|
||||
Цель:
|
||||
|
||||
- перевести streaming design в agent-friendly execution plan по файлам, тестам и DoD.
|
||||
|
||||
DoD:
|
||||
|
||||
- есть отдельный implementation spec по всем streaming slices;
|
||||
- указаны file-level changes;
|
||||
- указаны обязательные тесты и acceptance criteria;
|
||||
- state transitions и sequence outlines зафиксированы явно.
|
||||
- `docs/product-editions.md`
|
||||
- `docs/commercial-boundaries.md`
|
||||
- `docs/frontend-roadmap.md`
|
||||
- `docs/refactoring-roadmap.md`
|
||||
- `docs/agent-auth-model.md`
|
||||
|
||||
@@ -110,6 +110,11 @@
|
||||
- операция задает обязательный `security_level`, и `mcp-server` обязан отклонять вызов, если представленный credential слабее требуемого уровня;
|
||||
- детальная модель уровней зафиксирована в `docs/agent-auth-model.md`.
|
||||
|
||||
Важно:
|
||||
|
||||
- Community-сборка должна работать полностью без private token services;
|
||||
- commercial token flows должны подключаться через capability-gated server-side integrations.
|
||||
|
||||
Уровни защиты операции:
|
||||
|
||||
- `standard`
|
||||
|
||||
@@ -159,3 +159,41 @@
|
||||
Антипаттерн:
|
||||
|
||||
не превращать `mcp-server` во второй `admin-api`.
|
||||
|
||||
## 5. Разделение open-source и commercial модулей
|
||||
|
||||
### 5.1. Что остается в public repository
|
||||
|
||||
В этом репозитории должны жить:
|
||||
|
||||
- Community domain model;
|
||||
- Community runtime;
|
||||
- Community UI;
|
||||
- extension seams для коммерческих возможностей;
|
||||
- capability model по редакциям.
|
||||
|
||||
### 5.2. Что должно выноситься в private delivery
|
||||
|
||||
За пределами public repo должны жить:
|
||||
|
||||
- short-lived и one-time token issuers;
|
||||
- enterprise access services;
|
||||
- `SSO`, `2FA`, `RBAC`, `audit log`;
|
||||
- metering и billing;
|
||||
- cloud control plane;
|
||||
- premium protocol families, если они не входят в Community edition.
|
||||
|
||||
### 5.3. Техническое правило
|
||||
|
||||
Public code не должен содержать скрытую private business logic.
|
||||
|
||||
Допустимо:
|
||||
|
||||
- trait boundaries;
|
||||
- capability flags;
|
||||
- edition-aware service contracts.
|
||||
|
||||
Недопустимо:
|
||||
|
||||
- полноценная коммерческая реализация в open-source исходниках;
|
||||
- UI, который реально включает premium flow без server-side gating.
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# Редакции продукта
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует продуктовую модель Crank как open-core платформы и определяет, какие возможности входят в открытую редакцию, а какие относятся к коммерческим редакциям.
|
||||
|
||||
Документ нужен для трех целей:
|
||||
|
||||
- не смешивать в одном репозитории открытый и коммерческий контур без явных границ;
|
||||
- синхронизировать продуктовые ограничения с архитектурой, API и UI;
|
||||
- дать реализации четкий ориентир по edition gating и delivery model.
|
||||
|
||||
## 2. Базовая модель
|
||||
|
||||
Crank развивается как три редакции:
|
||||
|
||||
1. `Community` — открытая self-hosted редакция;
|
||||
2. `Enterprise` — коммерческая self-hosted редакция;
|
||||
3. `Cloud` — коммерческая vendor-hosted редакция.
|
||||
|
||||
Принцип:
|
||||
|
||||
- открытая редакция должна быть самодостаточной и полезной сама по себе;
|
||||
- коммерческие редакции должны расширять продукт, а не ломать открытую основу;
|
||||
- различия между редакциями должны быть видны в capability model, документации, UI и delivery pipeline.
|
||||
|
||||
## 3. Community
|
||||
|
||||
### 3.1. Целевая аудитория
|
||||
|
||||
`Community` предназначена для:
|
||||
|
||||
- индивидуального пользователя;
|
||||
- AI-энтузиаста;
|
||||
- небольшой команды, которой нужен один рабочий MCP endpoint без enterprise-функций.
|
||||
|
||||
### 3.2. Что входит
|
||||
|
||||
- self-hosted развертывание;
|
||||
- одна рабочая область;
|
||||
- один пользователь;
|
||||
- один AI-агент;
|
||||
- протоколы:
|
||||
- `REST / HTTP`
|
||||
- `GraphQL`
|
||||
- `gRPC unary`
|
||||
- создание и публикация операций;
|
||||
- журналы вызовов и метрики использования;
|
||||
- секреты и профили аутентификации для внешних сервисов;
|
||||
- статический ключ AI-агента;
|
||||
- только `security_level = standard`;
|
||||
- контейнерное развертывание;
|
||||
- документация, демо-сценарий и базовый CI.
|
||||
|
||||
### 3.3. Что не входит
|
||||
|
||||
- несколько рабочих областей;
|
||||
- несколько пользователей;
|
||||
- `SSO`, `2FA`, развитая `RBAC`, `audit log`;
|
||||
- короткоживущие и одноразовые машинные токены;
|
||||
- `WebSocket`, `SOAP`, `gRPC streaming`;
|
||||
- режимы `window`, `session`, `async_job`;
|
||||
- биллинг и usage metering для SaaS;
|
||||
- cloud control plane.
|
||||
|
||||
## 4. Enterprise
|
||||
|
||||
### 4.1. Целевая аудитория
|
||||
|
||||
`Enterprise` предназначена для компаний, которые:
|
||||
|
||||
- разворачивают Crank на своей инфраструктуре;
|
||||
- хотят полный набор протоколов;
|
||||
- требуют усиленную безопасность, командный доступ и аудит;
|
||||
- готовы платить за сопровождение и коммерческие расширения.
|
||||
|
||||
### 4.2. Что добавляется к Community
|
||||
|
||||
- несколько рабочих областей;
|
||||
- несколько пользователей;
|
||||
- `SSO`, `2FA`, расширенная `RBAC`, `audit log`;
|
||||
- короткоживущие машинные токены;
|
||||
- одноразовые токены для критичных операций;
|
||||
- `security_level = elevated` и `security_level = strict`;
|
||||
- `WebSocket`, `SOAP`, `gRPC streaming`;
|
||||
- streaming execution modes;
|
||||
- расширенные административные и эксплуатационные функции;
|
||||
- поставка через приватные образы и `Helm`-чарты.
|
||||
|
||||
## 5. Cloud
|
||||
|
||||
### 5.1. Целевая аудитория
|
||||
|
||||
`Cloud` предназначена для команд, которым нужна:
|
||||
|
||||
- готовая размещенная платформа;
|
||||
- минимизация собственной эксплуатационной нагрузки;
|
||||
- SaaS-модель с управляемыми обновлениями и платными лимитами.
|
||||
|
||||
### 5.2. Что добавляется к Enterprise
|
||||
|
||||
- vendor-hosted развертывание;
|
||||
- usage metering;
|
||||
- тарифы и лимиты;
|
||||
- cloud control plane;
|
||||
- эксплуатационный мониторинг и обновления со стороны поставщика;
|
||||
- биллинг и tenant-oriented support tooling.
|
||||
|
||||
## 6. Матрица возможностей
|
||||
|
||||
| Возможность | Community | Enterprise | Cloud |
|
||||
| --- | --- | --- | --- |
|
||||
| Hosting | self-hosted | self-hosted | vendor-hosted |
|
||||
| Workspace count | 1 | many | many |
|
||||
| User count | 1 | many | many |
|
||||
| Agent count | 1 | many | many |
|
||||
| REST / GraphQL / gRPC unary | yes | yes | yes |
|
||||
| WebSocket / SOAP / gRPC streaming | no | yes | yes |
|
||||
| Streaming modes | no | yes | yes |
|
||||
| Static agent key | yes | yes | yes |
|
||||
| Short-lived MCP token | no | yes | yes |
|
||||
| One-time MCP token | no | yes | selectively |
|
||||
| `security_level = standard` | yes | yes | yes |
|
||||
| `security_level = elevated` | no | yes | yes |
|
||||
| `security_level = strict` | no | yes | limited by policy |
|
||||
| Logs and usage | yes | yes | yes |
|
||||
| SSO / 2FA / RBAC / audit | no | yes | yes |
|
||||
| Billing / metering | no | no | yes |
|
||||
|
||||
## 7. Правила для реализации
|
||||
|
||||
### 7.1. Community не должен зависеть от private code
|
||||
|
||||
Открытая редакция должна:
|
||||
|
||||
- собираться из этого репозитория полностью;
|
||||
- иметь завершенный сценарий демо и эксплуатации;
|
||||
- не требовать закрытых сервисов для базового машинного доступа.
|
||||
|
||||
### 7.2. Коммерческие возможности должны быть явно отделены
|
||||
|
||||
Коммерческие функции не должны появляться в Community как полурабочие заглушки. Для каждой такой функции требуется одно из двух:
|
||||
|
||||
- capability flag с честным недоступным состоянием;
|
||||
- полное отсутствие функции из open-source сборки.
|
||||
|
||||
### 7.3. Различия по редакциям должны быть зафиксированы в четырех местах
|
||||
|
||||
1. в продуктовой документации;
|
||||
2. в архитектурной декомпозиции;
|
||||
3. в административном API и MCP-контрактах;
|
||||
4. в UI через capability gating и честный copy.
|
||||
|
||||
## 8. Правила для машинной аутентификации
|
||||
|
||||
Продуктовые редакции различаются и по входящему машинному доступу:
|
||||
|
||||
- `Community`:
|
||||
- только статический ключ AI-агента;
|
||||
- только операции уровня `standard`;
|
||||
- `Enterprise`:
|
||||
- статический ключ AI-агента;
|
||||
- короткоживущий токен;
|
||||
- одноразовый токен;
|
||||
- `Cloud`:
|
||||
- статический ключ как режим совместимости;
|
||||
- короткоживущий токен как основной режим;
|
||||
- одноразовый токен — только там, где это поддерживается продуктовой политикой.
|
||||
|
||||
Подробная модель описана в `docs/agent-auth-model.md`.
|
||||
|
||||
## 9. Правила для UI
|
||||
|
||||
Открытый UI не должен:
|
||||
|
||||
- обещать недоступные в Community возможности как почти готовые;
|
||||
- показывать enterprise/cloud controls без capability gating;
|
||||
- использовать ложные CTA для недоступных функций.
|
||||
|
||||
Если функция не входит в текущую редакцию, UI должен делать одно из двух:
|
||||
|
||||
- не показывать ее вовсе;
|
||||
- показывать ее как явно недоступную и документированно требующую другую редакцию.
|
||||
|
||||
## 10. Связанные документы
|
||||
|
||||
- `docs/architecture.md`
|
||||
- `docs/module-decomposition.md`
|
||||
- `docs/agent-auth-model.md`
|
||||
- `docs/frontend-roadmap.md`
|
||||
- `docs/refactoring-roadmap.md`
|
||||
- `docs/implementation-plan.md`
|
||||
@@ -0,0 +1,111 @@
|
||||
# Refactoring roadmap
|
||||
|
||||
## 1. Назначение документа
|
||||
|
||||
Этот документ фиксирует оставшийся технический backlog после уже выполненных больших backend и frontend refactoring tracks.
|
||||
|
||||
Он не повторяет уже завершенные изменения, а описывает то, что еще нужно для product-ready open-core платформы.
|
||||
|
||||
## 2. Что уже считается выполненным
|
||||
|
||||
Закрытыми считаются следующие крупные инженерные направления:
|
||||
|
||||
- модульное разбиение `crank-registry`;
|
||||
- compile-time SQL verification для статических запросов;
|
||||
- `HKDF` вместо прямого `SHA-256` derivation;
|
||||
- typed timestamps;
|
||||
- `Display` для typed ids;
|
||||
- explicit PostgreSQL pool configuration;
|
||||
- structured runtime and registry errors;
|
||||
- correlation IDs;
|
||||
- runtime backpressure и request throttling;
|
||||
- distributed transport session store;
|
||||
- frontend build pipeline и wizard modularization.
|
||||
|
||||
## 3. Оставшиеся технические треки
|
||||
|
||||
### 3.1. Open-core boundary extraction
|
||||
|
||||
Цель:
|
||||
|
||||
- отделить Community runtime от будущих commercial implementations.
|
||||
|
||||
Что нужно:
|
||||
|
||||
- capability model по редакциям;
|
||||
- protocol gating;
|
||||
- auth gating;
|
||||
- extension seams для private implementations;
|
||||
- отдельные delivery manifests для Community.
|
||||
|
||||
Ключевые места:
|
||||
|
||||
- `crates/crank-core`
|
||||
- `apps/admin-api`
|
||||
- `apps/mcp-server`
|
||||
- `apps/ui`
|
||||
- `docs/product-editions.md`
|
||||
- `docs/commercial-boundaries.md`
|
||||
|
||||
### 3.2. Agent-scoped machine auth completion
|
||||
|
||||
Цель:
|
||||
|
||||
- довести current docs-first auth model до рабочего Community implementation.
|
||||
|
||||
Что нужно:
|
||||
|
||||
- полноценный `AgentKey` lifecycle в `admin-api` и UI;
|
||||
- отказ от remaining workspace/platform-key assumptions;
|
||||
- enforcement `security_level = standard` в Community flow;
|
||||
- capability scaffolding для `elevated` и `strict`.
|
||||
|
||||
### 3.3. Private token-service seam
|
||||
|
||||
Цель:
|
||||
|
||||
- подготовить публичный код к private реализации short-lived и one-time token flows.
|
||||
|
||||
Что нужно:
|
||||
|
||||
- stable HTTP contracts;
|
||||
- server-side trait boundary;
|
||||
- token verification abstraction in `mcp-server`;
|
||||
- capability-aware UI contract.
|
||||
|
||||
### 3.4. Commercial protocol split
|
||||
|
||||
Цель:
|
||||
|
||||
- перестать считать все уже написанные protocol families частью Community surface.
|
||||
|
||||
Что нужно:
|
||||
|
||||
- определить Community-supported protocol set;
|
||||
- вынести premium protocols и premium execution modes в private delivery plan;
|
||||
- синхронизировать UI, docs и release process.
|
||||
|
||||
### 3.5. Release and distribution hardening
|
||||
|
||||
Цель:
|
||||
|
||||
- подготовить reproducible public Community release и private commercial delivery.
|
||||
|
||||
Что нужно:
|
||||
|
||||
- public release flow for GitHub;
|
||||
- private image flow for Enterprise;
|
||||
- artifact signing / provenance;
|
||||
- clear packaging split for Community vs commercial.
|
||||
|
||||
## 4. Правила приоритизации
|
||||
|
||||
Сначала выполняются треки, которые формируют границу продукта:
|
||||
|
||||
1. open-core boundary extraction;
|
||||
2. Community agent-scoped auth completion;
|
||||
3. private token-service seam;
|
||||
4. frontend edition gating;
|
||||
5. release and distribution hardening.
|
||||
|
||||
После этого уже можно безопасно идти в enterprise/cloud-specific implementation.
|
||||
Reference in New Issue
Block a user